Chris said:
This depends on the situation.
If adding the new abstraction causes you to do anything differently from
the way you would do it in a more specific case, then the new way is in
that respect inferior for the originally intended purpose. It's then
time to compare that cost against the potential for re-use, and make an
informed decision.
You have a good point, but I don't know that a generalized solution is
automatically inferior to a custom solution, any more than hand-made
goods are automatically superior to machine-manufactured alternatives.
Implementing a class in the most general possible way has the nice
side-effect of distilling the exact concept the class is meant to
represent, and helps keep fundamentally separate logic wherever it
really belongs. You're right that generalization isn't always worth the
time, though, nor is it guaranteed to improve the product as a whole.
As one input into that informed decision, consider
that reuse is the most over-rated of all the frequently listed
advantages to object oriented programming.
Is that still true? It certainly used to be. I hear more about
maintainability and logical correctness than about reusability nowadays.
It seems like fat interfaces were in vogue for a while, with classes
trying to be all things to all people in the wan hope of potential
reuse. Now we seem to have swung to the opposite extreme, with lots of
tiny, immutable objects being the hallmarks of best practice.
Considering that a "helper" class doesn't really have much meaning
beyond a class that handles part of the work of building an abstraction,
eliminating helper classes is a rather poor goal.
Nonsense. By that definition, all classes are helper classes. You
might as well throw the term away entirely. Do you actually find that
your released code has lots of classes called DoohickeyHelper? I bet it
doesn't, because you are an experienced developer, and you probably know
better.
Well-designed object
oriented applications end up looking like a layered system of
abstractions.
True. I think that's true of good procedural programs, too, but even
more so of OOP.
From the perspective of any higher level of abstraction,
*any* class belonging to a lower abstraction level can reasonably be
described as a "helper" class.
You could choose to view it that way, but I don't think it would be very
useful. Primitive ints and doubles aren't just "helper types" by virtue
of being low-level. I don't know whether anybody has assigned "helper
class" a formal definition, but this certainly isn't the way it is used
in practice.
Certainly not as end-user documentation, nor as the only description of
what a class does.
The end user shouldn't see the helper class at all, else it's part of
the public interface, and not just a helper. I think a helper is, by de
facto definition, part of the implementation code, but specifically not
part of the interface.
OTOH, if you really have a class that's just a place to dump some code
related to Foo, then I suppose FooHelper is a reasonable name. What
would bother me personally about that name is that it makes me feel the
code probably belongs in Foo proper, else it should not have been
factored into a separate type.