September 27, 2004

The downside to Agile

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.

Posted by ivan at 2:37 PM Copyright (c) 2004-2007 Ivan Moore | Comments (4)

September 20, 2004

The Most Important Refactoring

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:

Delete unused code

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.

Delete unnecessary code

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.

Delete untested code

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.

Delete poor quality code

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).

Posted by ivan at 12:21 PM Copyright (c) 2004-2007 Ivan Moore | Comments (2)

September 19, 2004

Closures in Python (part 1)

Martin Fowler (obligitary Fowlbot namedrop) recently blogged about the power of closures in languages that support them. Here's a translation of Martin's Ruby code into Python. [Initial sentence and table structure copied from Joe Walnes] (not knowing how to get this to format correctly is my fault. I want to write a part 2, but that'll have to wait as I have other commitments (who are currently calling for me!) (now done)
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]
Posted by ivan at 9:22 AM Copyright (c) 2004-2007 Ivan Moore | Comments (2)