views:

178

answers:

3

What are possibles designs for implementation of the DCI (data, contexts, interactions) architecture in different OOP languages? I thought of Policy based design (Andrei Alexandrescu) for C++, DI and AOP for Java. However, I also thought about using State design pattern for representing roles and some sort of Template method for the interactions... What are the other possibilities?

A: 

In Java, without byte-code generation, I would use Decorator pattern for contexts, however I will instead of classes decorate interfaces, which will be more flexible. Data than will be represented through classes implementing the interfaces. The interactions will be done using manual dependency injection into Template methods.

Gabriel Ščerbák
A: 

Very few languages, if any, are suited to implement DCI in its purest form.

But the motivation behind DCI is to have OO code that can be understood by reading it.

Let me try to examplify:

You're working on a big project and your boss asks you for the code for a given use-case that involves a bunch of different classes.

What do you give him?

Do you give him all the code for all the classes involved? Do you give him the code for the relevant methods in each class? You also need to explain to him which methods are called in which order, but this depends on the runtime situation...

Which means that the OO code can't be reviewed, it can only be tested.

DCI tries to solve this by organizing code into contexts instead of classes.

My favourite language doesn't really allow this in it's present release, so I try to approach the DCI idea by modelling the situations instead of the objects.

Guge
you did not answer the question at all
Gabriel Ščerbák
DCI is not a pattern or an architecture. It is a paradigm, like classes are. You can approach it in existing languages, but to really work it needs to have support in the language itself. The goal of DCI is to reorganize code around the use-case not around the class to make it more readable. If you try to use state patterns for roles and templates for contexts you'll probably just add complexity without making the code more readable. I thought the best way to answer your question was to try to explain the goal of DCI, so I spent 10 minutes on it. And -1 is the thanks I get?
Guge
A: 

This is how I would use DCI in C# as of 2010:

interface IAccount
{
    decimal Balance { get; }
    void Withdraw(decimal amount);
    void Deposit(decimal amount);
}

class Account : IAccount
{
    private decimal balance;
    private string name;

    public Account(string name)
    {
        this.name = name;
        this.balance = 0;
    }

    public decimal Balance
    {
        get
       {
            return balance;
        }
    }

    public void Withdraw(decimal amount)
    {
        if (amount <= 0)
            throw new ArgumentOutOfRangeException("amount must be positive");
        balance -= amount;
    }

    public void Deposit(decimal amount)
    {
        if (amount <= 0)
            throw new ArgumentOutOfRangeException("amount must be positive");
        balance += amount;
    }
}


class TransferContext
{
    private FromAccountRole fromRole;
    private ToAccountRole toRole;

    public TransferContext(IAccount from, IAccount to)
    {
        fromRole = new FromAccountRole(from);
        toRole = new ToAccountRole(to);
    }

    public void Transfer(decimal amount)
    {
        // some kind of transaction control would be necessary

        if (fromRole.Balance < amount)
            throw new Exception("Insufficient funds");

        fromRole.Withdraw(amount);
        toRole.Deposit(amount);
    }

    class FromAccountRole
    {
        private IAccount account;

        public FromAccountRole(IAccount account)
        {
            this.account = account;
        }

        public decimal Balance { get { return account.Balance; } }

        public void Withdraw(decimal amount)
        {
            account.Withdraw(amount);
        }
    }

    class ToAccountRole
    {
        private IAccount account;

        public ToAccountRole(IAccount account)
        {
            this.account = account;
        }

        internal void Deposit(decimal amount)
        {
            account.Deposit(amount);
        }
    }

}

I would implement the Context as a class, Roles would be inner classes to the context class.

The way I see it the main point of DCI is to make the use-case code readable, and I think the example achieves that. The interface is there to ensure that the role is filled by someone that is able to fill that role.

Guge