• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Living With Legacy Code
 

Living With Legacy Code

on

  • 12,551 views

Practical tips for dealing with projects involving legacy code. Covers investigating past projects, static analysis of existing code, and methods for changing legacy code. ...

Practical tips for dealing with projects involving legacy code. Covers investigating past projects, static analysis of existing code, and methods for changing legacy code.

Presented at PHP Benelux '10

Statistics

Views

Total Views
12,551
Views on SlideShare
10,213
Embed Views
2,338

Actions

Likes
9
Downloads
85
Comments
2

22 Embeds 2,338

http://merewood.org 2211
http://www.merewood.org 24
http://martindekeijzer.nl 22
http://www.slideshare.net 20
http://www.martindekeijzer.nl 15
http://abtasty.com 12
http://www.rodeveer.be 6
http://mlocal.merewood.org 5
http://intranet 4
http://www.linkedin.com 3
http://www.vanderveer.be 2
http://m.merewood.org 2
http://awesomepitch.co 2
http://bitly.com 2
http://webcache.googleusercontent.com 1
http://www.365dailyjournal.com 1
http://ranksit.com 1
http://www.phptalks.de 1
http://www.thewebhatesme.com 1
http://life-of-a-webdeveloper.blogspot.com 1
https://www.linkedin.com 1
http://mrowan8832.merewood.org.moovapp.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

