should we allow Role to call other Role's Data Object's method directly?

372 views
Skip to first unread message

Hai Quang Kim

unread,
Feb 26, 2015, 11:32:20 PM2/26/15
to object-co...@googlegroups.com
I have this question while working on the interaction diagram.
I saw 2 kind of interaction links from one Role to another Role: from Role Method to Role Method, from Role Method to Data Object Method

example:

Role A:
   Role Method X()
       RoleB.RoleMethod Y()    // this is OK
       RoleB.DataObjectMethodXYZ() // is this OK?

Role B:
   Role Method Y()
   
DataObjectB:
      DataObjectMethodXYZ();

I think if we restrict this then the Role A should know RoleB's RoleMethod, but we have more Role Method as wrapper just for calling Data Object's method.
If we don't the Role A will know all kind of method from Role B which makes the Role Concept not very clear:
- what Role B can do with Data Object B can be done by Role A as well.

/quang

Matthew Browne

unread,
Feb 27, 2015, 8:11:26 AM2/27/15
to object-co...@googlegroups.com
I don't see a problem with allowing any role being able to call the role player's instance methods, as long as those instance methods are public. The whole point of role binding is that you can add role methods but still be able to call the object's own methods. I don't understand why you're concerned about this (I was a little confused by your explanation).

Hai Quang Kim

unread,
Feb 27, 2015, 9:03:53 AM2/27/15
to object-co...@googlegroups.com
It is about:
- RoleA calls RoleB's object's method. 
not RoleA calls its own object's method. ( since the method is public, any one can call it)

sorry if I did not make it clear.

/quang

Hai Quang Kim

unread,
Feb 27, 2015, 9:27:29 AM2/27/15
to object-co...@googlegroups.com
that means increasing encapsulation of Data Object.
Only injected Role Methods can call Data Object Methods (declared as private or protected not public)

/quang

Matthew Browne

unread,
Feb 27, 2015, 9:43:47 AM2/27/15
to object-co...@googlegroups.com
On 2/27/15 9:27 AM, Hai Quang Kim wrote:
that means increasing encapsulation of Data Object.
Only injected Role Methods can call Data Object Methods (declared as private or protected not public)
Cope made a strong case in an earlier thread that role methods should never be able to call private or protected instance methods (FYI just so you're clear on my meaning, "instance methods" is the term we usually use on this group for what you referred to here as "Data Object Methods"). Although I initially thought that maybe this didn't need to be an absolute rule, I now agree with Cope that this seriously breaks encapsulation of the data class.

It is about:
- RoleA calls RoleB's object's method. 
not RoleA calls its own object's method. ( since the method is public, any one can call it)
What I meant to say (and should have said) is that I don't think calling instance methods from role methods is a problem - it doesn't matter whether it's calling its own object's method or another role player's instance method.

Contexts should never have access to private/protected instance methods of role players. Given that, does your question still apply?
sorry if I did not make it clear.

/quang

On Friday, February 27, 2015 at 9:11:26 PM UTC+8, Matthew Browne wrote:
I don't see a problem with allowing any role being able to call the role player's instance methods, as long as those instance methods are public. The whole point of role binding is that you can add role methods but still be able to call the object's own methods. I don't understand why you're concerned about this (I was a little confused by your explanation).

On Thursday, February 26, 2015 at 11:32:20 PM UTC-5, Hai Quang Kim wrote:
I have this question while working on the interaction diagram.
I saw 2 kind of interaction links from one Role to another Role: from Role Method to Role Method, from Role Method to Data Object Method

example:

Role A:
   Role Method X()
       RoleB.RoleMethod Y()    // this is OK
       RoleB.DataObjectMethodXYZ() // is this OK?

Role B:
   Role Method Y()
   
DataObjectB:
      DataObjectMethodXYZ();

I think if we restrict this then the Role A should know RoleB's RoleMethod, but we have more Role Method as wrapper just for calling Data Object's method.
If we don't the Role A will know all kind of method from Role B which makes the Role Concept not very clear:
- what Role B can do with Data Object B can be done by Role A as well.

/quang
--
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/Zc-aVmFpIgA/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.

Hai Quang Kim

unread,
Feb 27, 2015, 10:31:28 AM2/27/15
to object-co...@googlegroups.com

Below is the example:

Account
public:
    increase(amount) {}
    decrease(amount) {}
protected:
}

Rule 1:

Role SourceAccount
{
     RoleMethod::Transfer()
     {
            self.decrease(amount)
            DestAccount.Deposite(amount) // calling RoleMethod, do not allow calling DestAccount.increase(amount)
     }
}

Role DestAccount
{
     RoleMethod:Deposite(amount)
     {
          self.increase(amount)
     }  
}

vs

Rule 2:

Role SourceAccount
{
     RoleMethod::Transfer()
     {
            self.decrease(amount)
            DestAccount.increase(amount) /// allow calling instance method directly since it is public method
     }
}

Role DestAccount
{
   // no Role method
}

Should we consider to have Rule 1 which is stricter than Rule 2?
The stricter the Rule the easier to place the call to instance methods.
With Rule 2, sometimes I keep moving the call to instance methods back and forth between the two Roles.

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

Egon Elbre

unread,
Feb 27, 2015, 10:46:40 AM2/27/15
to object-co...@googlegroups.com
I would say that allow calling any of the role methods and anything that is exposed via role-object contract.

That way it's clear that what can be called and where the invoked code is located.

+ Egon

Hai Quang Kim

unread,
Feb 27, 2015, 11:05:13 AM2/27/15
to object-co...@googlegroups.com
should the role-object contract be exposed to the Role that the object will play or any other Role?

let's take a look at the diagram:

-> Context Triggered
-> ContextFileOpeningContext::Open -> SolutionExplorer::FindSelectedContextFile (Role method to Role method, left to right)
-> SolutionExplorer::FindSelectedContextFile -> self:GetSelectedFile  (Role method to Object's instance method, up to down)

-> SolutionExplorer::FindSelectedContextFile -> Parser::ParseContextFile  ( Role method to Role method, left to right)
-> Parser::ParseContextFile -> Parser::Parse  ( up to down)

OR

-> SolutionExplorer::FindSelectedContextFile -> Parser::Parse  (Role method to Object's instance method, diagonal)

Diagonal is ugly rule, go left to right then up to down is better rule :)

/quang

Egon Elbre

unread,
Feb 27, 2015, 11:16:21 AM2/27/15
to object-co...@googlegroups.com
On Friday, 27 February 2015 18:05:13 UTC+2, Hai Quang Kim wrote:
should the role-object contract be exposed to the Role that the object will play or any other Role?

Any other role.

If it's explicitly agreed on, that object knows how to do X, then there's really no point in repeating that information with wrapping the Role methods.

Of course, if it adds clarity then you can always add such "wrapping" role method.

+ Egon

Matthew Browne

unread,
Feb 27, 2015, 11:17:27 AM2/27/15
to object-co...@googlegroups.com
Egon, good point - the role-object contract is helpful here since it makes it easier to remember what public instance methods are guaranteed to be available.

Quang, your "Rule 1" is overly restrictive. Role names are identifiers pointing to the role player, which means that they're always a valid way of calling either role methods or instance methods (or accessing public properties). It doesn't matter where you call them from as long as it's somewhere in the Context to which the role belongs. I'd like to highlight something from my Wiki answer to "What is DCI":
In traditional class-based programming, “storing” and “processing” code is placed together in the same class, and the code for “communicating” (communication between objects) is often scattered across many different classes. DCI is more truly “object-oriented”: objects still contain both data and behavior at runtime, but DCI avoids the often incorrect assumption that system behavior shares the same structure as the data model.
I think the fact that the role player is one cohesive object at runtime is critical to understanding DCI. Once the role binding happens, the set of methods available when calling that role player is the instance methods + the role methods. All of these methods are public, and they're all available from anywhere in the Context. Before binding a data object to a role, I doubt you'd complain about calling its public methods from a Context method, so why is it an issue to call the same method after role binding from outside the role? For example:

context C {
    constructor(DataInterface data) {
        data.foo();
        MyRole <- data;  //bind to role
        MyRole.foo();
    }
}


I'm calling foo() from the Context's constructor - not even from a role method. If it's OK to do it here, why should it not also be OK to call MyRole.foo() from any other role?

To Egon's point, it's important that DataInterface includes the method foo(), otherwise you might indeed have an encapsulation problem.
--
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/Zc-aVmFpIgA/unsubscribe.
To unsubscribe from this group and all its topics, send an email to object-composit...@googlegroups.com.

Risto Välimäki

unread,
Feb 27, 2015, 2:50:10 PM2/27/15
to object-co...@googlegroups.com
> I would say that allow calling any of the role methods and anything that is exposed via role-object contract.

This is important (emphasis mine). Calling arbitrary instance methods that are not part of the role contract would be dangerous, but depending the implementation, fortunately often impossible.

Eg. Scala implementation and Marvin implementations with strict and contract typing disallows calling instance methods that are not defined in role contract.

Using dynamic role typing on Marvin as well as in most DCI implementations in dynamically typed languages allows that kind of instance method calls, but the coding conventions should just strictly forbid using other instance methods.


Reasoning behind allowing direct calls to (public, defined in role contract) instance methods is that the role playing object is just enhanced by the role methods, and not by any means wrapped by role or restricted by role.

On the other hand, the reason why to use only those instance methods that are part of the role contract (or something that every object has on some languages, such as toString()) is simply that those methods are the only ones that are guaranteed to be there for every possible role player.

It's not only possible, but also I think it's quite common that you'll have some Roles acting just as identifiers in your Contexts, without having any role methods. Of course you could add "proxy" role methods that just directly calls instance methods, but why to do that?

-Risto

--
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 27, 2015, 5:19:13 PM2/27/15
to object-co...@googlegroups.com
The serious downside is that thos encourages thinking in terms Of classes and roles instead of objects. 

This restriction does not feel right to me. 

Sendt fra min iPhone
--
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 27, 2015, 5:45:52 PM2/27/15
to object-co...@googlegroups.com


Sendt fra min iPhone

> Den 28/02/2015 kl. 01.17 skrev Matthew Browne <mbro...@gmail.com>:
>
> Once the role binding happens, the set of methods available when calling that role player is the instance methods + the role methods.

Nicely put. Not quite right, though, because of the possibility of an object playing multiple roles from one or more Contexts. Its not really class composition: objects accumulate methods over time.

The problem arises when the name space for these spaces collide. I say: the fix is to disallow such collisions.

My mental model is that the objects carry these methods. I don't need compile-time context (small "c") to clutter my mental model.

Hai Quang Kim

unread,
Feb 27, 2015, 7:20:32 PM2/27/15
to object-co...@googlegroups.com
old OOP:

class Account
{
public:
    void transfer(amount, otherAccount)

protected:    // hide implementation 
    void increase(amount)
    void decrease(amount)
}

DCI

class Account
{
public: //have to expose these implementations for any Role and Context
    void increase(amount)
    void decrease(amount)
}

at runtime

SourceAccount
{
public:
     void transfer(amount)

     // accidently exposed, and could be dangerous
     void increase(amount)
     void decrease(amount)
}

As you can see in DCI the 2 methods increase and decrease have to be public (object data contract), while in old OOP they are protected (more encapsulation).
I am thinking new access type

Account
{
public:
      void anypublic() // for accessing from Context example

role: <--- new kind of access
      void increase() // only available for Role that this object will play

protected:
}

@Matthew, in your example, the object contract is for both Context and Role, is that intended?
What if I just want that contact to be available in Role Method only  not in Context's system operation or constructor.
How can we do that? (or do we need that?) 

/quang

James O Coplien

unread,
Feb 27, 2015, 7:33:07 PM2/27/15
to object-co...@googlegroups.com

On 28 Feb 2015, at 01:17, Matthew Browne <mbro...@gmail.com> wrote:


I'm calling foo() from the Context's constructor - not even from a role method. If it's OK to do it here, why should it not also be OK to call MyRole.foo() from any other role?

Exactly right.

James O Coplien

unread,
Feb 27, 2015, 7:33:28 PM2/27/15
to object-co...@googlegroups.com

On 28 Feb 2015, at 04:50, Risto Välimäki <risto.v...@gmail.com> wrote:

It's not only possible, but also I think it's quite common that you'll have some Roles acting just as identifiers in your Contexts, without having any role methods.

Interesting. I don't call those "roles." Should I?

Hai Quang Kim

unread,
Feb 27, 2015, 7:40:26 PM2/27/15
to object-co...@googlegroups.com
I actually have this question in my head for a long time.
And DHH also have a critics about minxin in DCI

"This approach to breaking up domain logic into concerns is similar in some ways to the DCI notion of Roles. It doesn’t have the run-time mixin acrobatics "

Basically, I am questioning the need for mixin and if we need it, it should be  defined in clearer way.
The problem is:
1-  All the Roles can see other Roles through the Context.
2-  All the Role's instance methods are public
3- In any Role Method of any Role, i can call any Role's instance method (no real difference between Role method and instance method)

The only reason I can see why we nee mixin is:
- in Role method I can use self/this
with mixin

Role A
    RoleMethodA()
    {
       self.instanceMethod()
       
        var b = Context.ObjectB   // global
        b.instanceMethod()    // public
    }
}

