Clean Architecture
Chapter 5 - Object-oriented programming
- Object-orientation (OO) makes software easier to understand, being able to model concepts in the real world
- It's implied OO is a mixture of encapsulation, inheritance and polymorphism, an OO language must support these things
Encapsulation
-
Hide information such as data and functions inside a unit / class, restricting access from other parts of the program
-
Ex. of encapsulation in C
- Users of the point.h file have no knowledge of the Point data structure implementation
struct Point; struct Point* makePoint(double x, double y); double distance (struct Point *p1, struct Point *p2);
-
There are public, private and protected keywords which provides weak form of encapsulation
-
OO depends on programmers are well-behaved enough to not circumvent encapsulated data
Inheritance
- Inheritance is the redeclaration of a group of variables and functions within an enclosing scope
- NamedPoint acts like a derivation of the Point data structure, they have the same x, y field
- NamedPoint can "pretend" to be Point as it's a pure superset of Point
- The order of the members are important, x, y being the first two of both structures
struct Point { double x, y; }; struct NamedPoint { double x, y; char* name; }; int main(int ac, char** av) { struct NamedPoint* origin = makeNamedPoint(0.0, 0.0, "origin"); struct NamedPoint* upperRight = makeNamedPoint (1.0, 1.0, "upperRight"); printf("distance=%f\n", distance( (struct Point*) origin, (struct Point*) upperRight)); }
Polymorphism
-
Interfaces for defining a common set of methods, but implemented differently depending on the concrete subclass
-
Ex. STDIN and STDOUT provides 5 standard functions, same for every IO device driver in the UNIX OS]
- FILE is a struct containing function pointers, essentially an interface
struct FILE { void (*open)(char* name, int mode); void (*close)(); int (*read)(); void (*write)(char); void (*seek)(long index, int mode); };
-
OO made polymorphism safer and convenient by eliminating:
- Initialisation to all pointers correctly
- Call all functions through pointers
The power of polymorphism
- Don't need to change the structure of the program
- Does not depend on the specific implementations of the interface
- Ex. Adding a new IO device won't require the main program to recompile, it just needs to meet the specification to become usable
Dependency inversion
-
Before object-oriented programming:
- Function calls: Main --> High-level --> Mid-level --> Low-level
- Same applies for dependencies, main has to import higher level functions to invoke them
- Lack of diversity for software architecture
- Flow of control dictated by behaviour of the system
- Source code dependencies dictated by that flow of control
-
After object-oriented programming with polymorphism:
- Can import an interface rather than a concrete implementation (any of them can be used at runtime)
- Software architects have complete control over the direction of dependencies in the system
- Ex. Can have a DB and UI depend on business rules, rather than the other way
- DB and UI are plugins, which the source code of the business rules aren't concerned with
- Business rules can be deployed independently
- Changes to the plugins don't have an effect on the business rules
- Changes to non-dependent components can be deployed and developed independently by different teams
Conclusion
- OO is the ability to gain control of direction of every source code dependency in the system
- It enables a plugin architecture, high-level modules are independent of low-level modules
- Low-level modules can be developed and deployed independently