[JAVA] Arrêtons l'entité divine qui exprime toutes les statistiques dans une seule classe!

Je l'ai écrit uniquement avec élan! Comme le dit le titre!

Soudainement, lorsque j'écoute l'histoire ou que je regarde Twitter pendant la session d'étude, j'ai l'impression qu'il y a souvent des entités qui utilisent la nomenclature qu'elles trouvent en tant que classe et y jettent toutes les choses qui ressemblent à des données autour d'elles. J'ai aussi écrit quand j'étais débutant w

Coder immédiatement

UserStatus.java


public enum UserStatus {
    Applying,    //Postuler
    Using,       //utilisé
    Leaved,      //Retiré
    BlackListed, //liste noire
    Erased,      //Effacer
}

(Seulement) ʻUser`, qui a un tel état, a été représenté par une classe!

Je pense que c'est courant au stade, "Parce que c'est DDD, créez une classe appelée User et écrivez le traitement là-bas." Je suis sûr que ce n'était pas en bon état au début, mais je comprends que cela a fini par être dangereux pendant que je faisais des analyses ou que je développais des services. Unun

User.java


public class User {
    private UserId userId;
    private UserCourse userCourse;
    private UserStatus userStatus;
    private ApplyDate applyDate;
    private Optional<UseStartDate> useStartDate;
    private Optional<LeaveDate> leaveDate;
    private Optional<EraseDate> eraseDate;

    public User apply(UserCourse userCourse) {
        return new User(
                new UserId(), userCourse, Applying, new ApplyDate(), Optional.empty(), Optional.empty(), Optional.empty()
        );
    }

    public User useStart() {
        if (userStatus != Applying)
            throw new RuntimeException("not applying");

        return new User(
                userId, userCourse, Using, applyDate, Optional.of(new UseStartDate()), leaveDate, eraseDate
        );
    }

    public User courseChange(UserCourse userCourse) {
        if (userStatus != Using)
            throw new RuntimeException("not using");

        return new User(
                userId, userCourse, userStatus, applyDate, useStartDate, leaveDate, eraseDate
        );
    }

    public User leave() {
        if (userStatus != Using)
            throw new RuntimeException("not using");

        return new User(
                userId, userCourse, Leaved, applyDate, useStartDate, Optional.of(new LeaveDate()), eraseDate
        );
    }

    public User blackListIn() {
        if (userStatus != Using)
            throw new RuntimeException("not using");

        return new User(
                userId, userCourse, BlackListed, applyDate, useStartDate, leaveDate, eraseDate
        );
    }

    public User blackListOut() {
        if (userStatus != BlackListed)
            throw new RuntimeException("not black listed");

        return new User(
                userId, userCourse, Using, applyDate, useStartDate, leaveDate, eraseDate
        );
    }

    public User erase() {
        if (userStatus != BlackListed)
            throw new RuntimeException("not black listed");

        return new User(
                userId, userCourse, Erased, applyDate, useStartDate, leaveDate, Optional.of(new EraseDate())
        );
    }
}

Le code à utiliser est comme ça

UserService.java


public class UserService {
    public void leave(UserId userId) {
        User usingUser = userRepository.find(userId);
        User leavedUser = usingUser.leave();

        userRepository.leave(leavedUser);
        
        billing.stop(leavedUser.getLeaveDate().get());

        ...
    }
}

Uhe ~ épicé ~

Le code est long! Même si vous compilez, vous obtiendrez de nombreuses exceptions d'exécution! Je veux dire, la logique de domaine est Nani!

** Ce n'est pas presque un DTO ~? ** **

Divisons la classe selon l'état!

Je vais omettre l'implémentation, mais divisons la classe en fonction de l'état.

image.png

Il y a deux points!

Les principaux avantages!

C'est facile, mais c'est super efficace, alors essayez-le!

Bien sûr, ce n'est pas la technologie d'abord, c'est la modélisation.

J'ai utilisé l'état dans l'exemple, mais cela dépend de la modélisation. Les cas d'utilisation et le degré d'impact sur l'entreprise doivent être différents.

Et cette scission n'est pas «c'est DDD!» Mais «juste un point de départ»! De cette façon, vous pouvez réduire la taille du modèle, l'analyser et régler la logique!

Par exemple, dans cet exemple, l'arrêt de facturation (billing.stop (...)) est modélisé en commençant par LeavedUser.

Si vous faites attention, même si vous pensez avoir créé une entité, ce ne sera qu'un DTO, alors soyez prudent!

Au fait, j'ai écrit un article similaire il y a environ deux ans, si vous l'aimez, s'il vous plaît. [Il est bon de préparer différentes classes pour les mêmes valeurs de table #Case 2-Mettre à jour le statut d'une classe](https://qiita.com/suzuki-hoge/items/b8eb2fe9fbe551cfede4#%E3%82%B1% E3% 83% BC% E3% 82% B92-% EF% BC% 91% E3% 81% A4% E3% 81% AE% E3% 82% AF% E3% 83% A9% E3% 82% B9% E3 % 81% AE% E7% 8A% B6% E6% 85% 8B% E6% 9B% B4% E6% 96% B0% E3% 82% 92% E3% 81% 99% E3% 82% 8B)

Recommended Posts

Arrêtons l'entité divine qui exprime toutes les statistiques dans une seule classe!
Arrêtons d'écrire le chemin de spécification dans le code dans les commentaires
Résolution du problème d'affichage de toutes les données du tableau
éclipse tout en une seule installation
[Gradle] L'histoire selon laquelle le fichier de classe n'existait pas dans le fichier jar