如何强制约束,如任何领域(或特定的字段​​),如果实体是在某些状态不能改变?

问题描述:

我试图用DDD在我目前的项目(C#,MVC,NHibernate的,城堡),我想最好的方法来检查约束,说任何领域(或特定的字段​​)不得改变,如果实体在一些国家,即。这被黄牌警告发票(国有=预订)不得有多少场改变。在服务层我得到一些DTO对象(从GUI或Web服务等),我需要映射到域对象。映射完成后,我想验证我的对象 - 特别是我想要查询的具体约束我的问题

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 not change if entity is in some state, ie. invoice that is booked (state=booked) must not have amount field changed. In service layer I get some DTO object (from gui or web service, etc) that I need to map to domain object. After mapping is complete I want to validate my object - in particular I want to check the specific constraint in my question.

目前我在想:

    在实体层面
  • 在跟踪变化,即在每一个二传手添加字段来改变字段集合并切换NHibernate的使用字段访问策略。这种模式的变化将是扔在二传手异常,如果改变的价值是不允许
  • 在映射之前创建对象的副本,并比较原始和映射值
  • 在回落的NHibernate和得到这个信息从NHibernate的会议 - 但该规则将不会在实体层面予以强制执行(恕我直言,它打破了DDD)

你觉得呢?你知道有什么好的方式为这个?还是我失去了一些东西,我需要改变我思考这个约束的方法是什么?

What do you think about it? Do you know any good patterns for this? Or am I missing something and I need to change my way of thinking about this constraint?

先谢谢您的帮助。

在DDD域对象是自我确证。换句话说,这是不可能的客户端code打破域规则,因为对象执行其内部变量。例如:

Domain objects in DDD are 'self validating'. In other words, it is not possible for client code to break domain rules because objects enforce their internal invariants. For example:

public class Invoice {
    private Money _amount;
    private InvoiceState _state;

    public void ChangeAmount(Money newAmount) {
        if(_state == State.Booked) {
            throw new InvalidOperationException(
                      "Unable to change amount for booked invoice.");
        }
        _amount = newAmount;
    }

    // Methods like this can be used by external code (UI) to check business
    // rules upfront, to avoid InvalidOperationException.
    public Boolean CanChangeAmount() {
        if(_state == State.Booked) {
            return false;
        }
        return true;
    }
}

DDD样品又如:

  public HandlingEvent(final Cargo cargo,
                       final Date completionTime,
                       final Date registrationTime,
                       final Type type,
                       final Location location,
                       final Voyage voyage) {

    ...

    if (type.prohibitsVoyage()) {
      throw new IllegalArgumentException(
                       "Voyage is not allowed with event type " + type);
    }

不要让你的UI框架请客域对象作为哑数据容器。不幸的是,这是通过getter和setter互联网和C#的强调了很多的例子鼓励。如果你改变对象的状态,而不会强制执行业务规则,你将最终结束了破坏的对象。这是NHibernate的尤其如此,因为它的Session记住的所有对象,并愉快地将它们放到数据库下次提交或刷新。但是,这仅仅是一个技术性问题,主要的原因是,你需要能够仅通过查看发票类推理发票相关业务规则。另请注意,code,应根据通用语言。你应该看到像发票,预订,金额,而不是一般的'场','财产','验证'。

Never allow your UI framework treat domain object as dumb data container. Unfortunately this is encouraged by a lot examples on the internet and C#'s emphasis on getters and setters. If you change object state without enforcing business rules you will eventually end up with 'corrupted' objects. This is especially true for NHibernate because its Session 'remembers' all objects and will happily dump them into database on next commit or flush. But this is just a technicality, the main reason is that you need to be able to reason about Invoice related business rules just by looking at Invoice class. Also note that the code should be based on Ubiquitous Language. You should see words like 'Invoice', 'Booked', 'Amount' instead of generic 'Field', 'Property', 'Validator'.

更新:EMPI,感谢你重申你的问题。你可能会想打开一个新的问题。这是引用我强调

UPDATE: empi, thank you for restating your problem. You might want to open a new question. This is the quote with my emphasis

正如我在我的意见一说 - 这个问题是一个更大的一部分   我有问题。我在寻找定义域的标准方式   只有在域,然后逻辑和约束它转换成图形用户界面   和其他层。我看不出有什么共同的模式下面很   共同的需求:域名称字段不能被编辑和此   规则被自动转换为GUI逻辑禁用领域   并使其只读。我正在寻找在MVC堆栈样品溶液。一世   觉得我重新发明轮子,大部分开发商干脆放弃   和重复的逻辑GUI

As I said in one of my comments - this question is a part of a bigger problem I'm having. I'm looking for a standard way to define domain logic and constraints only in the domain and then translate it to gui and other layers. I don't see any common pattern to the following very common demand: the domain states that field cannot be edited and this rule is automatically converted to gui logic that disables the field and makes it readonly. I'm looking for sample solution in mvc stack. I feel like I'm reinventing the wheel and most developers just give up and duplicate the logic in gui

我认为你正在寻找一种方式来说明一切域,然后'生成'的用户界面。像裸对象为的 MVC ?我从来没有使用过这种方法,但我怀疑,生成的UI将能赢得美女或可用性比赛。在我看来,总是会在UI的业务逻辑的一些重申。有些领域不变量过于复杂,涉及多个领域,需要存储库,甚至外部服务。我不知道,它可以自动生成高质量的用户界面。我认为,试图这样做可能会开始弯曲你的模型,以符合用户界面的基础设施。

I think that you looking for a way to state everything in domain and then 'generate' UI. Something like Naked Objects for MVC? I never used this approach but I doubt that generated UI would ever win beauty or usability contest. In my opinion there will always be some 'restating' of business logic in UI. Some domain invariants are too complex, involve multiple fields, require repository and maybe even external services. I'm not sure that it is possible to generate high quality user interface automatically. I think that attempts to do this may start bending your model to conform to the UI infrastructure.