For a long time I’ve felt uncomfortable every time I’ve written a class with a name like ‘FooManager’, ‘BarWatcher’ or ‘BazHelper’. This has always smelt bad and opening any codebase that is structured this way has always made me feel ever so slightly uneasy. My thoughts as to why are still slightly fuzzy, but here’s what I have so far…
Firstly some background, my perspective on object-oriented programming is deliberately naive. I don’t like to create interfaces for everything and I don’t use lots of factories. This comes, I guess, from my earliest education in C++, through one of the best books ever written on the subject. Simple C++ by Geoffrey Cogswell. While you stop laughing at the idea that you can learn something as complex as object-oriented programming from a thin paperback featuring a robot dog and the term POOP (Profound Object Orientated Programming), think about the very essence of what it is we’re trying to do.
OOP is about modelling objects. Objects are things that are, and to name things that are we use nouns. Then we give the objects responsibilities, things that they can do, behaviour. So we use what my primary school english so beautifully called ‘doing words’ or verbs if you prefer.
Now, not long ago I wrote a ByteArrayHelper class in Java. I’m not ashamed of it. The code is good, efficient, readable code that does many of the common things I needed to do with a byte. However, help is a verb. My classes responsibility is to help byte by doing things that byte doesn’t do. I’ve made the class name into a noun by nounifying the verb.
By de-nounifying it I can see where the responsibilities should really sit – with byte. My ByteArrayHelper does nothing for itself. All of its methods do something with a byte. The methods are things like SubArray(offset, length) and insertAt(offset, bytes). These are methods that I wanted on byte.
Following the search for a noun-base approach I could have created my own ByteArray that may or may not have delegated to a byte internally. This could not have been passed around as a byte though, so would have required substantial refactoring of the classes already there. So, I wrote a ByteArrayHelper instead. Having written the ByteArrayHelper, though, it was obvious that none of the methods required any instance variables, they all took and returned byte arrays – so I made them all static. So, my nounified verb had actually led me to write nothing more than a function library.
Whether or not I made the right decision is left as an exercise for the reader.
Taking another example, this time from a friend’s code. Looking through it we noticed that one of the classes was a FileLoaderManager – a class who’s responsibility is to manage FileLoaders. A nounified verb looking after another nounified verb. I hasten to add that this is not bad code – the code in question does some awesome processing of relationships looking for similarities, like Amazon’s ‘people who bought this also bought’ but more generic.
When we looked into the FileLoaderManager and took away some of the responsibilities that fitted better with other classes we were left with just the need to list all the files in a given path that matched a particular pattern. Knowing what files are at a given path sounds like the responsibility of a Directory to me. Now, being very lean C++ we didn’t bother looking for one of the readily available Directory classes, the code we already had could be re-factored quickly. Having written the Directory class it becomes obvious that it would be useful elsewhere, whereas the FileLoaderManager could only be used for the one specific case it originally fulfilled. The nounified verb had led to the code being far more specific than it needed to be.
Two classes I came across in a PHP codebase recently were called FilePutter and FileGetter. These two classes wrap the file_put_contents and file_get_contents functions in PHP, wrapping these functions as classes allows them to be mocked, and therefore users of them can be unit tested. Wouldn’t a single class called, simply, File be easier to follow? The nounified verb approach had led to a peculiar structure in the code made it less obvious for a reader to follow.
So far then, my conclusion is that nounified verbs are likely to be a sign that I’m not using OO techniques for specialisation of behaviour; that my code is more specialised than it could be or that I’m writing in a way that is less easy to read than it could be.