How to enforce constraint such as any field (or specific field) must not change if entity is in some state?

前端 未结 3 1862
名媛妹妹
名媛妹妹 2021-01-03 09:03

I\'m trying to use DDD in my current project (c#, mvc, nhibernate, castle) and I\'m thinking of best way to check a constraint that says any field (or specific field) must n

3条回答
  •  轮回少年
    2021-01-03 09:22

    When designing my domain objects, I try not to think of them just as a collection of data, but as an object that can be acted upon. Instead of providing direct access to the data (even through getter and setter methods), provide methods that correspond to the actions one might take with the object. Sometimes an action will change multiple data fields. Sometimes it might only change one and functionally be no different from a setter, but it is named such that it represents the action and not just a data modification.

    With this approach you can easily enforce what actions would be allowed based on the state of the entity. For example with an Invoice, you might Add or Remove items. This would change the total, but access isn't provided to modify the total directly. When the invoice is in a certain state (e.g. booked) when you no longer allow changes, then enforce that by throwing an exception from the Add or Remove methods indicating the methods aren't valid in the current state. However other methods may still be valid such as those related to shipping or payment of the invoice.

    Along with this approach, I've also used different entities to represent the same data at different points in the lifecycle. While the invoice is active, it needs to be an object that can be acted upon. However, once it reaches a final state, it is only used for viewing and reporting and none of the data changes. By using different entities (e.g. ActiveInvoice and CompletedInvoice), it becomes clear in the application where it is used as part of the process and where it is used just for viewing. It also makes it easier when dealing with archiving data that may be coming from a different table or read-only view.

    If the object only has two states representing a mutable and non-mutable state without much logic for allowing different methods for various states, you can use Eric Lippert's 'Popsicle Immutability' pattern. It allows more direct modification of the object than, but then enforces its immutability once it is frozen.

提交回复
热议问题