In recent years within the object oriented and agile community, several approaches to software design and development have materialized and are in use by professional software developers. Test-Driven Development (TDD), Domain-Driven Design (DDD), Behavior-Driven Design (BDD) and Feature-Driven Design (FDD) are some of the more well known approaches. While these philosophies all imbibe the classic agile principles of an incremental and iterative mindset to software development, they subtly differ from each other.
Each approach focuses on a different aspect. This articles aims to highlight the subtle differences between the approaches and hopefully expose that knowledge so the readers can leverage key aspects in their own development.
Test-Driven Development is probably the most well known development approach in the agile community today. TDD took root in the Xtreme Programming space and was notably brought into the public arena by Kent Beck's book, "Test-driven Development by Example". The focus of TDD is to write tests before you write writing code, but in an iterative manner. Robert C Martin drives home the point when he emphasizes the three Laws of TDD :
- You are not allowed to write any production code unless it is to make a failing unit test pass.
- You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
- You are not allowed to write any more production code than is sufficient to pass the one failing unit test.
These three points nicely define the rules, but they lack the intent of following these rules. The goal behind TDD is not just to write tests before so that you 1) don't forget to later or 2) run out of time or 3) you become lazy and just let it go or 4) that you are pressured to not write tests by external forces who don't see the benefit. These problems are addressed by using TDD but they are not the focus of TDD. Test-Driven Development is more about the design of the code and the rhythm of the developer creating code.
TDD focus is to think about what a specific module was created to do and how its clients expect to interact with it. The approach with TDD is aimed to get the developer to focus on the behavior of a class rather than the implementation. Thus a test is written specifying an expected behavior. Then code is written to satisfy that behavior. Another test is written with an additional behavior. Subsequently more code is written to satisfy this additional behavior. Thus, as a result you have written code to satisfy some desired behavior of a system. No more, no less. Within this rhythm of development, refactoring for cleaner code and better design can confidently take place due to the fact that a suite of tests has been developed along the way to ensure no functionality has been broken. Ron Jeffries, an XP founder refers to this habit as RefactorMercilessly
The definition of TDD is not as much about whether unit tests are written or ... integration tests are written ... or whether a unit test should test a class in total isolation ... as much as it is about specifying the behavior of modules through executable tests and then satisfying that behavior with code. TDD guides the design of code with the added benefit of providing a safety net of regression tests to allow for refactoring.
Eric Evan's book Domain-Driven Design has become very popular in the last decade. Few teams claim to exclusively follow domain-Driven design, but many teams who are agile aware