"Code must be Chunkable"

On Sat, Feb 13, 2010 at 5:27 AM, Ryan D. [email protected]
wrote:

On Feb 13, 2010, at 00:42 , Michel D. wrote:

Modules are
not really objects (“everything is an object”, they say), but a way to
assign methods to objects “from outside”.

how are modules not objects? do they not have state? do they not have behavior? are they not instances of a class?

If you prick them, do they not bleed?


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: Rick DeNatale - Developer - IBM | LinkedIn

On Friday 12 February 2010 06:00:06 pm Jörg W Mittag wrote:

Unfortunately, for this dynamic role injection stuff, we run into one
of the (very few) limitations of Ruby. We cannot just, as Trygve says,
“subclass the compiler”

That’s true, although the suggestion that we do so made me a bit
uncomfortable. If you’re right, I’ll have to actually see a language
that
implements this in order to get it, if I get it even then.

But probably the most important property Ruby has is that it’s easy to
implement things that look like new syntax, but don’t actually involve
touching the parser at all.

and “add to and delete methods from the method
dictionary” in Ruby

Sure we can! We have define_method, remove_method, undef_method,
UnboundMethod, and metaclasses. Where’s the problem?

subvert the compiler like
James’s C++ template metaprogramming implementation does.

I guess it depends how much you want to do, but we also have methods
which can
accept blocks, which makes it very easy to create DSLs. We can also
define
methods on classes, or even on Class itself. Whether you consider this
“subversion” is a matter of semantics, but I didn’t really see anything
in the
talk that looked impossible, except maybe the graphical representation.

the leaky
abstraction of ECMAScript actually helps rather than hurts.

I doubt it. I think what’s much more useful is that ECMAScript has
prototypal
inheritance. If you’re talking about the fact that I can “steal” a
method from
one class and apply it to another, there is only one thing stopping this
in
Ruby, and it’s some anal-retentive type-safety thing probably leftover
from
Java or C++ – the fact that you can’t bind an UnboundMethod to anything
that’s not either a direct class or a subclass of the class that
UnboundMethod
was originally defined on.

Which just means that we can either deal purely in blocks/procs, or we
can
define “roles” as UnboundMethods on Object.

Now, I’ll grant this kind of composition is much easier in ECMAScript,
in
that we can easily rebind methods, pass them around as arguments, and
assign
them directly to objects using the [] notation. However, just about all
the
same tools exist in Ruby, they’re just clumsier to use.

On Sat, Feb 13, 2010 at 1:40 PM, Rick DeNatale [email protected]
wrote:

If you prick them, do they not bleed?


Rick DeNatale

I just read Rick’s one-liner sitting - appropriately - in the cafe/bar
of the ICA (Institute of Contemporary Arts) in London, and it’s made
my afternoon, even if I don’t get to see the Japanese film for which
I’m third on a waiting list!

On Feb 15, 4:24 am, Caleb C. [email protected] wrote:

When people say things like this, it makes me think there ought to be
a way to do it by using RubyMacros. So, I tried to rewrite Tom/Brian’s
code as macros… I think I can get rid of the need to call extend or
use method_missing/proxies. But I had to use a feature of RubyMacros
that I haven’t invented yet (motivation!) and I may be missing the
point (esp as I didn’t watch the movie). Since I don’t know if it
would even work, I’m reluctant to post the example I came up with,
but if anyone really wants to see it, I will.

Personally I think Mr. Mittag is overstating the issue. I haven’t seen
anything yet to indicate that DCI is beyond implementation in regular
Ruby. But then maybe I am misunderstanding some key elements --I would
love to know. In any case, feel free to show us your code, even if it
is just an exercise in what can be done with RubyMacros.

On 2/12/10, Jörg W Mittag [email protected] wrote:

Unfortunately, for this dynamic role injection stuff, we run into one
of the (very few) limitations of Ruby. We cannot just, as Trygve says,
“subclass the compiler” and “add to and delete methods from the method
dictionary” in Ruby (although we probably can in Rubinius) like
Trygve’s Squeak implementation does or subvert the compiler like
James’s C++ template metaprogramming implementation does.

