Python Rocks! and other rants
Weblog of Kent S Johnson

2008-04-16 15:02:11

Getting started with Agile Development

An overview of agile development as I practice it.

Fundamental principles

You aren't going to need it (YAGNI)

Today, write the code needed to solve today's requirements. Leave tomorrow's requirements until tomorrow.

I am not very good at predicting the future. I may think I know what my customer is going to want next month; my customer may think he knows. Frequently we will be wrong. All of these are common:

  • Our understanding of the problem area may change, leading to new, changed or dropped requirements
  • Our understanding of the solution may change. This happens frequently; there is nothing like working code to help a customer understand what he doesn't want :-)
  • An unforseen requirement may come up that is more important
  • We might just change our minds

Designing and coding for today keeps the design simple. Designing and coding for tomorrow costs

  • development time
  • test time
  • maintenance time
  • increased code size and complexity

for no current benefit. Don't do it!

Exceptions: If you are a domain expert and you have written similar programs before, you might be pretty darn sure you are going to need something. Go ahead and include it, I won't tell!

See also: http://c2.com/cgi/wiki?YouArentGonnaNeedIt

The simplest thing that could possibly work

So, what should you do today, to meet today's requirements? Do the simplest thing that could possibly work. Keep the design and code simple. If you are not sure if something will work, try it and see. Maybe it is too simple but you won't know until you try it.

How do you know if you have done the simplest thing? Simple code

  1. Runs all the tests.
  2. Expresses every idea that we need to express.
  3. Says everything once and only once.
  4. Has no superfluous parts.

See also: Simplicity Rules

Practices

Test-Driven Development

Write unit tests as you write code.

There are several benefits to writing unit tests:

  • you have confidence that the code works
  • you can change the code and have confidence that it still works
  • you design from the point of view of a client
  • your code is loosely coupled and more reusable

Write the tests as you write the code. It is very difficult to retrofit tests to existing code.

  • When writing tests there are occasional rough spots where some scaffolding must be created. For existing code this can be a daunting task. If you write tests with code, your scaffolding will develop as needed.
  • Untested code is often monolithic and tightly coupled making it difficult to test. Writing tests forces the code to be loosely coupled and testable.

You think you don't have time to write tests? I don't have time not to! Unit testing helps me go faster.

Unit testing is for bug-fixes, too! Before you fix a bug, write a test that exposes the bug. Then fix the bug to make the test pass.

One benefit of unit testing is not realized until you have to make a change to code that has tests. Unit testing is an enabling technology. It lets you refactor with confidence.

See also: Test Driven Development

Refactor mercilessly

Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure. -- Martin Fowler

Many mature software projects calcify. They have been built and rebuilt and patched and shoehorned to death. The developers don't fully understand the code. There are sections of code that they know are badly in need of a rewrite, but they don't dare touch them because they have no tests or clear specifications. Progress is slow, bugs are plentiful. Making changes is like running with your shoelaces tied together - you keep falling down.

What is the alternative? Keep the code clean, always. This is a key aspect of agile development and implicit in the simplicity rules above.

The current code should always reflect the simplest thing that could possibly work. It should always be designed to meet the current requirements. As requirements change and features are added, these goals are easily broken. Refactor to bring the design back in line with the requirements.

Include refactoring in your work cycle. Periodically step back and evaluate what you have done. If the design is lacking, if there is duplication, if the code is not expressive of what it does, then it is time to refactor.

You can also refactor when you start making a change. If you find you have to make a change, and you don't see an easy way to make the change, then refactor until the change is easy.

Martin Fowler's book Refactoring: Improving the Design of Existing Code is the classic introduction to refactoring. It includes an extended example, a catalog of refactorings, and a chapter on Code Smells.

See also: Refactor mercilessly

Deliver value to the customer

The goal of software development is ultimately to deliver value to the customer - the person who will use the software.

Focus on the highest value tasks first. Use your to do list as a priority queue. Pick the highest value task and do it. When you finish, pick the new highest value task and do that. It's helpful, but not necessary, to have a rough order for the top of the list. All you really need is to know what is at the top. Expect the order to change with time.

Release incrementally so the customer receives the value and can provide feedback. Frequent releases and customer feedback ensure that you are on track and providing something useful. Your goal should be to delight your customer!

 
© Kent S Johnson Creative Commons License

Comments about life, the universe and Python, from the imagination of Kent S Johnson.

kentsjohnson.com

Weblog home

All By Date

All By Category

Essays

XML-Image

BlogRoll