DDD - 有界上下文和多个模型?

发布于 2024-10-08 20:23:11 字数 263 浏览 0 评论 0原文

我正在阅读有关 DDD 中的有界上下文的概念,并且开始意识到我对模型在实践中的具体外观并没有清晰的了解。 (我什至可能也不知道的确切含义。)

让我们看一下流行的电子商务示例:客户浏览产品,添加到购物车,下订单。订单履行人员发出订单。

是否存在一个具有多个限界上下文(产品目录上下文、购物车上下文、订单上下文、履行上下文)的大型电子商务域?每个限界上下文是否包含一堆模型(以便产品目录上下文包含产品、产品图像、产品评论的模型)?

我离这还有多远?

I'm reading about the idea of Bounded Contexts in DDD, and I'm starting to realize that I don't have a clear understanding of exactly what a Model looks like in practice. (I might not even know exactly what a Domain means, either.)

Let's look at the popular e-commerce example: A customer browses products, adds to their cart, places an order. The order fulfillment people ship out the orders.

Is there one big e-commerce Domain with multiple Bounded Contexts (Product Catalog Context, Shopping Cart Context, Order Context, Fulfillment Context)? Does each Bounded Context contain a bunch of Models (So that the Product Catalog Context contains models for the products, the product images, the product reviews)?

How far off am I?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

安静 2024-10-15 20:23:11

至少你走在正确的轨道上。典型的错误是只看到模式。

领域意味着您正在处理的问题(支持电子商务、医疗保健、会计等)。领域模型是用代码表示的那些问题的解决方案,尽可能地遵循我们的思维模型。

让我们看一下流行的电子商务示例:客户浏览产品、添加到购物车、下订单。订单履行人员发货。

在你的例子中,我会从这样的事情开始:

class Product { }

class Customer
{
    Cart Cart;
    void PlaceAnOrder()
    {
        order = new Order(Cart.Products);
        Orders.Add(order);
        Cart.Empty(); //if needed
    }
    Orders Orders;
    Orders UnfulfilledOrders()
    {
        Orders.Where(order => !order.IsFilled);
    }
}

class Cart
{
    void AddProduct(product)
    {
        Products.Add(product);
    }
    void Empty()
    {
        Products.Clear();
    }
}

class Order
{
    bool IsFilled;
    void Order(products)
    {
        Products = products;
        IsFilled = false;
    }
    void Fill()
    {
        IsFilled = true;
        //TODO: obviously - more stuff needed here
    }
    Money TotalPrice()
    {
        return Products.Sum(x => x.Price);
    }
}

class System
{
    void Main()
    {
        SimulateCustomerPlacingAnOrder();
        SimulateFulfillmentPeople();
    }
    void SimulateCustomerPlacingAnOrder()
    {
        customer = new Customer();
        customer.Cart.AddProduct(allProducts.First());
        allCustomers.Add(customer);
    }
    void SimulateFulfillmentPeople()
    {
        foreach (var customer in allCustomers)
        {
            foreach (var order in customer.UnfulfilledOrders())
                order.Fill();
        }
    }
}

一开始 - 这似乎是一个巨大的杀伤力。使用过程代码 - 只需很少的集合和 for 循环就可以实现相同的效果。但领域驱动设计的思想是解决真正复杂的问题。

面向对象编程非常适合——有了它,当你前进时,你可以抽象出一些无关紧要的东西。另外 - 相应地命名事物也很重要,这样您(和您的领域专家(理解问题的人))即使在多年后也能够理解代码。不仅是编码,还可以用一种普遍存在的语言进行交谈。

请注意,我不知道电子商务领域以及您可能试图解决什么样的问题,因此 - 我很可能只是根据您的思维模型写了完全废话。这就是领域建模教学如此混乱和困难的原因之一。另外,它需要很强的抽象思维能力,根据我的理解,这并不是获得计算机科学学位的主要要求。


您对有界上下文的看法是正确的。但您应该记住,它们需要在它们之间进行翻译。它们增加了复杂性,并且像往常一样 - 复杂的解决方案仅适用于复杂的问题(对于 ddd 本身也是如此)。因此 - 只要您的域实体的含义不重叠,您就应该避免向它们发送垃圾邮件。第二个原因(不太“自然”)是强烈需要分解。

