I was reading about LSP (Liskov Substitution Principle) in a book called Clean Architecture: A Craftsman's Guide to Software Structure and Design. I have a question regarding how this would be implemented in C++.
On page 95, there is a figure explaining LSP using a simple example:
My interpretation of the figure in C++:
// License.h
class License {
public:
virtual calcFee();
};
// PersonalLicense.h
#include "License.h"
class PersonalLicense : public License {
};
// BusinessLicense.h
#include "License.h"
class BusinessLicense : public License{
private:
someDataType users;
};
To my understanding, Billing
will be using PersonalLicense
and BusinessLicense
(and other derivatives) potentially, so Billing.h
will contain #include-s for all their header files:
// Billing.h
#include "PersonalLicense.h"
#include "BusinessLicense.h"
...
My concern is that
a) if there are a lot of License derivatives, Billing.h will have to include all of them, and
b) it looks like Billing.h will have to be edited to include every new kind of License.
Is this the case? Or am I missing something?
Update
After reading the answer by Ryathal, I am now under the impression that I misunderstood the above figure. I was understanding the diagram as Billing
has a License
, which doesn't seem to be correct.
The aforementioned answer says that "This would be used in something like a shopping cart that does have references to all the different license types". This makes me think that the original diagram is incorrect, and that it should look like this instead (ShoppingCart
has a License
).
Assumptios based on the above
- class
License
is defined in file namedLicense.h
. - class
PersonalLicense
is defined in file namedPersonalLicense.h
and includesLicense.h
. - class
BusinessLicense
is defined in file namedBusinessLicense.h
and includesLicense.h
. - class
ShoppingCart
is defined in file namedShoppingCart.h
and its member function has expressions as such:
...
list<License*> orders;
orders.add(new PersonalLicense());
orders.add(new BusinessLicense());
...
Questions
- Which of the diagrams is correct, if any?
- Is the diagram possible to implement using C++?
- If we have multiple
License
types, let's say 5 ~ 10, do we have to include each header intoShoppingCart.h
? Or is there any way of including as little headers as possible? I'm unsure how all this works in practice.
License
types" <- even if you have thousands of license types in your system, you almost certainly shouldn't have thousands of license classes. This is an indication you are missing a layer (or more than one) of abstraction.License
types was just an way of explaining my question. If there is future plan for moreLicense
types which are defined as classes, such asSchoolLicense
,EducationLicense
,DiscountedLicense
, andFreeLicense
, will it be just including all headers into theBilling.h
?main()
function is) where you'd create the Billing object by passing to it an instance of a concrete license subtype - you'd include the header file of that subtype there. Billing's constructor expects a License, but it will accept any subtype of License.Billing
shall not know or include any of following License types as well as that is the whole point of this diagram. However, I cannot think of any other ways of solving this problem and implementing this diagram with C++ while not including any of thePersonalLicense.h
orBusinessLicense.h
. Thus I was asking for "efficient way of solving this question" with this question.