8
votes

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?

3

3 Answers

7
votes

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... :)

3
votes

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.

1
votes

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