When people say things like this, it makes me think there ought to be
a way to do it by using RubyMacros. So, I tried to rewrite Tom/Brian’s
code as macros… I think I can get rid of the need to call extend or
use method_missing/proxies. But I had to use a feature of RubyMacros
that I haven’t invented yet (motivation!) and I may be missing the
point (esp as I didn’t watch the movie). Since I don’t know if it
would even work, I’m reluctant to post the example I came up with,
but if anyone really wants to see it, I will.

On 2/15/10, Intransition [email protected] wrote:

Personally I think Mr. Mittag is overstating the issue. I haven’t seen
anything yet to indicate that DCI is beyond implementation in regular
Ruby. But then maybe I am misunderstanding some key elements --I would
love to know. In any case, feel free to show us your code, even if it
is just an exercise in what can be done with RubyMacros.

Since writing that, it occurred to me that the same effect could be
achieved with regular old eval. There’s always an eval equivalent to
any use of macros, but in this case the result is actually pretty
clean. So, here’s my eval-based version: dci2.rb · GitHub

What I did differently: creation of the context subclass I consigned
to a utility method, since that appears to be boilerplate code. The
role class has disappeared entirely, replaced by hashes. The result is
less orthodox than the classes-and-modules approach used by brian and
yourself… but I think the minimal amount of code that users of this
context library have to write is particularly nice. I may have made
too many static assumptions, such as:

Balance::Transfer#transfer always just calls #transfer on its child
Roles

Those roles in turn simply forward the #transfer message to some
other method(s)
(increaseBalance and decreaseBalance in this case)

Please let me know what you think of this.

Caleb C. wrote:

Those roles in turn simply forward the #transfer message to some
other method(s)
(increaseBalance and decreaseBalance in this case)

Please let me know what you think of this.

I think it’s more limiting that what DCI is supposed to offer; I think
you are supposed to inject new methods into the underlying objects to
help them fulfil their roles, rather than just mapping existing ones.
That is, the role contains extra logic which in normal OOP might pollute
the model, and DCI helps separate it out.

I’ve been going through Trygve’s Gantt planner example documented in

Whilst the code appears incomplete (it relies on a base class defined
earlier in the book), and given also that I don’t grok Smalltalk, I’ve
still picked up a few things. Here is one example:

