Can I ask what .NET libraries you usually use on your projects? I.e., what IoC/DI library?

One of the article's claims was DCI enables rich multiobject interaction that can replace object state machines. I see your current form of interaction as somewhat anemic, though - you are using inheritance to give your domain object Account additional capabilities that probably don't belong to it.

This is a model smell in my books.

The interesting thing is that so far nothing in the original article's top half has been proven, whatsoever. (This isn't a shot at you, Christian - just a critique of the original article.)

I'll continue to say that existing approaches are way further in theory&practice than this approach. MEF is a good example, albeit I feel MEF has many shortcomings and reasons why I don't use it - it at least gives me a reference point.

But, more importantly, in my experience there is nothing new here and nothing "agile" here, either. Instead, we're just creating a different way to do the SAME typechecking we were doing before - "Fortune 100"-style source code controls.

Businesses have more basic concerns that are better talking points for "mental models". One company we work with had their two head IT people tell us the biggest problem they face is silos. So what is there solution? Build a data warehouse - another silo, What ends up happening is nobody is accountable because there is no electronic workflow attached to the analysis that comes out of the warehouse data mining aventures. People print out sheets of paper, hand them out in the office, and people are supposed to be doing their work -- but they don't. Why? My guess is that people find it a pain in the butt to navigate back-and-forth between the data warehouse silo and their back office apps where they (re-)enter everything in.

Then on another level you have what I call the designer-developer facade, which is how you actually facilitate rapid prototyping of user interfaces. There is a reason why companies pay such a ridiculous amount of money for tools like iRise: it gets the client talking and thinking.

Now, I'm not that familiar with that language, so can someone explain whether this binds the trait to the Account interface? And if so, in the Java world, why not make TransferMoneySourceAccount a proper class and inject an Account instance into it rather than worrying about trying to mixin the trait into SavingsAccount?

