Create your own awesome maps

Even on the go

with our free apps for iPhone, iPad and Android

Get Started

Already have an account?
Log In

Working Effectively With Legacy Code by Mind Map: Working Effectively With Legacy
Code
5.0 stars - 2 reviews range from 0 to 5

Working Effectively With Legacy Code

Adding a feature

Test Driven Development

Write a failing test

Get it to compile

Make it pass

Remove Duplication, Refactor

Repeat

Legacy Addition, Get the class under test

Inheritance

Can be useful but use carefully, long term could cause confusion & need refactoring, Liskov substitution principle, A Rectangle != Square, Objects of subclasses should be substitutable for their parent class

Avoid overwriting concrete classes, if so, try to call super

Testing takes too long?

When we don't test it takes too long

Compile Time, Entire project compilation

Deploy Time

Manual Verification, Multiple Times

Testing

Instantaneous feedback

Helps keep you in context & focused

Future guarantee of the feature with no additional work afterward

Interfaces require less code to need compiling

so utilize them

Test Code

Not production code

Mock objects can break encapsulation if it makes testing easier

Try passing null, Worst case... exception, Maybe implement Null Object Pattern, This can be production code

Getting Classes into Test Harness

Extract Interface

Mock out new interfaces

Hidden dependencies

Parameterized constructor

Supersede Instance Variable, Worst Case Scenario, Public Setter

Global Dependencies

Singletons, Relax it, Introduce static setter, Set Testing Instance Method, resetForTesting(), set to null, Not Production Code

Subclass

when difficult to construct, dependencies can be overwritten by a subclass, used as an interface to test desirable testable code

Get Method into Test Harness

Private method

test appropriate public methods, they will touch private methods, no need to test the private ones specifically

Make it public, if bad, fix class, single responsibility pricnciple

Make it protected & subclass with a public method, java package level scope to circumvent the subclass

Reflection, Try to NEVER do this, sets bad presedence, can mask how bad a class is

Finding Bugs

Tests prevent future bugs

Once reducing the area a bug is in

write, Characterization Tests, Tests what the code does, not supposed to do, then identify & fix bugs w/ this test, not all of the characterizations have the bug, Ensures you are not breaking current working functionality, even if you don't fully understand what that is, you have tests for it, Steps, Use piece of code in test hardness, Write a failing assertion, Let the failure tell you what the behavior is, Change the test to expect that behavior, Repeat

Legacy

Dilema

When we change code - have tests, to add tests, I need to change code

Definition

Code Without Tests

Unit Tests

FAST!

Localize problems

quickly

NOT

touch database

Communicate across network

touch file system

require special environment config

Integration tests

Refactoring

Definition

Changes made to structure w/out changing behavior to make it easier to understand

Initially

Start Ugly

Surgery analogy, Scar left after, BUT, Everything beneanth it can get better

Legacy Code Change Algorithm

Identify Change Points

Find Test Points

Break Dependencies, interfaces

Write Tests

Make Changes & Refactor

Adding Tests

Seam

Definition, Alter behavior in program without editing in that place, Test & Prod code IS THE SAME CODE, enabling point, spot to enable seam

Use indirect / hard seams to change legacy code very little so you can get tests in place, Then refactor

Types, Object Seam, Replace / Overwrite Object, Extending, Pre-Processing Seam, Compiler arguments to overwrite function definitions, C/C++, Not Java, Link Seam, Overwrite 'Linked'" / imported objects, Classpath manipulation, Java

Change Definition

Does it change behavior??

Functionality

New Functionality

Structure

Resource Usage

Adding Behavior

Sprout Method

Put behavior in a new, distinct, testable method

Test this method even if/though caller is untested

Worst Case, Static method w/ arguments of intended class, This is a scar, Over time it will find a home

Sprout Class

When difficult to instantiate a class for testing

New class to do new behavior

Would NOT receive "Caller Class" (untested class where code was desired to be put in the first place), Caller Class = Source Class

Wrap Method

Wrap source method with simpler delegating method, Or reuse method name & abstract original code

Decouple functionality from being shoved into the same method

Prevents temporal coupling

Wrap Class

Decorator Pattern