SlideShare a Scribd company logo
1 of 53
Download to read offline
Working Effectively with
 Legacy Perl Code
       Erik Rantapaa
      Frozen Perl 2010
What is Legacy Code?
What is Legacy Code?

Uses old/obsolete perl and modules
Not well factored / organically grown
Original developers gone
No one fully understands it
Uses outdated practices
Hard to modify without breaking it
Long new developer ramp-up time
No documentation (or wrong documentation)
No tests

On the other hand...
  Doing useful work - generating revenue
What is Legacy Code?


Michael Feathers - "Code without tests"

Ward Cunningham - "Accumulated technical debt"

Stuart Halloway - "Legacy is the degree to which code:
                    - fails to capture intent
                    - fails to communicate intent
                    - captures irrelevant detail (ceremony)"
Example Legacy App

 e-commerce application
 over 10 years old
 "rewritten" at least a couple of times
 worked on by lots of different developers
 > 1000 .pm files
 > 150 database tables, >2000 columns
 3 templating systems, 100's of template files
 used perl 5.8.0 until recently
 lots of old versions of CPAN modules (some customized)
 didn't compile with -cw until recently
 rm -rf not an option
Overview

 Unit Testing from a Perl perspective
 Working with the Code Base
 Instrumentation
 Future Directions
The Case for Testing


"... With tests we can change our code quickly and verifiably.
Without them we really don't know if our code is getting better
or worse. ..."

  - Michael Feathers
Cost of Fixing Defects
The Feedback Cycle
Testing vs. Debugging

Debugging:
  manual set-up (set breakpoints, step code, etc.)
  temporarily modifies code (printf debugging)
  manual verification
  pay for it every time

Testing:
   no source code modification
   automated set-up and verification
   pay once when you create the test
   reap the rewards every time you run it
Your Application
A Unit Test
Unit Testing

   isolates a small piece of functionality
   eliminates dependencies on other components through
   mocking / substitution
   ideally runs quickly
   provides automated verification

Benefits:
   safety net during refactoring
   after refactoring becomes a regression test
   speeds up the Edit-Compile-Run-Debug cycle
Impediments to Unit Testing

Main impediment: the way the application is glued together.

use LWP;
...
sub notify_user {
  my ($user, $message) = @_;
  ...
  my $ua = LWP::UserAgent->new;
  ...
  $ua->request(...);
}
Strongly Coupled Concerns

sub emit_html {




}
Dependency Breaking Techniques
Adapt Parameter                Parameterize Constructor
Break Out Method Object        Parameterize Method
Definition Completion          Primitive Parameter
Encapsulate Global             Pull Up Feature
References                     Push Down Dependency
Extract and Override Call      Replace Function with
Extract and Override Factory   Function Pointer
Method                         Replace Global Reference
Extract and Override Getter    with Getter
Extract Implementer            Subclass and Override
Extract Interface              Method
Introduce Instance Delegator   Supersede Instance Variable
Introduce Static Setter        Template Redefinition
Link Substitution              Text Redefinition
                               ...
Sprouting

   replace a block of code with a subroutine/method call (even
   for new code)

Benefits:

   simple and safe code transformation
   code block can be run independently
   permits the code to be redefined
Sprouting Example - DBI calls

Any DBI call is a good candidate for sprouting.

DBI call = an action on a business concept
Sprouting permits:
   testing of SQL syntax
   testing of query operation
   removal of interaction with the database
Dependency Injection

# use LWP;
...
sub notify_user {
  my ($user, $message, $ua ) = @_;
  ...
  # my $ua = LWP::UserAgent->new;
  ...
  $ua->request(...);
}

"Ask for - Don't create"
Preserving Signatures

use LWP;
...
sub notify_user {
  my ($user, $message, $ua ) = @_;
  ...
   $ua ||= LWP::UserAgent->new;
  ...
  $ua->request(...);
}
Perl-Specific Mocking/Isolation
         Techniques
Replacing a Package

 alter @INC to load alternate code

 alter %INC to omit unneeded code
Replacing Subroutines

Monkey patch the symbol table:

  no warnings 'redefine';
  *Product::saveToDatabase = sub { $_[0]->{saved} = 1 };

  *CORE::GLOBAL::time = sub { ... }

