Do you work in a codebase where 80% of the class names look painfully similar to one-another?
Now, tell me, does that make it easier, or harder to find what you are looking for when you are trying to get work done?
This is not a new problem. In fact, Kevlin Henney wrote an excellent article on the subject called 'Exceptional Naming', which I will link below for further reading. It was Kevlin's article that inspired me to write this one. However, rather than simply repeat what has already been said, I want to take it a step further.
In his article, Kevlin references the common habit of 'Homeopathic Naming'. We developers have a habit of adding extra fuzzy words to the end of our names in an attempt to add more meaning (as well as make them sound more programmer-y). This creeps in particularly with words like Manager, Handler, Object, Controller, Context and, my personal favourite, Service.
Stop calling everything a Service.
That was actually the original title of this article, but I opted in the end for something less confrontational sounding.
Kevlin quite rightly pointed out that using this homeopathic naming convention does nothing but dilute the meaning of the words being used. His example was Exception types in both .NET and Java. Since every type has the word Exception tacked on the end, the word starts to lose meaning and is pretty much just there as a matter of convention.
This is where I would like to take the discussion further. I believe that this habit does far worse than simply dilute the meaning of words. I feel that it can be actively misleading about the intent of the system.
To explain why I feel this way, I'm going to make reference to some of the established patterns that we use daily in our systems.
Consider the widely used Layered Architecture pattern. We organise our system by separating it into layers. We might have the Presentation (or API/Controller etc.) layer, the Services (Business) layer and the Persistence (Data Access/Repository) layer.
In this context, the word Service has a distinct meaning. We are referring to a particular part of our architecture. In my experience, this tends to be the middleware between the API and the persistence of our Entities. We might have a UserController that calls the UserService, which in turn calls the UserRepository to perform User-specific operations. The purpose of these classes focuses on the Entities that our system is dealing with.
Someone who frequently works with this style of architecture might be misled when they come across a class called, say, PayCalculationService. Is this class acting as the middleware for a PayCalculation entity in a layered system? Or does it simply reference other entities in order to calculate pay?
One might think that PayCalculator would be a more suitable (and more obvious) name, which does not mislead about its intent. It may seem like a contrived example but I have actually seen this one in the wild.
Of course, I can't talk about patterns without mentioning the Gang of Four and the plethora of now widely used design patterns that they helped to create.
This problem becomes more obvious if you start to mis-use design pattern terminology in places where it doesn't belong.
If you see a class called UserFactory, you are already making assumptions about what that class does, provided that you are familiar with the Factory pattern.
That could lead to problems if it turned out that the class does not, in fact, perform the role of a Factory as defined in the Go4 description.
Another gripe that I have with the word Service in particular is that it is usually a sign of a poorly designed Object Oriented system. These Services have a tendency to be little more than bags of public methods. The idea of good OO design has been abandoned in favour of a largely procedural pipeline of data. This is fine if your application is just supposed to process a pipeline of data. All too often I simply see missed opportunities where objects could have been utilised, but instead the "objects" are simply proxies for public methods.
And so the name of the class tends to be a vague description of what the method does, with Service tacked on the end.
In summary, a lot of work has been done by groups such as the Gang of Four to establish patterns for development. This is important as it allows experienced developers to speak a common language that they all understand. Mis-using terminology in this way breaks down the efficiency of that common language and actively hinders communication of ideas.
Programmers, think about your names. Use common sense. If your class calculates something, it's a Calculator. If it generates something, consider Generator over GenerationService. These words can be over-used like any other, but at least they contribute to expressing the intent of that class.
Further Reading: Exceptional Naming, Kevlin Henney