Seven Steps to Better PHP Code

Loading...

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

0 comments

Post a comment

    Post a comment
    Embed Video
    Edit your comment Cancel

    6 Favorites

    Seven Steps to Better PHP Code - Presentation Transcript

    1. The Seven Steps To Better PHP Code Stefan Priebsch, e-novative GmbH
    2. Who I am • PHP enthusiast since 2000 • IT and PHP Consultant • From Munich, Germany • University Degree in Computer Science • Writer (Books and Articles) • Blog: http://inside.e-novative.de • Email: stefan.priebsch@e- novative.de The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 2
    3. Step 1 Consistently Format Source Code The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 3
    4. Format Source Code • It's easy to code for computers, but hard to code for humans • Code is read more often than written • Code should be human-readable The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 4
    5. Unredable Code #include <stdio.h>#define y for(c=0,i=54;i>=0;c=(s[i]+=a[i]+c)/11,s[i]=s[i]%11 ,i--);#define z for(i=0main(){char s[55],a[55];int c,i,d;for(;;){z;i<55;s[i++]=0);for(;(d=getchar())! ='\\n';){d=d>58?(d>77?d-87:d-55):d- 48;z;i<55;a[i]=s[i],i++);y z;i<54;s[i]=s[i+1],i++);s[54]=0;y z;i<53;a[i++]=0);a[53]=d/11;a[54]=d%11;y}z;i<54&&s [i]==0;i++);for(;i<55;i++)printf(\"%c\",s[i]<10?s[i] +48:32);printf(\"\\n\");}}
    6. Unredable Code <?php $bool = ($i<7&&$j>8||$k==4); if ($a == $b) { if ($b > 4){ do_something(); } } else { do_something_else(); } ?>
    7. Format Source Code • Format source code consistently • Establish a coding standard ▪ How to indent ▪ Where to put whitespace ▪ Capitalization • Reuse existing coding standards • Use a code beautifer The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 7
    8. Step 2 Establish Naming Conventions The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 8
    9. Naming Conventions • Establish a naming scheme ▪ Capitalization ▪ Consistent names ▪ Make the purpose clear • Keep file names simple (alphanumeric chars, blanks, underscores) • Prefix names in global namespace The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 9
    10. Naming Conventions processData() doIt() innerLoop() $del_pos checkConnection() vs. isConnected() $filename vs. $fileName open_connection($a, $b, $c, $d); ftp_connect($server, $port, ...);
    11. Step 3 Create API Documentation The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 11
    12. API Documentation • Document public interfaces • Code assumptions instead of commenting • Are inline comments necessary? ▪ Code should communicate its purpose ▪ The better the names, the fewer comments • PHPDoc, derived from JavaDoc The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 12
    13. API Documentation • Special Comment Blocks /** * ... */ • Special @tags (@author, @version, @param, @returns, …) The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 13
    14. Naming Conventions /** * This is what the class does. * * @package PackageName * @author Your Name * @version 1.0.0RC2 */ class myFooClass { /** * @param $aBar the Bar * @param $aBaz the Baz * @return bool success */ public function doFoo($aBar, $aBaz)
    15. Step 4 Eliminate Redundant Redundant Redundant Code The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 15
    16. Eliminate Redundant Code • Avoid duplicate or similar code • The Goal is: Make code changes in just one spot • Create parametrized functions and methods („helper functions“) • Do not over-generalize when programming, use Refactoring The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 16
    17. Eliminate Duplicate Code if (isset($_REQUEST['action'])) { if ('add' == $_REQUEST['action']) { $q = $db->query('SELECT quantity FROM data WHERE item=\\'' . $_REQUEST['item'] . '\\''); $quantity = $q->current(SQLITE_NUM); $quantity = $quantity[0]; $quantity++; $q = $db->queryExec('UPDATE data SET quantity=' . $quantity . ' WHERE item=\\'' . $_REQUEST['item'] . '\\''); } if ('remove' == $_REQUEST['action']) { $q = $db->query('SELECT quantity FROM data WHERE item=\\'' . $_REQUEST['item'] . '\\''); $quantity = $q->current(SQLITE_NUM); $quantity = $quantity[0]; if ($quantity > 0) $quantity--; $q = $db->queryExec('UPDATE data SET quantity=' . $quantity . ' WHERE item=\\'' . $_REQUEST['item'] . '\\''); } }
    18. Eliminate Duplicate Code if (isset($_REQUEST['action'])) { if ('add' == $_REQUEST['action']) { $q = $db->query('SELECT quantity FROM data WHERE item=\\'' . $_REQUEST['item'] . '\\''); $quantity = $q->current(SQLITE_NUM); $quantity = $quantity[0]; $quantity++; $q = $db->queryExec('UPDATE data SET quantity=' . $quantity . ' WHERE item=\\'' . $_REQUEST['item'] . '\\''); } if ('remove' == $_REQUEST['action']) { $q = $db->query('SELECT quantity FROM data WHERE item=\\'' . $_REQUEST['item'] . '\\''); $quantity = $q->current(SQLITE_NUM); $quantity = $quantity[0]; if ($quantity > 0) $quantity--; $q = $db->queryExec('UPDATE data SET quantity=' . $quantity . ' WHERE item=\\'' . $_REQUEST['item'] . '\\''); } }
    19. Eliminate Duplicate Code if (isset($_REQUEST['action'])) { if ('add' == $_REQUEST['action']) { $quantity = get_quantity($_REQUEST['item']); $quantity++; $q = $db->queryExec('UPDATE data SET quantity=' . $quantity . ' WHERE item=\\'' . $_REQUEST['item'] . '\\''); } if ('remove' == $_REQUEST['action']) { $quantity = get_quantity($_REQUEST['item']); if ($quantity > 0) $quantity--; $q = $db->queryExec('UPDATE data SET quantity=' . $quantity . ' WHERE item=\\'' . $_REQUEST['item'] . '\\''); } } function get_quantity($aItem) { $db = new SQLiteDatabase('report.sqlite'); $q = $db->query('SELECT quantity FROM data WHERE item=\\'' . $aItem . '\\''); $result = $q->current(SQLITE_NUM); return $result[0]; }
    20. Eliminate Duplicate Code if (isset($_REQUEST['action'])) { if ('add' == $_REQUEST['action']) { $quantity = get_quantity($_REQUEST['item']); $quantity++; $q = $db->queryExec('UPDATE data SET quantity=' . $quantity . ' WHERE item=\\'' . $_REQUEST['item'] . '\\''); } if ('remove' == $_REQUEST['action']) { $quantity = get_quantity($_REQUEST['item']); if ($quantity > 0) $quantity--; $q = $db->queryExec('UPDATE data SET quantity=' . $quantity . ' WHERE item=\\'' . $_REQUEST['item'] . '\\''); } }
    21. Eliminate Duplicate Code if (isset($_REQUEST['action'])) { if ('add' == $_REQUEST['action']) { $quantity = get_quantity($_REQUEST['item']); $quantity++; $q = $db->queryExec('UPDATE data SET quantity=' . $quantity . ' WHERE item=\\'' . $_REQUEST['item'] . '\\''); } if ('remove' == $_REQUEST['action']) { $quantity = get_quantity($_REQUEST['item']); if ($quantity > 0) $quantity--; $q = $db->queryExec('UPDATE data SET quantity=' . $quantity . ' WHERE item=\\'' . $_REQUEST['item'] . '\\''); } }
    22. Eliminate Duplicate Code if (isset($_REQUEST['action'])) { if ('add' == $_REQUEST['action']) { $quantity = get_quantity($_REQUEST['item']); $quantity++; update_quantity($_REQUEST['item'], $quantity); } if ('remove' == $_REQUEST['action']) { $quantity = get_quantity($_REQUEST['item']); if ($quantity > 0) $quantity--; update_quantity($_REQUEST['item'], $quantity); } } function update_quantity($aItem, $aQuantity) { $db = new SQLiteDatabase('report.sqlite'); $q = $db->queryExec('UPDATE data SET quantity=\\'' . $aQuantity . '\\' ' . 'WHERE item=\\'' . $aItem . '\\''); }
    23. Before if (isset($_REQUEST['action'])) { if ('add' == $_REQUEST['action']) { $q = $db->query('SELECT quantity FROM data WHERE item=\\'' . $_REQUEST['item'] . '\\''); $quantity = $q->current(SQLITE_NUM); $quantity = $quantity[0]; $quantity++; $q = $db->queryExec('UPDATE data SET quantity=' . $quantity . ' WHERE item=\\'' . $_REQUEST['item'] . '\\''); } if ('remove' == $_REQUEST['action']) { $q = $db->query('SELECT quantity FROM data WHERE item=\\'' . $_REQUEST['item'] . '\\''); $quantity = $q->current(SQLITE_NUM); $quantity = $quantity[0]; if ($quantity > 0) $quantity--; $q = $db->queryExec('UPDATE data SET quantity=' . $quantity . ' WHERE item=\\'' . $_REQUEST['item'] . '\\''); } }
    24. After if (isset($_REQUEST['action'])) { if ('add' == $_REQUEST['action']) { $quantity = get_quantity($_REQUEST['item']); $quantity++; update_quantity($_REQUEST['item'], $quantity); } if ('remove' == $_REQUEST['action']) { $quantity = get_quantity($_REQUEST['item']); if ($quantity > 0) $quantity--; update_quantity($_REQUEST['item'], $quantity); } }
    25. Step 5 Shorten Code Blocks The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 25
    26. Shorten Code Blocks • Break down code into little pieces • A method or function should fit on the screen without scrolling • When the code needs (too many) inline comments, it may be too complex • No more than three nesting levels The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 26
    27. The 30 Second Rule • If you don't understand a function or method in 30 seconds, it is probably too complex The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 27
    28. Step 6 Separate Different Concerns The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 28
    29. Separate Concerns • Three-Tier architecture: ▪ Presentation ▪ Business Logic ▪ Data Access • Functionality (add, remove, modify) • Input (pre)processing • No SQL near HTML The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 29
    30. Separate Concerns • Makes Unit Testing easier, because logic is decoupled from data source and presentation • Allows much more code reuse • Code becomes easier to read because you can focus on one aspect The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 30
    31. Separate Concerns $q = $db->query('SELECT * from data ORDER BY ' . $order); print '<table><tr><td><b><a href=\"?sort=item\">Item</a></b></td><td><b><a href=\"?sort=barcode\">Barcode</a></b></td><td><b><a href=\"?sort=shelf\">Shelf</a></b></td><td><b><a href=\"?sort=quantity\">Quantity</a></b></td></tr>'; while($q->valid()) { $r = $q->current(SQLITE_ASSOC); print '<tr>'; $first = true; foreach ($r as $key => $value) { if ($first) { $item = $value; $first = false; } print '<td>' . $value . '</td>'; if ('quantity' == $key) $sum += $value; } print '<td>[<a href=\"?sort=' . $order . '&action=add&item=' . $item . '\">+</a>]</td><td>[<a href=\"?sort=' . $order . '&action=remove&item=' . $item . '\">-</a>]</td></tr>'; $q->next(); } print '<tr><td></td><td></td><td>Total:</td><td><b>' . $sum . '</b></td></tr></table>';
    32. Data Access $q = $db->query('SELECT * from data ORDER BY ' . $order); print '<table><tr><td><b><a href=\"?sort=item\">Item</a></b></td><td><b><a href=\"?sort=barcode\">Barcode</a></b></td><td><b><a href=\"?sort=shelf\">Shelf</a></b></td><td><b><a href=\"?sort=quantity\">Quantity</a></b></td></tr>'; while($q->valid()) { $r = $q->current(SQLITE_ASSOC); print '<tr>'; $first = true; foreach ($r as $key => $value) { if ($first) { $item = $value; $first = false; } print '<td>' . $value . '</td>'; if ('quantity' == $key) $sum += $value; } print '<td>[<a href=\"?sort=' . $order . '&action=add&item=' . $item . '\">+</a>]</td><td>[<a href=\"?sort=' . $order . '&action=remove&item=' . $item . '\">-</a>]</td></tr>'; $q->next(); } print '<tr><td></td><td></td><td>Total:</td><td><b>' . $sum . '</b></td></tr></table>';
    33. Logic $q = $db->query('SELECT * from data ORDER BY ' . $order); print '<table><tr><td><b><a href=\"?sort=item\">Item</a></b></td><td><b><a href=\"?sort=barcode\">Barcode</a></b></td><td><b><a href=\"?sort=shelf\">Shelf</a></b></td><td><b><a href=\"?sort=quantity\">Quantity</a></b></td></tr>'; while($q->valid()) { $r = $q->current(SQLITE_ASSOC); print '<tr>'; $first = true; foreach ($r as $key => $value) { if ($first) { $item = $value; $first = false; } print '<td>' . $value . '</td>'; if ('quantity' == $key) $sum += $value; } print '<td>[<a href=\"?sort=' . $order . '&action=add&item=' . $item . '\">+</a>]</td><td>[<a href=\"?sort=' . $order . '&action=remove&item=' . $item . '\">-</a>]</td></tr>'; $q->next(); } print '<tr><td></td><td></td><td>Total:</td><td><b>' . $sum . '</b></td></tr></table>';
    34. Presentation $q = $db->query('SELECT * from data ORDER BY ' . $order); print '<table><tr><td><b><a href=\"?sort=item\">Item</a></b></td><td><b><a href=\"?sort=barcode\">Barcode</a></b></td><td><b><a href=\"?sort=shelf\">Shelf</a></b></td><td><b><a href=\"?sort=quantity\">Quantity</a></b></td></tr>'; while($q->valid()) { $r = $q->current(SQLITE_ASSOC); print '<tr>'; $first = true; foreach ($r as $key => $value) { if ($first) { $item = $value; $first = false; } print '<td>' . $value . '</td>'; if ('quantity' == $key) $sum += $value; } print '<td>[<a href=\"?sort=' . $order . '&action=add&item=' . $item . '\">+</a>]</td><td>[<a href=\"?sort=' . $order . '&action=remove&item=' . $item . '\">-</a>]</td></tr>'; $q->next(); } print '<tr><td></td><td></td><td>Total:</td><td><b>' . $sum . '</b></td></tr></table>';
    35. Separate Data Access function get_data($aSort) { $db = new SQLiteDatabase('report.sqlite'); $q = $db->query('SELECT * from data ORDER BY ' . $aSort); $result = array(); while($q->valid()) { $result[] = $q->current(SQLITE_ASSOC); $q->next(); } return $result; }
    36. Separate Logic function get_total() { $db = new SQLiteDatabase('report.sqlite'); $q = $db->query('SELECT SUM(quantity) from data'); $result = $q->current(SQLITE_NUM); return $result[0]; }
    37. Putting it together print '<table>'; print '<tr><td><b><a href=\"?sort=item\">Item</a></b></td><td><b><a href=\"?sort=barcode\">Barcode</a></b></td><td><b><a href=\"?sort=shelf\">Shelf</a></b></td><td><b><a href=\"?sort=quantity\">Quantity</a></b></td></tr>'; foreach (get_data() as $r) { print '<tr>'; $first = true; foreach ($r as $key => $value) { if ($first) { $item = $value; $first = false; } print '<td>' . $value . '</td>'; } print '<td>[<a href=\"?sort=' . $order . '&action=add&item=' . $item . '\">+</a>]</td><td>[<a href=\"?sort=' . $order . '&action=remove&item=' . $item . '\">-</a>]</td>'; print '</tr>'; } print '<tr><td></td><td></td><td>Total:</td><td><b>' . get_total() . '</b></td></tr></table>';
    38. New Possibilities print create_good_old_HTML_table(get_data(), get_total()); print create_fancy_AJAX_user_interface(get_data(), get_total()); export_data_to_a_really_really_special_format(get_data());
    39. Step 7 Replace Implementations The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 39
    40. Replace Implementations • Use native PHP instead of an old extension • Use components (PEAR, Zend Framework, ezComponents) • Use PHP extensions (XMLWriter, SOAP) The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 40
    41. Replace Implementations • Rewrite ugly functions/methods • Keep the API • If you don't rely on global variables, this should not affect the rest of the application The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 41
    42. The Seven Steps 1. Consistently Format Source Code 2. Establish Naming Conventions 3. Create API Documenation 4. Eliminate Redundant Code 5. Shorten Code Blocks 6. Separate Different Concerns 7. Replace Implementations The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 42
    43. What is Refactoring? • Changing code ▪ to improve readability ▪ to simplify the structure • Without changing the results • Not adding new functionality • 'Clean Up' the code • Improve the design The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 43
    44. What is Refactoring? • important part of agile methods • not only suited for OOP • an interesting experience • and fun to do! The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 44
    45. Why Refactor • The world constantly changes ▪ environment changes ▪ terminology changes ▪ requirements change • Software design decays over time • We never get things right the first time The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 45
    46. When To Refactor • Before you add new functionality ▪ Refactor until it becomes obvious how to add a feature • When you don't understand the code ▪ Make code more readable • When you fix a bug • After a code review The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 46
    47. How To Refactor • Run tests to make sure things work • Refactor, one step at a time • Rerun tests to make sure things still work • Automated Refactoring support starts showing up in PHP IDEs ▪ Automation does not replace thinking The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 47
    48. Testing • xUnit Framework for PHP ▪ PHPUnit (www.phpunit.de) ▪ SimpleTest (www.simpletest.org) • Not only for object-oriented code • If you don't have tests, create them as you go • At least, run a Lint check: php -l <filename> The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 48
    49. Resources • The definitive book on Refactoring: Martin Fowler: Refactoring. Improving the Design of Existing Code • www.refactoring.com • http://c2.com/cgi/wiki?WhatIsRefactoring • How to write unmaintainable code http://mindprod.com/jgloss/unmain.html • Slides will be made available at http://inside.e-novative.de The Seven Steps To Better PHP Code - Stefan Priebsch, e-novative GmbH 49
    50. The Seven Steps To Better PHP Code Thank you for listening. stefan.priebsch@e-novative.de

    + Stefan PriebschStefan Priebsch, 2 years ago

    custom

    2857 views, 6 favs, 4 embeds more stats

    Teaches refactoring PHP code in seven easy to learn more

    More info about this document

    © All Rights Reserved

    Go to text version

    • Total Views 2857
      • 2796 on SlideShare
      • 61 from embeds
    • Comments 0
    • Favorites 6
    • Downloads 86
    Most viewed embeds
    • 47 views on http://emartini.wordpress.com
    • 12 views on http://www.priebsch.de
    • 1 views on http://www.blogger.com
    • 1 views on http://faustol.wordpress.com

    more

    All embeds
    • 47 views on http://emartini.wordpress.com
    • 12 views on http://www.priebsch.de
    • 1 views on http://www.blogger.com
    • 1 views on http://faustol.wordpress.com

    less

    Flagged as inappropriate Flag as inappropriate
    Flag as inappropriate

    Select your reason for flagging this presentation as inappropriate. If needed, use the feedback form to let us know more details.

    Cancel
    File a copyright complaint
    Having problems? Go to our helpdesk?

    Categories