Frontloader>>frontloadFrom: startWeek
AllActivities do: [:act | act earlyStart: nil].
[ Context reselectObjectsForRoles.
Activity notNil
] whileTrue:
[ Activity earlyStart: startWeek.
Predecessors do:
[ :pred |
(pred earlyFinish > Activity earlyStart)

In the PDF, you’ll see that “AllActivities”, “Context”, “Activity” and
“Predecessors” are roles, and are underlined to highlight them - a bit
of a weakness IMO that they are not clear in the syntax.

Anyway, the Frontloader is a separate class which is (as far as I can
see) somehow ‘mixed in’ to the FrontloaderCtx context object using
roleStructure magic. But if it were a single object I think it might
look roughly like this:

class FrontloaderCtx
attr_reader :all_activities, :activity, :predecessors

def initialize(model)
@model = model
end

def reselect_objects_for_roles
@all_activities = @model.all_activities
@activity = @all_activities.find { |act|
act.early_start.nil? && !@model.predecessors_of(act).find { |pred|
pred.early_start.nil? }
}
@predecessors = @model.predecessors_for(@activity)
end

def frontload(start_week)
while (reselect_objects_for_roles, activity)

end
end
end

which is probably not too much different to how you’d write a
front-loader “controller”, except I’d be inclined to use local variables
for the ‘roles’ rather than instance variables.

However it’s clear from this that the assignment of objects to roles is
something which it intended to change during execution of a single
method, since the whole algorithm relies on
“reselect_objects_for_roles”.

I still haven’t achieved enlightenment as to what is new or different
about “DCI”. The view contexts might provide meatier examples. I did
actually start to translate the whole lot virtually line-by-line into
Ruby, but got a bit stuck on the UI side because I’ve not done any Ruby
UI programming. It’s probably possible to hook Tk in, but I don’t fully
understand what’s going on in the Smalltalk yet.

Regards,

Brian.

On 2/15/10, Brian C. [email protected] wrote:

That is, the role contains extra logic which in normal OOP might pollute
the model, and DCI helps separate it out.

So, you’re saying that this method, which I had optimized away:

class Balance::TransferDestination < Role
def transfer(amount)
increaseBalance(amount)
puts “Tranfered to account #{id} $#{amount}”
end
end

should be able to contain arbitrary amounts of logic?

Let me think about this some more. Maybe I’ll try again.

I still haven’t achieved enlightenment as to what is new or different
about “DCI”. The view contexts might provide meatier examples. I did

I have the feeling this is one of those theoretical things that seems
really complicated but once you understand it its actually quite
simple.

Caleb C. wrote:

So, you’re saying that this method, which I had optimized away:

class Balance::TransferDestination < Role
def transfer(amount)
increaseBalance(amount)
puts “Tranfered to account #{id} $#{amount}”
end
end

should be able to contain arbitrary amounts of logic?

I think so. Otherwise you end up putting all the logic about
transferring money inside the Balance object, which really should just
be a dumb model which maintains a balance.

I have the feeling this is one of those theoretical things that seems
really complicated but once you understand it its actually quite
simple.

I’ve not yet seen a clear (to me) exposition of what DCI actually
means in practice. But then I could say the same about AOP.

Then at the end, it says that an account isn’t really an object at all -
but all the previous code has shown it as a concrete object (e.g.
Account.find(id)). So an example of what an account role should look
like in code would be good.

Such code has been posted in the past on object-composition, to which
you are subscribed, Brian. You’re welcome to re-post it here.

Indeed, an Account is not an object, any more than a predecessor is an
object in the front loader example. It is a role. Remember, the D in DCI
stands for data. In architecture, we are trying to separate many things
from the data. MVC separates the data (the representation of
information) from user interaction. DCI separates use case logic from
domain logic.

The general approach to DCI is that objects should be pretty dumb. They
are just-barely-smart data, and are usually primitive. Over the years we
have been taught that objects should be smart and that their APIs should
reflect what goes on in the use cases. That creates several problems.
One problem is that rapidly changing use-case level logic is mixed in
the same interface with slowly-changing domain interfaces. Another is
that classes don’t provide natural boundaries for the delineation of
mental models of algorithms (as DCI used to call them when it was DCA)
or interactions.

An account is a collection of use cases. It is in the “I” part of DCI,
not in the “D” part. If you look at real banking software, the real
objects are transaction logs and audit trails. They become re-configured
in interactions on every use case, where the use cases are at the level
of a Context object called an account. Except for its housekeeping
references that set up the current role / instance binding at the audit
trail and transaction level, the account is stateless. Your bank account
is not a number sitting in memory or sitting on a disk somewhere,
anymore than your money is sitting in a bag on a shelf in a bank
somewhere. It is a computation: a use case. In DCI, we encapsulate those
in Contexts.

In my talk, I catered to the usual kind of example used by consultants
and university professors in talking about object-oriented programming,
where they apply the little white lie of an account being an object.
Later in the talk I introduce the concept of an account as a context.
This is a recent and rather advanced concept in DCI.

I can see from the thread below that it was too much for the posters in
this thread, and that the posters were unable to correlate that example
with the description in the Artima article. The reason this is a bit
advanced is that it comes from the design thinking that Trygve and I
have put into DCI, rather than the nerd-level stuff. It doesn’t cater to
UML-shaped heads, or even to the way that most people characterize
object-oriented programming. It is one of the more difficult ideas in
DCI, and it is the one that most people trip on. Most people have so
much trouble fitting into their mental model that they just say that it
is wrong, or stupid. It’s O.K. if you feel that way: new paradigms are
hard, and it will take a while to unlearn old ways and to learn new.

The best way is to keep in dialog and to keep trying things out. Try to
get above the code level and think about this from a design perspective
(but still with the code in the back of your mind, by all means). You’ll
hopefully get to a turning point where you see programming in a totally
different way. If you haven’t gotten to that point yet, you probably
have internalized only the nerd part of DCI. That’s a good start. But as
one poster here said: it’s not about traits, it’s not about injection,
and it’s not about aspects, but about something higher level. It’s about
thinking in objects while being able to separate the algorithm into
something manageable and understandable.

I did a couple of interesting things (though I suppose I may be taking
it too far) I thought of a Context as a Scene in a play, in which I
defined the roles upfront (ie. at the class level) – I use the Anise
gem to do this, btw. And, despite what was said in the lecture, I was
able to use polymorphism with regard to the roles. This approach seems
very interesting. I was able to define two methods of the same name
that can act on the same object, but dependent on the role it plays.
Thus the Context has a method that is dispatched to all the roles.
While my code is from perfect the approach itself does seem like it
could be useful for large applications. (It feels like overkill for
small libraries though).

Right! This is the metaphor we often have been using. More precisely,
the Context is a combination of the script (which is in the roles within
its scope) and the casting (the dynamic mapping of roles to
objects/actors).

I in fact have been working on a DCI pattern language based on this
metaphor, because it works so well.

Thomas S. wrote:

I just finished watching the 2nd video. I agree with you. Coplien does
an awful job of explaining things. Trygve, despite his age, does a
much better job.

Thomas, I apologize if I did not explain things well for you. To move
things forward as a community, it’s good to ask questions. I’m happy to
try to answer. Thomas, I tell people all the time that if they fail to
ask their business people for clarification about requirements but
instead cast cowardly aspersions supposedly out of earshot, that it
explains many of the problems their firms have been having in its
developments. Maybe you behave that way with your business people, but
I’d appreciate enough respect from you to address your concerns about
me, to me.

Then at the end, it says that an account isn’t really an object at all -
but all the previous code has shown it as a concrete object (e.g.
Account.find(id)). So an example of what an account role should look
like in code would be good.

I don’t know what he is talking about.

Yes, it is clear that you don’t understand what I am talking about.

It’s as if he thinks, if
something isn’t solid it isn’t an object.

No, that isn’t it. Instead of guessing, or putting words in my mouth, or
assuming, you could have asked me. I’m pretty easy to find on the web. I
have done my best in the above posting to answer your question. I do so
as a service and because I think it’s important that this community
understand the subtleties here.

And his whole speel about
logging-in is not a usecase because there’s no business goal, is silly
too.

This represents a fundamental misunderstanding of use cases. The
distinction between atomic operations on objects (the direct
manipulation metaphor) and the role of algorithms (the use case angle)
is fundamental to understanding why DCI is different from
object-oriented programming. I use the term “use case” in the Cockburn
sense, as a collection of possible scenarios. Each scenario is a
collection of interactions towards a goal. I think this definition is
consistent with Jacbosson’s more formalized use case framework. I am not
sure what you are using as your reference standard, but I would be
interested in your arguments against Cockburn’s use of the goal as a
major element that distinguishes use cases from just blah blah blah.
Words mean things, and use case is not just Swedish for scenario.

He’s splitting hairs over words and as much as he thinks DCI is
so cool, I’m not sure he actually “gets it” himself.

Can you translate that into some delineated professional feedback?

However, at the
very beginning he does point out the main point of the whole pursuit
– code readability.

His Ruby code, btw, wasn’t very well written, would not run and worse,
I don’t think represents DCI well either.

Well, my version of the code runs fine here. One takes certain liberties
with presentation in PowerPoint to a large audience to make points about
design. And the code passes Trygve’s muster as representing DCI well; we
had been corresponding intensely to nurture the ideas using this
example. But it is good to hear your input. Maybe we have found someone
here in Thomas who understands DCI better than Trygve and I do. Please
join the object-composition list, listen, learn, and contribute
positively. When you post objections in a frustrated way on this list
without engaging those you criticize, it makes me frustrated, and it
does not advance our collective understanding.

If you feel the Ruby style bears improvement I am open to suggestions.

(P.S. I also think this is much more like AOP then Coplien is willing
to admit.)

Second, I’d like to know why; and first, I’d like to know why it’s
important. Again, I think you are making the mistake that another poster
here warns about: confusing the language mechanisms with the design
ideas.

These things just take time. Keep working at it, guys, and don’t let
your preconceptions get in the way… any more.

On Feb 16, 11:41 am, James C. [email protected] wrote:

hard, and it will take a while to unlearn old ways and to learn new.
No matter how hard anew paradigms is, it must still be taught.

Hi James,

On Feb 16, 12:06 pm, James C. [email protected] wrote:

explains many of the problems their firms have been having in its
developments. Maybe you behave that way with your business people, but
I’d appreciate enough respect from you to address your concerns about
me, to me.

Honestly, James, I didn’t even think about contacting you --I didn’t
even suspect I’d be getting this deep into a conversation about it. I
was just sharing an interesting presentation, Trygve’s (in which you
do a good job in the Q & A periods, btw). I looked forward to the
second video when I understood it had a Ruby example (as you might
imagine from a Ruby ethusiast). However, while your example gave me at
least something to go on, the presentation as a whole left me more
confused and thus less enthusiastic about the whole DCI idea. I
apologize for compacting this opinion into the one word “awful”, I
suppose that is too disparaging a term, and for that I apologize. So
please accept this explanation in it’s place and take it for what it’s
worth.

something isn’t solid it isn’t an object.

No, that isn’t it. Instead of guessing, or putting words in my mouth, or
assuming, you could have asked me.

No, no. I wasn’t putting words in your mouth. I was expressing what
I was getting out of your words.

distinction between atomic operations on objects (the direct
manipulation metaphor) and the role of algorithms (the use case angle)
is fundamental to understanding why DCI is different from
object-oriented programming. I use the term “use case” in the Cockburn
sense, as a collection of possible scenarios. Each scenario is a
collection of interactions towards a goal. I think this definition is
consistent with Jacbosson’s more formalized use case framework. I am not
sure what you are using as your reference standard, but I would be
interested in your arguments against Cockburn’s use of the goal as a
major element that distinguishes use cases from just blah blah blah.
Words mean things, and use case is not just Swedish for scenario.

The definition seems fine. I just don’t see why logging-in can’t be
viewed as a goal in itself.

He’s splitting hairs over words and as much as he thinks DCI is
so cool, I’m not sure he actually “gets it” himself.

Can you translate that into some delineated professional feedback?

Ok. This is my take. DCI seems to me like an idea with a lot of
potential. But I don’t think it’s an all of nothing kind of thing. I
get the feeling that you so badly want DCI to be a Major Paradigm
Shift that you might be pushing it’s concepts too far.

For instance, to say that an account is not a not object… going all
the way back to the bad old days of COBOL, an account has always been
treated as as object, even if not coded in OOP form. That’s because
banks treat accounts as objects --people have them, they have ID
numbers, etc. Writing a banking system without the concept of an
account ignores the very system to be modeled. I’m pretty sure that
any attempt to do so will prove far less readable (exactly the
opposite of what DCI is trying to achieve) then any program that does
–even in COBOL. Moreover, when you say an account isn’t an object and
yet give a presentation where it is an object, that’s just confusing.

However, at the
very beginning he does point out the main point of the whole pursuit
– code readability.

His Ruby code, btw, wasn’t very well written, would not run and worse,
I don’t think represents DCI well either.

Well, my version of the code runs fine here.

Then please make it available!

One takes certain liberties
with presentation in PowerPoint to a large audience to make points about
design. And the code passes Trygve’s muster as representing DCI well; we
had been corresponding intensely to nurture the ideas using this
example. But it is good to hear your input. Maybe we have found someone
here in Thomas who understands DCI better than Trygve and I do. Please
join the object-composition list, listen, learn, and contribute
positively. When you post objections in a frustrated way on this list
without engaging those you criticize, it makes me frustrated, and it
does not advance our collective understanding.

Please don’t feel that I am criticizing you --take it for what it
is, my personal critique of your presentation.

If you feel the Ruby style bears improvement I am open to suggestions.

I can can certainly offer some suggestions, but I would have to
understand DCI better to go beyond the surface. I posted my take on
it, but being new to DCI, I can only guess if I am on the right track
or not.

(P.S. I also think this is much more like AOP then Coplien is willing
to admit.)

Second, I’d like to know why; and first, I’d like to know why it’s
important. Again, I think you are making the mistake that another poster
here warns about: confusing the language mechanisms with the design
ideas.

The goal of AOP is to come at a problem orthogonal to the traditional
OOP direction. In AOP you are organizing code into aspects. These
aspects are like contexts in DCI. Aspects are composed of advice, code
injected into classes/objects by wrapping other methods.
There are clear similarities. DCI goes a bit further by injecting
methods whole-clothe, and in doing so decomposes “aspects” into a
context and set of roles. (Actually that might be useful, might DCI
roles make use of AOP’s concept of advice too?)

On Feb 17, 6:31 am, Intransition [email protected] wrote:

The goal of AOP is to come at a problem orthogonal to the traditional
OOP direction. In AOP you are organizing code into aspects. These

“goal” isn’t the right word actually, more like “tactic”.

Thomas S. wrote:

No matter how hard a new paradigms is, it must still be taught.

Dear All,

Indeed !

Please do not end this very interesting discussion. Some people may be
eagerly following it without participating (at least I am).

Please do not end this very interesting discussion. Some people may be
eagerly following it without participating (at least I am).

I’ve been taking apart one of the Smalltalk examples in an attempt to
understand it and perhaps port bits of it to Ruby. Trygve himself has
been gracious in helping me through this process. You can follow the
discussion here:

http://groups.google.com/group/object-composition/browse_thread/thread/854df3a328e1c263

On 13 February 2010 19:07, David M. [email protected] wrote:

I doubt it. I think what’s much more useful is that ECMAScript has prototypal
inheritance. If you’re talking about the fact that I can “steal” a method from
one class and apply it to another, there is only one thing stopping this in
Ruby, and it’s some anal-retentive type-safety thing probably leftover from
Java or C++ – the fact that you can’t bind an UnboundMethod to anything
that’s not either a direct class or a subclass of the class that UnboundMethod
was originally defined on.

Obviously, if you unbind a method from Array which is implemented in C
you cannot rebind it to something else. This restrictions is probably
less meaningful for pure ruby methods but allowing some methods to be
rebound freely and restrict others does not sound very nice either.

Thanks

Michal

Brian C. wrote:
You can follow the

discussion here:

http://groups.google.com/group/object-composition/browse_thread/thread/854df3a328e1c263

We’ll keep both eyes open !

Thomas S. wrote:

On Feb 16, 11:41�am, James C. [email protected] wrote:

hard, and it will take a while to unlearn old ways and to learn new.
No matter how hard anew paradigms is, it must still be taught.

No. I was a professional educator for several years. One thing you find
in the theories of education is that though many things can be learned,
only some of them can be taught — in the normal Western application of
the word “teaching.”

The normal model of education, as described by educators like Piaget, is
to move from the known to the unknown. The essence of a paradigm shift,
according to Kuhn, is that the new paradigm is irreconcilable with the
old. I think that’s what we’re faced with here. As such, I think the
best way to learn is through practice.

Furthermore, I think it is better to think of DCI as a community effort
to explore a new space, working with each other, than to have the Master
“instruct” the newbies. It is true that Trygve and I have about ten
years of thought about this, and we’re happy to relate our experiences.
That’s why I’m here — to give. That’s why Trygve has published so many
reports and why we published a joint report on Artima. That’s why I have
spent the past three years writing a book on this (and related) topics.
Learning this will take hard work: don’t expect to be spoon-fed.