Comment apprendre la conception et l'architecture logicielles - une feuille de route

Cet article est un résumé de ce que j'écris dans mon dernier projet, solidbook.io - Le manuel de conception et d'architecture logicielles avec TypeScript. Vérifiez-le vous aimez ce post.

C'est fou pour moi de considérer le fait que Facebook était autrefois un fichier texte vide sur l'ordinateur de quelqu'un.

Lol.

Cette dernière année, j'ai travaillé dur dans la conception et l'architecture de logiciels, la conception axée sur le domaine, et j'ai écrit un livre dessus, et je voulais prendre un moment pour essayer de le reconstituer en quelque chose d'utile que je pourrais partager avec la communauté .

Voici ma feuille de route pour apprendre la conception et l'architecture de logiciels.

Je l'ai décomposé en deux artefacts: la pile et la carte .

La pile

Semblable au modèle OSI en réseau, chaque couche se construit au-dessus de la fondation de la précédente.

La pile

La carte

Bien que je pense que la pile est bonne pour voir une vue d'ensemble de la façon dont tout fonctionne ensemble, la carte est un peu plus détaillée (et inspirée de la feuille de route des développeurs Web) et, par conséquent, je pense que c'est plus utile.

La voici ci-dessous! Pour bifurquer le repo, lisez mon article détaillé et téléchargez-le en haute résolution, cliquez ici.

Feuille de route pour la conception et l'architecture logicielles

Étape 1: nettoyer le code

La toute première étape vers la création de logiciels durables consiste à trouver comment écrire du code propre .

Un code propre est un code facile à comprendre et à modifier. Au bas niveau, cela se manifeste par quelques choix de conception tels que:

  • être cohérent
  • préférer les noms de variables, de méthodes et de classes significatifs à l'écriture de commentaires
  • s'assurer que le code est indenté et espacé correctement
  • s'assurer que tous les tests peuvent être exécutés
  • écrire des fonctions pures sans effets secondaires
  • ne pas passer null

L'écriture de code propre est extrêmement importante.

Pensez-y comme un jeu de jenga.

Afin de maintenir la structure de notre projet stable dans le temps, des choses comme l'indentation, les petites classes et méthodes, et les noms significatifs, sont très rentables à long terme.

La meilleure ressource pour apprendre à écrire du code propre est le livre d'oncle Bob, "Clean Code".

Étape 2: Paradigmes de programmation

Maintenant que nous écrivons du code lisible et facile à maintenir, ce serait une bonne idée de vraiment comprendre les 3 principaux paradigmes de programmation et la façon dont ils influencent la façon dont nous écrivons le code.

Dans le livre de l'oncle Bob, "Clean Architecture", il attire l'attention sur le fait que:

  • La programmation orientée objet est l'outil le mieux adapté pour définir comment nous traversons les frontières architecturales avec le polymorhpisme et les plugins
  • La programmation fonctionnelle est l'outil que nous utilisons pour pousser les données aux limites de nos applications
  • et la programmation structurée est l'outil que nous utilisons pour écrire des algorithmes

Cela implique qu'un logiciel efficace utilise un hybride des 3 styles de paradigmes de programmation à des moments différents.

Bien que vous puissiez adopter une approche strictement fonctionnelle ou strictement orientée objet pour écrire du code, comprendre où chacun excelle améliorera la qualité de vos conceptions.

Si tout ce que vous avez est un marteau, tout ressemble à un clou.

Ressources

Pour la programmation fonctionnelle , consultez:

  • Le guide le plus adéquat de la programmation fonctionnelle du professeur Frisby
  • Modélisation de domaine rendue fonctionnelle

Étape 3: Programmation orientée objet

Il est important de savoir comment chacun des paradigmes fonctionne et comment ils vous incitent à structurer le code en leur sein, mais en ce qui concerne l'architecture, la programmation orientée objet est l' outil clair pour le travail .

Non seulement la programmation orientée objet nous permet de créer une architecture de plugins et d' intégrer de la flexibilité dans nos projets; La POO est fournie avec les 4 principes de la POO (encapsulation, héritage, polymorhisme et abstraction) qui nous aident à créer des modèles de domaine riches .

La plupart des développeurs qui apprennent la programmation orientée objet ne parviennent jamais à cette partie: apprendre à créer une implémentation logicielle du domaine problématique et à la localiser au centre d'une application Web en couches .

La programmation fonctionnelle peut sembler être le moyen à toutes les fins dans ce scénario, mais je recommanderais de se familiariser avec la conception axée sur les modèles et la conception axée sur le domaine pour comprendre la façon dont les modélisateurs d'objets sont capables d'encapsuler une entreprise entière dans un modèle de domaine sans dépendance.

