DCI in C# & Welcome to Christian Horsdal Gammelgaard

317 views
Skip to first unread message

James O. Coplien

unread,
Mar 5, 2009, 9:50:16 AM3/5/09
to object-co...@googlegroups.com, Christian Horsdal Gammelgaard
Another step forward, and welcome to Christian.

-----------------------------------------------------------------------------------------------------------

Begin forwarded message:

Hi James and Gertrud
 
I just finished reading the draft of your upcoming book on “Lean Software Architecture and Agile Production”, and I found it to be very much worth the read.  There are a lot of very interesting ideas in there, and I must say that I enjoy the fact that there is so much code to support the explaination of the DCI ideas.
Personally I mainly work in .NET, so while I appriciate the niceness of the running C++ example, I was also sort of looking forward to the Java appendix when reading the book. Mainly because I expected to be able to almost run the Java code through my C# compiler and have .NET code – almost. But (as you rightly point out in the book) the Java implemtation is less than satisfactory, especially compared to something as clean and readable as the Scala version, so I though to myself “does C# have any features I could take advantage of to do DCI”. It turnes out that it does. Or at least I think it does. I have attached a C# proof-of-concept implementation of the money transfer example in C# which uses extension methods for methodfull roles. The extension methods are setup to extend interfaces, and the roles are mixed into domain classes by having them implement the exteded interfaces (which is easy since those interfaces are empty – all their functionality comes via the extension methods). The rest is pretty straight forward: Methodless roles are interfaces, context object are done using classes, abstract domain classes are abstract classes, concrete domain classes are concrete classes.
Anyway I thought you might find yet-another shot at a DCI implementation interesting. If you do, and if you have any comments on the code or otherwise please let me now.
 
 
Med venlig hilsen / Best regards

Christian Horsdal Gammelgaard
Senior Software Architect
Tlf. 41 95 36 67 - c...@mjolner.dk
Mjølner Informatics A/S
Finlandsgade 10, 8200 Århus N
Tlf. 70 27 43 43 - www.mjolner.dk
Class1.cs
image001.jpg

Christian Horsdal

unread,
Mar 6, 2009, 4:40:03 AM3/6/09
to object-composition
Hi everybody

Thanks for the welcome.
I've uploaded the code that Cope attached to the previous message
along with a Visual Studio solution to the shared files area of this
group (http://groups.google.com/group/object-composition/web/DCI_C
%23.zip?hl=en). I would appreciate any feedback on the code; I've
written a couple of questions in the comments to the code, any
opinions on those would be appreciated as well.

/Christian
> Denne e-mail kan indeholde fortrolig information, som ikke må kopieres  
> eller udleveres til anden side, og som kun er bestemt for den angivne  
> modtager. Hvis du ved en fejltagelse har modtaget denne e-mail, skal  
> du venligst orientere afsenderen herom og straks slette e-mailen.
>
> G&C
> James O. Coplien
> Software Architecture & Agile Consultant
> c...@gertrudandcope.com
> +45-4021-6220

Arnt

unread,
Apr 21, 2009, 4:44:17 AM4/21/09
to object-composition
Hi

My first post at here. My name is Arnt Emmanuel Berge. Working as Lead
Developer at Engineering Systems. I had the pleasure of talking to
Trygve and Cope at ROOTS last year. Very interesting ideas. I have
some experience trying to implement OORam role models with regular C#
and interfaces. I’m not satisfied with the results. I would like to
take a look at your attempt at on traits like implementation in C#.
Tried your link but got a “Page doesn’t exist” message. Is the file
removed? If so could you possibly send it directly to me.


--
Arnt

