Question

Most examples of a DCI Context are implemented as a Command pattern. When using Dependency Injection though, it's useful to have the dependencies injected in the constructor and send the parameters into the executing method. Compare the Command pattern class:

public class SomeContext
{
    private readonly SomeRole _someRole;
    private readonly IRepository<User> _userRepository;

    // Everything goes into the constructor for a true encapsuled command.
    public SomeContext(SomeRole someRole, IRepository<User> userRepository)
    {
        _someRole = someRole;
        _userRepository = userRepository;
    }

    public void Execute()
    {
        _someRole.DoStuff(_userRepository);
    }
}

With the Dependency injected class:

public class SomeContext
{
    private readonly IRepository<User> _userRepository;

    // Only what can be injected using the DI provider.
    public SomeContext(IRepository<User> userRepository)
    {
        _userRepository = userRepository;
    }

    // Parameters from the executing method
    public void Execute(SomeRole someRole)
    {
        someRole.DoStuff(_userRepository);
    }
}

The last one seems a bit nicer, but I've never seen it implemented like this so I'm curious if there are any things to consider.

Was it helpful?

Solution

There's a contrast between Command and DCI. In Command you distribute the interaction between objects, in DCI you centralize the interaction through rolemethods. In the MoneyTRansfer example the accounts will not have the ability to withdraw or deposit becasue they are simple data with no behavior. however in a context such as Transfer that behavior will exist for the roles. So when the source account role is bound to an account object the account object gets the withdraw behavior and the same is true for the destination account.

In the command pattern they have the behavior but the execution of the behavior is scripted in the command object and can be passed around. The entire interaction is not part of the command object but typically distributed between the participating objects.

In Marvin, a language build to support DCI as a result of the realization that most modern languages only partly supports DCI, you can only bind roles to objects in the constructor. How you call the constructor is of no concern to the context. This ensures that the binding is done once for all roles. Rebinding is then only possible by instantiation of another context. This is not a constraint from DCI but a design choice for Marvin.

To the question about whether or not an context method can take arguments, it's a bit philosophical but as far as I remember the last time I debatted it with Trygve Reenskaug we agreed that they could take arguments and I know that I've implemented a few examples (the moneytransfer at the DCI site included) where they do.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top