web-dev-qa-db-fra.com

La conception pilotée par domaine est-elle un modèle anti-SQL?

Je plonge dans la conception pilotée par domaine (DDD) et même si j'y vais plus profondément, il y a certaines choses que je ne comprends pas. Si je comprends bien, un point principal est de séparer la logique du domaine (Business Logic) de l'infrastructure (DB, système de fichiers, etc.).

Ce que je me demande, c'est ce qui se passe quand j'ai des requêtes très complexes comme une requête de calcul des ressources matérielles? Dans ce type de requête, vous travaillez avec des opérations d'ensemble lourdes, le genre de chose pour laquelle SQL a été conçu. Faire ces calculs à l'intérieur de la couche de domaine et travailler avec de nombreux ensembles, c'est comme jeter la technologie SQL.

Faire ces calculs dans l'infrastructure ne peut pas se produire aussi, car le modèle DDD permet des changements dans l'infrastructure sans changer la couche de domaine et sachant que MongoDB n'a pas les mêmes capacités, par exemple SQL Server, cela ne peut pas arriver.

Est-ce un écueil du modèle DDD?

46
Leonardo Mangano

De nos jours, vous verrez probablement les lectures (requêtes) traitées différemment des écritures (commandes). Dans un système avec une requête compliquée, il est peu probable que la requête elle-même passe par le modèle de domaine (qui est principalement responsable du maintien de la cohérence des écritures ).

Vous avez tout à fait raison de dire que nous devons rendre à SQL ce qui est SQL. Nous allons donc concevoir un modèle de données optimisé autour des lectures, et une requête de ce modèle de données prendra généralement un chemin de code qui n'inclut pas le modèle de domaine (à l'exception possible d'une validation d'entrée - en veillant à ce que dans la requête sont raisonnables).

39
VoiceOfUnreason

Si je comprends bien, un point principal est de séparer la logique du domaine (Business Logic) de l'infrastructure (DB, système de fichiers, etc.).

C'est le fondement du malentendu: le but de DDD n'est pas de séparer les choses le long d'une ligne dure comme "c'est dans le serveur SQL, donc ne doit pas être BL", le but de DDD est de séparer les domaines et de créer des barrières entre ceux qui permettent aux internes d'un domaine d'être complètement séparés des internes d'un autre domaine, et de définir entre eux des externes partagés.

Ne pensez pas à "être en SQL" comme barrière BL/DL - ce n'est pas ce que c'est. Au lieu de cela, pensez à "c'est la fin du domaine interne" comme barrière.

Chaque domaine doit avoir des API orientées vers l'extérieur qui lui permettent de fonctionner avec tous les autres domaines : dans le cas de stockage de données = couche, il doit avoir des actions de lecture/écriture (CRUD) pour les objets de données qu'il stocke. Cela signifie que SQL lui-même n'est pas vraiment la barrière, les composants VIEW et PROCEDURE le sont. Vous ne devriez jamais lire directement à partir du tableau: que est le détail de mise en œuvre DDD nous dit que, en tant que consommateur externe, nous ne devons pas nous inquiéter.

Considérez votre exemple:

Ce que je me demande, c'est ce qui se passe quand j'ai des requêtes très complexes comme une requête de calcul des ressources matérielles? Dans ce type de requête, vous travaillez avec des opérations d'ensemble lourdes, le genre de chose pour laquelle SQL a été conçu.

C'est exactement ce qui devrait être dans SQL, et ce n'est pas une violation de DDD. C'est ce pour quoi nous avons créé DDD . Avec ce calcul en SQL, cela devient partie du BL/DL. Ce que vous feriez serait d'utiliser une vue/procédure stockée/ce que vous avez séparé et de séparer la logique métier de la couche de données, comme que est votre API externe. En fait, votre couche de données devrait être une autre couche de domaine DDD, où votre couche de données possède ses propres abstractions pour fonctionner avec les autres couches de domaine.

Faire ces calculs dans l'infrastructure ne peut pas se produire aussi, car le modèle DDD permet des changements dans l'infrastructure sans changer la couche de domaine et en sachant que MongoDB n'a pas les mêmes capacités, par ex. SQL Server, cela ne peut pas arriver.

C'est un autre malentendu: il dit les détails de mise en œuvre en interne peuvent changer sans changer autre couches de domaine. Cela ne dit pas que vous pouvez simplement remplacer un élément d'infrastructure complet.

