Si Vous Construisez des Microservices, Vous Devez Comprendre Ce Qu’est un Contexte Borné

16 mars 2020 · 19 min de lecture

Photo de l’Institut national du cancer sur Unsplash figcaption>

La croissance de l’adoption des microservices a provoqué un regain de popularité de certains modèles de conception de logiciels auparavant négligés. Beaucoup de ces modèles ont été extraits du Domain Driven Design d’Eric Evans, un livre qui traite autant de la structure de l’équipe que de l’architecture logicielle.

Et de ces modèles, le Contexte borné est peut-être le plus important à comprendre. En tant qu’ingénieurs, nous en sommes venus à considérer le contexte borné comme un modèle de conception d’architecture logicielle. Mais c’est parce que nous l’avons un peu coopté par rapport à son utilisation d’origine. Tel qu’utilisé par Evans, le contexte borné est autant un modèle organisationnel que technique.

C’est pourquoi j’en suis venu à considérer le modèle de contexte borné comme une pierre angulaire dans la compréhension des microservices. Pas seulement comment les construire, mais vraiment pourquoi nous les construisons en premier lieu, et comment ils peuvent rendre nos organisations plus performantes. Si nous comprenons ce que sont les Contextes Bornés — si nous adoptons l’état d’esprit du Contexte borné à la fois techniquement et organisationnellement — alors nous pouvons vraiment réussir à construire notre architecture de microservices.

Pourquoi passer aux microservices ?

Pour commencer, faisons un peu d’exercice. Posez-vous cette question: Pourquoi construisons-nous des microservices en premier lieu?

Prenez un moment pour y réfléchir. Quels sont les avantages qui viennent d’abord à l’esprit? Quels sont les principaux problèmes que nous devrions espérer résoudre? Notez quelques réponses, juste pour rester honnête.

Do

Avez-vous votre réponse ? Bien. Relisez-le vous-même. Avez-vous touché les avantages techniques standard? Livraison continue, évolutivité, environnements polyglottes, conteneurs et clouds, et toutes ces bonnes choses ? Grand.

Mais votre réponse principale comprenait-elle quelque chose sur le fait de permettre à votre organisation de fonctionner plus efficacement? Ça devrait. Parce que la création de microservices ne consiste pas à obtenir des avantages techniques. Vraiment, il s’agit d’obtenir des avantages organisationnels. Tout le reste est un détail d’implémentation.

Monolithes =code couplé et équipes couplées

Au fur et à mesure que nos monolithes grossissent, la productivité commence à décliner. Il y a au moins deux raisons principales à cela.

Freiner notre vélocité

Tout d’abord, chaque équipe d’ingénierie contribue à une base de code géante. En tant que telles, les équipes sont confrontées à une probabilité toujours croissante que leur code entre en conflit avec le code des autres. Pour aider à atténuer les problèmes potentiels que cela pourrait causer, nous instituons des procédures — gel du code, périodes de test d’assurance qualité, trains de libération, etc. – qui sont littéralement conçus pour ralentir notre productivité.

Bien entendu, ces procédures empêchent le déploiement rapide des fonctionnalités et des améliorations. Ils nuisent également à la capacité des ingénieurs à se concentrer sur les priorités de leurs équipes. Si un bogue est détecté pendant une période de test, l’équipe responsable doit changer de contexte et se concentrer sur la résolution de ce bogue. Si un bogue grave est détecté en production, l’équipe doit non seulement corriger le bogue, mais aussi passer à travers des cerceaux pour le faire déployer par le prochain train de versions.

Le service de garde devient une aubaine. Si quelque chose ne va pas avec notre monolithe, quelqu’un doit être disponible — jour ou nuit — pour résoudre le problème. Mais qui ? Les grandes organisations avec de grands monolithes sont généralement confrontées à deux choix:

  • Une équipe de gestion des incidents dont le seul travail, triste et désolé au sein de l’organisation est de répondre aux problèmes causés par le code d’autres ingénieurs et de trouver comment les résoudre.
  • Un horaire de garde rotatif, par lequel chaque semaine un ingénieur arbitraire se voit attribuer le triste et désolé travail de devenir responsable de la résolution des problèmes qui sont probablement causés par du code écrit par un autre ingénieur, dans une autre équipe d’ingénierie.

