I just got back from JAOO2007. One session of the conference was James Coplien’s “Scrum Architecture”. After this session, a discussion took place about Coplien’s statement that “TDD harms your architecture”! This discussion continued afterwards as an Open Spaces debate. I had the chance then, with the help of Floyd Marinescu, to organize a filmed debate at InfoQ’s studio between Bob Martin and James Coplien on the same topic. I really enjoyed this debate which really showed a high quality spirit of discussion from both sides. Both had their arguments. I will not tell my opinion but rather let you judge yourself once the video is out on www.InfoQ.com .
Recently, I posted about the fact that I always write tests before code, but I don’t do Test Driven Development where I discussed the way I view testing. Yet I don’t guess I’ve been clear enough, so I decided to write few lines trying to better reflect the way I view a testing approach.
When I have a domain problem at hand, first what I think about is partitioning and abstraction, which means dividing the domain into sub-domains. This partitioning procedure is not driven by any tests, but rather by domain knowledge acquired from domain experts. This is extremely important; the architecture/design should reflect the domain/sub-domain problem it is trying to solve. This helps the software be flexible adopting business changes, as it was designed from a business perspective. A book that explains very well this approach is Eric Evans’s Domain Driven Design.
This Up-Front analysis is not defining the full up-front architecture, far from it, rather defining good bases for an architecture that maps to business. It shouldn’t take much time, just enough to help going forward with an iterative approach. This should define, either in code or in a tinny UML sketch, an object structure that forms the basic sub-domain’s components.
After defining the main structure of the sub-domain’s solution, I follow an iterative process as follows:
1: Driven by the business knowledge crunching, I define a component’s contract with its invariants and conditions
2: I write a test that forms the specification of this contract and its invariants
3: I start the implementation to satisfy the specifications I defined in the test
A very important note here is that the contract specifications should be readable, very clear and explicit. This explicitness helps to have a better vision of the whole system while reading the contracts-invariants of its defined components. This also helps spot bugs without the painful debugging: this approach of Design by Contract reflects developers understanding of the business domain in a more explicit way, so it makes it easier to spot misjudgments developers might have done in their implementation. This intention revealing method of development highlights important business rules, rather than letting them hidden behind an abstraction. Abstractions should not hide any important business concern as an implementation details. Explicit contracts and invariants allow business experts to have a look on what is going on inside the software. For an example of bugs that result from developer’s misjudgment see Reganwald’s recent post .
Of course unit tests are not the best tools for this approach. They work fine if we emphasize on methods and class naming for readability and visibility of invariants and rules. Still I prefer tools like BDD or Eiffel/Spec# Design by Contract. Hope we will have some more support for such tools in the industry soon.
A metaphor James Coplien used to illustrate the problem in Test Driven Development approach, which made sense to me, is a test driven course in a school. It’s about a teacher that finds that most of his students fail in the final test. So to make things work better, he decided to ask the students to write themselves their tests by the beginning of the semester, and then to let them pass these tests by the end of that semester! Hence, they might get better grades, but that doesn’t mean they got better knowledge at all.
Â


[...] about this approach to testing in my newer post Design Driven Testing: Using tests as specifications of system’s invariants and contracts desi…… del.icio.us, [...]
Pingback by Sadek Drobi’s Blog » I always write tests before code, but I don’t do Test Driven Development — September 29, 2007 @ 5:38 pm
Sadek, I think your description of the architecture/design approach summarizes my JaOO talk beautifully. Add to that the Tools and Materials metaphor that Serge pointed out to us, and the use of Java abstract classes for the domain architecture and of Java interfaces for the tool architecture, and it pretty much sums it up.
I like your notion of tieing the tests back to business invariants. Those can usually be found in the Use Cases. However, I can’t follow your reasoning of how to bring these invariants to the level of components. I think too many people guess about individual components’ invariants at the time they are coding them up. This is reminiscent of what Bas Vodde said at JaOO: that you can use a modified TDD at the integration level. I claim that that’s not TDD any more, at least not in the sense of driving the design, and certainly not in the sense that Bob Martin defined TDD. You really are going to write all the integration tests at that level *before* writing any code subject to that scope of integration? A sane person would develop the tests and code in parallel. To do this serialization will greatly decrease your velocity.
As Gertrud Bjørnvig points out, It’s not “test first” that’s important: it’s “test-while.”
Comment by Cope — October 2, 2007 @ 7:01 am
There are a lot of interesting ideas in our previous discussions, including the “Tools and Materials” metaphor you’ve just mentioned. I really would like to have such discussions public because I guess we tend all to agree on a lot of values and concepts. And we share some understanding of what agile really means.
On the other hand, I would prefer to have this kind of discussion in a more neutral place than my personal blog that can be influenced by my ideas. I can suggest publishing a WIKI where we can discuss such ideas, then publish our shared understanding about agile development. I won’t go personally for choosing Wikipedia as I concerned about spam. I can arrange for the host/domain name/installation. I also welcome any other suggestions.
For the business invariants, yes I am talking about the integration level, but also talking about tracing them down till the coherent units/elements of the program, be it classes, methods or a whole structure of classes. The aim is to make developers’ intention and assumptions more visible.
I agree with you that defining business invariants in an up-front manner in the level of integration will have its effects on velocity. That’s why I tried to avoid using the term “test-first” that I, mistakenly, used in the previous post. I tend to agree on the importance of the “test-while†over the rigid “test-first†term. That’s why I mentioned that I do this approach in an iterative way. Still that can be misunderstood as to be a test-first approach. But what I want to say is that at any moment of implementation/test we can go back and modify invariants and assumption in all the levels (from integration level down to the deepest coherent set of elements of the implementation). I guess I should update the post to add that the process I am using is recursive, and that it can go down and up defining/modifying/adding invariants in all the levels of coherent elements of the implementation.
Comment by Sadek Drobi — October 2, 2007 @ 11:28 am
[...] bugs. The goal of Unit testing must be to define system boundaries and to specify invariants (Design Driven Testing: Using tests as specifications of system’s invariants and contracts desi… – Sadek [...]
Pingback by Julien Delhomme’s Blog » Are you really sure Agile is not bad for Design? — October 13, 2007 @ 11:33 pm
[...] I could of course be preaching test-driven development (TDD) and show how Rails makes this approach quite easy, but haven’t TDD’ed much in my latest projects, because I was tired of having this huge, always-breaking test suite, which rarely caught any real bugs, and mostly just indicated that my tests was buggy. I’m starting to get a feeling that Cope is right when he says that unit testing can be harmful. [...]
Pingback by Fingerprints of Casper Fabricius » Talking at BarCamp Copenhagen — January 16, 2008 @ 7:29 pm