Create accessors for package lexicals
Modifying Object Instances

Re-bless to a subclass:

package MockTemplateEngine;
our @ISA = qw(RealTemplateEngine);
sub process {
  ... new behavior ...
}
...
$template = RealTemplateEngine->new(...);
bless $template, 'MockTemplateEngine';
Use the Stack

Define behavior based on caller().

Use in conjunction with monkey patching subs.
Exploiting Perl's Dynamicism

  Use the dynamic capabilities of Perl to help you isolate code
  and create mock objects.
  Not the cleanest techniques, but they can greatly simplify
  getting dependency-laden code under test.
Manual Testing

 Not always bad
 Some times it's the best option:
    automated verification is difficult / impossible
    automated test to costly to create
Manual Testing Example
Using an Wrapper Layer
Real-World Experience

 Writing the first test is very difficult
 It gets easier!
 Biggest win: automated verification
 Next biggest win: efficient tests
 Manual testing is ok (save what you did!)
More Real-World Experience

 Isolating code will help you understand the dependency
 structure of your application
 Let your tests guide refactoring
 Testable code ~ clean code ~ modular code
Working with the Code Base
Source Control

Get everthing under source control:
   perl itself
   all CPAN modules
   shared libraries
   Apache, mod_perl, etc.
Reliable Builds

  Automate building and deployment
  Break dependencies on absolute paths, port numbers
  Enable multiple deployments to co-exist on the same
  machine
Logging

   make logs easy to access
   import logs into a database
   automate a daily synopsis

SELECT count(*), substr(message, 0, 50) as "key"
FROM log_message
WHERE log_time BETWEEN ... AND ...
GROUP BY key
ORDER BY count(*) DESC;
Wrappers

Create deployment-specific wrappers for perl and perldoc:

#!/bin/sh
PATH=...
PERL5LIB=...
LD_LIBRARY_PATH=...
ORACLE_HOME=...
...

/path/to/app/perl "$@"
Create Tools

$ compile-check Formatter.pm

Runs app-perl -cw -MApp::PaymentService::Email::Formatter

Full module name determined from current working directory.
Automated Testing

 Continuous Integration
 Smoke Tests
 Regression Tests
Instrumentation
Devel::NYTProf

Pros:
   full instrumentation of your code
   timing statistics on a per-line basis
   call-graphs, heat map
   useful for

Cons:
  big performance hit (not suitable for production)
  you need to drive it

Also see Aspect::Library::NYTProf for targeted profiling
Devel::Leak::Object

   Original purpose: find leakage of objects due to cyclic
   references

Modifications:

   Record how (the stack) objects get created
   Count the number of each type of object created
   Determine where objects of a certain class are created
   Robust facility to instrument bless and DESTROY.
dtrace


Pros:
   instrument events across the entire system
   runs at nearly full speed - usable in production

Cons:
  only available for Mac OS and Solaris
  perl probes still under development
Future Directions

More static analysis
  manually added soft type assertions
  more help in editors/IDEs
  more refactoring tools
  better compilation diagnostics
  catch mistyped subroutine names
  catch errors in calling methods/subs
  catch other type errors
Future Directions

More dynamic instrumention
  usable in production
  low performance hit
  mainly interested in:
      the call chain (stack)
      types of variables / subroutine parameters / return
      values
  dtrace? modified perl interpreter?
Future Directions

Automated Instrumentation
   build a database of the runtime behavior of your program
   collect design details not expressed in the source
   mine the database to infer internal rules:
       call graphs
       signature of subroutines
   use rules to aid static analysis
A Refactoring Problem

Want to change $self->{PRICE} to $self->getPrice:

package Product;

sub foo {
  my ($self, ...) = @_;
  ...
  ... $self->{PRICE} ...
  ...
}
A Refactoring Problem

Within package Product → easy!

package Product;

sub getPrice { ... }

sub foo {
  my ($self, ...) = @_;
  ...
  ... $self->getPrice ... # know type of $self
  ...
}
A Refactoring Problem

Can we change this?

package SomeOtherClass;

sub bar {
  ...
  ... $product->{PRICE} ...
}

Need to know if $product is from package Product (or a
subclass)
A Refactoring Problem

Look at context for help.

package SomeOtherClass;