(Mis)organisation de nos équipes

Les monolithes brouillent encore nos organisations d’une autre manière. Toute notre organisation travaille sur le même gros produit. Mais nous devons encore diviser l’organisation en équipes gérables. Nous avons donc tendance à nous tourner vers les rôles fonctionnels pour trouver les limites de l’équipe:

Malheureusement, ce type de structure organisationnelle limite le travail collaboratif. Plutôt que de travailler ensemble pour résoudre le vrai problème (par exemple, comment concevons-nous, construisons-nous et maintenons-nous la fonctionnalité X?) les membres des différents domaines fonctionnels se concentrent simplement sur leur propre partie, jetant métaphoriquement leur travail par-dessus la clôture lorsqu’ils sont terminés. Le potentiel de collaboration et de synergie — où la qualité combinée de l’effort de l’équipe est bien plus que la somme des membres individuels de l’équipe — est perdu.

Il est également truffé de goulots d’étranglement. Lorsque nous organisons nos équipes par domaine fonctionnel, nous aurons naturellement un désalignement des priorités. Disons que l’équipe de gestion des produits a décidé que le processus de paiement de notre monolithe devait être remanié. Ils planifieront du temps avec l’équipe de conception pour mettre sur pied des moqueries. À un moment donné, les simulacres seront terminés et remis à l’équipe frontend pour être mis en œuvre. Bien sûr, l’équipe frontend aura besoin que les API soient implémentées par l’équipe backend, elles seront donc bloquées jusqu’à ce que cela soit terminé. Une fois que l’équipe backend donne la priorité à son travail sur les nouveaux services de paiement, elle constate qu’elle a besoin de l’aide de l’équipe d’administration de la base de données (DBA). Ce qui, bien sûr, a ses propres priorités. Ainsi, l’équipe backend sera bloquée jusqu’à ce qu’une DBA soit libérée.

D’une certaine manière, cette structure organisationnelle ressemble un peu à une architecture logicielle mal conçue et trop couplée… n’est-ce pas?

Microservices = code découplé, équipes découplées

En revanche, une architecture de microservices permet une autonomie d’équipe. Il devient beaucoup plus facile de former des équipes autonomes, qui travaillent efficacement ensemble et qui ne sont pas constamment bloquées par des dépendances à d’autres équipes.

Les équipes peuvent s’approprier pleinement leur travail, de la conception au développement en passant par le déploiement. Chaque membre partage la responsabilité d’atteindre l’objectif de son équipe, de sorte qu’il est incité à participer à plus que « sa part ». J’ai travaillé avec des équipes où les chefs de produits, les concepteurs, les ingénieurs front-end, back-end et mobiles se sont réunis pour concevoir des fonctionnalités de produits, donnant des résultats bien meilleurs que ceux qui auraient pu être obtenus par une seule personne.

L’équipe prend la responsabilité de ses propres artefacts une fois qu’ils sont déployés en production. Cela conduit généralement à un code de meilleure qualité plus facile à dépanner. Pourquoi ça ? Contrairement à un monolithe, les équipes ont tendance à avoir une vision holistique des microservices qu’elles possèdent. Il est donc beaucoup plus facile pour l’équipe d’anticiper les problèmes, d’ajouter une bonne journalisation et des métriques pour résoudre les problèmes lorsqu’ils se produisent, et d’utiliser correctement les modèles de résilience (par exemple, les tentatives, les disjoncteurs et les solutions de secours, etc.) pour éviter les problèmes en premier lieu.

De plus, puisque les équipes ont un sentiment d’appropriation totale de leur travail, maintenir leurs services en bonne santé et fonctionner en production devient moins une question de calendrier de sortie cauchemardesque, et plus de nourrir leur création.

Enfin, les équipes travaillent vers le même objectif, sur le même calendrier. Cela signifie qu’il n’est plus nécessaire de bloquer une personne en attendant que quelqu’un dans un autre domaine fonctionnel se libère.

Nous devons être intentionnels en matière d’autonomie

