Graduate Program KB

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