
Programmation fonctionnelle pour la conception pilotée par le domaine
Description
Introduction au livre
DDD fonctionnel dans le monde réel, même avec un code d'exemple remanié
Ce livre établit un lien naturel entre la modélisation de domaine et le paradigme fonctionnel, vous guidant tout au long du processus de mise en œuvre de problèmes complexes du monde réel avec un code simple et sécurisé.
Plus précisément, elle présente une méthode de conception logicielle qui réduit les erreurs et révèle plus clairement les règles métier grâce à la philosophie consistant à exprimer les connaissances du domaine sous forme de types.
Le célèbre ouvrage de Scott Blasin, Domain Modeling Made Functional, explique cette philosophie à l'aide d'exemples basés sur F#, mais une barrière linguistique empêchait son utilisation dans l'environnement pratique domestique.
Dans cette nouvelle édition coréenne traduite, nous avons surmonté cet obstacle et réécrit tous les exemples en TypeScript et en Kotlin.
La principale différence réside dans le fait qu'il ne s'agit pas d'une simple substitution grammaticale, mais plutôt du résultat d'une refonte et d'une implémentation utilisant le système de types et les idiomes de chaque langage, et qu'il renaît sous une forme immédiatement applicable en pratique.
Grâce à cela, les lecteurs peuvent non seulement acquérir une compréhension conceptuelle de la conception pilotée par le domaine, mais aussi expérimenter naturellement le processus de modélisation en suivant du code écrit dans un langage familier.
De plus, grâce au flux « concept → code → amélioration (refactorisation) » qui suit chaque chapitre, vous pouvez apprendre l'état d'esprit nécessaire pour construire des modèles et des conceptions adaptés à une utilisation pratique, plutôt que de simplement apprendre des théories.
Ce n'est pas grave si vous n'avez pas une compréhension approfondie de la programmation fonctionnelle.
Ce livre privilégie les exemples intuitifs aux abstractions complexes, guidant les développeurs vers une approche centrée sur le domaine. Ce guide pratique, rare en son genre, aborde les concepts de DDD, de programmation fonctionnelle et de systèmes de types jusqu'au niveau du code, offrant des perspectives nouvelles même aux développeurs ayant déjà constaté les limites du DDD orienté objet traditionnel.
Cet ouvrage est une lecture incontournable pour les développeurs qui souhaitent appréhender les problèmes complexes de manière simple et claire, et implémenter les domaines grâce à un code sûr.
Ce livre établit un lien naturel entre la modélisation de domaine et le paradigme fonctionnel, vous guidant tout au long du processus de mise en œuvre de problèmes complexes du monde réel avec un code simple et sécurisé.
Plus précisément, elle présente une méthode de conception logicielle qui réduit les erreurs et révèle plus clairement les règles métier grâce à la philosophie consistant à exprimer les connaissances du domaine sous forme de types.
Le célèbre ouvrage de Scott Blasin, Domain Modeling Made Functional, explique cette philosophie à l'aide d'exemples basés sur F#, mais une barrière linguistique empêchait son utilisation dans l'environnement pratique domestique.
Dans cette nouvelle édition coréenne traduite, nous avons surmonté cet obstacle et réécrit tous les exemples en TypeScript et en Kotlin.
La principale différence réside dans le fait qu'il ne s'agit pas d'une simple substitution grammaticale, mais plutôt du résultat d'une refonte et d'une implémentation utilisant le système de types et les idiomes de chaque langage, et qu'il renaît sous une forme immédiatement applicable en pratique.
Grâce à cela, les lecteurs peuvent non seulement acquérir une compréhension conceptuelle de la conception pilotée par le domaine, mais aussi expérimenter naturellement le processus de modélisation en suivant du code écrit dans un langage familier.
De plus, grâce au flux « concept → code → amélioration (refactorisation) » qui suit chaque chapitre, vous pouvez apprendre l'état d'esprit nécessaire pour construire des modèles et des conceptions adaptés à une utilisation pratique, plutôt que de simplement apprendre des théories.
Ce n'est pas grave si vous n'avez pas une compréhension approfondie de la programmation fonctionnelle.
Ce livre privilégie les exemples intuitifs aux abstractions complexes, guidant les développeurs vers une approche centrée sur le domaine. Ce guide pratique, rare en son genre, aborde les concepts de DDD, de programmation fonctionnelle et de systèmes de types jusqu'au niveau du code, offrant des perspectives nouvelles même aux développeurs ayant déjà constaté les limites du DDD orienté objet traditionnel.
Cet ouvrage est une lecture incontournable pour les développeurs qui souhaitent appréhender les problèmes complexes de manière simple et claire, et implémenter les domaines grâce à un code sûr.
- Vous pouvez consulter un aperçu du contenu du livre.
Aperçu
indice
Préface du traducteur xii
Recommandation xv
Revue du lecteur bêta xvi
Préface à l'édition coréenne xviii
Préface xix
PARTIE I Comprendre les domaines
CHAPITRE 1 Introduction à DDD 3
1.1 L'importance du modèle de partage 4
1.2 Comprendre les domaines en tant qu'événements commerciaux 7
1.2.1 Exploration du domaine avec Event Storming 8 / 1.2.2 Exploration du domaine : Le système de prise de commandes 8 / 1.2.3 Extension des événements jusqu’à la fin 12 / 1.2.4 Documentation des commandes 13
1.3 Division d'un domaine en sous-domaines 15
1.4 Création de solutions à l'aide du contexte limite 17
1.4.1 Bien contextualiser 18 / 1.4.2 Créer une carte contextuelle 19 / 1.4.3 Se concentrer sur le contexte le plus important 21
1.5 Création d'un langage commun 21
1.6 Résumé des concepts DDD 22
1.7 Finale 23
1.7.1 Événements et processus 23 / 1.7.2 Sous-domaines et contextes limites 24 / 1.7.3 Langage commun 24 / 1.7.4 Guide du chapitre suivant 24
CHAPITRE 2 Comprendre les domaines 25
2.1 Entretiens avec des experts du domaine 25
2.1.1 Comprendre les exigences non fonctionnelles 27 / 2.1.2 Comprendre le reste du flux de travail 28 / 2.1.3 Réflexion sur les entrées 29
2.2 Éviter une conception centrée sur la base de données 30
2.3 Éviter une conception centrée sur la classe 31
2.4 Documentation du domaine 32
2.5 Analyse approfondie du flux de travail d'acceptation des commandes 33
2.6 Modélisation de domaines complexes 36
2.6.1 Expression des contraintes 37 / 2.6.2 Expression du cycle de vie d'une commande 39 / 2.6.3 Spécification des étapes d'un flux de travail 41
2.7 Conclusion 43
__2.7.1 Guide du chapitre suivant 44
CHAPITRE 3 ARCHITECTURE FONCTIONNELLE 45
3.1 Contexte de frontière en tant que composants logiciels autonomes 46
3.2 Communication entre contextes frontières 47
3.2.1 Transfert de données entre contextes limites 48 / 3.2.2 Limites de confiance et vérification 49
3.3 Contrats entre contextes frontières 50
3.3.1 Couche anti-corruption 51 / 3.3.2 Carte contextuelle représentant les relations intercontextuelles 51
3.4 Flux de travail du contexte de frontière 52
3.4.1 Entrées et sorties du flux de travail 53 / 3.4.2 Interdiction des événements de domaine dans les contextes limites 54
3.5 Structure du code dans le contexte de frontière 55
3.5.1 Architecture en oignon 56 / 3.5.2 Suppression des E/S externes des limites de contexte 57
3.6 Finale 57
__3.6.1 Guide du chapitre suivant 58
PARTIE II Modélisation du domaine
CHAPITRE 4 Comprendre les types 61
4.1 Comprendre les fonctions 61
4.1.1 Comprendre les fonctions 62
4.2 Types et fonctions 63
4.3 Synthèse de type 66
__4.3.1 ET type 67 / 4.3.2 OU type 67 / 4.3.3 Type simple 69 / 4.3.4 Système de types algébriques 69
4.4 Gestion des types TypeScript et Kotlin 70
4.5 Création d'un modèle de domaine de type 73
4.6 Modélisation des valeurs manquantes, des erreurs et des collections 77
4.6.1 Modélisation des valeurs optionnelles 78 / 4.6.2 Modélisation des erreurs 79 / 4.6.3 Modélisation de l'absence de valeurs 80 / 4.6.4 Modélisation des listes et des collections 81
4.7 Final 83
CHAPITRE 5 : Modélisation des domaines avec des types 85
5.1 Réexamen du modèle de domaine 85
5.2 Recherche de modèles dans le modèle de domaine 87
5.3 Modélisation simple des valeurs 87
5.3.1 Utilisation des types wrapper 89 / 5.3.2 Valeurs contraintes 90 / 5.3.3 Atténuation des problèmes de performance avec les types simples 90
5.4 Modélisation de données complexes 92
5.4.1 Modélisation des enregistrements 92 / 5.4.2 Modélisation des types inconnus 93 / 5.4.3 Modélisation des types sélectionnés 94
5.5 Modélisation des flux de travail avec des fonctions 95
5.5.1 Gestion des entrées et sorties complexes 96 / 5.5.2 Documentation des effets dans les signatures de fonctions 99
5.6 Sur l'identité : Objets de valeur 100
__5.6.1 Égalité des objets de valeur 102
5.7 Sur l'identité : Entité 103
5.7.1 Identifiants d'entités 103 / 5.7.2 Inclusion des identifiants dans les définitions de données 104 / 5.7.3 Égalité des entités 106 / 5.7.4 Immuabilité et identité 108
5.8 Assemblage 110
5.8.1 Agrégats responsables de la cohérence et de l'invariance 112 / 5.8.2 Référence des agrégats 112
5.9 Synthèse 115
5.9.1 Repenser le défi : les types peuvent-ils vraiment remplacer les documents ? 119
5.10 Arrivée 120
CHAPITRE 6 Intégrité et cohérence du domaine 121
6.1 Intégrité des valeurs simples 122
6.2 Unités de mesure 126
6.3 Imposition de l'immuabilité avec le système de types 128
6.4 Intégration des règles métier au système de types 128
6.4.1 Modification du domaine d'exemple pour éviter les états incorrects 133
6.5 Cohérence 135
6.5.1 Cohérence au sein d'une même collection 135 / 6.5.2 Cohérence entre différents contextes 137 / 6.5.3 Cohérence entre les collections dans un même contexte 138 / 6.5.4 Plusieurs collections traitant les mêmes données 140
6.6 Arrivée 140
CHAPITRE 7 Modélisation des flux de travail avec des pipelines 141
7.1 Flux de travail Entrée 142
7.1.1 Utilisation des commandes comme entrée 143 / 7.1.2 Généralisation des structures communes 144 / 7.1.3 Regroupement de plusieurs commandes en un seul type 145
7.2 Modélisation des commandes sous forme d'ensembles d'états 146
7.2.1 Ajout de nouveaux types d'état en fonction de l'évolution des besoins 149
7.3 Machine à états 149
7.3.1 Pourquoi utiliser une machine à états ? 151 / 7.3.2 Comment implémenter une machine à états simple avec TypeScript et Kotlin 151
7.4 Modélisation des étapes individuelles d'un flux de travail avec le type 153
7.4.1 Étape de validation 153 / 7.4.2 Étape de tarification 156 / 7.4.3 Étape de confirmation de commande 157 / 7.4.4 Création d'événements à retourner 160
7.5 Documenter les effets 162
7.5.1 Effet de l'étape de vérification 162 / 7.5.2 Effet de l'étape de calcul du prix 164 / 7.5.3 Effet de l'étape de confirmation de commande 165
7.6 Synthèse d'un flux de travail à partir d'étapes individuelles 166
7.7 Faut-il inclure les dépendances dans votre conception ? 167
7.8 Pipeline complet 169
__7.8.1 Étape interne 171
7.9 Flux de travail de longue durée 175
7.10 Finale 176
__7.10.1 Guide du chapitre suivant 177
PARTIE III Mise en œuvre du modèle
CHAPITRE 8 Comprendre les fonctions 181
8.1 Des fonctions, des fonctions partout 182
8.2 La fonction est le personnage principal 183
8.2.1 Fonctions comme protagonistes 184 / 8.2.2 Fonctions comme entrées 185 / 8.2.3 Fonctions comme sorties 186 / 8.2.4 Currying 187 / 8.2.5 Application partielle 188
8.3 Fonctions complètes 189
8.4 Composition fonctionnelle 192
8.4.1 Composition de fonctions en TypeScript et Kotlin 193 / 8.4.2 Création d'applications complètes avec des fonctions 195 / 8.4.3 Composition de fonctions : un exercice plus complexe 196
8,5 Terminer 198
CHAPITRE 9 Mise en œuvre : Combinaison de pipelines 199
9.1 Gestion des types simples 200
9.2 Guide d'implémentation avec les types de fonctions 202
9.3 Mise en œuvre de l'étape de validation 204
9.3.1 Génération d'une adresse valide 207 / 9.3.2 Création d'un article de commande 209 / 9.3.3 Création d'un adaptateur de fonction 211
9.4 Mise en œuvre des étapes restantes 214
9.4.1 Mise en œuvre de l'étape d'approbation 218 / 9.4.2 Création d'un événement 220
9.5 Assemblage de toutes les étapes du pipeline 224
9.6 Injection de dépendances 227
__9.6.1 Dépendance excessive 235
9.7 Tests de dépendance 237
9.8 Pipeline assemblé 240
9,9 Arrivée 244
CHAPITRE 10 Mise en œuvre : Gestion des erreurs 247
10.1 Détection des erreurs de type 247
10.2 Gestion des erreurs de domaine 249
10.2.1 Modélisation des erreurs de domaine avec des types 251 / 10.2.2 Gestion des erreurs qui encombrent votre code 253
10.3 Connexion de fonctions qui produisent des types Either 255
10.3.1 Implémentation d'un bloc adaptateur 258 / 10.3.2 Gestion des fonctions Either 260 / 10.3.3 Composition de fonctions et vérification de type 261 / 10.3.4 Conversion vers des types d'erreurs courants 262
10.4 Assemblage d'un pipeline avec FlatMap et Map 266
10.5 Adaptation d'autres types de fonctions au modèle à double voie 269
10.5.1 Gestion des exceptions 269 / 10.5.2 Gestion des fonctions sans issue 273
10.6 Gestion des pipelines complexes 275
__10.6.1 Notation « do » de fp-ts 275 / 10.6.2 Bloc « either » d'arrow-kt 277 / 10.6.3 Contexte « Raise » d'arrow-kt 278 / 10.6.4 Vérification de l'ordre avec le type « Either » 282 / 10.6.5 Validation des listes « Either » 283
10.7 Monades et autres concepts 286
__10.7.1 Synthèse parallèle et applications 287
10.8 Ajout d'effets asynchrones 287
10.9 Arrivée 291
CHAPITRE 11 SÉRIALISATION 293
11.1 Persistance et sérialisation 293
11.2 Conception pour la sérialisation 294
11.3 Connexion du code de sérialisation à un flux de travail 295
__11.3.1 DTO 296 en tant que contrat entre contextes frontières
11.4 Exemple de sérialisation complète 297
11.4.1 Intégration d'une bibliothèque de sérialisation JSON 301 / 11.4.2 Pipeline de sérialisation complet 302 / 11.4.3 Gestion de plusieurs versions d'un type de sérialisation 306
11.5 Comment convertir un type de domaine en DTO 306
11.5.1 Types simples 306 / 11.5.2 Valeurs optionnelles 307 / 11.5.3 Enregistrements 307 / 11.5.4 Collections 308 / 11.5.5 Énumérations 310 / 11.5.6 Tuples 311 / 11.5.7 Types de choix 312 / 11.5.8 Sérialisation des types d'enregistrements et de choix avec des dictionnaires 317 / 11.5.9 Génériques 320
11,6 Arrivée 321
CHAPITRE 12 Perpétuation 323
12.1 Déploiement du code de persistance en périphérie 324
12.1.1 Prise de décision basée sur les données d'entrée 329 / 12.1.2 Où se situe le modèle de référentiel ? 330
12.2 Séparation des commandes de mise à jour et des requêtes d'interrogation 331
12.2.1 Séparation des responsabilités commande-requête 334 / 12.2.2 Séparation CQRS et base de données 336 / 12.2.3 Event Sourcing 336
12.3 Posséder un magasin de données de lecteur pour chaque contexte de limite 337
12.3.1 Comment utiliser des données provenant de plusieurs domaines 337
12.4 Utilisation des bases de données documentaires 339
12.5 Utilisation des bases de données relationnelles 339
12.5.1 Association des types de sélection aux tables 341 / 12.5.2 Association des types imbriqués aux tables 344 / 12.5.3 Lecture d'une base de données relationnelle 345 / 12.5.4 Lecture des types de sélection depuis une base de données relationnelle 352 / 12.5.5 Écriture dans une base de données relationnelle 355
12.6 Transaction 358
12.7 Finir 360
CHAPITRE 13 Conception propre 361
13.1 Première modification : Ajout des frais de livraison 362
13.1.1 Simplification de la logique métier par la séparation des préoccupations 363 / 13.1.2 Ajout d'une nouvelle étape à un flux de travail 364 / 13.1.3 Autre raison d'ajouter une nouvelle étape à un pipeline 368
13.2 Deuxième modification : Ajout d’un support client VIP 368
13.2.1 Ajout d'une nouvelle entrée à un flux de travail 371 / 13.2.2 Ajout d'une règle de livraison gratuite à un flux de travail 373
13.3 Troisième modification : Ajout de la prise en charge des codes promotionnels 374
13.3.1 Ajout d'un code promotionnel au modèle de domaine 374 / 13.3.2 Modification de la logique de tarification 376 / 13.3.3 Implémentation de la fonction GetPricingFunction 378 / 13.3.4 Documentation des remises sur les articles de commande 379 / 13.3.5 Systèmes de tarification plus complexes 381 / 13.3.6 Modification d'un contrat entre contextes limites 382 / 13.3.7 Impression des commandes 384
13.4 Quatrième modification : Ajout de restrictions sur les heures d’ouverture 384
13.5 Gestion des modifications d'exigences supplémentaires 386
13,6 Arrivée 386
13.7 Fin du livre 387
Recherche 390
Recommandation xv
Revue du lecteur bêta xvi
Préface à l'édition coréenne xviii
Préface xix
PARTIE I Comprendre les domaines
CHAPITRE 1 Introduction à DDD 3
1.1 L'importance du modèle de partage 4
1.2 Comprendre les domaines en tant qu'événements commerciaux 7
1.2.1 Exploration du domaine avec Event Storming 8 / 1.2.2 Exploration du domaine : Le système de prise de commandes 8 / 1.2.3 Extension des événements jusqu’à la fin 12 / 1.2.4 Documentation des commandes 13
1.3 Division d'un domaine en sous-domaines 15
1.4 Création de solutions à l'aide du contexte limite 17
1.4.1 Bien contextualiser 18 / 1.4.2 Créer une carte contextuelle 19 / 1.4.3 Se concentrer sur le contexte le plus important 21
1.5 Création d'un langage commun 21
1.6 Résumé des concepts DDD 22
1.7 Finale 23
1.7.1 Événements et processus 23 / 1.7.2 Sous-domaines et contextes limites 24 / 1.7.3 Langage commun 24 / 1.7.4 Guide du chapitre suivant 24
CHAPITRE 2 Comprendre les domaines 25
2.1 Entretiens avec des experts du domaine 25
2.1.1 Comprendre les exigences non fonctionnelles 27 / 2.1.2 Comprendre le reste du flux de travail 28 / 2.1.3 Réflexion sur les entrées 29
2.2 Éviter une conception centrée sur la base de données 30
2.3 Éviter une conception centrée sur la classe 31
2.4 Documentation du domaine 32
2.5 Analyse approfondie du flux de travail d'acceptation des commandes 33
2.6 Modélisation de domaines complexes 36
2.6.1 Expression des contraintes 37 / 2.6.2 Expression du cycle de vie d'une commande 39 / 2.6.3 Spécification des étapes d'un flux de travail 41
2.7 Conclusion 43
__2.7.1 Guide du chapitre suivant 44
CHAPITRE 3 ARCHITECTURE FONCTIONNELLE 45
3.1 Contexte de frontière en tant que composants logiciels autonomes 46
3.2 Communication entre contextes frontières 47
3.2.1 Transfert de données entre contextes limites 48 / 3.2.2 Limites de confiance et vérification 49
3.3 Contrats entre contextes frontières 50
3.3.1 Couche anti-corruption 51 / 3.3.2 Carte contextuelle représentant les relations intercontextuelles 51
3.4 Flux de travail du contexte de frontière 52
3.4.1 Entrées et sorties du flux de travail 53 / 3.4.2 Interdiction des événements de domaine dans les contextes limites 54
3.5 Structure du code dans le contexte de frontière 55
3.5.1 Architecture en oignon 56 / 3.5.2 Suppression des E/S externes des limites de contexte 57
3.6 Finale 57
__3.6.1 Guide du chapitre suivant 58
PARTIE II Modélisation du domaine
CHAPITRE 4 Comprendre les types 61
4.1 Comprendre les fonctions 61
4.1.1 Comprendre les fonctions 62
4.2 Types et fonctions 63
4.3 Synthèse de type 66
__4.3.1 ET type 67 / 4.3.2 OU type 67 / 4.3.3 Type simple 69 / 4.3.4 Système de types algébriques 69
4.4 Gestion des types TypeScript et Kotlin 70
4.5 Création d'un modèle de domaine de type 73
4.6 Modélisation des valeurs manquantes, des erreurs et des collections 77
4.6.1 Modélisation des valeurs optionnelles 78 / 4.6.2 Modélisation des erreurs 79 / 4.6.3 Modélisation de l'absence de valeurs 80 / 4.6.4 Modélisation des listes et des collections 81
4.7 Final 83
CHAPITRE 5 : Modélisation des domaines avec des types 85
5.1 Réexamen du modèle de domaine 85
5.2 Recherche de modèles dans le modèle de domaine 87
5.3 Modélisation simple des valeurs 87
5.3.1 Utilisation des types wrapper 89 / 5.3.2 Valeurs contraintes 90 / 5.3.3 Atténuation des problèmes de performance avec les types simples 90
5.4 Modélisation de données complexes 92
5.4.1 Modélisation des enregistrements 92 / 5.4.2 Modélisation des types inconnus 93 / 5.4.3 Modélisation des types sélectionnés 94
5.5 Modélisation des flux de travail avec des fonctions 95
5.5.1 Gestion des entrées et sorties complexes 96 / 5.5.2 Documentation des effets dans les signatures de fonctions 99
5.6 Sur l'identité : Objets de valeur 100
__5.6.1 Égalité des objets de valeur 102
5.7 Sur l'identité : Entité 103
5.7.1 Identifiants d'entités 103 / 5.7.2 Inclusion des identifiants dans les définitions de données 104 / 5.7.3 Égalité des entités 106 / 5.7.4 Immuabilité et identité 108
5.8 Assemblage 110
5.8.1 Agrégats responsables de la cohérence et de l'invariance 112 / 5.8.2 Référence des agrégats 112
5.9 Synthèse 115
5.9.1 Repenser le défi : les types peuvent-ils vraiment remplacer les documents ? 119
5.10 Arrivée 120
CHAPITRE 6 Intégrité et cohérence du domaine 121
6.1 Intégrité des valeurs simples 122
6.2 Unités de mesure 126
6.3 Imposition de l'immuabilité avec le système de types 128
6.4 Intégration des règles métier au système de types 128
6.4.1 Modification du domaine d'exemple pour éviter les états incorrects 133
6.5 Cohérence 135
6.5.1 Cohérence au sein d'une même collection 135 / 6.5.2 Cohérence entre différents contextes 137 / 6.5.3 Cohérence entre les collections dans un même contexte 138 / 6.5.4 Plusieurs collections traitant les mêmes données 140
6.6 Arrivée 140
CHAPITRE 7 Modélisation des flux de travail avec des pipelines 141
7.1 Flux de travail Entrée 142
7.1.1 Utilisation des commandes comme entrée 143 / 7.1.2 Généralisation des structures communes 144 / 7.1.3 Regroupement de plusieurs commandes en un seul type 145
7.2 Modélisation des commandes sous forme d'ensembles d'états 146
7.2.1 Ajout de nouveaux types d'état en fonction de l'évolution des besoins 149
7.3 Machine à états 149
7.3.1 Pourquoi utiliser une machine à états ? 151 / 7.3.2 Comment implémenter une machine à états simple avec TypeScript et Kotlin 151
7.4 Modélisation des étapes individuelles d'un flux de travail avec le type 153
7.4.1 Étape de validation 153 / 7.4.2 Étape de tarification 156 / 7.4.3 Étape de confirmation de commande 157 / 7.4.4 Création d'événements à retourner 160
7.5 Documenter les effets 162
7.5.1 Effet de l'étape de vérification 162 / 7.5.2 Effet de l'étape de calcul du prix 164 / 7.5.3 Effet de l'étape de confirmation de commande 165
7.6 Synthèse d'un flux de travail à partir d'étapes individuelles 166
7.7 Faut-il inclure les dépendances dans votre conception ? 167
7.8 Pipeline complet 169
__7.8.1 Étape interne 171
7.9 Flux de travail de longue durée 175
7.10 Finale 176
__7.10.1 Guide du chapitre suivant 177
PARTIE III Mise en œuvre du modèle
CHAPITRE 8 Comprendre les fonctions 181
8.1 Des fonctions, des fonctions partout 182
8.2 La fonction est le personnage principal 183
8.2.1 Fonctions comme protagonistes 184 / 8.2.2 Fonctions comme entrées 185 / 8.2.3 Fonctions comme sorties 186 / 8.2.4 Currying 187 / 8.2.5 Application partielle 188
8.3 Fonctions complètes 189
8.4 Composition fonctionnelle 192
8.4.1 Composition de fonctions en TypeScript et Kotlin 193 / 8.4.2 Création d'applications complètes avec des fonctions 195 / 8.4.3 Composition de fonctions : un exercice plus complexe 196
8,5 Terminer 198
CHAPITRE 9 Mise en œuvre : Combinaison de pipelines 199
9.1 Gestion des types simples 200
9.2 Guide d'implémentation avec les types de fonctions 202
9.3 Mise en œuvre de l'étape de validation 204
9.3.1 Génération d'une adresse valide 207 / 9.3.2 Création d'un article de commande 209 / 9.3.3 Création d'un adaptateur de fonction 211
9.4 Mise en œuvre des étapes restantes 214
9.4.1 Mise en œuvre de l'étape d'approbation 218 / 9.4.2 Création d'un événement 220
9.5 Assemblage de toutes les étapes du pipeline 224
9.6 Injection de dépendances 227
__9.6.1 Dépendance excessive 235
9.7 Tests de dépendance 237
9.8 Pipeline assemblé 240
9,9 Arrivée 244
CHAPITRE 10 Mise en œuvre : Gestion des erreurs 247
10.1 Détection des erreurs de type 247
10.2 Gestion des erreurs de domaine 249
10.2.1 Modélisation des erreurs de domaine avec des types 251 / 10.2.2 Gestion des erreurs qui encombrent votre code 253
10.3 Connexion de fonctions qui produisent des types Either 255
10.3.1 Implémentation d'un bloc adaptateur 258 / 10.3.2 Gestion des fonctions Either 260 / 10.3.3 Composition de fonctions et vérification de type 261 / 10.3.4 Conversion vers des types d'erreurs courants 262
10.4 Assemblage d'un pipeline avec FlatMap et Map 266
10.5 Adaptation d'autres types de fonctions au modèle à double voie 269
10.5.1 Gestion des exceptions 269 / 10.5.2 Gestion des fonctions sans issue 273
10.6 Gestion des pipelines complexes 275
__10.6.1 Notation « do » de fp-ts 275 / 10.6.2 Bloc « either » d'arrow-kt 277 / 10.6.3 Contexte « Raise » d'arrow-kt 278 / 10.6.4 Vérification de l'ordre avec le type « Either » 282 / 10.6.5 Validation des listes « Either » 283
10.7 Monades et autres concepts 286
__10.7.1 Synthèse parallèle et applications 287
10.8 Ajout d'effets asynchrones 287
10.9 Arrivée 291
CHAPITRE 11 SÉRIALISATION 293
11.1 Persistance et sérialisation 293
11.2 Conception pour la sérialisation 294
11.3 Connexion du code de sérialisation à un flux de travail 295
__11.3.1 DTO 296 en tant que contrat entre contextes frontières
11.4 Exemple de sérialisation complète 297
11.4.1 Intégration d'une bibliothèque de sérialisation JSON 301 / 11.4.2 Pipeline de sérialisation complet 302 / 11.4.3 Gestion de plusieurs versions d'un type de sérialisation 306
11.5 Comment convertir un type de domaine en DTO 306
11.5.1 Types simples 306 / 11.5.2 Valeurs optionnelles 307 / 11.5.3 Enregistrements 307 / 11.5.4 Collections 308 / 11.5.5 Énumérations 310 / 11.5.6 Tuples 311 / 11.5.7 Types de choix 312 / 11.5.8 Sérialisation des types d'enregistrements et de choix avec des dictionnaires 317 / 11.5.9 Génériques 320
11,6 Arrivée 321
CHAPITRE 12 Perpétuation 323
12.1 Déploiement du code de persistance en périphérie 324
12.1.1 Prise de décision basée sur les données d'entrée 329 / 12.1.2 Où se situe le modèle de référentiel ? 330
12.2 Séparation des commandes de mise à jour et des requêtes d'interrogation 331
12.2.1 Séparation des responsabilités commande-requête 334 / 12.2.2 Séparation CQRS et base de données 336 / 12.2.3 Event Sourcing 336
12.3 Posséder un magasin de données de lecteur pour chaque contexte de limite 337
12.3.1 Comment utiliser des données provenant de plusieurs domaines 337
12.4 Utilisation des bases de données documentaires 339
12.5 Utilisation des bases de données relationnelles 339
12.5.1 Association des types de sélection aux tables 341 / 12.5.2 Association des types imbriqués aux tables 344 / 12.5.3 Lecture d'une base de données relationnelle 345 / 12.5.4 Lecture des types de sélection depuis une base de données relationnelle 352 / 12.5.5 Écriture dans une base de données relationnelle 355
12.6 Transaction 358
12.7 Finir 360
CHAPITRE 13 Conception propre 361
13.1 Première modification : Ajout des frais de livraison 362
13.1.1 Simplification de la logique métier par la séparation des préoccupations 363 / 13.1.2 Ajout d'une nouvelle étape à un flux de travail 364 / 13.1.3 Autre raison d'ajouter une nouvelle étape à un pipeline 368
13.2 Deuxième modification : Ajout d’un support client VIP 368
13.2.1 Ajout d'une nouvelle entrée à un flux de travail 371 / 13.2.2 Ajout d'une règle de livraison gratuite à un flux de travail 373
13.3 Troisième modification : Ajout de la prise en charge des codes promotionnels 374
13.3.1 Ajout d'un code promotionnel au modèle de domaine 374 / 13.3.2 Modification de la logique de tarification 376 / 13.3.3 Implémentation de la fonction GetPricingFunction 378 / 13.3.4 Documentation des remises sur les articles de commande 379 / 13.3.5 Systèmes de tarification plus complexes 381 / 13.3.6 Modification d'un contrat entre contextes limites 382 / 13.3.7 Impression des commandes 384
13.4 Quatrième modification : Ajout de restrictions sur les heures d’ouverture 384
13.5 Gestion des modifications d'exigences supplémentaires 386
13,6 Arrivée 386
13.7 Fin du livre 387
Recherche 390
Image détaillée