Mais nous n’obtenons pas ces avantages gratuitement simplement en divisant notre monolithe en microservices. Jetons un coup d’œil à notre première vue naïve d’une architecture de microservices :

Si nous sommes comme la plupart des ingénieurs, notre idée initiale d’une architecture de microservices est, bien, un tas de microservices. Chacun expose une sorte d’API (ReST, peut-être) pour permettre à tout autre service de le lire et d’y écrire.

Au fur et à mesure que nous acquérons de l’expérience, nous apprenons que tous les microservices ne servent pas le même objectif — ou, du moins, ils ne devraient pas le faire. Et donc, tout comme notre monolithe avait été disposé en couches, nous organisons donc nos microservices:

div>

À ce stade, nous avons défini les différents types de microservices et d’applications que nous voulons créer. Grand. Mais nous n’avons toujours pas beaucoup progressé en termes d’autonomie de l’équipe. Chaque microservice devra appartenir à une équipe. Et donc la question se pose: quelles équipes posséderont quels microservices?

Équipes interfonctionnelles

Notre première approche naïve pourrait être d’organiser nos équipes en imitant notre structure d’organisation monolithe :

Ici, nous voyons des équipes (en violet) organisées par fonction: conception UX, ingénierie frontend, ingénierie backend, ingénieurs de données, DBA, QA, etc.

Cela peut sembler juste, au moins au début. Mais prenons un peu de recul et examinons la valeur que nous essayons d’offrir à nos clients. Est-ce notre objectif de construire des choses comme celles-ci pour nos clients?

  • Un tas de schémas de base de données
  • Un tas de maquettes d’interface utilisateur
  • Un tas de microservices qui peuvent parler à une base de données MySQL ?

Pas vraiment. Ce ne sont là que les outils que nous utilisons pour créer de la valeur pour nos clients. La valeur réelle que nous fournissons à nos clients / utilisateurs se présente sous la forme de fonctionnalités telles que:

  • Un catalogue de produits à rechercher
  • Un mécanisme pour placer des articles dans un panier et les acheter ensuite
  • Un système de notification pour alerter les clients de l’état de leurs achats

De même, nous ne voulons pas organiser notre équipe par domaine fonctionnel. Nous devrions plutôt définir nos équipes en fonction de la valeur qu’elles créent pour les clients, c’est-à-dire entre les fonctions, au sein d’équipes interfonctionnelles (les bien nommées).

Avec des équipes interfonctionnelles, tout le monde travaille ensemble pour créer un produit ou une fonctionnalité spécifique, du début à la fin. Tout le monde dans l’équipe a les mêmes objectifs et priorités, donc aucun domaine fonctionnel n’est bloqué par un autre. Le nouveau service d’API backend nécessite-t-il un travail de conception de base de données? Très bien; l’ingénieur backend de l’équipe et le DBA peuvent tous deux hiérarchiser leur travail ensemble.

Au mieux, les équipes interfonctionnelles encouragent les membres à collaborer tout au long de chaque phase du projet. Chaque membre de l’équipe contribue à la conception globale de la fonctionnalité. Les ingénieurs frontend, backend et mobiles définissent conjointement des contrats d’API. Tout le monde teste. Et tout le monde commence à bien connaître son domaine particulier.

Et ainsi, nos structures d’équipe pourraient commencer à ressembler à ceci:

div>

C’est mieux. Mais quelque chose ne va toujours pas.

Bien sûr, nous avons formé des équipes qui seront probablement plus efficaces pour posséder des produits. Mais nous avons toujours adopté une approche descendante pour identifier la topologie des microservices que notre organisation a l’intention de construire. Nous nous retrouvons avec une grande collection de microservices interdépendants, dont la plupart sont couplés ensemble. Nous les avons simplement assignés à différentes équipes à construire.

