A client recently emailed (quote included here with his permission):
> It's funny but I think I can only work on Agile/XP projects now. I don't think I can "go back" to the old way. Thanks for the brain washing......
This got me thinking. I feel the same, and have done since soon after I got into XP in 1999. I've heard lots of people say the same over the last few years.
This causes a problem. Once converted to Agile/XP, you'll be dissatisfied if you have to work on a non-Agile project. Currently only a minority of jobs are working on Agile/XP projects, so if you want to be happy in your work your job opportunities become more limited once you've worked on an Agile/XP project.
Fortunately, Agile/XP projects are becoming more common now, so the situation for converts is improving.
Through careful selection of employer, and plenty of good fortune, I haven't had to "go back" to the old way and hope I never do.
Martin Fowler missed out the Most Important Refactoring in his book - delete.
Before applying any of the refactorings in Martin Fowler's catalog, consider one of the delete refactorings. Sometimes, you will find that rather than renaming some badly named method (for example) you can just delete it, which is a much better refactoring.
One of the goals of refactoring is to reduce code entropy - and delete is the best refactoring for this. Less code means: less code to understand, less code to change when you make a change to something it depends on, less code to read through to find what you are looking for, shorter build times, shorter checkout times, shorter search times.
Mike Hill and I have put together a preliminary catalog:
You have code that isn't executed by the deployed system
Examples are: as-yet unrequested functionality, or functionality that is no longer required. Don't delete test or build code related to the deployed system.
You have code that is executed by the deployed system but does not effect the desired functionality of the system.
Examples are: EJBs for systems that don't need them, properties of objects that are set but never read.
You have code that is executed by the deployed system but has not been tested.
If the code hasn't been tested then you don't know what it does, so it is a risk to include it in the deployed system.
You have code that is difficult to maintain.
For example, code that no one understands, code that requires the same changes in multiple places for fixing a bug. Sometimes, you are better deleting it and starting again - but be careful not to jump to this solution too soon, it's often possible to refactor poor quality code into a usable state. (To be fair to Martin Fowler, I think he does mention this one).
| Ruby | Python (Direct translation, using "lambda") |
def managers(emps)
return emps.select {|e| e.isManager}
end
|
def managers(emps):
return filter(lambda e: e.isManager, emps)
|
def highPaid(emps)
threshold = 150
return emps.select {|e| e.salary > threshold}
end
|
def highPaid(emps):
threshold = 150
return filter(lambda e: e.salary > threshold, emps)
|
def paidMore(amount)
return Proc.new {|e| e.salary > amount}
end
|
def paidMore(amount):
return lambda e: e.salary > amount
|
highPaid = paidMore(150) john = Employee.new john.salary = 200 print highPaid.call(john) |
highPaid = paidMore(150) john = Employee() john.salary = 200 print highPaid(john) |
| Ruby | Python (Idiomatic translation, using "list comprehensions") |
def managers(emps)
return emps.select {|e| e.isManager}
end
|
def managers(emps):
return [e for e in emps if e.isManager]
|
def highPaid(emps)
threshold = 150
return emps.select {|e| e.salary > threshold}
end
|
def highPaid(emps):
threshold = 150
return [e for e in emps if e.salary > threshold]
|