$30 off During Our Annual Pro Sale. View Details »

Coding Quality & Coding Standards

Coding Quality & Coding Standards

A general introduction into a compilation of tools, good practices and what to do (or not) regarding good quality coding, while also looking at some of the most popular coding standards available today in the PHP world

Camilo Sperberg

March 02, 2015
Tweet

More Decks by Camilo Sperberg

Other Decks in Programming

Transcript

  1. Code Quality
    &
    Coding Standards
    LimburgPHP / EindhovenPHP / pugle
    2015-03-02
    Camilo Sperberg

    View Slide

  2. Part 1
    What color is this
    rubik cube?

    View Slide

  3. Part 1: Coding quality

    View Slide

  4. What is code quality?
    Short answer: nobody knows for sure
    Problem: there are too many definitions
    4

    View Slide

  5. 5

    View Slide

  6. Legibility (Bad example)
    code-quality/10-unlegible-code.php
    6
    define('ONE', 1); // Defines ONE
    define('TWO', 2); // Defines TWO
    define('FOUR', 9); // Defines FOUR
    define('FIVE', 5); // Defines FIVE
    // Declaring a variable
    $a = FOUR;
    // Checking a variable
    if ($a == 4) goto b; goto c;
    // Print something
    a:echo ONE;goto c;b:echo TWO;goto c;
    c:echo 'not ONE nor TWO';
    echo "\n";

    View Slide

  7. Legibility (Better)
    7
    /**
    * Checks what to print depending on output
    *
    * Prints constant ONE, TWO or another string
    * depending on the input $number
    *
    * @param int $number The number to check
    * @return boolean Returns always true
    */
    function checkNumber($number)
    {
    switch ($number) {
    case 1:
    echo ONE;
    break;
    case 4:
    echo TWO;
    break;
    default:
    echo 'not ONE nor TWO';
    break;
    }
    return true;
    }
    // Human readable representation of constants
    define('ONE', 1);
    define('TWO', 2);
    define('FOUR', 9); // CAUTION! Due to BC this one is different!
    define('FIVE', 5);
    // Assign and check the number
    $myNumber = FOUR;
    checkNumber($myNumber);
    echo PHP_EOL;
    code-quality/10-legible-code.php

    View Slide

  8. 8

    View Slide

  9. Testable & flexible code (Bad example)
    9
    /*
    * Thanks @jaytaph for your excellent
    * example of non-reusable code
    */
    $dir = opendir('.');
    while (($file = readdir($dir)) !== false) {
    // Filter php files:
    if (!preg_match('/\.php$/', $file)) {
    continue;
    }
    print "File: $file\n";
    }
    ‣Not easy to test
    ‣Not reusable
    ‣Bonus: No way to maintain
    code-quality/20-untestable.php

    View Slide

  10. Testable & flexible code (Better)
    10
    /*
    * Another thanks to @jaytaph for your excellent
    * example of reusable code
    */
    $it = new \DirectoryIterator('.');
    // Filter php files
    $it2 = new \RegexIterator($it, '/\.php$/');
    foreach ($it2 as $file) {
    printf("File: %s".PHP_EOL, $file->getFilename());
    }
    ‣Iterators are testable
    ‣Also reusable
    ‣Easy to maintain
    code-quality/20-testable.php

    View Slide

  11. 11

    View Slide

  12. Compliancy (Bad example)
    12
    /*
    * Task: Build an iterator that goes
    * from 0 to 10 and prints out
    * the value of the NEXT
    * iterator
    */
    for ($i = 0; $i < 15; $i++) {
    printf('Current value: %d'.PHP_EOL, $i);
    }
    ‣Prints from 1 to 15
    ‣Prints current value instead of next
    code-quality/30-uncompliant.php

    View Slide

  13. Compliancy (Better)
    13
    /*
    * Task: Build an iterator that goes
    * from 0 to 10 and prints out
    * the value of the NEXT
    * iterator
    */
    for ($i = 0; $i < 10; $i++) {
    printf('Next value: %d'.PHP_EOL, ($i + 1));
    }
    ‣Prints from 1 to 10
    ‣Prints next value
    ‣Everybody happy!
    code-quality/30-compliant.php

    View Slide

  14. 14

    View Slide

  15. Efficiency
    Don't bother on micro-optimization
    15
    Just don't

    View Slide

  16. Notes on efficiency
    ‣ Mr. Eugene Lewis Fordsworthe: "Assumptions is the mother of all screw ups"
    ‣ Not entirely true, sometimes good stuff comes out from assumptions
    ‣ Does not apply in the IT sector
    ‣ Do you want efficient running code? Profile. Period.
    16

    View Slide

  17. What to optimize?
    17
    code-quality/40-non-efficient.php
    if (is_writable('test.txt')) {
    unlink('test.txt');
    }
    for ($i = 1; $i <= 100; $i++) {
    if (isset($i) && !empty($i) && is_numeric($i) && is_int($i)) {
    file_put_contents('test.txt', 'Current value: '.$i.PHP_EOL, FILE_APPEND);
    }
    }

    View Slide

  18. View Slide

  19. Efficiency (Better)
    19
    $fileData = '';
    for ($i = 1; $i <= 100; $i++) {
    $fileData .= sprintf('Current value: %d'.PHP_EOL, $i);
    }
    file_put_contents('test.txt', $fileData);
    unset($fileData);
    code-quality/40-efficient.php

    View Slide

  20. View Slide

  21. View Slide

  22. Comparing both scripts
    22
    unreal4u-MBP:code-quality$ time php 40-non-efficient.php
    real 0m0.194s
    user 0m0.145s
    sys 0m0.023s
    unreal4u-MBP:code-quality$ time php 40-efficient.php
    real 0m0.168s
    user 0m0.143s
    sys 0m0.017s

    View Slide

  23. Tip: how-to profile in 2 minutes
    23
    git clone git://github.com/xdebug/xdebug.git
    cd xdebug/
    phpize
    ./configure
    make
    cp modules/xdebug.so [extensions-folder]
    ‣ Install xDebug:
    ‣ Add following options in php.ini:
    xdebug.profiler_enable = On
    xdebug.profiler_output_dir = "/tmp/profiler"
    xdebug.profiler_output_name = %p.callgrind
    ‣ Install kcachegrind and profit!

    View Slide

  24. http://xkcd.com/927/

    View Slide

  25. So… what is good code quality?
    Good definition I stumbled upon:
    ‣ Legible
    ‣ Testable
    ‣ Flexible
    ‣ Compliant
    ‣ Economical (Efficient)
    25
    http://stackoverflow.com/questions/405243/how-do-we-define-code-quality

    View Slide

  26. Code Quality: Documentation
    Most used documentation system in PHP:
    PHPDocumentor
    ‣ Is able to generate technical documentation right
    from the PHP code
    ‣ Is also used by almost all IDE's to enable code- and
    semantic autocompletion
    ‣ More information: http://www.phpdoc.org
    26

    View Slide

  27. Code Quality: Good practices
    ‣ OOP vs Procedural programming? Go for OOP
    ‣ Always try to program in English
    ‣ Don't reinvent the wheel, check packagist.org or search for a native function
    ‣ Documentation (PHPDocumentor) should be precise and concise
    27

    View Slide

  28. Code Quality: Good practices
    ‣ Use UTF-8 everywhere
    ‣ Don't hash passwords yourself, use built-in functions!
    ‣ Adhere to the coding standards
    ‣ Think ahead before writing code
    28

    View Slide

  29. Code Quality: Good practices
    Think about your code as a civil engineer
    would think about building a skyscraper
    29

    View Slide

  30. View Slide

  31. Code quality: Good practices
    Much more information than I could possibly talk about:
    ‣ http://www.phptherightway.com/
    ‣ https://phpbestpractices.org/
    ‣ http://www.php-fig.org
    ‣ Google "PHP best practices" for more, but trust those that are current
    31

    View Slide

  32. Part 2: Coding Standards

    View Slide

  33. Prehistory: ~1997 till 2004
    ‣ No really good support for classes
    ‣ Not very reusable
    ‣ No coding standards
    ‣ Frameworks of that time:
    ‣ NupeCode (2000)
    ‣ PEAR (1999)
    ‣ PECL (2003)
    33

    View Slide

  34. Medieval: 2004 till 2012≈2013
    The golden era of the frameworks
    ‣ osCommerce (2003, previously known
    as "The Exchange Project" [2000])
    ‣ WordPress (2003)
    ‣ CakePHP (2005), Symphony (2005)
    ‣ Zend Framework (2008)
    ‣ PHPUnit! (15 march 2004)
    34

    View Slide

  35. Renaissance: 2012+
    ‣ Rebirth of PHP as a language
    ‣ 2 mayor changes: PHP-Fig and Composer
    ‣ PHP-Fig (2009): Ground for rules and
    conventions
    ‣ Composer (2012): Good quality packages
    35
    Image credits: Luc Viatour / www.Lucnix.be

    View Slide

  36. To infinity and beyond: ∞+
    ‣ In PHP, strict type checking, scalar type hints?
    ‣ On userland: more PSR standards
    ‣ WIP: Cache
    ‣ WIP: Security
    ‣ WIP: HTTP message interface
    36

    View Slide

  37. Some standards before PHP-Fig
    ‣ PEAR
    ‣ Symphony
    ‣ Zend Framework
    ‣ TYPO3
    ‣ Drupal
    ‣ WordPress
    37

    View Slide

  38. PHP-Fig
    ‣ Stands for PHP Framework Interoperability Group
    ‣ Ways of mayor framework players to play together
    ‣ Creation of PSR's: PHP Standard Recommendation
    38
    http://www.php-fig.org

    View Slide

  39. PSR-1 and PSR-2
    ‣ Basic Coding Standard and Coding Style Guide, respectively
    ‣ PSR-2 extends PSR-1:
    ‣ PSR-1: PHP opening tags, camel-casing, intention of files, etc.
    ‣ PSR-2: Tabs or spaces, line length, positioning of opening braces, etc.
    39

    View Slide

  40. Close look to PSR-1
    ‣ Use only ‣ Only UTF-8 without BOM
    ‣ Files should declare symbols or cause side-effects
    ‣ Namespaces and classes must follow PSR-0 or PSR-4
    40

    View Slide

  41. Close look to PSR-1
    ‣ Class names: StudlyCaps
    ‣ Method names: camelCase
    ‣ Class constants: uppercase with underscore separators
    41

    View Slide

  42. Close look to PSR-2: General
    ‣ Code must follow PSR-1
    ‣ Code must use 4 spaces for indenting, no tabs
    ‣ Lines should be 80 characters or less, soft limit on 120, no hard limit
    42

    View Slide

  43. Close look to PSR-2: Visibility
    Visibility must be always declared
    ‣ abstract and final before visibility
    ‣ static after
    43
    abstract class Visibility
    {
    /**
    * Returns a nice greeting
    */
    final protected static function hello()
    {
    return 'Hello';
    }
    /**
    * Returns the world
    */
    public function world()
    {
    return 'world';
    }
    }
    coding-standards/20-visibility.php

    View Slide

  44. Close look to PSR-2: spacing
    ‣ One blank line after namespace and use statements
    ‣ Opening and closing braces for methods and classes must go on next line
    ‣ Control structure keywords must have one space after them
    ‣ Method and function calls not
    44

    View Slide

  45. Close look to PSR-2: spacing
    ‣ Opening braces for control structure keywords must go on the same line
    ‣ Closing braces must have their own line
    45

    View Slide

  46. Example
    46
    namespace Vendor\Package;
    use FooInterface;
    use BarClass as Bar;
    use OtherVendor\OtherPackage\BazClass;
    class Foo extends Bar implements FooInterface
    {
    public function sampleFunction($a, $b = null)
    {
    if ($a === $b) {
    bar();
    } elseif ($a > $b) {
    $foo->bar($arg1);
    } else {
    BazClass::bar($arg2, $arg3);
    }
    }
    final public static function bar()
    {
    // method body
    }
    }
    coding-standards/10-psr.php

    View Slide

  47. PSR-0 and PSR-4
    ‣ All about autoloading
    ‣ PSR-4 (Improved Autoloading) replaces PSR-0 (Autoloading Standard)
    ‣ Was the key to let composer gain momentum
    47

    View Slide

  48. Composer
    ‣ Dependency manager for PHP
    ‣ Nice little feature: mostly only good quality code can be
    found
    ‣ Infinitely better than www.phpclasses.org
    48
    https://getcomposer.org

    View Slide

  49. Packagist
    ‣ Simply a web interface for composer
    ‣ Useful for listing information about a package
    ‣ Only bad thing? No search by popularity yet :(
    ‣ https://github.com/composer/packagist/issues/365
    49
    https://packagist.org

    View Slide

  50. Semantic versioning
    ‣ Packages will have a common versioning system
    ‣ Given MAJOR.MINOR.PATCH (v1.2.3), increment:
    ‣ MAJOR when causing BC
    ‣ MINOR when adding functionality in backwards-compatible manner
    ‣ PATCH for bug fixes only
    ‣ More information: http://semver.org/
    50

    View Slide

  51. Semver example
    51
    class HelloWorld
    {
    public $name;
    public $age = 0;
    public function returnString($name, $age = 0)
    {
    $this->name = $name;
    if ($age > 0) {
    $this->age = $age;
    }
    return sprintf('Hello %s, your age is %d', $this->name, $this->age);
    }
    }
    semver/10-semver.php

    View Slide

  52. Part 3: Code Analysis

    View Slide

  53. Part 3: Code Analysis
    PHPUnit
    (No logo, sorry)

    View Slide

  54. PHPUnit
    54

    View Slide

  55. PHPUnit
    ‣ Used to avoid BC
    ‣ Quick and easy
    ‣ Unit tests must test real specific parts of the application
    ‣ More about Unit Testing next month!
    55
    PHPUnit
    (No logo, sorry)

    View Slide

  56. Other analyzers
    ‣ PHPLoc: Measures the size and structure of a PHP project
    ‣ PHP Copy/Paste Detector: Scans for duplicated code
    ‣ PHP Dead Code Detector: Scans for code no longer in use
    56

    View Slide

  57. Travis-CI
    ‣ Very easy to setup tests for
    multiple PHP versions
    ‣ Requires only a .travis.yml
    file with build information
    ‣ Very configurable
    57
    https://travis-ci.org/
    language: php
    php:
    - 5.6
    - 5.5
    - 5.4
    - hhvm
    matrix:
    allow_failures:
    - php: hhvm
    before_script:
    - "mkdir -p ~/.composer"
    - composer self-update
    - composer install
    script:
    - vendor/bin/phpunit --coverage-clover=coverage.clover
    after_script:
    - wget https://scrutinizer-ci.com/ocular.phar
    - php ocular.phar code-coverage:upload --format=php-clover coverage.clover

    View Slide

  58. View Slide

  59. Scrutinizer
    ‣ Executes almost all previous seen programs
    ‣ Integrates with Travis-CI
    ‣ Very good at explaining things
    ‣ Nice little badges for you to use!
    59
    https://scrutinizer-ci.com/

    View Slide

  60. View Slide

  61. Jenkins
    ‣ Self-hosted continuous integration server
    ‣ Very similar to Travis-CI, except that you have to do all the setup and configuration
    ‣ Lot of options, lots of plugins to do stuff as well
    61

    View Slide

  62. View Slide

  63. 63
    Finally: Who am I?
    ‣ Want to know more? My name is Camilo Sperberg
    ‣ Twitter: http://twitter.com/unreal4u
    ‣ Mail: [email protected]

    View Slide

  64. Finally: Who am I?
    ‣ Blog: http://blog.unreal4u.com/ (Spanish)
    ‣ Rate the talk and comment at: https://joind.in/talk/view/13713
    ‣ Please, it's the only way this talk (and others) can be improved
    ‣ Slides are ready to be downloaded:
    ‣ http://unreal4u.com/talks/
    ‣ https://speakerdeck.com/unreal4u
    ‣ Code examples: https://github.com/unreal4u/code-quality-talk/
    64

    View Slide

  65. Thanks!
    65

    View Slide

  66. Credits
    ‣ Bad code quality tips: http://fwebde.com/programming/write-unreadable-code/
    ‣ Bender applause: http://www.theatlantic.com/technology/archive/2013/03/a-brief-history-
    of-applause-the-big-data-of-the-ancient-world/274014/
    ‣ Vase of pre-history: http://esask.uregina.ca/entry/prehistory_southern_saskatchewan.html
    ‣ Medieval fort: http://commons.wikimedia.org/wiki/
    File:Medieval_fortifications_of_Provins_P1120608.JPG
    ‣ The Vitruvian Man (Used with permission): http://commons.wikimedia.org/wiki/
    File:Da_Vinci_Vitruve_Luc_Viatour.jpg
    66

    View Slide