Cela conduit à des préoccupations telles que:

  • Comment pouvons-nous créer des API qui répondront à tous les besoins actuels et futurs de tout client ? Pouvons-nous encapsuler nos données lorsque l’un de nos services peut être appelé par les services d’une autre équipe?
  • Combien de temps allons-nous perdre à attendre que d’autres équipes implémentent nos dépendances ?
  • Quelles défaillances de nos systèmes pourraient être causées par des défaillances dans d’autres systèmes (défaillances en cascade)?
  • Pouvons-nous contrôler le nombre d’appels auxquels nos services pourraient être impliqués? Pouvons-nous nous assurer que notre organisation ne finit pas par créer des appels synchrones illimités entre les services, entraînant des temps de réponse astronomiques, ou pire (et oui, j’ai vu cela se produire) des appels infiniment récursifs entre les services?
  • Que se passe-t-il si la fonctionnalité ou l’espace de problème spécifique de notre équipe n’est pas bien adapté à la topologie de microservices pré-planifiée ?

Nous avons encore besoin d’une façon de penser différente. Peut-être existe-t-il déjà un modèle à suivre?

Entrez le Contexte borné

Le contexte borné est un modèle de conception clé issu de la conception pilotée par domaine, ou DDD. La compréhension du contexte borné nous aide à former des équipes autonomes et, par extension, des architectures de microservices autonomes.

DDD lui-même décrit une méthodologie de développement de logiciels dans laquelle les individus au sein d’une organisation travaillent ensemble pour définir un langage commun. Dans son livre Domain Driven Design, Eric Evans décrit fréquemment des ingénieurs travaillant avec des propriétaires de produits pour établir un vocabulaire convenu pour décrire des choses telles que des produits, des composants des produits, des actions qu’un produit peut effectuer (ou peut être effectué sur le produit), des parties des flux de travail, etc. Ce vocabulaire englobe le domaine de l’organisation.

Dans de nombreuses grandes organisations, cependant, la définition d’un vocabulaire unique et cohérent devient irréalisable. Dans ces cas, nous divisons notre domaine en sous-domaines. Des exemples de sous-domaines peuvent inclure:

  • Gestion des stocks
  • Découverte de produits
  • Gestion des commandes
  • Paniers d’achat et caisse

Au fur et à mesure que les concepteurs, les ingénieurs, les chefs de produits, etc. se réunissent pour créer un sous-domaine, ils forment leur propre façon de penser et de parler du sous-domaine et de ses composants.

C’est là que DDD rencontre la structure d’équipe interfonctionnelle. Bien que les membres de l’équipe proviennent de différents domaines fonctionnels, ils sont responsables de leur propre sous-domaine et deviennent éventuellement des experts résidents. En outre, l’équipe est chargée de déterminer quels artefacts — microservices, applications Web, applications mobiles, bases de données et infrastructures connexes — sont nécessaires pour donner vie au sous-domaine et aux clients de l’organisation.

Nous pouvons considérer l’équipe et ses artefacts comme comprenant un contexte borné.

Définition du Contexte borné

Bien qu’Evans discute fréquemment des contextes bornés dans son livre, il ne définit pas vraiment le modèle explicitement. Je vais donc essayer de le faire ici:

Contexte borné:

Un système cohérent en interne avec des limites soigneusement conçues qui déterminent ce qui peut entrer dans le système et ce qui peut en sortir.

En d’autres termes, un Contexte borné représente un contexte — essentiellement, un système qui encapsule des composants coopératifs — avec des limites clairement définies qui régissent ce qui peut entrer dans le système et ce qui peut en sortir.

(ces petites choses qui composent collectivement tous les êtres vivants) offrent une belle analogie. Dans une cellule se trouvent toutes sortes de composants (le noyau, les ribosomes, le cytoplasme, les cytosquelettes, etc.) qui sont tous encapsulés dans la cellule elle-même. Autour de chaque cellule, cependant, se trouve une membrane, qui agit comme la barrière entre les internes de la cellule et le reste de l’organisme. La membrane protège la cellule de son environnement, permet à des nutriments spécifiques d’y pénétrer et permet à divers sous-produits de sortir.

