Why Derive from a Concrete Class Is a Poor Design

why derive from a concrete class is a poor design

A problem with inheriting from a concrete type is that it creates some ambiguity as to whether code which specifies a certain type really wants an object of the specific concrete type, or wants an object of a type which behaves in the fashion that the concrete type behaves. This distinction is vital in C++, since there are many cases where operations which will work correctly on objects of a certain type will fail badly on objects of derived types. In Java and .NET, there are many fewer situations where one can use an object of a particular type, but could not use an object of a derived type. As such, inheriting from a concrete type isn't nearly as problematical. Even there, however, having sealed concrete classes which inherit from abstract classes, and using the abstract class types everywhere except in constructor invocations (which must use the concrete types) will make it easier to change parts of the class hierarchy without breaking code.

Deriving from a concrete class?

Inheritance is an important part of c#, ruling it out would be a waste.

Nevertheless, the book emphasizes the open for extension closed for change SOLID principle and this is actually a good thing.

Not to derive from concrete classes ( note, abstract classes and interfaces are not concrete ), helps you to adapt this paradigm. Inheritance is not typically suited for extension, and makes inversion harder ( because the latter relies on interfaces and concretes are not interfaces ).

So in practice, you'll see that base classes are often abstract. Not all, and not every framework adopts it. Sometimes there are good reasons to inherit from a concrete. But the book, is in it's way a easy read and to go into details on the exceptions would make it much harder to read.

So bottom line: no, one should not follow the rule at all cost but only do concrete inheritance if one of the following:

  • you know what you are doing (so you have a really really really good reason)
  • you know it doesn't matter ( because it's a simple project/object)
  • you know the concretes will be contained to the project itself (internals)

Is inheritance of concrete classes evil?

Not a C++ guy (have professional experience with big enterprise systems in c#, java, and ruby), but here is my 2 cents anyways

This isn't a black and white thing.

The problem with inheritance is that it introduces tight coupling. Worse, that coupling is usually around encapsulated state. Changes in super classes can have rippling effects down inheritance hierarchies, creating subtle and hard to predict bugs.

Interface segregation totally sidesteps those issues, because it doesn't break encapsulation the same way.

The good thing about inheritance is that sometimes you have an object model that really is the same thing, just with a very small change or addition. As long as that change is very clear, not wide reaching in scope, and isn't an additional constraint (see the circle-ellipse problem), the code reuse will trump the tight coupling.

I stick to composition over inheritance as a rule of thumb, not a law.

Decorating a concrete class, bad practice?

Extending a class can have unintended side effects.

If Foo already has a constructor (or multiple) you have to implement those too and call the super class.

Additionally, if Foo has private state or side effects in the constructor, those now get executed twice. Once for the Foo passed in the constructor and once for the LoggedFoo, which is also a Foo.

It could get messy and lead to bugs and increased resource consumption, but that depends entirely on the class. If the class behaves like an interface (default constructor, no side effects, no state) it might not directly be a problem. But at this point it would just be a subclass that calls through to an other instance, which may be a handy construct but I wouldn't call it using the decorator pattern.

Is it wrong to make every concrete class to inherit from an interface?

It's more than just mocks. In the case of Spring, it's about dynamic proxies and aspect-oriented programming. That's how Spring does transactions, remoting, and aspects of all types.

I use interfaces for repositories, services, and the like, but I don't put interfaces on model objects or anything else whose implementation isn't likely to change.

Interfaces separate APIs from how they're implemented. If your implementation doesn't change, an interface doesn't make much sense.

Zed Shaw is a terrific writer and developer, but take what he says with a grain of salt. I think some of the over the top hyperbole that he indulges in is for entertainment value. He's got a point ("Don't do things just because somebody who claims to be an authority tells you it's a 'best practice'"), but the way he's saying it is part theater.

OO principle: c#: design to interface and not concrete classes

For your first question the answer is NO for all your points. If it would be that way then backward compatibility would not make any sense. You have to recompile chunkCode only if you brake the API, that is remove some functionality that chunkCode is using, changing calling conventions, modifying number of parameters, these sort of things == breaking changes.

For the second I usually, but only if I really have to, use dynamic_cast in those situations.

Note my answer is valid in the context of C++;I just saw the question is language agnostic(kind of tired at this hour; I'll remove the answer if it offenses anybody).

Cast from interface to class, bad design or small violation?

The general rule of thumb is if you are going to expose your API through interfaces, you should uses interfaces throughout. Your interfaces should only include things you want to publicly expose. If it's something you just need inside of the implementation of that interface it goes in the class.

The other part, "it depends". Usually with the way you are headed, at some point, you're going to want a collection of all of those implementations and so you would need to refer to them by the common base interface/class.

EDIT: if you find that you need to cast interfaces from the base class, you are "probably" doing something wrong. If multiple interfaces have the same method, it belongs in the base interface. You can do this with generics.

If you have a scenario where the derived classes need to do something different from the base class, then you should use virtual methods and overrides.

Adding something into a derived class is fine as long as it doesn't change the interface which it shouldn't since if you are using interfaces, you generally don't want to expose the implementation classes.



Related Topics



Leave a reply



Submit