Explain SOLID Principles from Company perspective(with few Swift codes)

Attempt to elaborate SOLID principles in a better understanding way

Richard Lu
4 min readNov 14, 2019

Let’s get straight into these five principles. (Btw, the name of “SOLID” is formed with first letters of five principles.)

Single Responsibility Principle

A module should have only one responsibility

Like all kinds of departments in a company, every department is defined to take specific tasks. For example, HR department is mainly responsible for recruiting, interviewing and staffing.

Open-Closed Principle

Open for extension but closed for modification(extension without modification in base module)

Staff in the same department should all have some shared common specialties (base module) but there are many different levels and positions in one department, for example, Junior Developer and Senior Developer. Therefore, these roles will have their own specialties extension based on the common ones.

Liskov Substitution Principle

A subclass must be substitutable for its superclass

Here I am going to show some codes to elaborate this concept, but still in kind of a company(team) perspective. I am taking the code review process for example, it usually takes a Senior Developer to do the PR review and approval, however, it’s not necessary to be exact which Senior Developer (substitutable). Instead of using class as superclass and subclass, here I am using protocol and class conforms to protocols, following POP in Swift.

protocol SeniorDeveloper {
func codeReview()
func approvePR()
}
protocol Mentor {
func coachMembers()
}
protocol Manager {
func organize()
}
class TeamLead: SeniorDeveloper, Manager, Mentor {
func codeReview() {
print("PR reviewing by TeamLead")
}
func approvePR() {
print("PR approved by TeamLead")
}
func organize() {...}

func coachMembers() {...}
}class SoftwareMentor: SeniorDeveloper, Mentor {
func codeReview() {
print("PR reviewing by SoftwareMentor")
}

func approvePR() {
print("PR approved by SoftwareMentor")
}
func coachMembers() {...}
}
class StubbedSeniorDeveloper: SeniorDeveloper {
func codeReview() {
print("PR reviewing by Stubbed SeniorDeveloper")
}
func approvePR() {
print("PR approved by Stubbed SeniorDeveloper")
}
}

There are three different position(class) in above codes and they all conforms to SeniorDeveloper protocol and other role-specific protocols. Then we declare CodeReview class to perform PR review and approval process.

class CodeReview {
var senior: SeniorDeveloper
init(senior: SeniorDeveloper) {
self.senior = senior
}
func update(senior: SeniorDeveloper) {
self.senior = senior
}
func PRApproval() {
self.senior.approvePR()
}
func reviewCodesOfPR() {
self.senior.codeReview()
}
}
// Init CodeReview with SoftwareMentor
let codeReview = CodeReview(senior: SoftwareMentor())
codeReview.reviewCodesOfPR()
codeReview.PRApproval()
// Substitute senior role with a TeamLead object
codeReview.update(senior: TeamLead())
codeReview.reviewCodesOfPR()
codeReview.PRApproval()
// Substitute senior role with a StubbedSeniorDeveloper
codeReview.update(senior: StubbedSeniorDeveloper())
codeReview.reviewCodesOfPR()
codeReview.PRApproval()

We first init a CodeReview object with SoftwareMentor object and the review and approve process works perfectly. Then later we substitute the senior role with TeamLead and StubbedSeniorDeveloper , both also works perfectly. Of course, this also benefits in writing tests. Run above codes and will print

PR reviewing by SoftwareMentor
PR approved by SoftwareMentor
PR reviewing by TeamLead
PR approved by TeamLead
PR reviewing by Stubbed SeniorDeveloper
PR approved by Stubbed SeniorDeveloper

Interface Segregation Principle

Any type should not be forced to depend upon protocol requirements that they do not use(Make fine grained specific protocol).

This should be automatically fulfilled if we do above principles right. Like Senior Developer example in above section, we have declared three protocols SeniorDeveloper , Mentor and Manager so every different role only takes on what they need. A Senior Developer is not necessary to take on Manager tasks, that’s what a Team Lead mainly responsible for.

Dependency Inversion Principle

High level module should not dependent on low level module. Both should depend on abstraction

We also fulfilled this principle in above CodeReview example. The senior variable in CodeReview class is not a class but a protocol as type, thus its init function takes injection of SeniorDeveloper type. By doing this, the CodeReview class depend on SeniorDeveloper protocol(abstraction), also those objects we passed into CodeReview ( SoftwareMentor , TeamLead , StubbedSeniorDeveloper ) are all depend on SeniorDeveloper protocol. This fulfilled decoupling modules ( CodeReview class and other classes.)

If we instead declare senior variable in CodeReview class as a specific class, let’s say, StubbedSeniorDeveloper . This will cause module coupling and it won’t be possible to substitute that senior role with TeamLead or SoftwareMentor object, then we will lose flexibility in this mechanism.

Summary

In this article, I am trying to talk about SOLID principles in a different way to help myself (and hopefully you readers) to have a more thorough understanding in this concept. If there are any doubts or questions, please kindly comment below. Thanks for reading.

--

--

Richard Lu

🌞iOS Developer | 🌛2 kids' Daddy | Striving for being awesome day and night