Dans la même veine, un Contexte borné comprend une variété de composants (microservices, applications web, applications mobiles, bases de données, files d’attente de messages, etc.). Il sert également de barrière logique qui encapsule ces composants. En interne, les composants peuvent être couplés et peuvent se transmettre librement des données. Mais le contexte borné aide à appliquer un couplage lâche à l’extérieur, en définissant des points explicites où:

  • les données externes peuvent entrer (peut-être via un consommateur abonné à une rubrique Kafka)
  • les données internes peuvent sortir (peut-être via une autre rubrique Kafka, ou via une API GET bien conçue, soigneusement conçue pour masquer les détails du système interne)

Un contexte borné représente également son équipe interfonctionnelle. L’équipe est composée de différents membres de l’équipe (concepteurs, ingénieurs frontend / backend / mobiles, chefs de produit, ingénieurs de données et ingénieurs QA, etc.). En interne, ces membres travaillent en collaboration vers les mêmes objectifs cohérents. De plus, ces membres de l’équipe sont (ou devraient être) encapsulés de manière à avoir un minimum de dépendances sur les autres équipes.

Ainsi, plutôt que de commencer au niveau organisationnel et de définir toutes les applications et microservices que nous prévoyons de construire, nous construisons des équipes autour de nos sous-domaines, permettant à ces équipes de développer leurs sous-domaines et de définir ce qui doit être construit. Bien fait, nous avons tendance à considérer divers contextes bornés dans l’organisation comme se développant de manière organique, plutôt que comme des structures rigides et prédéfinies.

Implications sur la rupture du monolithe

La loi de Conway nous dit que les organisations conçoivent des systèmes logiciels qui imitent la structure de communication de leur organisation. Cela s’avère souvent vrai, nous devons donc réfléchir à la façon dont nous structurons notre organisation lorsque nous commençons à créer des microservices.

En effet, maintenant, une image devrait émerger dans votre esprit. Lorsque nous passons du monolithe aux microservices, nous devrions commencer à penser verticalement (en divisant le monolithe par ses sous-domaines) au lieu de horizontalement (en divisant le monolithe par ses couches fonctionnelles).

Nous devrions divisez les choses pas comme nous le faisons à gauche, mais comme nous le faisons à droite

En d’autres termes, nous ne devrions pas commencer par remplacer la couche d’accès aux données du monolithe par des microservices de données. Au contraire, nous devrions commencer par diviser une fonctionnalité entière (comme le processus de paiement, ou peut-être la recherche de produits). Chaque entité représentera un contexte borné. Et chacun sera divisé par une équipe transversale dédiée.

De plus, cette équipe devrait se concentrer sur sa tâche à accomplir, qui consiste à :

  • reproduire fidèlement les fonctionnalités existantes,
  • ou (mieux) créer une toute nouvelle expérience améliorée pour ses clients.

Dans le cadre du processus, l’équipe doit concevoir le système le mieux adapté à l’entreprise.

Par exemple, nous pourrions décider de retirer notre fonctionnalité de recherche de produits de notre monolithe. L’équipe de recherche de produits peut finalement concevoir un système qui comprend:

  • Les consommateurs Kafka qui écoutent un certain nombre de sujets Kafka externes pour mettre à jour son propre système d’enregistrement interne (SoR) pour les produits.
  • un éditeur Kafka qui pousse les modifications apportées à son SoR sur une rubrique interne de Kafka
  • un autre consommateur Kafka qui écoute cette rubrique interne et met à jour un index de recherche Elastic
  • un point de terminaison GraphQL pour les recherches de forme libre qui interroge Elastic Search
  • un point de terminaison ReST qui récupère des produits individuels par ID
  • une application Web repensée qui utilise ces points de terminaison pour permettre aux clients de rechercher des produits et d’explorer les détails du produit
  • un ensemble similaire d’écrans dans nos applications mobiles qui utilisent ces points de terminaison
  • Un éditeur Kafka qui pousse des messages, représentant des requêtes distinctes effectuées par des clients, vers un sujet Kafka externe, pour une utilisation par tout autre contexte borné (par exemple, analytics) qui pourrait être intéressé

À quoi pourrait ressembler la conception de notre Contexte borné de Recherche de produits, encapsulé en rouge,

Alors que nous commençons à éplucher de plus en plus de parties verticales de notre monolithe, d’autres équipes construisent leurs propres Contextes bornés. Ces contextes bornés peuvent finir par sembler très différents les uns des autres.

