Who finds the participants, Context or Controller?

56 views
Skip to first unread message

Iain Duncan

unread,
Dec 6, 2017, 12:06:45 PM12/6/17
to object-composition
Apologies if this is a naive questions, I'm new to my DCI reading. I'll be using a DCI (or at least DCI inspired) approach with a web app in Python, in which we use the ZCA as a DI system, and are moving to a DDD approach for the domain area. My question is, for operations where we want to map roles to several data objects, where and when are the data objects normally found? Is it normal for a Controller to retrieve these objects from the db repository and then pass them to the Context classes constructor for instantiation or is more common to create a Context object and let it find the data objects? Are there pros and cons to either?

thanks!
Iain

Vlad Lyga

unread,
Dec 7, 2017, 3:09:57 PM12/7/17
to object-composition
Hi Iain

What framework do you use (and what is ZCA?)?
For example if you use Flask you can fetch the domain object (flask model) in the the route function, 
and pass them to the relevant context.
Remember that View or Response is also an object, so it also can play  a role in the Context.
That way you can build the response/view as the context executes.
After context returns you just persist the domain objects (flask models), and return the response/view.
I wouldn't advice to lookup the database from within the context because many types of domain objects can play same roles.

Matthew Browne

unread,
Dec 7, 2017, 10:00:43 PM12/7/17
to object-co...@googlegroups.com
I don't think DCI is opinionated about this; you can obtain the data
objects in whatever way works best for your particular DCI Context. I
would say it depends on what you consider to be part of the use case; if
processing input from the UI is part of the use case, then it makes
sense to do that inside the Context. I'm not sure that should be a hard
and fast rule though - I think you could equally make the case that the
View and Controller of MVC should be responsible for translating user
input to domain objects, and that a Context focused on doing something
with those objects shouldn't have to know how to obtain them.

I have seen both approaches used in official and contributed examples.
For example, in Trygve's version of the money transfer example, he
creates a Transaction object that's responsible for looking up the bank
Account objects, and passes that Transaction into the MoneyTransfer
context. In Cope's version of the example in the Lean Architecture book,
the MoneyTransfer context is instantiated with account IDs and the
context is responsible for retrieving the Account objects.

In terms of a guideline to follow, I can only think of one rule that
would be true across different systems and languages... If you decide to
retrieve objects from a database inside your Context, I would say to
avoid putting raw database queries there (at least if you're using SQL;
with something like Mongo that provides a find() method in its API it
might be less of an issue). (I realize that's probably not what you're
suggesting, just trying to give a general answer.) My reasoning is that
boilerplate SQL code could be distracting from the main logic of the use
case, making the code harder to read, so it would be good to abstract
that to a data access layer.

I'd also be interested to hear any opinions from others about pros and
cons of these alternatives.

Matthew Browne

unread,
Dec 7, 2017, 10:20:27 PM12/7/17
to object-co...@googlegroups.com
On 12/7/17 3:09 PM, Vlad Lyga wrote:
> I wouldn't advice to lookup the database from within the context
> because many types of domain objects can play same roles.
This is a good point. Roles should be generic whenever possible. In the
money transfer example, it should be possible to transfer money between
any two accounts - e.g. from a CheckingAccount to a SavingsAccount. It's
arguably OK to look up bank accounts inside the Context as long as it
does the database lookup in such a way that it could fetch either type
of Account from the database (i.e. Database.getAccountById(accountNum)
--> works for both CheckingAccount and SavingsAccount).

On the other hand, if the app also needed to transfer money from one
bank to another, or if you anticipated the need for that in a future
version of the app, then this approach would create too much of a
dependency between the MoneyTransfer context and the bank (and making it
impossible to reuse the same Context for transferring money to a
different bank). Of course there are other considerations in this
particular use case, but the complexities / differences between
different kinds of transfers could be handled by nested Contexts without
needing to write a new TransferMoneyToExternalBank context from scratch.

In any case, make sure you do any database lookups in the Context's
constructor and not in any of its role methods, that way if you needed
to refactor in the future it would be easy: you'd simply move that code
from the constructor to somewhere else (e.g. an MVC controller), and
wouldn't need to touch the rest of the Context.