sub bar {
  ...
  my $product = Product->new(...);
  ...
  ... $product->{PRICE} ...
}
A Refactoring Problem

Now what?

package SomeOtherClass;

sub bar {
  my ($self, $product, ...) = @_;
  ...
  ... $product->{PRICE} ...
}

Need to figure out where SomeOtherClass::bar() gets called.

Instrumentation DB → just look up the answer
References

 "Working Effectively with Legacy Code" - Michael Feathers
 "Clean Code Talks" - googletechtalks channel on YouTube
 Writing Testable Code - Misko Hevery http://misko.hevery.
 com/code_reviewers_guide
 "Clean Code: A Handbook of Agile Software
 Craftsmanship," Robert C. Martin, ed.
Thanks!

Feedback, suggestions, experiences?

                  erantapaa@gmail.com

More Related Content

What's hot

Keep your repo clean
Keep your repo cleanKeep your repo clean
Keep your repo cleanHector Canto
 
Integration testing with spring @snow one
Integration testing with spring @snow oneIntegration testing with spring @snow one
Integration testing with spring @snow oneVictor Rentea
 
How to write maintainable code without tests
How to write maintainable code without testsHow to write maintainable code without tests
How to write maintainable code without testsJuti Noppornpitak
 
Integration testing with spring @JAX Mainz
Integration testing with spring @JAX MainzIntegration testing with spring @JAX Mainz
Integration testing with spring @JAX MainzVictor Rentea
 
Can you upgrade to Puppet 4.x?
Can you upgrade to Puppet 4.x?Can you upgrade to Puppet 4.x?
Can you upgrade to Puppet 4.x?Martin Alfke
 
Testing untestable code - phpconpl11
Testing untestable code - phpconpl11Testing untestable code - phpconpl11
Testing untestable code - phpconpl11Stephan Hochdörfer
 
Object Oriented Design Patterns for PHP
Object Oriented Design Patterns for PHPObject Oriented Design Patterns for PHP
Object Oriented Design Patterns for PHPRobertGonzalez
 
Coding Best Practices
Coding Best PracticesCoding Best Practices
Coding Best Practicesmh_azad
 
Testing the frontend
Testing the frontendTesting the frontend
Testing the frontendHeiko Hardt
 
Puppet modules: An Holistic Approach
Puppet modules: An Holistic ApproachPuppet modules: An Holistic Approach
Puppet modules: An Holistic ApproachAlessandro Franceschi
 
Js fwdays unit tesing javascript(by Anna Khabibullina)
Js fwdays unit tesing javascript(by Anna Khabibullina)Js fwdays unit tesing javascript(by Anna Khabibullina)
Js fwdays unit tesing javascript(by Anna Khabibullina)Anna Khabibullina
 
JS Frameworks Day April,26 of 2014
JS Frameworks Day April,26 of 2014JS Frameworks Day April,26 of 2014
JS Frameworks Day April,26 of 2014DA-14
 
Learning puppet chapter 2
Learning puppet chapter 2Learning puppet chapter 2
Learning puppet chapter 2Vishal Biyani
 
The Art of Unit Testing - Towards a Testable Design
The Art of Unit Testing - Towards a Testable DesignThe Art of Unit Testing - Towards a Testable Design
The Art of Unit Testing - Towards a Testable DesignVictor Rentea
 
Testing untestable code - phpday
Testing untestable code - phpdayTesting untestable code - phpday
Testing untestable code - phpdayStephan Hochdörfer
 
An Introduction to Java Compiler and Runtime
An Introduction to Java Compiler and RuntimeAn Introduction to Java Compiler and Runtime
An Introduction to Java Compiler and RuntimeOmar Bashir
 

What's hot (20)

Keep your repo clean
Keep your repo cleanKeep your repo clean
Keep your repo clean
 
Integration testing with spring @snow one
Integration testing with spring @snow oneIntegration testing with spring @snow one
Integration testing with spring @snow one
 
How to write maintainable code without tests
How to write maintainable code without testsHow to write maintainable code without tests
How to write maintainable code without tests
 
Integration testing with spring @JAX Mainz
Integration testing with spring @JAX MainzIntegration testing with spring @JAX Mainz
Integration testing with spring @JAX Mainz
 