> In the Scala example, the following is used to define a> trait:> > > trait TransferMoneySourceAccount extends SourceAccount {> this: Account =>> ...> > > Now, I'm not that familiar with that language, so can> someone explain whether this binds the trait to the> Account interface? > Good question. The "this: Account =>" bit at the top of the trait is called a "self type," and what it does is give the this reference a different type than usual. In Java, the type of this is always the type of the class or interface you are defining. That's also true for classes in Scala, and is the default for traits, but with a self type you can give it a different type in a trait. When you say "this: Account =>", you are saying you want the type of "this" inside trait TransferMoneySourceAccount to be "TransferMoneySourceAccount mixed into Account." Because of this the Scala compiler will let you call anything on the this reference that's defined in either the TransferMoneySourceAccount trait or in class or trait Account. And when you mix the trait into something, the Scala compiler will enforce that whatever you mix it into is at least an Account.

> And if so, in the Java world, why not> make TransferMoneySourceAccount a proper class and inject> an Account instance into it rather than worrying about> trying to mixin the trait into SavingsAccount?>Your intuition is good (if I understand correctly what you're saying). One way you can think of self types is as a way to inject dependencies. The TransferMoneySourceAccount trait's self type says that the trait effectively depends on everything in Account. When you mix the trait into an Account, you are effectively injecting the trait's dependencies into it. You can actually take this quite far and do natively in the Scala language much of the dependency injection that requires an external framework like Spring or Guice in Java.

> Rich domain models are wrong because the assumption is> placing logic in one place (a domain class) is a good> idea. ...> > Anemic domain models are wrong because they flatten an> architecture into orthogonal layers, requiring developers> to pass tramp parameters to pass an object across multiple> layers. > I think I wasn't clear. Let me try to clarify what I mean, because I wasn't trying to say that DCI promotes anemic domain models. Instead it challenges a basic assumption inherent in the notion of an anemic domain model. The assumption is that an object has a class.

Basically what we've been doing in OO modeling is designing classes whose names often map to the domain. So if there's an "account" in the problem domain, then we might have an Account class in the code. But what behavior do we attach to that class? Well, if the class is anemic, then it is just simple behavior of getting and setting data. The class is "dumb," little more than a glorified data holder. If the class is non-anemic, then it will have more interesting behavior that has something to do with the data. In OO we tend to move the behavior that uses data to the classes that have the data.

OK. So what happens is that if the account concept is involved in 10 use cases of your application, you may end up placing some behavior for each of those use cases into class Account. Deciding what behavior to put in and what to leave out is the designer's challenge.

DCI challenges the assumption that each object has one and only one class. The observation is that objects need different behavior in different contexts. So why not let an object have a different class in each context? The way it shakes out is that you will have an anemic Account class in your design, and different traits that can be mixed into Account to supply just the extra (non-anemic) behavior needed for the use case at hand. And DCI also suggests is that use map these traits to conceptual roles in the user's thinking.

Since you like code, let me show you how this maps to Scala, in which you can model it nicely. You can have a anemic class Account, and then mix in one ore more traits at instantiation time. So in the transfer use case, you might write:

val source = new Account with TransferMoneySource

What the Scala compiler does with this is create an anonymous class (it creates a class and assigns it a name that includes some dollar signs) that extends SavingsAccount and mixes in TransferMoneySourceAccount, then creates an instance of that. On the JVM then, each object does have one and only one class. But the conceptual account object may have many different classes, one of which is the anonymous class created here that is only used in this one use case.

Yes, I understand that. I know a lot about traits. I'm being hypercritical, because I hate sucky explanations.

I think too often people try to sound too smart.

Realistically, a more appropriate introductory article would be along the lines of what you just said.

As I said earlier, compiler syntax features are important b/c the average developer isn't a compiler writer, and it is tricky to get right. For instance, Sather had a way stronger notion of contracts than Eiffel, but never became popular.

Also, I think what Coplien/Reenskaug are *aspiring to* with "DCI" is what most good IoC containers such as Nicholas Blumhardt's Autofac do. Thus, I don't see it as a new concept. And, again, I see state machines and roles as complementary. In fact, containers like Autofac have a very Demeter Method Tools feel to them, too.

Most people, unfortunately, don't understand IoC and perceive it to be a technique for improving testability or whatever, when really it is best viewed as a data modeling paradigm.

@I think I wasn't clear. Let me try to clarify what I mean, because I wasn't trying to say that DCI promotes anemic domain models. Instead it challenges a basic assumption inherent in the notion of an anemic domain model. The assumption is that an object has a class.

My objects are aren't classes, either. In fact, my object models are very similar to constraint-based programming. The reason for this is to avoid the cross-product statespace problem you get with anemic domain models. This isn't DCI - it's just good modeling with math to back it up. It makes it much easier to comprehend performance, too.

@DCI challenges the assumption that each object has one and only one class.

Just to be clear, this is a problem space abstraction issue. Traits are really just a way to place constraints on the object model. However, DCI does not fundamentally invent anything new at all -- that's very important to realize, because most people don't understand this due to never being taught it.

Calling this an architecture is just buzzword stuffing in a day and age where everybody gets promoted to architect to make them feel important. Fundamentally, we're saying, "hey, let's practice OO for a change". That's not a "new vision for OO", but rather a change in human behavior. You can't call change in behavior an architecture, though - especially when so much code out there is crap and shows there is no movement in place.

> OK. So what happens is that if the account concept is> involved in 10 use cases of your application, you may end> up placing some behavior for each of those use cases into> class Account. Deciding what behavior to put> in and what to leave out is the designer's challenge.> > DCI challenges the assumption that each object has one and> only one class. The observation is that objects need> different behavior in different contexts. So why not let> an object have a different class in each context? The way> it shakes out is that you will have an anemic> Account class in your design, and different> traits that can be mixed into Account to> supply just the extra (non-anemic) behavior needed for the> use case at hand. And DCI also suggests is that use map> these traits to conceptual roles in the user's thinking.>

Bill, thank you for that explanation.

OK. So what happens is that if the account concept isinvolved in 10 use cases of your application, you may endup placing some behavior for each of those use cases intoclass Account. Deciding what behavior to putin and what to leave out is the designer's challenge.

That has always been my fundamental problem with OO languages like Java and C#. Grouping behavior with different contexts in the same class isn't right, but as you stated, what do you leave in and out. Maybe that's why I've always been intrigued with Common Lisp's CLOS style of OO.

@John it appears, you have knowledge of so many theories and technologies, that it's hard to believe you still have a time to be a practitioner :)

As I can see, DCI is not about how to write lines of code in any given programming language. It's not even about the idea of coding anything, nor writing source neither code nor grammar specifics of C# or Smalltalk. DCI is going further. If you want to create a system based on ideas of DCI you need something more than just a bunch of source files.

Believe me, the source code could be seen as an object, everything could be registered in an object oriented database and the property of identity will allow to keep versions and interactions between system objects. System objects like class, field, method, user, access levels etc. Based on that system one could build an application modeler/generator capable of producing programs working in DCI philosophy in the environment of the mentioned system.

Just a quick observation since this article tackles the problem of the user mental model vs. computer model:

Why does everyone insist on using Account Transfer as their primary example of system transactions?

Mentally the user may picture some sort of ACIDic transaction going on, but implementation-wise: no bank accounting system I ever came across uses transactions for this use case -

They all implement some variant of the Double Bookkeeping accounting principle; at best, you'll find a system transaction spanning the source account and some intermediary mother-of-all collection account (though not likely since most are of a different age). The target account is most frequently not at the same bank, and even when, the Double Bookkeeping principle is still used. Even what the balance is on the account depends on what you're after, as the bank knows several.

In many ways, Banks implementation of the Account Transfer use-case is really closer to what is known as BASE: Basically Available, Soft State, Eventually Consistent; where end of day reconciliation ensures the consistency of the balance(s) on the account.

As an example Account Transfer may explain to developers the mental model behind how transactions are supposed to work, but it does not help them translate the mental model into a working computer model.

> > Here is all you need to see:> > new TransferMoneyContext(src, snk, 1000).Doit();>

As I'm sure you realize, this is actually just the command pattern: Some part of the application instantiates a context object, "remembers" the necessary domain objects in terms of the individual (context specific) roles. It is a design decision when/where to execute the context instance. As I see it DCI does not dictate how the split between instantiating and executing contexts is implemented. Or even if there is such a split.I dont see this as a code smell.

@John it appears, you have knowledge of so many theories and technologies, that it's hard to believe you still have a time to be a practitioner :)

There are five people in the world who remember everything that has ever happened to them. I'm not quite there, but my memory is prolific.

The hard part is not being burned out. Working myself up into a white-hot concentration and sustaining it simply isn't possible. My rule of thumb is to only promise one good idea every three months, and guarantee mediocrity the rest of the time (while ideally doing no harm).

@As I can see, DCI is not about how to write lines of code in any given programming language. It's not even about the idea of coding anything, nor writing source neither code nor grammar specifics of C# or Smalltalk. DCI is going further. If you want to create a system based on ideas of DCI you need something more than just a bunch of source files.

I read Trygve's papers last night. It seems he feels object polymorphism makes code unreadable (which I hear from F# programmers all the time) and traits are the key concept. I enjoyed reading his funny rant about unreadable code. However, his quote of Serge Beaumont was probably the best "strong content" in all the writing. Yet, BabyIDE has a couple of design flaws and its explanation doesn't map use cases to code, which strongly diminishes proving the point "it is about mental models".

@Yet, BabyIDE has a couple of design flaws and its explanation doesn't map use cases to code, which strongly diminishes proving the point "it is about menta models".

Does "use cases" mean Use Cases? Is the goal really to map Use Cases to code? Is that even desirable or achievable? Caveat: I didn't read the article on BabyIDE. Still, I think they are valid questions.

Thanks for the clear explanation of the Scala code. Having slept on the concepts for a night, I have a followup question which perhaps gets more to the heart of my inquiry.

Just how important are traits (or equivalent programming language constructs) to DCI? In the Scala example, we mixin the trait to the Account class. But it seems apparent that, at least for the article's example, we could implement the same in Java (without Qi4j) by injecting an Account into an instance of a TransferMoneySourceAccount.

Or, to put it another way -- in certain dynamic languages such as Ruby (hand waving alert:I am no expert on Ruby), I believe we could do a mixin without an explicit coupling between the methodful role/trait and the Account object. Is this a real advantage? Does the Scala implementation lose something by coupling the trait to the Account?

> > > > Here is all you need to see:> > > > new TransferMoneyContext(src, snk, 1000).Doit();> > > > As I'm sure you realize, this is actually just the command> pattern: Some part of the application instantiates a> context object, "remembers" the necessary domain objects> in terms of the individual (context specific) roles. It is> a design decision when/where to execute the context> instance. As I see it DCI does not dictate how the split> between instantiating and executing contexts is> implemented. Or even if there is such a split.> I dont see this as a code smell.

You scenario is not event-driven. The fact you are reaching up the program's stack frame to grab objects to inject at a fixed point in execution is your code smell. The tip-off is the DoIT() method, and now also your use of "remembers" which can create scope impedance mismatches (hanging onto stale references). In addition, you have no scope guard for your command. How do you know if a multiple object interaction is valid?