Ps 阅读埃文斯的书。两次...直到有意义...:)

At least You are on right track. Classic mistake is to see patterns only.

Domain means problems You are dealing with (support for e-commerce, healthcare, accounting, etc.). Domain model is solution of those problems represented in code that follows our mental model as close as possible.

Let's look at the popular e-commerce example: A customer browses products, adds to their cart, places an order. The order fulfillment people ship out the orders.

In Your example, I would start with something like this:

class Product { }

class Customer
{
    Cart Cart;
    void PlaceAnOrder()
    {
        order = new Order(Cart.Products);
        Orders.Add(order);
        Cart.Empty(); //if needed
    }
    Orders Orders;
    Orders UnfulfilledOrders()
    {
        Orders.Where(order => !order.IsFilled);
    }
}

class Cart
{
    void AddProduct(product)
    {
        Products.Add(product);
    }
    void Empty()
    {
        Products.Clear();
    }
}

class Order
{
    bool IsFilled;
    void Order(products)
    {
        Products = products;
        IsFilled = false;
    }
    void Fill()
    {
        IsFilled = true;
        //TODO: obviously - more stuff needed here
    }
    Money TotalPrice()
    {
        return Products.Sum(x => x.Price);
    }
}

class System
{
    void Main()
    {
        SimulateCustomerPlacingAnOrder();
        SimulateFulfillmentPeople();
    }
    void SimulateCustomerPlacingAnOrder()
    {
        customer = new Customer();
        customer.Cart.AddProduct(allProducts.First());
        allCustomers.Add(customer);
    }
    void SimulateFulfillmentPeople()
    {
        foreach (var customer in allCustomers)
        {
            foreach (var order in customer.UnfulfilledOrders())
                order.Fill();
        }
    }
}

At start - this seems like a huge overkill. With procedural code - the same can be achieved with few collections and few for loops. But the idea of domain driven design is to solve really complex problems.

Object oriented programming fits nicely - with it You can abstract away things that doesn't matter when You advance forward. Also - it's important to name things accordingly so You (and Your domain experts (people that understands problem)) would be able to understand code even after years. And not only code but to talk in one ubiquitous language too.

Note that I don't know e-commerce domain and what kind of problems You might be trying to solve, therefore - it's highly likely that I just wrote complete nonsense according to Your mental model. That is one reason why teaching domain modeling is so confusing and hard. Also - it demands great skill in abstract thinking which according to my understanding ain't main requirement to get CS degree.


You are kind a right about bounded contexts. But You should remember that they add need for translation between them. They add complexity and as usual - complex solution is appropriate for complex problems only (this is true for ddd itself too). So - You should avoid spamming them as long as meaning of your domain entities don't overlap. Second reason (less "natural") would be strong need for decomposition.

P.s. Read Evans book. Twice... Until it makes sense... :)

燕归巢 2024-10-15 20:23:11

我认为你的观点是准确的。上下文涉及同一现实世界概念的不同方面。在您的情况下,您可能有一个订单,该订单表示为用户的某种购物车抽象,同时以某种与所使用的 ERP 兼容的形式。

DDD 的上下文基本上表明可以使用两个完全不同的模型(在不同的上下文中)表示某些概念,并在需要时提供这些模型之间的显式映射,而不是试图将订单的概念硬塞到单个模型中。这可以防止模型聚合通常在多个上下文中使用同一模型时会出现的问题。

I think your view is accurate. Contexts deal with different aspects of the same real-world concept. In your case, you might have an order represented as some kind of shopping cart abstraction for the user and at the same time in some form that is compatible with the used ERP.

Instead of trying to shoehorn the concept of an order into a single model, DDD's contexts basically say it's OK to represent some concept using two completely different models (in different contexts), providing explicit mappings between these models as the need arises. This prevents models from aggregating the cruft that usually creeps in if one tries to use the same model within a multitude of contexts.

小猫一只 2024-10-15 20:23:11

如果您可以使用java中的示例,这可能会很有用: http://dddsample.sourceforge.net/

If you are ok with example in java, this might be useful: http://dddsample.sourceforge.net/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文