Can you upgrade to Puppet 4.x?
Can you upgrade to Puppet 4.x?Can you upgrade to Puppet 4.x?
Can you upgrade to Puppet 4.x?
 
Testing untestable code - phpconpl11
Testing untestable code - phpconpl11Testing untestable code - phpconpl11
Testing untestable code - phpconpl11
 
Object Oriented Design Patterns for PHP
Object Oriented Design Patterns for PHPObject Oriented Design Patterns for PHP
Object Oriented Design Patterns for PHP
 
Coding Best Practices
Coding Best PracticesCoding Best Practices
Coding Best Practices
 
Testing the frontend
Testing the frontendTesting the frontend
Testing the frontend
 
Puppet modules: An Holistic Approach
Puppet modules: An Holistic ApproachPuppet modules: An Holistic Approach
Puppet modules: An Holistic Approach
 
Js fwdays unit tesing javascript(by Anna Khabibullina)
Js fwdays unit tesing javascript(by Anna Khabibullina)Js fwdays unit tesing javascript(by Anna Khabibullina)
Js fwdays unit tesing javascript(by Anna Khabibullina)
 
JS Frameworks Day April,26 of 2014
JS Frameworks Day April,26 of 2014JS Frameworks Day April,26 of 2014
JS Frameworks Day April,26 of 2014
 
Learning puppet chapter 2
Learning puppet chapter 2Learning puppet chapter 2
Learning puppet chapter 2
 
The Art of Unit Testing - Towards a Testable Design
The Art of Unit Testing - Towards a Testable DesignThe Art of Unit Testing - Towards a Testable Design
The Art of Unit Testing - Towards a Testable Design
 
Testing untestable code - phpday
Testing untestable code - phpdayTesting untestable code - phpday
Testing untestable code - phpday
 
An Introduction to Java Compiler and Runtime
An Introduction to Java Compiler and RuntimeAn Introduction to Java Compiler and Runtime
An Introduction to Java Compiler and Runtime
 
Complete Java Course
Complete Java CourseComplete Java Course
Complete Java Course
 
Cursus phpunit
Cursus phpunitCursus phpunit
Cursus phpunit
 
TDD, BDD, RSpec
TDD, BDD, RSpecTDD, BDD, RSpec
TDD, BDD, RSpec
 
PHPUnit
PHPUnitPHPUnit
PHPUnit
 

Similar to Working Effectively With Legacy Perl Code

TDD And Refactoring
TDD And RefactoringTDD And Refactoring
TDD And RefactoringNaresh Jain
 
Bring the fun back to java
Bring the fun back to javaBring the fun back to java
Bring the fun back to javaciklum_ods
 
Linq To The Enterprise
Linq To The EnterpriseLinq To The Enterprise
Linq To The EnterpriseDaniel Egan
 
Practical catalyst
Practical catalystPractical catalyst
Practical catalystdwm042
 
Asp.net MVC - Course 2
Asp.net MVC - Course 2Asp.net MVC - Course 2
Asp.net MVC - Course 2erdemergin
 
Joomla! Day Chicago 2011 Presentation - Steven Pignataro
Joomla! Day Chicago 2011 Presentation - Steven PignataroJoomla! Day Chicago 2011 Presentation - Steven Pignataro
Joomla! Day Chicago 2011 Presentation - Steven PignataroSteven Pignataro
 
Lecture: Refactoring
Lecture: RefactoringLecture: Refactoring
Lecture: RefactoringMarcus Denker
 
Linq 1224887336792847 9
Linq 1224887336792847 9Linq 1224887336792847 9
Linq 1224887336792847 9google
 
Breaking Dependencies Legacy Code - Cork Software Crafters - September 2019
Breaking Dependencies Legacy Code -  Cork Software Crafters - September 2019Breaking Dependencies Legacy Code -  Cork Software Crafters - September 2019
Breaking Dependencies Legacy Code - Cork Software Crafters - September 2019Paulo Clavijo
 
Stopping the Rot - Putting Legacy C++ Under Test
Stopping the Rot - Putting Legacy C++ Under TestStopping the Rot - Putting Legacy C++ Under Test
Stopping the Rot - Putting Legacy C++ Under TestSeb Rose
 
Drupal Best Practices
Drupal Best PracticesDrupal Best Practices
Drupal Best Practicesmanugoel2003
 
