TITLE: TDD and Encapsulated Objects AUTHOR: Eugene Wallingford DATE: August 05, 2004 11:04 AM DESC: hpw TDD does and does not encourage tight encapsulation ----- BODY: Does test-driven development help us to build software with a higher degree of encapsulation? I feel like it does when I write code. But this is the sort of claim that, when made in front of students, can be exposed as either wrong or more complex than it first appears. That's because it depends on assumptions and skills that not all programmers hold. How might test-driven development help us to build better-encapsulated software? When we write tests first, we have an opportunity to think about our code in terms solely of its interface because we haven't written the implementation yet! In an object-oriented program, the test involves sending a message to an object in order to see whether the object behaves as expected. The object's class may may be partially implemented, but not the behavior we are testing. And we are supposed to be thinking about just the requirement at hand, not anything else. But how can we go wrong? If we become sloppy, we can fall into the trap of writing a test that causes a change in the object's state and then verifies that the expected change has occurred. This often requires adding a public accessor to the object's interface that is otherwise unnecessary. Even you don't intend for client programmers to use the method, it's now there. One of the lessons of interface design is that, if it's there, clients will use it. It's more than just sloppiness that can lead us astray, though. Testing some behaviors is not straightforward because they involve outside resources (say, a web connection) or non-trivial collaborations (say, a network error). Often it's easier to write a state-based test than a behavior-based test. But those kinds of tests usually leave me feeling unfulfilled. That feeling is my test telling me to do better. The idea of mock objects developed in the XP community as a way to support behavior-driven testing in the face of such difficulties. But even mock objects aren't a guarantee that we will write well-encapsulated code. Martin Fowler wrote a recent article discussing the common confusion of mocks with stubs. I do think that TDD encourages and supports well-encapsulated code -- but only if the programmer understands the Tell, Don't Ask principle for designing objects. And practices it faithfully. And uses mock objects (or their equivalent in your programming style) for the tough cases. That's a lot of assumptions built into a simple claim. But most knowledge works that way. How can you support yourself in those assumptions? Pair programming! Those XP practices really do add up to something more than their parts. -----