Pourquoi est-ce un gros problème?

C'est énorme parce que si vous pouvez créer un modèle mental d'une entreprise, vous pouvez créer une implémentation logicielle de cette entreprise.

Étape 4: principes de conception

À ce stade, vous comprenez que la programmation orientée objet est très utile pour encapsuler des modèles de domaines riches et résoudre le 3ème type de «problèmes logiciels durs» - les domaines complexes.

Mais la POO peut présenter certains défis de conception.

Quand dois-je utiliser la composition?

Quand dois-je utiliser l'héritage?

Quand dois-je utiliser une classe abstraite?

Les principes de conception sont des meilleures pratiques orientées objet bien établies et testées au combat que vous utilisez comme garde-corps.

Voici quelques exemples de principes de conception courants avec lesquels vous devez vous familiariser:

  • La composition plutôt que l'héritage
  • Encapsulez ce qui varie
  • Programme contre des abstractions, pas des concrétions
  • Le principe hollywoodien: "Ne nous appelez pas, nous vous appellerons"
  • Les principes SOLID, en particulier le principe de responsabilité unique
  • SEC (Ne vous répétez pas)
  • YAGNI (Tu n'en auras pas besoin)

Assurez-vous cependant de tirer vos propres conclusions. Ne vous contentez pas de suivre ce que quelqu'un dit que vous devriez faire. Assurez-vous que cela a du sens pour vous.

Étape 5: Modèles de conception

Presque tous les problèmes logiciels ont déjà été classés et résolus. Nous appelons ces modèles: des modèles de conception, en fait.

Il existe 3 catégories de modèles de conception: création , structure et comportement .

Créatif

Les modèles de création sont des modèles qui contrôlent la façon dont les objets sont créés.

Voici des exemples de modèles de création:

  • Le modèle Singleton , pour garantir qu'une seule instance d'une classe peut exister
  • Le pattern Abstract Factory , pour créer une instance de plusieurs familles de classes
  • Le modèle Prototype , pour démarrer avec une instance clonée à partir d'une instance existante

De construction

Les modèles structurels sont des modèles qui simplifient la façon dont nous définissons les relations entre les composants.

Voici des exemples de modèles de conception structurelle:

  • Le modèle d'adaptateur , pour créer une interface permettant aux classes qui ne peuvent normalement pas fonctionner ensemble, de fonctionner ensemble.
  • Le modèle Bridge , pour diviser une classe qui devrait en fait être une ou plusieurs, en un ensemble de classes appartenant à une hiérarchie, permettant aux implémentations d'être développées indépendamment les unes des autres.
  • Le modèle Decorator , pour ajouter des responsabilités aux objets de manière dynamique.

Comportementale

Les modèles de comportement sont des modèles courants pour faciliter une communication élégante entre les objets.

Des exemples de modèles de comportement sont:

  • Le modèle de modèle , pour reporter les étapes exactes d'un algorithme à une sous-classe.
  • Le modèle Mediator , pour définir les canaux de communication exacts autorisés entre les classes.
  • Le modèle Observer , pour permettre aux classes de s'abonner à quelque chose qui les intéresse et d'être notifiées lorsqu'un changement s'est produit

Critiques des modèles de conception

Les modèles de conception sont excellents et tous, mais ils peuvent parfois compliquer davantage nos conceptions. Il est important de se souvenir de YAGNI et d'essayer de garder nos designs aussi simples que possible. N'utilisez les modèles de conception que lorsque vous êtes vraiment sûr d'en avoir besoin. Vous saurez quand vous le ferez.

Si nous savons ce que sont chacun de ces modèles, quand les utiliser et quand même ne pas prendre la peine de les utiliser, nous sommes en bonne forme pour commencer à comprendre comment concevoir des systèmes plus grands.

La raison en est que les modèles architecturaux ne sont que des modèles de conception agrandis à l'échelle du haut niveau , où les modèles de conception sont des implémentations de bas niveau (plus proches des classes et des fonctions).

Ressources

Refactoring Guru - Modèles de conception

Étape 6: Principes architecturaux

Maintenant, nous sommes à un niveau de réflexion supérieur au niveau de la classe.

Nous comprenons maintenant que les décisions que nous prenons pour organiser et établir des relations entre les composants de haut niveau et de bas niveau auront un impact significatif sur la maintenabilité, la flexibilité et la testabilité de notre projet.

Apprenez les principes directeurs qui vous aident à intégrer la flexibilité dont votre base de code a besoin afin de pouvoir réagir aux nouvelles fonctionnalités et exigences, avec le moins d'effort possible.

Voici ce que je recommanderais d'apprendre dès le départ:

  • Principes de conception des composants: le principe d'abstraction stable, le principe de dépendance stable et le principe de dépendance acyclique, pour savoir comment organiser les composants, leurs dépendances, quand les coupler et les implications de la création accidentelle de cycles de dépendance et de l'utilisation de composants instables.
  • Stratégie vs détail, pour comprendre comment séparer les règles de votre application des détails de mise en œuvre.
  • Limites et comment identifier les sous-domaines auxquels appartiennent les fonctionnalités de votre application.

L'oncle Bob a découvert et documenté à l'origine plusieurs de ces principes, donc la meilleure ressource pour en savoir plus est à nouveau "Clean Architecture".

Étape 7: Styles architecturaux

L'architecture concerne ce qui compte.

Il s'agit d'identifier ce dont un système a besoin pour réussir, puis d'empiler les chances de succès en choisissant l'architecture qui correspond le mieux aux exigences.

Par exemple, un système qui a beaucoup de complexité de logique métier gagnerait à utiliser une architecture en couches pour encapsuler cette complexité.

Un système comme Uber doit être capable de gérer de nombreux événements en temps réel à la fois et de mettre à jour les emplacements des pilotes, de sorte qu'une architecture de style publication-abonnement pourrait être la plus efficace.

Je me répète ici car il est important de noter que les 3 catégories de styles architecturaux sont similaires aux 3 catégories de modèles de conception, car les styles architecturaux sont des modèles de conception de haut niveau .

Structurel

Les projets avec différents niveaux de composants et des fonctionnalités étendues bénéficieront ou souffriront de l'adoption d'une architecture structurelle.

Voici quelques exemples:

  • Les architectures basées sur les composants mettent l'accent sur la séparation des préoccupations entre les composants individuels d' un système. Pensez à Google pendant une seconde. Considérez le nombre d'applications dont ils disposent au sein de leur entreprise (Google Docs, Google Drive, Google Maps, etc.). Pour les plates-formes dotées de nombreuses fonctionnalités, les architectures basées sur les composants divisent les préoccupations en composants indépendants faiblement couplés. C'est une séparation horizontale .
  • Monolithique signifie que l'application est combinée en une plate-forme ou un programme unique, déployé dans son ensemble. Remarque: Vous pouvez avoir une architecture basée sur des composants ET monolithique si vous séparez correctement vos applications, tout en les déployant en une seule pièce .
  • Les architectures en couches séparent les problèmes verticalement en découpant les logiciels en couches d'infrastructure, d'application et de domaine.

Architecture propre

Un exemple de découpage vertical des préoccupations d'une application en utilisant une architecture en couches. Lisez ici pour plus d'informations sur la façon de procéder.

Messagerie

En fonction de votre projet, la messagerie peut être un élément très important du succès du système. Pour des projets comme celui-ci, les architectures basées sur les messages reposent sur des principes de programmation fonctionnelle et des modèles de conception comportementale tels que le modèle d'observateur.

Voici quelques exemples de styles architecturaux basés sur des messages:

  • Les architectures pilotées par les événements considèrent toutes les modifications importantes de l'état comme des événements. Par exemple, dans une application de trading de vinyle, l'état d'une offre peut passer de «en attente» à «accepté» lorsque les deux parties s'accordent sur l'échange.
  • Les architectures de publication-abonnement s'appuient sur le modèle de conception d'Observer en en faisant la principale méthode de communication entre le système lui-même, les utilisateurs finaux / clients et d'autres systèmes et composants.

Distribué

Une architecture distribuée signifie simplement que les composants du système sont déployés séparément et fonctionnent en communiquant via un protocole réseau. Les systèmes distribués peuvent être très efficaces pour faire évoluer le débit, faire évoluer les équipes et déléguer (des tâches potentiellement coûteuses ou) des responsabilités à d'autres composants.

Voici quelques exemples de styles architecturaux distribués:

  • Architecture client-serveur . Une des architectures les plus courantes, où l'on répartit le travail à effectuer entre le client (présentation) et le serveur (logique métier).
  • Les architectures peer-to-peer répartissent les tâches de la couche application entre des participants également privilégiés, formant un réseau peer-to-peer.

Étape 8: Modèles architecturaux

Les modèles architecturaux expliquent plus en détail tactique comment mettre en œuvre l'un de ces styles architecturaux .

Voici quelques exemples de modèles architecturaux et des styles dont ils héritent:

  • La conception pilotée par domaine est une approche du développement de logiciels contre des domaines de problèmes très complexes. Pour que DDD réussisse le mieux, nous devons implémenter une architecture en couches afin de séparer les préoccupations d'un modèle de domaine des détails infrastruraux qui font réellement fonctionner l'application, comme les bases de données, les serveurs Web, les caches, etc.
  • Model-View Controller est probablement le modèle architectural le plus connu pour le développement d'applications basées sur une interface utilisateur. Cela fonctionne en divisant l'application en 3 composants: modèle, vue et contrôleur. MVC est incroyablement utile lorsque vous débutez, et il vous aide à utiliser d'autres architectures, mais à un moment donné, nous réalisons que MVC n'est pas suffisant pour les problèmes avec beaucoup de logique métier.
  • Le sourcing événementiel est une approche fonctionnelle où nous ne stockons que les transactions, et jamais l'état. Si jamais nous avons besoin de l'état, nous pouvons appliquer toutes les transactions depuis le début des temps.

Étape 9: Modèles d'entreprise

Tout modèle architectural que vous choisissez introduira un certain nombre de constructions et de jargon technique pour vous familiariser avec et décider si cela vaut la peine de l'utiliser ou non.

Prenant un exemple que beaucoup d'entre nous connaissent, dans MVC , la vue contient tout le code de la couche de présentation, le contrôleur traduit les commandes et les requêtes de la vue en requêtes qui sont gérées par le modèle et renvoyées par le contrôleur .

Où dans le modèle (M) traitons-nous ces choses?:

  • logique de validation
  • règles invariantes
  • événements de domaine
  • cas d'utilisation
  • requêtes complexes
  • et logique métier

Si nous utilisons simplement un ORM (object-relational mapper) comme Sequelize ou TypeORM comme modèle , tout ce qui est important est laissé à l'interprétation sur où il devrait aller, et il se retrouve dans une couche non spécifiée entre (ce qui devrait être un ) modèle et le contrôleur .

mvc-2

Tiré de "3.1 - Modèles Slim (sans logique)" dans solidbook.io.

S'il y a quelque chose que j'ai appris jusqu'à présent dans mon voyage au-delà de MVC, c'est qu'il y a une construction pour tout .

Pour chacun de ces problèmes que MVC ne parvient pas à résoudre, il existe d'autres modèles d'entreprise pour les résoudre. Par exemple:

  • Les entités décrivent des modèles qui ont une identité.
  • Les objets de valeur sont des modèles qui n'ont aucune identité et peuvent être utilisés pour encapsuler la logique de validation.
  • Les événements de domaine sont des événements qui signifient que certains événements commerciaux pertinents se produisent et auxquels vous pouvez vous abonner à partir d'autres composants.

Selon le style architectural que vous avez choisi, il y aura une tonne d'autres modèles d'entreprise à apprendre afin de mettre en œuvre ce modèle à son plein potentiel.

Modèles d'intégration

Une fois que votre application est opérationnelle et que vous obtenez de plus en plus d'utilisateurs, vous pouvez rencontrer des problèmes de performances. Les appels d'API peuvent prendre beaucoup de temps, les serveurs peuvent tomber en panne à cause de la surcharge de requêtes, etc. Pour résoudre ces problèmes, vous pouvez lire sur l'intégration d'éléments tels que les files d'attente de messages ou les caches afin d'améliorer les performances.

C'est probablement la chose la plus difficile: la mise à l'échelle, les audits et les performances .

La conception d'un système à l' échelle peut être extrêmement difficile. Cela nécessite une compréhension approfondie des limites de chaque composant au sein de l'architecture et un plan d'action sur la manière d'atténuer le stress sur votre architecture et de continuer à répondre aux demandes dans des situations de trafic élevé.

La nécessité également de vérifier ce qui se passe dans votre application. Les grandes entreprises doivent pouvoir effectuer des audits afin d'identifier les problèmes de sécurité potentiels, comprendre comment les utilisateurs utilisent leurs applications et avoir un journal de tout ce qui s'est passé.

Cela peut être difficile à mettre en œuvre, mais les architectures courantes finissent par être basées sur des événements et s'appuient sur un large éventail de concepts, de principes et de pratiques de conception de logiciels et de systèmes tels que Event Storming, DDD, CQRS (ségrégation des réponses aux requêtes de commandes) et Event Sourcing. .

J'espère que cela vous a été utile!

Faites-moi savoir si vous avez des suggestions ou des questions.

À votre santé!

Forkez-le sur GitHub

Lisez le livre sur la conception et l'architecture de logiciels

Lire la rédaction

khalilstemmler.com - J'enseigne les meilleures pratiques Advanced TypeScript & Node.js pour les applications à grande échelle et comment écrire des logiciels flexibles et maintenables.