--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To post to this group, send email to object-co...@googlegroups.com.
To unsubscribe from this group, send email to object-composit...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/object-composition?hl=en.
Also, I would really be interested in hearing how to model a DCI
system. I'm guessing UML class diagrams could be used to design
classes, let alone the fact that they would probably still fail due to
the static biais of the notation, but how about roles, contexts, and
even object?
<snip>
A personal advice: Try to implement this first in any language that support traits. Don't use at the beginning c#, java. Then when you fully understand the DCI approach look into the previously mentioned languages. You will find that a lot of the noise is because limitations of those languages.
Hi group
The dynamic capabilities of C#4 are designed for interoperability with dynamic languages. Sure, you can build native C# code using a bag of tricks using this feature, but then you lose everything that C# as a statically typed language is about. If you want dynamic programming, you really should look into a dynamic language, because with C# you’re not going to get the full dynamic experience. It would probably be a rather frustrating middle ground.
If you want to use mixins in C#, I humbly recommend looking into our project re-mix: remix.codeplex.com. It’s a lot like Qi4j.
However, there are viable examples out there doing DCI in C# with interfaces and extension methods. And I still don’t see anything in DCI that cannot be implemented using those. I do know the limitations of extension methods (there are many: they are just syntactical sugar for static methods), and there are many things that mixins can do and extension methods cannot, but they seem to be excluded by DCI: roles have neither state nor polymorphism after all.
I’m eager to see the sample we’ve been talking about, this should help make a lot of things clearer.
Cheers,
Stefan
"A collaboration describes a structure of collaborating elements (roles), each performing a specialized function, whichAnd then there is the large body of UML behavior modeling concepts available for modeling the behavior of a Collaboration object. (Like state and sequence diagrams as suggested by Michael)
collectively accomplish some desired functionality. Its primary purpose is to explain how a system works and, therefore,
it typically only incorporates those aspects of reality that are deemed relevant to the explanation. Thus, details, such as the
identity or precise class of the actual participating instances are suppressed "
Description
A collaboration is represented as a kind of classifier and defines a set of cooperating entities to be played by instances (its
roles), as well as a set of connectors that define communication paths between the participating instances. The
cooperating entities are the properties of the collaboration (see “Property (from InternalStructures)” on page 189).
A collaboration specifies a view (or projection) of a set of cooperating classifiers. It describes the required links between
instances that play the roles of the collaboration, as well as the features required of the classifiers that specify the
participating instances. Several collaborations may describe different projections of the same set of classifiers.
--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To post to this group, send email to object-co...@googlegroups.com.
To unsubscribe from this group, send email to object-composit...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/object-composition?hl=en.
Trygve Reenskaug mailto: try...@ifi.uio.no
Morgedalsvn. 5A http://folk.uio.no/trygver/
N-0378 Oslo Tel: (+47) 22 49 57 27
Norway
> Hello everybody,
>
> I am just discovering the DCI approach to object-orientation, and I
> really like it.
Welcome to the community :-)
> However, I'm having trouble finding resources
> explaining each aspects of it. I'm especially having a hard time
> understanding the concept of "Context". I'd need some clarification.
> Is it only a different kind of object, or is it something different?
It is an object that wires up objects to roles. Think of it as the producer in a play — the one who hires the actors and assigns their roles.
What's interesting is that because it is an object it, too, can be an actor, which means it can play a role (but it doesn't have to).
> Also, I would really be interested in hearing how to model a DCI
> system. I'm guessing UML class diagrams could be used to design
> classes, let alone the fact that they would probably still fail due to
> the static biais of the notation, but how about roles, contexts, and
> even object?
In asking for a notation, what problem are you trying to solve? The answer varies widely depending on your answer. You might download Trygve's IDE and play with it a bit — in his approach, the program more or less *is* the model, and is represented graphically.
> Thank you,
> Michael
On Jun 30, 2011, at 5:33 , Erlis Vidal wrote:
> A personal advice: Try to implement this first in any language that support traits. Don't use at the beginning c#, java. Then when you fully understand the DCI approach look into the previously mentioned languages. You will find that a lot of the noise is because limitations of those languages.
I think this is good advice, or at least seems to be heading in the right direction.
But — can you be more explicit? I mean, to me, C++ supports traits (and always has since the implementation of templates back in the 1980s), so I'd include it in the list. Others may not. The Python approach to DCI doesn't really use traits because classes are of negligible importance in that implementation. It's probably a cleaner implementation than any trait-based implementation because you get to think in objects instead of classes which, in some sense, is where DCI starts. (Traits are useful to implement DCI in classful languages.) Which languages — other than Scala, which is the obvious choice — would you include in your list?
Hi, Erlis,
I think this is good advice, or at least seems to be heading in the right direction.
On Jun 30, 2011, at 5:33 , Erlis Vidal wrote:
> A personal advice: Try to implement this first in any language that support traits. Don't use at the beginning c#, java. Then when you fully understand the DCI approach look into the previously mentioned languages. You will find that a lot of the noise is because limitations of those languages.
But — can you be more explicit? I mean, to me, C++ supports traits (and always has since the implementation of templates back in the 1980s), so I'd include it in the list. Others may not. The Python approach to DCI doesn't really use traits because classes are of negligible importance in that implementation. It's probably a cleaner implementation than any trait-based implementation because you get to think in objects instead of classes which, in some sense, is where DCI starts. (Traits are useful to implement DCI in classful languages.) Which languages — other than Scala, which is the obvious choice — would you include in your list?
It should be possible to write a guide for modeling DCI systems with UML.
Jim: Is this a theme for a Master or PhD? It could be a new and very useful intro for DCI novices.
The work would involve extracting useful bits from UML and possibly modifying them where necessary. The modifications could become input to a next version of UML.
Hi Rune, do you have any example to share?..
public class MoneyTransferContext : ClearMud<MoneyTransferContext>
{
[Role(Name = "Source")]
public interface ISource
{
Func<Account,decimal,bool> TransferFrom { get; }
}
private static class RoleMethods
{
public static bool TransferFrom([Role]Account Source, Account destination, decimal amount)
{
Source.DecreaseBalance(amount);
Source.Log("Withdrew: " + amount);
destination.IncreaseBalance(amount);
destination.Log("Withdrew: " + amount);
return true;
}
}
private ISource Source;
private Account Destination;
public void Doit(decimal amount)
{
Source.TransferFrom(Destination, amount);
}
public static MoneyTransferContext Bind()
{
var _this = new MoneyTransferContext();
Bind(_this,new {Source = new Account(),Destination = new Account()});
return _this;
}
}
So once again it's the MoneyTransfer example. Yes I know we've been over it a multitude of times but then at least we can compare :)
The class above is the context. The first interface is marked with a Role attribute and describes the contract for the role called Source.
Then comes a private nested class called RoleMethods this class is the implementation of the role methods. The first argument marks with the Role attribute will be the role it's injected into.
Then comes to fields each holding the a reference to a RolePlayer when Bind has been called
the DoIt method is the method to "activate" the context not much here
and finally the bind method. The thing to not here is that the context binds RolePlayers to Roles by giving an anonymous type to another Bind method (the other bind method does dynamic voodoo). Each property of the anonymous typed object is mapped to a role.
If we wish to use the code we just do:
var context = MoneyTransferContext.Bind();
context.Doit(100m);
The only part of the code that's not compile time type safe is what goes on in the base class implementation of bind. That however only needs to be written once.
Comments are of course welcome and if some one feels this is a frustrating middle ground I'd be glad to know what the frustrating parts are, I'll then do my best to clean them up.
if you want to see the voodoo of the base class I've created a github repo at https://runefs@github.com/runefs/ClearMud.git. I haven't tried accessing from any other profile than mine so if you don't have access send me a mail with you github ID and I'll add you as collaborator.
The code is a PoC atm so don't expect clean code. The only really interesting part is the Bind method (61 LOC) the rest is just scaffolding.
The code won't compile since I haven't check in third party libraries put all you need is Clay (install-package Clay with NuGet)
Best regards
Rune
> The only part of the code that's not compile time type safe is what
> goes on in the base class implementation of bind. That however only
> needs to be written once.
That would not be an issue. However, the real problem is that there's no compile-time
type safety between
> Func<Account,decimal,bool> TransferFrom { get; }
and
> public static bool TransferFrom([Role]Account Source,
> Account destination, decimal amount)
So if either signature changes, you'll only discover this at runtime.
> Comments are of course welcome and if some one feels this is a
> frustrating middle ground I'd be glad to know what the frustrating
> parts are, I'll then do my best to clean them up.
This obviously addresses me. You announced a piece of code that uses 'dynamic' to create
traits. The code you sent does neither:
- no use of 'dynamic' in domain code
- no traits, but a wrapper that encapsulates a static method and a RolePlayer instance
However, the problem mentioned above is still there.
The question this really raises is different though: There are a few disadvantages to straightforward
C# code, using extension methods for instance. Where are the advantages? Which concept of DCI is better
implemented using your method? Which structural difference in the code makes up for all the voodoo,
indirection and conventions that I have to keep in my head to read, change, understand, debug, edit etc.
this code? For the lost type safety? For the lost capabilities of automatic refactoring, analysis...
Don't get me wrong: I'm definitely interested in libraries that extend the structural expressiveness of
C#. That's what our library re-mix, just like Qi4j, is all about. But I still didn't get the part of DCI
that calls for such elaborate approaches, and it doesn't seem like anybody here is going to show it to me.
Cheers,
Stefan
So I think a serious drawback of my extension method approach is that
the domain objects must 'implement' marker interfaces for the roles
they need to play. This turns things things up side down: The domain
classes, which are supposed to be the stable - what the system *is* -
part are now compile time dependent on the roles, that belong to the
faster moving - the what the system *does* - part. Drawbacks for this
includes deciding, when coding the domain class, on all the roles the
instances of that class should be able to play, and having to change
that code, recompile, and redeploy it whenever a new role is
introduced, or whenever a role is removed.
> (Medical software where a bug had the potential of literally killing the user)
Bug? I thought that the scheduler's omniscience to do context-sensitive context switching was a feature... Hey, it was really object-oriented... you couldn't reason about the PITL sequencing of code by looking at any code in particular....
Sigh, it's a weekend, and I'm bored... :-)
That would not be an issue. However, the real problem is that there's no compile-time
type safety between
and
> Func<Account,decimal,bool> TransferFrom { get; }
So if either signature changes, you'll only discover this at runtime.
> public static bool TransferFrom([Role]Account Source,
> Account destination, decimal amount)
> Comments are of course welcome and if some one feels this is aThis obviously addresses me. You announced a piece of code that uses 'dynamic' to create
> frustrating middle ground I'd be glad to know what the frustrating
> parts are, I'll then do my best to clean them up.
traits.
The code you sent does neither:
- no use of 'dynamic' in domain code
Don't get me wrong: I'm definitely interested in libraries that extend the structural expressiveness of
C#. That's what our library re-mix, just like Qi4j, is all about. But I still didn't get the part of DCI
that calls for such elaborate approaches, and it doesn't seem like anybody here is going to show it to me.
Cheers,
Stefan
> What I actually stated was that you could use the dynamic binding to create traits
Careful on the terminology. I usually use "traits" to describe semantics like class composition. I don't view Ruby as using traits. DCI does not depend on traits.
Maybe it's worthwhile adding "traits" to our lexicon, with a formal delineation.
I actually think the original paper has a pretty good definition
(http://scg.unibe.ch/archive/papers/Scha03aTraits.pdf) which as I said doesn't really match my own use of the term I'm affraid. I usually think of composition that results in a new type of objects. I think a more precise term for this would be valuable in a DCI context
Injection: "RoleMethod injection is a mechanism that maintains the invariant: “For any given Role, its RoleMethods are shared among all its RolePlayers.”The glossary does not mention the important characteristic that a RoleMethod is stateless and has access to the current RolePlayer (through self?, this?) and the CurrentContext. ...
RoleMethod. A stateless method that is a feature of a Role and that is shared among all
the Role’s RolePlayers. A RoleMethod can access the RolePlayer currently mapped to the Role and also the CurrentContext.
Polymorphism does not apply to these methods; methods specified for the Roles have priority over methods specified in the RolePlayer classes.
I think I do understand the intention of the term "Stateless method", but at the same time I get a bit confused, since there would then also be a notion of "stateful method". I would say all methods are stateless? Traditionally, there are static and none-static methods (or class versus instance methods).
/Johan
On 3 jul 2011 v26, at 10.32, Trygve Reenskaug wrote:
It sounds like a good idea to add something about a 'DCI Trait' to our glossary (lexicon).
In the vanilla Traits implementation in Squeak, a Trait method is stateless in itself, but can access the state of selected objects through accessors to self or this� (self getX; self putX). A Squeak/Trait method can also access global variables, but this may be incidental. In my extension to Squeak/Traits, a Trait method can also access the CurrentContext and thereby its state and its Roles and RolePlayers. (Ther latter through the RoleMap of the CurrentContext).
The glossary version of April 10, 2011, defines
Injection:� "RoleMethod injection is a mechanism that maintains the invariant: �For any given Role, its RoleMethods are shared among all its RolePlayers.�
The glossary does not mention the important characteristic that a RoleMethod is stateless and has access to the current RolePlayer (through self?, this?) and the CurrentContext. ...
May be this can best be fixed by adding a few words to the definition of RoleMethod:
RoleMethod. A stateless method that is a feature of a Role and that is shared among all
the Role�s RolePlayers. A RoleMethod can access the RolePlayer currently mapped to the Role and also the CurrentContext.
Polymorphism does not apply to these methods; methods specified for the Roles have priority over methods specified in the RolePlayer classes.
The underlined words are the proposed addition.
Comments?
--Trygve
On 2011.07.02 21:54, Rune Funch S�ltoft wrote:Den 02/07/2011 kl. 21.45 skrev "James O. Coplien" <jcop...@gmail.com>:On Jul 2, 2011, at 5:01 , rune funch wrote:What I actually stated was that you could use the dynamic binding to create traitsCareful on the terminology. I usually use "traits" to describe semantics like class composition. I don't view Ruby as using traits. DCI does not depend on traits. Maybe it's worthwhile adding "traits" to our lexicon, with a formal delineation.I actually think the original paper has a pretty good definition (http://scg.unibe.ch/archive/papers/Scha03aTraits.pdf) which as I said doesn't really match my own use of the term I'm affraid. I usually think of composition that results in a new type of objects. I think a more precise term for this would be valuable in a DCI context-- You received this message because you are subscribed to the Google Groups "object-composition" group. To post to this group, send email to object-co...@googlegroups.com. To unsubscribe from this group, send email to object-composit...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/object-composition?hl=en.
--
Trygve Reenskaug������ mailto: try...@ifi.uio.no
Morgedalsvn. 5A ������� http://folk.uio.no/trygver/
N-0378 Oslo�������������� Tel: (+47) 22 49 57 27
Norway
--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To post to this group, send email to object-co...@googlegroups.com.
To unsubscribe from this group, send email to object-composit...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/object-composition?hl=en.
--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To post to this group, send email to object-co...@googlegroups.com.
To unsubscribe from this group, send email to object-composit...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/object-composition?hl=en.
Trygve Reenskaug������ mailto: try...@ifi.uio.no
Morgedalsvn. 5A ������� http://folk.uio.no/trygver/
N-0378 Oslo�������������� Tel: (+47) 22 49 57 27
Norway
To my understanding, a stateless method is a piece of code safe to be
called at any time. As opposed to a "stateful method" (it does sound
awful, by the way) who modifies the state of the receiver, the
stateless method doesn't require the receiver to be in a given state
before being callable, and is side-effect-free. In a way, stateless
methods are more like functions than traditional methods.
--
For side effects my C++ background leads me to "const" or "constant" who opposite would be "non-const" or "mutating" (I dislike non-mutating as the affirmative consideration, that it is safe, should be the primary term - which I guess should cause me to favor independent over non-contingent). I can see that some folk might not like const as it could imply other things like constant runtime or space requirements but I struggle for a better term.
"Stateful method" does perhaps sounds ambiguous as it might be interpreted as either or both of these concerns whereas "stateless" might imply that it is both independent and constant.Feel free to provide better words especially if you think my terms overlap with something else too much. Given the above, is my assumption correct that a Role Method would be an independent constant method?
I don't think being an object vs class method is necessarily a consideration, correct?
From: object-co...@googlegroups.com [mailto:object-co...@googlegroups.com] On Behalf Of rune funch
Sent: 5. juli 2011 09:28
To: object-co...@googlegroups.com
Subject: Re: Glossary extension for Traits? (was 'How to model a DCI system?')
2011/7/5 proteus guy <prote...@gmail.com>
Feel free to provide better words especially if you think my terms overlap with something else too much. Given the above, is my assumption correct that a Role Method would be an independent constant method?
It wouldn't be constant side effects are likely (just see the transfer money example)
I don’t see the need for role methods to be independent always. Again see the money transfer example.
I think this discussion is chasing the wrong horse. We are talking about methods on roles. Methods are run-time animals; roles (traits), compile-time. I think the stipulation might be that roles be logically stateless.
Sent from my iPad
- Role methods are design to be mixed into the set of instance methods of the role player class or object?
"RoleMethod. A method that is a feature of a Role and that is shared among all
the Role’s RolePlayers. A RoleMethod is design to be mixed into the set of instance methods of role player object. Unlike a native methods of a role player, A RoleMethod has access to the CurrentContext."
/Johan
> - Role methods are design to be mixed into the set of instance methods of the role player class or object?
That kind of smacks of aspects, which they're not...
Again: I think the Wiki article's description of the methods is enough. Can't we just say that the roles / traits are logically stateless?
RoleMethod A method that is a feature of a Role and that is shared among all the Role’s RolePlayers.
An executing RoleMethod can access its actual parameters and temporary variables. It can also access the current RolePlayer and the current Context.
Polymorphism does not apply to these methods; methods specified for the Roles have priority over methods specified in the RolePlayer
classes.
Sounds good to me.
Med venlig hilsen / Best regards
Christian Horsdal Gammelgaard, Mjølner Informatics A/S
From: object-co...@googlegroups.com [mailto:object-co...@googlegroups.com] On Behalf Of Trygve Reenskaug
Sent: 5. juli 2011 10:16
To: object-co...@googlegroups.com
Subject: Re: Glossary extension for Traits? (was 'How to model a DCI system?')
Let me try to add the essence of figure 5 in the "Execution Model" article without using any special terms:
--
Let me try to add the essence of figure 5 in the "Execution Model" article without using any special terms:
RoleMethod A method that is a feature of a Role and that is shared among all the Role’s RolePlayers.
An executing RoleMethod can access its actual parameters and temporary variables. It can also access the current RolePlayer and the current Context.
Polymorphism does not apply to these methods; methods specified for the Roles have priority over methods specified in the RolePlayer
classes.
Acceptable?
--Trygve
--
Trygve Reenskaug mailto: try...@ifi.uio.no
Morgedalsvn. 5A http://folk.uio.no/trygver/
N-0378 Oslo Tel: (+47) 22 49 57 27
Norway
--
Christian Horsdal Gammelgaard, Mjølner Informatics A/S
From: object-co...@googlegroups.com [mailto:object-co...@googlegroups.com] On Behalf Of rune funch
Sent: 5. juli 2011 10:48
To: object-co...@googlegroups.com
Subject: Re: Glossary extension for Traits? (was 'How to model a DCI system?')
2011/7/5 Trygve Reenskaug <try...@ifi.uio.no>
Let me try to add the essence of figure 5 in the "Execution Model" article without using any special terms:
RoleMethod A method that is a feature of a Role and that is shared among all the Role’s RolePlayers.
An executing RoleMethod can access its actual parameters and temporary variables. It can also access the current RolePlayer and the current Context.
Polymorphism does not apply to these methods; methods specified for the Roles have priority over methods specified in the RolePlayer
classes.
Almost like it. There's to points I strugle with though.
"...Role’s RolePlayers" to me that sounds as if multiple objects can play the same role at the same time. I struggle to find a short and precise alternative
"...
methods specified in the RolePlayer
classes." implies that such a thing as classes exists but that's language specific. I'd preferre something like
"...methods specified by RolePlayer instance
"
Or ”RolePlayer object”
Acceptable?
--Trygve
--
Trygve Reenskaug mailto: try...@ifi.uio.no
Morgedalsvn. 5A http://folk.uio.no/trygver/
N-0378 Oslo Tel: (+47) 22 49 57 27
Norway
--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To post to this group, send email to object-co...@googlegroups.com.
To unsubscribe from this group, send email to object-composit...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/object-composition?hl=en.
"...methods specified by RolePlayer instance" is OK with me.
> So I think a serious drawback of my extension method approach is that
> the domain objects must 'implement' marker interfaces for the roles
> they need to play.
Now we're talking!
Yes, this is an issue. It's actually something we've spent a lot of
time getting right in re-mix - it's a big difference whether a target
class "uses" a mixin (much like classical multiple inheritance in its
purpose), or whether a class is "extended" by a mixin. Dependencies
matter.
I'm pretty sure I've seen some Qi4j samples doing it the other way
around though. Were these obsolete samples, or is this still up to
debate? Or is (was?) it just a limitation of Qi4j?
Here's a piece of C# code based on re-mix:
// seperate the capabilities of Account into several interfaces
(interface
// seggregation, taken to an extreme for the sake of demonstration.
we
// could combine them, but then the dependencies of roles would
increase.)
public interface ILoggable
{
void Log(string s);
}
public interface IDecreasable
{
void DecreaseBalance(decimal amount);
}
public interface IIncreasable
{
void IncreaseBalance (decimal amount);
}
// Account actually implements all those interfaces in order to
qualify
// the roles that depend on them. if it wouldn't, we could create
mixins
// to translate between specific Roles and RolePlayers.
public class Account : ILoggable, IDecreasable, IIncreasable
{
decimal _balance = 0;
public void Log (string s)
{
Console.WriteLine(s + " (new balance: " + Balance + ")");
}
public void DecreaseBalance (decimal amount)
{
_balance -= amount;
}
public void IncreaseBalance (decimal amount)
{
_balance += amount;
}
public decimal Balance
{
get { return _balance; }
}
}
// now we declare the interfaces we will use to access RolePlayers via
// their roles. concrete classes that implement these roles can
already
// be wired up at this point. so while Account might be implemented
in
// a different assembly with no dependency on this assembly, instances
// will still implement these interfaces.
[CompleteInterface (typeof (Account))]
public interface IMoneyTransferSourceRole : ILoggable, IDecreasable
{ }
[CompleteInterface(typeof(Account))]
public interface IMoneyTransferDestinationRole : ILoggable,
IIncreasable { }
// this is the interface that is exposed by the mixin that adds the
// RoleMethods. it is of no interest to anybody outside the
implementation
// of MoneyTransfer.
public interface IMoneyTransferSourceRoleImpl
{
bool TransferTo(IMoneyTransferDestinationRole destination, decimal
amount);
}
// the actual mixin. it declares classes to be applied upon, but this
// doesn't have to happen here (useful if the assemblies defining
// Account and MoneyTransfer don't know each other)
[Extends (typeof (Account))]
public class MoneyTransferSourceMixin :
Mixin<IMoneyTransferSourceRole>, IMoneyTransferSourceRoleImpl
{
public bool TransferTo (IMoneyTransferDestinationRole destination,
decimal amount)
{
Target.DecreaseBalance (amount);
Target.Log ("Withdrew: " + amount);
destination.IncreaseBalance (amount);
destination.Log ("Deposited: " + amount);
return true;
}
}
// the context. nothing surprising here, but note the absence of any
// references to concrete types
public class MoneyTransferContext
{
public IMoneyTransferSourceRoleImpl Source;
public IMoneyTransferDestinationRole Destination;
public decimal Amount;
public MoneyTransferContext(IMoneyTransferSourceRole source,
IMoneyTransferDestinationRole destination, decimal amount)
{
Source = (IMoneyTransferSourceRoleImpl) source;
Destination = destination;
Amount = amount;
}
public void Execute ()
{
Source.TransferTo (Destination, Amount);
}
}
class Program
{
static void Main(string[] args)
{
Account s = ObjectFactory.Create<Account>();
s.IncreaseBalance (1000);
Account d = ObjectFactory.Create<Account>(ParamList.Empty);
d.IncreaseBalance (2000);
var c = new MoneyTransferContext((IMoneyTransferSourceRole) s,
(IMoneyTransferDestinationRole) d, 100);
c.Execute();
}
}
(we could write 'new' instead of ObjectFactory.Create, but then we'd
have to run a tool after compilation)
This code is much more about keeping interfaces separate and avoiding
dependencies than anything else. The actual mixin just plays a
supporting role in this play. Could this be the gist of DCI after all?
Stefan
--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To post to this group, send email to object-co...@googlegroups.com.
To unsubscribe from this group, send email to object-composit...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/object-composition?hl=en.
i'm hoping to learn about this as well, now that you have mentioned it.
here's my guess: i can describe 2 extremes of system implementation.
(1) is classic functional decomposition from the old days. this makes
a system that does one thing well. and makes it usually not too hard
to see exactly the flow of things. however when you try to implement a
change, you might have to rip up the world, which sucks.
(2) is the dope-smoking kool-aid drinking OO-to-the-hilt approach with
polymorphism and messaging and multiple communicating finite state
machines that are working in a conversation, not a functional
decomposition. your system is inherently more flexible when it comes
to handling a variety of similar conversations. this is better than
f.d. /however/ it can lead to code that is bloody hard to understand
and maintain and get right.
a problem with (2) is when you do it with standard OO junk like single
inheritance, or even mixins. traits give a way to more flexibly be
doing an "open-closed" principle. so i hazard to guess that things
like mixins and traits in DCI and other things are about walking a
middle path between (1) and (2) above.
sincerely.
> But I still don't see a reason to implement the RoleMethod via mixins.
Each of these role methods operates on a specific object during a given use case enactment.
If you don't put this code in a mix-in, where do you propose putting it?
i suspect people can think of plenty of options for where it can go,
but one has to then understand the negative consequences for each of
those options. once the light dawns about how ungood those options
are, maybe then the mix-in approach is more clearly desirable.
sincerely.
another way of stating the general-philosophical-level question is:
for software development in the widest sense, "why should any given
aspect of our code be joined at the hip with any other vs. there being
some form of separation/indirection & the ability to fuse things only
as/when need?" (one take on the latter is e.g. "applicative"
programming / mathematically more pure functional programming in the
sense of combining fragments together as people often do in the lands
of haskell, ml, scalaz.) the systems we use, like java and c#, tend to
have some default approaches. people are used to them. they don't see
or feel particular pains, they are inured to them. we all have to
question what the inflection point is, when the benefits outweigh the
costs (subjectively and along many dimensions), for joining some
concepts together in the code. as any paradigm must, dci says certain
pains are more important than others.
sincerely.
> i suspect people can think of plenty of options for where it can go,
> but one has to then understand the negative consequences for each of
> those options. once the light dawns about how ungood those options
> are, maybe then the mix-in approach is more clearly desirable.
>
> sincerely.
I am indeed trying to follow a rhetorical path, based on a concrete answer, that would help people discover that for themselves...
So, let me ask again (to those who don't already understand the answer): If not in a role, where would you put it?
The more interesting conclusion from my sample for myself is this: I see a good reason to use re-mix for composing interfaces. And I would see a reason for using mixins to implement roles on objects that don't naturally support them.
But I still don't see a reason to implement the RoleMethod via mixins. Once I've compiled the role interfaces, why not just use static methods?
Or, more likely, instance methods on the context? (that would spare us the "current context" problem, the stack-based solution has so many unwanted side effects: no concurrency, only one active context at a time...
But when were talking about implementations, we get back to this question: why bother to inject those methods?
If you take polymorphism and state out of the equation, there's nothing a mixin can do that a plain old extension method can't. And those are just static methods with funny syntax.
Cheers,
Stefan
Sent from my phone
----- Ursprüngliche Nachricht -----
Von: Raoul Duke
Gesendet: Mittwoch, 06. Juli 2011 14:50
An: object-co...@googlegroups.com
Betreff: Re: How to model a DCI system?
sincerely.
--
Stefan
Sent from my phone
----- Ursprüngliche Nachricht -----
Von: James O. Coplien
Gesendet: Mittwoch, 06. Juli 2011 16:03
An: object-co...@googlegroups.com
Betreff: Re: How to model a DCI system?
--
Stefan
Sent from my phone
----- Ursprüngliche Nachricht -----
Von: Raoul Duke
Gesendet: Mittwoch, 06. Juli 2011 18:17
An: object-co...@googlegroups.com
Betreff: Re: How to model a DCI system?
sincerely.
--
> Like I said: static/extension methods are just fine.
Justification?
Quantification?
In terms of DCI's goals of supporting end-user and programmer mental models?
I find them a poor man's hack, but it at least supports some consistent programming conventions when combined with the right conventions and disciplines. Again: C# with extension methods is not DCI.
The code I've posted will work.
If you declare roles via interfaces
, and role methods operate on role players via those interfaces, you need to implement the interfaces' methods in every role player (e.g. The Log, increase/decreasebalance methods in the money transfer sample). All the samples I've seen so far just implement these methods directly on the role player. The question was only, do we implement the actual interface too on the RP?
From: object-co...@googlegroups.com [mailto:object-co...@googlegroups.com] On Behalf Of Wenig, Stefan
Sent: 7. juli 2011 15:35
To: object-co...@googlegroups.com
Subject: AW: Re: How to model a DCI system?
If you declare roles via interfaces, and role methods operate on role players via those interfaces, you need to implement the interfaces' methods in every role player (e.g. The Log, increase/decreasebalance methods in the money transfer sample). All the samples I've seen so far just implement these methods directly on the role player. The question was only, do we implement the actual interface too on the RP?
We may declare roles via interfaces, but the role methods do not operate on the role players via those interfaces. The role methods implement those interfaces, and operate on the RPs via other interfaces.
With mixins you could go further and inject implementations for these methods. You could also share them. However, a mixin needs to operate on a specified type or interface too. the basic capabilities have to be in the RP already.
Sounds exactly like what we want for a role: sharing the implementation of the role methods among all the RPs. And letting the role methods operate on the RPs through some interface/controact.
/Christian
With mixins you could go further and inject implementations for these methods.
Jim,
there are several issues here that I think should be treated separately:
1) Thinking and modeling in roles: i totally think this is a good idea. I like the 90s ideas that started with role models (Trygve was an essential driver here), took a turn around multi-dimensional separation of concerns (MDSOC), surrendered to AOP and eventually died with it. I would very much like MDSOC to come back, because I think it still stands, and the reasons that made AOP die don"t apply to MDSOC. But it hasn't come back, and the only "surviving" community around seems to be DCI, so I'm trying to understand it. My thinking is grounded in MDSOC, I have experience with this and not with DCI, so obviously I'm trying to relate it.
2) The tool provider perspective: Once we have an exact definition of what DCI should be (I believe we don't have this yet), we can start designing languages around it, or providing support for existing languages. Especially for an existing language, I'm always looking for the most straightforward way, because it will integrate best with existing knowledge, tools etc. If you introduce a concept like mixins to a language that doesn't support it, you'll have to deal with some issues, and you want to see good benefits for that. From what I've seen, DCI doesn't require mixins, traits or any such advanced concept. (Except maybe for adapters between role-interfaces and RolePlayers as I wrote before, but even those could possibly be realized just as well using adapter objects)
3) Polymorphism or not. This is interesting to me for two reasons:
a) the MDSOC perspective: like the name says, this is all about separation of concerns. SoC was also very prominent in Trygves early papers. On an implementation level, this boils down to the question: how can youc combine the advantages of polymorohism with the SoC-wise advantages of functional decomposition?
DCI avoids this by declaring polymorphism harmful. But this claim is not based on any evidence, consensus, or discussion. It's just stated as a fact in some DCI papers. I don't think I'm out of line if I say that the rest of the world would disagree. So if you cannot show me the difference between DCI and functional decomposition, I'm naturally wondering how DCI would not put us back into pre-OO ages in many ways, even if it brings other advantages. On the other hand, if you just removte this assumption from DCI, you might end up with something that brings us the best of MDSOC plus some benefits of more explicit role modeling than the MDSOC literature has to offer.
b) Implementing MDSOC is only difficult if you also want to have the advantages of polymorphism. Every implementation of MDSOC, be it using multiple inheritance, a specific language like HyperJ, or using AOP (Jacobson), focuses on this. Without polymorphism, it is easy: use procedures. So this is interesting to me from a tool provider's perspective.
The comparison with Freud and couches is misleading in many ways. There is nothing wrong with philosphical views, but computer science is called a science for a reason. Every useful philosophical idea will eventually be implemented in real designs and real code. And there will be real benefits and real costs that can be discussed. The sooner you stop hiding behind philosophical answers and start giving real answers to real questions, the sooner DCI will stand a chance to be going anywhere.
Stefan
1) Thinking and modeling in roles: i totally think this is a good idea.
I thought Christian's extension method sample has it all, but then he brought up the problem of upside-down dependencies (role players have to implement role interfaces)
I posted a sample that uses re-mix' ability to declare implemented interfaces externally from the class that should implement them. This solves the dependency problem. (the inaptly-named [CompleteInterface] attribute)
So this was fine. Then I went ahead and implemented a RoleMethod via a mixin, but I think this part wasn't necessary.
RoleMethod == procedure
In C# I'd use static methods or instance methods of context objects
- Their scope is local within their context
- the only effect of merging them with instance methods of the role player that's discussed in any of the papers I've read is unwanted name collissions, no advantages
- there is no abstraction or indirection within a single context - you program to classes, not interfaces. In fact, creating hard-coded dependencies seems to be a goal of DCI as you describe it, because no indirections == easier to review
You can still apply every philosophical idea of DCI. You might be tempted to use C# extension methods because they would make very clear which role a method belongs to ('this' keyword). But any convention would do (e.g. first parameter of RoleMethod specifies the Role it's acting on).
That doesn't mean I wouldn't use mixins or traits, but only because I'm not buying the "polymorphism is harmful" part of DCI.
Cheers,
Stefan
Sent from my phone
----- Ursprüngliche Nachricht -----
Von: Wenig, Stefan
Gesendet: Donnerstag, 07. Juli 2011 09:13
An: object-co...@googlegroups.com
Betreff: AW: Re: How to model a DCI system?
> I'd write a sample but just have my phone now.
I'll wait for the sample.
This probably won't compile or run.
Stefan
Sent from my phone
// seperate the capabilities of Account into several interfaces
(interface
// seggregation, taken to an extreme for the sake of demonstration.
we
// could combine them, but then the dependencies of roles would
increase.)
public interface ILoggable
{
void Log(string s);
}
public interface IDecreasable
{
void DecreaseBalance(decimal amount);
}
public interface IIncreasable
{
void IncreaseBalance (decimal amount);
}
// Account actually implements all those interfaces in order to
Qualify for
// the context. note the absence of any
// references to concrete types
public class MoneyTransferContext
{
public IMoneyTransferSourceRole Source;
public IMoneyTransferDestinationRole Destination;
public decimal Amount;
public MoneyTransferContext(IMoneyTransferSourceRole source,
IMoneyTransferDestinationRole destination, decimal amount)
{
Source = source;
Destination = destination;
Amount = amount;
}
public void Execute ()
{
TransferTo (Source, Destination, Amount);
// was: Source.TransferTo (Destination, Amount);
}
// this method used to be in the mixin.
private bool TransferTo (IMoneyTransferSourceRole source, IMoneyTransferDestinationRole destination,
decimal amount)
{
source.DecreaseBalance (amount);
source.Log ("Withdrew: " + amount);
destination.IncreaseBalance (amount);
destination.Log ("Deposited: " + amount);
return true;
}
}
class Program
{
static void Main(string[] args)
{
Account s = ObjectFactory.Create<Account>();
s.IncreaseBalance (1000);
Account d = ObjectFactory.Create<Account>(ParamList.Empty);
d.IncreaseBalance (2000);
var c = new MoneyTransferContext((IMoneyTransferSourceRole) s,
(IMoneyTransferDestinationRole) d, 100);
c.Execute();
}
}
----- Ursprüngliche Nachricht -----
Von: Stefan Wenig
Gesendet: Samstag, 02. Juli 2011 01:22
An: object-composition
Betreff: Re: How to model a DCI system?
Hi Christian!
Now we're talking!
Stefan
--
> Oh screw it, who says you can't code on a phone? Here's my sample using externally applied interfaces and RoleMethods as context methods. Pls comment.
>
> This probably won't compile or run.
There is literally no sense in discussing nonsense, and there is no hurry. The world will not end. Let's wait until we get some real code. Anything follows from a fantasy / fallacy.
BTW, my first sample compiled and ran just fine, and there were zero comments.
Stefan
Sent from my phone
----- Ursprüngliche Nachricht -----
Von: James O. Coplien
Gesendet: Freitag, 08. Juli 2011 10:53
An: object-co...@googlegroups.com
Betreff: Re: AW: Re: How to model a DCI system?
--
"...all the Role's potential RolePlayers"?
"...methods specified by RolePlayer instance" is OK with me.
On 2011.07.05 10:48, Christian Horsdal Gammelgaard wrote:Christian Horsdal Gammelgaard, Mjølner Informatics A/S
From: object-co...@googlegroups.com [mailto:object-co...@googlegroups.com] On Behalf Of rune funch
Sent: 5. juli 2011 10:48
To: object-co...@googlegroups.com
Subject: Re: Glossary extension for Traits? (was 'How to model a DCI system?')
2011/7/5 Trygve Reenskaug <try...@ifi.uio.no>
Let me try to add the essence of figure 5 in the "Execution Model" article without using any special terms:
RoleMethod A method that is a feature of a Role and that is shared among all the Role’s RolePlayers.
An executing RoleMethod can access its actual parameters and temporary variables. It can also access the current RolePlayer and the current Context.
Polymorphism does not apply to these methods; methods specified for the Roles have priority over methods specified in the RolePlayer
classes.
Almost like it. There's to points I strugle with though.
"...Role’s RolePlayers" to me that sounds as if multiple objects can play the same role at the same time. I struggle to find a short and precise alternative
"...
methods specified in the RolePlayer
classes." implies that such a thing as classes exists but that's language specific. I'd preferre something like
"...methods specified by RolePlayer instance
"
Or ”RolePlayer object”
Acceptable?
--Trygve
--
Trygve Reenskaug mailto: try...@ifi.uio.no
Morgedalsvn. 5A http://folk.uio.no/trygver/
N-0378 Oslo Tel: (+47) 22 49 57 27
Norway
--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To post to this group, send email to object-co...@googlegroups.com.
To unsubscribe from this group, send email to object-composit...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/object-composition?hl=en.
--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To post to this group, send email to object-co...@googlegroups.com.
To unsubscribe from this group, send email to object-composit...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/object-composition?hl=en.
--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To post to this group, send email to object-co...@googlegroups.com.
To unsubscribe from this group, send email to object-composit...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/object-composition?hl=en.
--
Trygve Reenskaug mailto: try...@ifi.uio.no
Morgedalsvn. 5A http://folk.uio.no/trygver/
N-0378 Oslo Tel: (+47) 22 49 57 27
Norway
Trygve Reenskaug mailto: try...@ifi.uio.no
Morgedalsvn. 5A http://folk.uio.no/trygver/
N-0378 Oslo Tel: (+47) 22 49 57 27
Norway
On Jun 30, 2011, at 10:44 , Trygve Reenskaug wrote:
It should be possible to write a guide for modeling DCI systems with UML.
Jim: Is this a theme for a Master or PhD? It could be a new and very useful intro for DCI novices.
The work would involve extracting useful bits from UML and possibly modifying them where necessary. The modifications could become input to a next version of UML.
I doubt that this is ph.d. material, but it could be a good MS project.--

