[Python] Générer ValueObject avec un constructeur complet à l'aide de classes de données

introduction

Récemment, j'ai commencé imprudemment à étudier le DDD, mais il existe peu d'exemples de Python ...! Alors ・ Organisez vos réflexions sur DDD ・ Proposer un exemple d'écriture en Python J'ai décidé d'écrire un article à cet effet. Pour le moment, cette fois, j'écris sur l'objet de valeur qui semble être le plus facile d'accès.

Qu'est-ce qu'un ValueObject et un constructeur complet ...

Il existe de nombreux articles qui sont très faciles à comprendre pour les autres, je vais donc vous les donner, mais si vous l'écrivez brièvement, ValueObject est "une valeur exprimée en utilisant une classe, pas un type primitif tel que int, mais le comportement attendu et la manière d'être", Un constructeur complet peut être considéré comme une méthode pour obtenir un "comportement attendu" ou, au contraire, "ne pas provoquer de comportement inattendu". (Je comprends cela ... est-ce vrai ...?)

Par exemple, si vous souhaitez exprimer «montant», vous pouvez dire «ce ne sera pas une valeur négative». ValueObject est une classe qui définit le comportement attendu. Décrivez ce qui précède "ce ne sera pas une valeur négative" dans le constructeur, C'est un constructeur complet qui se rend compte que "les valeurs qui ne devraient pas exister n'existent pas".

Essayez d'exprimer ValueObject avec des classes de données

Puisque nous avons parlé du montant d'argent dans la section précédente, écrivons-le brièvement en utilisant le montant d'argent comme exemple.

import dataclasses

@dataclasses.dataclass
class Money:
    #Je n'entrerai pas dans les détails, mais les variables listées ici sont pour les classes régulières.__init__Ce sera une variable d'instance décrite dans
    amount: int

    # __post_init__Est__init__C'est le processus qui est exécuté après.
    #L'expression du constructeur complet est décrite ici.(2020/5/9 Correction d'une erreur)
    def __post_init__(self):
        if self.amount < 0:
            raise ValueError()

Il ne peut plus y avoir d’objet Money avec une valeur négative, Il y aura uniquement des objets Money dont les valeurs sont garanties. (Je pense qu'il y a d'autres restrictions qui devraient être imposées, mais cette fois je passerai à ce niveau)

Rendez-le immuable

Vous pouvez également rendre les classes immuables à l'aide de classes de données. Immuable rend la réaffectation impossible et améliore la sécurité du code. (Value Object semble être fondamentalement quelque chose qui devrait être immuable) Python est une fonctionnalité importante car il existe peu de moyens d'empêcher la réaffectation aux variables d'instance.

import dataclasses

# frozen=True le rend immuable
@dataclasses.dataclass(frozen=True)
class Money:
    amount: int

    def __post__init__(self):
        if amount < 0:
            raise ValueError()

Comment exprimer le changement de montant

En la rendant immuable, une fois instanciée, la valeur ne peut pas être modifiée même si le montant augmente ou diminue. Maintenant, comment exprimer l'augmentation ou la diminution du montant, créez une nouvelle instance avec la valeur du montant après l'augmentation ou la diminution. Les méthodes peuvent être écrites comme des classes régulières.

import dataclasses

@dataclasses.dataclass(frozen=True)
class Money:
    amount: int

    def __post__init__(self):
        if amount < 0:
            raise ValueError()

    def lost(self, loss):
        return Money(self.amount - loss.amount)

#Par exemple, écrivez comme ceci
money1 = Money(1000)
money2 = Money(100)
left_money = money1.lost(money2)

Dois-je utiliser des classes de données

La même chose peut être faite avec la méthode de description conventionnelle, donc ce n'est pas indispensable. cependant, ・ Peut être immuable ・ La quantité de description du constructeur peut être réduite. -La description de la variable d'instance et la description de la logique pour en faire un constructeur complet peuvent être séparées, ce qui facilite la visualisation. À cet égard, j'ai l'impression qu'il vaut mieux utiliser des classes de données. Étant donné que les classes de données ont diverses autres fonctions, je voudrais l'utiliser non seulement pour ValueObject.

