Recently published

Practice notes

Home arrow Blog arrow Helpers are unhelpful

Helpers are unhelpful

It isn't new to have doubts about helpers. One provocative blog by Nick Malik grabbed attention with the title "Are Helper Classes Evil?". That talked about helper classes, defined as classes consisting entirely of static methods. I wanted to broaden the scope and also give my own reasons for trying to avoid helpers.

Why broaden the scope? Simply because the term "helper" seems to be getting used more and more widely, and that is one of my objections to it. It all started out with helper methods, and I'll come back to those. But now there are helper classes and I've also seen talk of helper functions. They were defined as "a function that performs part of the computation of another function".

terms that don't mean anything are a liability

Maybe that gives a clue to a major objection. "Helper" often doesn't mean anything at all in many cases. And terms that don't mean anything are a liability when it comes to clear thinking about design. Meaningless terms have a number of nasty effects. They give you an unpleasant feeling of not having quite grasped what is going on, because you don't understand what they are. They make you think there ought to be something they have in common. Also, they encourage people to believe they have given a description when really they have said nothing. Stripping away meaningless words makes it clear that some better words are needed to explain what is going on.

Think about those helper functions. They perform "part of the computation of another function". Well. It's been around for a long time, and top down design works by determining a top level function and relegating everything else to sub-functions. On that basis, every function in a system except one performs a part of the computation.

It's not as if we could decide which functions, classes or methods are helpers on account of them being helpful. Where are we going to find unhelpful parts of the system?

So one part of the problem is that "helper" doesn't convey any useful information. But how did the terminology ever get started? For that we need to go back to helper methods, and they will give us some ideas about why over generous use of "helper" is not only meaningless but also bad, "evil" maybe!

The goal has always been good design

There is a danger of getting the cart before the horse in discussing design techniques, such as object orientation. The goal becomes to achieve a class hierarchy, or inheritance, or encapsulation. All those things have virtues, but they aren't themselves the goals we should be seeking. The goal has always been good design - something that we can't define except by its virtues when it is experienced. Good design has clarity and economy of expression. It is flexible and relates naturally to the problem that is being solved.

Of course the reason many of us are committed to the techniques of object orientation is that they have been shown time and time again to contribute to the desirable properties of a good design. But the overarching objective of object orientation is to find a good object model exactly because it models the problem well. If we achieve that, our design discussions are far more fruitful, the code can be related to the problem and provides an efficient working system. It takes hard work to do that, but the goal is simply stated.

So if we accept those basic principles, then we want to find a way to break down the problem into cooperating classes with no residue. Everything that goes on will ideally be a capability that we see evidently belongs to one of the objects within our problem. Unfortunately, life is not always so obliging and helper methods started out as methods that were included in a class because, although they were not essential behaviours of the class, they were useful to other parts of the system in utilising the class.

There's always room for debate about what is essential to a class and what is ancillary. One example that might be classified as a helper method could be the abililty to produce a tidy display of the information contained in an object. Displaying object properties is not essential to the behaviours that make the object model our problem, but is a useful facility for other classes to use.

Possibly validation methods might be seen as helper methods, when they are peripheral to the main responsibilities of an object. But that seems a more arguable case, as the ability to validate inputs might be seen as an essential capability for an object. Decisions need to be made on a case by case basis.

Extending "helper" to private methods ... meaninglessness

On that definition of a helper method, it is obvious that it cannot be a private method, since the whole notion being advanced here is that a helper method provides additional assistance to other objects, over and above the core capabilities of the object. Extending "helper" to private methods seems once again to be an example of descending into meaninglessness, where a method is a "helper" just because it is useful. Surely we shouldn't have any methods that are not useful!

Armed with a more palatable definition of what is to be counted as a helper method, it is easier to make the key criticism of the excessive use of "helper". It is that building systems with numerous helper methods, functions or classes is a failure to build a decent object model. It is an attempt to cover up a lack of object orientation by the use of seemingly OO jargon. And that is a bad thing to do, since there is so much to be gained by continuing design work until we have a good OO design and most of the helpers fall away.

Take another example of unnecessary helpers. Some people have decided to write web related code starting with some kind of template, filling in the variable values by reference to a helper class. This is usually the kind of helper class that is nothing but static methods, which means that it is not really a class at all, but merely a kind of namespace. But why go this way when there is almost certainly a perfectly good object model that can be applied?

For a web application, we can assume that there is a dispatcher of some kind that fields the actual request and decides what needs to be done to fullfil it, possibly many things. We can associate this situation with a classic principle, that of a controller. In the web application environment, a controller may present an interface that is used to act upon information submitted by a site visitor; it may also present an interface that provides elements of the browser page that will be the response to the visitor. It may also have other relationships within the web application. And it will particularly have a relationship with the classes and objects that model the problem.

A controller... is well able to be a proper object

But we have no need of static methods for the most part. A controller knows things (it has properties) and it knows how to do things (it has methods) and is well able to be a proper object. The situation certainly does not seem to require us to have much if any residue left over from a genuine object design. And, once again, it is worth saying that the aim is not an object design per se, but a good design that serves the purposes of a sound system.

Should static methods be anathema? Often, the answer to that must be "yes". The real justification for a static method is that it is another name for a class method - it runs against the class rather than any particular instance of the class. (The distinction between class and object becomes one of perspective in those subtle languages where classes are themselves first class objects).

The first questions to be asked about a static method is whether it is truly a class method, some behaviour that belongs to the whole class (such as knowing how many objects of the class are currently instantiated)? If it is not, then what we really have is actually just a function. If it is a function, then we need to ask the second question, which is whether there really is a need for an isolated function, or whether it is a defect in our object design and the "function" should really be a behaviour of some class.

I'd see it as really rather incidental, since it is rarely worth allowing efficiency considerations to overrule good design, but it so happens that PHP rewards us for avoiding static methods. Instantiating an object and using its methods are nearly always faster in PHP than making references to static methods that are lumped together in a "helper class".

It looks to me as if it would be no bad thing if the word "helper" were to largely disappear from the software development lexicon. It does have a legitimate use, although maybe someone could coin a better expression for the true helper method. "Helpers" sound such nice, friendly things that they seduce people into bad designs. Really, though, it's time they were put out to pasture.

#128003 • 08/05/2008 2:36pm by Martin Brampton • Vote: Up votes (658) Down votes (501)

blog comments powered by Disqus