Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Language IDEs » Objectteams » Some questions on design decisions
Some questions on design decisions [message #515541] Fri, 19 February 2010 10:31 Go to next message
Eugene Hutorny is currently offline Eugene HutornyFriend
Messages: 110
Registered: January 2010
Senior Member
Hi Stephan,

I have some questions on design decisions that OT/J is based on:

1. Order of after callins
When callin methods from several roles are bound to the same based method, after callins are called in the same order as before callins. Would not it be better to have reverse order for after callins (e.g. LIFO)? The motivation behind this is the following the around callins may be used to allocate and free resources and the LIFO pattern is preferable for this case.

2. Currently the team activation mode (local/global) is determined by the team user. In my opinion, it should be an explicit decision of the team vendor. And the language shall discourage the activation mode misusage.

3. Currently it is not possible for a team to play a role of its own (Illegal base class T, is an enclosing type of R (OTJLD 2.1.2(b))). Not clear why this restriction is introduced since the team may play a role in a descendant team.
Re: Some questions on design decisions [message #515582 is a reply to message #515541] Fri, 19 February 2010 13:04 Go to previous messageGo to next message
Stephan Herrmann is currently offline Stephan HerrmannFriend
Messages: 1853
Registered: July 2009
Senior Member
Eugene Hutorny wrote on Fri, 19 February 2010 05:31

1. Order of after callins
When callin methods from several roles are bound to the same based method, after callins are called in the same order as before callins. Would not it be better to have reverse order for after callins (e.g. LIFO)? The motivation behind this is the following the around callins may be used to allocate and free resources and the LIFO pattern is preferable for this case.


If you are talking about the semantics of "precedence" than this seem to be
trac ticket 328, right?
This issue was discovered by a student working on refactorings.

Eugene Hutorny wrote on Fri, 19 February 2010 05:31

2. Currently the team activation mode (local/global) is determined by the team user. In my opinion, it should be an explicit decision of the team vendor. And the language shall discourage the activation mode misusage.


My first answer would be a no and a yes.
No, I consider team activation to a large part as a matter of system composition,
not component building. Specifically the ordering of team activation can only
be determined by the system, not the individual team.
Yes, since team activation boils down to creating an instance and
calling activate() the team can indeed implement these things in a way as
to prevent "misusage", like: if no default constructor exists, activation via
configuration file (§5.5) is not possible, if a team overrides activate(Thread)
and checks whether or not the argument is the constant ALL_THREADS it
may simply ignore bogus attempts, throw an exception etc.

By local/global activation do you refer to per-thread vs. all threads or to
explicit using activate or within vs. §5.5? Do you have an example of what
misusage you'd like to prevent?

Eugene Hutorny wrote on Fri, 19 February 2010 05:31

3. Currently it is not possible for a team to play a role of its own (Illegal base class T, is an enclosing type of R (OTJLD 2.1.2(b))).


Not sure I understand you. Something like this?
public team class MyTeam {
    protected class RoleForTeam playedBy MyTeam {
    }
}

Any reasons why not use team fields and methods instead of
fields and methods of RoleForTeam? So, yes the team can certainly
be a participant in the interaction among roles, but it needs no role for
that. And if you really prefer a separate class (for better encapsulation e.g.)
why not use an unbound role, which still has access to all team methods
via MyTeam.this.m() rather than via callout.
A role is usually a view of something outside the team. Maybe I didn't
understand your intention.

Quote:
Not clear why this restriction is introduced since the team may play a role in a descendant team.

If I understand correctly the compiler allows a situation that it should no
by intention. Again, do you have an example?

Stephan

Re: Some questions on design decisions [message #515607 is a reply to message #515582] Fri, 19 February 2010 14:19 Go to previous messageGo to next message
Eugene Hutorny is currently offline Eugene HutornyFriend
Messages: 110
Registered: January 2010
Senior Member
Stephan Herrmann wrote on Fri, 19 February 2010 08:04

If you are talking about the semantics of "precedence" than this seem to be
trac ticket 328, right?
This issue was discovered by a student working on refactorings.



Yes, that's what I meant.

Stephan Herrmann wrote on Fri, 19 February 2010 08:04

Eugene Hutorny wrote on Fri, 19 February 2010 05:31

2. Currently the team activation mode (local/global) is determined by the team user. In my opinion, it should be an explicit decision of the team vendor. And the language shall discourage the activation mode misusage.


My first answer would be a no and a yes.
No, I consider team activation to a large part as a matter of system composition,
not component building. Specifically the ordering of team activation can only
be determined by the system, not the individual team.
Yes, since team activation boils down to creating an instance and
calling activate() the team can indeed implement these things in a way as
to prevent "misusage", like: if no default constructor exists, activation via
configuration file (§5.5) is not possible, if a team overrides activate(Thread)
and checks whether or not the argument is the constant ALL_THREADS it
may simply ignore bogus attempts, throw an exception etc.



Yes, a team may block bogus attempts, but this will be runtime exception, not a compilation error.

Stephan Herrmann wrote on Fri, 19 February 2010 08:04

By local/global activation do you refer to per-thread vs. all threads or to
explicit using activate or within vs. §5.5? Do you have an example of what
misusage you'd like to prevent?



Yes, I meant per-thread vs. all threads activation.

For example there are two threads, first thread activates a team per thread, another - activates for all threads.
When the first thread deactivates the team (per thread) - would it be active for this thread?

    // 1st thread                                               2nd thread
  ateam.activate();
                                                              ateam.activate(ALL_THREADS)
  ateam.deactivate();
  // is ateam active for this thread?


Stephan Herrmann wrote on Fri, 19 February 2010 08:04

Eugene Hutorny wrote on Fri, 19 February 2010 05:31

3. Currently it is not possible for a team to play a role of its own (Illegal base class T, is an enclosing type of R (OTJLD 2.1.2(b))).


Not sure I understand you. Something like this?
public team class MyTeam {
    protected class RoleForTeam playedBy MyTeam {
    }
}

Any reasons why not use team fields and methods instead of
fields and methods of RoleForTeam? So, yes the team can certainly
be a participant in the interaction among roles, but it needs no role for
that. And if you really prefer a separate class (for better encapsulation e.g.)
why not use an unbound role, which still has access to all team methods
via MyTeam.this.m() rather than via callout.
A role is usually a view of something outside the team. Maybe I didn't
understand your intention.

Quote:
Not clear why this restriction is introduced since the team may play a role in a descendant team.

If I understand correctly the compiler allows a situation that it should no
by intention. Again, do you have an example?
Stephan



Please take a look at the example below:
// this class is needed just to overcome compiler error
public abstract team class Server {
	public abstract String respond();
}

public team class WebServer extends Server {

	public String respond() {
		return "HTTP 1.1";
	}
	protected class Maintenance playedBy Server {
		String respond() <- replace String respond();
		@SuppressWarnings("basecall")
		callin String respond() {
			return "Server is on maintenace";
		}
	}
	public void beginMaintenance() {
		activate(ALL_THREADS);
	}
	public void endMaintenance() {
		deactivate(ALL_THREADS);
	}

    server.respond();   // returns "HTTP 1.1"
    server.beginMaintenance();
    server.respond();  // returns "Server is on maintenace"
    server.endMaintenance();


If such constructions are not allowed by language design, compiler should not allow a role played by a team superclass as well, e.g. issue error on Maintenance playedBy Server.
If such construction is allowed, compiler should not complain about Maintenance playedBy WebServer.
Re: Some questions on design decisions [message #515780 is a reply to message #515607] Sat, 20 February 2010 17:39 Go to previous messageGo to next message
Stephan Herrmann is currently offline Stephan HerrmannFriend
Messages: 1853
Registered: July 2009
Senior Member
Eugene Hutorny wrote on Fri, 19 February 2010 09:19

Yes, a team may block bogus attempts, but this will be runtime exception, not a compilation error.


It certainly would be cool if the compiler could detect ill-behaving threads
in advance. Do you have any solution in mind?

Eugene Hutorny wrote on Fri, 19 February 2010 09:19

Stephan Herrmann wrote on Fri, 19 February 2010 08:04

By local/global activation do you refer to per-thread vs. all threads or to
explicit using activate or within vs. §5.5? Do you have an example of what
misusage you'd like to prevent?



Yes, I meant per-thread vs. all threads activation.

For example there are two threads, first thread activates a team per thread, another - activates for all threads.
When the first thread deactivates the team (per thread) - would it be active for this thread?

    // 1st thread                                       2nd thread
  ateam.activate();
                                                      ateam.activate(ALL_THREADS)
  ateam.deactivate();
  // is ateam active for this thread?



Well, we worked hard towards orthogonality of per-thread and global activation.
In your example each method call does as advertized, which means ateam is
not active for the 1st thread at the end of the scenario. The idea was to make
both kinds of activation harmonize rather than making one stronger than the other
(which one?).

I do believe we have every flexibility needed, and all combinations of different
activations will behave well. What you are seeking seems to be ways for
restricting the possible usages of team activation, which should be possible
to implement on top of the flexibility we have (the opposite would not work).

I still owe you an answer regarding the WebServer example (interesting!),
which I'll write up later.

Stephan
Re: Some questions on design decisions [message #515792 is a reply to message #515607] Sat, 20 February 2010 22:46 Go to previous messageGo to next message
Stephan Herrmann is currently offline Stephan HerrmannFriend
Messages: 1853
Registered: July 2009
Senior Member
Before I discuss your WebServer example I'd like to post a tiny quiz:
Assuming the following would be legal (which is not, so you can't just
try the example Wink ), what output would you expect from this program:

public team class MyTeam  {
        R theR;
        public MyTeam () {
                theR = new R();
                System.out.println(theR.toString());
        }
        protected class R playedBy MyTeam {
                protected R() {
                        base();
                }
        }
        public static void main(String[] args) {
                new MyTeam();
        }
}


?
Stephan
Re: Some questions on design decisions [message #515807 is a reply to message #515780] Sun, 21 February 2010 08:27 Go to previous messageGo to next message
Eugene Hutorny is currently offline Eugene HutornyFriend
Messages: 110
Registered: January 2010
Senior Member
Stephan Herrmann wrote on Sat, 20 February 2010 12:39

It certainly would be cool if the compiler could detect ill-behaving threads in advance. Do you have any solution in mind?



From the set of techniques you already used - declaring appropriate interface on the team class, as you did with ILowerable. It would feature the team class with an appropriate method

interface IActivatedLocally {
  void activate();
}

interface IActivatedGlobally {
  void activateForAllThreads();
}

public class team MyTeam implements IActivatedGlobally {
...
}



Although, it covers only two kinds of team activations out of four (may be five?) provided by OT/J, similar approach can be used for others.
By 4-5 provided kinds I mean: (1) within, (2) activate(), (3) activate(otherThread), (4) activate(ALL_THREADS), (5?) new Thread() { /* while ateam is activated for ALL_THREADS */ }

BTW, ILowerable creates a hole in the type - a typehole (according to my understanding of typehole model) which is then filled by the compiler. The typehole may be beneficial in many other cases, but this another topic and I'll start another thread.

Stephan Herrmann wrote on Sat, 20 February 2010 12:39

I do believe we have every flexibility needed, and all combinations of different
activations will behave well. What you are seeking seems to be ways for
restricting the possible usages of team activation, which should be possible
to implement on top of the flexibility we have (the opposite would not work).



I am not against the flexibility. I am for controlled flexibility - the team author should decide what kind of activation is allowed for this particular team.

Regards,

Eugene
Re: Some questions on design decisions [message #515808 is a reply to message #515792] Sun, 21 February 2010 08:33 Go to previous messageGo to next message
Eugene Hutorny is currently offline Eugene HutornyFriend
Messages: 110
Registered: January 2010
Senior Member
Stephan Herrmann wrote on Sat, 20 February 2010 17:46
Before I discuss your WebServer example I'd like to post a tiny quiz:
Assuming the following would be legal (which is not, so you can't just
try the example Wink ), what output would you expect from this program:



I am not sure I understand what this means:

                protected R() {
                        base();
                }


Is it a call to MyTeam constructor? MyTeam is not a superclass for R, so what is the meaning of calling constructor of a class wich is not the superclass?

To answer the quiz - I would expect stack overflow.
Re: Some questions on design decisions [message #515854 is a reply to message #515808] Sun, 21 February 2010 20:47 Go to previous messageGo to next message
Stephan Herrmann is currently offline Stephan HerrmannFriend
Messages: 1853
Registered: July 2009
Senior Member
Eugene Hutorny wrote on Sun, 21 February 2010 03:33

I am not sure I understand what this means:

                protected R() {
                        base();
                }


Is it a call to MyTeam constructor? MyTeam is not a superclass for R, so what is the meaning of calling constructor of a class wich is not the superclass?


You guess right, in analogy to a super constructor call this is a base constructor call (§2.4.2).
It is what you need if you want to instantiate a bound role but have no
base instance. In that case it's the role's responsibility to create the base, too.

Quote:

To answer the quiz - I would expect stack overflow.


Right again.
The program tries to recursively allocate an infinite number of objects.

Since you recognized the problem my point is not very strong, but the
example should demonstrate how the proposed design may create recursions
that are not perfectly obvious.

I've researched some evidence on why we added rule 2.1.2(b)
(back in March 2005).
It seems we didn't have a truly harmful example, but apparently we simply
wanted to rid ourselves of a complexity, we didn't consider worthwhile.

However, seeing your WebServer example I'm intrigued by this pattern,
so let's weigh costs vs. benefits:

Benefits
A role-playedBy-enclosing provides a very convenient way to implement
an exceptional state / mode of the enclosing object, while keeping this
solution perfectly local.

The exceptional mode does not clutter the regular behavior.

With a slight extension of the pattern one can create an arbitrary number
of modes, like:
public team class MyTeam {
   enum Mode {NORMAL, MAINTENANCE, BOOT_IN_PROGRESS};
   Mode mode;
   protected class MaintenanceMode playedBy MyTeam
      base when (MyTeam.this.mode == Mode.MAINTENANCE) { ... }
   protected class BootingMode playedBy MyTeam
      base when (MyTeam.this.mode == Mode.BOOT_IN_PROGRESS) { ... }
}

(caveat: declaring an enum inside a team currently breaks content
assist Sad - this bug is fixed in the OTDT 1.4.0 final
)
[Edited 2010-03-20]

I have never seen a cleaner implementation of objects with modes.

Costs
We don't want to trick developers into unexpected program errors:

  • Recursions are more difficult to identify
  • It's easy to forget that this kind of role can also adapt more
    team instances in addition to the enclosing.


As for the recursions it appears that these arise (and are difficult to spot)
when and because the role accesses its enclosing instance in unusual
ways, either when creating a new outer using a base constructor call,
or similarly when doing a callout to the enclosing. Thus it should be
possible to effectively warn the developer by one or two new warnings:

  • I could change 2.1.2(b) from an error into a warning, i.e., give a first
    warning whenever a role is played by its enclosing
  • Give a second - urgent - warning, if a role-playedby-enclosing issues
    a base constructor call or defines a callout. Both can be done in more
    explicit ways, so discouraging both constructs for this situation doesn't
    seem to harm.


Regarding unexpected adaptation of a non-enclosing instance of the
enclosing team class (wow, that sounds complicated..), one might recommend
using the following guard in all of these roles:
public team class MyTeam {
   protected class MaintenanceMode playedBy MyTeam
      base when (MyTeam.this == base) { ... } // only adapt this team instance
}

If a team only contains mode roles of its own self, this can be further
generalized to
public team class MyTeam
    base when (this == base) // only adapt this team instance
{ ...
}

I'd probably place this recommendation right into the OTJLD and phrase
the new warning such that it recommends to actually read this paragraph.

I'm seriously considering these changes to the OTJLD and the compiler,
because you convinced me that I was just overly anxious when defining
the rule 2.1.2(b).

Naturally, the indirection via a super team (WebServer extends Server)
should make no difference whatsoever.


Does anyone see a problem that I'm failing to see now?
Stephan

[Updated on: Sat, 20 March 2010 23:02]

Report message to a moderator

Re: Some questions on design decisions [message #515930 is a reply to message #515854] Mon, 22 February 2010 09:35 Go to previous messageGo to next message
Eugene Hutorny is currently offline Eugene HutornyFriend
Messages: 110
Registered: January 2010
Senior Member
Stephan Herrmann wrote on Sun, 21 February 2010 15:47

You guess right, in analogy to a super constructor call this is a base constructor call (§2.4.2).
It is what you need if you want to instantiate a bound role but have no
base instance. In that case it's the role's responsibility to create the base, too.



I have searched the documentation and have found no reference on ability to create a bound role without the base reference, except, of course, the §2.4.2 which does not elaborate why a call to the base constructor is needed.

Stephan Herrmann wrote on Sun, 21 February 2010 15:47

I have never seen a cleaner implementation of objects with modes.



Afterwards I have found a reference in the Kasper's work to the pattern:

Kasper Bilsted Graversen, p.96

In Graversen and Beyer (2002,p. 76-84) we proposed Internal roles as a strategy for using and implementing acquisition dispatching. A internal role model a specific state of an intrinsic



Regards,

Eugene

[Updated on: Tue, 23 February 2010 10:33]

Report message to a moderator

Re: Some questions on design decisions [message #516001 is a reply to message #515930] Mon, 22 February 2010 12:52 Go to previous messageGo to next message
Stephan Herrmann is currently offline Stephan HerrmannFriend
Messages: 1853
Registered: July 2009
Senior Member
Eugene Hutorny wrote on Mon, 22 February 2010 04:35

I have searched the documentation and have found no reference on ability to create a bound role without the base reference, except, of course, the §2.4.2 which does not elaborate why a call to the base constructor is needed.


You're right, §2.4.2(b) needs to be expanded by a short explanation.

Eugene Hutorny wrote on Mon, 22 February 2010 04:35

Afterwards I have found a reference in the Kasper's work to the pattern:

Kasper Bilsted Graversen, p.96

In Graversen and Beyer (2002,p. 7684) we proposed Internal roles as a strategy for using and implementing acquisition dispatching. A internal role model a specific state of an intrinsic




Thanks for the reference (oops, the 2002 paper doesn't have > 7000 pages!?!).
For some reason that slipped my attention, so thanks again for bringing it up.

Stephan
Re: Some questions on design decisions [message #516242 is a reply to message #516001] Tue, 23 February 2010 10:35 Go to previous messageGo to next message
Eugene Hutorny is currently offline Eugene HutornyFriend
Messages: 110
Registered: January 2010
Senior Member
Hi Stephan

Stephan Herrmann wrote on Mon, 22 February 2010 07:52


Thanks for the reference (oops, the 2002 paper doesn't have > 7000 pages!?!).
For some reason that slipped my attention, so thanks again for bringing it up.

Stephan



There was a slipped dash, I've corrected the original message - 76-84.
Re: Some questions on design decisions [message #568678 is a reply to message #515607] Sat, 20 February 2010 17:39 Go to previous messageGo to next message
Stephan Herrmann is currently offline Stephan HerrmannFriend
Messages: 1853
Registered: July 2009
Senior Member
Eugene Hutorny wrote on Fri, 19 February 2010 09:19
> Yes, a team may block bogus attempts, but this will be runtime exception, not a compilation error.

It certainly would be cool if the compiler could detect ill-behaving threads
in advance. Do you have any solution in mind?

Eugene Hutorny wrote on Fri, 19 February 2010 09:19
> Stephan Herrmann wrote on Fri, 19 February 2010 08:04
> > By local/global activation do you refer to per-thread vs. all threads or to
> > explicit using activate or within vs. §5.5? Do you have an example of what
> > misusage you'd like to prevent?
>
>
> Yes, I meant per-thread vs. all threads activation.
>
> For example there are two threads, first thread activates a team per thread, another - activates for all threads.
> When the first thread deactivates the team (per thread) - would it be active for this thread?
>
>
> // 1st thread 2nd thread
> ateam.activate();
> ateam.activate(ALL_THREADS)
> ateam.deactivate();
> // is ateam active for this thread?

Well, we worked hard towards orthogonality of per-thread and global activation.
In your example each method call does as advertized, which means ateam is
not active for the 1st thread at the end of the scenario. The idea was to make
both kinds of activation harmonize rather than making one stronger than the other
(which one?).

I do believe we have every flexibility needed, and all combinations of different
activations will behave well. What you are seeking seems to be ways for
restricting the possible usages of team activation, which should be possible
to implement on top of the flexibility we have (the opposite would not work).

I still owe you an answer regarding the WebServer example (interesting!),
which I'll write up later.

Stephan
Re: Some questions on design decisions [message #568689 is a reply to message #515607] Sat, 20 February 2010 22:46 Go to previous messageGo to next message
Stephan Herrmann is currently offline Stephan HerrmannFriend
Messages: 1853
Registered: July 2009
Senior Member
Before I discuss your WebServer example I'd like to post a tiny quiz:
Assuming the following would be legal (which is not, so you can't just
try the example ;) ), what output would you expect from this program:

public team class MyTeam {
R theR;
public MyTeam () {
theR = new R();
System.out.println(theR.toString());
}
protected class R playedBy MyTeam {
protected R() {
base();
}
}
public static void main(String[] args) {
new MyTeam();
}
}

?
Stephan
Re: Some questions on design decisions [message #568706 is a reply to message #568678] Sun, 21 February 2010 08:27 Go to previous messageGo to next message
Eugene Hutorny is currently offline Eugene HutornyFriend
Messages: 110
Registered: January 2010
Senior Member
Stephan Herrmann wrote on Sat, 20 February 2010 12:39
> It certainly would be cool if the compiler could detect ill-behaving threads in advance. Do you have any solution in mind?


From the set of techniques you already used - declaring appropriate interface on the team class, as you did with ILowerable. It would feature the team class with an appropriate method


interface IActivatedLocally {
void activate();
}

interface IActivatedGlobally {
void activateForAllThreads();
}

public class team MyTeam implements IActivatedGlobally {
...
}



Although, it covers only two kinds of team activations out of four (may be five?) provided by OT/J, similar approach can be used for others.
By 4-5 provided kinds I mean: (1) within, (2) activate(), (3) activate(otherThread), (4) activate(ALL_THREADS), (5?) new Thread() { /* while ateam is activated for ALL_THREADS */ }

BTW, ILowerable creates a hole in the type - a typehole (according to my understanding of typehole model) which is then filled by the compiler. The typehole may be beneficial in many other cases, but this another topic and I'll start another thread.

Stephan Herrmann wrote on Sat, 20 February 2010 12:39
> I do believe we have every flexibility needed, and all combinations of different
> activations will behave well. What you are seeking seems to be ways for
> restricting the possible usages of team activation, which should be possible
> to implement on top of the flexibility we have (the opposite would not work).


I am not against the flexibility. I am for controlled flexibility - the team author should decide what kind of activation is allowed for this particular team.

Regards,

Eugene
Re: Some questions on design decisions [message #568719 is a reply to message #568689] Sun, 21 February 2010 08:33 Go to previous messageGo to next message
Eugene Hutorny is currently offline Eugene HutornyFriend
Messages: 110
Registered: January 2010
Senior Member
Stephan Herrmann wrote on Sat, 20 February 2010 17:46
> Before I discuss your WebServer example I'd like to post a tiny quiz:
> Assuming the following would be legal (which is not, so you can't just
> try the example ;) ), what output would you expect from this program:


I am not sure I understand what this means:


protected R() {
base();
}


Is it a call to MyTeam constructor? MyTeam is not a superclass for R, so what is the meaning of calling constructor of a class wich is not the superclass?

To answer the quiz - I would expect stack overflow.
Re: Some questions on design decisions [message #568805 is a reply to message #568719] Sun, 21 February 2010 20:47 Go to previous messageGo to next message
Stephan Herrmann is currently offline Stephan HerrmannFriend
Messages: 1853
Registered: July 2009
Senior Member
Eugene Hutorny wrote on Sun, 21 February 2010 03:33
> I am not sure I understand what this means:
>
>
> protected R() {
> base();
> }
>
>
> Is it a call to MyTeam constructor? MyTeam is not a superclass for R, so what is the meaning of calling constructor of a class wich is not the superclass?

You guess right, in analogy to a super constructor call this is a http://www.objectteams.org/def/1.3/s2.html#s2.4.2
It is what you need if you want to instantiate a bound role but have no
base instance. In that case it's the role's responsibility to create the base, too.

Quote:
> To answer the quiz - I would expect stack overflow.

Right again.
The program tries to recursively allocate an infinite number of objects.

Since you recognized the problem my point is not very strong, but the
example should demonstrate how the proposed design may create recursions
that are not perfectly obvious.

I've researched some evidence on why we added rule 2.1.2(b)
(back in March 2005).
It seems we didn't have a truly harmful example, but apparently we simply
wanted to rid ourselves of a complexity, we didn't consider worthwhile.

However, seeing your WebServer example I'm intrigued by this pattern,
so let's weigh costs vs. benefits:

Benefits
A role-playedBy-enclosing provides a very convenient way to implement
an exceptional state / mode of the enclosing object, while keeping this
solution perfectly local.

The exceptional mode does not clutter the regular behavior.

With a slight extension of the pattern one can create an arbitrary number
of modes, like:

public team class MyTeam {
enum Mode {NORMAL, MAINTENANCE, BOOT_IN_PROGRESS};
Mode mode;
protected class MaintenanceMode playedBy MyTeam
base when (MyTeam.this.mode == Mode.MAINTENANCE) { ... }
protected class BootingMode playedBy MyTeam
base when (MyTeam.this.mode == Mode.BOOT_IN_PROGRESS) { ... }
}

(caveat: declaring an enum inside a team currently breaks content
assist :( - fixed in SVN but current release has this bug)

I have never seen a cleaner implementation of objects with modes.

Costs
We don't want to trick developers into unexpected program errors:

Recursions are more difficult to identify
It's easy to forget that this kind of role can also adapt more
team instances in addition to the enclosing.


As for the recursions it appears that these arise (and are difficult to spot)
when and because the role accesses its enclosing instance in unusual
ways, either when creating a new outer using a base constructor call,
or similarly when doing a callout to the enclosing. Thus it should be
possible to effectively warn the developer by one or two new warnings:

I could change 2.1.2(b) from an error into a warning, i.e., give a first
warning whenever a role is played by its enclosing
Give a second - urgent - warning, if a role-playedby-enclosing issues
a base constructor call or defines a callout. Both can be done in more
explicit ways, so discouraging both constructs for this situation doesn't
seem to harm.


Regarding unexpected adaptation of a non-enclosing instance of the
enclosing team class (wow, that sounds complicated..), one might recommend
using the following guard in all of these roles:
public team class MyTeam {
protected class MaintenanceMode playedBy MyTeam
base when (MyTeam.this == base) { ... } // only adapt this team instance
}
If a team only contains mode roles of its own self, this can be further
generalized to
public team class MyTeam
base when (this == base) // only adapt this team instance
{ ...
}
I'd probably place this recommendation right into the OTJLD and phrase
the new warning such that it recommends to actually read this paragraph.

I'm seriously considering these changes to the OTJLD and the compiler,
because you convinced me that I was just overly anxious when defining
the rule 2.1.2(b).

Naturally, the indirection via a super team (WebServer extends Server)
should make no difference whatsoever.


Does anyone see a problem that I'm failing to see now?
Stephan
Re: Some questions on design decisions [message #568881 is a reply to message #568805] Mon, 22 February 2010 09:35 Go to previous messageGo to next message
Eugene Hutorny is currently offline Eugene HutornyFriend
Messages: 110
Registered: January 2010
Senior Member
Stephan Herrmann wrote on Sun, 21 February 2010 15:47
> You guess right, in analogy to a super constructor call this is a base constructor call (§2.4.2).
> It is what you need if you want to instantiate a bound role but have no
> base instance. In that case it's the role's responsibility to create the base, too.


I have searched the documentation and have found no reference on ability to create a bound role without the base reference, except, of course, the http://www.objectteams.org/def/1.3/s2.html#s2.4.2 which does not elaborate why a call to the base constructor is needed.

Stephan Herrmann wrote on Sun, 21 February 2010 15:47
> I have never seen a cleaner implementation of objects with modes.


Afterwards I have found a reference in the Kasper's work to the pattern:

Kasper Bilsted Graversen, p.96
> In Graversen and Beyer (2002,p. 7684) we proposed Internal roles as a strategy for using and implementing acquisition dispatching. A internal role model a specific state of an intrinsic


Regards,

Eugene
Re: Some questions on design decisions [message #568992 is a reply to message #568881] Mon, 22 February 2010 12:52 Go to previous messageGo to next message
Stephan Herrmann is currently offline Stephan HerrmannFriend
Messages: 1853
Registered: July 2009
Senior Member
Eugene Hutorny wrote on Mon, 22 February 2010 04:35
> I have searched the documentation and have found no reference on ability to create a bound role without the base reference, except, of course, the §2.4.2 which does not elaborate why a call to the base constructor is needed.

You're right, §2.4.2(b) needs to be expanded by a short explanation.

Eugene Hutorny wrote on Mon, 22 February 2010 04:35
> Afterwards I have found a reference in the Kasper's work to the pattern:
>
> Kasper Bilsted Graversen, p.96
> > In Graversen and Beyer (2002,p. 7684) we proposed Internal roles as a strategy for using and implementing acquisition dispatching. A internal role model a specific state of an intrinsic

Thanks for the reference (oops, the 2002 paper doesn't have > 7000 pages!?!).
For some reason that slipped my attention, so thanks again for bringing it up.

Stephan
Re: Some questions on design decisions [message #569015 is a reply to message #568992] Tue, 23 February 2010 10:35 Go to previous message
Eugene Hutorny is currently offline Eugene HutornyFriend
Messages: 110
Registered: January 2010
Senior Member
Hi Stephan

Stephan Herrmann wrote on Mon, 22 February 2010 07:52
> Thanks for the reference (oops, the 2002 paper doesn't have > 7000 pages!?!).
> For some reason that slipped my attention, so thanks again for bringing it up.
>
> Stephan


There was a slipped dash, I've corrected the original message - 76-84.
Previous Topic:Fragile compilation for circularly referenced classes
Next Topic:eclipse update OTDT failed
Goto Forum:
  


Current Time: Fri Apr 19 02:26:14 GMT 2024

Powered by FUDForum. Page generated in 0.03376 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top