On 6 Mar, 11:40, Christian Horsdal <c.hors...@gmail.com> wrote:
> Hi everybody
>
> Thanks for the welcome.
> I've uploaded the code that Cope attached to the previous message
> along with a Visual Studio solution to the shared files area of this
> group (http://groups.google.com/group/object-composition/web/DCI_C
> %23.zip?hl=en). I would appreciate any feedback on the code; I've
> written a couple of questions in the comments to the code, any
> opinions on those would be appreciated as well.
>
> /Christian
>
> On Mar 5, 3:50 pm, "James O. Coplien" <jcopl...@gmail.com> wrote:
>
>
>
> > Another step forward, and welcome to Christian.
>
> > --------------------------------------------------------------------------- --------------------------------
>
> > Begin forwarded message:
>
> > Hi James and Gertrud
>
> > I just finished reading the draft of your upcoming book on “Lean  
> > Software Architecture and Agile Production”, and I found it to be very  
> > much worth the read.  There are a lot of very interesting ideas in  
> > there, and I must say that I enjoy the fact that there is so much code  
> > to support the explaination of the DCI ideas.
> > Personally I mainly work in .NET, so while I appriciate the niceness  
> > of the running C++ example, I was also sort of looking forward to the  
> > Java appendix when reading the book. Mainly because I expected to be  
> > able to almost run the Java code through myC#compiler and have .NET  
> > code – almost. But (as you rightly point out in the book) the Java  
> > implemtation is less than satisfactory, especially compared to  
> > something as clean and readable as the Scala version, so I though to  
> > myself “doesC#have any features I could take advantage of to do  
> > DCI”. It turnes out that it does. Or at least I think it does. I have  
> > attached aC#proof-of-concept implementation of the money transfer  
> > example inC#which uses extension methods for methodfull roles. The  

Trygve Reenskaug

unread,
Apr 21, 2009, 4:54:01 AM4/21/09
to object-co...@googlegroups.com
Hi Arnt,
Which link didn't work?
--Trygve
--

Trygve Reenskaug       mailto: try...@ifi.uio.no

Morgedalsvn. 5A         http://heim.ifi.uio.no/~trygver

N-0378 Oslo               Tel: (+47) 22 49 57 27

Norway

Arnt

unread,
Apr 21, 2009, 4:57:16 AM4/21/09
to object-composition
Hi,

Sorry. Figured it out. The last part of the link is left out in the
link.
Copy pasted the Url in stead.

Arnt

unread,
Apr 21, 2009, 7:24:35 AM4/21/09
to object-composition
Hi,

Nice example. Interesting approach. I have taken the liberty of
suggesting some adjustments. What do you think about this?

By pushing the method definitions from the abstract Account class to
the role interfaces you don’t have to cast the input objects. This way
the role interface can specify what the objects have to provide.
Also a little experiment her with the context class. What about
writing it with a fluent interface? This way one can write:

MonyTransfer.Transfer(1000).From(sourceAccount).To
(destinationAccount);

------ CODE -------
using System;

namespace AccountSample
{
public interface Log
{
void Log(string message);
}

// Methodless/"Traitless?" roles
public interface TransferMoneySink : Log
{
void Deposit(double amount);
}

// Methodfull roles
public interface TransferMoneySource : Log
{
void Withdraw(double amount);
}

// Concrete domain object
public class SavingsAccount : TransferMoneySource,
TransferMoneySink
{
private double balance;

public SavingsAccount()
{
balance = 10000;
}

public void Withdraw(double amount)
{
balance -= amount;
}

public void Deposit(double amount)
{
balance += amount;
}

public void Log(string message)
{
Console.WriteLine(message);
}

public override string ToString()
{
return "Balance " + balance;
}
}

public static class TransferMoneySourceTraits
{
public static void TransferFrom(this TransferMoneySource self,
TransferMoneySink recipient, double amount)
{
// Selfcontained readable and testable algorithm
if (self != null && recipient != null)
{
self.Withdraw(amount);
self.Log("Withdrawing " + amount);
recipient.Deposit(amount);
recipient.Log("Depositing " + amount);
}
}
}

// Context object
public class MonyTransfer
{
// Properties for accesing the concrete objects relevant in
this context through their methodless roles
private TransferMoneySource Source;
private TransferMoneySink Sink;
private double amount;

public MonyTransfer(double amount)
{
this.amount = amount;
}

public void Doit()
{
Source.TransferFrom(Sink, amount);
}

public MonyTransfer From(TransferMoneySource src)
{
Source = src;
return this;
}

public void To(SavingsAccount snk)
{
Sink = snk;
Doit();
}

public static MonyTransfer Transfer(int amount)
{
return new MonyTransfer(amount);
}
}

///////////// Controller ////////////////
// Test controller
public class Program
{
public static void Main(string[] args)
{
SavingsAccount sourceAccount = new SavingsAccount();
SavingsAccount destinationAccount = new SavingsAccount();
Console.WriteLine("Before:");
Console.WriteLine("Src:" + sourceAccount);
Console.WriteLine("Snk:" + destinationAccount);

Console.WriteLine("Run transfer:");

MonyTransfer.Transfer(1000).From(sourceAccount).To
(destinationAccount);

Console.WriteLine("After:");
Console.WriteLine("Src:" + sourceAccount);
Console.WriteLine("Snk:" + destinationAccount);

Console.ReadLine();
}
}
}

