Archive for July, 2007

Designed vs. Open Inheritance

Wednesday, July 25th, 2007

I like Martin Fowler’s write up on Designed Inheritance, but I’m not so sure I agree with his implied suggestion that you cannot have designed inheritance and provide an enabling design.

If I have a component that is being called by other code, and that component is implemented as an abstract class that only allows subclasses to implement abstract methods (all concrete methods are final), then I cannot override the behavior of the parent class. This is designed inheritance because people can only subclass it in the way that I’ve designed. I wrote about this a few years ago when I talked about extending non-abstract classes.

To make this design “enabling” I can simply provide an interface for my component (above the abstract class), and make all the code that references the component point to the interface instead. Now, if I am developing a library and somebody decides that they want to extend it in a way that I didn’t anticipate, they can do so, they just have to implement the interface from scratch. They are free to do it, they just can’t misuse my implementation by using it in a way that it wasn’t designed to be used. I think its fair to have to go out of your way to provide an alternative implementation. Essentially, I’m saying that the framework provides open inheritance, but the implementation provides designed inheritance.

You only really have to worry about unanticipated uses if you’re writing a library anyways. If your writing code within an application, then I would stick to the designed inheritance and let people refactor and change the code if the requirements drive them to that. This is another perspective that I think Fowler didn’t address. I believe that Josh Bloch’s advice is probably geared more towards application developers, while Eliotte Rusty Harold’s comments are within the context of library development. These are different beasts. When you’re contributing to an application, you can change the code, when you’re using a library, you typically can’t.

Don’t mercilessly refactor unit tests!

Wednesday, July 25th, 2007

I teach TDD courses, and one of the questions that inevitably pops up is whether you should refactor your tests. When it comes to eliminating duplication in tests, my threshold is very high. By that, I mean that the most important thing to me is readability. I want to read a test like a mini story: I set this up, I execute this, I verify that.

One of the biggest annoyances I encounter with experienced TDDers is when they decompose tests to the point where you can’t see what the test is doing without bouncing around to 50 places in the code. I don’t care if I have duplicate setup for multiple tests if that setup is only 1-5 lines of code. If the entire test can be seen on the screen, then you can understand what it is doing much more easily. By eliminating duplication in test setup and verification, tests become less readable. For example, I might have to keep jumping to the top of the class (or worse yet to another class) just to see what the expected values are that I’m comparing to.

When I do eliminate duplication in tests, I try to use composed methods (with descriptive names) that are explicitly called from the test methods, rather than using methods that are automatically called by a testing framework (e.g. setup methods in JUnit); this maintains the readability of each test.

I’m not saying that you shouldn’t refactor your tests at all. I just recommend that you have a higher threshold and not be as “merciless” as you are on your real code.