In defining an class's responsibility the overriding guideline is to stick to the Single Responsibility Principle like glue and you can do this by coming up with one concise sentence that clearly reveals your object’s intent. Two sentences usually implies two responsibilities and three sentences implies three responsibilities etc... When you've written down one sentence, check that you’ve actually got one sentence and that you haven’t stuck two together using a conjunction such as ‘and’, ‘but’ or ‘or’. This isn’t as simple as it sounds as the English languages is a lax and flakey entity so several attempts are occasionally necessary.
In my first two blogs in this series, What’s in a Name and Classification, I mentioned a badly named class called: XMLDataProcessor, so as an example I’m going to try to correct its name by defining its responsibility.
The name XMLDataProcessor doesn’t particularly reveal any intent and I previously said that there were several questions we could ask of this class. For example:
- Which XML Data?
- From what Feed?
- What processing does it do?
Now lets suppose the answers are...
- Which XML Data? A user timeline from Twitter.
- From what Feed? The data is available from a simple Twitter URL that look something like this:
- What processing does it do? It reads the XML data and converts the <Time> and <Text> element data (which are the Tweets) into an array of beans.
So, in summing this up we might as a first attempt get something like this:
This class is responsible for... reading the Twitter feed. It parses the XML. It extracts the <Text> and <Time> elements and converts the result into a list of simple beans.
Note the first part of the sentence “This class is responsible for...”. This is alway a good way to start defining a class’s responsibility.
HOWEVER, and this is a big however, the question ‘From what Feed?’ is a bogus question. The XMLDataProcessor shouldn’t care which feed the data comes from, if it did then we’d really be breaking the Single Responsibility Rule. It should be passed the data to ‘process’ in a convenient form such as a stream. This means that we can drop the bit about the twitter feed from our definition, though this fact should be noted as it’s a really good pointer to the design of the XMLDataProcessor’s collaborators.
Also, our first attempt at defining our class’s responsibility is too wordy. It’s three sentences and the third one contains the conjunction ‘and’. So trying again...
This class is responsible for converting the <Text> and <Time> elements of Twitter XML into a list of beans.
This is much better, the object’s responsibility has been specified using a single sentence and without any conjunctions (I’ve still used the word ‘and’; however, in this case it’s as a list separator).
Having defined our class’s responsibility, we can now come up with a good name. A list of candidates might include: TweetConvertor, TweetXmlToBeanConvertor, TweetXmlToBeanParser or TweetXmlParser - I’ll let you pick your favourite. The point to take away from all this is that it’s much easier to name a class once you know why it exists and what it does.
To repeat a key point from my last blog:
The idea of constantly reviewing the name of a class and comparing it with its responsibility is the key to good object naming.
The final thing to do is to use eclipse to rename the class...
...something that some developers are somewhat reticent of doing; however, classes should be ruthlessly renamed. It may cause a little short term confusion, but in the long term your software and project will be that much better.
To sum up, I’ll agree that the names of the majority of the classes you’ll write will be pretty obvious and that most of us will go through the mental shenanigans above in our heads without even thinking about it. However, there will be those cases where the name of a class isn’t all that clear and the best way to solve this problem is to define its responsibility with crystal clear clarity.