finalement

J'ai introduit cette fois que ValueObject peut être exprimé même en Python en écrivant comme ceci. Depuis que je viens de commencer à étudier, l'explication sur ValueObject lui-même est mince, mais si vous approfondissez votre compréhension Je souhaite rédiger des articles supplémentaires et rédiger des articles sur les entités.

référence

Veuillez vous référer ici pour l'utilisation des classes de données. https://docs.python.org/ja/3.7/library/dataclasses.html

Recommended Posts

[Python] Générer ValueObject avec un constructeur complet à l'aide de classes de données
Créer un répertoire avec python
Créer une interface graphique python à l'aide de tkinter
Créez un environnement virtuel avec Python!
Créer un décorateur de fonction Python avec Class
Créez une image factice avec Python + PIL.
[Python] Créez un environnement virtuel avec Anaconda
Créons un groupe gratuit avec Python
[Python] Créer un environnement Batch à l'aide d'AWS-CDK
Créer un compteur de fréquence de mots avec Python 3.4
Créez un outil qui secoue automatiquement furigana avec html en utilisant Mecab de Python3
Créer un enregistrement avec des pièces jointes dans KINTONE à l'aide du module de requêtes Python
Créer un cadre avec un arrière-plan transparent avec tkinter [Python]
Créer un fichier GIF en utilisant Pillow en Python
Créer un LINE BOT avec Minette pour Python
Créer un environnement virtuel avec conda avec Python
Créer une page qui se charge indéfiniment avec python
[Note] Créez une classe de fuseau horaire sur une ligne avec python
Vous pouvez facilement créer une interface graphique même avec Python
Créer un environnement de construction python3 avec Sublime Text3
Créer une carte Web en utilisant Python et GDAL
Créer une barre de couleurs avec Python + Qt (PySide)
Étapes pour créer un bot Twitter avec Python
Créer un arbre de décision à partir de 0 avec Python (1. Présentation)
Créer une nouvelle page en confluence avec Python
Créer un widget avec une couleur spécifiée avec Python + Qt (PySide)
Créer un fichier au format Photoshop (.psd) avec python
Créez un fichier MIDI en Python en utilisant pretty_midi
Facile à créer une application console Python avec Click
Créer un module Python
Créer un environnement Python
Créer un bot de collecte de données en Python à l'aide de Selenium
[CRUD] [Django] Créer un site CRUD en utilisant le framework Python Django ~ 1 ~
Pourquoi ne pas créer facilement une table élégante avec Python?
Créez un environnement de développement python avec vagrant + ansible + fabric
Enregistrez des tickets avec l'API de Redmine en utilisant des requêtes Python
Créer une couche pour AWS Lambda Python dans Docker
[python] Créez un tableau de dates avec des incréments arbitraires avec np.arange
[CRUD] [Django] Créer un site CRUD en utilisant le framework Python Django ~ 2 ~
[Python] Comment créer un histogramme bidimensionnel avec Matplotlib
[Python] Créez un fichier de distribution pour le programme Tkinter avec cx_Freeze
Créez un faux serveur Minecraft en Python avec Quarry
Utilisez des programmes Python avec le plugin de sortie exec_filter de fluentd
[CRUD] [Django] Créer un site CRUD en utilisant le framework Python Django ~ 3 ~
[CRUD] [Django] Créer un site CRUD en utilisant le framework Python Django ~ 4 ~
[CRUD] [Django] Créer un site CRUD en utilisant le framework Python Django ~ 5 ~
Créer un fichier CAO 2D ".dxf" avec python [ezdxf]
Utilisez des programmes Python avec le plugin de sortie exec de fluentd
Créer un plugin Wox (Python)
Créer une fonction en Python
Créer un dictionnaire en Python
Utilisation de Quaternion avec Python ~ numpy-quaternion ~
Créer un gif 3D avec python3
[Python] Utilisation d'OpenCV avec Python (basique)
Créer une page d'accueil avec django
Créer des tickets JIRA en utilisant Python
Créer un tableau numpy python
Utiliser une imprimante avec Debian 10