Dans le livre
La plupart des gens pensent probablement que le travail d'un programmeur consiste à écrire du code.
Mais je ne suis pas d'accord.
Le travail d'un programmeur consiste à résoudre des problèmes à l'aide de logiciels, et la programmation n'est qu'un aspect du développement logiciel.
Un bon design et une bonne communication sont tout aussi importants que le codage.
Si l'on considère le développement logiciel comme un processus qui prend en entrée des exigences et produit le résultat final, la loi du « mauvaises données en entrée, mauvaises données en sortie » s'applique également ici.
Aucun code ne produira le résultat souhaité avec des entrées incorrectes, telles que des exigences imprécises ou une conception défectueuse.
--- p.3
C'est le moment idéal pour jeter un coup d'œil rapide sur la manière d'implémenter un modèle de domaine dans un logiciel.
Dans les cycles de développement rapides, on se retrouve souvent à implémenter des parties d'un domaine avant même de comprendre l'ensemble du domaine.
Avant de construire tous les composants, nous devons donc déterminer comment les combiner.
Il y a également beaucoup à dire sur la création d'un « squelette fonctionnel », un prototype rudimentaire qui démontre comment l'ensemble du système pourrait fonctionner.
Explorer dès le début quoi faire et comment le mettre en œuvre est la meilleure façon de déterminer ce que vous ne comprenez pas encore pleinement.
--- p.45
Maintenant que vous avez pris la peine de modéliser correctement votre domaine, vous devez prendre certaines précautions pour garantir que toutes les données de votre domaine sont valides et cohérentes.
Nous veillerons à ce que seules des données fiables existent au sein d'un périmètre défini, séparées du monde extérieur non fiable.
Si vous pouvez être sûr que toutes les données dans un contexte donné sont toujours valides, vous pouvez éviter le code défensif inutile et obtenir une implémentation plus propre.
--- p.121
Jusqu'à présent, nous avons identifié les exigences de notre flux de travail de traitement des commandes et les avons modélisées en différents types.
La prochaine étape consiste à implémenter cette conception selon les principes de la programmation fonctionnelle.
Avant d'entrer dans le vif du sujet, il est important de comprendre ce qu'est la programmation fonctionnelle ainsi que les outils et les stratégies nécessaires à sa mise en œuvre.
À la fin de ce chapitre, vous aurez une solide compréhension des concepts fondamentaux de la programmation fonctionnelle.
Ces concepts sont utiles non seulement pour la conception axée sur le domaine, mais aussi pour tous les types de programmation.
--- p.181
Chaque étape du pipeline est implémentée comme une fonction indépendante.
Les fonctions doivent être implémentées sans état ni effets de bord, afin qu'elles puissent être testées et analysées indépendamment.
Ensuite, nous combinons ces petites fonctions en une seule grande fonction.
C'est facile à dire, mais lorsqu'on le fait réellement, on rencontre souvent des problèmes où la sortie des fonctions conçues et l'entrée de la fonction suivante ne correspondent pas.
Pour résoudre ce problème, vous devez apprendre à manipuler les entrées et les sorties de chaque étape afin que les fonctions soient composables.
--- p.200
Ce chapitre explique comment assurer la persistance de votre modèle de domaine.
Commençons par aborder les principes généraux, tels que la séparation des commandes et des requêtes, puis examinons les détails de mise en œuvre.
Nous explorons en particulier deux implémentations pour la persistance des modèles de domaine dans les bases de données documentaires NoSQL et les bases de données SQL traditionnelles.
À la fin de ce chapitre, vous disposerez de toutes les connaissances nécessaires pour intégrer les mécanismes de persistance.
Mais je ne suis pas d'accord.
Le travail d'un programmeur consiste à résoudre des problèmes à l'aide de logiciels, et la programmation n'est qu'un aspect du développement logiciel.
Un bon design et une bonne communication sont tout aussi importants que le codage.
Si l'on considère le développement logiciel comme un processus qui prend en entrée des exigences et produit le résultat final, la loi du « mauvaises données en entrée, mauvaises données en sortie » s'applique également ici.
Aucun code ne produira le résultat souhaité avec des entrées incorrectes, telles que des exigences imprécises ou une conception défectueuse.
--- p.3
C'est le moment idéal pour jeter un coup d'œil rapide sur la manière d'implémenter un modèle de domaine dans un logiciel.
Dans les cycles de développement rapides, on se retrouve souvent à implémenter des parties d'un domaine avant même de comprendre l'ensemble du domaine.
Avant de construire tous les composants, nous devons donc déterminer comment les combiner.
Il y a également beaucoup à dire sur la création d'un « squelette fonctionnel », un prototype rudimentaire qui démontre comment l'ensemble du système pourrait fonctionner.
Explorer dès le début quoi faire et comment le mettre en œuvre est la meilleure façon de déterminer ce que vous ne comprenez pas encore pleinement.
--- p.45
Maintenant que vous avez pris la peine de modéliser correctement votre domaine, vous devez prendre certaines précautions pour garantir que toutes les données de votre domaine sont valides et cohérentes.
Nous veillerons à ce que seules des données fiables existent au sein d'un périmètre défini, séparées du monde extérieur non fiable.
Si vous pouvez être sûr que toutes les données dans un contexte donné sont toujours valides, vous pouvez éviter le code défensif inutile et obtenir une implémentation plus propre.
--- p.121
Jusqu'à présent, nous avons identifié les exigences de notre flux de travail de traitement des commandes et les avons modélisées en différents types.
La prochaine étape consiste à implémenter cette conception selon les principes de la programmation fonctionnelle.
Avant d'entrer dans le vif du sujet, il est important de comprendre ce qu'est la programmation fonctionnelle ainsi que les outils et les stratégies nécessaires à sa mise en œuvre.
À la fin de ce chapitre, vous aurez une solide compréhension des concepts fondamentaux de la programmation fonctionnelle.
Ces concepts sont utiles non seulement pour la conception axée sur le domaine, mais aussi pour tous les types de programmation.
--- p.181
Chaque étape du pipeline est implémentée comme une fonction indépendante.
Les fonctions doivent être implémentées sans état ni effets de bord, afin qu'elles puissent être testées et analysées indépendamment.
Ensuite, nous combinons ces petites fonctions en une seule grande fonction.
C'est facile à dire, mais lorsqu'on le fait réellement, on rencontre souvent des problèmes où la sortie des fonctions conçues et l'entrée de la fonction suivante ne correspondent pas.
Pour résoudre ce problème, vous devez apprendre à manipuler les entrées et les sorties de chaque étape afin que les fonctions soient composables.
--- p.200
Ce chapitre explique comment assurer la persistance de votre modèle de domaine.
Commençons par aborder les principes généraux, tels que la séparation des commandes et des requêtes, puis examinons les détails de mise en œuvre.
Nous explorons en particulier deux implémentations pour la persistance des modèles de domaine dans les bases de données documentaires NoSQL et les bases de données SQL traditionnelles.
À la fin de ce chapitre, vous disposerez de toutes les connaissances nécessaires pour intégrer les mécanismes de persistance.
--- p.323
Avis de l'éditeur
● Comment bien comprendre les domaines
Repenser le DDD avec la pensée fonctionnelle
● Technique de modélisation pour la conception par type
● Logique métier exprimée sous forme de pipeline
● Concevoir pour bloquer les erreurs à la compilation
● Intégration flexible avec les bases de données
● Modélisation du domaine : le code et la documentation ne font plus qu'un.
Repenser le DDD avec la pensée fonctionnelle
● Technique de modélisation pour la conception par type
● Logique métier exprimée sous forme de pipeline
● Concevoir pour bloquer les erreurs à la compilation
● Intégration flexible avec les bases de données
● Modélisation du domaine : le code et la documentation ne font plus qu'un.
SPÉCIFICATIONS DES PRODUITS
- Date d'émission : 20 novembre 2025
- Nombre de pages, poids, dimensions : 416 pages | 188 × 245 × 20 mm
- ISBN13 : 9791194587897
Vous aimerez peut-être aussi
카테고리
Langue coréenne
Langue coréenne