Exforsys
+ Reply to Thread
Page 1 of 2 12 LastLast
Results 1 to 10 of 12

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 > standard ...

  1. #1
    panu Guest

    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




  2. #2
    cstb Guest

    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



  3. #3
    Chris Uppal Guest

    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






  4. #4
    panu Guest

    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




  5. #5
    panu Guest

    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





  6. #6
    Chris Uppal Guest

    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






  7. #7
    cstb Guest

    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



  8. #8
    panu Guest

    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




  9. #9
    panu Guest

    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
    >
    >
    >





  10. #10
    Chris Uppal Guest

    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







    •    Sponsored Ads



Latest Article

Network Security Risk Assessment and Measurement

Read More...