12 of 2 previous next

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

    Living With Legacy Code Living With Legacy Code Presentation Transcript

    • vingLiwithLegacy Code
    • @rowan_m
    • @rowan_mPlusnet Ibuildings
    • What is“Legacy Code”?
    • What is“Legacy Code”? Code without tests Code youve “inherited” Code no-one understands Technical debt
    • Who has never createdLegacy Code?
    • My own littlestory
    • Pragmatic, not ideal isticMy own littlestory
    • Starting a project
    • Aim to understand the concepts and motivations
    • Try usingthe application
    • Find and then read any / all documentation
    • Official: CheProject brief ( ) c kliRequirements ( ) stTech. Spec. ( )Actual:Emails ( )Meeting notes ( )Progress:Gant charts ( )Burndowns ( )Overtime logs ( )Quality:Bug tracker ( )Complaints ( )User Forums ( )
    • Talk to theoriginal developers
    • Talk to the users … especially the “different” ones
    • Approaching the code
    • Catalogue thelive platform& environment
    • Recreate it!
    • Deploy the code
    • PHP: Chephp.ini ( ) c kliPEAR / PECL modules ( ) stCompile options ( )Patches ( )The Rest:OS ( )Package manager ( )Web server ( )Web server modules ( )Site config. ( )Database ( )Cache ( )JS libraries ( )Firewall rules ( )Proxies ( )Services running ( )
    • Time to enter The Code
    • Time to enter The Code ReadingStatic analysisDynamic analysis
    • http://www.phpdoc.org/ docphp Title phpdoc -ti Sweet Application -pp -o HTML:Smarty:PHP -d Libraries Style -t Docs Code in here Docs out here!
    • Beware of type-hiding! Type-hinting/** * @param array $opts Current options * @return array Options with flag set */function setFlag(array $opts) { $opts[flag] = true; return $opts;} Type-hiding /** * @param int $fullPence Full price in pence * @return float Discounted price in pence */ function applyDiscount($fullPence) { return ($fullPence * 0.8); }
    • ygendox doxygen -s -g ~/doxy.conf vim ~/doxy.conf # edit at least thisCode in here OUPUT_DIRECTORY # play with the rest cd ~/dev/project Docs out here doxygen ~/doxy.conf http://www.stack.nl/~dimitri/doxygen/
    • http://ctags.sourceforge.net/ ta gsc Code in here#!/bin/bash Tags out herecd ~/Dev/ &&ctags-exuberant -f ~/.vimtags -h ".php" -R --exclude=".git" --links=no --totals=yes --tag-relative=yes --PHP-kinds=+cf --regex-PHP=/abstracts+classs+([^ ]+)/1/c/ --regex-PHP=/interfaces+([^ ]+)/1/c/ --regex-PHP=/(publics+|statics+|abstracts+|protecteds+|privates+) ↵ functions+&?s*([^ (]+)/2/f/ Voodoo
    • ml http://www.bouml.fr/bou
    • ml http://bouml.free.fr/bou
    • ml http://bouml.free.fr/bou
    • ml http://bouml.free.fr/bou
    • ml http://bouml.free.fr/bou
    • ml http://bouml.free.fr/bou
    • ou mlb
    • ffer esnico drowan@swordbean:~/Dev/ZendFramework-1.9.4/library/Zend/Service$ phpcs --standard=Zend Exception.phpFILE: /home/rowan/Dev/ZendFramework-1.9.4/library/Zend/Service/Exception.php--------------------------------------------------------------------------------FOUND 1 ERROR(S) AND 2 WARNING(S) AFFECTING 3 LINE(S)-------------------------------------------------------------------------------- 17 | WARNING | Line exceeds 80 characters; contains 87 characters 32 | WARNING | Line exceeds 80 characters; contains 87 characters 36 | ERROR | Opening class brace must be on a line by itself 36 | ERROR | Closing brace must be on a line by itself-------------------------------------------------------------------------------- http://pear.php.net/package/PHP_CodeSniffer/
    • t in uousCon io nInte grat http://jenkins-ci.org/ http://phpundercontrol.org/ http://sismo.sensiolabs.org/
    • Decisi on tim e!
    • Decisi on tim e! Igncod ore e a it , nyw ay a cto r, ref est ite, st, t Rewr , te test
    • Ignore it,code anyway
    • Ignore it,code anywayPlease dont.
    • Ignore it,code anywayPlease dont. however...
    • Deadlines, clients, money, etc.
    • Deadlines, clients, money, etc. Make everyoneaware of the risks Secure afollow-up project
    • Why do you need the code?
    • Why do you need the code? simple Library dependency Adding new behaviour Changing behaviour complex
    • Isolatelegacy dependencies
    • Isolatelegacy dependencies Create ananti-corruption layer
    • Complete isolation Create a legacy service
    • Partial isolation Wrapper classes or methods
    • Wrapper class<?phpinclude(/home/victorvon/secrets.inc);/** * @param array $person willing volunteer */function extract_brain(&$person) { $brain = $person[brain]; unset($person[brain]);} return $brain; Some code/** you need * @param array $person * @return bool living or not :( */function create_life($person) { require_once(LIB_DIR.../nuts_n_bolts.inc); kerzap(); $person[living] = true; return $person;}?>
    • class VictorWrapper{ Wrapper class public function __construct() { require_once /home/victorvon/tragedy.php; } public function extractBrain(Person $p) { // format to legacy style $pLgcy = $this->toArray($p); // run legacy code $bLgy = extract_brain($pLgcy); // format to new style $p = $this->toPerson($pLgcy); Some code $b = $this->toBrain($bLgcy); return array($p, $b); you can use } :) public function createLife(Person $p) { // validate if ($person->isAlive()) throw new LivingException(); // format to legacy style $pLgcy = $this->toArray($p); // run legacy code $pLgy = create_life($pLgcy); // format to new style return $this->toPerson($pLgcy); }}
    • Changing the code
    • Changing the code Take an incremental approach Commit to 1 day at a time
    • Why?Difficult to estimateHidden dependencies Unknown behaviour
    • 1. Get it intoversion control
    • 2. Identify theinflection point
    • 3. Create integration & acceptance tests
    • 4. Set up yourcontinuous integration environment
    • 5. Rewrite and refactor!
    • Types ofchanges
    • Mixed → Procedural
    • includes HTML PHP HTMLHTML PHP HTML PHP HTML PHP PHP HTML PHP HTML HTML PHP HTML PHP
    • includes function function function includes HTML PHP HTML HTML echo HTMLHTML PHP HTML HTML echo HTML PHP HTML PHP if HTML if PHP foreach HTML PHP HTML HTML echo HTML HTML PHP HTML HTML echo HTML PHP foreach
    • Procedural → OO
    • includesfunctionfunctionfunctionfunctionfree code
    • includes includesfunction static methodfunction static methodfunction static methodfunction static methodfree code static method
    • includes includes includesfunction static method constructorfunction static method methodfunction static method methodfunction static method methodfree code static method method
    • Sprout method / class
    • public function createInvoice(Account $acc, array $charges){ $invoice = new Invoice(); foreach ($charges as $chg) { $invoice->addLine($chg->getDesc(), $chg->getAmount()); } return $invoice;} The existing code“We just need to be able to giveeach client their own personal discount on certain charges.”
    • public function createInvoice(Account $acc, array $charges){ $invoice = new Invoice(); foreach ($charges as $chg) { $invoice->addLine($chg->getDesc(), $chg->getAmount()); } return $invoice;} The new codeprivate function calcDiscount(Account $acc, Charge $chg){ $accDisc = new AccountDiscounter($acc); $discountedCharge = $accDisc->calculate($chg); return $discountedCharge;}
    • public function createInvoice(Account $acc, array $charges){ $invoice = new Invoice(); Call it foreach ($charges as $chg) { // Sprout new behaviour! $chg = $this->calcDiscount($acc, $chg); $invoice->addLine($chg->getDesc(), $chg->getAmount()); } return $invoice;}private function calcDiscount(Account $acc, Charge $chg){ $accDisc = new AccountDiscounter($acc); $discountedCharge = $accDisc->calculate($chg); return $discountedCharge;}
    • Untestable OO → testable OO
    • Dependency Inversion / Extraction
    • The Problempublic function calcDiscount(Account $acc, Charge $chg){ $accDisc = new AccountDiscounter($acc); $discountedCharge = $accDisc->calculate($chg); return $discountedCharge;} Untestable!
    • The Problempublic function calcDiscount(Account $acc, Charge $chg){ $accDisc = new AccountDiscounter($acc); $discountedCharge = $accDisc->calculate($chg); return $discountedCharge;} Untestable!class AccountDiscounter{ public function __construct(Account $acc) { // check cache // contact the database // call a web service }}
    • Quick Solutionpublic function calcDiscount(Account $acc, Charge $chg){ $accDisc = $this->getAccountDiscounter($acc); $discountedCharge = $accDisc->calculate($chg); return $discountedCharge;} Mock object in your test Override methodprotected function getAccountDiscounter(Account $acc){ return new AccountDiscounter($acc);}
    • Dependency Injection Solutionpublic function __construct(AccountDiscounter $ad){ $this->discounter = $ad;} Pass it into the classpublic function calcDiscount(Account $acc, Charge $chg){ $accDisc = $this->discounter; $discountedCharge = $accDisc->calculate($chg); return $discountedCharge;}
    • (v2) → Dependency Injection Solutionpublic function __construct(IAccountDiscounter $ad){ $this->discounter = $ad;} Make an interfacepublic function calcDiscount(Account $acc, Charge $chg){ $accDisc = $this->discounter; $discountedCharge = $accDisc->calculate($chg); return $discountedCharge;}
    • Summary Analyse Plan Test IsolatE ChangeTest MORE
    • Any questions? Feedback to: https://joind.in/6020 @rowan_m
    • Further reading: Michael Feathers Martin Fowlerhttp://www.flickr.com/photos/flatlinevision/1514971535/http://commons.wikimedia.org/wiki/File:Weird_Tales_November_1950.jpghttp://commons.wikimedia.org/wiki/File:AdventuresIntoDarkness1401.jpghttp://www.flickr.com/photos/locationscout/3594432797/http://www.flickr.com/photos/rawhead/3466304669/http://commons.wikimedia.org/wiki/File:Rocket_to_the_Moon_54893.jpghttp://commons.wikimedia.org/wiki/File:Weird_Chills_July.jpghttp://commons.wikimedia.org/wiki/File:Terrific_01.jpghttp://commons.wikimedia.org/wiki/File:Strange_Fantasy_01.jpghttp://commons.wikimedia.org/wiki/File:Beware_01.JPGhttp://www.flickr.com/photos/erokcom/2873449983/http://www.flickr.com/photos/locationscout/3594433235/http://commons.wikimedia.org/wiki/File:Weird_Chills_Sept.JPGhttp://commons.wikimedia.org/wiki/File:Weird_Comics_01.JPGhttp://www.flickr.com/photos/x-ray_delta_one/3972988193/http://commons.wikimedia.org/wiki/File:Weird_Tales_January_1950.jpg ts dihttp://commons.wikimedia.org/wiki/File:Plan_nine_from_outer_space.jpghttp://www.flickr.com/photos/javyer/3545217741/http://www.flickr.com/photos/76074333@N00/318034222/http://commons.wikimedia.org/wiki/File:Dime_Mystery_Magazine_July_1934.jpghttp://www.flickr.com/photos/quinnanya/3802177022/ C re