template <class M, class State, class Stimulus> class AbstractFSM {public:virtual void addState(State) = 0;virtual void addTransition(Stimulus, State, State, void (M::*)(Stimulus));};class UserFSM: public AbstractFSM<UserFSM, char, char> {public:void x1(char);void x2(char); void init() {addState(1); addState(2); addTransition(EOF,1,2,&UserFSM::x1); ... .}};template <class UserMachine, class State, class Stimulus> class ImplementationFSM: public UserMachine {public:ImplementationFSM() { init(); }virtual void addState(State);virtual void addTransition(Stimulus, State from, State to, void (UserMachine::*)(Stimulus));virtual void fire(Stimulus);private:unsigned nstates;State *states, currentState;map<State, void(UserMachine::*)(Stimulus)> *transitionMap;};
The parallel side is likely just a mix of dci and the join calculus. You can do this easily today in scala using akkas futures.
On 11 Jul 2011 16:53, "James O. Coplien" <jcop...@gmail.com> wrote:
> My concerns:
>
> 1. With such a meta-model in hand, what could you do that you couldn't do today? UML to me is an informal communication tool, but the fact that you need to honor the effort with a full academic degree suggests to me that it isn't the first informalism I'd choose to communicate what DCI is.
>
> 2. I don't think that UML has sufficiently formal semantics to support Ph.D meta-modeling work.
>
> 3. I think parallel processes is a separate issue, a separate thesis, and I still don't understand why it has anything to do with DCI in particular.
>
> 4. UML is a collection of notations rather than a formalism. I'm not sure that the principle opportunities ahead of DCI lend themselves well to UML as a formalism. I'd identify the challenges first and the formalism separate. Each challenge might beg a different formalism. If the parallelism is important and in fact can be described using marked Petri nets, I don't understand the value is of bringing UML into the picture.
>
> 5. Though I think I know UML and DCI, I would never want my name associated with a Ph.D thesis that used UML as its expository formalism — either as a student or a professor. Part of it is that UML has become as passé as relational modeling as an academic topic, but part of it is that it can't stand up even to the formalism of relational modeling...
>
> I am not sure that express-ability in UML is necessarily a good thing. When we uncovered the indirect template idiom — now a staple of programming in C++ and a foundation of the STL — I used it to design a simple state machine. I went to Grady Booch and asked him how we could represent it in the Booch notation. It was almost unreadable. UML makes it a little better, but is still pretty opaque and lacks most of the interesting details. Do you think you can really understand this diagram?
>
>
>
My concerns:
1. With such a meta-model in hand, what could you do that you couldn't do today? UML to me is an informal communication tool, but the fact that you need to honor the effort with a full academic degree suggests to me that it isn't the first informalism I'd choose to communicate what DCI is.
2. I don't think that UML has sufficiently formal semantics to support Ph.D meta-modeling work.
3. I think parallel processes is a separate issue, a separate thesis, and I still don't understand why it has anything to do with DCI in particular.
4. UML is a collection of notations rather than a formalism. I'm not sure that the principle opportunities ahead of DCI lend themselves well to UML as a formalism. I'd identify the challenges first and the formalism separate. Each challenge might beg a different formalism. If the parallelism is important and in fact can be described using marked Petri nets, I don't understand the value is of bringing UML into the picture.
5. Though I think I know UML and DCI, I would never want my name associated with a Ph.D thesis that used UML as its expository formalism � either as a student or a professor. Part of it is that UML has become as pass� as relational modeling as an academic topic, but part of it is that it can't stand up even to the formalism of relational modeling...
I am not sure that express-ability in UML is necessarily a good thing. When we uncovered the indirect template idiom � now a staple of programming in C++ and a foundation of the STL � I used it to design a simple state machine. I went to Grady Booch and asked him how we could represent it in the Booch notation. It was almost unreadable. UML makes it a little better, but is still pretty opaque and lacks most of the interesting details. Do you think you can really understand this diagram?
I don't understand it, and I wrote the code. C++ programmers will find the code much more accessible (if you're not a C++ programmer, you'll probably find this code disgusting and ugly, much as a Finn probably finds German poetry disgusting and ugly):
template <class M, class State, class Stimulus>�class AbstractFSM {public:�� �virtual void addState(State) = 0;�� �virtual void addTransition(Stimulus, State, State,�void (M::*)(Stimulus));
};
class UserFSM: public AbstractFSM<UserFSM, char, char> {public:
�� �void x1(char);�� �void x2(char); void init() {�� � � �addState(1); addState(2); addTransition(EOF,1,2,&UserFSM::x1); ... .�� �}
};
template <class UserMachine, class State, class Stimulus> class ImplementationFSM: public UserMachine {public:
�� �ImplementationFSM() { init(); }�� �virtual void addState(State);�� �virtual void addTransition(Stimulus, State from,�State to,�void (UserMachine::*)(Stimulus));�� �virtual void fire(Stimulus);private:�� �unsigned nstates;�� �State *states, currentState;�� �map<State, void(UserMachine::*)(Stimulus)>�*transitionMap;};
I would much rather see a more formal basis for a DCI metamodel. Academic notations like the first-order predicate calculus are probably no more or less opaque than UML, but at least they have universally understood formal semantics. It's a good thing to get DCI more broadly understood, but I am not convinced that UML is the ideal tool to do this.
It would be a great thing to codify DCI so we could formally answer hard questions about it in the future, based an agreed, formal model of its fundamentals. That could be a good Ph.D thesis.
On Jul 10, 2011, at 2:21 , Trygve Reenskaug wrote:
Jim,
M.Sc. or P.D.for evolving a metamodel for DCI based on UML?�� It could include modeling parallel processes with DCI.
The advisor needs to be a UML expert as well as having internalized DCI. A tall order, methinks.
The role structure part should be relatively trivial.�
Modeling the behavior of a Context with its roles is more challenging.
Half of UML is about modeling the behavior of object systems. Most of this metamodel can possibly be applied to the Context. This includes multi-process as well as sequential execution. UML has has rich semantics for modeling behavior such as state machines, Petri nets, data flow graphs, etc.
This is far outside my expertise, but UML looks promising to an uninformed eye. (UML has disappointed me in the past, but it need not do so in this case)
--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To post to this group, send email to object-co...@googlegroups.com.
To unsubscribe from this group, send email to object-composit...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/object-composition?hl=en.
Trygve Reenskaug������ mailto: try...@ifi.uio.no
Morgedalsvn. 5A ������� http://folk.uio.no/trygver/
N-0378 Oslo�������������� Tel: (+47) 22 49 57 27
Norway
Let me try to add the essence of figure 5 in the "Execution Model" article without using any special terms:
RoleMethod A method that is a feature of a Role and that is shared among all the Role’s RolePlayers.
An executing RoleMethod can access its actual parameters and temporary variables. It can also access the current RolePlayer and the current Context.
Polymorphism does not apply to these methods; methods specified for the Roles have priority over methods specified in the RolePlayer
classes.
Acceptable?
--Trygve
--
Trygve Reenskaug mailto: try...@ifi.uio.no
Morgedalsvn. 5A http://folk.uio.no/trygver/
--N-0378 Oslo Tel: (+47) 22 49 57 27
Norway
On Tue, Jul 5, 2011 at 4:15 AM, Trygve Reenskaug <try...@ifi.uio.no> wrote:
Let me try to add the essence of figure 5 in the "Execution Model" article without using any special terms:
RoleMethod A method that is a feature of a Role and that is shared among all the Role’s RolePlayers.
An executing RoleMethod can access its actual parameters and temporary variables. It can also access the current RolePlayer and the current Context.
Polymorphism does not apply to these methods; methods specified for the Roles have priority over methods specified in the RolePlayer
This is a problem whey implementing RoleMethods as extension methods in C#. RolePlayer methods take precedence.
OK, here's the next version of my sample without mixins (it still uses re-mix to address the problem of composing role interfaces from individual interfaces without creating dependencies from RolePlayers to Roles).
I tried to address the requirements I identified in my last mail:
1) code elegance: instance methods are usually more elegant than accessing parameter #1
Not much I can do about that. I name the first parameter representing the role 'self' (not a reserved keyword in C#). I also attach the [MethodRole] attribute (annotation) to this parameter, which is just for readability and has no actual functionality.
2) namespaces for each role
No problem in C# due to method overloading - the role parameter is part of the method's signature
3) independent files/modules for each role
I use partial classes for each role's methods. They can easily be distributed among several files. This clearly lacks in the elegance area. However, the only real disadvantages I see are that
a) putting role methods in the right partial class/file is not enforced
b) looking at the compiled context class (via tools/reflection) is a mess
If you compare this to my first sample using mixins, I'd say the mixin version is more elegant since it more clearly reflects the intention of the code. It also keeps the compiled classes separate, and even the generated classes are merged by RolePlayer class (not by context class) which is much more useful.
On the other hand, this version does have two important benefits:
- it does not require learning additional syntax and concepts, or additional libaries or tooling
- RoleMethods have direct access to their context
Only the context class changed since the last time, so I put it first.
Cheers,
Stefan
// the context (general part)
public partial class MoneyTransferContext
{
public IMoneyTransferSourceRole Source;
public IMoneyTransferDestinationRole Destination;
public MoneyTransferContext (IMoneyTransferSourceRole source,
IMoneyTransferDestinationRole destination)
{
Source = source;
Destination = destination;
}
// slight modification: Transfer instead of Execute, amout is
// specified to separate roles from (temporary) arguments
public bool Transfer (decimal amount)
{
TransferTo (Source, amount);
}
}
// all methods for IMoneyTransferSourceRole
public partial class MoneyTransferContext
{
// this time, the destination is not a parameter in order to
// demonstrate simple and direct access to other roles via
// the context
private bool TransferTo( [MethodRole] IMoneyTransferSourceRole self,
decimal amount)
{
self.DecreaseBalance (amount);
self.Log ("Withdrew: " + amount);
Destination.IncreaseBalance (amount);
Destination.Log ("Deposited: " + amount);
return true;
}
}
class Program
{
static void Main(string[] args)
{
Account s = ObjectFactory.Create<Account>();
s.IncreaseBalance (1000);
Account d = ObjectFactory.Create<Account>(ParamList.Empty);
d.IncreaseBalance (2000);
var c = new MoneyTransferContext ((IMoneyTransferSourceRole) s,
(IMoneyTransferDestinationRole) d);
c.Transfer (100);
That's not quite correct. if I want to avoid re-mix at all, I also have to stop using the [CompleteInterface] attribute, so I'd have to implement role interfaces directly with RolePlayer types, potentially leading to the dependency problem Christian mentioned.
Although this is probably a separate debate, I'll also include this version for completeness. It's just a matter of removing the [CompleteInterface] attribute and including those interfaces in the list of interfaces implemented by the RolePlayers. Furthermore, objects can now be constructed using the 'new' operator without any additional compile-time steps.
// seperate the capabilities of Account into several interfaces (interface
// seggregation, taken to an extreme for the sake of demonstration. we
// could combine them, but then the dependencies of roles would increase.)
public interface ILoggable
{
void Log(string s);
}
public interface IDecreasable
{
void DecreaseBalance(decimal amount);
}
public interface IIncreasable
{
void IncreaseBalance (decimal amount);
}
// Account actually implements all those interfaces in order to Qualify for
// the roles that depend on them. if it wouldn't, we could create mixins
// to translate between specific Roles and RolePlayers.
public class Account : ILoggable, IDecreasable, IIncreasable, IMoneyTransferSourceRole, IMoneyTransferDestinationRole
{
decimal _balance = 0;
public void Log (string s)
{
Console.WriteLine(s + " (new balance: " + Balance + ")");
}
public void DecreaseBalance (decimal amount)
{
_balance -= amount;
}
public void IncreaseBalance (decimal amount)
{
_balance += amount;
}
public decimal Balance
{
get { return _balance; }
}
}
// declaration of role interfaces
public interface IMoneyTransferSourceRole: ILoggable, IDecreasable { }
public interface IMoneyTransferDestinationRole: ILoggable, IIncreasable { }
// the context (general part)
public partial class MoneyTransferContext
{
public IMoneyTransferSourceRole Source;
public IMoneyTransferDestinationRole Destination;
public MoneyTransferContext (IMoneyTransferSourceRole source,
IMoneyTransferDestinationRole destination)
{
Source = source;
Destination = destination;
}
// slight modification: Transfer instead of Execute, amout is
// specified to separate roles from (temporary) arguments
public bool Transfer (decimal amount)
{
TransferTo (Source, amount);
}
}
// all methods for IMoneyTransferSourceRole
public partial class MoneyTransferContext
{
// this time, the destination is not a parameter in order to
// demonstrate simple and direct access to other roles via
// the context
private bool TransferTo([MethodRole] IMoneyTransferSourceRole self,
decimal amount)
{
self.DecreaseBalance (amount);
self.Log ("Withdrew: " + amount);
Destination.IncreaseBalance (amount);
Destination.Log ("Deposited: " + amount);
return true;
}
}
class Program
{
static void Main(string[] args)
{
Account s = new Account();
s.IncreaseBalance (1000);
Account d = new Account();
> TransferTo (Source, amount);
This statement kind of offends my sense of aesthetics. It doesn't look like an operation on the Source role. And the Destination role should be implicated here, and is not. Or maybe I'm just confused.
I'm not saying this can't be more beautiful. But how much trickery are we ready to put up with just to get more beautiful method invocation code? We need better reasons.
The destination role question is interesting. I personally don't have a very strong opinion about this, but isn't one of the advantages of DCI that you do not need to pass around role objects, but rather access the context directly from RoleMethds? I read some of Rickard's messages this way. Also, if this is not required, what's the big deal about accessing the context from RoleMethods via some stack in Trygve's execution paper? Passing everything around as parameters is easy and creates none of these problems (unique active context, single thread).
It's a bit hard to come up with answers if I have to show my own ideas and guess what DCI would require at the same time. A good, complete sample is overdue. And again, this sample just has to show how it's done, not prove the usefulness of DCI.
Cheers,
Stefan
> --
> You received this message because you are subscribed to the Google
> Groups "object-composition" group.
> To post to this group, send email to object-
> To unsubscribe from this group, send email to object-
> composition...@googlegroups.com.
/Rune
> I'm not saying this can't be more beautiful. But how much trickery are we ready to put up with just to get more beautiful method invocation code? We need better reasons.
I would never hire anyone who said that to work on real code.
> It's a bit hard to come up with answers if I have to show my own ideas and guess what DCI would require at the same time. A good, complete sample is overdue. And again, this sample just has to show how it's done, not prove the usefulness of DCI.
We are waiting for your good, complete sample.
Have you read RIckard's sample? That qualifies as a good, complete sample to me. It's commercially deployed.
Have you read the Lean Architecture Book yet to understand a bit more of the context, history and motivation?
Paradigm shifts are hard. This is a paradigm shift, into object thinking. It sounds like you're not there yet. I empathize with your difficulty, but would challenge you to higher aspirations and continued work. For some, it's just too hard, and if that's the case, you're always welcome to leave. But neither should you expect to learn everything here without having gone through the basics: the fact that you say that there is no, good, complete sample makes me wonder if you've taken advantage of the basic startup resources available to you.
I know we need a FAQ page. Let me again see what I can do about that.
--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To post to this group, send email to object-co...@googlegroups.com.
To unsubscribe from this group, send email to object-composit...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/object-composition?hl=en.
No need to discuss controversial matters then, how convenient.
> -----Original Message-----
> From: object-co...@googlegroups.com [mailto:object-
> compo...@googlegroups.com] On Behalf Of rune funch
> Sent: Sunday, July 31, 2011 1:21 PM
> To: object-co...@googlegroups.com
> Subject: Re: How to model a DCI system?
>
If you are here to teach, you'll need to get some credibility with us first.
I do appreciate your efforts. At least you're writing code, which most people don't try. I know it is frustrating. But, like I say, it's a paradigm shift. That you can't make a paradigm shift doesn't mean you're clueless, or that those in the current paradigm are smart. It just means that we're different, and that we're human.
> To post to this group, send email to object-co...@googlegroups.com.
> To unsubscribe from this group, send email to object-composit...@googlegroups.com.
Maybe we can get this discussion back to a more productive level.
I just provided two very different samples, one with mixins and one based on a simpler implementation that nevertheless maps 1:1 to the conceptual model of DCI as I understand it so far. I did not express a preference of one of them. All I did was stating my opinion that the purely syntactical matter of writing a.Foo(b) vs. Foo (a,b) alone is not important enough to ignore all other factors.
Is that really a reason to resort to personal attacks?
I did clearly not read every available piece of information about DCI. I read that part of your book, several papers by Trygve, and some of the mailing list code. I looked for samples and found some, but I don't know which of them are really worth giving a close look. Are they authorative? Do they implement DCI as it is agreed upon in this group, or do they contain additional or controversial stuff? I cannot know that, so I came here to ask.
If there is a sample that would answer my questions, please just share a link.
Stefan
> -----Original Message-----
> From: object-co...@googlegroups.com [mailto:object-
> compo...@googlegroups.com] On Behalf Of James O. Coplien
> Sent: Sunday, July 31, 2011 1:34 PM
> To: object-co...@googlegroups.com
> Subject: Re: How to model a DCI system?
>
>
I asked for samples. The answer was: go write your own.
I provided samples with some discussion. The answer now is that I'm not up to understanding the paradigm shift that is so obvious to everyone else here, and I might want to consider going away.
I wonder what I should try next.
To post to this group, send email to object-co...@googlegroups.com.
To unsubscribe from this group, send email to object-composit...@googlegroups.com.
Hi Jim
Maybe we can get this discussion back to a more productive level.
Let me know, and we'll go from there.
Sent from my iPhone
> To post to this group, send email to object-co...@googlegroups.com.
> To unsubscribe from this group, send email to object-composit...@googlegroups.com.
I did read that as an insult, but I don’t insist. Anyway, I can take one or two. All I’m asking is that replies refer to my questions and do not resort back to “DCI is so great and you just didn’t get it”. This does not help even if it’s true.
One thing that I do insist is that OOP is not defined by where in a method call the self parameter is. I did not and still do not consider this an attack on DCI, so I don’t understand the harsh reactions. Is this not something that can be discussed on this list? To me, this seems to be an essential part of discussing the relative advantages and disadvantages of various DCI implementations.
Stefan
> I did clearly not read every available piece of information about
> DCI. I read that part of your book, several papers by Trygve, and
> some of the mailing list code. I looked for samples and found some,
> but I don't know which of them are really worth giving a close look.
> Are they authorative? Do they implement DCI as it is agreed upon in
> this group, or do they contain additional or controversial stuff? I
> cannot know that, so I came here to ask.
>
> If there is a sample that would answer my questions, please just
> share a link.
I just tried to look at Rickard's samples, but it seems they have moved and I can't find them either at their old address http://dscm.ops4j.org/git/gitweb.cgi?p=qi4j-samples.git;a=tree;f=dci;h=d60693a8e7e162cf46e12ab37aeb09d246021f2a;hb=HEAD nor at github. Got a link to share?
Stefan
class Program
{Account s = new Account();
static void Main(string[] args)
{
s.IncreaseBalance (1000);
Account d = new Account();
d.IncreaseBalance (2000);
var c = new MoneyTransferContext ((IMoneyTransferSourceRole) s,
(IMoneyTransferDestinationRole) d);
c.Transfer (100);
}
}
One thing that I do insist is that OOP is not defined by where in a method call the self parameter is.