Our applications are usually split into more functional units. We try to follow good software engineering practices to make our code as robust and maintainable as possible. There are many ways, how to do it. This series will talk about Module Oriented Architecture, which splits functionality into groups of objects, which we shall call modules. Let this not be mistaken for any kind of specific description for a specific representation in some technology. The term ‘module’ is used here in a very general sense.

Next parts of this series will provide code implementation in Swift. It’s quite general, so it shouldn’t be a hard read for any developer, but it would definitely be the easiest for iOS developers. However, the principle is widely applicable to any client native technology.

SOLID?

Well, yes. Regardless of development paradigms and forms, we adhere to and comply with some basic principles of OOP, which we try to follow as much as possible to create the code that will get as close as possible to the technical and organisational goals. Which are such goals? I would think of at least of the ones below:

Easy to:

read

understand

maintain

debug

test

change

swap parts

add different scenarios

extend existing functionality

add new functionality

Gosh, everything needs to be easy nowadays.. Are we lazy or something? No, it’s all about making our business to run efficiently during the code lifecycle and lifetime, actually.

Single Responsibility principle is probably one of the most used and abused. It’s most important principle to reach most of the goals above to the certain degree. However, on its own, it has limitations which prevent us to progress from better code to great.

Its opposite is monolithic code, which old definitions argue to be more efficient, than fragmented, less coupled, but that would be the case only if we observe speed of execution, which is becoming the least important aspect of app development and delivery, so I won’t spend any time to reason anything, I think the picture is generally clear to all of us.

From Coupled to Loosely Coupled and finally to Decoupled

Following Single Responsibility principle only will fragment our code (in a positive way) into separate, let’s say, modules, classes, functions even, which would definitively make our code easy to:

read

understand

maintain

debug

but sometimes not so easy to:

test

change

and definitively not at all easy to:

swap parts

add different scenarios

extend existing functionality

add new functionality

Coupled

Functionality is distributed through several classes, but types are explicitly referenced

Definitively not so easy to test, because it may prove that some types will not be easy to create mocks for. Still, not critical and still manageable in terms of testing.

Changes are still manageable as long as they are contained in a class. As soon as we want to introduce changes to the whole types, we can get into the trouble, because we shall have to change the code in other classes which references them.

If we would want to add different scenarios, we would have to resort to if-else and switch statements, type checking, flag checking, all the nasty stuff…

Loosely coupled

Classes are connected through interfaces/protocols

This more or less solves all the issues above. We can definitely mock with ease, we can inject actual implementation to a calling object through the interface, thus implementing different scenarios with strategy pattern, apply abstract factories, … all the goodies of OOP.

We solve all the issues …. within the same platform/app/system.

Decoupled

Systems connect through protocols, ruled by conventions, generic and app specific

Nice examples of the above are HTTP, REST, Microservices. The difference is, we don’t talk about the single system anymore, we talk about distributed systems, heterogeneous in terms of technologies used, actually, technologies don’t matter anymore, it’s only about the messages and convention which defines their payload, it’s a vocabulary, dictionary, which is recognised by many sides.

Fine. But what does this have to do with the apps and client architecture? Well, it has. Most of you have already implemented deep links in your app and you could see, how a URL request, formed upon convention was deconstructed and used to activate and call exactly the functionality/classes, that it needed, thus basically establish unilateral connection between your email or web page and your classes in your app, which effectively become URL resource. Magical isn’t it?! :)

URL

The name says it all: it’s universal address of the resource. Add HTTP/REST and you have a convention to asynchronously pass requests and responses between resources. If you can use it to establish a link between different systems, why not use it as a decoupled principle within the same system?

Let’s read about that in the next story of this series, where we shall use everything we spoke about here and create Modules as representation of Decoupled architecture.