Encore une fois, gardez à l'esprit que DDD consiste à masquer les éléments internes avec des API externes bien définies. Où se situent ces API est une question totalement différente, et DDD ne le définit pas. Il définit simplement que ces API existent et ne devraient jamais changer .

DDD n'est pas configuré pour vous permettre de remplacer ad-hoc MSSQL par MongoDB - ce sont deux composants d'infrastructure totalement différents.

Au lieu de cela, utilisons une analogie pour ce que DDD définit: les voitures à essence ou électriques. Les deux véhicules ont deux méthodes complètement différentes pour créer la propulsion, mais ils ont les mêmes API: un marche/arrêt, un accélérateur/frein et des roues pour propulser le véhicule. DDD dit que nous devrions pouvoir remplacer le moteur (à essence ou électrique) de notre voiture. Cela ne dit pas que nous pouvons remplacer la voiture par une moto, et c'est effectivement ce qu'est MSSQL → MongoDB.

21
Der Kommissar

Si vous avez déjà été sur un projet où l'organisation payant pour héberger l'application décide que les licences de couche de base de données sont trop chères, vous apprécierez la facilité avec laquelle vous pouvez migrer votre base de données/stockage de données. Tout bien considéré, alors que cela se produit, cela ne se produit pas souvent .

Vous pouvez obtenir le meilleur des deux mondes pour ainsi dire. Si vous envisagez d'effectuer les fonctions complexes de la base de données comme une optimisation, vous pouvez utiliser une interface pour injecter une autre implémentation du calcul. Le problème est que vous devez maintenir la logique à plusieurs endroits.

Déviant d'un modèle architectural

Lorsque vous vous trouvez en désaccord avec la mise en œuvre d'un modèle purement, ou la déviation dans certains domaines, alors vous avez une décision à prendre. Un modèle est simplement une manière basée sur des modèles de faire des choses pour aider à organiser votre projet. À ce stade, prenez le temps d'évaluer:

  • Est-ce le bon schéma? (plusieurs fois c'est le cas, mais parfois c'est juste un mauvais ajustement)
  • Dois-je dévier de cette façon?
  • Jusqu'où ai-je dévié jusqu'à présent?

Vous constaterez que certains modèles architecturaux conviennent bien à 80 à 90% de votre application, mais pas tant aux bits restants. L'écart occasionnel par rapport au modèle prescrit est utile pour des raisons de performances ou de logistique.

Cependant, si vous constatez que vos écarts cumulés représentent bien plus de 20% de l'architecture de votre application, c'est probablement juste un mauvais ajustement.

Si vous choisissez de continuer avec l'architecture, faites-vous une faveur et documentez où et pourquoi vous vous êtes écarté de la manière prescrite de faire les choses. Lorsque vous obtenez un nouveau membre enthousiaste dans votre équipe, vous pouvez le diriger vers cette documentation qui comprend les mesures de performance et les justifications. Cela réduira la probabilité de demandes répétées pour résoudre le "problème". Cette documentation contribuera également à dissuader les écarts généralisés.

18
Berin Loritsch

La logique de manipulation des ensembles dans laquelle SQL est bon peut être intégrée à DDD sans problème.

Disons par exemple que j'ai besoin de connaître une valeur agrégée, le nombre total de produits par type. Facile à exécuter en sql, mais lent si je charge chaque produit en mémoire et les additionne tous.

Je présente simplement un nouvel objet Domain,

ProductInventory
{
    ProductType
    TotalCount
    DateTimeTaken
}

et une méthode sur mon référentiel

ProductRepository
{
    List<ProductInventory> TakeInventory(DateTime asOfDate) {...}
}

Bien sûr, je compte peut-être maintenant sur ma base de données ayant certaines capacités. Mais j'ai toujours techniquement la séparation et tant que la logique est simple, je peux affirmer que ce n'est pas de la "logique métier"

8
Ewan

L'une des façons possibles de résoudre ce dilemme est de considérer le SQL comme un langage d'assemblage: vous y codez rarement, voire pas du tout, mais là où les performances sont importantes, vous devez être en mesure de comprendre le code produit par votre C/C++/Golang/Rust et peut-être même écrire un petit extrait dans Assembly, si vous ne pouvez pas changer le code dans votre langage de haut niveau pour produire le code machine souhaité.

