Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

Part 1 What color is this rubik cube?

Slide 3

Slide 3 text

Part 1: Coding quality

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

5

Slide 6

Slide 6 text

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";

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

8

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

11

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

14

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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); } }

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

No content

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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!

Slide 24

Slide 24 text

http://xkcd.com/927/

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

Part 2: Coding Standards

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

Close look to PSR-1 ‣ Use only

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

Part 3: Code Analysis

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

PHPUnit 54

Slide 55

Slide 55 text

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)

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

No content

Slide 59

Slide 59 text

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/

Slide 60

Slide 60 text

No content

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

No content

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

Thanks! 65

Slide 66

Slide 66 text

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