Chaque équipe détermine comment construire au mieux résoudre sa tâche à portée de main

Notez que les composants dans un Contexte borné donné peuvent être étroitement couplés; cependant, nous gardons nos Contextes Bornés découplés les uns des autres. Dans notre exemple, toute communication entre contextes bornés se fait en passant des messages via une file d’attente de messages Kafka. Il est important de noter que nous évitons les appels de requête / réponse synchrones entre contextes bornés.

Ceci est également vrai avec ce qui reste du monolithe. Nous ne voulons certainement pas d’un couplage étroit entre nos nouveaux microservices et notre ancien monolithe. Ainsi, lorsque nous enlevons des parties du monolithe, nous exploitons le passage de messages pour permettre aux parties restantes de communiquer avec nos nouveaux contextes bornés.

Vérification de la réalité sur tout ce découplage

À ce stade, nous pouvons nous demander s’il est vraiment possible de garder nos Contextes Bornés découplés.

Dans le monde réel, pouvons-nous vraiment protéger nos équipes des dépendances externes ? N’y aura-t-il jamais de cas où une équipe doit être bloquée par une autre équipe pour faire son travail?

Et pouvons-nous réellement créer des architectures de service pour nos sous-domaines qui sont complètement découplées des autres sous-domaines ? N’y a-t-il vraiment pas besoin qu’une application dans un contexte borné appelle jamais de manière synchrone un service dans un autre ?

En réalité, il pourrait être impossible de garder nos Contextes Bornés découplés à 100%. Mais nous pouvons nous rapprocher, beaucoup plus que la plupart d’entre nous ne le pensent.

Architectures réelles

Commençons par regarder les architectures découplées. Souvent, nous souscrivons à l’erreur que tout type de données donné doit vivre exactement à un endroit, et que tout autre système doit appeler directement à cet endroit pour accéder aux données.

Nous appelons cela l’attribution d’une Source unique de vérité (SSoT) à nos données. Mais comme décrit dans cet article qui dissèque l’idée de SSOTS, cette notion même est, dans l’ensemble, un anti-modèle. Au lieu de cela, la plupart des contextes bornés doivent stocker leur propre copie locale de toutes les données qu’ils doivent utiliser.

Ceci est illustré par notre Contexte borné de Recherche de produits de la section précédente. Bien entendu, ce contexte limité repose en grande partie sur les données du catalogue de produits de notre organisation. Mais il y a de fortes chances que les données soient générées dans un contexte borné différent (nous l’appellerons le Contexte borné d’entrée de produit).

Notre première approche (naïve) peut consister à exposer une API ReST à partir du Contexte borné d’Entrée de Produit et à forcer les services dans le Contexte borné de Recherche de Produit à appeler cette API. Mais nous pouvons faire mieux. Nous pouvons à la place garder les systèmes découplés en publiant les modifications apportées par les services de saisie de produits sur Kafka. Nos consommateurs Kafka de Recherche de produits récupèrent ensuite ces messages et mettent à jour les bases de données de recherche de produits.

Notez que ces deux contextes bornés sont finalement cohérents. Cela signifie qu’il y aura de brèves périodes pendant lesquelles une donnée donnée pourrait être incohérente entre la Saisie de produits et la Recherche de produits. Par exemple, si le prix des widgets Wombat blancs passe de 1,99 $ à 2 $.49, il y aura une brève période de temps (souvent une question de secondes sinon de millisecondes) où il y aura une différence de 50 ¢ dans le prix du widget Wombat blanc entre les deux contextes bornés.

Cela conduit aux cas réels où nous n’avons pas d’autre alternative que de coupler des contextes bornés. Dans certains cas, la cohérence éventuelle n’est pas acceptable. Par exemple, avant qu’un client puisse effectuer son achat en ligne, il se peut que nous devions nous assurer que chaque article de son panier est effectivement disponible à ce moment-là. Même alors, nous pouvons souvent minimiser le couplage entre les deux contextes bornés.

