OOP Fundamentals

Class Relationships

Design Principles

Example

What design principle(s) below class is breaking? this is adopted from https://x.com/SumitM_X

class FeeCalculator {
public:
    double calculateFee(Instrument* instrument) {
        if (dynamic_cast<Stock*>(instrument)) {
            return 1.5;
        } else if (dynamic_cast<Bond*>(instrument)) {
            return 2.0;
        } else {
            return 0.0;
        }
    }
};

1. Violation of the Open–Closed Principle (OCP)

OCP: Classes should be open for extension, but closed for modification.

Your calculateFee() method must be edited every time you add a new instrument type:

else if (dynamic_cast&lt;Option*&gt;(instrument)) ...

This means your class is not closed for modification. A single new instrument forces changes in this class.


2. Violation of the Single Responsibility Principle (SRP)

SRP: A class should have only one reason to change.

This mixes instrument type logic with fee logic → one class handling multiple responsibilities.


3. Violation of Polymorphism / Liskov Substitution Principle (LSP)

Instead of using dynamic dispatch, the class:

This breaks proper polymorphism because:


4. Violation of the Dependency Inversion Principle (DIP)

DIP: Depend on abstractions, not concrete types.

This class depends directly on the concrete classes:

Stock
Bond

Making it rigid and fragile.


Correct OOP version (polymorphism)

class Instrument {
public:
    virtual ~Instrument() = default;
    virtual double fee() const = 0;
};

class Stock : public Instrument {
public:
    double fee() const override { return 1.5; }
};

class Bond : public Instrument {
public:
    double fee() const override { return 2.0; }
};

class FeeCalculator {
public:
    double calculateFee(const Instrument* instrument) const {
        return instrument->fee();   // polymorphic call
    }
};