11

I was reading up on design patterns, and I read that the prototype design pattern does away with excessive subclassing.

Why is subclassing bad? What advantage would using a prototype bring about over subclassing?

3

6 Answers 6

21

Why is subclassing too much bad

"Too much" is a judgement call; but take it from me it is bad. The code I work with has DEEP inheritance and the code is just damn hard to read, understand, follow, trace, debug, etc. etc. It is effectively impossible to write test code for this stuff.

Prototype pattern does away with subclassing

Or does the question mean "does away with too much subclassing?". This pattern calls for cloning a "template" object to avoid subclassing, at least at that point. There's no rule that says the "template" can't be a subclass.

Favor composition over inheritance

This idea here also includes delegation and aggregation. Following this heuristic means your software tends to be more flexible, easier to maintain, extend, and reuse.

When a class is composed of parts you can substitute those parts at runtime. This has a profound effect on testability.

Testing is easier. You can use fake parts (i.e. "mocks", "doubles" and other testing-talk). Our code's deep inheritance means we must instantiate the entire hierarchy to test any bit of it. In our case that is not possible without running the code in it's real environment. For example we need a database in order to instantiate business objects.

Changes come with side effects and uncertainty - The more "base" the class the more widespread the effects, for good or bad. There may be desired changes you dare not make due to side effects uncertainty. Or a change that is good for some place in our inheritance chain is bad for another. This is certainly my experience.

3
  • I'd be really interested to see some examples of when inheritance makes testing (especially mocking) difficult and how composition helps with that.
    – Armand
    Mar 4, 2012 at 15:26
  • @alison: a Method in a derived class that uses another method from the base class where the implementation in the base class makes it virtually impossible to test error scenarios. Had that been composition it would be easier to inject an object which causes the error to arise
    – Rune FS
    Mar 4, 2012 at 20:32
  • @allison: Examples? When the code base is very large, when base classes are used by dozens of classes directly and hundreds by inheritance. Because the point of deep inheritance is reuse and so a base class is genericized to the point that the debugger stack trace can't show what methods are actually being called. Finally, When there is no dependency injection already built into such a Frankenstein. A top level class may "be a" half dozen or more other things which collectively "have" dozens of internal objects - each with their own inheritance fun house.
    – radarbob
    Mar 11, 2012 at 3:47
9

I think one of the reasons this has been viewed as a bad practice is that over time each subclass can contain attributes and methods that make no sense for that object the further you go down the chain (in a poorly developed hierarchy). You can end up with a bloated class that contains items that don't make sense for that class.

I'm agnostic about this myself. It seems dogmatic to just say it's bad. Anything is bad when misused.

3

Inheritance can break encapsulation in some cases, and if that does happen it is bad. Read for more.


In good old days without inheritance, a library would publish an API and application using it makes use of what is publically visible, and library now has it's own way to handle the internal gears which keep changing without breaking the App.

As the needs evolve, library can evolve and can have more customers; or it can provide extended functionality by inheriting from its own class with other flavors. So far so good.

However, fundamental thing is, if an application take's up the class and begins to subclass it, now a subclass is actually a client rather than an internal partner. However, unlike a clear unambiguous way that public API is defined, the subclass is now much deeper inside the library (access to all private variables and so on). It is not bad yet, but a nasty character can bridge an API which is too much inside the APP as well as in the library-

In essence while this may not always be the case but,

It is easy to misuse inheritance to break encapsulation

Allowing subclassing can be wrong if that point.

2

Two reasons.

  1. Is runtime performance. Everytime you invoke a subclass from a superclass you are doing a method call so if you have nested five classes and invoke a method in the base class you will be doing five method invocations. Most compilers/runtimes will try to recognose this and optimise the extra calls away but it is only safe to do this for very simple cases.

  2. Is the sanity of your fellow programmers. If you nest five classes I have to examine all four parent classes to establish you are really calling a method in the base class, it gets tedious. I may also have to step through five method invocations when I debug the program.

3
  • 6
    -1: You're right about #2; but not about #1. Several layers of inheritance won't necessarily impact runtime performance.
    – Jim G.
    Mar 4, 2012 at 14:54
  • Worried about a couple of extra procedure calls at machine code level and using OP and inheritance, and you worry about the sanity of your fellow programmers.....
    – mattnz
    Mar 4, 2012 at 23:16
  • @JimG. It might not, but it can. :) There's also possible memory usage to worry about: if you don't reuse all of the base's variables, they may still get allocated as part of constructing the object.
    – Adam Lear
    Mar 15, 2012 at 2:52
2

"Too much" is a judgement call.

As with most things in programming, sub-classing isn't inherently bad when it makes sense. When the model of your problem solution makes more sense as a hierarchy rather than a composition of parts, subclassing may be the preferred option.

That said, favoring composition over inheritance is a good rule of thumb.

When you subclass, testing can be more difficult (as radarbob noted). In a deep hierarchy, isolating problematic code is more difficult because instantiating a subclass requires bringing in the entire superclass hierarchy and a bunch of additional code. With a compositional approach, you can isolate and test each component of your aggregate object with unit tests, mock objects, etc.

Subclassing can also cause you to expose details of your implementation that you might not want to. This makes it difficult to control access to the underlying representation of your data and it ties you to a particular implementation of your backing model.

One example I can think of is java.util.Properties, which inherits from Hashtable. The Properties class is only intended to store String-String pairs (this is noted in the Javadocs). Because of inheritance, the put and putAll methods from Hashtable have been exposed to users of Properties. While the "right" way to store a property is with setProperty(), there is absolutely nothing preventing a user to call put() and passing in a String and Object.

Basically, the semantics of Properties are poorly defined because of the inheritance. Additionally, should anyone ever want to change the backing object for Properties, the impact will have a much greater impact on code that uses Properties than if Properties had taken a more compositional approach.

1

Short Quick Answer:

Its depends on what you are doing.

Extended Boring Answer:

A developer can make an app. using either, subclassing or (prototypal) templates. Sometimes one technique works better. Sometimes the other techinque works better.

Choosing with technique works best, also requires, to consider if a "Multiple Inheritance" scenario its present. Even if the programming language only supports single inheritance, templates or prototypes.

Complementary Note:

Some answers relate to the "multiple inheritance". Altought, not the main question, it's related to the subject. There are several, similar, posts about "multiple inheritance v.s. composition". I had a case where I mix both.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.