Nos interactions peuvent ressembler à ceci :

  • Lorsque le client utilise l’interface utilisateur de Recherche de produits pour trouver des produits, les bases de données de recherche de produits sont utilisées pour récupérer des informations (telles que les styles, les avis des clients, les prix, etc.) à propos des produits
  • Même lorsque le client commence le processus de paiement, nous utilisons toujours les bases de données de recherche de produits pour récupérer les informations à afficher.
  • Enfin, lorsque le client clique sur ce dernier bouton « Terminer l’achat », nous effectuons un seul appel synchrone au Contexte Borné de l’Entrée de Produit pour valider la disponibilité des articles avant de terminer l’achat.

Un autre exemple courant qui nécessite une cohérence immédiate liée à l’autorisation. Dans de nombreux systèmes, les jetons de sécurité doivent être récupérés ou validés à chaque demande. Dans ces cas, nous devons probablement permettre à nos Contextes bornés d’appeler un autre Contexte borné orienté vers la sécurité.

Structures d’organisation réelles

Que diriez-vous d’équipes autonomes et interfonctionnelles? Dans quelle mesure sont-ils possibles dans le monde réel?

En réalité, c’est un processus de mouvement continu vers des équipes totalement autonomes. Rarement nous atteindrons 100% d’autonomie avec nos équipes. Mais si nous commençons par organiser nos équipes intelligemment, et reconnaître et répondre aux goulots d’étranglement qui surviennent, nous pouvons nous en approcher.

Pour commencer, nous devrions maximiser nos équipes verticales et interfonctionnelles et minimiser le nombre d’équipes horizontales et mono-fonctionnelles. Cela signifie résister à l’envie de former des équipes dites « de base » – dont la mission est de créer des services de données communs qui sont consommés par d’autres équipes axées sur les produits — et de former plutôt nos équipes autour de la valeur commerciale qu’elles fourniront.

De nombreuses organisations sont sur la pointe des pieds pour atteindre cet objectif, en formant d’abord des équipes orientées domaine de chefs de produits et d’ingénieurs front-end et back-end. C’est un début. Mais qui d’autre devrait inclure ces équipes? L’adhésion exacte peut différer selon les équipes ayant des besoins différents. Mais nous devrions considérer des choses comme:

  • Si notre équipe a des ingénieurs front-end, il y a de fortes chances qu’ils travaillent en étroite collaboration avec un graphiste dédié au domaine.
  • Les ingénieurs mobiles – souvent séquestrés dans leur propre zone de l’organisation — devraient être inclus pour les domaines avec un composant mobile.
  • Dans son article éclairant sur les maillages de données, Zhamak Dehghani déplore que les ingénieurs de données soient souvent exclus des équipes interfonctionnelles — au détriment des ingénieurs de données et des équipes interfonctionnelles elles-mêmes.

Une fois que nous avons déterminé la composition de nos équipes, nous devons faire attention aux goulots d’étranglement. Y a-t-il d’autres équipes qui bloquent habituellement la productivité de nos équipes interfonctionnelles ?

Par exemple, de nombreuses organisations ont une équipe de sécurité dédiée. C’est une bonne pratique, bien sûr; les organisations ont besoin d’une stratégie de sécurité cohérente et d’un moyen d’assurer la gouvernance de cette stratégie. Cependant, il est également courant que les équipes arrêtent leur travail à différentes étapes pour permettre des examens de sécurité de leur travail. Même dans les meilleures situations, cela établit des barrages routiers pour nos équipes comme une pratique courante et une pratique commerciale. De plus, cela conduira souvent les équipes à abandonner tout ou partie de leur travail et à recommencer, car elles découvrent des exigences de sécurité qui n’avaient pas été respectées.

C’est clairement une mauvaise odeur. Mais, comment faire respecter les normes de sécurité de notre organisation tout en permettant aux équipes de rester autonomes et productives ?

