Perspective in DCI

60 views
Skip to first unread message

Anton Wieslander

unread,
Jan 15, 2023, 10:52:06 AM1/15/23
to object-composition
Hi everyone

when I try to apply DCI when writing my code, I struggle with perspective, wanted to convey my thoughts and get some opinions on the matter, as I struggle putting this in to a concrete question.

When I build context's I keep slipping in to what I think is self awareness? If a customer is in a shop and can take and remove products from cart and then checkout at the end, I don't know the correct term but something of a customer journey. In the eyes of the customer you have Cart/Catalog interaction and then Checkout which might be a multistep process. In the eyes of a shop owner you'd perhaps like to analyse journeys to improve your shop. Hopefully you can see how you can keep zooming out of the context and there are more contexts around it.

so most of the time I'm torn between:
1. being the customer: putting items in to cart - load catalog and cart session, initiate transfer, finish scenario.
2. looking from the side: customer is putting items in to his cart - the context becomes persistent, where the customer is now emitting events and the whole thing becomes a state machine (most likely an async one), the context finishes when the customer completes the purchase.

I haven't spend enough time here and can't articulate why I would like to pick one over the other. Anyone has similar experience/opinions?

Anton

Benjamin Scherrey

unread,
Jan 15, 2023, 1:08:39 PM1/15/23
to object-co...@googlegroups.com
Hi Anton,

    Excellent questions. I generally think of Contexts as Use Cases. There's lots of good docs on making use cases (Alistair Cockburn has some excellent writings on this) but DCI allows a better more formal definition of them. Next, I think it may help to break your large scenario down into a composition of multiple smaller scenarios - and DCI excels at this. So maybe putting items in your cart is a Context. Listing things in a Catalog is a Context. Checking out your purchase is a Context. Paying for the purchase is a Context. And then some or all of these can be combined to make a higher level Context because Contexts are proper Objects and can participate as roles in other Contexts. A good hint that your context is too broad is when you keep changing perspective like you described. A good Use Case as a primary actor who triggers the Use Case via an initial triggering interaction. When you get too far removed from your primary actor or doing what's only strictly necessary to fulfill the primary trigger request, you're probably going down the rabbit hole into another Use Case/Context that would be better separated out.

    Hope that helps a bit to get you oriented,

  -- Ben Scherrey

--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/object-composition/f40980af-c67b-448c-9216-3b11cbea5f21n%40googlegroups.com.

James O Coplien

unread,
Jan 16, 2023, 8:32:46 AM1/16/23
to object-co...@googlegroups.com
Use cases (start there!) usually look from the side, and then map actors to end-users and the systems under construction.

Matthew Browne

unread,
Jan 16, 2023, 12:10:28 PM1/16/23
to object-co...@googlegroups.com, James O Coplien

Hi Anton,
I would second the approach of looking from "the side." If I understand what you're saying, then another way of saying it would be a first-person perspective vs. a third-person perspective, where third-person is looking from "the side."

For example, consider Rune's example of front-loading activities in a project planning system (inspired by Trygve's Prokon example):

https://fulloo.info/Examples/Marvin/FrontLoader/Listings/FrontLoader/

That's an example using the third-person approach, whereas the first-person approach could look like this:

internal class FrontLoaderContext {
    public FrontLoader(IEnumerable<Activity> activities){
        projectPlanner = null;
        allActivities = activities;
    }

    // represents the current user - the person planning the project
    role projectPlanner {
        allActivities.Plan();
    }

    role allActivities {
        ...
    }

    public IEnumerable<Activity> Plan() {
        projectPlanner.Plan();
        return allActivities;
    }
}


In this example, I think it's clear that the 'projectPlanner' role is overkill, since it's not doing anything other than calling the allActivities role, and there isn't even any data about the current user needed by this context.

Having said that, it's entirely allowed in DCI to bind null/nil to a role if you want to add a role for semantic reasons only, and I think people in this group probably have somewhat different preferences about this. And to take your example, I could definitely envision a PurchaseProducts context where Customer is a role (whether Customer is bound to null or a real User object).

It's also valid to create roles to represent people or theoretical people who aren't necessarily the user of the Context you're writing. For example, consider this alternative version of the money transfer example (switching to trygve syntax now):

context TransferMoney {
    public TransferMoney(Currency amount, Account source, Account destination) {
        Banker = null;
        Source = Source;
        Destination = Destination;
        Amount = amount;
    }
    
    role Banker {
        void transfer() {
            Source.withdraw();
            Destination.deposit();
        }
    }

    role Source {...}
    
    role Destination {...}
    
    role Amount {...}
}

(compare with the example in the trygve repo which starts the transfer using a Source.transferTo() method and has no Banker role.)

In summary, there are many different approaches that are all valid and can work, but which one is best depends on your particular Context and the mental model you want to convey.

Best,
Matt

Reply all
Reply to author
Forward
0 new messages