Been thinking a lot about OO just recently, as you do. A lot of the practices I use get questioned when I demonstrate them, exactly as I would have done had the situation been reversed. Many of the questions are of the form ‘Isn’t this OO for OO’s sake?’, or ‘That seems like a lot of work, couldn’t we just use a Getter?’. What’s interesting is that the question of whether something is a lot of work depends very much on your perspective. I’m fairly lazy (aka. ‘pragmatic’) so I seek to find neat ways of reducing effort, but my perspective is usually a fairly wide one, so I’m usually thinking about ways of reducing effort over the life of a project and not just the code I’m typing at 2.30 on a tuesday. Its often the start of an interesting discussion when stuff I’m doing to reduce effort is queried as too much work. It is also be a hard thing to explain, when it does take demonstrably longer to write some code that doesn’t break encapsulation, as opposed to just adding a Getter. I’ve seen what happens to a system when all the objects in it have had their boundaries eroded by the addition of getters, and I remember wishing that there was another way to do it, which ultimately led me to considering the following approach, which I’ve worded as a ‘challenge’:
- Can you take any class in your system and instantiate it easily in a test harness? -Credit to Michael Feathers for this one.
- Can you write a system where none of the classes have Getters (or public properties in .net)?
- Do all your objects have only one constructor?
- Can you write a system where none of your objects take primitives (including string) as parameters to their public methods?
- Where a class accepts multiple parameters in its constructor, can you write it in such a way that none of them are primitives (or strings)?
- Can you do the above using TDD?
I’m not saying I do all this all the time, but it is a goal I try to keep in mind when developing. As an approach it leads to many more fine grained classes with names like ‘FirstName’, ‘Age’ etc that might otherwise have been represented with strings and ints, but it is a fascinating way to develop, and leads to some very interesting code. For example, lets say I want to take an object and render it out as HTML. Usually I immediately think of adding getters for all the fields that needed to be written. If you’re avoiding getters, then you end up with something more like ‘public void WriteTo(IRenderer)’. Which is also really easy to write a test case for, either with a mock object, or by having the test case implement the interface itself.