Intro à Structurizr

Introduction à Structurizr

1. introduction

Cet article concerne Structurizr, un outil qui fournit unprogrammatic approach to architectural definitions and visualizations based on the C4 Model.

Structurizr rompt avec les approches classiques du glisser-déposer d'éditeurs de diagrammes architecturaux tels que UML et nous permet de décrire nos artefacts architecturaux à l'aide de l'outil que nous connaissons le mieux: Java.

2. Commencer

Pour commencer, ajoutons la dépendancestructurizr-core à nospom.xml:


    com.structurizr
    structurizr-core
    1.0.0-RC5

3. Les systèmes

Commençons par modéliser un exemple d’architecture. Supposons que nous construisions un terminal de paiement capable de détecter la fraude utilisé par les marchands pour compenser les paiements.

Tout d'abord, nous devons créer unWorkspace et unModel:

Workspace workspace = new Workspace("Payment Gateway", "Payment Gateway");
Model model = workspace.getModel();

Nous définissons également un utilisateur et deux systèmes logiciels au sein de ce modèle:

Person user = model.addPerson("Merchant", "Merchant");
SoftwareSystem paymentTerminal = model.addSoftwareSystem(
  "Payment Terminal", "Payment Terminal");
user.uses(paymentTerminal, "Makes payment");
SoftwareSystem fraudDetector = model.addSoftwareSystem(
  "Fraud Detector", "Fraud Detector");
paymentTerminal.uses(fraudDetector, "Obtains fraud score");

Maintenant que notre système est défini, nous pouvons créer une vue:

ViewSet viewSet = workspace.getViews();

SystemContextView contextView = viewSet.createSystemContextView(
  paymentTerminal, "context", "Payment Gateway Diagram");
contextView.addAllSoftwareSystems();
contextView.addAllPeople();

Ici, nous avons créé une vue qui inclut tous les systèmes logiciels et toutes les personnes. Maintenant, la vue doit être rendue.

4. Afficher via PlantUML

Dans la section précédente, nous avons créé une vue d’une passerelle de paiement simple.

La prochaine étape consiste à créer un diagramme convivial. La solution la plus simple pour une organisation utilisant déjàPlantUML serait probablement de demander à Structurizr de faire un export PlantUML:

StringWriter stringWriter = new StringWriter();
PlantUMLWriter plantUMLWriter = new PlantUMLWriter();
plantUMLWriter.write(workspace, stringWriter);
System.out.println(stringWriter.toString());

Ici, le balisage résultant est imprimé à l'écran, mais il peut tout aussi bien être envoyé dans un fichier. Le rendu des données de cette manière génère le diagramme ci-dessous:

image

5. Vue via le site Web Structurizr

Une autre option pour les diagrammes de rendu existe. Une vue architecturale peut être envoyée sur le site Web de Structurizr via une API client. Le diagramme sera ensuite généré en utilisant leur interface utilisateur riche.

Créons un client API:

StructurizrClient client = new StructurizrClient("key", "secret");

Les paramètres clés et secrets sont obtenus à partir du tableau de bord de l'espace de travail sur leur site Web. L'espace de travail peut alors être référencé par:

client.putWorkspace(1337, workspace);

De toute évidence, nous devons nous inscrire sur le site Web et créer un espace de travail. Un compte de base avec un seul espace de travail est gratuit. Dans le même temps, des plans commerciaux sont également disponibles.

6. Les conteneurs

Étendons notre système logiciel en ajoutant des conteneurs. Dans un modèle C4, les conteneurs peuvent être des applications Web, des applications mobiles, des applications de bureau, des bases de données et des systèmes de fichiers: pratiquement tout ce qui contient du code et / ou des données.

Tout d'abord, nous créons des conteneurs pour notre terminal de paiement:

Container f5 = paymentTerminal.addContainer(
  "Payment Load Balancer", "Payment Load Balancer", "F5");
Container jvm1 = paymentTerminal.addContainer(
  "JVM-1", "JVM-1", "Java Virtual Machine");
Container jvm2 = paymentTerminal.addContainer(
  "JVM-2", "JVM-2", "Java Virtual Machine");
Container jvm3 = paymentTerminal.addContainer(
  "JVM-3", "JVM-3", "Java Virtual Machine");
Container oracle = paymentTerminal.addContainer(
  "oracleDB", "Oracle Database", "RDBMS");

Ensuite, nous définissons les relations entre ces éléments nouvellement créés:

f5.uses(jvm1, "route");
f5.uses(jvm2, "route");
f5.uses(jvm3, "route");

jvm1.uses(oracle, "storage");
jvm2.uses(oracle, "storage");
jvm3.uses(oracle, "storage");

Enfin, créez une vue conteneur pouvant être transmise à un moteur de rendu:

ContainerView view = workspace.getViews()
  .createContainerView(paymentTerminal, "F5", "Container View");
view.addAllContainers();

Le rendu du diagramme résultant via PlantUML produit:

image

7. Composants

Le niveau de détail suivant dans le modèle C4 est fourni par la vue des composants. En créer un est similaire à ce que nous avons fait auparavant.

Tout d'abord, nous créons des composants dans un conteneur:

Component jaxrs = jvm1.addComponent("jaxrs-jersey",
  "restful webservice implementation", "rest");
Component gemfire = jvm1.addComponent("gemfire",
  "Clustered Cache Gemfire", "cache");
Component hibernate = jvm1.addComponent("hibernate",
  "Data Access Layer", "jpa");

Ensuite, ajoutons quelques relations:

jaxrs.uses(gemfire, "");
gemfire.uses(hibernate, "");

Enfin, créons la vue:

ComponentView componentView = workspace.getViews()
  .createComponentView(jvm1, JVM_COMPOSITION, "JVM Components");

componentView.addAllComponents();

Un rendu du diagramme résultant via PlantUML a pour résultat:

image

8. Extraction de composants

Pour les bases de code existantes utilisant le framework Spring, Structurizr fournit un moyen automatisé d'extraire les composants annotés Spring et de les ajouter aux artefacts architecturaux.

Pour utiliser cette fonctionnalité, nous devons ajouter une autre dépendance:


    com.structurizr
    structurizr-spring
    1.0.0-RC5

Ensuite, nous devons créer unComponentFinder configuré avec une ou plusieurs stratégies de résolution. Les stratégies de résolution affectent des éléments tels que les composants qui seront ajoutés au modèle, la profondeur de traversée de l'arbre de dépendance, etc.

Nous pouvons même intégrer des stratégies de résolution personnalisées:

ComponentFinder componentFinder = new ComponentFinder(
  jvm, "com.example.structurizr",
  new SpringComponentFinderStrategy(
    new ReferencedTypesSupportingTypesStrategy()
  ),
  new SourceCodeComponentFinderStrategy(new File("/path/to/base"), 150));

Enfin, nous commençons le chercheur:

componentFinder.findComponents();

Le code ci-dessus analyse le packagecom.example.structurizr pour les beans annotés Spring et les ajoute en tant que composants à la JVM du conteneur. Il va sans dire que nous sommes libres de mettre en œuvre nos propres scanners, des ressources annotées JAX-RS et même des classeurs Google Guice.

Un exemple de diagramme simple tiré d'un exemple de projet est reproduit ci-dessous:

image

9. Conclusion

Ce tutoriel rapide couvre les bases du projet Structurizr for Java.

Et, comme toujours, un exemple de code peut être trouvéover on GitHub.