Exforsys

Online Training

Re: Name spaces in Dolphin...

This is a discussion on Re: Name spaces in Dolphin... within the Software Patterns forums, part of the Testing category; Blair McGlashan wrote: > I'm afraid there is a downside, and it is incompatibility. There is no one > ...


Go Back   Exforsys > Testing > Software Patterns

Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

Reply

 

LinkBack Thread Tools
  #1 (permalink)  
Old 11-06-2003, 01:29 AM
panu
 
Posts: n/a
Re: Name spaces in Dolphin...

Blair McGlashan wrote:

> I'm afraid there is a downside, and it is incompatibility. There is no one
> standard namespace system, in fact they are all different, and often not
> just in the detail. ...


There is a simple workaround for class-namespaces that
works in *every* Smalltalk (and in Java too). Before
complicating things further by adding explicit class-
namespace support to a language, consider using this
design pattern:

1. Create all your classes with a suffix.
For example I could create a new class
called 'TransformerPANU'. It is unlikely
that anyone would come up with the same
name in their designs.

2. Create a method named #Transformer in your
class(es) or superclass as:

Transformer
^TransformerPANU

3. In your code, instead of accessing the global
'TransformerPANU' directly, call:

self Transformer.


This has the added benefit (over plain namespaces)
that you now *encapsulate* the information of which
actual object will be returned by #Transformer!

Using a method-call in this manner leads to more
cohesive, flexible, reusable code than accessing
a global directly (in several places). Remember
the Trick-of-63: Globals are BAD.

The downside is that 'self Transformer' is slightly
longer than plain 'Transformer', but that's the
price you pay for better encapsulation, and for
keeping the language & code simple and compatible
with other dialects.

-Panu Viljamaa

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #2 (permalink)  
Old 11-06-2003, 07:45 AM
cstb
 
Posts: n/a
Re: Name spaces in Dolphin...



panu wrote:
>
> There is a simple workaround for class-namespaces that
> works in *every* Smalltalk (and in [explitive deleted -ed] too).
> Before complicating things further by adding explicit class-
> namespace support to a language, consider using this
> design pattern:
>
> 1. Create all your classes with a suffix.
> For example I could create a new class
> called 'TransformerPANU'. It is unlikely
> that anyone would come up with the same
> name in their designs.
>
> 2. Create a method named #Transformer in your
> class(es) or superclass as:
>
> Transformer
> ^TransformerPANU
>
> 3. In your code, instead of accessing the global
> 'TransformerPANU' directly, call:
>
> self Transformer.
>...

====


A better pattern for this is as follows.

(1) Same as above
(2) Create methods in referring class(es):

category: 'accessing class'
>>transformer

^self class transformer

category: 'collaborators'
class>>transformer
^TransformerPANU

(3) In your code, always refer to
transformer via the local method

(self transformer) selectorWhatever


---
Advantages: Encapsulates further, as client
doesn't need to know the class
side methods, and referenced object
can switch between local supplied
(instance side answers inst var)
and externally supplied
(instance side forwards to class)
without changing all the
sendersOf:

Subclasses can each independently
choose whether to override with
a locally supplied or an
externally supplied object.

Scanning the class side methods
of a class quickly informs developers
of collaborating classes, especially
useful when subclassing, copying,
or porting a class.

====
An alternate form of this pattern is:

