Search code examples
oopinheritanceumlclass-diagramsolid-principles

Which of the SOLID principles is violated in this class diagram


This is one of the past year's exams that have no answers:
[1]: https://i.sstatic.net/RDzz0.jpg

It shows a diagram with two classes, Customer and Supplier, inheriting both from a class Partner. Another class Customer_Supplier inherits from both, Customer and Supplier.

The question asks what SOLID principle this design would violate. Despite attentive verification, I could not find any, and would really like to know.


Solution

  • The following diagram is the famous diamond of death, a very delicate problem when working with multiple inheritance:

    enter image description here

    The academic answer

    The academic answer to your question is that this design violates the Single Responsibility Principle. The reasoning is the following:

    • A class should have a single responsibility
    • Supplier and Customer both have a single responsibility
    • Customer_Supplier inherits of at least two responsibilities

    In reality, the SRP is about reason to change. But the general tendency is to apply the same reasoning: Customer_Supplier might have to change because of changes in Supplier or changes in Customer.

    Elimination of the other candidates

    It is in principle compliant with the Open/Close Principle by design. Each class could be extended, and unless the contrary is proven, there is no need to modify them.

    A class diagram is rarely sufficient to confirm or deny compliance with the Liskov Substitution Principle, since this principle is about the contracts/promises of the classes and their subclasses. LSP requires that an object of the subclass can be used whenever an object of the superclass is expected. At first sight, a Customer_Supplier could be used instead of a Supplier, as well as instead of a Customer. Of course, one could easily imagine a class that breaks this. But this is equally true with any of the simplest inheritance. The fact is that nothing in the diagram lets us assume the opposite.

    The Interface Segregation Principle is not violated either. On contrary, if a client does not need the Customer_Supplier interface, you could use one of the parent classes. If you use the Customer_Supplier in a client, it's probably because you need the full interface.

    Finally, the Dependency Inversion Principle is not relevant here. Nothing indicates that one class is more concrete or more abstract than the other. In fact, these could even all be abstract classes. So there is no reason to think that this design does not comply with "Abstractions should not depend on details. Details (concrete implementations) should depend on abstractions".

    Is the academic answer is flawed?

    The diamond of death is an extreme case that is often given as example to explain that multiple inheritance would be bad. And multiple inheritance can easily be misused. But so can be single inheritance and any other programming construct.

    Let's bring in some more objectivity:

    • Classes should have a single responsibility. If a class inherits from another it may then have two responsibilities: its own and the responsibility of the superclass. On the other side, nothing tells us that these responsibilities are independent: one could be a sub-responsibility of the other.
    • Consequently, if Supplier has a sub-responsibility of BusinessPartner, and Customer has a sub-responsibility of BusinessPartner, they both have the sub-responsibilities of the same larger responsibility, especially considering the Open/Closed principle. This means that Customer_Supplier could in the end still just be a sub-responsibility of this single large responsibility. So SRP could perfectly be respected.

    This is not advanced computer science, but basic set theory. You can use the same reasoning for the reason to change.

    Another reasoning can be used for reason to change: if the subclass uses only the public interface of the superclass (which is a robust practice in view of LSP's history constraint) the subclass would not be impacted by changes to the superclass more than by any other change of a class that its dependent uppon. So the single reason to change could still hold.

    For all these reasons, I'd reformulate the academic answer as follows: if this design would violate a SOLID principle, it could be only the the SRP. Nevertheless it does not necessarily violate it.

    And to hammer the nail, I'll conclude with a quote from R.C. Martin who invented the SRP concept:

    And this gets to the crux of the Single Responsibility Principle. This principle is about people.

    And this design does not say anything about people.

    And to finish with a philosophical question: is multiple inheritance really needed?