Pour résumer l'histoire, il ne suffisait pas d'utiliser la même classe simplement parce qu'elles ont la même valeur.
Écrivons trois exemples légèrement différents. J'ai changé le contenu de traitement de manière appropriée, mais je lui ai fait la même configuration que la partie où j'ai eu du mal avec le service que je maintiens.
En fait, la conception de la classe est décidée sur la base de l'idée de DDD, mais cette fois, je dirai simplement que ce sera assez bon simplement en concevant le type.
domaines
ne doit pas dépendre de service
ou de table
(ne dessinez pas de flèche de domaines
vers autre chose que domaines
)Par exemple, supposons qu'un téléphone portable d'entreprise prêté à un employé soit cassé et remplacé. Recevez le numéro de série que vous utilisez actuellement et remplacez-le par le nouveau numéro de série préparé.
(SerialNumber)
et (SerialNumber, SerialNumber)
sont sujets aux bogues.
Étant donné que les deux numéros de série ne se distinguent que par le nom de la variable, il peut être compilé même avec (changé, changé)
. ..
Ensuite, probablement en recherchant les données avec le premier argument, cela ressemble à une exception d'exécution telle que "Un tel numéro de série n'est pas prêté".
(En aparté, je viens de remarquer, si je l'écris avec le complément de l'éditeur, je peux faire une erreur parce que les deux «changé» et «courant» sont de «c». Il est inattendu qu'une telle erreur soit un long mot)
Puisque domaines
n'a qu'une seule classe de nombres, la manipulation est simple et se refactorise à la méthode d'identification de toutes les parties qui travaillent dur avec le nom de la variable courant
et changé
avec les classes actuel
et changé
. ..
Ça fait du bien.
Finalement, il ira dans la même colonne de la même table, donc si vous allez à la couche aussi près que possible de la base de données, vous pouvez créer SerialNumber
à partir de CurrentSerialNumber
pour augmenter le degré d'abstraction.
Cependant, SerialNumber
doit être préparé près deTable
au lieu de domaines
et doit êtreSerialNumber.from (CurrentSerialNumber) ʻau lieu de
CurrentSerialNumber.toSerialNumber () . Si vous le générez avec
to,
domaindépend de
Table, et
domains vous permettra d'utiliser
SerialNumber`.
Par exemple, supposons qu'il existe un système de gestion des membres qui accepte les retraits des membres. Lors du retrait de l'adhésion, définissez le statut de retrait et indiquez la date de retrait vide pour mettre à jour le statut.
Il est difficile de se rendre compte de la cohérence de «Status», et «0..1» est assez sujet aux exceptions d'exécution.
Je ne sais pas quel ** membre j'ai obtenu de find (id)
, donc je le vérifie.
Après cela, même lorsque le statut de membre est retiré et rendu permanent, si le paramètre est erroné, quelque chose qui n'est pas retiré sera rendu permanent.
Si un tel système de mise à jour de l'état est transformé en une classe différente pour chaque état, une quantité considérable de mines terrestres peut être éliminée.
Les «membres non abonnés» ne peuvent être créés qu'à partir des «membres en cours d'utilisation», les «membres en cours d'utilisation» ont toujours une date de retrait et les «membres retirés» ont toujours une date de retrait.
Vous pouvez être sûr que le résultat de «find (id)» est un «membre en cours d'utilisation». (Bien sûr, Table
est responsable de la vérification à la place)
Puisque Table.unSubscribe ()
est une méthode uniquement pour se désabonner, il n'est plus nécessaire de passer Status.UnSubscribed
, et la valeur de réglage pour la commodité du système ne provient plus de domaines
.
Il existe diverses situations telles que la candidature, le changement de formulaire de contrat, le non-paiement des frais, le gel, etc., et ce ne sont pas seulement les membres mais aussi diverses classes qui ne peuvent se passer de la direction. Si vous essayez d'utiliser correctement tous les états avec seulement la valeur de réglage dans la même classe, ce sera si douloureux que l'exception d'exécution mourra car elle sera couverte par la vérification d'incohérence de la valeur de réglage et la vérification «facultative».
Même si j'utilise un langage typé, je ne profite pas de la compilation en premier, donc j'ai l'impression de savoir dans quelle langue j'écris ... ??
Il existe différents modèles ici, et compte tenu de la conception de l'événement, ce sera trop long, alors je viens de le présenter. (Je suis plutôt en train d'étudier la conception d'événements ...)
Par exemple, supposons que toutes les opérations utilisateur doivent être enregistrées en tant qu'historique des opérations. Si vous effectuez un achat, enregistrez l'historique des demandes d'achat. En cas d'annulation, mettez à jour l'historique des applications sur annulé et créez un historique des opérations d'annulation.
opération | Historique des applications | Historique des annulations |
---|---|---|
Appliquer | Peut faire | n'existe pas |
Annuler | Mis à jour à annulé | Peut faire |
C'est compliqué, mais ça ressemble à ça.
«Depuis Application» et «Annulation» sont traités différemment, les classes sont séparées, mais il est également pratique de le gérer comme un historique des opérations à des fins générales, donc un exemple de création d'une classe parente.
Comme c'est compliqué à faire, il existe de nombreuses valeurs de réglage, et comme tout est enregistré sous .save ()
, il est possible que la valeur et le nombre de fois soient erronés.
Afin de gérer correctement l'application et l'annulation lors de la compilation tout en quittant la classe commune, il semble bon de séparer la classe parente.
Si vous utilisez une méthode dédiée de la même manière que le retrait, vous pouvez presque éliminer la valeur définie.
En changeant .save ()
en .cancel (appliqué, annulé)
, vous pouvez toujours mettre à jour les deux correctement.
Finalement, l'historique des opérations tombe pour s'annuler ou se terminer. Après avoir postulé, vous pouvez commencer à l'utiliser après avoir confirmé qu'il est arrivé. La raison de la création d'un historique d'annulation distinct est qu'il sera nécessaire d'accepter les remboursements à partir de maintenant, et l'annulation sera terminée lorsque le traitement nécessaire sera terminé.
En termes d'image, la forme finale ressemble à ceci.
opération | Historique des applications | Historique des annulations |
---|---|---|
Appliquer | Peut faire | n'existe pas |
Atteindre | Achevée | n'existe pas |
Annuler | Mis à jour à annulé | Peut faire |
Rembourser | Reste annulé | Achevée |
Fondamentalement, c'est sous cette forme, mais il y a autant d'histoires d'opérations que de services fournis, tels que la mise à jour des informations sur les membres et l'achat d'équipements supplémentaires.
Il est extrêmement difficile de les mettre à jour correctement à chaque fois, j'aimerais donc bénéficier de la puissance de la compilation lors de la préparation de certaines classes parentes.
membre
en tant que parent d'un membre en cours d'utilisation
et d'un membre qui s'est retiré
, mais il vaut mieux quitter., vous devrez toujours réparer ʻUser
indépendamment de tout changement de spécification, et finalement toutes les spécifications seront testées à nouveau.XxxUser
pour chaque spécification a une plus petite plage d'influenceTable
a une incohérence des données et une interruption de la communication, je vais faire une vérification des exceptions correctementService
fait ce qu'il doit faire en fonction des spécifications, alors concentrez-vous sur le comportement plutôt que de vérifier les exceptions d'exécutionQuelque chose comme ca.
Recommended Posts