(2') Create a mapping subclass of Object
named the same as your suffix
(in your case it would be
PANU>>
).

For each of your classNameWithSUFFIX classes,
create a mapping method:

PANU>>transformer
^TransformerPANU

and in referring classes create
this collaborator method instead:

class>>transformer
^PANU transformer

---
Advantages: Entire "extension package"
is mapped -- the mapping class
shows which classes are in the
"extension package", even when
the "extension package" is a
set of file-outs or a set
of some other deploymentForm.

Especially useful in environments
with external CMS (CVS etc).

====
Regards,

-cstb
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #3 (permalink)  
Old 11-06-2003, 07:48 AM
Chris Uppal
 
Posts: n/a
Re: Name spaces in Dolphin...

panu wrote:

> There is a simple workaround for class-namespaces that
> works in *every* Smalltalk (and in Java too). Before
> complicating things further by adding explicit class-
> namespace support to a language, consider using this
> design pattern:


An even more extreme point along the same design axis also obviates the need
for namespaces.

I recently (just for fun/interest in how it'd turn out) chose to implement a
small toy project in a style where all responsibility for creating objects (and
hence all references to classes) were the responsibility of a single
system-wide object. That object (which was named after the system) also had
the responsibility for providing access to the several "important" objects in
the system. I quite liked the way the code turned out, and may repeat the
experiment sometime. I've always felt that the actual class of an object
should be seen as a private matter -- an implementation detail only -- and in
this case I was able to design the system so that it fitted properly with that
idea. (At least from the outside, I did cheat on a few occasions in the
internals of the system).

Here's a couple of examples of how it looks from the outside:

"Music" is the name of the system, and the global that is the sole external
entrypoint.

"get/make a note of G#"
Music G sharp.
"--> Music G sharp"

"add a minor third to a note"
Music G + Music minorThird
"--> Music B flat"

"answer the notes in a C major scale"
Music C major notes
"--> #(Music C Music D Music E Music F Music G Music A Music B)"

And so on. (BTW I know nothing of music theory, so the above may be wrong --
the system was just an attempt to learn a bit of the basics of the theory by
turning it into code). All classnames (except 'Music'), and much of the class
structure, are hidden from the external code that uses the library. Internally
the pattern is much the same; e.g, the implementation of
MusicAbstractNote>>major which was used in the previous example:

major
"answer a major key with ourself as tonic"
^ self music major withTonic: self.

-- chris



Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #4 (permalink)  
Old 11-10-2003, 09:24 PM
panu
 
Posts: n/a
Re: Name spaces in Dolphin...

cstb wrote:
>
> (3) In your code, always refer to
> transformer via the local method
>
> (self transformer) selectorWhatever
>



I think I see your point, but I'm not quite
convinced that the added encapsulation is
worth the added complexity (then again I may
not quite get what your example correctly) .

There's some added complexity in the above.
First of all every reference to a global/class
now gets longer (if I get you correctly, right?).

I've tried something similar over the years
but somehow the added encapsulation doesn't
seem to be worth the added complexity.

Whereas the rule "Instead of accessing a class
directly, always call a method that returns it"
seems to be *easy to grasp*, and *easy to remember*.


> ...
> Advantages: Encapsulates further, as client
> doesn't need to know the class
> side methods,


The above seems to indicate that I perhaps
didn't explain my intentions clearly.

I didn't say - nor was it my intention - that
the method should be a "class side" method at
all. Rather, I tried to indicate by the example
that it should be a method that one sends to
'self'. Sending something to self is the closest
thing to "encapsulation" I can think of.

Cheers
-Panu Viljamaa

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #5 (permalink)  
Old 11-10-2003, 09:26 PM
panu
 
Posts: n/a
Re: Name spaces in Dolphin...

Chris Uppal wrote:

I recently (just for fun/interest in how it'd turn out) chose to
implement a
> small toy project in a style where all responsibility for creating objects (and
> hence all references to classes) were the responsibility of a single
> system-wide object.


Right. But that is *your* system-wide object.
What if you want to load some-one else's code
into your image?


-Panu Viljamaa


Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #6 (permalink)  
Old 11-11-2003, 04:29 AM
Chris Uppal
 
Posts: n/a
Re: Name spaces in Dolphin...

panu wrote:

> I recently (just for fun/interest in how it'd turn out) chose to
> implement a
> > small toy project in a style where all responsibility for creating
> > objects (and hence all references to classes) were the responsibility
> > of a single system-wide object.

>
> Right. But that is *your* system-wide object.
> What if you want to load some-one else's code
> into your image?


The relevance is that since "my" classnames are hidden, and there is only the
one "global" identifier, all the actual classnames can be (and are) long and
descriptive without impacting clients of my code (if there were any). That in
itself makes it highly unlikely that I/they will experience clashes. Also the
fact that all (just about) references to classnames from inside the module are
centralised in the 'Music' object means that changing them is extra specially
easy -- should the need ever arise.

There is, of course, no way that I can write *my* code such that it reduces the
possibility of name clashes between two separate third parties.

Well, not unless I go ahead and implement my "non-intrusive namespaces"
suggestion from elsewhere in this thread -- I'm getting increasingly tempted to
have a pop at it, it looks quite easy to do a bare-bones (little/no tools
support, global identifiers only, no selector namespaces) implementation.

-- chris



Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #7 (permalink)  
Old 11-12-2003, 03:15 AM
cstb
 
Posts: n/a
Re: Name spaces in Dolphin...



panu wrote:
>
> cstb wrote:
> >
> > (3) In your code, always refer to
> > transformer via the local method
> >
> > (self transformer) selectorWhatever
> >

>
> I think I see your point, but I'm not quite
> convinced that the added encapsulation is
> worth the added complexity (then again I may
> not quite get what your example correctly) .



Just noting that, whereas you put the
responsibility for answering an actual receiver
in an instance method, I suggest moving it
to the class side (whenever it will answer aClass).

So the trace is
(self transformer) selector
--> (self class transformer) selector
--> ActualReceiver selector

The second line of the trace is
the 'added complexity', but if you
do this all the time, its very easy
to follow. In fact, it gets exceptionally
easy, as we'll see below.


> There's some added complexity in the above.
> First of all every reference to a global/class
> now gets longer (if I get you correctly, right?).



If by longer you mean
takes one more indirection hop
then yes, it is longer. But I wouldn't
agree that this increases the 'complexity',
either formally or informally.

You can obviously ignore the 'cost' of the extra
indirection, as one doesn't refer to another class
very often, so the extra time is minuscule. In the
rare cases that this isn't true, either
a) you should think about refactoring,
as someOfThisCode wants to be
in that other class
or
b) you've got an otherwise working solution, but
which fails to meet some performance requirement
AND
profiling the code tells you that removing
this particular indirection will have a
significant effect toward speeding it up.


>
> Whereas the rule "Instead of accessing a class
> directly, always call a method that returns it"
> seems to be *easy to grasp*, and *easy to remember*.
>



My version of your rule, then, is two parts:

1) "Instead of accessing a class directly,
always ask yourself which class to use.

(self whichClassToUse) whateverTheSelectorIs...

2) "When you are asked which class to use,
always query your own class side for the answer.

