Clean Architecture — OOP
A chapter in which Uncle Bob tells us more about the object-oriented programming paradigm.
About this article
This is a part of my series of articles where I go chapter-by-chapter through the “Clean Architecture” by Robert.C.Martin and share my thoughts, analysis and pieces of knowledge I’ve gathered. Previous part can be found here.
The three great pillars
What is OO?
Just like any other programming paradigm it’s a set of restrictions imposed upon a programmer. In case of of OOP there are three of them that must be followed. These magic rules are called encapsulation, inheritance and polymorphism.
The implication is that OO is the proper admixture of these three things, and any truly OO language must support them.
Encapsulation
In object oriented programming languages, encapsulation is used to hide the values or state of a structured data object inside a class, preventing unauthorized parties’ direct access to them.
Ironically, the best example of the perfect implementation of encapsulation is not an OOP language, it’s the C language. Separation of code into header and implementation files guaranteed the perfect separation of knowledge about the implementation. Users of .h have absolutely no knowledge about how it’s actually implemented nor do they have access to the members of the implementation files.
Modern OOP languages, starting with C++, abandoned this perfection for the technical reasons related to how compilers are implemented. In Java and C#, for example, it’s impossible to separate the declaration and definition of a class. The best substitute we have are interfaces.
In the end, modern languages depend heavily on the disciple of a programmer. It’s up to developers to abide the encapsulation rule in their code.
Inheritance
In object-oriented programming, inheritance is the mechanism of basing an object or class upon another object or class , retaining similar implementation.
To put it simple, inheritance allows us to reuse old code, by accessing the functionality of a old class in the inheriting class. This was also somewhat doable in C, however it was not a feature of C but rather a hack-y workaround,. What’s more, C didn’t support multiple inheritance.
Inheritance’s main application is in code reuse. By default the subclass (inheriting class) retains all of the operations of the base class, but the subclass may override some or all operations, replacing or extending the base-class implementation with its own.
In modern days, more and more programmers vote for using composition over inheritance for multiple reasons.
Polymorphism
In programming languages and type theory, polymorphism is the provision of a single interface to entities of different types or the use of a single symbol to represent multiple different types.
Polymorphism is perhaps the grates advantage of OOP. The two other pillars could be achieved in non-OO languages in some hack-y but reasonably safe way. Multiple inheritance wasn’t there but at the same time people could easily live without it. However, when it comes to polymorphism the game is completely different.
In the early days there were pointers to functions, these pointers were used to achieve exactly the same what OOP’s polymorphism is. In fact, most modern languages use pointers to functions in their implementation of polymorphism.
So what is this great advantage that languages like Java and C++ have brought us? Well, OOP may not have come up with anything new but it has given us safety in using these pointers. As any programmer knows, pointers can be dangerous, they can lead to many unforeseen consequences if used incorrectly. OO languages eliminate this risk by taking pointers to functions away from programmers and wrapping them in a safe language-based environment.
The fact that OO languages provide safe and convenient polymorphism means that any source code dependency, no matter where it is, can be inverted.
Dependency inversion
Polymorphism allowed OO languages to introduce dependency inversion, which in short words is the ability for the software architect to point the source code dependency in any direction.
This allows programs to be built as plugins to any central logic. For example, your logic doesn’t have to know how either UI or datasource are implemented, all it needs are some interfaces. Thanks to this, modules can be developed independently by different teams. That’s independent developability, and it’s crazy useful when working with bigger projects.
Summary
I encourage you to share your feedback and point of view with me, it’s the best way for all of us to learn and grow. Also, check out the complete book, it’s a really wonderful source of knowledge for any developer. My articles are just a shallow summary of information that can be found in this book, do yourself a favor and read it all! Next part can be found here.
