• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Striving towards better PHP code
 

Striving towards better PHP code

on

  • 7,193 views

Slides of Steve's talk at the Italian PHPDay 2010, in Corropoli (TE), May 15th 2012

Slides of Steve's talk at the Italian PHPDay 2010, in Corropoli (TE), May 15th 2012

Statistics

Views

Total Views
7,193
Views on SlideShare
6,544
Embed Views
649

Actions

Likes
2
Downloads
23
Comments
0

9 Embeds 649

http://steve.maraspin.net 453
http://www.maraspin.local 100
http://www.slideshare.net 57
http://www.dev.mvassociati.it 22
http://steve.dev.maraspin.net 9
http://www.linkedin.com 3
http://www.lmodules.com 2
http://translate.googleusercontent.com 2
http://www.brijj.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

CC Attribution-ShareAlike LicenseCC Attribution-ShareAlike License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Striving towards better PHP code Striving towards better PHP code Presentation Transcript

    • STRIVING TOWARD BETTER CODE WITH PHP http://joind.in/talk/view/1493 Stefano "Steve" Maraspin E-Mail: steve [AT] maraspin [DOT] net LinkedIn: http://it.linkedin.com/in/maraspin PHPDAY Twitter: http://twitter.com/maraspin Corropoli, TE - ITALY Website: http://www.maraspin.net May, 15th 2010 [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP
    • About Me STEFANO "STEVE" MARASPIN ● PHP user since PHP3 ● Zend Certified Engineer ● PHP CLI User (Unix platforms) ● Consultant & Managing Partner at http://www.mvassociati.it [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 2 / 52
    • Why am I here? ● Not to preach anything ● Rather, to share a few practices which either myself or other colleagues I've been working with (in different projects and environments) have found to be useful ● (well deserved) emphasis always given to logical structuring of applications; but syntax and proper construct usage can also help writing better programs [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 3 / 52
    • Messages I'd like to convey today ● maintainance consitutes an (often forgotten) integral part of the software lifecycle ● the adoption of consistent coding standards and good practices can ease software mainteinance ● PHP offers a few constructs and tools to improve code quality and avoid common pitfalls ● it's dangerous to always rely on clichées; instead it's better to try being analytical; most likely it's not a construct itself to be the root of all evil in our code, but rather the use we make out of it ● There's no “Silver Bullet”; each specific development context differs from others, so that it's dangerous to blindly apply commonly accepted good practices without first making sure they suit the specific context we're dealing with [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 4 / 52
    • Agenda ● Key Principles ● Coding Standards ● Comments ● Namespaces ● Type Hinting ● The Magic Stuff ● Closures ● GOTO [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 5 / 52
    • What's our real goal? ● Most likely to build successful software products ● Software that does what it is supposed to do (meets expectations) ● Software that is reliable (low number of defects) ● Software that is easily maintainable (mainteinance do cost!) ● Software that talks for you (about you) even after you've left a working place... (do not understimate the effects of your traces for the future of your career!) ● A good software is not an output we can expect from an algorithm; we have to choose Heuristics wisely and depending on our specific context [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 6 / 52
    • Code quality and software success ● We spend more time reading than writing software ● Source code is often the ONLY documentation available to development & mainteinance teams ● When not the ONLY documentation available, it's usually the ONLY up to date ● Re-use code across projects (different people working on it) ● In agile environments code is now designed to change (modified more frequently) ● Let's Avoid the "Broken Window Principle" [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 7 / 52
    • Underlying Principles ● Consistency, Conceptual Integrity ● Don't Repeat Yourself (DRY) ● Don't rely upon chance ● Detect Errors Early ● Be consistent with abstraction levels ● Simplify the problem; do the possible to maximize the portion of a program that you can ignore while working on any section of code [McConnell] [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 8 / 52
    • Agenda ● Key Principles ● Coding Standards ● Comments ● Namespaces ● Type Hinting ● The Magic Stuff ● Closures ● GOTO [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 9 / 52
    • No Standards, uh? www.flickr.com/photos/european_community/529820772/sizes/l [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 10 / 52
    • Translating this pic into poor code Script Invocation HTTP GET request: ./page.php?month=MONTH <? // =====================================================* // Cool Code by John Doe * // =====================================================* if ($month=='may' || $month == 'jun' || $month=='july' || $month == 'augst') { echo 'Hot!'; } elseif ($month=='feb' || $month==”december” || $month == 'janur') { // ON DAY 1 I GO SKYING! if ($dayofweek == 1) { echo 'Gone Skying for the whole week-end. Will be [...] } else { print 'Cold!'; }} ?> OMG - WHAT A MESS! [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 11 / 52
    • A first attempt to improve code <?php /** * John Doe Yearly Feelings ● Sure enough, this is still far from perfect * @author John Doe code – in fact the poor design/logic still * This snippet tells users how John Doe * feels through the year remains the same ...let's see what's been */ already improved though: $month = $_GET['month']; const SUNDAY = 1; ● We do not rely on register_globals if ('may' == $month || ● We do not use php short_tags 'jun' == $month || ● Our naming convention is uniform 'jul' == $month || ● We have no magic numbers 'aug' == $month) { echo 'Hot!'; ● Code is reasonably indented } elseif ('feb' == $month || ● Line length is limited 'dec' == $month || ● Only one from print & echo is used 'jan' == $month) { // When skying I'm excited ● Header comment is easier to maintain // otherwise I feel cold! ● There are better (although still imperfect) if (SUNDAY == $dayOfWeek) { echo 'Gone Skying for the whole'. comments 'week-end. Will be back on'. ● Closing tag is omitted 'monday!'; } else { echo 'Cold!'; There road towards good code is not a } } nicely paved one... [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 12 / 52
    • Code Formatting and Layout ● Hard Tabs vs Soft Tabs debate (Religion War) ● Standards (PEAR, Zend, Linux, others...) Zend FW: Spaces only; no tabs Four (4) spaces per level of indentation Purpose is consistency of viewing ● A possible alternative, viable solution: ● Hard Tabs for indentation ● Soft Tabs for alignment [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 13 / 52
    • Braces ● Better to avoid situations such as: if ($condition) call_function(); ● Use braces, and do it consistently BSD Style GNU Style K&R Style if ($condition) if ($condition) if ($condition){ { { // statement // statement // statement } } } [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 14 / 52
    • About Names ● Match with level of abstraction ● Avoid No-Sense names (Foo, bar, person2, etc) $person­>eat($apple); ● Single letter variables ($x, $y, $i), are usually ok for loops only ● Here too, establish a standard (name language, notations, short forms) – camelCase vs Simonyi vs Petzold vs ... vUsing adjHungarian nnotation vmakes nreading ncode adjdifficult. ● yet, it makes wrong code look wrong (let's think about situations where unit testing is not an option and code inspection has to be performed) $count == $people $i_count == $as_people [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 15 / 52
    • Function/Methods ● “Functions should be short and sweet, and do just one thing” L. Torvalds ● Limit number of parameters (possibly to no more than 7) ● Always remove unused parameters ● Use Type Hinting [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 16 / 52
    • Alignment Styles STYLE A STYLE B $person->firstname = 'John'; $person->firstname = 'John'; $person->lastname = 'Doe'; $person->lastname = 'Doe'; $person->birthdate = '1980-01-01'; $person->birthdate = '1980-01-01'; $car->color = colors::RED; $car->color = colors::RED; $car->owner = $person; $car->owner = $person; Style B is “nicer” to your eyes, but also more difficult to maintain. What happens if you add a member variable which name is longer than all the others? Either you re-allign all assignments or you use an abbreviation for the newly created variable. But is it the abbreviation consistent with all other abbreviations you've used? Does it still allow you to easily understand what that variable contains? [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 17 / 52
    • Coding Standard Guidelines ● PEAR Coding Standards http://pear.php.net/manual/en/standards.php ● Zend Framework Coding Standards http://framework.zend.com/manual/en/coding-standard.html ● eZComponents Implementation guidelines http://www.ezcomponents.org/contributing/coding_standards Enforcing Coding Standards: http://pear.php.net/package/PHP_CodeSniffer Much more valuable than choosing the perfect style is having a consistent style across all your code [G. Schlossnagle] [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 18 / 52
    • Agenda ● Key Principles ● Coding Standards ● Comments ● Namespaces ● Type Hinting ● The Magic Stuff ● Closures ● GOTO [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 19 / 52
    • Comment Basics Should clarify the code intent (higher level of abstraction), not how things do get done (why, not how) If a snippet of code is really hard to understand, you might want, at least, start to think about rewriting the code, not just about adding more comments to it... It's better to always avoid redundancy in code/comments PHP Supported Document Formats ● C Style /* */ ● C++ Style // ● Shell/Perl style # ● PHPDocumentor [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 20 / 52
    • PHPDocumentor Class Example /** * studentClass – Represents a student * * This class represents a student in our Campus application * * @package Campus * @author AUTHOR <EMAIL> * @copyright 2010 NOTICE * @license LICENSE NOTICE * @version VERSION */ Class Student { /** * The Student Roommate * * @var Student */ private $roomMate = null; [...] } [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 21 / 52
    • PHPDocumentor Method Example /** * hasRoomMate – Tells us whether student has a roommate * * @return bool true if student has a roommate */ public function hasRoomMate() { return (null != $this->roomMate); } [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 22 / 52
    • PHPDocumentor Method Example [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 23 / 52
    • Agenda ● Why worry about Clean Code ● Key Principles ● Comments ● Namespaces ● Type Hinting ● The Magic Stuff ● Closures ● GOTO [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 24 / 52
    • Introducing Namespaces ● Class names have to be unique per running script ● Namespaces help us with classes which name is vague (possibly same name, different domain/levels of abstraction) IE “message” or third party code (possibility of naming collisions are diminished) ● Namespaces (PHP 5.3) help avoiding class names like: company_library_component_classofitems_item_element (which BTW also affect code autocomplete in editor) ● No (measurable) impact on the runtime performance ● Namespace declaration has to be at the beginning of the file (...multiple namespaces can actually be present in a single file but the aforementioned fact must hold true). [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 25 / 52
    • Namespace Example <?php namespace Phpday; const ANSWER = 'PHP'; class C { /* ... */ } function bestLanguage() { return ANSWER; } ?> <?php use PhpdayC; use Phpday as Fun; echo PhpdayANSWER; new PhpdayC(); PhpdaybestLanguage(); echo FunANSWER; ?> [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 26 / 52
    • Another Namespace Example <?php namepace Phpdaysteve; class Presentation { /* ... */  } The compile translates this to ?> StevephpdayPresentation <?php class odpPresentation extends  PhpdaystevePresentation { /* ... */  } ?> We can use the full name from within another file <?php namepace Phpdaysteve; echo strlen(); echo Phpdayotherspeakerstrlen(); ?> We can solve ambiguities [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 27 / 52
    • Agenda ● Key Principles ● Coding Standards ● Comments ● Namespaces ● Type Hinting ● The Magic Stuff ● Closures ● GOTO [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 28 / 52
    • What is Type Hinting? Signature example: public function giveTalk(Topic $talkTopic)                  { /* … */  } Benefits ● Early error detection ● More readable code Limitations ● Not allowed for primitives (only objects and arrays) ● Passing null cause exception Type Hinting Patch (Ilia Alshanetsky): http://ilia.ws/archives/205-Type-hinting-for-PHP-5.3.html [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 29 / 52
    • Type Hinting Example cont.d Alternatively, there is someone who suggest to encapsulate all base data types in objects Somewhere I've recently read: “Paradigm conflict here: On the one hand, we are usually open for most things users want to do (look at goto) and add them where needed. This would mean to basically add all variants above to let people do things the way they want. On the other hand, adding strong type hints and scalar (with and without additional info) and numeric and casts results in endless confusion and violates the KISS principle PHP has always been based on.” My personal opinion on this... [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 30 / 52
    • Agenda ● Key Principles ● Coding Standards ● Comments ● Namespaces ● Type Hinting ● The Magic Stuff ● Closures ● GOTO [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 31 / 52
    • Magic Getters/Setters class Test { public $data = null; public function __construct() { $this->data = array(); $this->data['Data'] = '2009-05-15'; $this->data['Evento'] = 'phpday'; } public function getEvento() { return ucfirst($this->data['Evento']); } [...] [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 32 / 52
    • Magic Getters/Setters Cont.d […] public function __get($variable) { if (method_exists($this, $method = 'get' . $variable)) { return $this->$method($variable); } elseif (array_key_exists($variable,$this->data)) { return $this->data[$variable]; } else { throw new Exception('No Var Here With That Name!'); } } Ease of mainteinance is often facilitated by Magic Methods. Sure they might slow down the code, but Profiling is the way to go. Better to avoid premature optimization! [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 33 / 52
    • clone() ● Used to “Make Copies” of objects (since they're passed by reference) ● __clone() is run on the copied object context class Person { private $name = null; function setName($name) { $this­>name = $name; } function __clone() { $this­>name = null; } } [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 34 / 52
    • Agenda ● Key Principles ● Coding Standards ● Comments ● Namespaces ● Type Hinting ● The Magic Stuff ● Closures ● GOTO [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 35 / 52
    • Anonymous Functions & Closures ● Closures rely upon concept of anonymous functions (but they're different things!). ● AF allow for the creation of quick throw-away functions (mainly used for callbacks). ● Don’t confuse with “create_function()”, since the functions that this construct creates compile at “run-time” (EVAL), so that Opcode cachers CANNOT cache them (Bad practice) [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 36 / 52
    • Basic Anonymous Function Example <?php $lambdaFunction=function($x)  { return $x*5; }; print $lambdaFunction(10); ?>  [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 37 / 52
    • Closure Definition ● “In computer science, a closure is a first-class function with free variables that are bound in the lexical environment. Such a function is said to be "closed over" its free variables. A closure is defined within the scope of its free variables, and the extent of those variables is at least as long as the lifetime of the closure itself.” [Wikipedia] ● In PHP Anonymous Functions/Closures are implemented as Objects of the type “Closure” ● Any object with an __invoke() method can be used as closure [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 38 / 52
    • OK, again, here's an example... <?php $x = 0; $closure = function() use ($x) { echo  $x . "n"; }; $closure(); // 0 $x = 10; $closure(); // 0 [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 39 / 52
    • Passing by Reference function fancy_count($arr) {     $count = 0;     $callback = function($dat) use (&$count) { $count++;};     array_walk($arr, $callback);     return $count;  } echo fancy_count(array(0,1,2,3,4));  // 5 [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 40 / 52
    • Callback Alternatives to Closures create_function(), which is not a good choice; and neither are global variables or objects created for the purpose; foreach cycles might well be, but watch out when you do use references, since surprises can arise if you don't pay attention... <?php $testArray = array('Uno','Due','Tre'); foreach ($testArray as &$elemento) { } foreach ($testArray as $elemento) { } print_r($testArray);  // Array([0] => Uno, [1] => Due [2] => Due)   [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 41 / 52
    • Agenda ● Why worry about Clean Code ● Key Principles ● Coding Standards ● Comments ● Namespaces ● Type Hinting ● The Magic Stuff ● Closures ● GOTO [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 42 / 52
    • GOTO – Common thoughts http://xkcd.com/292 ● Common fear and loathe towards GOTO, especially after famous article "Goto Statement Considered Harmful" by E. Dijkstra (which original title was "A Case Against the Goto Statement", by the way). ● Certainly not an essential construct [see Bohm, Jacopini work] [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 43 / 52
    • PHP GOTO – Damage Limitation ● target label must be within the same file ● you cannot jump out of a function or method, nor can you jump into one ● you also cannot jump into any sort of loop or switch structure ● works backwards also (uhmm...) ● interesting S. Golemon blog post about PHP GOTO history: http://blog.libssh2.org/index.php?/archives/2-GOTO...No,-seriously,-for-real-this-time..html [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 44 / 52
    • GOTO vs BREAK ● Simplistic and yet extreme example for ($i=0; $i<10; $i++) { for ($i=0; $i<10; $i++) { for ($x=0; $x<10; $x++) { for ($x=0; $x<10; $x++) { for ($y=0; $y<10; $y++) { for ($y=0; $y<10; $y++) { for ($z=0; $z<10; $z++) { for ($z=0; $z<10; $z++) { // Do Something if ($g > $n) goto second; if ($g > $n) break substitute(); dosomething(); } } second: // Do something else // Do something else } } } } } } function substitute() { // Do something return 4; Note: MISSING ; } [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 45 / 52
    • Nested If $filename = 'file.txt'; $somecontent = 'Just Some Example Textn'; if (is_writable($filename)) { if ($handle = fopen($filename, 'a')) { if (fwrite($handle, $somecontent) === FALSE) { echo 'Error Opening File'; echo 'Cleaning Up'; } fclose($handle); } else { echo 'Error Opening File'; echo 'Cleaning Up'; } } else { echo 'File is NOT Writable'; echo 'Cleaning Up'; } [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 46 / 52
    • GOTO $filename = 'file.txt'; $somecontent = 'Dummy Textn'; if (!is_writable($filename)) { echo 'File is NOT Writable'; goto abort; } if(!$handle = fopen($filename, 'a')) { echo 'Error Opening File'; goto cleanup; } if (false === fwrite($handle, $somecontent)) { echo 'Error Opening File'; goto cleanup; } fclose($handle); cleanup: echo "Cleaning Up"; [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 47 / 52
    • Other Alternatives $filename = 'file.txt'; $somecontent = 'Dummy Textn'; $error = false; ← Status Variable Approach if (!is_writable($filename)) { $error = true; echo 'File is NOT Writable'; } if (!$error) { if(!$handle = fopen($filename, 'a')) { $error = true; echo 'Error Opening File'; } } if (!$error) { if (false === fwrite($handle, $somecontent)) { $error = true; echo 'Error Opening File'; } } if (false !== $error) { Using Exceptions - Try-Finally fclose($handle); be sure of applying it consistently } else { though. Basic functions might echo 'Cleaning Up'; also need to be wrapped. Might } be overkill for small scripts [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 48 / 52
    • Another (Last) Example if ($fileReadActionHappened) { if (null != $dataAvailable) { $content = $dataAvailable; goto process; } } else { $content =file_get_contents('/some/file'); process: // Rest of Code... ← Here of course, we could decide to put "Rest of Code" in its own function. } [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 49 / 52
    • GOTO – Final Thoughts... ● "do you really want to outlaw sharp tools because amateur builders can hurt themselves?*" (...BTW when used improperly, even constructs like break, continue and multiple return points don't cause effects much different than those of GOTOs) *http://www.procata.com/blog/archives/2004/07/29/goto-in-php/ ● I think goto's are fine, and they are often more readable than large amounts of indentation. [L. Torvalds] http://kerneltrap.org/node/553/2131 ● Bottom Line: it's definitely still possible to write bad code without goto. It's definitely not a single construct which can determine the quality of our code! [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP 50 / 52
    • ANY QUESTIONS? [Feel free to e-mail me] [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP
    • THANK YOU FOR YOUR ATTENTION [S. Maraspin] STRIVING TOWARD BETTER CODE WITH PHP