self>>whichClassToUse
^self class whichClassToUse

self class>>whichClassToUse
^TheActualClass


> > ...
> > Advantages: Encapsulates further, as client
> > doesn't need to know the class
> > side methods,


Meaning - [and not that you do this, just that one shouldn't]

Don't directly refer to your own
class side methods using CapitalizedSelectors,
(as is sometimes suggested) - instead,
always refer to a forwarding method
that is defined on the instance side.

Result:

1) Scanning some code, you see a reference:
self thingAmaJig doSomething

You don't know about thingAmaJig,
so you look for it (in the all categories list)
- and find it in the category 'accessing class'.

You now know (without looking at it)
that it is either answering a constant,
or a collaborating class, and decide you
can safely ignore that detail for now.
You return to scanning the original
code.

2) You want to modify a class,
changing a collaborator.

You go to the class side, and select the
category 'collaborators'.
You look at all the methods, and one of them
just answers ThingAmaJig. That's the guy
you want to swap out. The name of the method
answering ThingAmaJig is #thatThingYouUse,
so you browse local senders of #thatThingYouUse,
and you get a list of every place this class
is using ThingAmaJig, i.e. by looking at just
these spots in the code you'll know the actual
protocol being used with ThingAmaJig.
So now you know -
you can indeed replace ThingAmaJig with
NewFangledCoolness because (having written it,
you happen to recognize) the latter also defines
all the methods that are actually being
used on ThingAmaJig -- used *by this class*.
You do not care about any other methods
ThingAmaJig might define, because only the
ones listed in the browser window right
now are used *here*, in the class you
want to change. The other 6,432 methods
defined on ThingAmaJig (a god class, obviously)
are not used here at all, so you don't have
to bother defining them on NewFangledCoolness.
You don't even have to read them.
Lucky you. Nice convention.


> ...
>
> Sending something to self is the closest
> thing to "encapsulation" I can think of.


That's right.

There's only one thing closer, which is
- don't send to anyone -
i.e. reference an instVar directly.

But I wouldn't advise doing this *unless*
you happen to have a reasonable refactoring
tool on hand, one that will let you change
your mind and switch all the getters to
directRefs, and back to getters again,
at will.

