[Seaside] Smalltalk design advice -
howtoimplement genericbi-directional pointers?
stephane.ducasse at free.fr
Mon Dec 24 08:01:19 UTC 2007
I agree with the debuggigng pain of DNU generalized :)
I read the streamlining.... book with the intention of turning it
into a lecture.
And I realized that while I was sure that there was a value in there
I could not
squisses its essence out of it. May be I did not practice enough the
but I would have that the book was half of its size.
So your comments are confirming my gut feeling.
On 24 déc. 07, at 08:39, Ramon Leon wrote:
>> Ramon mentioned "Class Responsibility Collaborator" models,
>> or just "CRC cards" for short. That terminology is new to me
>> and the idea is pretty cool. For the uninitiated, here's a few links:
>> Bitmap scans of the actual handwritten CRC cards used in the
>> creation of "HotDraw":
>> Review of "Ecode", a CRC card design tool for Squeak:
> This is one of the best techniques I've ever picked up from anyone,
> and it's
> no accident those HotDraw CRC cards are scanned from hand written
> Ward Cunningham does the things he does for very good reasons.
> Don't use
> software to do CRC design sessions, it defeats the purpose and
> utility of
> the technique. 3x5 index cards are one of the best thinking tools
> invented, they let you design and simulate the execution of an
> object model
> in minutes and being able to quickly write, pick up, move around,
> role play,
> and discard the objects is vital to the usefulness of the technique.
> Programs and white boards aren't nearly as useful as a handful of
> cards. A little play time spent simulating several variations of
> your model
> (cards are easy to throw away) will really solidify your ideas,
> finding the
> good ones, and working through and tossing out the bad ones very
> before you've invested yourself in code. Code is much harder to
> throw away,
> you're more emotionally invested in it (which is why you don't use
> for CRC).
>> Let's talk again about the "Car" and "Tire" objects. I agree
>> with Ramon that generally a Car needs to know about the Tire
>> objects but the inverse is not important. A Tire can be
>> placed on a different car and it shouldn't care. But what
>> about a luxury car? Is that any different? Could be. The Tire
>> might want to tell the car when its air pressure is low. For
> Nope, the tire should simply announce its air pressure and make no
> assumptions about who's listening. It's more composable that way.
> I might
> have the tire rigged up to a crazy 3 wheeled trike that doesn't
> care about
> air pressure, and just because the tire can give air pressure readings
> doesn't mean it should only work on cars it was made for.
>> Ramon, maybe you can clarify. You mentioned your Tsunami
>> framework but in the same breadth alluded that we shouldn't
>> use it? Or I misunderstand. In what situations *should* we
>> use Tsunami or is it that you once felt it was necessary but
>> later learned it isn't? In the Tsunami framework it mentions
>> inspiration from the book "Streamlined Object Modeling" which
>> has examples for both Java and Squeak. Would you say this is
>> an excellent book for us new guys to read?
> It is an excellent book, one of my favorites. It goes into great
> about exactly how to maintain relationships and model rules in
> objects using a minimal set of patterns they found all rules could be
> reduced to. Every example in the book is done in both Java and
> which ends up being quite an advertisement for Squeak when you see
> just how
> terse it is compared to Java doing the same thing.
> Initially I was so enamored by the book that I adopted the patterns
> and went
> overboard, using the patterns even when they weren't necessary
> because I
> wanted consistency. Here's an example, say I have a Person class,
> I'd do
> the #name accessor like so...
> name: aName
> self testName: aName.
> set doSetName: aName.
> testName: aName
> "throw exceptions for business rule violations"
> doSetName: aName
> name := aName
> This would give me an #x, #doSetX:, #testX: pattern of methods,
> each with a
> particular purpose, the primary get/set accessors for normal use,
> delegating to #textX: and #doSetX: which separate the testing and
> setting so
> subclasses can easily override and extend them to add new rules and
> behavior, or for allowing the running or bypassing of the rules when
> necessary. I really liked how they'd thought everything out, the
> rigor of
> their model and detailed explanations of every technique.
> I extended the Squeak IDE with my own create accessors routines that
> generated all this boilerplate every time I added accessors. What
> I learned
> very quickly afterwards was all this stubbed out code, this
> scaffolding for
> rules and subclass hooks, more often than not, went unused. As my
> changed and I needed to refactor, I also realized the maintenance
> burden all
> this extra code created for me, it made things hard to change and
> hard to
> find. I'd have 10 test methods but only two or three with actual
> rules in
> them, the rest just empty stubs waiting to be used.
> I grew tired of this, figured there had to be a better way, needed
> to rid
> myself of the boilerplate code, and the need to maintain it.
> That's when I
> build Tsunami, I reified those relationships and patterns as
> runtime objects
> and hacked doesNotUnderstand to deal with all this, I'd only add testX
> methods I needed and they'd be picked up automatically, I'd get
> bi-directional references maintained automatically, I'd get
> encapsulated automatically via #addX #testAddX: #doAddX: #removeX
> #testRemoveX: #doRemoveX:, and for a time, I was happy with it.
> Later, after working with them for a while, I started to realize that
> working with purely runtime generated constructs was a royal pain
> in the ass
> (a lot of Ruby folk are find this out as well), debugging was more
> difficult, stepping through the code was more difficult, nice
> things like
> symbol completion and lookup to navigate the code didn't work so well,
> because I'd gone to far, eliminated all the code including instance
> variables and accessors in favor of runtime meta level constructs. It
> actually is possible to be too dynamic and too abstract.
> I have a strong tendency to get sucked into solving the general
> case that
> often distracts me from what I'm actually trying to accomplish (often
> because I think it's more fun). I'm learning to resist this urge,
> learned to appreciate simplicity and direct solutions much more. I
> use many of the patterns I picked up from streamlined object
> modeling, but
> only when I actually need them. I use real instance variables and
> ordinary accessors (tools work much better now), and I never stub
> things out
> ahead of time anymore. I only write code that's actually needed,
> when I
> actually need it. Stubbing boilerplate stuff out for the future is
> a big
> waste of time and gives you so much velocity in one direction that
> it makes
> change harder. Change should be easy, so write as little code as
> to achieve a desired behavior and no more.
> I used to assume bi-directional references, now I consider them an
> to the rule, something to avoided if at all possible. Direct
> flow down from parent to child, but events bubble up from child to
> That's how I see things these days anyway, who knows what I'll
> think next
> Ramon Leon
> seaside mailing list
> seaside at lists.squeakfoundation.org
More information about the seaside