Liskov's Substitution Principle


LSP is probably the most consequential of the principles.


Lab time: 15-30 minutes

Objective: Demonstrate how the composite pattern can be used to implement the requirement. Experience the possible violations of LSP

Requirements Change

The customer has indicated that they would like to represent and process subsidiaries. Below is a sample org chart depicting the desired structure:

The GoF design pattern Composite provides a solution for this type of challenge. To implement the Composite pattern, we simply need to derive Company from HumanResource. We will make several other changes to adapt our classes to the new design:

  • Change the name of Company to Organization. This name more correctly can apply to a department or a multi-national corporation
  • Change the name of Hire to Add. While an organization hires people, that term doesn't fit well with the new design
  • The composite pattern suggests that the base class contain child methods (add, remove, etc) even though they don't apply to the leaves in the tree (Employee, Contractor). We will follow this pattern.

To refactor our design, follow the steps below:

  1. It will be much easier to do the refactoring in Visual Studio. Create a new .net core or standard library project and create the classes Organization, HumanResource, HRFactory, Employee and Contractor. Copy and paste the content from the files below into the corresponding files in VS. The project should build with no issues. 
  2. Rename Company to Organization. Use the rename... tool in Visual Studio so that it will update references.
  3. Add HumanResource as the base class of Organization
  4. Since Name & Id are defined in the base class, delete or comment out the name and id fields and properties.
  5. HumanResource only has 1 constructor that takes id and name as arguments. Modify the Organization constructor to chain those to the base class and remove the initialization from the constructor.
  6. Define an empty virtual function in HumanResource for public void Add(params HumanResource[] resources). 
  7. Make the Organization method an override (these methods need to have bodies in the base class so that leaves don't have to override).
  8. Define a do-nothing read-only virtual property public IEnumerable<HumanResource> Resources in HumanResources
  9. Make the Organization property an override
  10. Make Pay an override

Since an organization is-a human resource, it can be added to another organization's resources. This accomplishes the new requirement.

You will need to replace CompanyTest.cs in your project with OrganizationTest.cs, below

If you need a little help, peek at the solution below:

Complete and Continue