DCI in Javascript: eunomia

179 views
Skip to first unread message

Davide Callegari

unread,
Feb 24, 2015, 8:37:01 AM2/24/15
to object-co...@googlegroups.com
Hi guys,
I found myself intrigued by DCI lately and I wanted to try and see if I could write a proper library for Javascript, written in Coffeescript.
I would like to know if it could be interesting for anyone out there and I'm more than happy to welcome any feedback.


Let me know what you think!

Cheers,
Davide

Egon Elbre

unread,
Feb 24, 2015, 8:47:50 AM2/24/15
to object-co...@googlegroups.com
I would suggest implement the torture test

From a quick skim over the implementation it seems that you are using a wrapper:

Or alternatively I wasn't able to understand how the wrapper is elided.

+ Egon
(PS. mandatory disclaimer, listen to other people opinions more than mine :D)

Davide Callegari

unread,
Feb 24, 2015, 10:30:59 AM2/24/15
to object-co...@googlegroups.com
What I don't like about inferring methods to an object is that you can override previously held methods, override other role's methods, etc.
Also, reverting an applied role can be dangerous.

I know it's a paradigm of DCI to not change the identity of the objects but isn't it equivalent if you run the role's methods in the context of the object itself?

Hai Quang Kim

unread,
Feb 24, 2015, 10:31:57 AM2/24/15
to object-co...@googlegroups.com
welcome to the forum.
btw, fun fact: quick skim shows that you have a lot of role(s) with -er :)
there are a lot of old posts about wrapper, you can try to search for those posts.

/quang

Egon Elbre

unread,
Feb 24, 2015, 10:42:56 AM2/24/15
to object-co...@googlegroups.com
On Tuesday, 24 February 2015 17:30:59 UTC+2, Davide Callegari wrote:
What I don't like about inferring methods to an object is that you can override previously held methods, override other role's methods, etc.

You can override methods only locally inside the context; it's invisible to everything that is outside the context.

(Just a note that the torture test is only a torture test... it doesn't show how to write good DCI code. in practice you wouldn't write that convoluted code.)
 
Also, reverting an applied role can be dangerous.
 
Applying is not the only way to implement roles. (injectionless implementation for learning http://egonelbre.com/code/javascript-dci/)

I know it's a paradigm of DCI to not change the identity of the objects but isn't it equivalent if you run the role's methods in the context of the object itself?

No, the only way to understand why is to implement the Dijkstra algorithm. Only after doing that, I was able to understand why it is a good thing to have. Although, personally, I don't think it's vital.

+ Egon

James O Coplien

unread,
Feb 24, 2015, 3:14:40 PM2/24/15
to object-co...@googlegroups.com

On 24 Feb 2015, at 16:42, Egon Elbre <egon...@gmail.com> wrote:

You can override methods only locally inside the context; it's invisible to everything that is outside the context.

Exactly what does "override" mean here?

The point if DCI is to reduce everything to a static binding, modulo the role/object binding that applies atomically to all objects in the scope of a Context. There is no instance I know of that is both proper DCI and which overrides methods.

You can of course override instance methods of classes but by the time we're running a Context, those classes are gone and only objects remain.

Maybe I'm missing something here, but I'm a bit confused by the "clarification."

Egon Elbre

unread,
Feb 24, 2015, 3:26:29 PM2/24/15
to object-co...@googlegroups.com


On Tuesday, 24 February 2015 22:14:40 UTC+2, Cope wrote:

On 24 Feb 2015, at 16:42, Egon Elbre <egon...@gmail.com> wrote:

You can override methods only locally inside the context; it's invisible to everything that is outside the context.

Exactly what does "override" mean here?

Yeah, I was thinking what to exactly call it...

"reintroduce" as in Delphi
alternatively "shadowing method names"

There are two methods that have the same name and one has precedence in a specific Context. 

Not sure what the most accurate name is for that.

James O Coplien

unread,
Feb 24, 2015, 4:51:44 PM2/24/15
to object-co...@googlegroups.com

On 24 Feb 2015, at 21:26, Egon Elbre <egon...@gmail.com> wrote:

There are two methods that have the same name and one has precedence in a specific Context. 

In a given Context, role names are unique.

For a given object, method names — including role names — are unique. An instance method name should never collide with a role method name. That destroys comprehensibility of the Context.

Two given roles may each have a method of the same name, though that's a bit gauche and limits comprehensibility, particularly in the case where one object plays two roles.

I do not understand what you mean by two methods having the same name in a Context situation where there is an issue of precedence between them.

Matthew Browne

unread,
Feb 24, 2015, 11:02:45 PM2/24/15
to object-co...@googlegroups.com
On Tuesday, February 24, 2015 at 4:51:44 PM UTC-5, Cope wrote:
For a given object, method names — including role names — are unique. An instance method name should never collide with a role method name. That destroys comprehensibility of the Context.

I'm not sure that should be a hard and fast rule in a dynamic language like Javascript, where there is no need for a context stack. Whenever appropriate, a different / more specific name should be chosen for the role method even if it's just extending an instance method, but I think there can be exceptions to this.

For example, consider a shopping cart system with a Cart role in a context for adding items to the cart. Let's say the Cart data object has an addItems() method. I think in this case it might make sense for the Cart role to have a method that overrides the instance method Cart.addItems() but which first checks the inventory and does other validation. The role method could be called Cart.validateAndAddItems() but that's a bit lengthy and I think it would be nice to just call it Cart.addItems() and have it override the Cart.addItems() instance method, similarly to how methods in subclasses can override methods in parent classes in traditional polymorphism. Of course the problem with this example is that what I would really want to do is perform the validation, then call the Cart.addItems() instance method rather rewriting/copying the code that actually adds the items to a collection/list property. Making it possible to still call the instance method when it's already been overridden by a role method of the same name could be tricky and maybe should be forbidden. But there are other examples of polymorphism where you simply want to completely override a method with new behavior.

I have noticed that you have repeatedly argued against any name clashes at all in role method naming (aside from the same object playing multiple roles as you just mentioned) so maybe I'm still not understanding the deeper issues here. But with my current understanding it seems to me that there are plenty of artifacts available to the compiler to differentiate the role method from the instance method even if they have the same name - the compiler knows what roles the object can play and what context it's in when the role method is called.

Matthew Browne

unread,
Feb 24, 2015, 11:15:16 PM2/24/15
to object-co...@googlegroups.com
On Tuesday, February 24, 2015 at 10:42:56 AM UTC-5, Egon Elbre wrote:
Applying is not the only way to implement roles. (injectionless implementation for learning http://egonelbre.com/code/javascript-dci/)

+1
I think CoffeeScript presents a perfect opportunity for an injectionless implementation since there's a compilation step anyway. I think others here would agree that injectionless implementations are currently considered the "gold standard" for DCI - not that other implementations can't be useful.

Hai Quang Kim

unread,
Feb 25, 2015, 12:16:11 AM2/25/15
to object-co...@googlegroups.com
"Although, personally, I don't think it's vital."

Let's say we have a function in Data Object (Composite) that will add a Component into the List in the Composite.
Let's say in a Context we have a Role that is played by the Component. 
Now if we want to check whether or not this Role Object is in the List of the Composite we may have issue since the Role is a wrapper and the List contains the Raw Component. We need to override the Equals function of Object and all kind of problems will come :)


I have this problem while trying to use wrapper.

/quang

Hai Quang Kim

unread,
Feb 25, 2015, 12:24:59 AM2/25/15
to object-co...@googlegroups.com
if you want to do pure DCI you may need to do your own implementation for injectionless DCI 

examples from Rune's Maroon/Interact: 
https://github.com/runefs/Interact

If you want to play with DCI and avoid heavy duty to implement the framework you can try what I did: Raw version of Injectionless DCI.

class Context
{
    RoleA  A;
    RoleB  B;

    Context(objectA, objectB)
    {
        A = objectA;   // no injection, just to indicate which object plays which role
        B = objectB;
    }

    // System operation
    public DoSomething()
    {
        RoleA_MethodX(); // start interaction
    }

    // RoleA Methods
    RoleA_MethodX()     //   using _ to simulate RoleMethod that belongs to Role
    {    
         A.xyz();  // calling data object
         RoleB_MethodY();  // calling other Role's method
    } 

    // RoleB Methods
    RoleA_MethodY()     //   using _ to simulate RoleMethod that belongs to Role
    {    
         B.abc();  // calling data object
    } 
}

Yes, it is a fake version of DCI but with this I don't have to build a framework or maintain a Context Stack....
and I can focus on using DCI to implement the real problem :)

/quang

Rune Funch Søltoft

unread,
Feb 25, 2015, 2:11:22 AM2/25/15
to object-co...@googlegroups.com


> Den 25/02/2015 kl. 05.02 skrev Matthew Browne <mbro...@gmail.com>:
>
> But with my current understanding it seems to me that there are plenty of artifacts available to the compiler to differentiate the role method from the instance method even if they have the same name

It's not for the convenience of the compiler but for the understandability of the code reader

Rune Funch Søltoft

unread,
Feb 25, 2015, 2:14:52 AM2/25/15
to object-co...@googlegroups.com
Now if we want to check whether or not this Role Object is in the List of the Composite we may have issue since the Role is a wrapper and the List contains the Raw Component. We need to override the Equals function of Object and all kind of problems will come :)
In Net there's no way to get this perfect since Object.ReferenceEqual is a static method and can't be overridden

Egon Elbre

unread,
Feb 25, 2015, 2:55:26 AM2/25/15
to object-co...@googlegroups.com
On Tuesday, 24 February 2015 23:51:44 UTC+2, Cope wrote:

