I’m seeing a lot of instantiable classes in the C++ and Java world that don’t have any state.
I really can’t figure out why people do that, they could just use a namespace with free functions in C++, or a class with a private constructor and only static methods in Java.
The only benefit I can think of is that you don’t have to change most of your code if you later decide that you want a different implementation in certain situations. But isn’t that a case of premature design? It could be turned into a class later, when/if it becomes appropriate.
Am I getting this wrong? Is it not OOP if I don’t put everything into objects (i.e. instantiated classes)? Then why are there so many utility namespaces and classes in the standard libraries of C++ and Java?
Update:
I’ve certainly seen a lot examples of this in my previous jobs, but I’m struggling to find open source examples, so maybe it’s not that common after all. Still, I’m wondering why people do it, and how common it is.
4
I’m seeing a lot of instantiable classes in the C++ and Java world
that don’t have any state.
Some possibile reasons to create classes without ivars of their own:
-
State is or could be contained in a superclass.
-
Class implements some interface and needs to be instantiable so that instances can be passed to other objects.
-
Class is intended to be subclassed.
-
Handy way to group related functions. (Yes, there may be better or different ways to do the same.)
Am I getting this wrong? Is it not OOP if I don’t put everything into
objects (i.e. instantiated classes)?
OOP is a paradigm, not a law of nature. There are some languages where everything is an object, so you really don’t have a choice. Other languages (e.g. C) don’t provide any support for OOP at all, but you can still program in an object oriented style. I’d say you can have OOP if you don’t do everything in classes… you might say that you just have less OOP in that case.
Caleb and Robert Harvey have already pointed out what utility classes are, and some legitimate reasons for having “data-less” classes. Those descriptions are spot-on, but deal with the positive aspects.
I would like to just mention that the abuse of utility classes can definitely be an OO anti-pattern (see c2wiki’s description). This quote sums it up nicely:
A large number of such classes (particularly those with only a single method) indicates that the designers are thinking upside-down, ie. thinking of that which can be done to an object rather than that which can done by the object.
If you are claiming to be practicing object oriented design, but your codebase consists almost entirely of utility classes, I’d say that you are definitely doing something wrong. Having said this, a functional approach has just as many merits, and can be excellent to work with, too. Just don’t claim to be following the one, while half-heartedly implementing the other.
Utility classes in Java and C++ are used to maintain a library of methods that take one or more input parameters, and return a result. They have no need to hold state, if they simply return a value. In that respect, these methods can be regarded as a crude form of functional programming, with all the advantages thereof (no problems with concurrency, for one thing).
In any case, these classes just serve to group together related methods in a single container, methods that don’t require instantiation of an object to work properly. An example of such a class is a Math class containing SINE and COSINE (and other math) functions.
A lot of those classes do interact with data, even if they don’t explicitly contain it, and need to do so in ways that require multiple simultaneous instances to be active. E.g. a stateless session bean that interacts with a database stored procedure, passing incoming data to some PL/SQL package and passing the results back to the calling application. That thing needs to exist in multiple instances, but doesn’t itself contain any data fields.
In object oriented languages where classes are not objects, you can do a lot more with an object than a class.
You can pass an object as a parameter, you can substitute a type compatible object, you can implement an interface (I imagine there are languages in which classes are objects but you can do some of these things, but in any case…). All of these things are pretty important so the default decision is usually to make a class instantiable.
For some classes the capabilities granted by instantiation seem unlikely to be needed. You probably won’t need to swap out one implementation of Cosine for another, for example. It turns out it’s mostly utility functions that don’t need these capabilities, so it’s mostly utility functions that have classes that aren’t instantiable.