Nous pouvons le faire en ajoutant des ingénieurs de sécurité à nos équipes interfonctionnelles. Nous pouvons adopter trois approches:

  • Si nous avons la chance d’avoir une équipe de sécurité relativement importante, nous pouvons affecter à chaque équipe interfonctionnelle un ingénieur de sécurité (SE) à temps plein.
  • Avec des équipes de sécurité plus petites, chaque SE peut être affectée à un certain nombre d’équipes interfonctionnelles à temps partiel. Cela permettrait toujours au SES de comprendre les objectifs et les conceptions des équipes, et de travailler avec l’équipe pour adhérer aux normes de sécurité de l’organisation tout au long du processus.
  • Si nous n’avons pas assez de ressources de sécurité pour l’un ou l’autre, nous pouvons aller dans la direction opposée. Plutôt que d’intégrer des membres de l’équipe de sécurité dans nos équipes interfonctionnelles, nous pouvons intégrer des membres des équipes interfonctionnelles à l’équipe de sécurité. Chaque équipe interfonctionnelle désignerait un ou deux représentants de la sécurité. Les représentants rencontreraient périodiquement des agents de sécurité et seraient tenus au courant des exigences et des normes de sécurité de l’organisation. Ils peuvent ne pas être eux-mêmes des experts en sécurité. Mais ils pourront jouer le rôle d’ingénieur en sécurité, en veillant à ce que leurs équipes adhèrent aux pratiques de sécurité de l’organisation.

Guildes

Cela s’inscrit dans un autre modèle organisationnel qui gagne du terrain : les guildes. Le modèle de guilde est né du modèle d’équipe interfonctionnelle. De par leur nature, ces équipes sont peuplées de membres spécialisés dans différentes fonctions. Pourtant, il est souvent logique que les personnes spécialisées dans une fonction spécifique se rencontrent également; par exemple, pour:

  • Perfectionnez leurs compétences et apprenez les uns des autres
  • Découvrez et établissez les meilleures pratiques pour leur fonction particulière
  • En fonction de la fonction, créez des normes et des exigences de l’entreprise

Notre dernière solution de sécurité a effectivement formé une « guilde de sécurité ». Les membres de l’équipe travaillaient principalement avec leurs équipes verticales; mais périodiquement, certains d’entre eux rencontraient la « guilde » de la sécurité pour discuter des pratiques et des normes de sécurité de l’organisation.

Le modèle de guilde fonctionne également particulièrement bien en matière d’architecture logicielle. En particulier avec une architecture de microservices, un certain niveau de gouvernance technique à l’échelle de l’organisation est nécessaire. Pourtant, avoir un groupe d’architectes assis dans une tour d’ivoire métaphorique, distribuant des règles aux équipes, est généralement contre-productif. Au lieu de cela, les ingénieurs principaux / principaux de nos équipes interfonctionnelles peuvent se rencontrer périodiquement dans une guilde d’architecture. Là, ils peuvent soulever des problèmes auprès de leurs équipes, élaborer des solutions et établir des modèles et des normes.

Exemples de verticale les équipes interfonctionnelles, complétées par des guildes horizontales

Les guildes peuvent également être étendues à presque toutes les autres fonctions. Après tout, nous voulons que les concepteurs développent et travaillent à partir d’un guide de style d’interface utilisateur commun. Nous voulons que nos ingénieurs frontend utilisent les mêmes éléments d’interface utilisateur. Les ingénieurs d’assurance qualité doivent être alignés sur la façon dont les tests sont effectués dans nos organisations. Et les chefs de produit doivent être en phase avec la feuille de route globale des produits de l’organisation.

Rassemblez tout

Passer aux microservices peut considérablement améliorer la productivité de nos équipes. Mais nous devons comprendre comment tirer parti d’une architecture de microservices pour nous y rendre. De tous les modèles et concepts de conception liés aux microservices, le contexte borné est sans doute le plus important pour nous donner cette compréhension.

Avec une bonne compréhension du Contexte borné, nous comprenons que:

  • Notre structure organisationnelle et notre architecture technique vont de pair
  • Nos équipes axées sur les produits doivent avoir un minimum de dépendances vis-à-vis des autres équipes, tout comme les systèmes qu’elles construisent doivent être découplés des autres systèmes

En général, l’intégration du contexte borné met dans l’état d’esprit que nous devons réussir avec notre architecture de microservices. Assurez-vous de comprendre ce schéma important avant de vous lancer dans votre voyage en microservices!

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.