----------


On 6 Mar, 11:40, Christian Horsdal <c.hors...@gmail.com> wrote:

Rickard Öberg

unread,
Apr 21, 2009, 11:53:48 PM4/21/09
to object-co...@googlegroups.com
Hey,

The DCI article on Artima has three different suggestions for what C
means: Context, Collaboration and Communication.

Which one is it? :-)

Personally I would prefer Collaboration. But in any case it needs to be
decided ASAP so as to avoid confusion.

/Rickard

Trygve Reenskaug

unread,
Apr 22, 2009, 2:53:31 AM4/22/09
to object-co...@googlegroups.com
I hadn't notice the conflict. It is definitely Data - Context - Interaction.

The UML Collaboration is a modeling element. Using the same word in DCI could be confusing because the DCI Context bridges the gap between compile time and runtime and includes a bit of both.

If we choose to use the verb collaborate in its dictionary sense, we could say that objects collaborate within a context.

Thanks for pointing out this problem
--Trygve

Christian Horsdal

unread,
Apr 27, 2009, 1:44:13 AM4/27/09
to object-composition
Hi

Thanks for the feedback.
I didn't like the casting of objects down to the abstract account type
either, so I agree that it is nicer to push up the necesarry methods
to the role interfaces. From a modelling perscpective that also makes
sense.
I notice that you have deleted the abstract account class. Is that
just because there was nothing left in it after pushing up the methods
to the roles, or is there another reason? In a real life application I
think it would be important to keep the abstract account there in
order to capture the domain notice of an account.

I also like the fluent interface for the context.
I plan to do a slightly larger example following Jim's slightly larger
banking example within the next couple of weeks, and I will try to use
your ideas in it.

/Christian

Arnt Berge

unread,
Apr 28, 2009, 10:06:39 AM4/28/09
to object-co...@googlegroups.com
Hi,

2009/4/27 Christian Horsdal <c.ho...@gmail.com>:


> I notice that you have deleted the abstract account class. Is that
> just because there was nothing left in it after pushing up the methods
> to the roles, or is there another reason? In a real life application I
> think it would be important to keep the abstract account there in
> order to capture the domain notice of an account.

Yes I deleted it because it was empty. Personally I wouldn't have an
abstract account class before I needed it to express something of
importance. ;)


--
Arnt

Christian Horsdal Gammelgaard

unread,
Apr 29, 2009, 1:54:30 AM4/29/09
to object-co...@googlegroups.com
Hi,

I agree, I wouldn't keep an empty class either. I just image something of importance would land their sooner or later.

--
Med venlig hilsen / Best regards
Christian Horsdal Gammelgaard, Mjølner Informatics A/S

Christian Horsdal

unread,
May 4, 2009, 4:48:11 PM5/4/09
to object-composition
Hi

I updated my C# sample implementation of DCI. I've updated the code to
(more or less) match C++ banking sample. The new code includes and
tests a transfer money context, and a pay bills context. The
implementation is very much along the lines of the previous sample:
Roles are specified
by interfaces and extension methods in conjunction. Contexts and
domain objects are normal coded as classes.
An important difference is that there is no down-casting in the
contexts anymore. I've done as Arnt suggested and pushed the necessary
domain methods to roles.
The new sample is uploaded this groups shared files (http://
groups.google.com/group/object-composition/web/20090504_C%23_DCI.zip?
hl=en).

/Christian

Alan_Huffman

unread,
May 9, 2009, 12:03:44 AM5/9/09
to object-composition
Christian,

I agree with you having pushed required methods / behavior to the
roles as Arnte Berge suggested.

After having looked at this code, I noticed the Context objects were a
bit small and very similar in structure to each other. When you were
writing them ( PayBillsContext & TransferMoneyContext ), did they feel
unnecessary? Or to put it another way, what value did you see in them?

As put forth in the DCI architectural model, the Context is where
models & roles come together. Perhaps that is value I'm don't
understand / fully appreciate. Is the Context where the value is
(organizing the interaction of Model & Role)?

