Skip to content

Instantly share code, notes, and snippets.

@fxfabre
Created November 12, 2018 17:41
Show Gist options
  • Save fxfabre/c69010d3a8d3e7831023f53ee6f366e4 to your computer and use it in GitHub Desktop.
Save fxfabre/c69010d3a8d3e7831023f53ee6f366e4 to your computer and use it in GitHub Desktop.

Clean Architecture: A Craftsman's Guide to Software Structure and Design

Developers are overconfident in their ability to remain productive. But the mess of code will reduce productivity to 0 in few month. Making mess is always slower than clean, even in the short term. The developers may think the answer is to start over from scratch. But it will lead to the same mess.

Software provides 2 different values : behavior and structure (architecture). A software (and developer) is evaluated on the behavior -> bad architecture. But bad architecture -> uneasy / impossible to change -> bad behavior.

Les requêtes business 'urgentes' sont rarement importantes.

Paradigmes : structured programming, object oriented programming, functional programming.

  • Structured : if / then / else, do / while (instead of goto)
  • OO programming : use a heap : scope des var plus restreint a une fonction.
  • Functional : données immutables, no assignments.

=> Chaque paradigme enlève de la liberté au dev -> bonnes pratiques.

Dijkstra, pendant qu'il travaillait comme développeur, a essayé de décomposer tout programme en suite de lemmes -> factorisation de code -> création des if / then / else, while, for ...

OO programs provides safe and convenient polymorphism -> any source code dependency can be inverted (call an interface instead of an object at compile time).
OO is the ability, through the use of polymorphism, to gain absolute control over every source code dependency. Interfaces are the contract to follow.

Functional languages.

Variables, in functional languages, do not vary.
=> No race condition, deadlock condition and concurrent update problems.

Event sourcing : store the transaction / operations, not the state.

Ex : store initial account status / balance + all transactions on this account.
=> no need of mutable var.

Design principes

  • Single responsibility principe : Each software module has 1 and only 1 reason to change.
  • Open closed principle : software must allow to be changed by adding new code rather than changing existing code.
  • Liskov substitution principle : software parts must adhere to a contract that allows those parts to be substituted one for another.
  • Interface segregation principle : avoid depending on things that they don't use.
  • Dependency inversion principle : high level policy should not depend on low levels details.

Single responsibility principle (SRP) :

A module should have 1 and only 1 reason to change

ie : un module doit dépendre :

  • soit de l'utilisateur, soit du client.
  • d'une seule personne liée à l'application
  • soit de problématiques techniques (comme accès a la DB)
  • soit de problématiques fonctionnelles.

Exemple : Une class Employee ne doit pas dépendre :

  • RH pour calcul de la paye
  • Manager pour les horaires de travail
  • DBA pour sauvegarde en base.

=> Utiliser héritage multiple, design pattern facade et diviser en différentes classes.
=> SRP au niveau des fonctions et des classes.

Open close principle (OCP) :

A software artifact should be extensible without having to modify it.

If component A should be protected from changes in component B, then component B should depend on component A.

=> To protect the controller from changes in the presenter, the presenter should depend on the controller. open closed principle

Exemple d'architecture pour une application de reporting financier (p 72- 73).
Le financial report interactor contient les règles business et ne dépend de aucun module
=> Ne change que si changement des règles business (SRP), réalisé grace à une inversion de dépendance.

The Liskov substitution principle (LSP)

Plusieurs modules qui utilisent la même interface peuvent interchangeables.

The interface segregation principle (ISP)

Ne pas dépendre d'un module qui intégre plus de fonctionnalités que ce que l'on utilise.

Dependency inversion principle (DIP)

Use import and include statement should refer only to modules containing interfaces or abstract classes - Nothing concrete.

Class like string are very stable. Don't try to avoid those concrete dependencies.
Interfaces are less volatile than implémentations.

  • Don't refer to volatile concrete class
  • Don't derive from volatile concrete class
  • Don't override concrete function -> make the function abstract and create multiple implementations
  • Never mention the name of anything concrete and volatile

Stable abstraction principle (SAP)

  • si doit être stable -> interface ou class abstraite
  • si doit être flexible -> concret

Zone of pain : module stable (utilisé par d'autres composants) et concret.

  • tres difficile a faire évoluer
  • Généralement le cas des DAL (data access layer)

Zone of uselessness : abstract and not used
=> a supprimer, mais pas toujours évident à détecter

Bonne architecture : retarde les choix au maximum

  • Indépendant base de données
  • Indépendant format d'entrée / format de sortie
  • Indépendant du framework d'injection de dépendances
  • ...

=> permet d'ajouter facilement de nouvelles fonctionnalités, permet de réduire la maintenance.

Architectural layers (horizontal) :

  • User interface (UI)
  • Application specific business rules. Ex : validation of input fields
  • Application independant business rules. Ex : generic calculations.
  • Database

Use cases (vertical) :

  • separate the UI for the use case 1 from the UI for use case 2

Decoupling mode : should be able to run :

  • mono thread
  • multi thread
  • spread on many servers (SOA), micro services

Duplications :

  • True duplication is a bad thing : when every change to one instance necessitate the same change to every duplicate
  • False / accidental duplication is not bad : They change at different rates, for different reasons and will eventually be completely different. Don't remove it if it breaks modules independancy.

Références externes :

https://gist.github.com/ygrenzinger/14812a56b9221c9feca0b3621518635b

https://blog.xebia.fr/2016/03/16/perennisez-votre-metier-avec-larchitecture-hexagonale/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment