À mon avis, ce n'est absolument pas ce que cela veut dire. Et c'est une violation de DRY.
L'idée est que l'objet entité / domaine au milieu est modélisé pour représenter le domaine aussi bien et aussi facilement que possible. Il est au centre de tout et tout peut en dépendre puisque le domaine lui-même ne change pas la plupart du temps.
Si votre base de données à l'extérieur peut stocker ces objets directement, il est non seulement inutile de les mapper vers un autre format afin de séparer les calques, mais de créer des doublons du modèle et ce n'est pas l'intention.
Pour commencer, l'architecture propre a été conçue en tenant compte d'un environnement / scénario typique différent. Applications de serveur d'entreprise avec des couches externes gigantesques ayant besoin de leurs propres types d'objets spéciaux. Par exemple, les bases de données qui produisent des SQLRow
objets et doivent SQLTransactions
en retour mettre à jour des éléments. Si vous utilisiez celles du centre, vous violeriez le sens de la dépendance car votre noyau dépendrait de la base de données.
Avec des ORM légers qui chargent et stockent des objets d'entité, ce n'est pas le cas. Ils font le mappage entre leur domaine interne SQLRow
et votre domaine. Même si vous devez mettre une @Entitiy
annotation de l'ORM dans votre objet de domaine, je dirais que cela n'établit pas une "mention" de la couche externe. Les annotations n'étant que des métadonnées, aucun code qui ne les recherche pas ne les verra. Et plus important encore, rien ne doit changer si vous les supprimez ou les remplacez par une annotation de base de données différente.
En revanche, si vous changez de domaine et que vous créez tous ces mappeurs, vous devez beaucoup changer.
Amendement: ci-dessus est un peu trop simpliste et pourrait même être faux. Parce qu’une partie de l’architecture propre vous demande de créer une représentation par couche. Mais cela doit être vu dans le contexte de l'application.
Voici ce qui suit: https://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html
L'important est que des structures de données isolées et simples traversent les limites. Nous ne voulons pas tricher et passer des lignes Entities ou Database. Nous ne voulons pas que les structures de données aient un type de dépendance qui enfreint la règle de dépendance.
Passer des entités du centre vers les couches extérieures ne viole pas la règle de dépendance, pourtant elles sont mentionnées. Mais cela a une raison dans le contexte de l'application envisagée. Passer des entités déplacerait la logique d'application vers l'extérieur. Les couches externes doivent savoir comment interpréter les objets internes, elles doivent effectivement faire ce que les couches internes, comme le "cas d'utilisation", est censé faire.
En outre, il dissocie également les couches de sorte que les modifications apportées au cœur ne nécessitent pas nécessairement des modifications des couches externes (voir le commentaire de SteveCallender). Dans ce contexte, il est facile de voir comment les objets devraient représenter spécifiquement le but pour lequel ils sont utilisés. De plus, ces couches doivent communiquer entre elles en termes d’objets spécialement conçus pour les besoins de cette communication. Cela peut même signifier qu'il y a 3 représentations, 1 dans chaque couche, 1 pour le transport entre les couches.
Et il y a https://blog.8thlight.com/uncle-bob/2011/11/22/Clean-Architecture.html qui aborde ci-dessus:
D'autres personnes ont craint que le résultat final de mes conseils ne soit une grande quantité de code dupliqué et beaucoup de copies par cœur de données d'une structure de données à une autre à travers les couches du système. Certainement, je ne le veux pas non plus; et rien de ce que j'ai suggéré ne mènerait inévitablement à la répétition de structures de données et à une copie anormale de la copie sur le terrain.
Cette OMI implique que la copie simple d'objets 1: 1 est une odeur dans l'architecture, car vous n'utilisez pas les calques et / ou les abstractions appropriés.
Il explique ensuite comment il imagine toute la "copie"
Vous séparez l'interface utilisateur des règles de gestion en passant des structures de données simples entre les deux. Vous ne laissez pas vos contrôleurs connaître les règles commerciales. Au lieu de cela, les contrôleurs décompactent l'objet HttpRequest dans une structure de données simple vanilla, puis transmettent cette structure de données à un objet interactor qui implémente le cas d'utilisation en appelant des objets métier. L'interacteur rassemble ensuite les données de réponse dans une autre structure de données vanilla et les renvoie à l'interface utilisateur. Les vues ne connaissent pas les objets métier. Ils ne font que regarder dans cette structure de données et présenter la réponse.
Dans cette application, il y a une grande différence entre les représentations. Les données qui circulent ne sont pas simplement les entités. Et cela justifie et exige différentes classes.
Cependant, appliqué à une application Android simple, telle qu'une visionneuse de photos, où l' Photo
entité a environ 0 règles commerciales et où le "cas d'utilisation" qui les traite est quasiment inexistant et se préoccupe davantage de la mise en cache et du téléchargement (ce processus plus explicitement), le point de faire des représentations séparées d’une photo commence à disparaître. J'ai même l'impression que la photo elle-même est un objet de transfert de données alors que la véritable couche métier-logique-cœur-couche manque.
Il existe une différence entre "séparer l'interface utilisateur des règles de gestion en passant des structures de données simples entre les deux" et "lorsque vous souhaitez afficher une photo, renommez-la 3 fois en cours de route" .
En outre, je vois que les applications de démonstration ne parviennent pas à représenter l’architecture propre, c’est qu’elles ajoutent un accent important sur la séparation des couches dans l’intérêt de les séparer, tout en masquant efficacement le travail de l’application. Cela contraste avec ce qui est dit dans https://blog.8thlight.com/uncle-bob/2011/09/30/Screaming-Architecture.html - à savoir que
l'architecture d'une application logicielle crie sur les cas d'utilisation de l'application
Je ne vois pas cet accent mis sur la séparation des couches dans une architecture épurée. Il s’agit de l’orientation des dépendances et de la représentation du noyau de l’application - entités et cas d’utilisation - dans l’idéal java sans dépendances vers l’extérieur. Ce n'est pas tellement une question de dépendance envers ce noyau.
Par conséquent, si votre application comporte un noyau qui représente les règles métier et les cas d'utilisation, et / ou que différentes personnes travaillent sur des couches différentes, veuillez les séparer de la manière souhaitée. Si vous écrivez simplement une application simple par vous-même, n'en faites pas trop. 2 couches avec des limites fluides peuvent être plus que suffisantes. Et des couches peuvent également être ajoutées plus tard.
BankAccount
mais avec des règles spécifiques à l’application, vous permettent de gérer ce compte.@SerializedName
mettriez-vous des annotations Gson sur un modèle de domaine? Ou créeriez-vous un nouvel objet chargé de mapper la réponse Web au modèle de domaine?Vous avez vraiment tout compris. Et il n'y a pas de violation de DRY parce que vous acceptez SRP.
Par exemple: vous avez une méthode business createX (nom de chaîne), puis vous pouvez avoir une méthode createX (nom chaîne) dans la couche DAO, appelée dans la méthode métier. Ils peuvent avoir la même signature et peut-être qu'il n'y a qu'une délégation, mais ils ont des objectifs différents. Vous pouvez également avoir un createX (nom de chaîne) sur le UseCase. Même dans ce cas, ce n’est pas redondant. Ce que je veux dire par là est que: Les mêmes signatures ne signifient pas la même sémantique. Choisissez d'autres noms pour que la sémantique soit claire. Se nommer lui-même n'affecte pas du tout SRP.
Le UseCase est responsable de la logique spécifique à l'application, l'objet métier est responsable de la logique indépendante de l'application et le DAO est responsable du stockage.
En raison de la sémantique différente, toutes les couches peuvent avoir leur propre modèle de représentation et de communication. Souvent, vous voyez les «entités» comme des «objets métier» et souvent, vous ne voyez pas la nécessité de les séparer. Mais dans les projets "énormes", des efforts doivent être déployés pour séparer correctement les couches. Plus le projet est important, plus il est possible que vous ayez besoin des différentes sémantiques représentées dans différentes couches et classes.
Vous pouvez penser à différents aspects de la même sémantique. Un objet utilisateur doit être affiché à l'écran, il a des règles de cohérence internes et il doit être stocké quelque part. Chaque aspect doit être représenté dans une classe différente (SRP). La création des cartographes peut être pénible alors dans la plupart des projets sur lesquels j'ai travaillé, ces aspects sont fondus en une seule classe. C'est clairement une violation du PÉR, mais personne ne s'en soucie vraiment.
J'appelle l'application d'architecture propre et SOLID "non socialement acceptable". Je travaillerais avec si on me le permettait. Actuellement, je n'ai pas le droit de le faire. J'attends le moment où nous devons penser à prendre SOLID au sérieux.
la source
Non, vous n'avez pas besoin de créer des classes de modèle dans chaque couche.
Entity (
DATA_LAYER
) - est une représentation complète ou partielle de l'objet Database.DATA_LAYER
Mapper (
DOMAIN_LAYER
) - est en fait une classe qui convertit Entity en ModelClass, qui sera utilisée surDOMAIN_LAYER
Jetez un coup d'oeil: https://github.com/lifedemons/photoviewer
la source