On 24 Feb 2015, at 21:26, Egon Elbre <egon...@gmail.com> wrote:

There are two methods that have the same name and one has precedence in a specific Context. 

In a given Context, role names are unique.

For a given object, method names — including role names — are unique. An instance method name should never collide with a role method name. That destroys comprehensibility of the Context.

Destroying is an exaggeration, but I agree that it harms comprehensibility.
 

Two given roles may each have a method of the same name, though that's a bit gauche and limits comprehensibility, particularly in the case where one object plays two roles.

I do not understand what you mean by two methods having the same name in a Context situation where there is an issue of precedence between them.

For example every object in JavaScript has a method "toString", this would mean that you never can have a role method named "toString". Also this constraint assumes that you know all the information about the Contexts at instantiation time. For example if the object adds/removes methods - of course that code wouldn't be that easy to understand. 

Also given that mostly any object can play any role this severely would restrict the method names - of course in pratice it wouldn't be that restrictive.

Egon Elbre

unread,
Feb 25, 2015, 3:01:04 AM2/25/15
to object-co...@googlegroups.com


On Wednesday, 25 February 2015 07:16:11 UTC+2, Hai Quang Kim wrote:
"Although, personally, I don't think it's vital."

Vital as in you cannot live without.
 

Let's say we have a function in Data Object (Composite) that will add a Component into the List in the Composite.
Let's say in a Context we have a Role that is played by the Component. 
Now if we want to check whether or not this Role Object is in the List of the Composite we may have issue since the Role is a wrapper and the List contains the Raw Component. We need to override the Equals function of Object and all kind of problems will come :)


I have this problem while trying to use wrapper.

Exactly, that's why I say it's useful and really good to have.

In many cases static typing helps to avoid problems with the wrapper. Basically, I don't encounter that often those situation where it would cause problems. But I know those exist.

Also for clarification for Davide. From DCI standpoint the wrapper issue is important, it's something that is an essential part of DCI.

James O Coplien

unread,
Feb 25, 2015, 3:59:05 AM2/25/15
to object-co...@googlegroups.com

On 25 Feb 2015, at 05:02, Matthew Browne <mbro...@gmail.com> wrote:

I'm not sure that should be a hard and fast rule in a dynamic language like Javascript, where there is no need for a context stack.

This is not a matter of a technical issue. It is a matter of comprehensibility.

I am sure that, with suitable technology, you could have five roles in the context, each one of which had methods named M1, M2, M3, M4, and M5. Of course the technology can qualify them with the role names so that, within the Context, their bindings are unique. The problem is that this uniqueness does not extend to the end-user mental model, as their is no bridge from the source code to the programmer mental model of the object and its methods at run time.

Forcing qualified method invocation names increases cognitive load, increases code mass, and adds unnecessary redundancy — all of which are known to detract from comprehensibility.

But before we overly clarify this issue, I want to understand what Egon meant. I still don't.

James O Coplien

unread,
Feb 25, 2015, 4:06:28 AM2/25/15
to object-co...@googlegroups.com

On 25 Feb 2015, at 08:55, Egon Elbre <egon...@gmail.com> wrote:

For example every object in JavaScript has a method "toString", this would mean that you never can have a role method named "toString".

That's right. The object would have two methods, both called toString. If you believe in overriding then the instance method of the object wins and the Context no longer describes what really goes on in the code. If you don't believe in overriding you end violating the encapsulation of the class — its methods that invoke its own toString method can't count on it receiving the message. The latter is still a bit more in the same vein as old OOP and if one were to allow such overriding, then the latter approach should prevail. To my mind it's much better to flag this as an error. One can do that methodologically or with technology, and this is one place where the technology can help.

Name methods with the same care as for a first-born child. I don't see why anyone would consciously name entities in a way that could lead to this confusion, and I fear that this is a discussion about how to do the least damage for sloppy designs. Sloppy designs deserve a slap on the wrist above accommodation. Unless you're George Forman, you don't name all of your sons George.

Egon Elbre

unread,
Feb 25, 2015, 4:14:20 AM2/25/15
to object-co...@googlegroups.com
Simplest example I can give is this:

var items = {
list: [],
add: function(item){
this.list.push(item);
}
};

var context = Context(function(items, log){
Items = items;
Log = log;

Items.add({name: "Hello"});
Items.add({name: "World"});

log.info(items);
}, {
/*role*/ Items: {
add: function(item){
Log.info("Item named " + item.name + " added.");
this.add(item);
}
},
/*role*/ Log: {
info: function(message){
this.log(message);
}
}
});
context(items, console);

For example, in this code two methods being shadowed. Of course that depends on which browser you are running - in some cases there might be only one method being shadowed. Basically the "console" object might or might not have "info" method. But in this context that is an irrelevant detail because it's never being invoked. This would also mean that whenever someone would add method in the object that is being "overridden" in a context it would cause code to fail.

+ Egon

Egon Elbre

unread,
Feb 25, 2015, 4:16:06 AM2/25/15
to object-co...@googlegroups.com


On Wednesday, 25 February 2015 11:14:20 UTC+2, Egon Elbre wrote:


On Wednesday, 25 February 2015 10:59:05 UTC+2, Cope wrote:

On 25 Feb 2015, at 05:02, Matthew Browne <mbro...@gmail.com> wrote:

I'm not sure that should be a hard and fast rule in a dynamic language like Javascript, where there is no need for a context stack.

This is not a matter of a technical issue. It is a matter of comprehensibility.

I am sure that, with suitable technology, you could have five roles in the context, each one of which had methods named M1, M2, M3, M4, and M5. Of course the technology can qualify them with the role names so that, within the Context, their bindings are unique. The problem is that this uniqueness does not extend to the end-user mental model, as their is no bridge from the source code to the programmer mental model of the object and its methods at run time.

Forcing qualified method invocation names increases cognitive load, increases code mass, and adds unnecessary redundancy — all of which are known to detract from comprehensibility.

But before we overly clarify this issue, I want to understand what Egon meant. I still don't.

Simplest example I can give is this:

var items = {
list: [],
add: function(item){
this.list.push(item);
}
};

var context = Context(function(items, log){
Items = items;
Log = log;

Items.add({name: "Hello"});
Items.add({name: "World"});

log.info(items);

Obviously, this also shows what kinds of problems method shadowing can cause.

This should be: Log.info(items);

Davide Callegari

unread,
Feb 25, 2015, 9:05:41 AM2/25/15
to object-co...@googlegroups.com
Thank you guys for your feedback, especially Egon.
So, here's what I got back from this discussion:
 - absolutely do not use wrappers, objects identity must be preserved
 - do not let roles override methods of the object or of other roles applied to the object

I wonder if it's ok, though, in JS, to have a role with a toString method, since all objects have a toString method in their prototype chain.

-DC

James O Coplien

unread,
Feb 25, 2015, 3:03:07 PM2/25/15
to object-co...@googlegroups.com

On 25 Feb 2015, at 15:05, Davide Callegari <birraf...@gmail.com> wrote:

I wonder if it's ok, though, in JS, to have a role with a toString method, since all objects have a toString method in their prototype chain.

If all objects have a toString method, give me an example of what a toString role member would do (what is its role / object contract? what does it do?)

Matthew Browne

unread,
Feb 25, 2015, 9:49:25 PM2/25/15
to object-co...@googlegroups.com
On 2/25/15 4:06 AM, James O Coplien wrote:
On 25 Feb 2015, at 08:55, Egon Elbre <egon...@gmail.com> wrote:

For example every object in JavaScript has a method "toString", this would mean that you never can have a role method named "toString".

That's right. The object would have two methods, both called toString. If you believe in overriding then the instance method of the object wins and the Context no longer describes what really goes on in the code. If you don't believe in overriding you end violating the encapsulation of the class — its methods that invoke its own toString method can't count on it receiving the message.
I don't see how that's the case with injectionless DCI, since the method isn't actually being replaced. If an instance method calls toString(), the instance method toString() would be called. If a role method calls toString(), then the role method toString() would be called. I don't see how that sort of overriding would cause a problem.

Perhaps the best argument for allowing overriding is what Egon said here:

Also this constraint assumes that you know all the information about the Contexts at instantiation time. For example if the object adds/removes methods - of course that code wouldn't be that easy to understand. 

Also given that mostly any object can play any role this severely would restrict the method names - of course in pratice it wouldn't be that restrictive.
I think it's worth adding a bit of clarification to Egon's point about the object adding/removing methods...this is particularly relevant in Javascript where it's a common practice to add additional methods to an object or prototype at runtime - might not matter so much in other languages.

With respect to his second point, in an evolving design, you'll add new contexts with new roles over time - I suppose if role method overriding isn't allowed, you'd need to come up with new names for similar operations every time you have the same object playing roles in these different contexts. More on that below.


On 2/25/15 4:06 AM, James O Coplien wrote:
The latter is still a bit more in the same vein as old OOP and if one were to allow such overriding, then the latter approach should prevail. To my mind it's much better to flag this as an error. One can do that methodologically or with technology, and this is one place where the technology can help.

Name methods with the same care as for a first-born child. I don't see why anyone would consciously name entities in a way that could lead to this confusion, and I fear that this is a discussion about how to do the least damage for sloppy designs. Sloppy designs deserve a slap on the wrist above accommodation. Unless you're George Forman, you don't name all of your sons George.
It certainly makes sense that naming conflicts would come up infrequently in a well-thought-out design, but I think it would be going too far to say that wanting to override an instance method with a role method is always a sign of a bad design. Consider method names like print() or draw() that come up a lot, or examples like the following where there's some common behavior that needs to be overridden for specific roles:

class Vehicle {
    honk() {
        return 'HONK HONK';
    }
}

...
//played by a Vehicle object
role Bicycle {
    honk() {
        return 'Beep beep!';
    }
}


That's probably not the best example since honking is probably use case behavior rather than something that belongs in a data class, but this shows the type of overriding situation I'm thinking of.

Matthew Browne

unread,
Feb 25, 2015, 9:58:15 PM2/25/15
to object-co...@googlegroups.com
On 2/25/15 12:24 AM, Hai Quang Kim wrote:
> Yes, it is a fake version of DCI but with this I don't have to build a
> framework or maintain a Context Stack....
> and I can focus on using DCI to implement the real problem :)
I see no reason to go this route with Javascript. Method overriding
(which is easy to do in JS) would be far preferable to the code you
posted (I understand why you did it in C# but that was a special
circumstance). Of course an injectionless implementation would be best
of all.

Hai Quang Kim

unread,
Feb 25, 2015, 10:17:54 PM2/25/15
to object-co...@googlegroups.com
how about context stack for single thread and multi thread.
do we still need to do it for javascript?

/quang

Hai Quang Kim

unread,
Feb 25, 2015, 10:25:24 PM2/25/15
to object-co...@googlegroups.com
of course I am not suggesting to go this way.
I just suggest another options in the table.

when I started with DCI, I was blocked by this for a long time before I can start to try it out with real world example.

a new member want to try DCI, 1st thing need to do is to make a custom compiler for DCI.
to me, that was scary :)