Measuring Your Code
Measuring Your CodeMeasuring Your Code
Measuring Your CodeNate Abele
 
Measuring Your Code 2.0
Measuring Your Code 2.0Measuring Your Code 2.0
Measuring Your Code 2.0Nate Abele
 
Introduction to PowerShell
Introduction to PowerShellIntroduction to PowerShell
Introduction to PowerShellBoulos Dib
 
Patterns in Python
Patterns in PythonPatterns in Python
Patterns in Pythondn
 
2011-02-03 LA RubyConf Rails3 TDD Workshop
2011-02-03 LA RubyConf Rails3 TDD Workshop2011-02-03 LA RubyConf Rails3 TDD Workshop
2011-02-03 LA RubyConf Rails3 TDD WorkshopWolfram Arnold
 
Advanced driver debugging (13005399) copy
Advanced driver debugging (13005399)   copyAdvanced driver debugging (13005399)   copy
Advanced driver debugging (13005399) copyBurlacu Sergiu
 
Understanding Framework Architecture using Eclipse
Understanding Framework Architecture using EclipseUnderstanding Framework Architecture using Eclipse
Understanding Framework Architecture using Eclipseanshunjain
 

Similar to Working Effectively With Legacy Perl Code (20)

TDD And Refactoring
TDD And RefactoringTDD And Refactoring
TDD And Refactoring
 
Bring the fun back to java
Bring the fun back to javaBring the fun back to java
Bring the fun back to java
 
Linq To The Enterprise
Linq To The EnterpriseLinq To The Enterprise
Linq To The Enterprise
 
Practical catalyst
Practical catalystPractical catalyst
Practical catalyst
 
Asp.net MVC - Course 2
Asp.net MVC - Course 2Asp.net MVC - Course 2
Asp.net MVC - Course 2
 
Joomla! Day Chicago 2011 Presentation - Steven Pignataro
Joomla! Day Chicago 2011 Presentation - Steven PignataroJoomla! Day Chicago 2011 Presentation - Steven Pignataro
Joomla! Day Chicago 2011 Presentation - Steven Pignataro
 
Lecture: Refactoring
Lecture: RefactoringLecture: Refactoring
Lecture: Refactoring
 
Linq 1224887336792847 9
Linq 1224887336792847 9Linq 1224887336792847 9
Linq 1224887336792847 9
 
Breaking Dependencies Legacy Code - Cork Software Crafters - September 2019
Breaking Dependencies Legacy Code -  Cork Software Crafters - September 2019Breaking Dependencies Legacy Code -  Cork Software Crafters - September 2019
Breaking Dependencies Legacy Code - Cork Software Crafters - September 2019
 
Java Basics
Java BasicsJava Basics
Java Basics
 
Stopping the Rot - Putting Legacy C++ Under Test
Stopping the Rot - Putting Legacy C++ Under TestStopping the Rot - Putting Legacy C++ Under Test
Stopping the Rot - Putting Legacy C++ Under Test
 
Drupal Best Practices
Drupal Best PracticesDrupal Best Practices
Drupal Best Practices
 
Measuring Your Code
Measuring Your CodeMeasuring Your Code
Measuring Your Code
 
Measuring Your Code 2.0
Measuring Your Code 2.0Measuring Your Code 2.0
Measuring Your Code 2.0
 
Best practices tekx
Best practices tekxBest practices tekx
Best practices tekx
 
Introduction to PowerShell
Introduction to PowerShellIntroduction to PowerShell
Introduction to PowerShell
 
Patterns in Python
Patterns in PythonPatterns in Python
Patterns in Python
 
2011-02-03 LA RubyConf Rails3 TDD Workshop
2011-02-03 LA RubyConf Rails3 TDD Workshop2011-02-03 LA RubyConf Rails3 TDD Workshop
2011-02-03 LA RubyConf Rails3 TDD Workshop
 
Advanced driver debugging (13005399) copy
Advanced driver debugging (13005399)   copyAdvanced driver debugging (13005399)   copy
Advanced driver debugging (13005399) copy
 
Understanding Framework Architecture using Eclipse
Understanding Framework Architecture using EclipseUnderstanding Framework Architecture using Eclipse
Understanding Framework Architecture using Eclipse
 

Recently uploaded

08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 

