Refactor a Swift Codebase Using SOLID Principles — in an Iterative Way | by PTeng | Jun, 2022

Let’s construct a fictitious HR system in Swift

SOLID ideas in software program parlance isn’t just a buzzword however one thing that scalable software program improvement can’t dwell with out.

In a software program’s lifetime, most of the price of the software program improvement is spent on sustaining the software program. In order builders we wish to construct one thing that isn’t brittle however simple to take care of.

These ideas could seem tutorial if you hear about them first however after spending time creating software program in a crew you shortly notice their significance. A few of us might have even not heard of those ideas however possibly following a few of them already in some type or the opposite.

On this article we’ll attempt to construct a fictitious HR system, We’ll iterate over its improvement lifecycle as would occur in the actual world. Every iteration will enhance the code by implementing one of many SOLID ideas. The finished instance will be discovered here.

At some point Lisa walked into Springfield Applied sciences. The supervisor summoned the crew and introduced that they have been going to construct an in-house HR system that will be a path-breaking technique to handle the corporate’s HR processes.

The supervisor needed the system to have the ability to do the next:

  • It ought to have the ability to retailer and retrieve the worker particulars
  • It ought to have the ability to electronic mail pay slips

Lisa in her pleasure seconded himself to do the job and the following day she got here up with the next:

Lisa put this up for peer evaluation and her colleague raised a problem that her code was violating the Single Accountability precept.

The module that Lisa has constructed at the moment has two stakeholders: HR for sustaining the staff and Payroll for producing the payroll.

Think about if HR needed to vary the way in which the Payroll is generated (they needed that as a substitute of simply emailing the Payslip they wish to print it as properly and ship it by snail mail).

This is able to imply that underneath the present design the entire module will should be recompiled affecting Payroll as properly. Equally, if the IT division needed to vary the inner workings of the database the entire module will want recompilation affecting HR!

This precept has just a few meanings, amongst which the next stand out:

A operate or module ought to have just one purpose to vary.

A operate or module ought to have just one stakeholder (eg: HR, Payroll and so on).

Lisa went again to the drafting board and got here up with the next:

We will already see that the code is a lot better now. The inner workings of the EmployeeDatabase and Payroll are extracted out of HRSystems .

Any change that can should be made to them is not going to immediately have an effect on HRSystems module.

This precept states that:

A software program artefact needs to be open for extension however closed for modification.

Whereas Lisa is completely satisfied along with her final spherical of refactoring to evolve to SRP, her boss comes as much as her and says that he needs the Payroll module to have the ability to print the payslip to be posted to the worker together with the present electronic mail that it generates.

So Lisa got here up with the next change:

We will see that due to our adoption to SRP we have been capable of modify the Payroll module with out affecting the HRSystems module. We have been capable of lengthen the capabilities of the HRSystem module with out having to change it immediately.

Having made the earlier change, Lisa’s colleague Moe has made a touch upon her peer-review request that he has heard from the supervisor that they need the flexibility to swap to a unique database system in case the negotiations with the present database vendor don’t go as anticipated.

What it will imply is that Lisa might want to construct her code in order that the modules that aren’t database-related needs to be remoted from any adjustments to the database and the implementations of the database layer.

Liskov substitution precept states that if there are two objects O1 of kind T and O2 of kind U , then a operate F outlined when it comes to O1 ought to behave unchanged if O1 is changed by O2 , when U is kind of T.

Lisa and Moe pair collectively and provide you with the next refactored code:

For the primary time, Lisa and Moe have launched a protocol for what a Database ought to do.

Equally, any references of EmployeeDatabase have been changed by its abstraction,Database . Now we have made the RelationalDatabase and NoSQLDatabase undertake and conform to the Database protocol.

This enables us to have the ability to initialize the HRSystems module with a database implementation of our alternative (RDBMS or NoSQL) with out affecting the system behaviour.

We’re capable of substitute the database with both RDBMS or NoSQL with out affecting the system behaviour.

The system is now developing properly, there’s nonetheless some enchancment that may be performed to the HRSystems module to fulfill the ISP.

This module can doubtlessly be utilized by people who find themselves simply taken with “Worker operations” equally there will be one other group of people who find themselves taken with simply producing “Payroll”.

Because it stands if any of the worker operations want change it’ll additionally have an effect on the payroll operations because the module will should be rebuilt and vice versa.

To beat this drawback we must compose the HRSystems module out of particular person modules. These modules will both do EmployeeOperations or PayrollOperations .

We now have been capable of isolate Worker operations and Payroll operations into their very own modules such that change in every of them doesn’t immediately have an effect on the HRSystems module (even the modules themselves are decoupled).

This helps to fulfill the ISP. The HRSystems module consists of EmployeeOperations & PayrollOperations .

The HRModuleBuilder helps us to construct a HRSystems module by injecting into it the Worker and the Payroll modules at run time.

You probably have managed to observe on until now you can be completely satisfied to know that we now have already glad the Dependency Inversion precept which states that

Supply code modules ought to depend upon abstractions and never implementations. HRSystem module relies upon solely on the summary varieties (protocol) EmployeeOperations and PayrollOperations thus inverting the dependency we’d have in any other case had.

Equally EmployeeModule and PayrollModule depend upon Database abstraction and never an precise Database implementation.

If we draw an arrow from a module to its dependency we see the inversion.

HRSystems → EmployeeOperations ← EmployeeModule (inverted dependency)HRSystems → PayrollOperations ← PayrollModule (inverted dependency)

Beneath is the category relation diagram that we now have lastly arrived at after implementing the SOLID ideas. The whole instance will be discovered here.

A SOLID System

Observations

  • The system is split into modules every having a Single accountability (SRP).
  • Modules like Emp, Pay & DB will be prolonged in isolation with out affecting the opposite modules (OCP)
  • The modules depend upon abstraction of the Database to allow them to be instantiated with any alternative of implementation (LSP).
  • The HRSystems module is composed of Worker and Payroll module, adjustments to both will be performed in isolation with out affecting one another (ISP).
  • There’s a good use of protocols within the system as modules depend upon abstractions and never implementations. HRSystems module is dependent upon EmployeeOperations & PayrollOperations . Equally EmployeeModule & PayrollModule depend upon Database which is an abstraction of the database system. This helps to implement Dependency Inversion (DI).

For any moderately complicated codebase adapting SOLID ideas just isn’t a alternative however a necessity. It permits us to

  • To construct a system that’s modular.
  • The system parts have low coupling.
  • Particular person modules grow to be simple to grasp and purpose about.
  • Adjustments to at least one a part of the system don’t simply have an effect on the opposite components (module isolation).
  • Unit testing of particular person modules turns into simpler (as a result of capacity to inject mock implementations into modules because the modules depend upon abstractions and never implementations).
  • Adjustments will be made with confidence (because of low coupling and larger testability of the code at a decrease degree reasonably than greater up within the testing pyramid).
  • Software program upkeep prices are excessive so we wish to have the ability to have the above options.

More Posts