Which of course you do, so go ahead.
Lucky you.

(do stick to the convention in
the <Class> case though...
)

>
> Cheers
> -Panu Viljamaa


Cheers,

-cstb
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #8 (permalink)  
Old 11-13-2003, 02:59 AM
panu
 
Posts: n/a
Re: Name spaces in Dolphin...

cstb wrote:

> So the trace is
> (self transformer) selector
> --> (self class transformer) selector
> --> ActualReceiver selector
>


What I'm proposing is to always access a global
or class (for instance NeededClass below)
with something like:

self NeededClass
--> (self whichClassToUse) NeededClass "POSSIBLY"
--> (self class whichClassToUse) NeededClass "POSSIBLY"
--> ActualReceiver NeededClass "POSSIBLY"

The point being that the most important / valuable
step is the first one. I don't go into detail
of what *should* happen inside 'self NeededClass'.

Using 'whichClassToUse' inside it may indeed
the best solution, but I allow the situation and
circumstance affect that decision. In effect I
encapsulate this decision inside my (i.e. self's)
method #NeededClass.


In Smalltalk, the SystemDictionary 'Smalltalk' is the
'holder of globals'. In fact the compiler gets the
classes from it - but with no regards to encapsulation.
Therefore in many cases I've written:

self NeededClass
--> self Smalltalk NeededClass

The above I think follows your pattern closely:
Delegate to an object responsible for knowing
the thing asked for, but do the delegation by
accessing the delegate via a further message-send.

Since 'Smalltalk' (The SystemDictionary) above is
accessed via a method, it is easy to come up with
the idea that each 'self' may in fact have their
own SystemDictionary. Then it becomes only natural
to make the small step of calling such objects
'namespaces' instead:

self NeededClass
--> self namespace NeededClass


But as I said I find such indirection often *more
than enough*, and would rather refactor my code
to that form only when needed.

Why? Looking at the last example, I still don't know
which *actual* class gets returned, and figuring that
out takes an extra level of effort.

There's a fine balance between *forces* of minimizing
dependencies, and maximizing readability. How to balance
these forces naturally depends on the circumstances.

- Panu Viljamaa

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #9 (permalink)  
Old 11-13-2003, 03:05 AM
panu
 
Posts: n/a
Re: Name spaces in Dolphin...

Chris Uppal wrote:


> The relevance is that since "my" classnames are hidden, and there is only the
> one "global" identifier, all the actual classnames can be (and are) long and
> descriptive without impacting clients of my code (if there were any).


Ok. What I'm getting at is that there should be
one "global" identifier *per programmer or project*.

That would reduce the possibility of name conflicts
even further. And perhaps this was your intention too.

Regards
-Panu Viljamaa


That in
> itself makes it highly unlikely that I/they will experience clashes. Also the
> fact that all (just about) references to classnames from inside the module are
> centralised in the 'Music' object means that changing them is extra specially
> easy -- should the need ever arise.
>
> There is, of course, no way that I can write *my* code such that it reduces the
> possibility of name clashes between two separate third parties.
>
> Well, not unless I go ahead and implement my "non-intrusive namespaces"
> suggestion from elsewhere in this thread -- I'm getting increasingly tempted to
> have a pop at it, it looks quite easy to do a bare-bones (little/no tools
> support, global identifiers only, no selector namespaces) implementation.
>
> -- chris
>
>
>


Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #10 (permalink)  
Old 11-13-2003, 06:28 AM
Chris Uppal
 
Posts: n/a
Re: Name spaces in Dolphin...

panu

> Ok. What I'm getting at is that there should be
> one "global" identifier *per programmer or project*.
>
> That would reduce the possibility of name conflicts
> even further. And perhaps this was your intention too.


Well, I was working in standard Smalltalk, so the names of the classes were
still there in the global namespace. However I was attempting to program in a
style that didn't make use of them.

As I said, I quite liked the way the code worked out. But I wouldn't use it
for every project -- two downsides being the unidiomatic code, and the tendency
of the 'system' object to acquire (some of) the disadvantages of a God-class.

-- chris




Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply


Thread Tools

Posting Rules
You may not post new questions
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



All times are GMT -4. The time now is 05:47 PM.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.1.0
Copyright 2004 - 2007 Exforsys Inc. All rights reserved.