Recently uploaded (20)

08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
The transition to renewables in India.pdf
The transition to renewables in India.pdfThe transition to renewables in India.pdf
The transition to renewables in India.pdf
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 

Working Effectively With Legacy Perl Code

  • 1. Working Effectively with Legacy Perl Code Erik Rantapaa Frozen Perl 2010
  • 3. What is Legacy Code? Uses old/obsolete perl and modules Not well factored / organically grown Original developers gone No one fully understands it Uses outdated practices Hard to modify without breaking it Long new developer ramp-up time No documentation (or wrong documentation) No tests On the other hand... Doing useful work - generating revenue
  • 4. What is Legacy Code? Michael Feathers - "Code without tests" Ward Cunningham - "Accumulated technical debt" Stuart Halloway - "Legacy is the degree to which code: - fails to capture intent - fails to communicate intent - captures irrelevant detail (ceremony)"
  • 5. Example Legacy App e-commerce application over 10 years old "rewritten" at least a couple of times worked on by lots of different developers > 1000 .pm files > 150 database tables, >2000 columns 3 templating systems, 100's of template files used perl 5.8.0 until recently lots of old versions of CPAN modules (some customized) didn't compile with -cw until recently rm -rf not an option
  • 6. Overview Unit Testing from a Perl perspective Working with the Code Base Instrumentation Future Directions
  • 7.
  • 8. The Case for Testing "... With tests we can change our code quickly and verifiably. Without them we really don't know if our code is getting better or worse. ..." - Michael Feathers
  • 9. Cost of Fixing Defects
  • 11. Testing vs. Debugging Debugging: manual set-up (set breakpoints, step code, etc.) temporarily modifies code (printf debugging) manual verification pay for it every time Testing: no source code modification automated set-up and verification pay once when you create the test reap the rewards every time you run it
  • 14. Unit Testing isolates a small piece of functionality eliminates dependencies on other components through mocking / substitution ideally runs quickly provides automated verification Benefits: safety net during refactoring after refactoring becomes a regression test speeds up the Edit-Compile-Run-Debug cycle
  • 15. Impediments to Unit Testing Main impediment: the way the application is glued together. use LWP; ... sub notify_user { my ($user, $message) = @_; ... my $ua = LWP::UserAgent->new; ... $ua->request(...); }
  • 17. Dependency Breaking Techniques Adapt Parameter Parameterize Constructor Break Out Method Object Parameterize Method Definition Completion Primitive Parameter Encapsulate Global Pull Up Feature References Push Down Dependency Extract and Override Call Replace Function with Extract and Override Factory Function Pointer Method Replace Global Reference Extract and Override Getter with Getter Extract Implementer Subclass and Override Extract Interface Method Introduce Instance Delegator Supersede Instance Variable Introduce Static Setter Template Redefinition Link Substitution Text Redefinition ...
  • 18. Sprouting replace a block of code with a subroutine/method call (even for new code) Benefits: simple and safe code transformation code block can be run independently permits the code to be redefined
  • 19. Sprouting Example - DBI calls Any DBI call is a good candidate for sprouting. DBI call = an action on a business concept Sprouting permits: testing of SQL syntax testing of query operation removal of interaction with the database
  • 20. Dependency Injection # use LWP; ... sub notify_user { my ($user, $message, $ua ) = @_; ... # my $ua = LWP::UserAgent->new; ... $ua->request(...); } "Ask for - Don't create"
  • 21. Preserving Signatures use LWP; ... sub notify_user { my ($user, $message, $ua ) = @_; ... $ua ||= LWP::UserAgent->new; ... $ua->request(...); }
  • 23. Replacing a Package alter @INC to load alternate code alter %INC to omit unneeded code
  • 24. Replacing Subroutines Monkey patch the symbol table: no warnings 'redefine'; *Product::saveToDatabase = sub { $_[0]->{saved} = 1 }; *CORE::GLOBAL::time = sub { ... } Create accessors for package lexicals
  • 25. Modifying Object Instances Re-bless to a subclass: package MockTemplateEngine; our @ISA = qw(RealTemplateEngine); sub process { ... new behavior ... } ... $template = RealTemplateEngine->new(...); bless $template, 'MockTemplateEngine';
  • 26. Use the Stack Define behavior based on caller(). Use in conjunction with monkey patching subs.
  • 27. Exploiting Perl's Dynamicism Use the dynamic capabilities of Perl to help you isolate code and create mock objects. Not the cleanest techniques, but they can greatly simplify getting dependency-laden code under test.
  • 28. Manual Testing Not always bad Some times it's the best option: automated verification is difficult / impossible automated test to costly to create
  • 31. Real-World Experience Writing the first test is very difficult It gets easier! Biggest win: automated verification Next biggest win: efficient tests Manual testing is ok (save what you did!)
  • 32. More Real-World Experience Isolating code will help you understand the dependency structure of your application Let your tests guide refactoring Testable code ~ clean code ~ modular code
  • 33. Working with the Code Base
  • 34. Source Control Get everthing under source control: perl itself all CPAN modules shared libraries Apache, mod_perl, etc.
  • 35. Reliable Builds Automate building and deployment Break dependencies on absolute paths, port numbers Enable multiple deployments to co-exist on the same machine
  • 36. Logging make logs easy to access import logs into a database automate a daily synopsis SELECT count(*), substr(message, 0, 50) as "key" FROM log_message WHERE log_time BETWEEN ... AND ... GROUP BY key ORDER BY count(*) DESC;
  • 37. Wrappers Create deployment-specific wrappers for perl and perldoc: #!/bin/sh PATH=... PERL5LIB=... LD_LIBRARY_PATH=... ORACLE_HOME=... ... /path/to/app/perl "$@"
  • 38. Create Tools $ compile-check Formatter.pm Runs app-perl -cw -MApp::PaymentService::Email::Formatter Full module name determined from current working directory.
  • 39. Automated Testing Continuous Integration Smoke Tests Regression Tests
  • 41. Devel::NYTProf Pros: full instrumentation of your code timing statistics on a per-line basis call-graphs, heat map useful for Cons: big performance hit (not suitable for production) you need to drive it Also see Aspect::Library::NYTProf for targeted profiling
  • 42. Devel::Leak::Object Original purpose: find leakage of objects due to cyclic references Modifications: Record how (the stack) objects get created Count the number of each type of object created Determine where objects of a certain class are created Robust facility to instrument bless and DESTROY.
  • 43. dtrace Pros: instrument events across the entire system runs at nearly full speed - usable in production Cons: only available for Mac OS and Solaris perl probes still under development
  • 44. Future Directions More static analysis manually added soft type assertions more help in editors/IDEs more refactoring tools better compilation diagnostics catch mistyped subroutine names catch errors in calling methods/subs catch other type errors
  • 45. Future Directions More dynamic instrumention usable in production low performance hit mainly interested in: the call chain (stack) types of variables / subroutine parameters / return values dtrace? modified perl interpreter?
  • 46. Future Directions Automated Instrumentation build a database of the runtime behavior of your program collect design details not expressed in the source mine the database to infer internal rules: call graphs signature of subroutines use rules to aid static analysis
  • 47. A Refactoring Problem Want to change $self->{PRICE} to $self->getPrice: package Product; sub foo { my ($self, ...) = @_; ... ... $self->{PRICE} ... ... }
  • 48. A Refactoring Problem Within package Product → easy! package Product; sub getPrice { ... } sub foo { my ($self, ...) = @_; ... ... $self->getPrice ... # know type of $self ... }
  • 49. A Refactoring Problem Can we change this? package SomeOtherClass; sub bar { ... ... $product->{PRICE} ... } Need to know if $product is from package Product (or a subclass)
  • 50. A Refactoring Problem Look at context for help. package SomeOtherClass; sub bar { ... my $product = Product->new(...); ... ... $product->{PRICE} ... }
  • 51. A Refactoring Problem Now what? package SomeOtherClass; sub bar { my ($self, $product, ...) = @_; ... ... $product->{PRICE} ... } Need to figure out where SomeOtherClass::bar() gets called. Instrumentation DB → just look up the answer
  • 52. References "Working Effectively with Legacy Code" - Michael Feathers "Clean Code Talks" - googletechtalks channel on YouTube Writing Testable Code - Misko Hevery http://misko.hevery. com/code_reviewers_guide "Clean Code: A Handbook of Agile Software Craftsmanship," Robert C. Martin, ed.