De même, dans le domaine des bases de données et SQL, diverses bibliothèques SQL (dont certaines sont OUM ), par exemple SQLAlchemy et Django ORM pour Python, LINQ pour .NET, fournissent encore des abstractions de niveau supérieur utiliser le code SQL généré lorsque cela est possible pour obtenir des performances. Ils fournissent également une certaine portabilité quant à la base de données utilisée, ayant éventuellement des performances différentes, par exemple sur Postgres et MySQL, en raison de certaines opérations utilisant un SQL spécifique à la base de données plus optimal.

Et tout comme avec les langages de haut niveau, il est essentiel de comprendre le fonctionnement de SQL, même s'il s'agit simplement de réorganiser les requêtes effectuées avec les bibliothèques SQL mentionnées ci-dessus, pour pouvoir atteindre l'efficacité souhaitée.

P.S. Je préfère en faire un commentaire mais je n'ai pas une réputation suffisante pour cela.

3
Kyrylo Shpytsya

Comme d'habitude, c'est l'une de ces choses qui dépend d'un certain nombre de facteurs. Il est vrai que vous pouvez faire beaucoup avec SQL. Il existe également des défis avec son utilisation et certaines limites pratiques des bases de données relationnelles.

Comme le note Jared Goguen dans les commentaires, SQL peut être très difficile à tester et à vérifier. Les principaux facteurs qui y conduisent sont qu'il ne peut pas (en général) être décomposé en composants. En pratique, une requête complexe doit être considérée in toto. Un autre facteur de complication est que le comportement et l'exactitude de SQL dépendent fortement de la structure et du contenu de vos données. Cela signifie que tester tous les scénarios possibles (ou même déterminer ce qu'ils sont) est souvent impossible ou impossible. La refactorisation de SQL et la modification de la structure de la base de données sont également problématiques.

L'autre grand facteur qui a conduit à s'éloigner de SQL est que les bases de données relationnelles ont tendance à évoluer uniquement verticalement. Par exemple, lorsque vous créez des calculs complexes en SQL à exécuter dans SQL Server, ils vont s'exécuter sur la base de données. Cela signifie que tout ce travail utilise des ressources sur la base de données. Plus vous en faites en SQL, plus votre base de données aura besoin de ressources en termes de mémoire et de CPU. Il est souvent moins efficace de faire ces choses sur d'autres systèmes, mais il n'y a pas de limite pratique au nombre de machines supplémentaires que vous pouvez ajouter à une telle solution. Cette approche est moins coûteuse et plus tolérante aux pannes que la construction d'un serveur de base de données monstre.

Ces problèmes peuvent s'appliquer ou non au problème en question. Si vous êtes en mesure de résoudre votre problème avec les ressources de base de données disponibles, peut-être que SQL convient à votre problème. Vous devez cependant tenir compte de la croissance. Ça va peut-être bien aujourd'hui, mais dans quelques années, le coût de l'ajout de ressources supplémentaires peut devenir un problème.

2
JimmyJames

Est-ce un écueil du modèle DDD?

Permettez-moi d'abord de clarifier quelques idées fausses.

DDD n'est pas un modèle. Et il ne prescrit pas vraiment de modèles.

La préface de DDD d'Eric Evan livre déclare:

Les principaux concepteurs de logiciels reconnaissent la modélisation et la conception de domaines comme des sujets critiques depuis au moins 20 ans, mais étonnamment peu de choses ont été écrites sur ce qui doit être fait ou comment le faire. Bien qu'elle n'ait jamais été formulée clairement, une philosophie est apparue comme un courant sous-jacent dans la communauté des objets, une philosophie que j'appelle la conception axée sur le domaine.

[...]

Une caractéristique commune aux succès était un modèle de domaine riche qui a évolué à travers des itérations de conception et est devenu une partie du tissu du projet.

Ce livre fournit un cadre pour prendre des décisions de conception et un vocabulaire technique pour discuter de la conception de domaine. Il s'agit d'une synthèse des meilleures pratiques largement acceptées ainsi que de mes propres idées et expériences.

C'est donc une façon d'aborder le développement de logiciels et la modélisation de domaine, ainsi qu'un vocabulaire technique qui prend en charge ces activités (un vocabulaire qui comprend divers concepts et modèles). Ce n'est pas non plus quelque chose de complètement nouveau.

Une autre chose à garder à l'esprit est qu'un modèle de domaine n'est pas l'implémentation OO de celui-ci que l'on peut trouver dans votre système - c'est juste une façon de l'exprimer, ou d'en exprimer une partie. Un modèle de domaine est la façon dont vous pensez au problème vous êtes essayer de résoudre avec le logiciel. C'est comment vous comprenez et percevez les choses, comment vous en parlez. C'est conceptuel . Mais pas dans un sens vague. C'est approfondi et affiné, et résulte d'un travail acharné et de la collecte de connaissances. Il est encore affiné et probablement évolué au fil du temps, et il implique des considérations de mise en œuvre (dont certaines peuvent contraindre le modèle). Il devrait être partagé par tous les membres de l'équipe (et les experts du domaine impliqués), et il devrait guider la façon dont vous implémentez le système, afin que le système le reflète étroitement.

Rien à ce sujet n'est intrinsèquement pro- ou anti-SQL, bien que OO les développeurs soient généralement mieux à même d'exprimer le modèle en OO langages, et l'expression de nombreux Les concepts de domaine sont mieux pris en charge par la POO, mais parfois des parties du modèle doivent être exprimées dans un paradigme différent.

Je me demande ce qui se passe quand j'ai des requêtes très complexes [...]?

Eh bien, d'une manière générale, il y a deux scénarios ici.

Dans le premier cas, certains aspects d'un domaine nécessitent vraiment une requête complexe, et peut-être que cet aspect est mieux exprimé dans le paradigme SQL/relationnel - utilisez donc l'outil approprié pour le travail. Refléter ces aspects dans la réflexion de votre domaine et le langage utilisé dans la communication des concepts. Si le domaine est complexe, il s'agit peut-être d'une partie d'un sous-domaine avec son propre contexte borné.

L'autre scénario est que le besoin perçu d'exprimer quelque chose en SQL est le résultat d'une réflexion contrainte. Si une personne ou une équipe a toujours été orientée vers la base de données dans sa pensée, il peut être difficile pour eux, simplement en raison de l'inertie, de voir une manière différente d'aborder les choses. Cela devient un problème lorsque l'ancienne méthode ne répond pas aux nouveaux besoins et nécessite une réflexion hors des sentiers battus. DDD, en tant qu'approche de la conception, consiste en partie à trouver des moyens de sortir de cette boîte en rassemblant et en distillant les connaissances sur le domaine. Mais tout le monde semble ignorer cette partie du livre et se concentre sur une partie du vocabulaire technique et des modèles énumérés.

2

La suite est devenue populaire lorsque la mémoire était chère, car le modèle de données relationnel offrait la possibilité de normaliser vos données et de les stocker efficacement dans le système de fichiers.

Maintenant, la mémoire est relativement bon marché, nous pouvons donc ignorer la normalisation et stocker dans le format que nous utilisons ou même dupliquer beaucoup de mêmes données par souci de vitesse.

Considérez la base de données comme simple IO device, quelle responsabilité de stocker les données dans le système de fichiers - oui je sais qu'il est difficile de l'imaginer, car nous avons écrit beaucoup d'applications avec une logique métier importante écrite dans des requêtes SQL - mais essayez d'imaginer que SQL Server n'est qu'une autre imprimante.

Souhaitez-vous incorporé le générateur PDF dans le pilote d'imprimante ou ajouté un déclencheur qui imprimera la page de journal pour chaque commande client imprimée sur notre imprimante?

Je suppose que la réponse sera non, car nous ne voulons pas que nos applications soient couplées au type d'appareil spécifique (sans même parler de l'efficacité d'une telle idée)

Dans les années 70 et 90, la base de données SQL était efficace, maintenant? - Pas sûr, dans certains scénarios, une requête de données asynchrone renvoie les données requises plus rapidement que plusieurs jointures dans une requête SQL.

SQL n'a pas été conçu pour les requêtes complexes, il a été conçu pour stocker les données de manière efficace, puis fournir une interface/un langage pour interroger les données stockées.

Je dirais que construire votre application autour d'un modèle de données relationnel avec des requêtes compliquées est un abus du moteur de base de données. Bien sûr, les fournisseurs de moteurs de base de données sont satisfaits lorsque vous associez étroitement votre entreprise à leur produit - ils seront plus qu'heureux de fournir plus de fonctionnalités qui renforcent ce lien.

0
Fabio