FrOSCon - Fixing Legacy Code
By Benjamin Eberlei and Kore Nordmann.
What Is Legacy Code
- hard or impossible to fix errors or implement new features
- hard or impossible to implement automatic testing
What Is The Talk About
- common legacy code issues
- how to verify we do not breack everything
- refactoring legacy code
Issues With Legacy Code
- code issues
- inversion of control
- data structures
- application or business logic
- shared state
Code Issues
- code size
- high efferent coupling
- code duplication
- ...
- Use phpmd to locate size or complexity errors.
Efferent Coupling
- many outgoing coupling for one class in other classes
- can be located with pdepend
Inversion Of Control
- Missing abstractions
- Inline new
- Static calls
- Inline life cycle management (only value objects and exceptions should be newed inline)
Data Structure
- Missing abstractions
- Inline new
- Static calls
- Inline life cycle management (only value objects and exceptions should be newed inline)
Data Structure
- with arrays, you have a bad documentation
- use simple value objects (also known as dto) and they are not immutable
- split logic and try to avoid big models (seperation of concerns (roles/contextes) on model logic
- branch by abstraction
- introduce facade / proxy for old code
- call old code from facade / proxy implementation
- write new shiny facade / proxy implementation
- use new implementation
- delete old code
Application Or Business Logic
- mixed business logic (application logic) in large controllers is the most common and pressing issue with legacy code (fat controllers)
- try to use solutions like business requirement
- extract business logic like service layer pattern
- introduce (domain) events (in the same request)
- introduce message queues (not in the same request)
Shared State
- we know that global state is bad
- sessions are (often) cross-request global state in bash maps
- method execution pathes depending on current object state are horrible to track down
Testing Changes
- if your legacy code is hard to test, try to test it from the http protocoll point of view
- use behat as behaviour driven development (BDD)
- use mink with "goute", "sahi" or "zombie.js", "selenium", "selenium 2"
Extra
- do small checks when refactoring (good indicator are many, many commits)
- test your primary use cases (put the chaos in the cage)
- be bold (enough) and remove old code