Agile Development with PHP in Practice


Published on

After a short theoretical introduction into the Extreme Programming (XP) and Scrum, the two major flavours of agile development, we will work on an example web project using Extreme Programming. The workshop will cover the whole development cycle - from planning through setting up a continuous integration server with test framework, up to developing and shipping a web application with PHP. We will add new features incrementally in a test-driven way, covering the application with unit and acceptance tests, keeping it integrated and fully functional all the time. While working, we will exercise all main practices of XP, starting with Pair Programming, Simple Design, Test-Driven Development, Refactoring and finishing with Continuous Integration and Small Releases.

Published in: Technology

Agile Development with PHP in Practice

  1. 1. Practising Agile Development for Beginners 30.10.2009 Lars Jankowfsky CTO swoodoo AG Freitag, 30. Oktober 2009
  2. 2. About me: PHP, C++, Developer, Software Architect since 1992 PHP since 1998 Many successful projects from 2 to 20 developers Running right now three projects using eXtreme Programming CTO and (Co-)Founder swoodoo AG (Co-)Founder OXID eSales AG Freitag, 30. Oktober 2009
  3. 3. lessons learned COST QUALITY TIME SCOPE Freitag, 30. Oktober 2009
  4. 4. Get Ready FIRE! Aim... Aim... Aim... Freitag, 30. Oktober 2009
  5. 5. Agile methods are based on Courage Simplicity Communication Feedback Freitag, 30. Oktober 2009
  6. 6. Individuals and interactions over processes and tools Working software over comprehensive documentation Customer collaboration over contract negotiation Responding to change over following a plan Freitag, 30. Oktober 2009
  7. 7. Agile? Agile? THINK! Freitag, 30. Oktober 2009
  8. 8. popular Agile methods Adaptive Software Development Feature Driven Development DSDM - Dynamic Systems Development Method Scrum crystal clear XP Freitag, 30. Oktober 2009
  9. 9. Scrum Plan ( product backlog ) Sprint planning session Sprint ( == Iteration ) Daily meetings Sprint review Closure Freitag, 30. Oktober 2009
  10. 10. eXtreme Programming for smaller teams ( 2 - 12 ) focuses on automatic testing a change in the way we program includes continuous integration Freitag, 30. Oktober 2009
  11. 11. Lessons learned Freitag, 30. Oktober 2009
  12. 12. eXtreme Programming „Software development is too hard to spend time on things that don't matter. So, what really matters? Listening, Testing, Coding, and Designing.” Kent Beck, “father” of Extreme Programming Freitag, 30. Oktober 2009
  13. 13. eXtreme Programming people vs. hardware automated tests continuous integration Freitag, 30. Oktober 2009
  14. 14. eXtreme Programming Planning Designing Coding Testing Freitag, 30. Oktober 2009
  15. 15. Planning XP Planning The Customer Stories Estimation Release Plan Freitag, 30. Oktober 2009
  16. 16. The Customer Planning Is always available Writes User Stories and specifies Functional Tests Sets priorities, explains stories May or may not be an end-user Has authority to decide questions about the stories Create/Defines acceptance tests Freitag, 30. Oktober 2009
  17. 17. Balancing Power Freitag, 30. Oktober 2009
  18. 18. Customer bill of rights Planning As the customer, you have the right to: • An overall plan, to know what can be accomplished, when, and at what cost • Get the most possible value out of every programming week • See progress in a running system, proven to work by passing repeatable tests that you specify • Change your mind, to substitute functionality, and to change priorities without paying exorbitant costs • Be informed of schedule changes, in time to choose how to reduce scope to restore the original date, even cancel at any time and be left with a useful working system reflecting investment to date. Freitag, 30. Oktober 2009
  19. 19. Programmer bill of rights Planning As the Developer, you have the right to: • Know what is needed, with clear declarations of priority; • Produce quality work at all times; • Ask for and receive help from peers, superiors, and customers; • Make and update your own estimates; • Accept your responsibilities instead of having them assigned to you. Freitag, 30. Oktober 2009
  20. 20. The Stories Planning A short story about the functionality from the point of view of the Customer No technical jargon One for each major feature in the system Must be written by the customer Are used to create time estimates for release planning Replace a large Requirements Document The stories are the base for acceptance tests Only enough detail to make a low risk estimate of how long the story will take to implement. Freitag, 30. Oktober 2009
  21. 21. Planning XP - the Stories Planning Use simple technics ( postit ) Find a place where all developer can see the stories Freitag, 30. Oktober 2009
  22. 22. Estimation Planning Yesterdays Weather use your experience ask other teams which may have done similar things Estimate using „Story Points“ == ideal Person Days Freitag, 30. Oktober 2009
  23. 23. Release Plan Planning Customer defines the business value of desired stories ( priority ) Stories which are too large need to be split into smaller chunks Higher risks stories should come first Define release dates - these are fixed, scope not Freitag, 30. Oktober 2009
  24. 24. The Release plan Planning Freitag, 30. Oktober 2009
  25. 25. Never slip a date! Planning falling behind ? Change the plan! Freitag, 30. Oktober 2009
  26. 26. Iterations Planning From release backlog the stories with highest priorities are taken and assigned to the next iteration. An iteration can be 1-3 weeks usually Stories for Iteration are broken down into Tasks by Developers Tasks are estimated by all Developers as a group Developers “sign up” for Tasks, and estimate the time to complete Freitag, 30. Oktober 2009
  27. 27. Iterations... Planning If a task has more than 2-3 Story points, then break it into smaller parts. If there are any questions ask the customer, he should attend Iteration planning meeting Can only sign up for as many points as were completed in the last Iteration Once development begins, Project Velocity measures progress Freitag, 30. Oktober 2009
  28. 28. Iterations... Planning Freitag, 30. Oktober 2009
  29. 29. Stand Up Meeting Planning Track status in daily Stand-Up Meeting Ask for Story Points left - not for SP done Every morning for 5 minutes STAND UP! What did you do yesterday ? What do you plan todo today ? Any „Showstoppers“ or important issues ? ( e.g. taking half day off... ) Tell Team what you did, not some „Task number“ Freitag, 30. Oktober 2009
  30. 30. During Iteration: Tracking speed Planning Freitag, 30. Oktober 2009
  31. 31. Designing XP Designing XP Simplicity Standards Never Add Spike Solutions Functionality Early Freitag, 30. Oktober 2009
  32. 32. (c) spackletoe (c) Freitag, 30. Oktober 2009
  33. 33. Simplicity Designing XP Keep things as simple as possible as long as possible by never adding functionality before it is scheduled. Always do the simplest thing that could possibly work Beware, keeping a design simple is hard work! Freitag, 30. Oktober 2009
  34. 34. (c) istockphoto Freitag, 30. Oktober 2009
  35. 35. Standards Designing XP Name classes and methods consistently. (Metaphor) Choose a system of names for your objects that everyone can understand easily (Zend?) Being able to guess at what something might be named if it already existed and being right is a real time saver PHP Code Sniffer PHP_CodeSniffer pre commit hook Freitag, 30. Oktober 2009
  36. 36. Spike Solutions Designing XP Don‘t guess on difficult questions, try it! Create simple programs to get answers. It reduces the risk of a technical problem or increase the reliability of a user story's estimate. API? Performance? Database? Freitag, 30. Oktober 2009
  37. 37. Never Add Functionality Early Designing XP Don‘t implement what you don‘t need now Only 10% of your guesses will be really used later Turn a blind eye towards future requirements and extra flexibility. Concentrate on what is scheduled for today only. Freitag, 30. Oktober 2009
  38. 38. Coding XP Coding XP Code the unit test first. Check in daily. Collective code ownership. Optimization last. No overtime. Refactor Mercilessly Freitag, 30. Oktober 2009
  39. 39. Code the unit test first. Coding XP Upon creation of a function write unit tests Write many tests for each function Success case Error case Stupid input case Freitag, 30. Oktober 2009
  40. 40. PHPUnit - Freitag, 30. Oktober 2009
  41. 41. Proxy for testing protected methods Coding XP class unittools{ public static function getProxy($superClassName, array $params = null) { $proxyClassName = "{$superClassName}Proxy"; if (!class_exists($proxyClassName, false)) { $class = <<<CLASS class $proxyClassName extends $superClassName { public function __call($function, $args) { $function = str_replace('UNIT', '_', $function); if(method_exists($this,$function)) { return call_user_func_array(array(&$this, $function), $args); } else { throw new Exception("Method ".$function." in class ".get_class($this)." does not exist"); } } public function setNonPublicVar($name, $value) { $this->$name = $value; } public function getNonPublicVar($name) { return $this->$name; } } CLASS; eval($class); } if (!empty($params)) { // Create an instance using Reflection, because constructor has parameters $class = new ReflectionClass($proxyClassName); $instance = $class->newInstanceArgs($params); } else { $instance = new $proxyClassName(); } return $instance; } } Freitag, 30. Oktober 2009
  42. 42. STOP Freitag, 30. Oktober 2009
  43. 43. Freitag, 30. Oktober 2009
  44. 44. Enforces layered Architecture Freitag, 30. Oktober 2009
  45. 45. Layer Example Coding XP class someOtherClass { var $setting; function calculateSomething($a, $b) { return $a+$b; } } class myOldNastyClass { function needToTestThisFunction() { $class = new someOtherClass(); $z = $_GET['input']; // .... return $class->calculateSomething( $class->setting, $z); } } Freitag, 30. Oktober 2009
  46. 46. Layer Example Coding XP class someOtherClass { private $setting; public function calculateSomething($a, $b) { return $a+$b; } public function setSetting($set) { $this->setting = $set; } public function getSetting() { return $this->setting; } } class myInput { public function getParameter($name) { return $_GET[$name]; } } class myOldNastyClass { private $input; // set e.g. in constructor public function needToTestThisFunction(someOtherClass &$class, $z) { $z = $input->getParameter('input'); // .... return $class->calculateSomething( $class->getSetting(), $z); } } Freitag, 30. Oktober 2009
  47. 47. (c) istockphoto Freitag, 30. Oktober 2009
  48. 48. Code the unit test first. Coding XP OOP, public, private Globals Superglobals Sessions Cookies Freitag, 30. Oktober 2009
  49. 49. Dependencies ... Coding XP Separate logic from view create accessors, add all parameters in calls Freitag, 30. Oktober 2009
  50. 50. Dependency Example Coding XP class displayUserDetails() { /** * Processes input and sends user first name, last name to display; */ function show() { global $dbLink; global $templateEngine; $itemId = (int) $_REQUEST['user_id']; $firstName = $dbLink->getOne("select first_name from users where id = $itemId"); $lastName = $dbLink->getOne("select last_name from users where id = $itemId"); $templateEngine->addTemplateVar('firstName', $firstName); $templateEngine->addTemplateVar('lastName', $lastName); $templateEngine->display(); } } Freitag, 30. Oktober 2009
  51. 51. Dependency Example Coding XP /** * A view class responsible for displaying user details. */ class userView() { /** * Loads user object and sends first name, last name to display */ public function show() { $userId = $this->_inputProcessor->getParameter("user_id"); $this->templateEngine->addTemplateVar('user', $this->model->loadUser(userId)); $this->templateEngine->display(); } } /** * And the corresponding model */ class userModel() { public function loadUser($userId) { $user = new User( $userId ); return array('firstName' => $user->getFirstName(), 'lastName' => $user->getLastName()); } } Freitag, 30. Oktober 2009
  52. 52. Fixtures Coding XP Make sure that tests don‘t alter fixture Fixture is FIXture if you feel creating fixtures is too much work - refactor more! Do never let tests leave altered tests Freitag, 30. Oktober 2009
  53. 53. Fixtures the Ruby way... Coding XP Ruby uses YAML PHP YAML support done by using Syck Syck = YAML + fast database-fixtures-the-ruby-way/ Freitag, 30. Oktober 2009
  54. 54. YAML loading Coding XP public static function create($fileName) { $fileName = 'Fixtures'.DIRECTORY_SEPARATOR.$fileName; ob_start(); include $fileName; $fileContents = ob_get_contents(); ob_clean(); $yamlData = syck_load($fileContents); return $yamlData; } Freitag, 30. Oktober 2009
  55. 55. YAML storing Coding XP public static function load($fixtures, $tableName) { if (is_array($fixtures) && count($fixtures)) { foreach ($fixtures as $fixture) { if (is_array($fixture) && is_array(current($fixture))) { Fixtures::load($fixture, $tableName); } $fields = array_keys($fixture); $statement = "INSERT INTO $tableName (" . implode(', ', $fields) . ") VALUES (:" . implode(", :", $fields) . ")"; $stmt = self::$_db->prepare($statement); if (count($fixture)) { foreach ($fixture as $key => $value ) { $stmt->bindValue(':'.$key, $value); } } $stmt->execute(); self::$_usedTables[$tableName] = $tableName; } } } Freitag, 30. Oktober 2009
  56. 56. YAML - cleanup Coding XP if (!empty(self::$_usedTables)) { foreach (array_reverse(self::$_usedTables) as $tableName) { self::$_db->execute("TRUNCATE TABLE $tableName"); } } Freitag, 30. Oktober 2009
  57. 57. Fixtures the other side ... Coding XP manual fixtures are too much work use a test database think about automatic creation of YAML files Freitag, 30. Oktober 2009
  58. 58. Mocking stubs? Coding XP „...may simulate the behavior of existing code (such as a procedure on a remote machine) or be a temporary substitute for yet-to-be- developed code...“ Freitag, 30. Oktober 2009
  59. 59. Mocking stubs? Coding XP Unittesting is about testing a unit of work, not a complete workflow isolates your code from external dependencies can be done with PHPUnit, but you don‘t need to Freitag, 30. Oktober 2009
  60. 60. Mocking stubs The PHPUnit way Coding XP /** * A simple stub providing a simple result directly instead of using the database */ class UserModelStub extends UserModel { public getUserCount() { return 10; } } UserModelStub extends PHPUnit_Framework_Testcase { public function testGetUserCount() { $stub = $this->getMock(‘UserModel‘); $stub->expects($this->any())->method(‘getUserCount‘)->will($this- >returnValue(10)); } } Freitag, 30. Oktober 2009
  61. 61. Check in daily Coding XP Forces developer to write small functions Makes it impossible to create huge frameworks/functions This is the fundament for having good tests later Remember: You are not allowed to check in without Tests! Freitag, 30. Oktober 2009
  62. 62. Collective code ownership Coding XP Collective Code Ownership encourages everyone to contribute new ideas to all segments of the project. (Don Wells) Have a look what your collegaues are doing Any developer can change any line of code to add functionality, fix bugs, or refactor. Freitag, 30. Oktober 2009
  63. 63. Pair Programming? Coding XP All code to be included in a production release is created by two people working together at a single computer... ???? Our experience is different! Use pair programming on difficult tasks e.g. refactoring, framework etc. In small teams it makes no sense to use it always. Freitag, 30. Oktober 2009
  64. 64. Freitag, 30. Oktober 2009
  65. 65. Optimize last Coding XP Make it work, make it right, then make it fast. Never guess what performance will be - measure it! Create clear rules for performance and test it. ( „ab“ or „siege“ can be used in unit tests ) Freitag, 30. Oktober 2009
  66. 66. No overtime Coding XP Projects that require overtime to be finished on time will be late no matter what you do. Overtime sucks the spirit and motivation out of a team. Better play a game instead and build castles instead of creating bugs in the software Freitag, 30. Oktober 2009
  67. 67. Refactor Mercilessly Coding XP “Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure.” Martin Fowler Freitag, 30. Oktober 2009
  68. 68. Principle of „Bad smell“ (c) istockphoto Freitag, 30. Oktober 2009
  69. 69. comments „what not why“ long methods dead code data classes Freitag, 30. Oktober 2009
  70. 70. Refactor Mercilessly Coding XP No fear! Your tests will show if you break something. Keep your code clean! Freitag, 30. Oktober 2009
  71. 71. Freitag, 30. Oktober 2009
  72. 72. Testing XP Testing XP Create acceptance Use continuous tests. integration! Run tests Publish the results automatically Freitag, 30. Oktober 2009
  73. 73. Hope vs. Knowledge Freitag, 30. Oktober 2009
  75. 75. Acceptance Tests Testing XP use Selenium Java solution which enables automatic „click“ tests. Download Selenium RC Create Acceptance Tests with Selenium IDE Use PHPUnit and create Unit Tests Base Tests on Customer Stories Freitag, 30. Oktober 2009
  76. 76. Integration Tests Testing XP can be Unit Tests or Selenium Testing API‘s, whole Modules Overall picture instead of single functions Freitag, 30. Oktober 2009
  77. 77. continuous integration Testing XP „Continuous Integration is a software development practice where members of a team integrate their work frequently, usually each person integrates at least daily - leading to multiple integrations per day. Each integration is verified by an automated build (including test) to detect integration errors as quickly as possible. „ Freitag, 30. Oktober 2009
  78. 78. continuous integration Testing XP cruisecontrol - phpundercontrol - check out Freitag, 30. Oktober 2009
  79. 79. continuous integration Testing XP Freitag, 30. Oktober 2009
  80. 80. „Questions?“ Freitag, 30. Oktober 2009
  81. 81. Resources used: Extreme Programming: A gentle introduction. Extreme Programming - Introduction Mayford Technologies Inc. Wikipedia Extreme Programming Explained: Embrace Change - Kent Beck Refactoring Improving the Design of Existing Code - Martin Fowler Freitag, 30. Oktober 2009