I have rocked the boat again. I have got rid of Traits. DCI gets
simpler and simpler, IMO.
Traits carried a lot of excess baggage for method injection etc. I have
replaced Traits with a class for each role, subclass of
RuntimeRole.
This class is special in many ways:
- Its methods are RoleMethods.
- Its methods are compiled in the context of a DCI Context as
described earlier.
- Its methods are executed in the context of a RolePlayer object.
(NOT an instance of the RuntimeRole)
- It shall never be subclassed.
It seems to me that we now have a fundamental extension of the notion
of object orientation that adds runtime features to the common static
features of programs. Conventionally, an object receives a message; the
corresponding method is found by searching the object's class and its
superclasses. The
RuntimeRole acts as a very dynamic
class.
A Role receives a message; the corresponding method is found
by searching the RuntimeRole followd by the object's class and its
superclasses.
Put another way, the RuntimeRole is attached at the bottom of the class
hierarchy for the purpose of method selection. This attachement is
ephemeral, it only lasts as long as it takes to select the method. This
mechanism is new and fundamental.
One of the brilliant aspects of Jim's Dijkstra algorithm is that its
recursion exposes the dynamic nature of DCI.
I have extended the Dijkstra RoleMethods with trace statements at the
beginning and end of each method. Here is the trace of an execution. It
clearly illustrates that an object can be bound to play several roles
at the same time. I have highlighted
[1756] : BB7Node >> computeDistances
{CurrentIntersection, Enter}
[1756] : BB7Node >> computeDistances {CurrentIntersection,
Leave}
to show that this single method execution can last almost from
beginning to end.
The format of each trace is
[object ID] object class >> RoleMethod selector (roleName,
Enter/Leave)
[1750] : BB7Node >> computeDistances {CurrentIntersection, Enter}
[2736] : BB7Node >> recomputeTentativeDistance {EastNeighbor,
Enter}
[1750] : BB7Node >> distanceTo: {CurrentIntersection, Enter-Leave}
[2736] : BB7Node >> recomputeTentativeDistance {EastNeighbor,
Leave}
[1756] : BB7Node >> recomputeTentativeDistance {SouthNeighbor,
Enter}
[1750] : BB7Node >> distanceTo: {CurrentIntersection, Enter-Leave}
[1756] : BB7Node >> recomputeTentativeDistance {SouthNeighbor,
Leave}
[1756] : BB7Node >> computeDistances {CurrentIntersection,
Enter}
[1210] : BB7Node >> recomputeTentativeDistance {EastNeighbor,
Enter}
[1756] : BB7Node >> distanceTo: {CurrentIntersection, Enter-Leave}
[1210] : BB7Node >> recomputeTentativeDistance {EastNeighbor,
Leave}
[3193] : BB7Node >> recomputeTentativeDistance {SouthNeighbor,
Enter}
[1756] : BB7Node >> distanceTo: {CurrentIntersection, Enter-Leave}
[3193] : BB7Node >> recomputeTentativeDistance {SouthNeighbor,
Leave}
[1210] : BB7Node >> computeDistances {CurrentIntersection, Enter}
[3139] : BB7Node >> recomputeTentativeDistance {EastNeighbor,
Enter}
[1210] : BB7Node >> distanceTo: {CurrentIntersection, Enter-Leave}
[3139] : BB7Node >> recomputeTentativeDistance {EastNeighbor,
Leave}
[2736] : BB7Node >> computeDistances {CurrentIntersection, Enter}
[3246] : BB7Node >> recomputeTentativeDistance {EastNeighbor,
Enter}
[2736] : BB7Node >> distanceTo: {CurrentIntersection, Enter-Leave}
[3246] : BB7Node >> recomputeTentativeDistance {EastNeighbor,
Leave}
[1210] : BB7Node >> recomputeTentativeDistance {SouthNeighbor,
Enter}
[2736] : BB7Node >> distanceTo: {CurrentIntersection, Enter-Leave}
[1210] : BB7Node >> recomputeTentativeDistance {SouthNeighbor,
Leave}
[3193] : BB7Node >> computeDistances {CurrentIntersection, Enter}
[3999] : BB7Node >> recomputeTentativeDistance {EastNeighbor,
Enter}
[3193] : BB7Node >> distanceTo: {CurrentIntersection, Enter-Leave}
[3999] : BB7Node >> recomputeTentativeDistance {EastNeighbor,
Leave}
[3139] : BB7Node >> computeDistances {CurrentIntersection, Enter}
[3893] : BB7Node >> recomputeTentativeDistance {SouthNeighbor,
Enter}
[3139] : BB7Node >> distanceTo: {CurrentIntersection, Enter-Leave}
[3893] : BB7Node >> recomputeTentativeDistance {SouthNeighbor,
Leave}
[3999] : BB7Node >> computeDistances {CurrentIntersection, Enter}
[3893] : BB7Node >> recomputeTentativeDistance {EastNeighbor,
Enter}
[3999] : BB7Node >> distanceTo: {CurrentIntersection, Enter-Leave}
[3893] : BB7Node >> recomputeTentativeDistance {EastNeighbor,
Leave}
[3246] : BB7Node >> computeDistances {CurrentIntersection, Enter}
[3139] : BB7Node >> recomputeTentativeDistance {SouthNeighbor,
Enter}
[3246] : BB7Node >> distanceTo: {CurrentIntersection, Enter-Leave}
[3139] : BB7Node >> recomputeTentativeDistance {SouthNeighbor,
Leave}
[3893] : BB7Node >> computeDistances {CurrentIntersection, Enter}
[3893] : BB7Node >> computeDistances {CurrentIntersection, Leave}
[3246] : BB7Node >> computeDistances {CurrentIntersection, Leave}
[3999] : BB7Node >> computeDistances {CurrentIntersection, Leave}
[3139] : BB7Node >> computeDistances {CurrentIntersection, Leave}
[3193] : BB7Node >> computeDistances {CurrentIntersection, Leave}
[2736] : BB7Node >> computeDistances {CurrentIntersection, Leave}
[1210] : BB7Node >> computeDistances {CurrentIntersection, Leave}
[1756] : BB7Node >> computeDistances {CurrentIntersection,
Leave}
[1750] : BB7Node >> computeDistances {CurrentIntersection, Leave}
'Shortest path from #a to #i in BB7ManhattanTest1 is: '
#a #d #g #h #i
My Dijkstra Squeak code is at http://fulloo.info/Examples/SqueakExamples/BB7Dijkstra/BB7Dijkstra.html