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

Aca9a731cf8422c5ea7f6cb833d3976f?s=128

Camilo Sperberg

March 02, 2015
Tweet

Transcript

  1. 4.

    What is code quality? Short answer: nobody knows for sure

    Problem: there are too many definitions 4
  2. 5.

    5

  3. 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";
  4. 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
  5. 8.

    8

  6. 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
  7. 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
  8. 11.

    11

  9. 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
  10. 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
  11. 14.

    14

  12. 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
  13. 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); } }
  14. 18.
  15. 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
  16. 20.
  17. 21.
  18. 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
  19. 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!
  20. 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
  21. 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
  22. 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
  23. 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
  24. 29.

    Code Quality: Good practices Think about your code as a

    civil engineer would think about building a skyscraper 29
  25. 30.
  26. 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
  27. 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
  28. 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
  29. 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
  30. 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
  31. 37.

    Some standards before PHP-Fig ‣ PEAR ‣ Symphony ‣ Zend

    Framework ‣ TYPO3 ‣ Drupal ‣ WordPress 37
  32. 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
  33. 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
  34. 40.

    Close look to PSR-1 ‣ Use only <?php and <?=

    tags ‣ Only UTF-8 without BOM ‣ Files should declare symbols or cause side-effects ‣ Namespaces and classes must follow PSR-0 or PSR-4 40
  35. 41.

    Close look to PSR-1 ‣ Class names: StudlyCaps ‣ Method

    names: camelCase ‣ Class constants: uppercase with underscore separators 41
  36. 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
  37. 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
  38. 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
  39. 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
  40. 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
  41. 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
  42. 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
  43. 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
  44. 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
  45. 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
  46. 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)
  47. 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
  48. 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
  49. 58.
  50. 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/
  51. 60.
  52. 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
  53. 62.
  54. 63.

    63 Finally: Who am I? ‣ Want to know more?

    My name is Camilo Sperberg ‣ Twitter: http://twitter.com/unreal4u ‣ Mail: me@unreal4u.com
  55. 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
  56. 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