Modèle C4
4 niveaux de zoom :
- Context
- Container
- Component
- Code.
Représente le même système à plusieurs niveaux de détail.
Editeur: https://playground.structurizr.com
vue très large : où se place ton système ?
Les 4 C
Context
Vue très large : Ton système vu de l’extérieur, “Ce système sert à quoi, pour qui, et avec quoi il parle ?”. On y voit :
- les utilisateurs,
- les systèmes externes,
- ton application au milieu,
- les grandes interactions.
Exemple :
- Client
- Admin
- Shop Platform
- Stripe
- Service de mails
Container
Vue intermédiaire : quels gros blocs le composent (blocs exécutable ou stockant des données), “Techniquement, mon système est découpé en quels gros morceaux?".
Exemple:
- Frontend Web App (Nuxt/Vue)
- Backend API (Node.js ou PHP)
- MariaDB
- Worker d’envoi d’e-mails
Component
Vue fine : comment un bloc est organisé, “À l’intérieur de ce bloc, quels sont les modules importants et leurs responsabilités ?”?
Exemple poru une API :
- Auth Controller
- Order Service
- Payment Service
- Product Repository
- Email Gateway
Code
Vue très fine : à quoi ressemble le code / design interne ?
Niveau “Code” prévu, mais en pratique il est souvent optionnel, “Comment ce composant est structuré en classes, interfaces, modules, etc. ?”.
Exemple
workspace "Adext2"JustNote Reloaded" "C4Système modelde workspace"gestion de carnets pour institutions pénitentiaires belges" {
model {
user = person "User"Utilisateur adextPrison" "Membre du personnel pénitentiaire authentifié"
admin = person "Administrateur" "Utilisateur avec privilèges élevés"
ldapServer = softwareSystem "Adext2"Serveur LDAP/Active Directory" "Microsoft Active Directory"
smtpServer = softwareSystem "Serveur SMTP" "SMTP"
justNoteSystem = softwareSystem "JustNote Reloaded" "Système de gestion de carnets" {
webappfrontendApp = container "Application Web App"Frontend" "Angular"Application SPA" "Nuxt 4, Vue 3, Pinia" {
loginViewfrontendAuth = component "LoginModule View"Auth" authService"Gestion authentification" "Frontend module"
frontendRpcClient = component "auth.Client RPC" "Client JSON-RPC" "Frontend service"
externalsListViewfrontendStore = component "ExternalsState ListManagement" View""Gestion externalsServiceétat centralisée" "Pinia store"
pages = component "externals.service"Pages" newExternalView"Composants de page" "Vue components"
composables = component "Composables" New"Logique externalmétier" view""Vue formServicecomposables"
uiComponents = component "form.service"Composants UI" "Interface utilisateur" "Vue components"
pages -> frontendAuth "Utilise"
pages -> composables "Utilise"
pages -> uiComponents "Affiche"
frontendAuth -> frontendRpcClient "Appelle"
frontendStore -> frontendRpcClient "Gère tokens"
composables -> frontendRpcClient "Appelle RPC"
}
apibackendApi = container "API"API Backend RPC" "API JSON-RPC 2.0" "PHP 8.4, Apache" {
externalsControllerrpcDispatcher = component "ExternalsRPC Controller"Dispatcher" loginController"Gestion protocole JSON-RPC" "PHP component"
authMiddleware = component "LoginAuth Controller"Middleware" pagesController"Validation JWT" "PHP middleware"
serviceContainer = component "PageContainer Controller"DI" externalModel"Injection dépendances" "PHP service container"
authController = component "ExternalAuth Model"Controller" ldapModel"login, logout, refresh" "PHP controller"
usersController = component "LdapUsers Model"Controller" config"CRUD utilisateurs" "PHP controller"
notebooksController = component "Config"Notebooks Controller" "CRUD carnets" "PHP controller"
entriesController = component "Entries Controller" "CRUD entrées" "PHP controller"
sectionsController = component "Sections Controller" "CRUD sections" "PHP controller"
absencesController = component "Absences Controller" "CRUD absences" "PHP controller"
remindersController = component "Reminders Controller" "CRUD rappels" "PHP controller"
adminControllers = component "Admin Controllers" "Méthodes admin" "PHP controller"
publicControllers = component "Public Controllers" "Méthodes publiques" "PHP controller"
dbService = component "Database Service" "Wrapper ORM Medoo" "PHP service"
jwtService = component "JWT Service" "Gestion tokens JWT" "PHP service"
ldapService = component "LDAP Service" "Authentification AD" "PHP service"
refreshTokenService = component "Refresh Token Service" "Rotation tokens" "PHP service"
accessControlService = component "Access Control Service" "Évaluation permissions" "PHP service"
mailerService = component "Mailer Service" "Envoi emails" "PHP service"
rpcDispatcher -> authMiddleware "Passe par"
authMiddleware -> serviceContainer "Résout services"
authController -> jwtService "Utilise"
authController -> ldapService "Utilise"
authController -> refreshTokenService "Utilise"
authController -> dbService "Utilise"
usersController -> dbService "Utilise"
usersController -> accessControlService "Vérifie permissions"
notebooksController -> dbService "Utilise"
notebooksController -> accessControlService "Vérifie permissions"
entriesController -> dbService "Utilise"
entriesController -> accessControlService "Vérifie permissions"
sectionsController -> dbService "Utilise"
absencesController -> dbService "Utilise"
absencesController -> accessControlService "Vérifie permissions"
remindersController -> dbService "Utilise"
remindersController -> accessControlService "Vérifie permissions"
remindersController -> mailerService "Envoie notifications"
adminControllers -> dbService "Utilise"
adminControllers -> accessControlService "Vérifie permissions"
publicControllers -> dbService "Utilise"
}
dbdatabase = container "DataBase"Base de données" "Stockage relationnel" "MariaDB 11.8" {
tags "Database"
usersTable = component "Table users" "Comptes utilisateurs" "Table"
rolesTable = component "Table roles" "Définitions rôles" "Table"
userRolesTable = component "Table user_roles" "Assignations rôle" "Table"
orgsTable = component "Table organizations" "Organisations" "Table"
placesTable = component "Table places" "Établissements" "Table"
notebooksTable = component "Table notebooks" "Carnets" "Table"
sectionsTable = component "Table sections" "Sections" "Table"
entriesTable = component "Table entries" "Entrées" "Table"
absencesTable = component "Table absences" "Absences" "Table"
absenceTypesTable = component "Table absence_types" "Types absences" "Table"
remindersTable = component "Table reminders" "Rappels" "Table"
translationsTable = component "Table translations" "Traductions" "Table"
groupsTable = component "Table groups" "Groupes" "Table"
permissionsTable = component "Table permissions" "Permissions" "Table"
logsTable = component "Table logs" "Audit" "Table"
refreshTokensTable = component "Table refresh_tokens" "Tokens refresh" "Table"
}
//dbAdmin Niveau= 2container Containers"Admin DB" "Interface admin DB" "phpMyAdmin"
frontendApp -> backendApi "Appelle JSON-RPC" "HTTP/JSON"
backendApi -> frontendApp "Retourne réponses" "HTTP/JSON"
backendApi -> database "Lit/écrit" "MySQL"
database -> backendApi "Retourne données" "MySQL"
backendApi -> ldapServer "Authentifie" "LDAPS"
ldapServer -> backendApi "Retourne résultat" "LDAPS"
backendApi -> smtpServer "Envoie emails" "SMTP"
dbAdmin -> database "Administre" "MySQL"
}
user -> webappjustNoteSystem "Utilise"
webappadmin -> apijustNoteSystem "Appelle"Administre"
apiuser -> dbfrontendApp "Lit/Ecrit"Utilise"
// Niveau 3
// API
externalsControlleradmin -> externalModelfrontendApp "Utilise"
pagesControllerfrontendApp -> externalModeluser "Utilise"Affiche loginControllerle -> ldapModel "Utilise"
externalModel -> config "Utilise"
ldapModel -> config "Utilise"
externalModel -> db "Se connecte / MYSQL"
ldapModel -> db "Se connecte / MYSQL"
// Front - LoginView
loginView -> authService "Utilise"
authService -> loginController "HTTP"
// Front - Externals list
externalsListView -> externalsService "Utilise"
externalsService -> externalsController "HTTP"
// Front - New external
newExternalView -> formService "Utilise"
formService -> externalsController "HTTP"dashboard"
}
views {
systemContext adextjustNoteSystem "SystemContext" "Vue contexte système" {
include user
include adext*
autolayout lr
}
container adextjustNoteSystem "ContainerView" "Vue conteneurs" {
include *
autolayout lr
}
component apifrontendApp "FrontendComponents" "Vue composants Frontend" {
include *
autolayout lrtb
}
component webappbackendApi "BackendComponents" "Vue composants Backend" {
include *
autolayout lrtb
}
component database "DatabaseComponents" "Vue composants Database" {
include *
autolayout tb
}
dynamic justNoteSystem "AuthFlow" "Flux authentification" {
user -> frontendApp "1. Saisit identifiants"
frontendApp -> backendApi "2. Appelle Auth.login"
backendApi -> ldapServer "3. Valide LDAPS"
ldapServer -> backendApi "4. Retourne résultat"
backendApi -> database "5. Charge utilisateur"
database -> backendApi "6. Retourne données"
backendApi -> frontendApp "7. Retourne tokens"
frontendApp -> user "8. Redirige dashboard"
}
styles {
element "Person" {
background #08427b
color #ffffff
}
element "Software System" {
background #1168bd
color #ffffff
}
element "Container" {
background #438dd5
color #ffffff
}
element "Component" {
background #85bbf0
color #000000
}
element "Database" {
shape cylinder
}
}
theme default
}
}