I'll write up an example I've been struggling with (calculating an
order's cost for an American Mail Order Pharmacy). I'll post it when
I'm done.

Thanks for the projects (they help a lot),
Alan

Christian Horsdal Gammelgaard

unread,
May 9, 2009, 8:20:12 AM5/9/09
to object-co...@googlegroups.com
Hi Alan 

On Sat, May 9, 2009 at 6:03 AM, Alan_Huffman <alanh...@gmail.com> wrote:

Christian,

I agree with you having pushed required methods / behavior to the
roles as Arnte Berge suggested.

After having looked at this code, I noticed the Context objects were a
bit small and very similar in structure to each other. When you were
writing them ( PayBillsContext & TransferMoneyContext ), did they feel
unnecessary? Or to put it another way, what value did you see in them?


No I didn't feel they were unnecessary: I think their responsibility of pulling together all the objects necessary to run the use case in terms of the roles those objects play is important. I think the fact they are small is a good thing: They do just one well defined thing, so they don't have to be complicated. I.e. they respect the single responsibility principle.


As put forth in the DCI architectural model, the Context is where
models & roles come together. Perhaps that is value I'm don't
understand / fully appreciate. Is the Context where the value is
(organizing the interaction of Model & Role)?

I think the value of the context is that they organize the object graph necessary at runtime to execute a use case. Notably it does so in terms of roles. Therefore context classes specify which roles are involved in the use case, and the context objects make sure all those roles are assigned to suitable objects before the use case can be executed.

Arnt suggested coding a fluent interface for the contexts. This makes a lot of sense if the use cases are executed right after instantiation. As he pointed out a fluent interface enables client code to do something like MoneyTransferContext.Transfer(20).From(sourceAccount).To(sinkAccount); That results in the TransferTo method being invoked on the sourceAccount. So why not just do that directly? Firstly I think the fluent code is more readable, secondly having the context objects enables passing the context around such that the object instantiating the context object need not be the same object that invokes the use case (i.e. the Execute method). In other words the context objects are command objects, with the pros and cons that come with the command pattern.
 
Hope that makes sense to you?




I'll write up an example I've been struggling with (calculating an
order's cost for an American Mail Order Pharmacy). I'll post it when
I'm done.

I'm looking forward to seeing it.
 

/Christian Horsdal

Christian Horsdal

unread,
May 9, 2009, 8:23:27 AM5/9/09
to object-composition
Hi

I did a blog post on my C# DCI approach. It's at
http://horsdal.blogspot.com/2009/05/dci-in-c.html and hope some of you
will find it worth while :-)

/Christian

Alan_Huffman

unread,
May 11, 2009, 12:29:00 AM5/11/09
to object-composition
Christian,

The context class (TransferMoneyContext) has been bothering me. It
just seems unnecessary / redundant in the posted C# project. I
considered changing the access modifier on the extensibility method
(TransferTo) to INTERNAL -- at least this way there would be enforced
encapsulation (for code not in the same assembly). Of course, the
contexts would have to be in the same assembly.
> This addresses another issue that I've been worrying about. By
having public extensibility methods, our DTO objects are always
capable of the defined behavior -- but that really shouldn't be the
case. Certain behaviors should be *mixed* in or omitted depending on
the context.

I think the idea of using extensibility methods is a reasonable
approach. Certainly it allows us to modify the objects' behavior w/out
directly affecting the class code (but we do so at compile time, not
run time -- unless we make them internal and accumulate behavior by
passing them into a context w/ an assembly that has new defined
behaviors for that DTO's interface). In that case we *can* decorate up
the Domain Object. Or perhaps, the mechanism of mixing in behavior
should come as a consequence of including assemblies (like with
LINQ).

Not sure... still trying to get it. I do feel like a DataContext's are
sufficiently important if they *add* behavior by access to
extensibility methods in their assembly -- but I'm not sure. Perhaps
there is a way to use MEF (Microsoft Extensibility Framework) to
discover new behaviors at run time, compose them and organize via
contexts.

#CONTEXT
public void Execute()
{
Source.TransferTo(Sink, Amount);
}

#ROLE
// What if we made this INTERNAL e.g. ( internal static void
TransferTo )
public static void TransferTo(this TransferMoneySource self,
TransferMoneySink recipient, double amount)
{
if (self.Balance < amount)
{
throw new ApplicationException("insufficient funds");
}

self.Withdraw(amount);
self.Log("Withdrawing " + amount);
recipient.Deposit(amount);
recipient.Log("Depositing " + amount);
}

-Alan

On May 9, 7:20 am, Christian Horsdal Gammelgaard <c.hors...@gmail.com>
wrote:
> Hi Alan
Reply all
Reply to author
Forward
Message has been deleted
0 new messages