/quang

Matthew Browne

unread,
Feb 25, 2015, 10:42:11 PM2/25/15
to object-co...@googlegroups.com
On 2/25/15 10:25 PM, Hai Quang Kim wrote:
a new member want to try DCI, 1st thing need to do is to make a custom compiler for DCI.
to me, that was scary :)
I understand that you just wanted to share and be helpful, but for the sake of clarification...Fortunately it's possible to go ahead and use DCI in most common languages without needing to write a custom compiler. There are existing injectionless or other suitable implementations for many languages (including Egon's proof of concept for Javascript) and for many languages, method injection is also an option. I know the group tends to be critical of method injection, but I think the group also agrees that you can still do real-world projects with it. In your case method injection wasn't an option (due to limitations of C#) and you ran into technical issues with both Marvin and Interact; hopefully over time those particular compatibility issues will be less of a concern for you and others.

Also, it's possible to do a "quick-and-dirty" injectionless implementation that doesn't require a true parser/compiler; I'm thinking primarily of Egon's implementation.

/quang

On Thursday, February 26, 2015 at 11:17:54 AM UTC+8, Hai Quang Kim wrote:
how about context stack for single thread and multi thread.
do we still need to do it for javascript?

/quang

On Thursday, February 26, 2015 at 10:58:15 AM UTC+8, Matthew Browne wrote:
On 2/25/15 12:24 AM, Hai Quang Kim wrote:
> Yes, it is a fake version of DCI but with this I don't have to build a
> framework or maintain a Context Stack....
> and I can focus on using DCI to implement the real problem :)
I see no reason to go this route with Javascript. Method overriding
(which is easy to do in JS) would be far preferable to the code you
posted (I understand why you did it in C# but that was a special
circumstance). Of course an injectionless implementation would be best
of all.
--
You received this message because you are subscribed to a topic in the Google Groups "object-composition" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/object-composition/1okz656kbY8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to object-composit...@googlegroups.com.
To post to this group, send email to object-co...@googlegroups.com.
Visit this group at http://groups.google.com/group/object-composition.
For more options, visit https://groups.google.com/d/optout.

Matthew Browne

unread,
Feb 25, 2015, 10:43:53 PM2/25/15
to object-co...@googlegroups.com
I don't think so, but that's part of a larger question of whether injectionless implementations in general should still have a context stack. Most of the existing injectionless implementations do not, but Cope has previously pointed out why it might still be beneficial to have one (I could probably find that thread if you're interested).
--

Matthew Browne

unread,
Feb 26, 2015, 12:08:06 AM2/26/15
to object-co...@googlegroups.com
Hi Davide,
In case you're interested in seeing another injectionless DCI implementation, I created one for TypeScript (Microsoft's new language which compiles to Javascript - essentially Javascript with types). I posted about it here:

https://groups.google.com/d/msg/object-composition/QRgJp3N_VqY/J24EU6_7FygJ

Here's an example of what the generated source looks like (see above link for DCI source code):

/**
* Transfer Money use case
*/
function TransferMoney(sourceAcct, destinationAcct, amount) {
    var __context = this;
    this.__$SourceAccount = {
        transferOut: function () {
            __context.__$SourceAccount.withdraw.call(__context.SourceAccount);
            __context.__$DestinationAccount.deposit.call(__context.DestinationAccount);
        },
        withdraw: function () {
            if (__context.SourceAccount.getBalance() < __context.Amount) {
                throw new Error('Insufficient funds');
            }
            __context.SourceAccount.decreaseBalance(__context.Amount);
        }
    };
    this.__$DestinationAccount = {
        deposit: function () {
            __context.DestinationAccount.increaseBalance(__context.Amount);
        }
    };
    this.__$Amount = {};
   
    //bind the objects to their roles
    __context.SourceAccount = sourceAcct;
    __context.DestinationAccount = destinationAcct;
    __context.Amount = amount;
}


Obviously there are some differences from Egon's implementation but the basic idea is the same (in fact I took inspiration from his implementation).

I edited the source code of the TypeScript compiler in order to accomplish this, so I would recommend looking at some of the more straightforward injectionless implementations rather than mine to start, but I think if you can do something similar with the CoffeeScript compiler that would be great. BTW, Andreas, another member of this group, posted previously about his interest in writing a CoffeeScript implementation:

https://groups.google.com/d/msg/object-composition/-bJT08UOOJA/sobjvtIMIcYJ

He mentioned a newly rewritten version of the CoffeeScript compiler that would be better suited for this than the current one:
https://github.com/michaelficarra/CoffeeScriptRedux

Source transformation similar to the above may be all you need. But in case you're interested, here's some info on how I fine-tuned it a bit...

In the above example, all the role method invocations are transformed at compile time, but my library also does a few things at runtime in special cases, for example when the this keyword is used:

this.withdraw();

becomes:

__dci_internal.callMethodOnSelf(__context, this, 'SourceAccount', 'withdraw');

This could be avoided by always using self instead of this (which is preferable anyway from a DCI standpoint, and even just in terms of variable scope in JS), but I wanted to give the programmer the option of using this and have it work correctly. In order to do this it's necessary to check what this refers to at runtime - that's what callMethodOnSelf() does.

The other runtime behavior is for situations like this:

var methodName = 'withdraw';
SourceAccount[methodName]();


That would become:

var methodName = 'withdraw';
__dci_internal.getRoleMember(__context, __context.SourceAccount, "SourceAccount", methodName)


I can post the code for the __dci_internal functions if you're interested.
--

Egon Elbre

unread,
Feb 26, 2015, 2:40:12 AM2/26/15
to object-co...@googlegroups.com


On Thursday, 26 February 2015 04:49:25 UTC+2, Matthew Browne wrote:
On 2/25/15 4:06 AM, James O Coplien wrote:
On 25 Feb 2015, at 08:55, Egon Elbre <egon...@gmail.com> wrote:

For example every object in JavaScript has a method "toString", this would mean that you never can have a role method named "toString".

That's right. The object would have two methods, both called toString. If you believe in overriding then the instance method of the object wins and the Context no longer describes what really goes on in the code. If you don't believe in overriding you end violating the encapsulation of the class — its methods that invoke its own toString method can't count on it receiving the message.
I don't see how that's the case with injectionless DCI, since the method isn't actually being replaced. If an instance method calls toString(), the instance method toString() would be called. If a role method calls toString(), then the role method toString() would be called. I don't see how that sort of overriding would cause a problem.

Perhaps the best argument for allowing overriding is what Egon said here:
Also this constraint assumes that you know all the information about the Contexts at instantiation time. For example if the object adds/removes methods - of course that code wouldn't be that easy to understand. 

Also given that mostly any object can play any role this severely would restrict the method names - of course in pratice it wouldn't be that restrictive.
I think it's worth adding a bit of clarification to Egon's point about the object adding/removing methods...this is particularly relevant in Javascript where it's a common practice to add additional methods to an object or prototype at runtime - might not matter so much in other languages.

Actually I was thinking about it a bit more and found that there might be a more serious problem.

Let's say I have an external dependency X. I have a role method M. Now in their next version of X, they introduce method M to object X. The naming constraint would mean that now my code is broken.

tl;dr; an introduction of a method can break existing code at a distance.

Rune Funch Søltoft

unread,
Feb 26, 2015, 3:20:09 AM2/26/15
to object-co...@googlegroups.com

> Den 26/02/2015 kl. 08.40 skrev Egon Elbre <egon...@gmail.com>:
>
> tl;dr; an introduction of a method can break existing code at a distance
Or in other words even if you require no more and promise no less it would still be are breaking change

James O Coplien

unread,
Feb 26, 2015, 3:36:15 AM2/26/15
to object-co...@googlegroups.com
There are several issues that perhaps are being confused here. I am sure that we could make a George Foreman program run properly, and that each role could have a method called George, and even all classes could have such a method. It runs according to spec. Reasoning about the program is another matter. It has nothing to do with injection or, I would claim, even with tools.

Is it a good thing because it's in Javascript? I don't find that to be of particular interest in the argument. If the implementation violates the mental model of the paradigm, fix the implementation.

