Best practices tekx

  • 7,898 views
Uploaded on

Tutorial delivered by Matthew Weier O'Phinney and Lorna Mitchell at TEK-X in Chicago, May 2010

Tutorial delivered by Matthew Weier O'Phinney and Lorna Mitchell at TEK-X in Chicago, May 2010

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
7,898
On Slideshare
0
From Embeds
0
Number of Embeds
1

Actions

Shares
Downloads
94
Comments
0
Likes
8

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Best Practices Matthew Weier O'Phinney Zend Framework Lorna Jane Mitchell Ibuildings @lornajane @weierophinney
  • 2. The Plan
    • Source Control
    • 3. Coding Standards
    • 4. Design Patterns
    • 5. Documentation
    • 6. Testing
    • 7. Quality and Continuous Integration
    • 8. Deployment
  • 9. Source Control
  • 10. Source Control Features
    • Version history of all files
    • 11. Collaboration tool
    • 12. Authoritative version of a project
    • 13. Integration point
  • 14. Using Source Control
    • Create a repository, add project
    • 15. Check out project
    • 16. Make changes
    • 17. Update to get other changes
    • 18. Commit changes to repo
  • 19. svn log ------------------------------------------------------------------------ r3 | lornajane | 2010-04-25 10:32:09 +0100 (Sun, 25 Apr 2010) | 1 line adding documentation notes ------------------------------------------------------------------------ r2 | lornajane | 2010-04-22 09:07:56 +0100 (Thu, 22 Apr 2010) | 1 line outlining source control and design patterns sections ------------------------------------------------------------------------ r1 | weierophinney | 2010-03-30 17:37:27 +0100 (Tue, 30 Mar 2010) | 1 line Added readme with outline ------------------------------------------------------------------------
  • 20. svn diff Index: README.txt =================================================================== --- README.txt (revision 3) +++ README.txt (revision 4) @@ -31,12 +35,20 @@ to share ideas to raise profile to be told you're doing it wrong! + (pulling up examples off our own blogs, if connection allows) Testing (Matthew) QA tools and CI including code analysis, mess detection, etc (Lorna - QA tools; Matthew - CI) + Static analysis + code sniffer + demo examples, find a suitable small codebase (joindin?) + mess detector + demo examples + what else? + Deployment
  • 21. Source Control Tools
    • Subversion (svn)
      • http://subversion.apache.org/
    • Git (git)
      • http://git-scm.com/
    • Bazaar (bzr)
      • http://bazaar.canonical.com/
    • Mercurial (hg)
      • http://mercurial.selenic.com/
  • 22. Accessing Source Control
    • IDE Plugins
    • 23. Trac ( http://trac.edgewall.org/ )
    • 24. TortoiseSVN
  • 27. Centralised Source Control user repo user user user
  • 28. Centralised Source Control
    • Single repo (repository)
    • 29. Always commit to central
    • 30. Can branch centrally
  • 31. Repository Structure (Feature Branches)
  • 32. Repository Structure (Long-Lived Branches)
  • 33. Repository Structure (Release Branches)
  • 34. Distributed Source Control repo repo repo repo repo
  • 35. Distributed Source Control
    • Many repos
    • 36. Commit to local repo
    • 37. Share changes between anywhere
    • 38. No central point
  • 39. The Changing Landscape
    • Very active development area
    • 40. Today's conclusions not valid for long!
  • 41. Bridges
    • git-svn
      • http://www.kernel.org/pub/software/scm/git/docs/git-svn.html
    • bzr-svn
      • https://launchpad.net/bzr-svn
    • Check out from SVN to local repo
    • 42. Make as many changes/branches as you like
    • 43. Push back to SVN
  • 44. Hosted Solutions GitHub http://github.com/ git Bitbucket http://bitbucket.org/ hg Google Code http://code.google.com/ svn, hg Launchpad https://launchpad.net/ bzr SourceForge http://sourceforge.net/ svn, bzr, hg, git (and cvs)
  • 45. What If I Don't Have Source Control?
    • Get some :)
    • 46. Install subversion
    • 47. Use a hosted solution
  • 48. Resources
    • Talks at TEK-X
      • Subversion in a Distributed World, Lorna Mitchell
      • 49. Getting Git, Travis Swicegood (who literally wrote the book)
      • 50. Both Wednesday afternoon
    • Subversion book
      • http://svnbook.red-bean.com/
    • Comparison of tools
      • http://en.wikipedia.org/wiki/Comparison_of_revision_control_software
  • 51. Coding Standards
  • 52. You don't have a standard when …
    • You always reformat code you get from others
    • 53. Code you wrote 6 months ago looks different than what you wrote today
    • 54. Modifying old code often introduces new syntax errors
  • 55. Answer the following questions:
    • Can you read your own code?
    • 56. Can others read your code?
    • 57. Can you read other's code?
    • 58. Can you switch between code bases easily?
  • 59. Analogy "Elements of Style" :: Writing Coding Standard :: Development
  • 60. In sum, coding standards assist in:
    • Maintainability
    • 61. Collaboration
  • 62. How CS aids maintainability: Code is structured predictably
  • 63. How CS aids collaboration
    • Any developer can pick up and easily read existing code
    • 64. … which in turn means they can maintain it
    • 65. … which de-centralizes who is responsible for the code
    • 66. … which means issues and reature requests are resolved faster
    • 67. It democratizes code maintenance
  • 68. Two pillars of a Coding Standard:
    • Consistency of file system layout
    • 69. Consistency of code layout
  • 70. Ancillary goal:
    • Consistency in naming
  • 71. Use Public Standards
    • NIH has no place with CS
      • You and your project's needs are not unique
      • 72. What if you need to consume and potentially help maintain 3rd party libraries?
      • 73. Benefit from collective knowledge and empirical discoveries
  • 74. Need more reasons?
    • Objectivity
      • Choices are no longer based on subjective preferences, but on empirical experience.
    • Requirement when hiring or outsourcing
      • Easily judge the candidate's experience and code quality.
    • Compatibility
      • Use a standard that follows that of the libraries you use.
  • 75. Choices
    • Horde/PEAR/Zend Framework
      • Also: Solar, AdoDB, Doctrine 2, Symfony 2, and more...
    • eZcomponents/ZetaComponents
    • 76. PHPLIB
  • 77. Example <?php /** * In Foo/Bar.php */ class Foo_Bar { const BAZ = 'baz' ; protected $_bat ; public $bas ; public function bazBat( $someVar ) { if ( $someVar ) { echo 'Found' ; } } }
  • 78. Resources
    • PEAR
      • http://pear.php.net/manual/en/standards.php
      • 79. http://pear.php.net/manual/en/pear2cs.php
    • Zend Framework
      • http://framework.zend.com/manual/en/coding-standard.html
  • 80. Design Patterns
  • 81. A Design Pattern Is ...
    • NOT rocket science
    • 82. A common way to describe a common problem
    • 83. Shared language
    • 84. A problem and solution which is repeated many times
    • 85. Common across programming languages
    • 86. Heavily OOP
  • 87. Some Common Patterns
  • 92. Factory
    • Has methods to create and return objects
    • 93. May return different objects
    • 94. May use complex (and maintainable) logic to work out what to do
  • 95. Factory Example: Hat Types 1 < ?php 2 3 require_once ( 'hat.php' ); 4 5 class HatFactory { 6 public function getHat ( $type = 'woolly' ) { 7 // perform any logic you like here 8 return new Hat ( $type ); 9 } 10 } http://www.flickr.com/photos/91524358@N00/2260054061/
  • 96. Registry
    • Can be a singleton (but this is not a requirement!)
    • 97. Register objects here, access from elsewhere
    • 98. Often a factory/registry combination
  • 99. Registry Example: Hat Storage 1 < ?php 2 3 class HatRegistry { 4 private $registry ; 5 6 public function __construct () { 7 $this -> registry = array (); 8 } 9 10 public function registerHat ( $key , $hat ) { 11 $this -> registry [ $key ] = $hat ; 12 } 13 14 public function fetchHat ( $key ) { 15 return $this -> registry [ $key ]; 16 } 17 }
  • 100. Adapter
    • Adapts a specific interface to fit something else; typically, to provide a common API to related classes/components that have divergent APIs.
    • 101. Allows the class wrapped by the adapter to exist independently from the component consuming the adapter.
  • 102. Adapter Example: SOAP to REST
    • Real life example
    • 103. Client project to deliver SOAP
  • 104. PHP SOAP 1 < ?php 2 3 require_once ( 'lib/myClass.php' ); 4 5 $server = new SoapServer ( null , $options ); 6 $server -> setClass ( &quot;MyClass&quot; ); 7 $server -> handle ();
  • 105. Adapter Example: SOAP to REST
    • Real life example
    • 106. Client project to deliver SOAP
    • 107. Service part-built
    • 108. Client reads textbook(?)
    • 109. Client requests REST
    • 110. Adapter class to the rescue!
  • 111. Adapter Example: SOAP to REST myClass index.php
  • 112. Adapter Example: SOAP to REST myClass index.php Adapter
  • 113. Decorator
    • Wraps another class in order to modify its behavior
    • 114. Target class doesn't change
    • 115. Decorating class often implements the same interface(s)
    • 116. Can be visually decorative, not always
  • 117. Decorator Example 1 < ?php 2 3 interface LabelInterface { 4 public function render (); 5 } 6 7 class BasicLabel implements LabelInterface { 8 public function render () { 9 return $this -> label ; 10 } 11 }
  • 118. Decorator Example 13 abstract class LabelDecorator implements LabelInterface { 14 public function __construct ( LabelInterface $label ) { 15 $this -> label = $label ; 16 } 17 } 18 19 class LabelStarDecorator extends LabelDecorator { 20 public function render () { 21 return '** ' . $this -> label -> render () . ' **' ; 22 } 23 } 24 25 class LabelNewLineDecorator extends LabelDecorator { 26 public function render () { 27 return $this -> label -> render () . &quot; &quot; ; 28 } 29 } 30 31 class LabelHyphenDecorator extends LabelDecorator { 32 public function render () { 33 return str_replace ( ' ' , '-' , $this -> label -> render ()); 34 } 35 }
  • 119. Decorator Example 1 < ?php 2 3 require_once ( 'Label.php' ); 4 5 $basic_label = new BasicLabel (); 6 $basic_label -> label = &quot;Hello World&quot; ; 7 echo $basic_label -> render (); 8 9 $label = new LabelNewLineDecorator ( new LabelStarDecorator ( $basic_label )); 10 $label = new LabelNewLineDecorator ( new LabelStarDecorator ( new LabelHyphenDecorator ( $basic_label ))); 11 $label = new LabelNewLineDecorator ( new LabelHyphenDecorator ( new LabelStarDecorator ( $basic_label )));
  • 120. Observer
    • Watches for changes in another object
    • 121. Responds to those changes
    • 122. Target class is aware, notifies observing classes
    • 123. Example: a map showing where event attendees are located - needs to update when list updates
  • 124. Observer Example 3 class AttendeeList { 4 private $attendees ; 5 private $observers ; 6 7 public function addAttendee ( $id , $name ) { 8 $this -> attendees [ $id ] = $name ; 9 $this -> notify (); 10 } 11 12 public function removeAttendee ( $id ) { 13 unset ( $this -> attendees [ $id ]); 14 $this -> notify (); 15 } 16 17 public function notify () { 18 foreach ( $this -> observers as $ob ) { 19 $ob -> update ( $this ); 20 } 21 } 22 23 public function registerObserver ( $observer ) { 24 $this -> observers [] = $observer ; 25 } 26 }
  • 125. Observer Example AttendeeList Map Invites ...
  • 126. Resources
    • Books
      • Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides (&quot;Gang of Four&quot;)
      • 127. php|architect’s Guide to PHP Design Patterns by Jason Sweat
      • 128. Patterns of Enterprise Application Architecture by Martin Fowler (&quot;PoEAA&quot;)
    • Jason Sweat speaking on Design Patterns (Friday morning at TEK-X)
    • 129. http://www.fluffycat.com/PHP-Design-Patterns/
  • 130. Documentation
  • 131. API Docs
    • Documentation generated from source code itself
    • 132. Follows code structure
  • 136. PHPDocumentor
  • 137. PHPDocumentor
    • PHPDocumentor
      • http://www.phpdoc.org/
    • Uses reflection
    • 138. Comments for additional information
    • 139. Add descriptions to the documentation
  • 140. PHPDocumentor Comments 1 < ?php 2 3 class AttendeeList { 4 private $attendees ; 5 private $observers ; 6 7 /** 8 * Add an attendee to the list 9 * 10 * @param integer $id Attendee identifier/array index 11 * @param string $name Full name of the attendee 12 * @access public 13 * @return boolean If attendee was successfully added 14 */ 15 public function addAttendee ( $id , $name ) { 16 $this -> attendees [ $id ] = $name ; 17 $this -> notify (); 18 } 19 20 }
  • 141. Generating PHPDoc Output
    • Two main interfaces
      • Command line, e.g.
        • phpdoc -o HTML:frames:earthli -f sample1.php -t docs
      • Web Interface
    • IDE Plugins
  • 142. End-User Documentation
  • 143. Come again?
    • Narrative documentation for developers
    • 144. Often describes architecture, theory, and design patterns used
    • 145. Typically includes many example use cases
  • 146. What should you use?
    • Wikis
      • Easy for others to contribute
      • 147. Typically un-distributable, never mind offer in alternate formats
      • 148. Difficult to translate
      • 149. Usually un-versioned
  • 150. What should you use?
    • HTML
      • Easy for people with any web background to contribute
      • 151. Distributable, but difficult to offer in alternate formats
      • 152. Can be translated
      • 153. Can be versioned
  • 154. What should you use?
    • Docbook XML
      • Reasonably easy for people with a web background to contribute; easier if you establish standards
      • 155. Distributable, and trivial to offer in alternate formats (e.g., HTML, Windows Help files (CHM), PDF, man pages, etc.)
      • 156. Can be translated
      • 157. Can be versioned
  • 158. Docbook Example <?xml version = &quot;1.0&quot; encoding = &quot;UTF-8&quot; ?> <sect1 id = &quot;some.component&quot; > <title> Using Some Component </title> <para> This is a thorougly magical, catch-all component. <ulink url = &quot;http://wikipedia.com/&quot; > Wikipedia </ulink> may have more info. </para>
  • 159. Docbook Example <example id = &quot;some.component.example&quot; > <title> Example </title> <programlisting lang = &quot;php&quot; > <![CDATA[ $foo = new Component(); ]] ></programlisting> </example>
  • 160. Docbook Example <sect2 id = &quot;some.component.more-info&quot; > <title> More information </title> <itemizedlist> <listitem><para> Not much! </para></listitem> </itemizedlist> </sect2> </sect1>
  • 161. Tools You Will Need
    • xsltproc
      • http://xmlsoft.org/XSLT/xsltproc2.html
    • PhD (PHP Documentor)
      • http://doc.php.net/phd/docs/
  • 162. Beyond API Docs
  • 168. Be a User-Contributor
    • Answer forum questions
    • 169. Hang out on the IRC channel
    • 170. Help with official project documentation
    • 171. Blog
      • http://www.lornajane.net
      • 172. http://weierophinney.net/matthew/
  • 173. Testing
  • 174. Why Test?
    • Makes future maintenance of the code easier
      • Defined expectations
      • 175. Known behaviors
      • 176. Identify early when changes in code break existing behaviors
  • 177. Why Test?
    • Quantify the quality of your code
      • Code coverage (not the best metric)
      • 178. Self-documented behaviors via unit tests
  • 179. Why Test?
    • Warm fuzzy feeling from seeing green
  • 180. What testing is not:
    • Reloading
  • 181. What testing is not:
    • var_dump()
  • 182. Testing is …
    • Reproducible
  • 183. Testing is …
    • Automatable
  • 184. Good testing includes …
    • Defined behaviors
    • 185. Code examples of use cases
    • 186. Expectations
  • 187. Testing frameworks
    • PHPT
      • Used by PHP project, some PEAR libraries
    • SimpleTest
      • JUnit style testing framework
    • PHPUnit
      • JUnit style testing framework; de facto standard
  • 188. How to test
    • Create a test case class
      • Usually named after the unit or class you're testing
    class Css2XpathTest extends PHPUnit_Framework_TestCase
  • 189. How to test
    • What is the behavior you're testing?
      • State it in your native language &quot;Should Allow Whitespace In Descendent Selector Expressions&quot;
      • 190. Create a method named after the behavior public function testShouldAllowWhitespaceInDescendentSelectorExpressions()
      • 191. Capture the code that should create the behavior $test = Css2Xpath::transform('child > leaf');
      • 192. Create assertions indicating the expected results $this->assertEquals(&quot;//child/leaf&quot;, $test);
  • 193. How to test
    • Run the tests
      • Success? Move on to the next behavior
      • 194. Failure?
        • Check your test assumptions and assertions
        • 195. Check your code and correct it
        • 196. Re-run the tests to verify
  • 197. Other Testing Topics
    • Test Doubles
      • Stubs Replacing an object with another so that the system under test can continue down a path.
      • 198. Mock Objects Replacing an object with another and defining expectations for it.
  • 199. Other Testing Topics
    • Test Coverage What lines were executed, and how many times?
    • 200. Conditional tests Testing only when certain environmental conditions are met.
    • 201. Functional and Integration tests Testing that the systems a unit interacts with all respond as expected.
  • 202. Adding tests to existing, untested projects
    • Create tests:
      • Whenever you introduce new features, for those features
      • 203. Whenever you attempt to fix a bug
        • Capture the desired behavior in a unit test
        • 204. Fix the bug
      • Whenever you refactor
  • 205. Test-Driven Development
    • Capture behaviors individually and iteratively in unit tests
    • 206. Write code to make the tests pass
    • 207. Allows for playing with APIs before you've committed to coding them
    • 208. Often hard to get into the rhythm; once you do, often hard to quit
  • 209. Takeaways
    • Testing is easy
    class Css2XpathTest extends PHPUnit_Framework_TestCase { public function testShouldAllowWSInDescendentSctrExpressions() { $test = Css2Xpath::transform( 'child > leaf' ); $this ->assertEquals( &quot;//child/leaf&quot; , $test ); } }
  • 210. Takeaways
    • Test whenever you can -- preferably ALWAYS
    • 211. Automate your test suite (next topic!)
  • 212. Quality and CI
  • 213. Static Analysis
    • Analysing code without execution
    • 214. Evaluating code properties and patterns
    • 215. Common tools
      • Lines of code ( http://github.com/sebastianbergmann/phploc )
      • 216. Code sniffer ( http://pear.php.net/PHP_CodeSniffer )
      • 217. Mess detector ( http://phpmd.org/ )
  • 218. Lines of Code
    • Born from PHPUnit
    • 219. Available via PHPUnit's PEAR channel
    • 220. Shows lots of stats about a codebase
    • 221. Methods, lines per method
    • 222. Cyclomatic complexity: a measure of branching points in code
    • 223. E.g. when applied to wordpress:
  • 224. Lines of Code Example * phploc 1.3.2 by Sebastian Bergmann. Directories: 29 Files: 295 Lines of Code (LOC): 138661 Cyclomatic Complexity / Lines of Code: 0.19 Comment Lines of Code (CLOC): 43498 Non-Comment Lines of Code (NCLOC): 95163 * example from http://techportal.ibuildings.com/2010/01/28/phploc-php-lines-of-code/
  • 225. Lines of Code Example Interfaces: 0 Classes: 168 Abstract: 0 (0.00%) Concrete: 168 (100.00%) Lines of Code / Number of Classes: 377 Methods: 1973 Scope: Non-Static: 1972 (99.95%) Static: 1 (0.05%) Visibility: Public: 1964 (99.54%) Non-Public: 9 (0.46%) Lines of Code / Number of Methods: 32 Cyclomatic Complexity / Number of Methods: 5.44 Functions: 1599 Constants: 272 Global constants: 272 Class constants: 0
  • 226. Code Sniffer
    • Associated with coding standards
    • 227. Configurable &quot;sniffs&quot; to look for different properties
  • 228. Code Sniffer Example * 1 < ?php 2 3 class recipe 4 { 5 6 protected $_id ; 7 8 public $name ; 9 10 public $prep_time ; 11 12 function getIngredients () { 13 $ingredients = Ingredients :: fetchAllById ( $this -> _id ); 14 return $ingredients ; 15 } 16 } * example from http://techportal.ibuildings.com/2009/10/12/usphp_code_sniffer/
  • 229. Code Sniffer Example FILE: /home/lorna/phpcs/recipe.php ------------------------------------------------------------------- FOUND 8 ERROR(S) AND 0 WARNING(S) AFFECTING 5 LINE(S) ------------------------------------------------------------------- 2 | ERROR | Missing file doc comment 3 | ERROR | Class name must begin with a capital letter 3 | ERROR | Missing class doc comment 6 | ERROR | Protected member variable &quot;_id&quot; must not be prefixed | | with an underscore 12 | ERROR | Missing function doc comment 12 | ERROR | Opening brace should be on a new line 13 | ERROR | Line indented incorrectly; expected at least 8 | | spaces, found 1 13 | ERROR | Spaces must be used to indent lines; tabs are not | | allowed ------------------------------------------------------------------- output of running recipe.php through PEAR sniffs
  • 230. Mess Detector
    • Uses some &quot;rule of thumb&quot; metrics
    • 231. Tells you about the codebase, at a macro level
    • 232. Can catch
      • long class/method names and parametere lists
      • 233. complex code
      • 234. classes with too many public methods
      • 235. other &quot;bad smells&quot;
    • Under development
  • 236. Continuous Integration (CI)
  • 237. Continu … what?
    • Originally, automated build systems for compiled languages
    • 238. Used in PHP to run unit tests, build documentation, etc.
    • 239. Basically, any documentation or QA tool we've talked about can and should be automated
  • 240. Basics
    • System typically monitors commits
      • Have a post-receive/commit hook trigger a build
      • 241. Have cron/sleep processes that periodically wake up and check for new commits
    • A PHP Build …
      • Runs tests,
      • 242. Runs QA tools (mess detection, etc.),
      • 243. Builds documentation
  • 244. Solutions
    • Ant: http://ant.apache.org/
      • Not CI by itself, but a build system
    <?xml version = &quot;1.0&quot; encoding = &quot;UTF-8&quot; ?> <project name = &quot;zend_framework_current&quot; default = &quot;build&quot; basedir = &quot;.&quot; > <property name = &quot;output.dir&quot; value = &quot;${basedir}/build&quot; /> <target name = &quot;build&quot; depends = &quot;clean, checkout, apidoc, test&quot; /> <target name = &quot;checkout&quot; > <exec executable = &quot;svn&quot; dir = &quot;${basedir}&quot; > <arg line = &quot;co http://framework.zend.com/svn/framework/branch/release-1.10 source&quot; /> </exec> </target> <!-- ... --> </project>
  • 245. Solutions
    • Phing: http://phing.info/trac/
      • PHP Ant clone; again, not CI, but a build tool
    <?xml version = &quot;1.0&quot; encoding = &quot;UTF-8&quot; ?> <project name = &quot;tekx&quot; basedir = &quot;.&quot; > <property file = &quot;build.properties&quot; /> <target name = &quot;default&quot; > <echo message = &quot;Hello, attendees!&quot; /> </target> </project>
  • 246. Solutions
    • CruiseControl: http://cruisecontrol.sourceforge.net/
      • Uses Ant under the hood
    <cruisecontrol> <project name = &quot;zend_framework_current&quot; <schedule interval = &quot;86400&quot; > <ant anthome = &quot;apache-ant-1.7.0&quot; buildfile = &quot;projects/${proje </schedule> <modificationset quietperiod = &quot;0&quot; > <svn LocalWorkingCopy = &quot;projects </modificationset>
  • 247. Solutions
    • CruiseControl
  • 248. Solutions
    • phpUnderControl: http://www.phpundercontrol.org/
      • Superset of CruiseControl with built-in support for PHPUnit, CodeSniffer, and more.
  • 249. Solutions
    • Hudson: http://hudson-ci.org/
      • Oracle OSS project, written in Java, under active development.
      • 250. Also uses Ant for build configuration
      • 251. PHPUnit support via a generic xUnit plugin
      • 252. Support for other PHP tasks via a Phing plugin
  • 253. Solutions
    • Bamboo: http://www.atlassian.com/software/bamboo/
      • Commercial Java CI solution
      • 254. Can use Ant or Maven
      • 255. Most PHP QA tools export logs to formats compatible with equivalent Java tools; Bamboo simply uses these logs.
  • 256. Takeaways
    • Automate your QA tasks
      • Find issues early
      • 257. Fix them before deployment
    • Use continuous integration solutions to perform the automation
  • 258. Resources
    • Sebastian Bergmann's talk &quot;The State of QA Tools in PHP&quot;
    • 259. http://phpqatools.org
    • 260. http://phpqabook.com
  • 261. Deployment
  • 262. Why You Need A Process
    • Many steps for live deploy
    • 263. Wrap into one step, you won't miss anything
    • 264. It'll be done the same way by everyone
    • 265. You can roll back
      • (if you build that into your process)
  • 266. Deployment Tools
    • Hand-spun scripts
    • 267. Phing
      • http://phing.info/trac/
    • Capistrano (Ruby)
      • http://www.capify.org/index.php/Capistrano
  • 268. Further Reading
    • http://phpdeveloper.org
    • 269. http://devzone.zend.com
    • 270. http://techportal.ibuildings.com
  • 271. Thanks
    • http://joind.in/1563