James O Coplien

unread,
Dec 8, 2017, 8:46:25 AM12/8/17
to object-co...@googlegroups.com


> Den 8. dec. 2017 kl. 04.00 skrev Matthew Browne <mbro...@gmail.com>:
>
> On 12/6/17 12:06 PM, Iain Duncan wrote:
>> Apologies if this is a naive questions, I'm new to my DCI reading. I'll be using a DCI (or at least DCI inspired) approach with a web app in Python, in which we use the ZCA as a DI system, and are moving to a DDD approach for the domain area. My question is, for operations where we want to map roles to several data objects, where and when are the data objects normally found? Is it normal for a Controller to retrieve these objects from the db repository and then pass them to the Context classes constructor for instantiation or is more common to create a Context object and let it find the data objects? Are there pros and cons to either?
> I don't think DCI is opinionated about this; you can obtain the data objects in whatever way works best for your particular DCI Context. I would say it depends on what you consider to be part of the use case; if processing input from the UI is part of the use case, then it makes sense to do that inside the Context. I'm not sure that should be a hard and fast rule though - I think you could equally make the case that the View and Controller of MVC should be responsible for translating user input to domain objects,

The View is largely responsible for displaying objects in a way that fits the end-user mental model. It may handle local (to that object) input.

The Controller creates and coordinates views. It may handle input, but it’s more for directly the visibility of windows.


> and that a Context focused on doing something with those objects shouldn't have to know how to obtain them.
>
> I have seen both approaches used in official and contributed examples. For example, in Trygve's version of the money transfer example, he creates a Transaction object that's responsible for looking up the bank Account objects, and passes that Transaction into the MoneyTransfer context. In Cope's version of the example in the Lean Architecture book, the MoneyTransfer context is instantiated with account IDs and the context is responsible for retrieving the Account objects.
>
> In terms of a guideline to follow, I can only think of one rule that would be true across different systems and languages... If you decide to retrieve objects from a database inside your Context, I would say to avoid putting raw database queries there (at least if you're using SQL; with something like Mongo that provides a find() method in its API it might be less of an issue). (I realize that's probably not what you're suggesting, just trying to give a general answer.) My reasoning is that boilerplate SQL code could be distracting from the main logic of the use case, making the code harder to read, so it would be good to abstract that to a data access layer.
>
> I'd also be interested to hear any opinions from others about pros and cons of these alternatives.

I think there are few hard and fast rules here, particularly at the level of the mail that follows this one. I think the major guidelines are these:

Roles should be units of associated behavior that come from the mental model, e.g. in a CRC card exercise.

Original objects should manage application data, and should start with primitive domain operations. The classes that “create" these objects should come out of a good domain analysis.

The keys to success here are a good extraction of the use case from mental models, and a good domain analysis. I find that everything falls into place if I have these. DDD is very bad for this because there is no analysis at all: one goes from concept directly to code, so even there is no place to consider even a decision about whether a given responsibility belongs to a class or a role.

I think that to make an evolveable design, programming language is a consideration you can almost ignore. With good conventions you can do DCI in assembler. I do think the code is much more maintainable in a language that can express the identity of a Context or a Role, but I don’t think that’s the major benefit. I think it’s how you slice the pie, and that’s an analysis and design exercise rather than a programming exercise.

In terms of other details, it sounds like you are considering putting far too much business logic in the Controller. Think of MVC just as part of the hardware that exists to make sure views are updated at the right time.

Matthew Browne

unread,
Dec 8, 2017, 5:19:44 PM12/8/17
to object-co...@googlegroups.com
Thanks, Cope.


--
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-composition+unsub...@googlegroups.com.
To post to this group, send email to object-composition@googlegroups.com.
Visit this group at https://groups.google.com/group/object-composition.
For more options, visit https://groups.google.com/d/optout.

Iain Duncan

unread,
Dec 11, 2017, 7:40:20 PM12/11/17
to object-composition
Thanks everyone, that helps me think about this better. 
Reply all
Reply to author
Forward
0 new messages