The method draw is a reasonable example but I can't think of any example where good design wouldn't properly choose proper method names across roles and classes. Yes, it means thinking. It means thinking up suitable method names, and that touches on a part of design that I think few people appreciate. Curiously, Kent Beck did appreciate it many years ago when he described how to choose names with CRC cards. (And his sidekick Ward Cunningham is kind of the patron saint of names of things in OO — actually, if you dig a bit, you find that most of these ideas are Ward's.) You have an operation on a car to "fill the tank with gas." That can be an operation on the car. But it's the driver who does it, right (or, in civlised countries, the station attendant)? No: that method is "operate the pump." This re-naming adds information to the design. Giving multiple entities the same name actually removes information from the design. DCI, in spirit, is about readable code and about adding information to the design.

I'll let you do the math of how many unique names one can construct out of a string of six to ten characters. This is not an overconstrained problem.

We don't write software for cars like this, but if HONK HONK qualifies, so does this.


--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.

James O Coplien

unread,
Feb 26, 2015, 3:39:59 AM2/26/15
to object-co...@googlegroups.com

On 26 Feb 2015, at 08:40, Egon Elbre <egon...@gmail.com> wrote:

Actually I was thinking about it a bit more and found that there might be a more serious problem.

Let's say I have an external dependency X. I have a role method M. Now in their next version of X, they introduce method M to object X. The naming constraint would mean that now my code is broken.

Yup. Trygve and I shuddered, from the very beginning, at the notion of overridable Role methods. It destroys readability. I stick to my word: destroys. It's the fly in the ointment; or, better, the piss in the vinegar. It is a small thing, but it has disastrous consequences — consequences that are very difficult to track down.

Rune Funch Søltoft

unread,
Feb 26, 2015, 4:57:18 AM2/26/15
to object-co...@googlegroups.com

Den 26/02/2015 kl. 09.36 skrev James O Coplien <jcop...@gmail.com>:

You have an operation on a car to "fill the tank with gas." That can be an operation on the car. But it's the driver who does it, right (or, in civlised countries, the station attendant)? No: that method is "operate the pump." This re-naming adds information to the design. Giving multiple entities the same name actually removes information from the design. DCI, in spirit, is about readable code and about adding information to the design
In most of the projects I work in we rely on quite a long list of libraries we do not control in the current project more than 100. We will have to assume that since they are all actively maintained that new methods will be added. I don't think it changes our ability to understand our code if a method is added to a third party library and I think a compiler error either on the binding of a role or the name of a role method wouldn't help in contrast I think it would confuse

Egon Elbre

unread,
Feb 26, 2015, 5:01:21 AM2/26/15
to object-co...@googlegroups.com


On Thursday, 26 February 2015 10:39:59 UTC+2, Cope wrote:

On 26 Feb 2015, at 08:40, Egon Elbre <egon...@gmail.com> wrote:

Actually I was thinking about it a bit more and found that there might be a more serious problem.

Let's say I have an external dependency X. I have a role method M. Now in their next version of X, they introduce method M to object X. The naming constraint would mean that now my code is broken.

Yup. Trygve and I shuddered, from the very beginning, at the notion of overridable Role methods.

I'm not quite sure whether we are talking about the same thing when me say "overriding". I'm not suggesting that Role methods themselves should be overridable.

It might be clearer to call it henceforth "method shadowing", or alternatively if there is a more accurate description for:

Object X with methods M, K. Where K internally calls X.M.
Context Z with role R and method M.

Inside the Context R.M() will execute the role method.
Inside the Context R.K() will execute the object method K which internally calls the object method M.

Essentially the role method R.M is shadowing method O.M... because the object method is not directly accessible via the Role itself (unless some other way is provided).

Why I think method shadowing is a better name because it is very similar to variable shadowing (http://en.wikipedia.org/wiki/Variable_shadowing).

Egon Elbre

unread,
Feb 26, 2015, 5:06:02 AM2/26/15
to object-co...@googlegroups.com


On Thursday, 26 February 2015 12:01:21 UTC+2, Egon Elbre wrote:


On Thursday, 26 February 2015 10:39:59 UTC+2, Cope wrote:

On 26 Feb 2015, at 08:40, Egon Elbre <egon...@gmail.com> wrote:

Actually I was thinking about it a bit more and found that there might be a more serious problem.

Let's say I have an external dependency X. I have a role method M. Now in their next version of X, they introduce method M to object X. The naming constraint would mean that now my code is broken.

Yup. Trygve and I shuddered, from the very beginning, at the notion of overridable Role methods.

I'm not quite sure whether we are talking about the same thing when me say "overriding". I'm not suggesting that Role methods themselves should be overridable.

It might be clearer to call it henceforth "method shadowing", or alternatively if there is a more accurate description for:

Object X with methods M, K. Where K internally calls X.M.
Context Z with role R and method M.

Inside the Context R.M() will execute the role method.
Inside the Context R.K() will execute the object method K which internally calls the object method M.

Essentially the role method R.M is shadowing method O.M... because the object method is not directly accessible via the Role itself (unless some other way is provided).

Why I think method shadowing is a better name because it is very similar to variable shadowing (http://en.wikipedia.org/wiki/Variable_shadowing).


Also leave the overriding keeping as http://en.wikipedia.org/wiki/Method_overriding

It might be my fault for starting with "overriding" in the first place.

+ Egon

James O Coplien

unread,
Feb 26, 2015, 5:12:27 AM2/26/15
to object-co...@googlegroups.com
If you truly have overriding of Role methods by instance methods, then even an undocumented instance method (or, especially, an undocumented instance method) will destroy your code if its name collides with the Role for which it is a Role-player.

This is the strongest argument I know to disallow overriding of role methods.

An even stronger rule is to disallow the name collisions. I think there are places where that rule works in DCI, and, in particular, disallowing name collisions between Role methods. The reason is organisational: the enterprise delivering value delivers it as use cases and, as such, needs to have oversight of the direct value-generating code. That's embodied in the use cases and, as such, in the Role methods.

In the case of third-party software there is no single entity of detailed architectural oversight, so administrative techniques (or even techniques that can be enforced by the programming language) don't work.

So, to me, to disallow overriding of Role methods is mandatory and solves this latter problem. It is admittedly a weak solution since it doesn't solve the comprehensibility problem, particularly if the instance methods are visible. But the stronger solution, which *can* be applied from Role to Role, is to ensure that Role method names are unique. That is likely to fall under a single administrative body and correspondingly can be automatically administered under the rules of the programming language or of architectural enforcement.

James O Coplien

unread,
Feb 26, 2015, 5:13:00 AM2/26/15
to object-co...@googlegroups.com

On 26 Feb 2015, at 11:01, Egon Elbre <egon...@gmail.com> wrote:

I'm not quite sure whether we are talking about the same thing when me say "overriding".

I am using it in the sense of object-oriented programming.

James O Coplien

unread,
Feb 26, 2015, 5:17:58 AM2/26/15
to object-co...@googlegroups.com
I fear that this is a caricature. What is Object X is of class Q which has ø as a base class, and both Q and ø have method m. Now apply your scenario. Who shadows whom, overriding what, shadowing what?

I can't understand code like this, given your semantics. The rule set is too complex and doesn't correspond to my mental model. The psychological problem is called cognitive dissonance and it closely relates to the issue of locus of attention that we discussed here earlier. I want to get rid of code that I can't understand.

Raskin points out that only people with the mental illness called schizophrenia are able to really get into this kind of configuration. There's very deep stuff going on here.



On 26 Feb 2015, at 11:01, Egon Elbre <egon...@gmail.com> wrote:



On Thursday, 26 February 2015 10:39:59 UTC+2, Cope wrote:

On 26 Feb 2015, at 08:40, Egon Elbre <egon...@gmail.com> wrote:

Actually I was thinking about it a bit more and found that there might be a more serious problem.

Let's say I have an external dependency X. I have a role method M. Now in their next version of X, they introduce method M to object X. The naming constraint would mean that now my code is broken.

Yup. Trygve and I shuddered, from the very beginning, at the notion of overridable Role methods.

I'm not quite sure whether we are talking about the same thing when me say "overriding". I'm not suggesting that Role methods themselves should be overridable.

It might be clearer to call it henceforth "method shadowing", or alternatively if there is a more accurate description for:

Object X with methods M, K. Where K internally calls X.M.
Context Z with role R and method M.

Inside the Context R.M() will execute the role method.
Inside the Context R.K() will execute the object method K which internally calls the object method M.

In the end all methods (except class methods, like new) are object methods — including role methods.


Essentially the role method R.M is shadowing method O.M... because the object method is not directly accessible via the Role itself (unless some other way is provided).

Why I think method shadowing is a better name because it is very similar to variable shadowing (http://en.wikipedia.org/wiki/Variable_shadowing).

It destroys readability. I stick to my word: destroys. It's the fly in the ointment; or, better, the piss in the vinegar. It is a small thing, but it has disastrous consequences — consequences that are very difficult to track down.


Egon Elbre

unread,
Feb 26, 2015, 5:21:29 AM2/26/15
to object-co...@googlegroups.com
Then, I agree that overriding has severe consequences.

Although what is your opinion on method shadowing?

I don't see any obvious problem in allowing method shadowing. Of course there is the case that happened with Log.info vs log.info - but in the similar way it's as bad as simply mistyping the function name.

+ Egon

James O Coplien

unread,
Feb 26, 2015, 5:23:32 AM2/26/15
to object-co...@googlegroups.com

On 26 Feb 2015, at 11:21, Egon Elbre <egon...@gmail.com> wrote:

Although what is your opinion on method shadowing?

See my other mail. It contributes to cognitive load. Consider my example with two classes and a Role, all of which have a method named X. Now, consider looking at each of the three artefacts, where you are trying to understand the code.

Now multiply it to five classes deep in the inheritance hierarchy (not much you can do about this) and to five roles that the object simultaneously plays (a real possibility, and extremely problematic).

Egon Elbre

unread,
Feb 26, 2015, 5:34:01 AM2/26/15
to object-co...@googlegroups.com
On Thursday, 26 February 2015 12:17:58 UTC+2, Cope wrote:
I fear that this is a caricature. What is Object X is of class Q which has ø as a base class, and both Q and ø have method m. Now apply your scenario. Who shadows whom, overriding what, shadowing what?

It would depend on the language,

for example in Delphi, both shadowing/overriding are possible, e.g.:

TBase = class
  procedure Print; virtual;  // X
end;

TSubAlpha = class(TBase)
  procedure Print; override; // Y
end;

TSubBeta = class(TBase)
  procedure Print; reintroduce; // Z
end;

TSubAlpha is overriding the method
TSubBeta is shadowing the method.

A := TSubAlpha.Create;
A.Print; // calls Y
TBase(A).Print; // calls Y

B := TSubAlpha.Create;
B.Print; // calls Z
TBase(B).Print; // calls X

I expect that similar behaviors are available in Java/C++ etc. but I can't write those from the top of my head.

Of course, I'm (mostly) against overriding/inheritance in the first place, so I would say that get rid of overriding.

Egon Elbre

unread,
Feb 26, 2015, 5:35:11 AM2/26/15
to object-co...@googlegroups.com
I would then say get rid of inheritance and overriding; It looks to me that they contribute more to the cognitive load than method shadowing.

Rune Funch Søltoft

unread,
Feb 26, 2015, 7:07:43 AM2/26/15
to object-co...@googlegroups.com


> Den 26/02/2015 kl. 11.12 skrev James O Coplien <jcop...@gmail.com>:
>
> This is the strongest argument I know to disallow overriding of role methods

I think there are plenty of cases where I'm arguing against overriding or shadowing role methods. I'm advocating that a role method can shadow an instance method. If for nothing else to make sure that the fact that a third party adds a method the is not used is not a breaking change. I don't think it impacts comprehensibility either. The role method and the use of said method is in the same file. Not allowing role methods to shadow instance methods would break the design by contract rule I quoted earlier. Making it very difficult to reason about whether or not a change is a breaking one or not and to me understanding the impact of a change is an important aspect of comprehensibility

Matthew Browne

unread,
Feb 26, 2015, 7:50:41 AM2/26/15
to object-co...@googlegroups.com
Yes. Let's limit the discussion to a role method overriding (or shadowing) an instance method - not the other way around. I think the former is what Egon, Rune and I have been talking about the whole time; Cope, you seem to be talking about the latter. I think we all agree that allowing an instance method to override a role method is a bad idea.

Suppose you have a collection object from a 3rd party library that plays a role in several contexts, and that in one of those contexts you have a role method sort() that implements a custom sorting algorithm for the collection items. Now the maintainer of the collection library adds a new method sort() that didn't exit in the first version of the library. I think it's fairly obvious that that should not cause your existing DCI code to break.

Matthew Browne

unread,
Feb 26, 2015, 7:55:57 AM2/26/15
to object-co...@googlegroups.com
On 2/26/15 7:50 AM, Matthew Browne wrote:
I think the former is what Egon, Rune and I have been talking about the whole time
I forgot that we were also just mentioning a point about new instance methods being added to an object at runtime, which is ordinarily possible in Javascript. But let's set that aside for now - it's clearly problematic and should probably result in a runtime error in the case of an instance method attempting to override a role method.

Egon Elbre

unread,
Feb 26, 2015, 8:40:38 AM2/26/15
to object-co...@googlegroups.com
In injectionless implementation it's quite easy to ensure that it doesn't override role methods and that the Role method always shadows.


The method adding (also removal) works without problems.
Although, it's not clear code, due to the dynamic object behavior.

+ Egon

Matthew Browne

unread,
Feb 26, 2015, 11:27:02 AM2/26/15
to object-co...@googlegroups.com
If the code becomes incomprehensible then it doesn't matter that it's technically possible (as Cope pointed out).

I think there are cases where role methods can shadow instance methods without reducing comprehensibility (in fact it might even improve it if it would avoid having to come up with a long and unnatural-sounding method name...granted most of the time that wouldn't be an issue). But the opposite (adding new instance methods at runtime with the same names as existing role methods) would probably just cause confusion.

>+ Egon

--
Sent from my Android device with K-9 Mail.

Egon Elbre

unread,
Feb 26, 2015, 2:23:32 PM2/26/15
to object-co...@googlegroups.com
I'm not saying that it's something that is recommended. I really can't think of any practical example that would require method adding/removing outside of instantiation time. At best I can guess there might be some closure caching benefits, but I'm not convinced. But since the JavaScript implementation allows method adding/removal then the JavaScript implementation of DCI should be capable of dealing with it; mainly for compatibility with 3rd party libraries. If it were a new language I would not allow it.

Hai Quang Kim

unread,
Feb 26, 2015, 8:38:48 PM2/26/15
to object-co...@googlegroups.com
I find that naming convention may help.
+ Context's system operation: As short as possible since it may be used by many.
+ Data Object: As short as possible since it may be used by many
+ Role Method: As Long as Needed (inspired by Use case's words)

With or without DCI method overriding is always a problem :)

/quang

Matthew Browne

unread,
Feb 26, 2015, 10:39:00 PM2/26/15
to object-co...@googlegroups.com
These look like good rules except maybe the first one. At least for business (user goal level) use cases, I don't find that the Context's public methods need to be called repeatedly very often - you call a method for the user's first interaction with the system, then another method for the second interaction, etc. until you're done. In many cases there might only be one user interaction needed to complete the use case (e.g. the user submits a form and the system does something in response), in which case the Context would only need to have one public method. So better to name it something as descriptive as needed, derived from the use case step.

Although, if you weren't thinking of business use cases, but rather an internal use case from the programmer's mental model (when you said "Context's system operation"), you might have a point.
--
You received this message because you are subscribed to a topic in the Google Groups "object-composition" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/object-composition/1okz656kbY8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to object-composit...@googlegroups.com.

Hai Quang Kim

unread,
Feb 26, 2015, 11:08:34 PM2/26/15
to object-co...@googlegroups.com
yep you are right, Context can be habit and can be reused by many (but not too many).
Let's make it medium size :)

In my case, I use them everywhere so it is more important for me to keep in short.
This rule is from old good OOP, public method should be short, private method can be long :)

/quang
To unsubscribe from this group and all its topics, send an email to object-composition+unsub...@googlegroups.com.

Rune Funch Søltoft

unread,
Feb 27, 2015, 1:21:11 AM2/27/15
to object-co...@googlegroups.com
I find the rule that works best for me is to have meaningful and correct names. I don't care about the length. In my various tools I only have to write a few letters (typically 2-3) before the tool know what I'm looking for so size really doesn't matter
too much. I also find it entirely unrelated to DCI :)

You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.

Hai Quang Kim

unread,
Feb 27, 2015, 1:25:09 AM2/27/15
to object-co...@googlegroups.com
Role, and Role Method is kind of private part of a Context class, so we can have a bit longer name, that is just a guide line.
And yep modern IDE with intellisense can handle long name :)

/quang
To unsubscribe from this group and stop receiving emails from it, send an email to object-composition+unsub...@googlegroups.com.

James O Coplien

unread,
Feb 27, 2015, 3:41:04 AM2/27/15
to object-co...@googlegroups.com

On 26 Feb 2015, at 13:50, Matthew Browne <mbro...@gmail.com> wrote:

Yes. Let's limit the discussion to a role method overriding (or shadowing) an instance method - not the other way around. I think the former is what Egon, Rune and I have been talking about the whole time; Cope, you seem to be talking about the latter. I think we all agree that allowing an instance method to override a role method is a bad idea.

I think it's easy to argue that the latter is a problem. In fact the former is its dual and the same arguments apply. People have a bit more trouble seeing that argument because of the way they think about inheritance.

Consider a class C, two class methods called Cmethod and Cmethod2, and an instance of C that we'll address through a role name R. R has a Role method called Rmethod and it also has a Role method called Cmethod.

With your proposed shadowing: if an outsider invokes CMethod on R, it gets R's C method.

If Cmethod2 invokes Cmethod on self, what is invoked?

Can R express Cmethod both in its public interface and in its role / object contract interface? If so, then can R's Cmethod2 invoke C's Cmethod through that interface?

How would R's Cmethod differentiate between calling C's Cmethod and R's Cmethod?

How would any code within the context gain access to C's Cmethod of the object playing the role R, were it necessary to do so?

These are not idle questions. A good part of the design of C++ dealt with sorting out analogous complexities along the axis of the inheritance hierarchy, which roughly corresponds to the subtyping hierarchy. Therein lies a good bit of the complexity of the language. In C++ it's worse because of overloading, and indeed, the question becomes more interesting here if you allow compile-time polymorphism and its cousins.

C is a Context class and Cmethod is its only trigger method. Is it totally inaccessible as a role-player of R? (I have a lot of other interesting cases in my pocket, at least one of which involves a Context object, multiple of whose roles are played by itself. (Already in DCI each Context object plays one of its own roles — the role called self.) To that, add recursive methods, and you get lost really quickly.)

I can see some latent programming rules in my head that are "getting in the way." One of them is that an object should behave the same (in response to a request to perform a method) no matter the identifier through which we invoke the methods of that same instance. That is, if I associate the identifier S with an instance of C, and invoke one of its instance methods through S, I should instead be able to bind that same object to the identifier R, invoke an operation using the same method selector and arguments, and get the same result. Shadowing violates that: it means that the name through which I access an object changes the behaviour of a given method selector on that same object!

This radically violates the Rule of Least Surprise.

James O Coplien

unread,
Feb 27, 2015, 4:00:12 AM2/27/15
to object-co...@googlegroups.com
This is a position statement, taking the position that "shadowing" violates object identity.

We need a good definition of object identity. We start with a vocabulary of the things in our universe: names, objects, method selectors, arguments, and methods.

In the essence of object orientation there is no such thing as an "address" and, if there is, it is not invariant. Some GC schemes move objects around in memory, and the capability-based machines from Intel took many liberties with the memory management model while maintaining object identity. Even in modern C++ a single object, referenced through one identifier, can appear to have a different address when addressed through another identifier. (This relates to the implementation of polymorphism under multiple inheritance, where the identifiers are differently typed in terms of classes with different locations in the inheritance graph.) So we can't talk about "identity" in terms of "this piece of memory" or of something-at-some-address.

That said, there are some technologies where the address is homomorphic to an identity at some level of abstraction. In others, the address is insufficient. What, then, is identity?

So define an abstraction boundary between the programmer (or, in some weird sense, the end user as well) and the object. What does it mean for an object to have identity? It's not that it has a name (an address, by the way, is just one name for an object; it is not the object itself). An object can have many names. Names behave like Post-It Notes® that are peeled onto objects and removed from objects. They are just labels through which we reference the object. Of course, an object has to have some name in order to have any identity at all: the garbage collector has the right to cause an object to not exist if it's not reachable from any identifier. But it's quite O.K. for an object to have multiple names. That is not what I mean by identity.

All we can see of an object from this side of the abstraction boundary is its behaviour, so if identity is to be operational, then we must formulate it in terms of behaviour rather than state. Even states are elicited through behaviours called getter methods. We can guess about state but cannot factor any essence of state into a definition of identity. (In fact, it doesn't change the argument if we look at state, but I wanted as minimal a formal argument as possible.)

We can talk about "delivered state:" that is, the return values from methods. That's how we find out that objects are doing something.

Define O as a sequence of method invocations on some object A. It is implicit in this definition that each element of O includes a method selector and a suitable set of actual parameters. The set O may also includes assignment "operations;" whether we treat these as "part of the machine" (Smalltalk) or as an operation on the object (Smalltalk) is immaterial. For sake of generality, any invocation in this sequence may be allowed to use return values from any previous invocation. I make this rule explicit though it is in fact not necessary to do so; in the final formulation the dependency between invocations will already be implied. And, if you like, we can limit the invocations in O to "meaningful" operations (no "method not understood" stuff, though the argument generalises to that case as well.)

Let I be the (potentially infinite) set of all identifiers through which we can address an object A (though for sake of understanding, assume it just as a couple of identifiers, α and β. More formally, the argument should be in terms of "an arbitrarily large set I"). Let J be the (finite or countably infinite) set of all combinations of identifiers in I.

If A has identity, then we can apply elements of O in succession, each one applied to a successive element of J, and for each ordered selection of elements O and for all elements of J of equal length, the result will be the same.

This means that if α and β are identifiers, and if we take invocations in term from some J in I and look at the result (by looking anything we can deduce about the object on this side of the abstraction boundary) the result will be the same if we take a different J from I. Let's say the object is a stack. The claim says that if we do this:

α := class new.
β := α.
β push: 1.
β push: 1.
α push: 3.
β push: 4.
α push: 5.
β pop.
α pop.
ɣ := β pop.
β push: 0.

and then stop and find out as much about the object state as we can, and then start over and do this:

α := class new.
β := α.
α push: 1.
β push: 1.
α push: 3.
α push: 4.
α push: 5.
β pop.
β pop.
ɣ := β pop.
α push: 0.

and we hold the same investigation, that the object exhibits identity. (Showing that the results are the same for both implies identity of the object through each of all of such sequences.) It should work even for:

α := class new.
α := α.
α push: 1.
α push: 1.
α push: 3.
α push: 4.
α push: 5.
α pop.
α pop.
ɣ := α pop.
α push: 0.

with a subsequent evaluation.

If if helps your thinking, you can judge the "subsequent evaluation" to be just the state of the object (whatever that means). I think that O can be formalised as a more general Turing machine and that this argument can be made fully formal. But this seems good enough. I can't think of any other definition of identity that would be at odds with this one and still hold water. Standard assumptions apply, such as holding the environment invariant (no fair introducing parity errors) and other common-sense assumptions underlying causality.

The argument generalises to networks of objects, so it's not limited to any given object standing alone.

Shadowing blatantly violates this test. Consider the first scenario as taking place inside a Context, where α is a Role and β is a simple identifier. Game over.

Therefore, shadowing violates object identity.

You want to do that? Knock yourself out. But it's not DCI to me — for starters because it's not even OO. An object has state, behaviour — and identity.


Egon Elbre

unread,
Feb 27, 2015, 4:20:21 AM2/27/15
to object-co...@googlegroups.com


On Friday, 27 February 2015 10:41:04 UTC+2, Cope wrote:

On 26 Feb 2015, at 13:50, Matthew Browne <mbro...@gmail.com> wrote:

Yes. Let's limit the discussion to a role method overriding (or shadowing) an instance method - not the other way around. I think the former is what Egon, Rune and I have been talking about the whole time; Cope, you seem to be talking about the latter. I think we all agree that allowing an instance method to override a role method is a bad idea.

I think it's easy to argue that the latter is a problem. In fact the former is its dual and the same arguments apply. People have a bit more trouble seeing that argument because of the way they think about inheritance.

Consider a class C, two class methods called Cmethod and Cmethod2, and an instance of C that we'll address through a role name R. R has a Role method called Rmethod and it also has a Role method called Cmethod.

With your proposed shadowing: if an outsider invokes CMethod on R, it gets R's C method.

If Cmethod2 invokes Cmethod on self, what is invoked?

Can R express Cmethod both in its public interface and in its role / object contract interface? If so, then can R's Cmethod2 invoke C's Cmethod through that interface?

How would R's Cmethod differentiate between calling C's Cmethod and R's Cmethod?

Currently JavaScript implementation does it via either explicitly naming the role vs. this.
The rule is that only R.Cmethod() calls the role method. Using this means that it will call the class method.


How would any code within the context gain access to C's Cmethod of the object playing the role R, were it necessary to do so?

I would say that the R should explicitly expose it.


These are not idle questions. A good part of the design of C++ dealt with sorting out analogous complexities along the axis of the inheritance hierarchy, which roughly corresponds to the subtyping hierarchy. Therein lies a good bit of the complexity of the language. In C++ it's worse because of overloading, and indeed, the question becomes more interesting here if you allow compile-time polymorphism and its cousins.

C is a Context class and Cmethod is its only trigger method. Is it totally inaccessible as a role-player of R? (I have a lot of other interesting cases in my pocket, at least one of which involves a Context object, multiple of whose roles are played by itself. (Already in DCI each Context object plays one of its own roles — the role called self.) To that, add recursive methods, and you get lost really quickly.)

In the JavaScript implementation the role can access the context methods if it plays a role in the its own context, e.g.

var Example = Context(function(player1){
Player = player1

Context = {
start: function(){
console.log("START");
Player.play()
},
alternate: function(){
console.log("ALTERNATE");
}
};

return Context;
}, {
Context: {},
Player: {
play: function(){
console.log("PLAY");
Context.alternate();
}
}
});

var x = Example({});
x.start();

Although I have no clue whether this would be practical in any way.

Egon Elbre

unread,
Feb 27, 2015, 4:30:38 AM2/27/15
to object-co...@googlegroups.com
By the same argument wouldn't roles violate object identity in the same way.

α = new Class()
α :push 1

If α doesn't have method :push then this would crash (or some other behavior), whereas if it were playing a role that had that method, it doesn't crash. Which means that depending on the context you get different behaviors.

Similarly, when trying to enforce this property, this would mean that the Role methods could never have the same name. Basically, different contexts for: α :push 1 could have different behavior, even without method shadowing.

Egon Elbre

unread,
Feb 27, 2015, 4:42:43 AM2/27/15
to object-co...@googlegroups.com


On Friday, 27 February 2015 11:00:12 UTC+2, Cope wrote:
This is a position statement, taking the position that "shadowing" violates object identity.

We need a good definition of object identity. We start with a vocabulary of the things in our universe: names, objects, method selectors, arguments, and methods.


I was thinking about this... let's say there is a play where actor John is playing a role Hamlet.

Who is the person Hamlet and who is John, and would they act the same way? Or would their responses differ?

Rune Funch Søltoft

unread,
Feb 27, 2015, 5:13:32 AM2/27/15
to object-co...@googlegroups.com
Below is what happens in Marvin, maroon and interact

Den 26/02/2015 kl. 15.01 skrev James O Coplien <jcop...@gmail.com>:


On 26 Feb 2015, at 13:50, Matthew Browne <mbro...@gmail.com> wrote:

Yes. Let's limit the discussion to a role method overriding (or shadowing) an instance method - not the other way around. I think the former is what Egon, Rune and I have been talking about the whole time; Cope, you seem to be talking about the latter. I think we all agree that allowing an instance method to override a role method is a bad idea.

I think it's easy to argue that the latter is a problem. In fact the former is its dual and the same arguments apply. People have a bit more trouble seeing that argument because of the way they think about inheritance.

Consider a class C, two class methods called Cmethod and Cmethod2, and an instance of C that we'll address through a role name R. R has a Role method called Rmethod and it also has a Role method called Cmethod.

With your proposed shadowing: if an outsider invokes CMethod on R, it gets R's C method.

If Cmethod2 invokes Cmethod on self, what is invoked?
Cs Cmethod


Can R express Cmethod both in its public interface and in its role / object contract interface? If so, then can R's Cmethod2 invoke C's Cmethod through that interface?
Yes


How would R's Cmethod differentiate between calling C's Cmethod and R's Cmethod?
There'd be several. In Marvin and interact I'd recommend to cast to the type of the player because that's how C# deals with shadowing.

How would any code within the context gain access to C's Cmethod of the object playing the role R, were it necessary to do so?
Accesses it not through the role itself thereby making it explicit that in no case could it be accessing a role method and thus there's be no surprise that the instance method is invoked


These are not idle questions. A good part of the design of C++ dealt with sorting out analogous complexities along the axis of the inheritance hierarchy, which roughly corresponds to the subtyping hierarchy. Therein lies a good bit of the complexity of the language. In C++ it's worse because of overloading, and indeed, the question becomes more interesting here if you allow compile-time polymorphism and its cousins.

C is a Context class and Cmethod is its only trigger method. Is it totally inaccessible as a role-player of R? (I have a lot of other interesting cases in my pocket, at least one of which involves a Context object, multiple of whose roles are played by itself. (Already in DCI each Context object plays one of its own roles — the role called self.) To that, add recursive methods, and you get lost really quickly.)

I can see some latent programming rules in my head that are "getting in the way." One of them is that an object should behave the same (in response to a request to perform a method) no matter the identifier through which we invoke the methods of that same instance. That is, if I associate the identifier S with an instance of C, and invoke one of its instance methods through S, I should instead be able to bind that same object to the identifier R, invoke an operation using the same method selector and arguments, and get the same result. Shadowing violates that: it means that the name through which I access an object changes the behaviour of a given method selector on that same object!

This radically violates the Rule of Least Surprise.
So does the fact that some one external to the project adding method breaks my code it also breaks and age old definition of what a breaking change is. It would mean that promising more would also be a breaking change and that requiring less could also be a breaking change invalidating the foundation of design by contract. I'd say that is a bigger surprise than any of the above if we can prove that the foundation for DBC is based on a false understanding of what a contract violation is and through that prove that DBC is nothing but wishfull thinking that should better be substituted by something else like automated tests (did I push enough of your buttons :) :) :) )


--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.

Rune Funch Søltoft

unread,
Feb 27, 2015, 5:18:25 AM2/27/15
to object-co...@googlegroups.com

> Den 27/02/2015 kl. 09.59 skrev James O Coplien <jcop...@gmail.com>:
>
> This is a position statement, taking the position that "shadowing" violates object identity.

All injectionless implementations are an abstraction upon object identity. The identity is lost in the transformation from a instance method invocation statement related to the player into an invocation of either a static method or an instance method on the context. I'd claim that's it's not leaking much in any of my implementations but we have previously discussed some areas where they are currently leaking and in some sense injectionless implementations are compile time wrapper solutions

James O Coplien

unread,
Feb 27, 2015, 7:35:09 AM2/27/15
to object-co...@googlegroups.com

On 27 Feb 2015, at 10:30, Egon Elbre <egon...@gmail.com> wrote:

By the same argument wouldn't roles violate object identity in the same way.


No. The problem arises only if there is either shadowing or overriding. The use of a role identifier in a given universe of method selectors and arguments, in a given sequence, is invariant under the use of roles with unique method selectors.

Matthew Browne

unread,
Feb 27, 2015, 7:36:37 AM2/27/15
to object-co...@googlegroups.com
On 2/26/15 9:01 AM, James O Coplien wrote:
On 26 Feb 2015, at 13:50, Matthew Browne <mbro...@gmail.com> wrote:

Yes. Let's limit the discussion to a role method overriding (or shadowing) an instance method - not the other way around. I think the former is what Egon, Rune and I have been talking about the whole time; Cope, you seem to be talking about the latter. I think we all agree that allowing an instance method to override a role method is a bad idea.

I think it's easy to argue that the latter is a problem. In fact the former is its dual and the same arguments apply. People have a bit more trouble seeing that argument because of the way they think about inheritance.

Consider a class C, two class methods called Cmethod and Cmethod2, and an instance of C that we'll address through a role name R. R has a Role method called Rmethod and it also has a Role method called Cmethod.

With your proposed shadowing: if an outsider invokes CMethod on R, it gets R's C method.
No, it would still get get C's Cmethod. Role methods aren't accessible from outside the context, and in fact outside of the context it's as if they don't exist at all, thanks to the implementation being injectionless.

If Cmethod2 invokes Cmethod on self, what is invoked?
As Egon and Rune said, C's Cmethod would be invoked. Within class C, all method invocations would always refer to the instance methods.

Can R express Cmethod both in its public interface and in its role / object contract interface? If so, then can R's Cmethod2 invoke C's Cmethod through that interface?

How would R's Cmethod differentiate between calling C's Cmethod and R's Cmethod?
This to me is the most interesting question, since I think it could be useful to still be able to call C's Cmethod from R's context even if it's overridden -- in fact perhaps the reason it's being overridden is to add a simple validation check or log message and then call the original method (C'c Cmethod).

I like Rune's solution of casting to the type of the role player. But that only works for languages with static typing and casting. I suppose Egon's solution that this.foo() would always refer to the instance method foo() rather than the role method foo() could work, but then this would have a different meaning than self in this case, which could be confusing to the programmer and possibly a violation of the DCI mental model.
How would any code within the context gain access to C's Cmethod of the object playing the role R, were it necessary to do so?

These are not idle questions. A good part of the design of C++ dealt with sorting out analogous complexities along the axis of the inheritance hierarchy, which roughly corresponds to the subtyping hierarchy. Therein lies a good bit of the complexity of the language. In C++ it's worse because of overloading, and indeed, the question becomes more interesting here if you allow compile-time polymorphism and its cousins.

C is a Context class and Cmethod is its only trigger method. Is it totally inaccessible as a role-player of R? (I have a lot of other interesting cases in my pocket, at least one of which involves a Context object, multiple of whose roles are played by itself. (Already in DCI each Context object plays one of its own roles — the role called self.) To that, add recursive methods, and you get lost really quickly.)

I can see some latent programming rules in my head that are "getting in the way." One of them is that an object should behave the same (in response to a request to perform a method) no matter the identifier through which we invoke the methods of that same instance. That is, if I associate the identifier S with an instance of C, and invoke one of its instance methods through S, I should instead be able to bind that same object to the identifier R, invoke an operation using the same method selector and arguments, and get the same result. Shadowing violates that: it means that the name through which I access an object changes the behaviour of a given method selector on that same object!

This radically violates the Rule of Least Surprise.
--
You received this message because you are subscribed to a topic in the Google Groups "object-composition" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/object-composition/1okz656kbY8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to object-composit...@googlegroups.com.

Matthew Browne

unread,
Feb 27, 2015, 8:02:45 AM2/27/15
to object-co...@googlegroups.com
Note: I'm using the word "context" here in the traditional English language sense; I'm not referring to a DCI context (although obviously there's a DCI Context context for the use case and a class/prototype context for the instance).

This argument doesn't hold up if you consider the context in which the methods are called. A method name is a way of referring to a specific operation, much like object identifiers (or pointers / memory references) are a way of referring to a specific object. Let's take the example from your previous post and suppose that the methods are called in this order:
C.Cmethod()
R.Cmethod()
At first glance it might look like C.Cmethod and R.Cmethod are referring to the same operation, but that's only if you don't consider the context. The context is essential to understanding what we're referring to, just as how in English, the meaning of a verb depends on context. *  It's up to the programmer to do the mental combining here - but to make it explicit, what we're really dealing with is this:
C.instance_Cmethod()
R.role_Cmethod()
So I don't see how this violates the Rule of Least Surprise - why should the programmer be surprised that calling a different operation causes a different result? The error is thinking that they're the same operation just because they have the same method name. i.e. should we be surprised if this leads to a different result:
R.role_Cmethod()
C.instance_Cmethod()

* BTW, I think the use of verbs in language is a good analogy in general here, and shows why sometimes method shadowing might be the most natural and easily understandable naming solution. I'm not just talking about homonyms; there are also many other situations where the actual "operation" that a verb refers to may have differences depending on the noun and context that it's paired with.

James O Coplien

unread,
Feb 27, 2015, 8:05:46 AM2/27/15
to object-co...@googlegroups.com

On 27 Feb 2015, at 14:02, Matthew Browne <mbro...@gmail.com> wrote:

At first glance it might look like C.Cmethod and R.Cmethod are referring to the same operation, but that's only if you don't consider the context. The context is essential to understanding what we're referring to, just as how in English, the meaning of a verb depends on context.

The formal computational theory definition of the context of any algorithm is the entire state space of the program in which it is embedded. Anything else is a formally unsubstantiable approximation (see Kaiser and Perry's research on testing).

If you want to develop your argument in terms of such context, then all is lost.

James O Coplien

unread,
Feb 27, 2015, 8:15:40 AM2/27/15
to object-co...@googlegroups.com
On 27 Feb 2015, at 14:02, Matthew Browne <mbro...@gmail.com> wrote:

This argument doesn't hold up if you consider the context in which the methods are called. 

More deeply, the name of the thing is not the thing, does not change the thing, and is only a path to the thing. "A rose by any other name would smell as sweet." Folding entity names into contextualisation fails as an argument on the basis of category error.

Trygve Reenskaug

unread,
Feb 28, 2015, 5:42:42 AM2/28/15
to object-co...@googlegroups.com
The following comments are general and independent of Javascript.

Overriding/shadowing/masking role methods by instance methods is impossible in my SqueakContext implementation because role methods always have priority. It is, in any case, undesirable since the context will not tell the truth, the whole truth, and noting but the truth.

Another question is if it is bad form to let a role method override an instance method. With role method injection it clearly is because overriding destroys the instance method, the universe of objects is corrupted, and anything might happen. In Squeak, there is a high risk for inadvertent collisions with the 638 methods (!) defined in the Object, the root class. (638 is a ridiculous number, but even Java and C# define operations that the average programmer doesn't care to know). That's why I thought it essential to realize injectionless DCI. Contexts are now isolated from their Data objects so that role methods cannot inadvertently override anything.

Technically, a role method may be given any name as long as it is unique within the role. However ill considered the choice may be, the program will work. We are left with stylistic and readability issues. I think it should be permissible for me to name a method 'withoutListWrapper', for example, even if a method with that name happens to be implemented in class Object. It is outside my mental model, its original meaning is of no interest to me, and there will be no confusion if I make it mean something different in my context. I think the programmer's or the project's vocabulary should be the guide. If a word will be unambiguously be understood by all, fine. If not, change it. All OO is 'call by intent', a method name says what shall be achieved, not how. So it is perfectly OK to use a common name for a role method even if its implementation in the roleplayer is different. This would be the DCI equivalent of polymorphism. As one guru put it: "Words are important".

Two days ago, I thought I had a good example of an acceptable role method overriding an instance method. Fortunately, I tried it with my SqueakContext and it couldn't work. The role method could never be called.

But here's an override  example that works in my SqueakContext. 'printString' is declared in class Object. It returns a String that programmers use to identify object in inspectors, debuggers, and such. This has always been its meaning in all Smalltalks I have ever known. I would be very upset if anybody presented me with a method that meant something else.

A UML Port has a Boolean variable: isService. If false, an incoming message will be passed directly to the attached object. If true, the message is intercepted and behavior local to the port is executed. In my SqueakContext, an object has 2 input ports. One is named after the receiving role. its isService is conceptually true, and any role methods have precedence. The other is called by the reserved identifier self, and incoming messages are passed directly to the roleplayer object. Anybody remember methodless and methodful objects? Today, role methods have been moved from the object to an input port. Here's my demo override of printString in a role FOO:

    FOO>>printString
         ^ 'FOO is played by: ' , self printString.
It can be called by any role method in the context:
    Transcript show: FOO printString.
(Transcript is the Squeak console). The console result of the execution of this method could be 
    
FOO is played by a TextMorph
 where 'a TextMorph' is the default result of 'printString'.

Simple and easy to understand, IMO.




On 26.02.2015 11:12, James O Coplien wrote:
If you truly have overriding of Role methods by instance methods, then even an undocumented instance method (or, especially, an undocumented instance method) will destroy your code if its name collides with the Role for which it is a Role-player.

This is the strongest argument I know to disallow overriding of role methods.

An even stronger rule is to disallow the name collisions. I think there are places where that rule works in DCI, and, in particular, disallowing name collisions between Role methods. The reason is organisational: the enterprise delivering value delivers it as use cases and, as such, needs to have oversight of the direct value-generating code. That's embodied in the use cases and, as such, in the Role methods.

In the case of third-party software there is no single entity of detailed architectural oversight, so administrative techniques (or even techniques that can be enforced by the programming language) don't work.

So, to me, to disallow overriding of Role methods is mandatory and solves this latter problem. It is admittedly a weak solution since it doesn't solve the comprehensibility problem, particularly if the instance methods are visible. But the stronger solution, which *can* be applied from Role to Role, is to ensure that Role method names are unique. That is likely to fall under a single administrative body and correspondingly can be automatically administered under the rules of the programming language or of architectural enforcement.


On 26 Feb 2015, at 10:57, Rune Funch Søltoft <funchs...@gmail.com> wrote:

Den 26/02/2015 kl. 09.36 skrev James O Coplien <jcop...@gmail.com>:

You have an operation on a car to "fill the tank with gas." That can be an operation on the car. But it's the driver who does it, right (or, in civlised countries, the station attendant)? No: that method is "operate the pump." This re-naming adds information to the design. Giving multiple entities the same name actually removes information from the design. DCI, in spirit, is about readable code and about adding information to the design
In most of the projects I work in we rely on quite a long list of libraries we do not control in the current project more than 100. We will have to assume that since they are all actively maintained that new methods will be added. I don't think it changes our ability to understand our code if a method is added to a third party library and I think a compiler error either on the binding of a role or the name of a role method wouldn't help in contrast I think it would confuse

--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.

To post to this group, send email to object-co...@googlegroups.com.
Visit this group at http://groups.google.com/group/object-composition.
For more options, visit https://groups.google.com/d/optout.

--

The essence of object orientation is that objects collaborate  to achieve a goal.
Trygve Reenskaug      
mailto: try...@ifi.uio.no
Morgedalsvn. 5A       
http://folk.uio.no/trygver/
N-0378 Oslo             
http://fullOO.info
Norway                     Tel: (+47) 22 49 57 27

Matthew Browne

unread,
Apr 2, 2015, 11:16:49 PM4/2/15
to object-co...@googlegroups.com
Hi Quang,
I'm bringing up this thread again because I had meant to comment on something you said and realized I never did...

On Tuesday, February 24, 2015 at 10:31:57 AM UTC-5, Hai Quang Kim wrote:
btw, fun fact: quick skim shows that you have a lot of role(s) with -er :)

I think you may have misunderstood me earlier when I said that names ending with "er" can be a sign of procedural thinking when choosing role names. What I was really talking about was nouns based on verbs...many nouns ending with "er" are based on verbs, but of course not all.

In his library, Davide was using a restaurant example that was actually given by Trygve a long time ago. It wasn't necessarily intended to represent a real system, but Andreas later used it for a restaurant simulation example and pointed out that it could also be the basis for a real-world digital ordering system for a restaurant.

Anyway, I don't see any problem with the role names in the example - waiter, manager, and customer. Yes, "waiter" and "manager" are based on verbs ("to wait" tables, "to manage"), but they're real "objects" in the real world. The guideline about "er" names was about procedures / operations disguised as objects, e.g. "renderer". Such procedures should either be role methods (and a different name should be chosen for the role), or if there's enough complex logic then maybe a nested context (in which case such a role name ending in "er" would be OK -- they should generally be avoided for data objects). Another exception is names ending in "er" that refer to people or objects in the real world (as is the case here with waiter, manager, and customer).

But most important, this is just a guideline and there are many exceptions, since the English language is not exactly consistent (to say the least!).
 

there are a lot of old posts about wrapper, you can try to search for those posts.

/quang

On Tuesday, February 24, 2015 at 9:37:01 PM UTC+8, Davide Callegari wrote:
Hi guys,
I found myself intrigued by DCI lately and I wanted to try and see if I could write a proper library for Javascript, written in Coffeescript.
I would like to know if it could be interesting for anyone out there and I'm more than happy to welcome any feedback.


Let me know what you think!

Cheers,
Davide

Matthew Browne

unread,
Apr 2, 2015, 11:26:43 PM4/2/15
to object-co...@googlegroups.com
Or more succinctly: the role methods are "what happens" and the role players (identified with a role name) are "who does it". *

So if you name a role after "what happens" instead of "who does it," you need to work on better understanding roles...

* That of course is a reference to this quote from Trygve:
I think of the difference between procedure oriented and object oriented programming as being that procedure oriented answers the question: "What happens?". Object oriented answers an additional question: "Who does it?"
--
You received this message because you are subscribed to a topic in the Google Groups "object-composition" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/object-composition/1okz656kbY8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to object-composit...@googlegroups.com.

Hai Quang Kim

unread,
Apr 6, 2015, 5:10:16 AM4/6/15
to object-co...@googlegroups.com
Hi Matt,

to be honest, I hate all the generic/confused rules.
the rule should be more specific like naming thing according to the team's agreed DSL.
building good DSL is not easy, I have seen people within team debate endlessly :)

What is real thing and what is fake thing? People can make things for example: I never seen any XMLReader in my life :)
Just recently I saw receiptPrinter in real life...and there are things like: usb reader, card reader...
 
For DCI, there is a step to convert 'what happens' to 'who does it'. At this step sometimes I may overdo and convert everything to Role with -er.
Which I learnt that I need to be careful since we are converting procedural to object oriented, and not everything will work, hence mistake may happen.

What is important to me is when I did that for the first time in my life I feel that I am doing Object Oriented. I have a strong feeling that I am working on Object's code not Class's code.
What i wanted is an object that can scan a file and extract info per region for me, i was thinking about about something like card reader....

I have stopped working on that project for a few months, and now every thing I still remember about the project is RegionReader.
I have a tons of readers but I remember only 1, maybe region is the key concept in the algo I used to parse the context.

So RegionReader is the identity that compresses the knowledge about my project in my own way. and yes I knew that it may be not the perfect or the only way.
At least, even I named it badly it still works some how :)
I guess if I work on this project with a team then maybe as the team can help to improve it :) 

Even though with all the technical difficulty to implement pure DCI, just thinking in term of DCI helps me to solve a lot of problems of OOP.
Uncle Bob said the good thing of OOP is encapsulation which gives us a nice isolated place to work and think, the bad thing of OOP is  about dependency management(DI, patterns).
With DCI thinking we separate and encapsulate the hardest part of object dependency(association) into a isolated context. For the rest I just use fake DCI, and it still helps :)

/quang
Reply all
Reply to author
Forward
0 new messages