2015-09-14 1 views
0

Je suis encore en train d'étudier un tel pattern (c'est CQRS) et un de mes collègues a commencé à l'implémenter dans notre petit projet, mais franchement j'ai vraiment des doutes sur sa mise en œuvre.Dans une implémentation CQRS correcte, une commande peut-elle contenir une entité DB?

Pour commencer nous n'avons pas utilisé de framework particulier et nous avons développé en Java avec Spring Boot (mais cette question n'est pas spécifique au langage de programmation). Une autre chose que vous pouvez trouver très bizarre à ce sujet est que le modèle n'a pas été complètement implémenté, juste le concept Command and Query Separation (pas d'événements, pas d'agrégats, pas de bus réel).

Donc, nous allons jeter un oeil à ce que nous avons fait, avec une approche ascendante:

  • Entités DB mappée avec un ORM (Hibernate en Java cas)
  • Bus Commande simulée avec un médiateur
  • Les commandes de domaine sont simplement des objets immuables qui doivent représenter la commande elle-même.

Je ne veux pas aller beaucoup plus loin dans notre implémentation, puisque je veux juste savoir si la commande suivante est faisable ou non.

@Data // Lombok annotation 
@Entity 
class User { 
    @Id private Long id; 
    private String firstName; 
    private String lastName; 
    private Integer age; 
} 

@Value 
class EditUserCommand { 
    private final User user; 
} 

@Service 
class EditUserCommandHandler extends CommandHandler<EditUserCommand> { 
    @Inject 
    private UserRepository users; 

    @Override 
    public void handle(final EditUserCommand command) { 
     User old = this.users.findOne(command.getUser().getId()); 
     User current = command.getUser(); 
     current.setId(old.getId()); 

     current = this.users.save(current); 
    } 
} 

Et voilà comment nous avons implémenté le modèle (ou plutôt le C & Q concept de séparation) dans notre projet ... mais franchement? Je ne sais pas si c'est juste et j'ai trouvé le code assez peu conventionnel pour un modèle CQRS. Mes questions puis:

  • Supposons que je veux faire plusieurs opérations sur mon entité utilisateur, par exemple, je veux juste renommer son prénom et son nom, puis je crée une commande nommée RenameUserFirstAndLastNameCommand; ou si je veux modifier l'âge, alors je crée une commande nommée ModifyUserAgeCommand, n'est-ce pas?
  • Par conséquent je ne devrais jamais créer une commande avec l'entité entière comme montré ci-dessus, mais la commande devrait représenter une tâche spécifique pour le domaine, est-ce exact?

Merci d'avance pour toute réponse.

Répondre

6

Vous avez raison. La commande ne doit contenir que les informations minimales nécessaires pour effectuer le travail réel (dans le cas d'une commande ModifyUserAgeCommand, elle ne peut contenir que l'ID utilisateur et le nouvel âge). Dans votre gestionnaire, votre référentiel doit avoir la responsabilité de réhydrater le modèle à partir de la base de données et vous devez appliquer les modifications applicables à partir des informations contenues dans la commande et persister dans le référentiel. Si vous utilisez DDD, utilisez l'agrégat responsable de l'utilisateur pour appliquer la modification et persister. À propos, tant que vous traitez des lectures (requêtes) et des écritures (commandes) en utilisant des classes et des modèles séparés, c'est toujours CQRS. C'est souvent un malentendu que CQRS doit inclure l'approvisionnement d'événement, la cohérence éventuelle, DDD ... À mon humble avis, il arrive juste de travailler très bien avec ces modèles.