without mixin
Role A
    RoleMethodA
    { 
       var self = Context.ObjectA   // global
       self.instanceMethod()    // public
    }
}

Role B
    RoleMethodB
    { 
       var self = Context.ObjectB   // global
       self.instanceMethod()    // public
 
      var a = Context.ObjectA   // global
       a.instanceMethod()    // public
    }
}

/quang

Matthew Browne

unread,
Feb 27, 2015, 11:44:01 PM2/27/15
to object-co...@googlegroups.com
On 2/27/15 5:28 PM, James O Coplien wrote:

Sendt fra min iPhone

Den 28/02/2015 kl. 01.17 skrev Matthew Browne <mbro...@gmail.com>:

Once the role binding happens, the set of methods available when calling that role player is the instance methods + the role methods.
Nicely put. Not quite right, though, because of the possibility of an object playing multiple roles from one or more Contexts. Its not really class composition: objects accumulate methods over time. 
I was talking about the methods that are available when calling methods on a role player within a particular Context. Technically the role methods still exist on the object until the role is unbound (or at least that's the illusion) even if the execution flow returns to the environment or moves to another Context. But they're inaccessible from outside the Context to which the role(s) belong, so from a practical standpoint it's as though they don't exist anywhere else.

The problem arises when the name space for these spaces collide. I say: the fix is to disallow such collisions. 
I don't think this is much of an issue in an injectionless implementation. Name collisions should be avoided when possible for the sake of readability, but role methods are private to Contexts so when would this become a practical issue for the programmer in cases where it doesn't reduce readability? Perhaps you would argue that it always reduces readability (which I disagree with)...but even so that doesn't address Egon and Rune's point that a small change to a 3rd party library could break your existing code if role-method-overriding-instance-method is prohibited.

Matthew Browne

unread,
Feb 28, 2015, 12:10:03 AM2/28/15
to object-co...@googlegroups.com
On 2/27/15 7:20 PM, Hai Quang Kim wrote:
@Matthew, in your example, the object contract is for both Context and Role, is that intended?
Yes, that was on purpose. There are 2 approaches to role-object contracts, which I think are both valid. One is to specify them in the Context's constructor, as in Marc's ScalaDCI library:
https://github.com/DCI/scaladci/blob/master/core/src/test/Scala/scaladci/semantics/RoleContract.scala

The other is to specify them as part of the role definition, as Andreas did in his Haxe library:
https://github.com/ciscoheat/haxedci-example#defining-a-roleobjectcontract

Personally I prefer Andreas's approach because there's less visual separation between the role-object-contract and the role itself, so it's super easy to see what interface and/or specific instance methods are required for the object to be able to play the role without even having to scroll up to the top of the file.

But in this case I chose to use type hinting in the constructor since I was making the point that once you know what type of data object you're dealing with, it's safe to call its public instance methods from anywhere.

(Note: In ScalaDCI, roles are bound immediately, as soon as objects are passed as arguments to the Context's constructor, which is why type hinting of those parameters also doubles as a way of declaring a role-object-contract. So my brief code example wasn't fully consistent with the ScalaDCI approach and thus doesn't have a true role-object contract, but it comes pretty close and was intended just to get the idea across.)

What if I just want that contact to be available in Role Method only  not in Context's system operation or constructor.
How can we do that? (or do we need that?)
If two roles both have a contract with the same data class or interface (as in your example where both roles are played by Account objects), then the second contract is actually redundant; the first one is enough to guarantee that the instance methods in the data interface are available regardless of whether you call RoleA.instanceMethod() or RoleB.instanceMethod() -- either way, it's the same type of object, and its instances have the same instance methods the whole time.
/quang

On Saturday, February 28, 2015 at 6:45:52 AM UTC+8, Cope wrote:


Sendt fra min iPhone

> Den 28/02/2015 kl. 01.17 skrev Matthew Browne <mbro...@gmail.com>:
>
> Once the role binding happens, the set of methods available when calling that role player is the instance methods + the role methods.

Nicely put. Not quite right, though, because of the possibility of an object playing multiple roles from one or more Contexts. Its not really class composition: objects accumulate methods over time.

The problem arises when the name space for these spaces collide. I say: the fix is to disallow such collisions.

My mental model is that the objects carry these methods. I don't need compile-time context (small "c") to clutter my mental model.
--

Matthew Browne

unread,
Feb 28, 2015, 12:12:39 AM2/28/15
to object-co...@googlegroups.com
I thought that's what's happening in the TransferMoney context where Amount is a role...

Risto Välimäki

unread,
Feb 28, 2015, 1:26:15 AM2/28/15
to object-co...@googlegroups.com
Thanks Matthew, that was exactly what I was after.

Risto Välimäki

unread,
Feb 28, 2015, 1:51:48 AM2/28/15
to object-co...@googlegroups.com
2015-02-28 0:28 GMT+02:00 James O Coplien <jcop...@gmail.com>:

The problem arises when the name space for these spaces collide. I say: the fix is to disallow such collisions.

That has been always one of my main concerns. I'm afraid that it's not always possible to disallow such collisions, even if role methods are prefixed for example with underscore or other special character, as suggested by Trygve some years ago.

In my opinion, what should happen instead is that you should never be able to call role methods from instance methods. That's simply because role methods shouldn't be defined outside of their contexts, and class abstraction is simply outside the contexts. I guess this is no-brainer and we can all agree on that.

And on the other hand, IFF there is role method foo() defined in Bar context, all role method calls inside that Bar context should invoke the role method foo() and not the instance method foo(), given that there is any.

In injectionless implementations of DCI this is guaranteed. Even with Role-as-a-wrapper implementations of not-at-all-real-DCI this is guaranteed by nature. In other implementations of DCI this is something that has to be really carefully taken into account. And then there is one possibility to simply just disallow these collisions, but I see that very limiting.

In typical / easiest (and simply faulty) method-injection implementations (such as Ruby native modules), that allow instance methods to call role methods, all the demons are there ready to bite flesh of an innocent coder. Disallowing name clashes is simply the only way out, but unfortunately even that is not enough! There is also possibility of Role-Role method name clashes, if injectionfull method injection is used and this situation is not carefully taken into account. That is, method from different context may have been polluted the object already, and of course different contexts may have role methods with identical signatures. By definition, this is not conforming DCI (role methods are simply not defined outside the context).

Needless to say, injectionless implementations (*) are not plagued by this kind of role-role, role-data or data-role name clashes or accidental polymorphism, since role methods simply doesn't exist outside the Context where they are defined on.  

(*) at least those I'm familiar with

James O Coplien

unread,
Feb 28, 2015, 1:57:35 AM2/28/15
to object-co...@googlegroups.com
On 28 Feb 2015, at 13:43, Matthew Browne <mbro...@gmail.com> wrote:

I was talking about the methods that are available when calling methods on a role player within a particular Context.

Yes, I understand. Let's say that the current Context was instantiated through some execution path that entailed one of its objects already playing a role in another Context. In my mental model that object carries those role methods. In my mental model of DCI there are no method name conflicts so the question of whether those methods are ever executed outside their context never arises. By allowing duplication of method names, the system becomes an order of magnitude or so more complex with a system of epicycles and implementation arguments that protect against bad things happening in the case of name collisions.

Technically the role methods still exist on the object until the role is unbound (or at least that's the illusion) even if the execution flow returns to the environment or moves to another Context.

"Technically." Powerful word. Dangerous word. So: do they exist or not?

But they're inaccessible from outside the Context to which the role(s) belong, so from a practical standpoint it's as though they don't exist anywhere else.

So let's explore this in detail. If I have access to the object through a MOP, does the MOP carry any information about the presence of this method? That is, is the "as if they don't exist" air-tight and intended for cooperative communicating programmers, or are they an inviolate guarantees?


Risto Välimäki

unread,
Feb 28, 2015, 2:24:48 AM2/28/15
to object-co...@googlegroups.com
2015-02-28 8:57 GMT+02:00 James O Coplien <jcop...@gmail.com>:
By allowing duplication of method names, the system becomes an order of magnitude or so more complex with a system of epicycles and implementation arguments that protect against bad things happening in the case of name collisions.

I agree, if we are talking about injectionfull implementations. 

I strongly disagree on this if we are talking about injectionless implementations. It's simply guaranteed that there are no surprises, no accidental polymorphism or method overriding, even if methods with same signature are used in all classes and all roles. 

But I agree that you are also safe by disallowing all the name clashes that is:

1. There should be exactly one role method of the same signature. That is, if you have already method foo() in Bar context, you are not able to have context Baz with method foo().

2. There should be never role method called foo() given that any of possible role players has instance method foo() defined on their class abstraction.

For real, big applications I see this seriously limiting and resulting not only overly verbose, but also long or randomly prefixed methods. One possibility is of course use the context name as a prefix, but in my opinion, this is not neat at all. Yet I admit that I could live with this limitation, if there was no other alternative over this. But as said, there is a way over the hill, and I would rather take that way than feel myself being on prison.

All in all, no convention whatsoever can ever make you safe here. Only strict compiler error on name clashes may save you when using statically typed programming languages. Though I feel for you that are using run-time checked languages with method-injection and without sophisticated DCI implementation that takes care of these possible name clashes. I don't think there is much hope for you available.
 
Technically the role methods still exist on the object until the role is unbound (or at least that's the illusion) even if the execution flow returns to the environment or moves to another Context.

"Technically." Powerful word. Dangerous word. So: do they exist or not?

Depends. On injectionless implementation they simply do not exist. On injectionfull implementation they are there, and if not cared of, they will also bite you.

-Risto

James O Coplien

unread,
Feb 28, 2015, 2:29:57 AM2/28/15
to object-co...@googlegroups.com

On 28 Feb 2015, at 15:51, Risto Välimäki <risto.v...@gmail.com> wrote:

In my opinion, what should happen instead is that you should never be able to call role methods from instance methods.


Again: This doesn't solve the issue of code comprehensibility. All this does is it says: "I've covered your ass — the opportunity exists for you to get in trouble, so after you've decided to invoke a method in a reasonable way from a reasonable perspective, I'll make sure to make it impossible to do so out of concern for a potential conflicting call from another perspective."

James O Coplien

unread,
Feb 28, 2015, 2:31:30 AM2/28/15
to object-co...@googlegroups.com

On 28 Feb 2015, at 16:24, Risto Välimäki <risto.v...@gmail.com> wrote:

I strongly disagree on this if we are talking about injectionless implementations. It's simply guaranteed that there are no surprises, no accidental polymorphism or method overriding, even if methods with same signature are used in all classes and all roles. 


That all of this is true does nothing to help me reason about invocations in the source code.

This is not a nerd issue, but one of psychology. I am concerned about the comprehension and code analysis problem.

James O Coplien

unread,
Feb 28, 2015, 2:33:37 AM2/28/15
to object-co...@googlegroups.com
On 28 Feb 2015, at 16:24, Risto Välimäki <risto.v...@gmail.com> wrote:

All in all, no convention whatsoever can ever make you safe here. 

I disagree. Merely assuring that method names within the closure of a business offering (the union of the delivered use cases) solves the problem. That is not administratively unreasonable.

There are several other approaches (namespaces, name servers, etc.), but it only takes one to undo a claim of "no convention whatsoever."

Rune Funch Søltoft

unread,
Feb 28, 2015, 3:46:21 AM2/28/15
to object-co...@googlegroups.com

> Den 28/02/2015 kl. 07.57 skrev James O Coplien <jcop...@gmail.com>:
>
> So let's explore this in detail. If I have access to the object through a MOP, does the MOP carry any information about the presence of this method? That is, is the "as if they don't exist" air-tight and intended for cooperative communicating programmers, or are they an inviolate guarantees

In the tools I've made they don't exist outside the context. That's actually the leaking I talked about they aren't they if you inspect the object because inspection/reflection modules are outside the context in .NET and in Ruby because I've ignored the complexity of handling it correctly (I would need to monkey patch the core of Ruby and being no Ruby wiz I didn't feel like trying to do that)

Hai Quang Kim

unread,
Feb 28, 2015, 4:31:05 AM2/28/15
to object-co...@googlegroups.com
I am not sure that the group are aware that DCI Objects have less encapsulation compared to old OOP version.
this is one of my concern. in DCI object class, I have to expose too many things. 
But If that is not a big problem then I am fine with that.

I just think a stricter rule my help (only 1 place to call object instance method)
 while a flexible rule offers too many options to place the call to object instance methods ( in context, in Role 1, in Role 2,....)

(Rule: data object contract is only available for the Role it will play)
But it looks like this is not a big deal also :)

/quang

Egon Elbre

unread,
Feb 28, 2015, 4:41:02 AM2/28/15
to object-co...@googlegroups.com
On Saturday, 28 February 2015 00:19:13 UTC+2, Cope wrote:
The serious downside is that thos encourages thinking in terms Of classes and roles instead of objects. 

I'm not following how you came to that conclusion.

Trygve Reenskaug

unread,
Feb 28, 2015, 5:48:05 AM2/28/15
to object-co...@googlegroups.com
My answer is Yes we should. As I say at length in a recent post, my SqueakContext has two words for identifying the roleplayer. A message sent to 'self' goes directly to the roleplayer. A message sent to <ROLENAME> is intercepted at the input. A role method is executed if it exists, otherwise the message is forwarded to the roleplayer.



On 27.02.2015 05:32, Hai Quang Kim wrote:
I have this question while working on the interaction diagram.
I saw 2 kind of interaction links from one Role to another Role: from Role Method to Role Method, from Role Method to Data Object Method

example:

Role A:
   Role Method X()
       RoleB.RoleMethod Y()    // this is OK
       RoleB.DataObjectMethodXYZ() // is this OK?

Role B:
   Role Method Y()
   
DataObjectB:
      DataObjectMethodXYZ();

I think if we restrict this then the Role A should know RoleB's RoleMethod, but we have more Role Method as wrapper just for calling Data Object's method.
If we don't the Role A will know all kind of method from Role B which makes the Role Concept not very clear:
- what Role B can do with Data Object B can be done by Role A as well.

/quang
--
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

Trygve Reenskaug

unread,
Feb 28, 2015, 5:54:26 AM2/28/15
to object-co...@googlegroups.com
It doesn't make sense for RoleA to call RoleB's object's method because it breaks the encapsulation of roles. RoleA shouldn't be aware of RoleB's choice of roleplayer.



On 27.02.2015 15:03, Hai Quang Kim wrote:
It is about:
- RoleA calls RoleB's object's method. 
not RoleA calls its own object's method. ( since the method is public, any one can call it)

Rune Funch Søltoft

unread,
Feb 28, 2015, 6:03:02 AM2/28/15
to object-co...@googlegroups.com


> Den 28/02/2015 kl. 10.31 skrev Hai Quang Kim <wan...@gmail.com>:
>
> I am not sure that the group are aware that DCI Objects have less encapsulation compared to old OOP version.
> this is one of my concern. in DCI object class, I have to expose too many things

I have no clue how you can come to that conclusion. One of the most prominent ways of breaking encapsulation is banned in DCI: inheritance. It's often been debated whether data is immutable. There's no stronger encapsulation than that. You can't change anything and can only access what's exposed. If you expose more that you should have blame is on you not the paradigm

Trygve Reenskaug

unread,
Feb 28, 2015, 6:03:58 AM2/28/15
to object-co...@googlegroups.com

On 27.02.2015 17:05, Hai Quang Kim wrote:
should the role-object contract be exposed to the Role that the object will play or any other Role?
In a context, objects are accessed through their names, i.e., the roles they play. Do you see another way for 'any other role' to access an arbitrary roleplayer without using its name (ie. a role it is playing)?

Trygve Reenskaug

unread,
Feb 28, 2015, 6:10:36 AM2/28/15
to object-co...@googlegroups.com
I most certainly do. A role is an access point to an object- It may or it may not have attached role methods. See my eumonia
post of 11:42 today.

Rune Funch Søltoft

unread,
Feb 28, 2015, 6:21:05 AM2/28/15
to object-co...@googlegroups.com


> Den 28/02/2015 kl. 11.47 skrev Trygve Reenskaug <try...@ifi.uio.no>:
>
> My answer is Yes we should. As I say at length in a recent post, my SqueakContext has two words for identifying the roleplayer. A message sent to 'self' goes directly to the roleplayer. A message sent to <ROLENAME> is intercepted at the input. A role method is executed if it exists, otherwise the message is forwarded to the roleplayer
And Marvin,maroon and interact work in a similar way. The resolution is down compile/interpretation time for those

Rune Funch Søltoft

unread,
Feb 28, 2015, 6:22:01 AM2/28/15
to object-co...@googlegroups.com

Den 28/02/2015 kl. 11.54 skrev Trygve Reenskaug <try...@ifi.uio.no>:

RoleB's choice of roleplayer
Last time I look the context was responsible for choosing role player for both A and B

Hai Quang Kim

unread,
Feb 28, 2015, 6:31:16 AM2/28/15
to object-co...@googlegroups.com
this is exactly my point.

/quang

Hai Quang Kim

unread,
Feb 28, 2015, 6:36:08 AM2/28/15
to object-co...@googlegroups.com
at first I think I just want to expose data object's method to a specific Role.
but as a side effect (public access) I expose it the rest of the world (context, controller,.....)
maybe this only happens for language like C#, c++, java...where we use interface to define Role-Object contract.
(maybe not in Marvin, i need to play with Marvin again, and I will try it again in smalltalk)

/quang

Hai Quang Kim

unread,
Feb 28, 2015, 6:38:55 AM2/28/15
to object-co...@googlegroups.com
nope, it is more about should roleplayer's methods become part of Role's method list (Role methods + roleplayer's instance methods).
I think it is good to have control here but maybe too much.

/quang


On Saturday, February 28, 2015 at 7:03:58 PM UTC+8, trygve wrote:

On 27.02.2015 17:05, Hai Quang Kim wrote:
should the role-object contract be exposed to the Role that the object will play or any other Role?
In a context, objects are accessed through their names, i.e., the roles they play. Do you see another way for 'any other role' to access an arbitrary rtheyoleplayer without using its name (ie. a role it is playing)?

Trygve Reenskaug

unread,
Feb 28, 2015, 7:04:55 AM2/28/15
to object-co...@googlegroups.com
It is a pity that there appears to be a wide spread reluctance to study my implementation of the DCI context in Squeak. The implementation embodies most of my mental model of DCI and is uncluttered by remnants of class oriented programming. Indeed, there is no programming language in the conventional sense of the word. DCI is much simpler than you appear to believe.

A quick look at the SqueakContext code would show that a role method is executed in the context of an object but is never, even for a nanosecond, part of that object. A role is an entry point to an object. It intercepts incoming messages and executes role methods when required. This means that a role method that is being executed in one context is inherently not visible in another context regardless of history. This also means that many of the problems that are discussed on this list simply do not exist.  Even in the case of recursion where a role method calls another context; there will be no conflict even if the new context executes a same-named nethod with a different body.

Cope has suggest that it would be useful with a DCI workshop in Copenhagen some time this year. I would welcome such an opportunity to present how simply SqueakDCI works.

Trygve Reenskaug

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

On 28.02.2015 12:21, Rune Funch Søltoft wrote:

Den 28/02/2015 kl. 11.54 skrev Trygve Reenskaug <try...@ifi.uio.no>:

RoleB's choice of roleplayer
Last time I look the context was responsible for choosing role player for both A and B --
You are right. I should have phrased it differently.

Matthew Browne

unread,
Feb 28, 2015, 8:10:56 AM2/28/15
to object-co...@googlegroups.com
On 2/28/15 1:57 AM, James O Coplien wrote:
Technically the role methods still exist on the object until the role is unbound (or at least that's the illusion) even if the execution flow returns to the environment or moves to another Context.

"Technically." Powerful word. Dangerous word. So: do they exist or not?
"Technically" wasn't the best word choice - I didn't mean it in the sense of what's happening at a technological level but just to point out a subtlety...In current injectionless DCI implementations, speaking at the technical level, role methods simply do not exist at all outside the context. However, in my mental model of DCI, role methods do exist on the role player until the role is unbound, even if they're not accessible to be called at a particular moment in time (as long as it's a moment in time before the role is unbound, obviously). I think we agree on that. I think where we differ is that I don't find name collisions to be necessarily (100% of the time) confusing: the Context acts as a sort of contextualizing/namespacing which clarifies it for me mentally.

But they're inaccessible from outside the Context to which the role(s) belong, so from a practical standpoint it's as though they don't exist anywhere else.


So let's explore this in detail. If I have access to the object through a MOP, does the MOP carry any information about the presence of this method? That is, is the "as if they don't exist" air-tight and intended for cooperative communicating programmers, or are they an inviolate guarantees?
Do you mean MOP as in Meta Object Protocol? I'm not familiar with that in particular but I know it has to do with reflection. I'm certainly interested in reflection capabilities for DCI (which has influenced some of the choices I've made with tyepscript-dci). In my ideal vision, if you ask the reflection tool what methods are available on an object, it should give you a list of methods that is somehow categorized by the different roles that the object may be playing at that time, e.g.:

instanceMethods:
    i1()
    i2()

ContextA:
    RoleA:
        r1()
        r2()
    RoleB:
        r3()

ContextB:
    RoleC:
        r4()


I posted a diagram in an earlier thread that illustrates this idea:
https://groups.google.com/d/msg/object-composition/00Wr2qhkIfg/x6EoA4h85NgJ

Since all the method names are contextualized, in my mind it's OK and not necessarily confusing to allow overriding so long as the role method always takes precedence over the instance method, e.g.:

instanceMethods:
    i1()
    i2()

ContextA:
    RoleA:
        i1()
        r2()
    RoleB:
        r3()

ContextB:
    RoleC:
        i1()
        r3()

Matthew Browne

unread,
Feb 28, 2015, 8:22:01 AM2/28/15
to object-co...@googlegroups.com
On 2/28/15 2:24 AM, Risto Välimäki wrote:
But I agree that you are also safe by disallowing all the name clashes that is:

1. There should be exactly one role method of the same signature. That is, if you have already method foo() in Bar context, you are not able to have context Baz with method foo().

2. There should be never role method called foo() given that any of possible role players has instance method foo() defined on their class abstraction.

For real, big applications I see this seriously limiting and resulting not only overly verbose, but also long or randomly prefixed methods. One possibility is of course use the context name as a prefix, but in my opinion, this is not neat at all. Yet I admit that I could live with this limitation, if there was no other alternative over this. But as said, there is a way over the hill, and I would rather take that way than feel myself being on prison.
+1. This is the point I've been trying to make.

To take the English language analogy again, the verb "walk" applies both to humans and to many other animals, but humans walk upright whereas other mammals walk on all fours. We wouldn't say "I human-walked to the door and when I opened it, my dog dog-walked toward me." The verb has a slightly different meaning depending on the noun; there's no need to come up with new verb names all the time, because the verb-noun pairing distinguishes the meaning. And of course there are plenty of cases where the context changes the meaning of the verb much more dramatically than that. Since this happens in natural language, it also happens in use case descriptions. So if our goal is to translate use case steps and role behavior from the mental model to methods in the code, it will sometimes be more natural and easier to understand if role methods are allowed to override instance methods.

Hai Quang Kim

unread,
Feb 28, 2015, 9:33:56 AM2/28/15
to object-co...@googlegroups.com
hi Trygve,

after thinking more about this, I feel the forwarding step may be dangerous.

There are 2 contracts:
- between Role and RolePlayer
- between RoleA and RoleB

If RoleA calls RoleB's Role Method (toString for example)
And We haven't implemented that Role Method yet.
The we should get a compiling error, if we just forward that call to the RolePlayer's instance method, we may get unexpected behavior, imo.

/quang


On Saturday, February 28, 2015 at 6:48:05 PM UTC+8, trygve wrote:
My answer is Yes we should. As I say at length in a recent post, my SqueakContext has two words for identifying the roleplayer. A message sent to 'self' goes directly to the roleplayer. A message sent to <ROLENAME> is intercepted at the input. A role method is executed if it exists, otherwise the message is forwarded to the roleplayer.


On 27.02.2015 05:32, Hai Quang Kim wrote:
I have this question while working on the interaction diagram.
I saw 2 kind of interaction links from one Role to another Role: from Role Method to Role Method, from Role Method to Data Object Method

example:

Role A:
   Role Method X()
       RoleB.RoleMethod Y()    // this is OK
       RoleB.DataObjectMethodXYZ() // is this OK?

Role B:
   Role Method Y()
   
DataObjectB:
      DataObjectMethodXYZ();

I think if we restrict this then the Role A should know RoleB's RoleMethod, but we have more Role Method as wrapper just for calling Data Object's method.
If we don't the Role A will know all kind of method from Role B which makes the Role Concept not very clear:
- what Role B can do with Data Object B can be done by Role A as well.

/quang
--
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-composition+unsub...@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.

Rune Funch Søltoft

unread,
Feb 28, 2015, 10:59:39 AM2/28/15
to object-co...@googlegroups.com
And to me that makes quite a difference. The context is responsible for picking suitable players that fulfill the requirements and worrying about how the object acquired method doesn't sound awfully object oriented but rather more class oriented

--
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.

Trygve Reenskaug

unread,
Feb 28, 2015, 12:28:16 PM2/28/15
to object-co...@googlegroups.com
Comment below.

On 28.02.2015 16:59, Rune Funch Søltoft wrote:

Den 28/02/2015 kl. 13.09 skrev Trygve Reenskaug <try...@ifi.uio.no>:


On 28.02.2015 12:21, Rune Funch Søltoft wrote:

Den 28/02/2015 kl. 11.54 skrev Trygve Reenskaug <try...@ifi.uio.no>:

RoleB's choice of roleplayer
Last time I look the context was responsible for choosing role player for both A and B --
You are right. I should have phrased it differently.

And to me that makes quite a difference. The context is responsible for picking suitable players that fulfill the requirements and worrying about how the object acquired method doesn't sound awfully object oriented but rather more class oriented
Of course. That's what I agreed on. Here's a rephrase:

It doesn't make sense for RoleA to call RoleB's object's method because it breaks the encapsulation of roles. RoleA shouldn't be aware of RoleB's roleplayer or how the context has chosen it.


Matthew Browne

unread,
Feb 28, 2015, 6:01:32 PM2/28/15
to object-co...@googlegroups.com
Since you want to restrict it so that roles can only call instance methods in their own role-object contract, I'd recommend that you use Andreas's approach and do it like this:

role SourceAccount:
    //role-object contract
    Account {
        function decreaseBalance(a : Int) : Void;
    }
{
    function withdraw() : Void {
        self.decreaseBalance(amount);
        DestinationAccount.deposit();
    }
}

role DestinationAccount:
    //role-object contract
    Account {
        function increaseBalance(a : Int) : Void;
    }
{
    function deposit() : Void {
        self.increaseBalance(amount);
    }
}


And of course your implementation would need to throw an error if the programer tried to call DestinationAccount.increaseBalance() from outside of the DestinationAccount role.

Personally I think it should be allowed (as I have been arguing) rather than throwing an error, but I haven't fully made up my mind yet (I'll reply separately to Trygve's latest post about that).

As to your other point about feeling the need to expose more instance methods than you'd like to (and more than you would in class-based programming), can you give an example? If a role method needs to call an instance method in order to do its work, then shouldn't that instance method be public anyway? What is it that a role needs to do that requires defining the object's public interface differently than you ordinarily would?
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/Zc-aVmFpIgA/unsubscribe.
To unsubscribe from this group and all its topics, send an email to object-composit...@googlegroups.com.

Matthew Browne

unread,
Feb 28, 2015, 6:11:25 PM2/28/15
to object-co...@googlegroups.com
Doesn't the fact that RoleB has been bound to a roleplayer already tell you what instance methods are available when calling RoleB (assuming the presence of a role-object contract)? Why do you regard this as information that's only known inside RoleB? It's not like the role-object contract can change over time for different roleplayers; the whole point of the contract is that you know that every roleplayer of RoleB is guaranteed to have those methods.

Hai Quang Kim

unread,
Feb 28, 2015, 8:26:33 PM2/28/15
to object-co...@googlegroups.com
I realize that this is just small matter from old OOP.
C#, c++ have public, protected, private.
javascript has no protected.
python has only public:.
So I just want more control to specify the contract.

my example may not be the best:

Account
{
    void addMoney(amount)
    void removeMoney(amount)
}

SourceAccount:Withdraw()
       self.removeMoney()
       Log()

SourceAccount:transfer
    self.Withdraw(amount)
    DestAccount.addMoney (amount)  <------ Wrong call but it works. I am calling wrong function and miss the log. If we have the 'Rule', I should get error here and need to change the code.

DestAccount:Deposit
   self.removeMoney()
   Log("................") 

anyway, like I said it is just a small matter.

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

Hai Quang Kim

unread,
Feb 28, 2015, 8:41:13 PM2/28/15
to object-co...@googlegroups.com
I actually have this problem a few times.
1-I work on a use case
2-I just need to call DestAccount.removeMoney (no need for Log yet)
3- I do this for 10 places
4- User changes the usecase, we need to Log the info when removing money
5-I add Deposit RoleMethod ( removemoney + Log)
6-I need to find and replace 10 places to use Deposit (but maybe not all need to be changed)
7-I may miss a few places and code still work with a few bugs (missing Log)

Having the 'Rule' just to reinforce the contract from Role to Role , and then Role to RolePlayer.
(Enter the main gate first, then go through doors)

Again, I am just looking for the need to do this, not really a big deal for DCI.
/quang

Rune Funch Søltoft

unread,
Mar 1, 2015, 7:59:41 AM3/1/15
to object-co...@googlegroups.com

Den 28/02/2015 kl. 18.28 skrev Trygve Reenskaug <try...@ifi.uio.no>:

Comment below.
On 28.02.2015 16:59, Rune Funch Søltoft wrote:

Den 28/02/2015 kl. 13.09 skrev Trygve Reenskaug <try...@ifi.uio.no>:


On 28.02.2015 12:21, Rune Funch Søltoft wrote:

Den 28/02/2015 kl. 11.54 skrev Trygve Reenskaug <try...@ifi.uio.no>:

RoleB's choice of roleplayer
Last time I look the context was responsible for choosing role player for both A and B --
You are right. I should have phrased it differently.

To me that suggests that either A can't interact with B which I'm pretty sure is not the intention or that we are to substitute class thinking with role thinking ie we should think of object only in terms of the role it is playing.





And to me that makes quite a difference. The context is responsible for picking suitable players that fulfill the requirements and worrying about how the object acquired method doesn't sound awfully object oriented but rather more class oriented
Of course. That's what I agreed on. Here's a rephrase:

It doesn't make sense for RoleA to call RoleB's object's method because it breaks the encapsulation of roles. RoleA shouldn't be aware of RoleB's roleplayer or how the context has chosen it.


James O Coplien

unread,
Mar 1, 2015, 6:50:16 PM3/1/15
to object-co...@googlegroups.com
An object may have many names. Some of those names can be roles; others may be other  "ordinary" identifiers. I trust that DCI still allows both, even within a Context.

During Context initialisation we create an object which can be addressed through an instance member of that context, named G. The rebind method associates the object named G with a role, R.

I presume that a Role method can refer to any member of the enclosing Context. In this example G is not a role but is accessible in the enclosing Context.

Is there a tacit DCI restriction that the only object identifiers that can be used within a Context are Role identifiers? If so, is there any implementation in the world which enforces that restriction? That approach seems to change object identifiers into pretty heavy-weight building blocks. I often criticise Java based on a metric that I commonly use to judge programming languages: how many bytes of source code in the minimal Hello World? In this case I'd ask: How many bytes of code in the minimal "variable declaration"?

If this isn't the case then we have violation of object encapsulation right off the bat. (There are slightly more complex examples which also violate object encapsulation, the most easy of which to demonstrate involve multiple Contexts. The solution is computably beyond the power of a Turing machine so I don't see hope of solving it in my lifetime... All we can do with rules like this (to limit object addressing to Roles within a Context) is to knock off a few of the countably infinite ways in which object encapsulation can be violated.)

The most commonly used concept in a programming language should, following longstanding principles of linguistics, be minimal. In OO it's ID binding and method invocation.

Some other role S both invokes R's methods

Hai Quang Kim

unread,
Mar 1, 2015, 9:14:30 PM3/1/15
to object-co...@googlegroups.com
"longstanding principles of linguistics, be minimal"

Thanks for this very good point.

/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,
Mar 1, 2015, 11:42:03 PM3/1/15
to object-co...@googlegroups.com

On 02 Mar 2015, at 11:14, Hai Quang Kim <wan...@gmail.com> wrote:

"longstanding principles of linguistics, be minimal"

Thanks for this very good point.

More explicitly:

The most frequently used words in a language are usually the shortest words. So if you find a very short word in a language you usually know that it's culturally important. For example, "ice" in Malagasy is "ranomandry" whereas it's "ís" in Icelandic. You need to apply information theory to translate data into information, even at this lexical level, and to estimate how much information is in a given word. For efficiency, frequent memes of information transfer should be short. It's all a matter of contextualisation., in the deepest sense of the word context.

Matthew Browne

unread,
Mar 2, 2015, 8:43:15 AM3/2/15
to object-co...@googlegroups.com
Another interesting fact: there are often more different words for subtle variations of the same thing if that thing is prominent in a given culture. For example, there's a dialect of Inuit that has about 50 words for snow:
http://www.washingtonpost.com/national/health-science/there-really-are-50-eskimo-words-for-snow/2013/01/14/e0e3f4e0-59a0-11e2-beee-6e38f5215402_story.html

Regrettably, in the English language (I'm speaking from the perspective of living in the U.S.) there are a lot of words for "fat", haha (funny and not funny at the same time)...

James O Coplien

unread,
Mar 2, 2015, 7:00:46 PM3/2/15
to object-co...@googlegroups.com

On 02 Mar 2015, at 22:43, Matthew Browne <mbro...@gmail.com> wrote:

For example, there's a dialect of Inuit that has about 50 words for snow:

Well... yes and no. The "word" structure was imposed by Western linguists (and Boas wasn't even acting as an anthropologist in his "research" behind this myth — more as a tourist — let alone as a linguist), so it may be more appropriate to say that there are 50 phrases for snow. Inuit doesn't sharply delineate between words and phrases. I daresay that such a number compares favourably with Danish or with the union of regional and vernacular words in American English.

There is also a slight problem with cultural relativism in this comparison. It may be better to say that they have 50 words for "particulate frozen water," one of which is archetypical English-language "snow."

In that vein, it's kind of like saying that computer scientists have 100 ways to say "X" where "X" comprises the four primitive operations of a Turing machine. All of computing can be reduced to less than a handful of verbs. So all constructs of all computing languages can be reduced to less than 10, and they are all formally equivalent. No one would say that these constructs should be interpreted (hermenuetics) in the same way. Whether they mean the same thing (semantics) is a matter of minor debate about contextualisation. In epistemology and hermeneutics, contextualisation is everything.

Word length as a measure applies in an almost entirely uncontextualized setting, whereas meaning (as for "snow").

Context is everything...

Matthew Browne

unread,
Mar 2, 2015, 11:02:52 PM3/2/15
to object-co...@googlegroups.com
On 3/2/15 7:00 PM, James O Coplien wrote:

On 02 Mar 2015, at 22:43, Matthew Browne <mbro...@gmail.com> wrote:

For example, there's a dialect of Inuit that has about 50 words for snow:

Well... yes and no. The "word" structure was imposed by Western linguists (and Boas wasn't even acting as an anthropologist in his "research" behind this myth — more as a tourist — let alone as a linguist), so it may be more appropriate to say that there are 50 phrases for snow. Inuit doesn't sharply delineate between words and phrases. I daresay that such a number compares favourably with Danish or with the union of regional and vernacular words in American English.
The article I linked to says that although Boas's claims have often been regarded as a myth, it's actually true that the Inuit do have many more terms for snow than most other cultures. The article also says that many of these terms were phrases rather than single words, so yes, I should have said "terms" or "phrases" rather than "words". My goal here is simply to point out what the article says in case you didn't get a chance to read it yet - I can't vouch for its accuracy, I just found it interesting.

There is also a slight problem with cultural relativism in this comparison. It may be better to say that they have 50 words for "particulate frozen water," one of which is archetypical English-language "snow."

In that vein, it's kind of like saying that computer scientists have 100 ways to say "X" where "X" comprises the four primitive operations of a Turing machine. All of computing can be reduced to less than a handful of verbs. So all constructs of all computing languages can be reduced to less than 10, and they are all formally equivalent. No one would say that these constructs should be interpreted (hermenuetics) in the same way. Whether they mean the same thing (semantics) is a matter of minor debate about contextualisation. In epistemology and hermeneutics, contextualisation is everything.

Word length as a measure applies in an almost entirely uncontextualized setting, whereas meaning (as for "snow").

Context is everything...
Indeed.

Risto Välimäki

unread,
Mar 3, 2015, 5:01:30 AM3/3/15
to object-co...@googlegroups.com
2015-03-03 2:00 GMT+02:00 James O Coplien <jcop...@gmail.com>:

On 02 Mar 2015, at 22:43, Matthew Browne <mbro...@gmail.com> wrote:

For example, there's a dialect of Inuit that has about 50 words for snow:

Well... yes and no. The "word" structure was imposed by Western linguists (and Boas wasn't even acting as an anthropologist in his "research" behind this myth — more as a tourist — let alone as a linguist), so it may be more appropriate to say that there are 50 phrases for snow. Inuit doesn't sharply delineate between words and phrases. I daresay that such a number compares favourably with Danish or with the union of regional and vernacular words in American English.

There is also a slight problem with cultural relativism in this comparison. It may be better to say that they have 50 words for "particulate frozen water," one of which is archetypical English-language "snow."

I find the number 50 actually quite low, when we are talking about Inuit people that lives most of the time around snow. I guess there has to be over 100 words for snow ("lumi") in Finnish, though most of them are synonyms on different dialects and also some of them would be unions of words in English, such as quite recent "tykkilumi" which is "snow made by snow cannon" (or "cannon-snow" as a direct translation).

Wikipedia lists some 60 examples of Finnish words for snow:

The myth continues as "Inuit people do have 50 words of different types of snow, but yet only a single word for flower", but I guess that the latter has to be just a myth.

Trust me, it's useful to have several words for snow, if you have to live with that element, since different kind of snow behave so differently under your skis, on your rooftops or when you need (or want) a quinzhee for temporary shelter.

Back to the DCI or object oriented programming, the question is how many different terms or words we should have for an object? Object, role player, enhanced object, model, POJO? I don't quite remember the terms for plain objects and enhanced objects that were used in DCI article draft.

Things in real world are much more complex than in computer sciences. That's why Inuit people possibly need all those 50 terms for snow, and we Finns need at least 20 of these. But on the other hand, I think that some 3-5 terms for object could be sufficient since you just do not need a term for Object that's just hard enough not to collapse under grown up man on his skis...

-Risto


In that vein, it's kind of like saying that computer scientists have 100 ways to say "X" where "X" comprises the four primitive operations of a Turing machine. All of computing can be reduced to less than a handful of verbs. So all constructs of all computing languages can be reduced to less than 10, and they are all formally equivalent. No one would say that these constructs should be interpreted (hermenuetics) in the same way. Whether they mean the same thing (semantics) is a matter of minor debate about contextualisation. In epistemology and hermeneutics, contextualisation is everything.

Word length as a measure applies in an almost entirely uncontextualized setting, whereas meaning (as for "snow").

Context is everything...

--
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,
Mar 3, 2015, 8:19:37 PM3/3/15
to object-co...@googlegroups.com

On 03 Mar 2015, at 19:01, Risto Välimäki <risto.v...@gmail.com> wrote:

Trust me, it's useful to have several words for snow, if you have to live with that element, since different kind of snow behave so differently under your skis, on your rooftops or when you need (or want) a quinzhee for temporary shelter.

My complaint wasn't so much with the "50" as both with the casual use of the term "word" (they are phrases) and with the cultural comparison (that suggests that Danes or American English speakers do not have 50 words for snow). Those together are used to come to a cultural-linguistic conclusion that I am not sure is supportable.

Andreas Söderlund

unread,
Mar 7, 2015, 9:33:47 PM3/7/15
to object-co...@googlegroups.com
And to me that makes quite a difference. The context is responsible for picking suitable players that fulfill the requirements and worrying about how the object acquired method doesn't sound awfully object oriented but rather more class oriented
Of course. That's what I agreed on. Here's a rephrase:

It doesn't make sense for RoleA to call RoleB's object's method because it breaks the encapsulation of roles. RoleA shouldn't be aware of RoleB's roleplayer or how the context has chosen it.

So are we at a standoff about this currently? It's quite an explicit rule that only "self" should access the RoleObjectInterface, and I'm intrigued by it since I thought that a Role type should always be RoleMethods + RoleObjectInterface. It forced me to think even harder about good method names, and put the functionality when it belongs. Or did I misunderstand something?

I went through my example code anyway and about 75% of the code is following this rule anyway. But here's a tricky one, similar to what Quang talks about. With this rule I must create a RoleMethod on destinationAccount that will have a dubious name. Deposit is already taken by the roleplayer, but what if the use case specifies "deposit"?

/Andreas

Rune Funch Søltoft

unread,
Mar 8, 2015, 1:23:05 AM3/8/15
to object-co...@googlegroups.com

Den 08/03/2015 kl. 03.33 skrev Andreas Söderlund <cisc...@gmail.com>:

And to me that makes quite a difference. The context is responsible for picking suitable players that fulfill the requirements and worrying about how the object acquired method doesn't sound awfully object oriented but rather more class oriented
Of course. That's what I agreed on. Here's a rephrase:

It doesn't make sense for RoleA to call RoleB's object's method because it breaks the encapsulation of roles. RoleA shouldn't be aware of RoleB's roleplayer or how the context has chosen it.

So are we at a standoff about this currently? It's quite an explicit rule that only "self" should access the RoleObjectInterface, and I'm intrigued by it since I thought that a Role type should always be RoleMethods + RoleObjectInterface. It forced me to think even harder about good method names, and put the functionality when it belongs. Or did I misunderstand something?

I think that the idea of not treating the objects as the objects they are but as the roles they play breaks Kay's notion of a system of interconnected systems. It is would instead of objects being connect be the roles that were connected as if roles were  some virtual wrapper around the objects. 


I went through my example code anyway and about 75% of the code is following this rule anyway. But here's a tricky one, similar to what Quang talks about. With this rule I must create a RoleMethod on destinationAccount that will have a dubious name. Deposit is already taken by the roleplayer, but what if the use case specifies "deposit"?

/Andreas

Risto Välimäki

unread,
Mar 8, 2015, 4:09:06 AM3/8/15
to object-co...@googlegroups.com
2015-03-08 8:22 GMT+02:00 Rune Funch Søltoft <funchs...@gmail.com>:

Den 08/03/2015 kl. 03.33 skrev Andreas Söderlund <cisc...@gmail.com>:

And to me that makes quite a difference. The context is responsible for picking suitable players that fulfill the requirements and worrying about how the object acquired method doesn't sound awfully object oriented but rather more class oriented
Of course. That's what I agreed on. Here's a rephrase:

It doesn't make sense for RoleA to call RoleB's object's method because it breaks the encapsulation of roles. RoleA shouldn't be aware of RoleB's roleplayer or how the context has chosen it.

So are we at a standoff about this currently? It's quite an explicit rule that only "self" should access the RoleObjectInterface, and I'm intrigued by it since I thought that a Role type should always be RoleMethods + RoleObjectInterface. It forced me to think even harder about good method names, and put the functionality when it belongs. Or did I misunderstand something?

I think that the idea of not treating the objects as the objects they are but as the roles they play breaks Kay's notion of a system of interconnected systems. It is would instead of objects being connect be the roles that were connected as if roles were  some virtual wrapper around the objects. 

I second that. I think that would be just so counterintuitive, if in the same context other objects weren't real objects, but just proxies of objects, just accessible through their respective Role Methods. Methods defined in Role contract (or role-object contract) should be available as well, since they are known in Context.


Just a note on that "self"-thing. I regard that as the greatest of misunderstandings of the history of DCI. In Smalltalk-80 there were exactly six keywords, namely: truefalsenilselfsuper, and thisContext 
So in class-abstraction Smalltalk uses "self" keyword to refer the current object itself. "Super", in other hand refers to superclass in class-abstraction. So when Trygve added the role-abstraction to enhance objects when needed, he obviously used the "self" keyword to refer the current object also in role-abstraction. Nothing mystical here. On the other hand, there is no need for "super" keyword in DCI role-abstraction, since there is no need for inheriting Role Methods and then overriding them, and thus need to access the "super role". 

To sum up above paragraph, in Smalltalk/Squeak with added DCI-support by Trygve, "self" keyword is used on both abstractions for objects: class-abstraction (~D) and role-abstractions (C & I), and in both cases it works identically: It provides access to the object itself (and therefore, naturally also access to instance and role methods, which are currently bound to that object).

When other object-oriented / class-oriented languages emerged, such as C++ and Java, for reasons unknown to me, they did not take the "self" keyword from Smalltalk, but instead introduced a new keyword "this", that means exactly the same thing. Keyword "this" refers to the object.

What happened then was that all of us Smalltalk-illiterates took Trygve's notification of "self" when referring to object from Role methods as something completely new idea, instead of just using that very same "self" from class-abstraction in role-abstraction. That resulted so that in most non-Smalltalk takes on DCI used "this" for "this" in class-abstraction, but "self" for "this" in role-abstraction. That's not just confusing but also wrong. It's really shame that we can't read Smalltalk and are not willing to take the time for learning that language to better understand Trygve's ideas.

-Risto

Matthew Browne

unread,
Mar 8, 2015, 9:01:06 AM3/8/15
to object-co...@googlegroups.com
I agree with Rune and Risto.

There are two topics being discussed on this thread:
1. Quang's original question about two roles, role A and B in the same context, and whether role A should be allowed to call role B's instance methods directly.

2. Whether to allow role methods to override or shadow instance methods -- or whether to even allow method name conflicts among different roles played by the same object.

Regarding #1, if the programmer knows enough to call a role by its name, then he/she should also be aware of its Context and the role-object contract for that role. The idea that Role B's instance methods (the ones exposed in the role-object contract) should be hidden from Role A is at best a weak illusion; and as Rune put it, it replaces class-based thinking with role-based thinking instead of object-oriented thinking.

Regarding #2, I'm currently reading the latest draft DCI paper, which says this about encapsulation on page 6:
Different objects may invoke different methods for the same message, this is called polymorphism.
Does that not suggest that 2 different roles that may be played by the same object can both have a method with the same name? I have previously explained why I think role methods should be able to override instance methods as well - and of course we also discussed the more practical point that you don't want a single small update (the addition of a new method) to a 3rd party library class to break your existing code.

(BTW, why is encapsulation a "run time property" and not a "load time property"? Not making an argument, just trying to understand that one...)
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/Zc-aVmFpIgA/unsubscribe.
To unsubscribe from this group and all its topics, send an email to object-composit...@googlegroups.com.

Matthew Browne

unread,
Mar 8, 2015, 9:21:38 AM3/8/15
to object-co...@googlegroups.com
On 3/8/15 4:09 AM, Risto Välimäki wrote:
Just a note on that "self"-thing. I regard that as the greatest of misunderstandings of the history of DCI. In Smalltalk-80 there were exactly six keywords, namely: truefalsenilselfsuper, and thisContext 
So in class-abstraction Smalltalk uses "self" keyword to refer the current object itself. "Super", in other hand refers to superclass in class-abstraction. So when Trygve added the role-abstraction to enhance objects when needed, he obviously used the "self" keyword to refer the current object also in role-abstraction. Nothing mystical here. On the other hand, there is no need for "super" keyword in DCI role-abstraction, since there is no need for inheriting Role Methods and then overriding them, and thus need to access the "super role". 

To sum up above paragraph, in Smalltalk/Squeak with added DCI-support by Trygve, "self" keyword is used on both abstractions for objects: class-abstraction (~D) and role-abstractions (C & I), and in both cases it works identically: It provides access to the object itself (and therefore, naturally also access to instance and role methods, which are currently bound to that object).

When other object-oriented / class-oriented languages emerged, such as C++ and Java, for reasons unknown to me, they did not take the "self" keyword from Smalltalk, but instead introduced a new keyword "this", that means exactly the same thing. Keyword "this" refers to the object.

What happened then was that all of us Smalltalk-illiterates took Trygve's notification of "self" when referring to object from Role methods as something completely new idea, instead of just using that very same "self" from class-abstraction in role-abstraction. That resulted so that in most non-Smalltalk takes on DCI used "this" for "this" in class-abstraction, but "self" for "this" in role-abstraction. That's not just confusing but also wrong. It's really shame that we can't read Smalltalk and are not willing to take the time for learning that language to better understand Trygve's ideas.
Although I don't know Smalltalk, this is actually the impression I already had of "self" as used in Trygve's DCI examples -- similar to how "self" in Ruby also simply refers to the current object. Cope seems to have a different take on this, and has previously said that "self" is a special role identifier in DCI pointing to the current role; I think that definition works also. I imagine that Cope and Trygve must have discussed this in the past.

In any case, your points above are why I think calling "this" should always have the same effect as calling "self", except in certain multiple inheritance scenarios in C++ where there's some ambiguity with "this".

The tricky part is what to do if we want to allow a role method to override an instance method but still be able to call the instance method. I liked Rune's suggestion of using casting to solve this, e.g.:

class List {
  addItem(item) {...}
}

//in the Context:
...
role ListRole {
  addItem(item) {
    Logger.log('Adding item...');
    (List)self.addItem(item);
  }
}


(Note: Assuming the language doesn't allow multiple inheritance, I could alternatively have used "this" instead of "self" in the above example.)

The question then becomes what to do in dynamic languages that don't support casting. If source transformation is being used to implement DCI in the first place, then perhaps the above casting syntax could be implemented just for that specific purpose. As to Javascript, I realized there's another way:

role ListRole {
  function addItem(item) {
    console.log('Adding item...');
    List.addItem.call(this, item);

    //this would also work:
    //List.addItem.call(self, item);
  }
}


I much prefer either of the syntaxes above rather than "self" and "this" having different meanings. (I'm speaking here of Javascript, C#, Java, etc. but not C++ since as I acknowledged earlier [thanks to previous posts from Cope], "this" and "self" don't have the same meaning there in the first place.)

rune funch

unread,
Mar 8, 2015, 9:47:23 AM3/8/15
to object-co...@googlegroups.com
I think in general that most of the injectionless implementation ( Trygve's being the exception) all have one thing in common. If you write an expression that evaluates to the role player and invoke a method on the result of the expression it will call an instance method. A cast expression is just a simple one which is why I said I would use that in Marvin but in maroon that wouldn't work but any other expression returning the role player would do the same trick


Matthew Browne

unread,
Mar 8, 2015, 10:34:46 AM3/8/15
to object-co...@googlegroups.com
On 3/8/15 9:47 AM, rune funch wrote:
I think in general that most of the injectionless implementation ( Trygve's being the exception) all have one thing in common. If you write an expression that evaluates to the role player and invoke a method on the result of the expression it will call an instance method.
What about when you call another role method using "self", e.g. in your money transfer example what if you called the Withdraw method using "self" instead of calling "Source" explicitly:

    role Source{
         void Withdraw(decimal amount){
             Source.DecreaseBalance(amount);
         }
         void Transfer(decimal amount){
             ...
             self.Withdraw(amount);
             ...
         }
     }


I think that should work too (as should this.Withdraw()), and in this case it's calling a role method, not an instance method.
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/Zc-aVmFpIgA/unsubscribe.
To unsubscribe from this group and all its topics, send an email to object-composit...@googlegroups.com.

James O Coplien

unread,
Mar 8, 2015, 11:10:57 AM3/8/15
to object-co...@googlegroups.com
Exactly why my original example uses "Increase Balance". "Deposit" is a use case rather than an Account operation. "Deposit" is atomic at this abstraction boundary.

This "technique" is not a DCI thing; you'll find it in the earliest CRC Card literature.


Sendt fra min iPhone

Rune Funch Søltoft

unread,
Mar 8, 2015, 2:53:11 PM3/8/15
to object-co...@googlegroups.com


> Den 08/03/2015 kl. 15.34 skrev Matthew Browne <mbro...@gmail.com>:
>
> I think that should work too
And it does. This/self and the role name is easily verifiable to refer to the role player. Any expression not an identifier that will always refer to the role player would be an NP complete problem to solve

Marc Grue

unread,
Mar 8, 2015, 2:55:29 PM3/8/15
to object-co...@googlegroups.com


On Sunday, March 8, 2015 at 2:01:06 PM UTC+1, Matthew Browne wrote:
There are two topics being discussed on this thread:
1. Quang's original question about two roles, role A and B in the same context, and whether role A should be allowed to call role B's instance methods directly.

2. Whether to allow role methods to override or shadow instance methods -- or whether to even allow method name conflicts among different roles played by the same object.

Regarding #1, if the programmer knows enough to call a role by its name, then he/she should also be aware of its Context and the role-object contract for that role. The idea that Role B's instance methods (the ones exposed in the role-object contract) should be hidden from Role A is at best a weak illusion; and as Rune put it, it replaces class-based thinking with role-based thinking instead of object-oriented thinking.

Regarding #2, I'm currently reading the latest draft DCI paper, which says this about encapsulation on page 6:
Different objects may invoke different methods for the same message, this is called polymorphism.
Does that not suggest that 2 different roles that may be played by the same object can both have a method with the same name?

Hi all,

I hope to participate a bit again here if that's ok...

The questions raised in this thread are of course very relevant to ScalaDCI too, and I'm not sure I got method resolution right. So maybe I could ask you to consider the following examples? Are they covering some of the various concerns that Matt/Quang mentions? And are the interaction outcomes matching your expectations?:

// Data class
class Obj {

  def foo = "FOO"
  def bar = "BAR"

}


// Topic #2
@context class Context2(a: Obj) {
  def resolve = a.foo
  role a {
    def foo = self.bar + a.bar // (could say `bar` instead of `a.bar`) Doesn't feel like one object, hm...
    def bar = "bar"
  }
}
new Context2(new Obj).resolve === "BARbar" // expected?


// Topic #1 (and #2)
// An object plays different roles with same role method names
@context class Context1(a: Obj) {
  // Role players:
  val A = a
  val B = a

  def resolve = A.foo + B.foo // role methods only

  role A {
    def foo = self.bar + B.bar // Can't call instance method with `B.self.bar`
  }

  role B {
    def bar = foo
    def foo = "foo"
  }
}
new Context1(new Obj).resolve === "BARfoofoo" // expected?

As you see in my comments, to call both self.bar and a.bar on the same object in Context2 seems somehow "schizophrenic" as though they were two different things. Isn't that some kind of violation of comprehensiveness? I wonder if this touches upon some of the same concerns you had in this post, Cope?

In the bigger example ("Context1" - referring to #1 that Matt listed) I tried to code the simplest case I could imagine of an object playing 2 different roles having clashing role method names. Object `a` plays both a role A and B. I'm not sure if you would consider this "at the same time" since `B.foo` is evaluated sequentially after `A.foo` at runtime (or how it's correctly put). If this is not considered an example of an object playing two roles at the "same time" I wonder what that could be, maybe a recursive Context? - I don't know. Wouldn't only multi-threading be really at "the same time" and single-thread execution always "sequential"? Well that's a whole big other question...

If we were to disallow having role methods overriding instance methods conceptually and practically in code, couldn't we then unify instance/object method calls to only RoleName.roleMethod? We could consider a "unified object" - a RolePlayer with a set of unique methods that are all accessible on the same object through the same identifier. Yes, some defined in a Data class, and some in the role definition. But we would only consider the object as one RolePlayer and not a RolePlayer with "two faces".

Couldn't we say that these "two faces" of a RolePlayer causes us to switch back and forth between two different mental models of either an object with "instance methods" or "role methods"? That seems more like class thinking to me (Data class or Role definition). The runtime object has no differentiation between instance/object methods - it simply "has methods" as far as I understand. It would be nice if our mental model and code was relieved of this "split" too if we can call it that.

Technically I could disallow role/instance name clashes in ScalaDCI either with warnings or blocking errors - if all this is desireable in some form.

It could be left optional if one would refer to the RolePlayer with RoleName, `self` or `this`, not as a references to a subset of instance methods but a "full reference" to the object. This would be quite a big departure from the current meaning of self/this, but maybe a valuable unifying one?! I'm afraid this could cause big technical challenges in some implementations, but maybe you can start viewing it from a comprehensive perspective first before considering the technical implications?

I have previously explained why I think role methods should be able to override instance methods as well - and of course we also discussed the more practical point that you don't want a single small update (the addition of a new method) to a 3rd party library class to break your existing code.

Isn't that impossible to guard against? The best you can do is to have really weird or heavily namespaced role method names... ;-)

Cheers,
Marc

Hai Quang Kim

unread,
Mar 9, 2015, 3:49:20 AM3/9/15
to object-co...@googlegroups.com
In this case the Domain(Accounting) in the Data object is different from the Domain (Bannking) of the Context, Roles...
So It is good  to have Role to communicate to Role via Role Methods (not object instance methods) to avoid mixing Domain as much as possible.

It is good to have 'Deposit' as Role method even it just wraps around the DecreaseBalance method.
That was my intention, too. But I think if we try to put it as a rule then it maybe too much :)

/quang

James O Coplien

unread,
Mar 9, 2015, 6:14:18 AM3/9/15
to object-co...@googlegroups.com

On 08 Mar 2015, at 09:09, Risto Välimäki <risto.v...@gmail.com> wrote:

What happened then was that all of us Smalltalk-illiterates took Trygve's notification of "self" when referring to object from Role methods as something completely new idea, instead of just using that very same "self" from class-abstraction in role-abstraction. 

Er, in DCI, it is a new idea — at least the way I use it.

In a role method, the word self is a role that is the name of the object playing the current role.

In an instance method, it's like this in C++-

As far as I know, Trygve's Squeak implementation of DCI has no facility for addressing this from within a Role method. I think that is hailed as a benefit rather than as a liability. One might need it if one allowed shadowing and the kind of resolution that C++ offers. I tend to believe that such collisions are a bad idea.

FWIW, I usually designate yet another Role as the name of the currently active Context object.

James O Coplien

unread,
Mar 9, 2015, 6:16:52 AM3/9/15
to object-co...@googlegroups.com

On 08 Mar 2015, at 14:01, Matthew Browne <mbro...@gmail.com> wrote:

Does that not suggest that 2 different roles that may be played by the same object can both have a method with the same name?

The JIT injectionless implementations make this possible. (It is also possible in other implementations: it's just that they do which most people (arbitrarily) consider to be "the wrong thing.") Note, then, that for any method selector m, any object playing n roles may have n + 1 methods for the method selector m.

How this aids code comprehension is beyond me.

Rune Funch Søltoft

unread,
Mar 9, 2015, 8:52:30 AM3/9/15
to object-co...@googlegroups.com
To me the key is that it's obvious from the call site which is meant. Say both role foo and bar has a role method called baz then the code for calling it would be

foo.baz()

and

bar.baz()

How one would confuse the form with the later I don't know. At compile time (when reading the code) I do not know that it will be the same object playing the role and so I lack the information required to be confused (in the debugger the name of the role is part of the name of the actually selected method)

Trygve Reenskaug

unread,
Mar 9, 2015, 10:39:00 AM3/9/15
to object-co...@googlegroups.com
'baz' doesn't mean anything to me so I prefer a concrete example:
I have a context with several roles: FILE, WINDOW, ...
I have a role method somewhere in the same context that says:
    WINDOW.open()
and
    FILE.open()

There will be no confusion because 'open' is a generic word that means the same in both cases and gets a specialized meaning from the role name.

Homonyms should be avoided not only in contexts but everywhere.

James O Coplien

unread,
Mar 9, 2015, 11:44:22 AM3/9/15
to object-co...@googlegroups.com

On 09 Mar 2015, at 13:52, Rune Funch Søltoft <funchs...@gmail.com> wrote:

How one would confuse the form with the later I don't know.

The ultimate in lack-of-confusion is to statically bind everything: to let Roles become class-like entities (and with respect to the binding question there is no distinction between classes and Roles here) and to just think in classes — instead of objects with named behaviours.

I have difficulty distinguishing such an approach from your recommendation.

James O Coplien

unread,
Mar 9, 2015, 11:58:28 AM3/9/15
to object-co...@googlegroups.com

On 09 Mar 2015, at 15:38, Trygve Reenskaug <try...@ifi.uio.no> wrote:

Homonyms should be avoided not only in contexts but everywhere.

Yes. That's my point.

If it's not enforced, it's not a rule — which is why I am taking the position to suggest that the possibility to use homonyms be defined as being outside DCI.

Trygve Reenskaug

unread,
Mar 9, 2015, 11:59:25 AM3/9/15
to object-co...@googlegroups.com
From Kay: The history of Smalltalk:
In computer terms, Smalltalk is a recursion on the notion of computer itself. Instead of dividing "computer stuff" into things each less strong than the whole--like data structures, procedures, and functions which are the usual paraphernalia of programming languages--each Smalltalk object is a recursion on the entire possibilities of the computer. Thus its semantics are a bit like having thousands and thousands of computer all hooked together by a very fast network. Questions of concrete representation can thus be postponed almost indefinitely because we are mainly concerned that the computers behave appropriately, and are interested in particular strategies only if the results are off or come back too slowly.
This definition doesn't give any details about the  communication. DCI fills in these details by specifying the interaction.

My mental model is that an object is like a computer. An object's visible interface is like a computer's instruction repertoire. A role method is a subprogram that can use its roleplayer's instruction repertoire directly through 'self'. An interaction is like a program that is composed from such subprograms. I can't see how a remote computer could could see my 'self', it must go through one of my role methods.

The Squeak implementation of a DCI Context provides two ways of accessing an object: <self> in a role method refers to the current roleplayer directly. <ROLE NAME> refers to the object as seen from the inter-object space and a message may be intercepted by a role method.
--

Trygve Reenskaug

unread,
Mar 9, 2015, 12:11:15 PM3/9/15
to object-co...@googlegroups.com
I can't see how it can be enforced. Or would you like to change my example to be acceptable to FORTRAN?
    WINDOW.open() => WINDOW.windowopen()
    FILE.open()     => FILE.fileopen()
Sounds weird to me

James O Coplien

unread,
Mar 9, 2015, 12:11:36 PM3/9/15
to object-co...@googlegroups.com

On 09 Mar 2015, at 16:59, Trygve Reenskaug <try...@ifi.uio.no> wrote:

My mental model is that an object is like a computer. 

The pins of a CPU, as well as the other interfaces to a given computer, are usually uniquely named. Several computers together may publish a collection of names which together are not unique. However, those tend to fall into two categories: subparadigmatic interfaces such as power ("hot", "return", and "ground"), and busses.

Busses are perhaps the most interesting. I think that the shadowing discussion here has many of the aspects of trying to apply bus thinking to DCI. Bus thinking is what we use for object-level polymorphism: if an interface is polymorphic, then any object exhibiting the right behaviour can be used with that interface. The interface is the bus.

DCI polymorphism tends to take place atomically in the rebind method, which sets our mind in the framework of a given network of cooperating objects with enough knowledge to be able to associate a method invocation with a unique method. Any form of polymorphism — i.e., bus-structuring — takes away that ability. That is one of the core problems of "old OO" which we are attacking with DCI: that your chances at compile time of finding where that invocation of put will end up are almost nil.

Homonyms are a form of polymorphism — of bus-structuring.

The "ultimate Kay paradigm" gives up any hope of understanding the object interaction network. His objects are bus-structured, and his metaphor is very close to that of a collection of undirected but well-intentioned humans working together in a communicating community to achieve some system goal. That's an interesting idea and perhaps is a good metaphor for the Internet, but it's not DCI.

James O Coplien

unread,
Mar 9, 2015, 12:14:24 PM3/9/15
to object-co...@googlegroups.com

On 09 Mar 2015, at 17:11, Trygve Reenskaug <try...@ifi.uio.no> wrote:

I can't see how it can be enforced.

Then it's not a rule.

The problem is less than NP-hard so it can provably be enforced. The question is whether one can enforce it in the environment at program editing time or whether it can be enforced only at run time. I think that it can be enforced by the environment in many instances; that discussion has ensued here before. If it can be enforced only at run time, that sucks — and that is the essence of the problem of bus-structuring, as per my previous mail.

Rune Funch Søltoft

unread,
Mar 9, 2015, 12:17:00 PM3/9/15
to object-co...@googlegroups.com


> Den 09/03/2015 kl. 16.44 skrev James O Coplien <jcop...@gmail.com>:
>
> I have difficulty distinguishing such an approach from your recommendation
Your argument has been that it is confusing. I claime the code that I and Trygve has posted is not confusing. Might there be other reasons. Perhaps but I don't buy that it per se is confusing

James O Coplien

unread,
Mar 9, 2015, 12:24:29 PM3/9/15
to object-co...@googlegroups.com

On 09 Mar 2015, at 17:16, Rune Funch Søltoft <funchs...@gmail.com> wrote:

Your argument has been that it is confusing.

Yes.


I claime the code that I and Trygve has posted is not confusing.

I agree that it is less confusing.

The cost is that you need twice as much information to understand each method call. The cost of your approach to solving the shadowing problem doubles cognitive load.

I could have more disciplinedly articulated my argument in terms of cognitive load. Instead, I just re-cast the argument in terms of a technology with high cognitive load: compile-time binding. DCI localises that to the rebind method to alleviate the cognitive load in the complex parts of the code (the Interactions).


Might there be other reasons. Perhaps but I don't buy that it per se is confusing

Not ipso facto confusing; just mentally taxing. That causes its own disorientation, and we're looking at mental functions broader than cognitive dissonance.

Rune Funch Søltoft

unread,
Mar 9, 2015, 12:40:52 PM3/9/15
to object-co...@googlegroups.com
And in that Line of reasoning I think we are closer to agreeing. I don't like that Marvin is role oriented and not truly object oriented. It does make the code easier to reason but there's a discrepancy between the code and the object oriented runtime
--

Marc Grue

unread,
Mar 9, 2015, 1:06:05 PM3/9/15
to object-co...@googlegroups.com
On Monday, March 9, 2015 at 5:40:52 PM UTC+1, Rune wrote:
I don't like that Marvin is role oriented and not truly object oriented. It does make the code easier to reason but there's a discrepancy between the code and the object oriented runtime

If everything was possible, how could more object oriented code look like?

James O Coplien

unread,
Mar 9, 2015, 1:15:03 PM3/9/15
to object-co...@googlegroups.com

On 09 Mar 2015, at 17:40, Rune Funch Søltoft <funchs...@gmail.com> wrote:

And in that Line of reasoning I think we are closer to agreeing. I don't like that Marvin is role oriented and not truly object oriented. It does make the code easier to reason but there's a discrepancy between the code and the object oriented runtime

Damn. Another long discussion to be had in person.

James O. Coplien

unread,
Mar 9, 2015, 1:17:56 PM3/9/15
to object-co...@googlegroups.com

On 09 Mar 2015, at 18:06, Marc Grue <marc...@gmail.com> wrote:

If everything was possible, how could more object oriented code look like?

A great poet knows that constraints are enabling. Having constraints like rhythm and rhyme means that you don't have to focus on inventing a system of rhythm and rhyme. Instead, you can focus on the important things.

So I don't think that the "if everything was possible" perspective will be terribly productive. The key is to provide the right constraints.

I am arguing for the constraint that method names not collide with each other or shadow each other.

Trygve Reenskaug

unread,
Mar 9, 2015, 1:40:02 PM3/9/15
to object-co...@googlegroups.com
I don't follow your arguments. You haven't answered if you prefer to change my simple snippet from a role method:

    WINDOW.open() => WINDOW.windowopen()
    FILE.open()     => FILE.fileopen()
Personally, I prefer the first versions. I don't see the two uses as homonyms (a word that is spelled and pronounced like another word but is different in meaning) but as two uses of the same word (open: 2a :  to make available for or active in a regular function)

James O. Coplien

unread,
Mar 9, 2015, 1:50:41 PM3/9/15
to object-co...@googlegroups.com
On 09 Mar 2015, at 18:39, Trygve Reenskaug <try...@ifi.uio.no> wrote:

I don't follow your arguments.

We may need to take this up in person. It's subtle. I think Rune now understands what I'm trying to get at — see his most recent mail. "Role-oriented" is not "object-oriented."


You haven't answered if you prefer to change my simple snippet from a role method:
    WINDOW.open() => WINDOW.windowopen()
    FILE.open()     => FILE.fileopen()
Looks like something from the Department of Redundancy Department. It reminds me of what used to disparagingly be called Hungarian Notation: a sign of an overly weak type system, for which the programmer consciously had to compensate. That's roughly what I see happening here.

I better liked your pronouncement that homonyms should be avoided.

From my perspective open is just another baz, because in reality it would likely be an instance method and hardly ever a Role method.

Marc Grue

unread,
Mar 9, 2015, 1:58:46 PM3/9/15
to object-co...@googlegroups.com
Okay. Would your constraint make "role-oriented" code more "object-oriented"? I'm not arguing against but simply trying to understand the connection to my question to Rune.

Is it possible to give an example of how role-oriented vs object-oriented thinking could manifest itself in (fictive) code even though the thinking behind carries more insight than the code itself will likely reveal?

Matthew Browne

unread,
Mar 9, 2015, 9:17:23 PM3/9/15
to object-co...@googlegroups.com
Hi Marc,
Good to have you back on the group (whether just for this discussion or for others as well)...Comments below.


On 3/8/15 2:55 PM, Marc Grue wrote:

On Sunday, March 8, 2015 at 2:01:06 PM UTC+1, Matthew Browne wrote:
There are two topics being discussed on this thread:
1. Quang's original question about two roles, role A and B in the same context, and whether role A should be allowed to call role B's instance methods directly.

2. Whether to allow role methods to override or shadow instance methods -- or whether to even allow method name conflicts among different roles played by the same object.

Regarding #1, if the programmer knows enough to call a role by its name, then he/she should also be aware of its Context and the role-object contract for that role. The idea that Role B's instance methods (the ones exposed in the role-object contract) should be hidden from Role A is at best a weak illusion; and as Rune put it, it replaces class-based thinking with role-based thinking instead of object-oriented thinking.

Regarding #2, I'm currently reading the latest draft DCI paper, which says this about encapsulation on page 6:
Different objects may invoke different methods for the same message, this is called polymorphism.
Does that not suggest that 2 different roles that may be played by the same object can both have a method with the same name?

Hi all,

I hope to participate a bit again here if that's ok...

The questions raised in this thread are of course very relevant to ScalaDCI too, and I'm not sure I got method resolution right. So maybe I could ask you to consider the following examples? Are they covering some of the various concerns that Matt/Quang mentions? And are the interaction outcomes matching your expectations?:

// Data class
class Obj {

  def foo = "FOO"
  def bar = "BAR"

}


// Topic #2
@context class Context2(a: Obj) {
  def resolve = a.foo
  role a {
    def foo = self.bar + a.bar // (could say `bar` instead of `a.bar`) Doesn't feel like one object, hm...
    def bar = "bar"
  }
}
new Context2(new Obj).resolve === "BARbar" // expected?
I would have expected this to result in "barbar". I don't think there should be any difference between 'self.bar' and 'a.bar' when inside role a. I would prefer a different mechanism to be able to explicitly call the instance method, e.g. casting to the type of the role player as Rune suggested. I also think that in ScalaDCI, calling 'this' should have the same effect as calling 'self', although I realize there are probably technical challenges with making that happen.



// Topic #1 (and #2)
// An object plays different roles with same role method names
@context class Context1(a: Obj) {
  // Role players:
  val A = a
  val B = a

  def resolve = A.foo + B.foo // role methods only

  role A {
    def foo = self.bar + B.bar // Can't call instance method with `B.self.bar`
  }

  role B {
    def bar = foo
    def foo = "foo"
  }
}
new Context1(new Obj).resolve === "BARfoofoo" // expected?
The output matches my expectation in this case, but after an earlier discussion with Rune I now think that both instance and role methods should always be prefixed by either the role name, 'self', or 'this'. Otherwise it gets confusing, because other role players can be accessed without a prefix, and in most implementations, Context methods can also be accessed without a prefix. So it's much more consistent if unprefixed variable names always refer to something in the Context, and within a role you have to use 'self' or 'this' (or use the name of the current role explicitly). Actually, having re-read Rune's earlier comment I realized it's quite relevant to this discussion so I'll quote it here:
In Marvin this is an alias for the role. Not specifying anything is accessing properties of the context (other roles usually) to access an instance method you can do several different things. All of which boils down to any expression that has the RolePlayer as the resulting value and is not the expression 'this' or 'role'. Eg assigning the RolePlayer to a variable and accessing a method on the variable would only look for instance methods. An inline cast would have the same effect. Of course this is only needed if you have a role method named the same as an instance method because in all other case you could just use the role or 'this'

On 3/8/15 2:55 PM, Marc Grue wrote:
As you see in my comments, to call both self.bar and a.bar on the same object in Context2 seems somehow "schizophrenic" as though they were two different things. Isn't that some kind of violation of comprehensiveness? I wonder if this touches upon some of the same concerns you had in this post, Cope?
If the aim is for more consistency, then I prefer using 'self', mainly because it's more succinct, especially for long role names. But I would argue that explicitly calling the role name should work too, since that should work from anywhere within the Context.


In the bigger example ("Context1" - referring to #1 that Matt listed) I tried to code the simplest case I could imagine of an object playing 2 different roles having clashing role method names. Object `a` plays both a role A and B. I'm not sure if you would consider this "at the same time" since `B.foo` is evaluated sequentially after `A.foo` at runtime (or how it's correctly put). If this is not considered an example of an object playing two roles at the "same time" I wonder what that could be, maybe a recursive Context? - I don't know. Wouldn't only multi-threading be really at "the same time" and single-thread execution always "sequential"? Well that's a whole big other question...
My understanding of "at the same time" as we've been discussing it here is an object that is bound to a first role, and then is bound to a second role that also has a method with the same name -- before the first role is unbound. The two roles might both belong to the same context, or not. Even though the role methods aren't being called at the same time, they're still both bound to the same object at the same time. That's where the potential for reduced code comprehension comes up. I think Cope may be taking that line of thinking a bit too far, but I definitely agree that such naming conflicts are potentially confusing in many cases.

If we were to disallow having role methods overriding instance methods conceptually and practically in code, couldn't we then unify instance/object method calls to only RoleName.roleMethod? We could consider a "unified object" - a RolePlayer with a set of unique methods that are all accessible on the same object through the same identifier. Yes, some defined in a Data class, and some in the role definition. But we would only consider the object as one RolePlayer and not a RolePlayer with "two faces".

Couldn't we say that these "two faces" of a RolePlayer causes us to switch back and forth between two different mental models of either an object with "instance methods" or "role methods"? That seems more like class thinking to me (Data class or Role definition). The runtime object has no differentiation between instance/object methods - it simply "has methods" as far as I understand. It would be nice if our mental model and code was relieved of this "split" too if we can call it that.

Technically I could disallow role/instance name clashes in ScalaDCI either with warnings or blocking errors - if all this is desireable in some form.

It could be left optional if one would refer to the RolePlayer with RoleName, `self` or `this`, not as a references to a subset of instance methods but a "full reference" to the object.
This is how I always thought it was supposed to work, and still do - it's just different identifiers for the same object. Object-oriented rather than class-oriented / role-oriented, as Rune has been saying.

This would be quite a big departure from the current meaning of self/this, but maybe a valuable unifying one?! I'm afraid this could cause big technical challenges in some implementations, but maybe you can start viewing it from a comprehensive perspective first before considering the technical implications?

I have previously explained why I think role methods should be able to override instance methods as well - and of course we also discussed the more practical point that you don't want a single small update (the addition of a new method) to a 3rd party library class to break your existing code.

Isn't that impossible to guard against? The best you can do is to have really weird or heavily namespaced role method names... ;-)
"Really weird or heavily namespaced role method names.." are one of the things I want to avoid, and one of the potential drawbacks I see with Cope's position.

With regard to library classes, if role methods are allowed to override instance methods, then the introduction of a new method to a library class is not a problem for existing code. The existing code can remain blissfully ignorant of the addition of the new method (assuming you don't have any current need for it).

On the other hand, if overriding is forbidden, then if you have a role method 'foo' played by a MyLibraryClass object and you upgrade to the next version of MyLibraryClass which happens to have a new method called 'foo', then it will break your existing code.

Cheers,
Marc
--
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/Zc-aVmFpIgA/unsubscribe.
To unsubscribe from this group and all its topics, send an email to object-composit...@googlegroups.com.

Hai Quang Kim

unread,
Mar 9, 2015, 9:36:47 PM3/9/15
to object-co...@googlegroups.com
I just highlight this. Because it is my original question :)
"it must go through one of my role methods."

/quang

Matthew Browne

unread,
Mar 9, 2015, 9:48:13 PM3/9/15
to object-co...@googlegroups.com
On 3/9/15 1:50 PM, James O. Coplien wrote:

On 09 Mar 2015, at 18:39, Trygve Reenskaug <try...@ifi.uio.no> wrote:

I don't follow your arguments.

We may need to take this up in person. It's subtle. I think Rune now understands what I'm trying to get at — see his most recent mail. "Role-oriented" is not "object-oriented."


You haven't answered if you prefer to change my simple snippet from a role method:
    WINDOW.open() => WINDOW.windowopen()
    FILE.open()     => FILE.fileopen()
Looks like something from the Department of Redundancy Department. It reminds me of what used to disparagingly be called Hungarian Notation: a sign of an overly weak type system, for which the programmer consciously had to compensate. That's roughly what I see happening here.
I thought the concern was only about method name conflicts among roles played by the same type of object. Is that right Cope? Presumably WINDOW and FILE would be played by different types of objects, so having an open() method in both of those roles wouldn't be a problem.

I think a better example would be something like this:

role Salesman {
    calculateSalary() {...}
}

role Engineer {
    calculateSalary() {...}
}


Both roles could be played by the same type of object, e.g. a User or Person class.

I think it would be overly limiting to say that you can't use the same method name in a case like this, especially if Salesman and Engineer are in two different Contexts. What if when you originally write your system, you only have a Salesman role? Then in order to keep the method names unique, you'd have to rename the Salesman.calculateSalary() method when you add the Engineer role. It's difficult to predict how a system is going to evolve; I prefer to keep things more flexible and I think allowing role methods to override instance methods would help in cases like this.

But the bigger issue is the possibility of a new method being added to a 3rd party library class, as we've been discussing.

BTW let's not forget that although related, we're actually discussing two different things here (actually 3 things if we go back to Quang's original question, but I'll set that aside for now)...it's possible we could reach one conclusion about method name conflicts among different roles, and a different conclusion about allowing a role method to override an instance method. Personally I think both should be allowed, but I think the discussion is getting muddied and we need to be clear.

Cope, can you explain how you would deal with the above issues and still forbid these kinds of method name conflicts?

I better liked your pronouncement that homonyms should be avoided.

From my perspective open is just another baz, because in reality it would likely be an instance method and hardly ever a Role method.
--
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/Zc-aVmFpIgA/unsubscribe.
To unsubscribe from this group and all its topics, send an email to object-composit...@googlegroups.com.

Matthew Browne

unread,
Mar 9, 2015, 10:25:38 PM3/9/15
to object-co...@googlegroups.com
On 3/9/15 9:48 PM, Matthew Browne wrote:
role Salesman {
    calculateSalary() {...}
}

role Engineer {
    calculateSalary() {...}
}


Both roles could be played by the same type of object, e.g. a User or Person class.
Or (probably more likely) an Employee class.

Marc Grue

unread,
Mar 9, 2015, 10:48:43 PM3/9/15
to object-co...@googlegroups.com


On Tuesday, March 10, 2015 at 2:17:23 AM UTC+1, Matthew Browne wrote:
Hi Marc,
Good to have you back on the group (whether just for this discussion or for others as well)...Comments below.

On 3/8/15 2:55 PM, Marc Grue wrote:
And are the interaction outcomes matching your expectations?:

// Data class
class Obj {

  def foo = "FOO"
  def bar = "BAR"

}


// Topic #2
@context class Context2(a: Obj) {
  def resolve = a.foo
  role a {
    def foo = self.bar + a.bar // (could say `bar` instead of `a.bar`) Doesn't feel like one object, hm...
    def bar = "bar"
  }
}
new Context2(new Obj).resolve === "BARbar" // expected?
I would have expected this to result in "barbar". I don't think there should be any difference between 'self.bar' and 'a.bar' when inside role a.

Wouldn't it be "BARbar" according to Trygves implementation?:

On Monday, March 9, 2015 at 4:59:25 PM UTC+1, trygve wrote:
The Squeak implementation of a DCI Context provides two ways of accessing an object: <self> in a role method refers to the current roleplayer directly. <ROLE NAME> refers to the object as seen from the inter-object space and a message may be intercepted by a role method. 

It depends on what you mean with "the current role-player directly", Trygve. I presume you mean the "instance method" on the Data class, in my example `def bar = "BAR"` in the Obj class. In this interpretation, my example should return "BARbar".

I agree though that it seems odd that 'self.bar' + 'a.bar' gives two different results! Doesn't this break the mental model of one object? Or maybe I should just see it as one object with two faces (via self/rolename)? If overriding was not allowed we would at least not have the mental tax of seeing to equally named methods returning different results. I think that's a reasonable argument to avoid/dis-allow overriding instance methods.

Wouldn't the same mental split be present if we accessed the instance method with whatever other mechanism (casting or other ways) - it would still be the object with two faces (two ways of accessing various method on it).
 
I would prefer a different mechanism to be able to explicitly call the instance method, e.g. casting to the type of the role player as Rune suggested. I also think that in ScalaDCI, calling 'this' should have the same effect as calling 'self', although I realize there are probably technical challenges with making that happen.

Oh, the technical part is easy - I allowed 'this' before and it worked exactly as 'self'. But it isn't Scala-ideomatic unless you see the role definition as an inner class which I think would lead to thinking of a Role as a class which seems the wrong direction back towards class-thinking. That's why I dis-allowed 'this' as a role-player reference.

In some ways it would generally be good to have a syntax in role definitions that didn't resembled a class definition, but rather an "object definition" however that would look like...
 


// Topic #1 (and #2)
// An object plays different roles with same role method names
@context class Context1(a: Obj) {
  // Role players:
  val A = a
  val B = a

  def resolve = A.foo + B.foo // role methods only

  role A {
    def foo = self.bar + B.bar // Can't call instance method with `B.self.bar`
  }

  role B {
    def bar = foo
    def foo = "foo"
  }
}
new Context1(new Obj).resolve === "BARfoofoo" // expected?
The output matches my expectation in this case, but after an earlier discussion with Rune I now think that both instance and role methods should always be prefixed by either the role name, 'self', or 'this'.

In Scala this is technically enforceable.
 
Otherwise it gets confusing, because other role players can be accessed without a prefix,

You mean role methods?
 
and in most implementations, Context methods can also be accessed without a prefix. So it's much more consistent if unprefixed variable names always refer to something in the Context, and within a role you have to use 'self' or 'this' (or use the name of the current role explicitly). Actually, having re-read Rune's earlier comment I realized it's quite relevant to this discussion so I'll quote it here:
In Marvin this is an alias for the role. Not specifying anything is accessing properties of the context (other roles usually) to access an instance method you can do several different things. All of which boils down to any expression that has the RolePlayer as the resulting value and is not the expression 'this' or 'role'. Eg assigning the RolePlayer to a variable and accessing a method on the variable would only look for instance methods. An inline cast would have the same effect. Of course this is only needed if you have a role method named the same as an instance method because in all other case you could just use the role or 'this'

On 3/8/15 2:55 PM, Marc Grue wrote:
As you see in my comments, to call both self.bar and a.bar on the same object in Context2 seems somehow "schizophrenic" as though they were two different things. Isn't that some kind of violation of comprehensiveness? I wonder if this touches upon some of the same concerns you had in this post, Cope?
If the aim is for more consistency, then I prefer using 'self', mainly because it's more succinct, especially for long role names. But I would argue that explicitly calling the role name should work too, since that should work from anywhere within the Context.

But you think it's okay to have two different mechanisms to access either instance or role methods? This is what I start to find troublesome mentally. I would like a RolePlayer to be one object with a unified way of accessing it and not "two different ways" that will lead to different sets of methods. The unified accessor could be RoleName, 'self', 'this' or whatever as long as there is not two different entrances into the house. I'm arguing against my current implementation... 

In the bigger example ("Context1" - referring to #1 that Matt listed) I tried to code the simplest case I could imagine of an object playing 2 different roles having clashing role method names. Object `a` plays both a role A and B. I'm not sure if you would consider this "at the same time" since `B.foo` is evaluated sequentially after `A.foo` at runtime (or how it's correctly put). If this is not considered an example of an object playing two roles at the "same time" I wonder what that could be, maybe a recursive Context? - I don't know. Wouldn't only multi-threading be really at "the same time" and single-thread execution always "sequential"? Well that's a whole big other question...
My understanding of "at the same time" as we've been discussing it here is an object that is bound to a first role, and then is bound to a second role that also has a method with the same name

Like in my example? (Both role A and B has a 'foo' role method)
 
-- before the first role is unbound.

I can't really argue precisely for it but I have a sense that there's no need to "unbound" in an injectionless implementation since role binding happens as assignments to variables (this is though another discussion).
 
The two roles might both belong to the same context, or not. Even though the role methods aren't being called at the same time, they're still both bound to the same object at the same time. That's where the potential for reduced code comprehension comes up.

Is that the case in my example would you say?
 
I think Cope may be taking that line of thinking a bit too far, but I definitely agree that such naming conflicts are potentially confusing in many cases.
If we were to disallow having role methods overriding instance methods conceptually and practically in code, couldn't we then unify instance/object method calls to only RoleName.roleMethod? We could consider a "unified object" - a RolePlayer with a set of unique methods that are all accessible on the same object through the same identifier. Yes, some defined in a Data class, and some in the role definition. But we would only consider the object as one RolePlayer and not a RolePlayer with "two faces".

Couldn't we say that these "two faces" of a RolePlayer causes us to switch back and forth between two different mental models of either an object with "instance methods" or "role methods"? That seems more like class thinking to me (Data class or Role definition). The runtime object has no differentiation between instance/object methods - it simply "has methods" as far as I understand. It would be nice if our mental model and code was relieved of this "split" too if we can call it that.

Technically I could disallow role/instance name clashes in ScalaDCI either with warnings or blocking errors - if all this is desireable in some form.

It could be left optional if one would refer to the RolePlayer with RoleName, `self` or `this`, not as a references to a subset of instance methods but a "full reference" to the object.
This is how I always thought it was supposed to work, and still do - it's just different identifiers for the same object.

I would like to see it this way also, but I'm not sure Trygve sees it like this (as per the quote above)?
 
Object-oriented rather than class-oriented / role-oriented, as Rune has been saying.
This would be quite a big departure from the current meaning of self/this, but maybe a valuable unifying one?! I'm afraid this could cause big technical challenges in some implementations, but maybe you can start viewing it from a comprehensive perspective first before considering the technical implications?

I have previously explained why I think role methods should be able to override instance methods as well - and of course we also discussed the more practical point that you don't want a single small update (the addition of a new method) to a 3rd party library class to break your existing code.

Isn't that impossible to guard against? The best you can do is to have really weird or heavily namespaced role method names... ;-)
"Really weird or heavily namespaced role method names.." are one of the things I want to avoid, and one of the potential drawbacks I see with Cope's position.

Maybe the role name is namespace enough and not too bad with regards to length (that IDE's auto-complete anyway)? Or are you asking for more/something else, Cope?
 
With regard to library classes, if role methods are allowed to override instance methods, then the introduction of a new method to a library class is not a problem for existing code. The existing code can remain blissfully ignorant of the addition of the new method (assuming you don't have any current need for it).

It would though trigger my design curiosity if the library author came up with a same-named method. Maybe he wanted the same...
 

On the other hand, if overriding is forbidden, then if you have a role method 'foo' played by a MyLibraryClass object and you upgrade to the next version of MyLibraryClass which happens to have a new method called 'foo', then it will break your existing code.

In static implementations such emerging discrepancy would simply prevent the code to compile and force one to reconsider. And if the library author introduced an instance method with the same name as our role method we would anyhow have to rethink our design in that case. Maybe the library author would have though of the same needs if the method name carried thoughtful design considerations...? I think this is less of a problem than the object with two faces.

Rune Funch Søltoft

unread,
Mar 10, 2015, 2:54:40 AM3/10/15
to object-co...@googlegroups.com


> Den 09/03/2015 kl. 18.06 skrev Marc Grue <marc...@gmail.com>:
>
> how could more object oriented code look like?
The same but the discrepancy between the form of the code and the form of the running system would be smaller

James O Coplien

unread,
Mar 10, 2015, 4:17:03 AM3/10/15
to object-co...@googlegroups.com
Marc

Great question. Let me think about this and take some time and work up a good example. I have some ideas in my head and I'll play with them to see if they pan out.


Risto Välimäki

unread,
Mar 10, 2015, 5:20:10 AM3/10/15
to object-co...@googlegroups.com
Just my two cents about this "role-oriented" / "object-oriented" issue:

1. We have concluded that "class-oriented" programming is restricted object orientation. You can quite well define what the object IS using class-abstraction (including prototypes and other possibilities). But with class-orientation you are restricted so that you cannot fully express the communication between interconnected objects. Since run time structure of a object oriented program consists of networks of intercommunicating objects, object oriented programming with only class abstraction is seriously restricted.

2. In addition to class abstraction found in restricted object oriented languages, DCI adds another abstractions, namely role abstraction and Contexts. Contexts defines those networks of interconnected objects, and the collaboration / interaction / behavior of those interconnected objects are defined using role abstraction. We can say that in role abstraction you define what objects DOES. Therefore, in contrast to restricted object oriented with only class abstraction available, class-abstraction + role-abstraction + Contexts results in full or non-restricted object orientation.

3. Object orientation exists only in heads of human people, developers, designers, users etc. In contrast, computers, CPUs, memory and other peripherals are not object-oriented by any means. Source code may be object oriented, but the running program in memory and CPU is not. It's all fake and our imagination, yet powerful as such. As long as you can write your programs object-oriented in your source code and there are no surprises on run time, your code is object oriented. As I know that's the case with Marvin (and eg. ScalaDCI), I can assure you that they are perfectly object-oriented languages.

-Risto

James O Coplien

unread,
Mar 10, 2015, 7:55:53 AM3/10/15
to object-co...@googlegroups.com

On 10 Mar 2015, at 10:20, Risto Välimäki <risto.v...@gmail.com> wrote:

Source code may be object oriented, but the running program in memory and CPU is not

Alan Kay viewed it just the other way around, I think. In that regard I tend to think of this the way I understand that Kay thinks of it.

That doesn't mean that the compile-time stuff is useless. However, the compile-time understanding should do its best to fit 1. our mental model, and 2. the run-time reality. Too much OOPSLA history is focused on useless properties of the compile-time stuff for its own sake (e.g., limiting the depth of inheritance hierarchies or the breadth of a class interface).

This is also how I understand Trygve to think but I'll let him validate that.

James O Coplien

unread,
Mar 10, 2015, 7:56:48 AM3/10/15
to object-co...@googlegroups.com
Profound.
It is loading more messages.
0 new messages