Getting rid of 'case statements'

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
32 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Getting rid of 'case statements'

Fernando Rodriguez
Hi,

This is from Squeak's Url class>>absoluteFromText:
----------------------------------------------------------------------------
        (scheme = 'http') ifTrue:
        [ newUrl _ HttpUrl new privateInitializeFromText: remainder ].
       
        (scheme = 'msw') ifTrue:
        [ newUrl _ MswUrl new privateInitializeFromText: remainder ].
       
        (scheme = 'ftp') ifTrue:
        [ newUrl _ FtpUrl new privateInitializeFromText: remainder ].
       
        (scheme = 'file') ifTrue:
        [newUrl _ FileUrl new privateInitializeFromText: remainder ].
       
        (scheme = 'browser') ifTrue:
        [ newUrl _ BrowserUrl new privateInitializeFromText: remainder
].
        (scheme = 'mailto') ifTrue:
        [ newUrl _ MailtoUrl new privateInitializeFromText: remainder
].

        newUrl ifNil:
        [  newUrl _ GenericUrl new privateInitializeFromText:
remainder ].
--------------------------------------------------------------------------------

It checks the contents of the string scheme and depending on it, it
creates an instance of a subclass of Url.

It looks awfully as a case statement. Is there a better and more OO
way of doing this sort of thing?

Thanks


Reply | Threaded
Open this post in threaded view
|

Re: Getting rid of 'case statements'

Vincent Foley-2
How about a hash table?  Something like:

choices := { 'http'->HttpUrl 'ftp'->FtpUrl }.
(choices at: scheme) new privateInitializeFromText: remainder.

Something like that?


Reply | Threaded
Open this post in threaded view
|

Re: Getting rid of 'case statements'

Sean M-4
In reply to this post by Fernando Rodriguez
schemes := (Dictionary new)
    at: 'http' put: HttpUrl;
    at: 'msw' put: MswUrl;
    at: 'ftp'put: FtpUrl;
    at: 'file' put: FileUrl;
    at: 'browser' put: BrowserUrl;
    at: 'mailto' put: MailtoUrl;
    yourself.

newUrl := (schemes at: scheme ifAbsent: [ GenericUrl ])
    new privateInitializeFromText: remainder.

or something?


Reply | Threaded
Open this post in threaded view
|

Re: Getting rid of 'case statements'

Chris Uppal-3
Sean M wrote:
> schemes := (Dictionary new)
>     at: 'http' put: HttpUrl;

Or, since URL schemes are case-insensitive (sorry about the wrapping):

    schemes := (PluggableLookupTable searchPolicy: SearchPolicy
caseInsensitive)
                        at: 'http' put: ... etc ...


The pluggable Collections are rather nice, and it'd be a shame to miss the
chance to give them a plug...

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: Getting rid of 'case statements'

NiallRoss
In reply to this post by Fernando Rodriguez
Dear Fernando,
    my 'Smalltalk for Java Programmers' pages have a full discussion of
this, including adding a case statement construct to Smalltalk as an
exercise (to show how easy it is, thence to justify Smalltakers saying they
don't have it in the base because they don't need it).  The whole thing
starts at

http://wiki.cs.uiuc.edu/CampSmalltalk/Smalltalk+for+Java+Programmers

For the discussion of case statements, scroll to the foot of page

http://wiki.cs.uiuc.edu/CampSmalltalk/control+flow

where you will find links to pages on each of the four approaches.

HTH.
            Yours faithfully
                Niall Ross

> This is from Squeak's Url class>>absoluteFromText:
> --------------------------------------------------------------------------
--

> (scheme = 'http') ifTrue:
> [ newUrl _ HttpUrl new privateInitializeFromText: remainder ].
>
> (scheme = 'msw') ifTrue:
> [ newUrl _ MswUrl new privateInitializeFromText: remainder ].
>
> (scheme = 'ftp') ifTrue:
> [ newUrl _ FtpUrl new privateInitializeFromText: remainder ].
>
> (scheme = 'file') ifTrue:
> [newUrl _ FileUrl new privateInitializeFromText: remainder ].
>
> (scheme = 'browser') ifTrue:
> [ newUrl _ BrowserUrl new privateInitializeFromText: remainder
> ].
> (scheme = 'mailto') ifTrue:
> [ newUrl _ MailtoUrl new privateInitializeFromText: remainder
> ].
>
> newUrl ifNil:
> [  newUrl _ GenericUrl new privateInitializeFromText:
> remainder ].
> --------------------------------------------------------------------------
------
>
> It checks the contents of the string scheme and depending on it, it
> creates an instance of a subclass of Url.
>
> It looks awfully as a case statement. Is there a better and more OO
> way of doing this sort of thing?
>
> Thanks


Reply | Threaded
Open this post in threaded view
|

Re: Getting rid of 'case statements'

Steven Kelly
In reply to this post by Fernando Rodriguez
For completeness' sake: One other possible way is to note that there is a consistent mapping from the scheme to the
class name:

(Smalltalk at: (scheme asTitlecase, 'Url') asSymbol ifAbsent: [GenericUrl])
   new privateInitializeFromText: remainder

Of course you'd only do this if you can limit the search space better than Smalltalk (e.g. with VW's namespaces),
otherwise you run the risk of picking up an entirely different kind of class whose name just happens to end in Url.
Performance is not quite as good as the cached dict of string->class (bigger dict, need to create and internalize a
Symbol). Overall, I think this is a pretty poor choice, although it might do as a quick hack solution (being the
shortest to write). About the only thing going for this way is that it makes explicit the fact that Url classes should
be named after their schemes.

Steve

"Fernando Rodriguez" <[hidden email]> wrote in message
news:[hidden email]...

> Hi,
>
> This is from Squeak's Url class>>absoluteFromText:
> ----------------------------------------------------------------------------
> (scheme = 'http') ifTrue:
> [ newUrl _ HttpUrl new privateInitializeFromText: remainder ].
>
> (scheme = 'msw') ifTrue:
> [ newUrl _ MswUrl new privateInitializeFromText: remainder ].
>
> (scheme = 'ftp') ifTrue:
> [ newUrl _ FtpUrl new privateInitializeFromText: remainder ].
>
> (scheme = 'file') ifTrue:
> [newUrl _ FileUrl new privateInitializeFromText: remainder ].
>
> (scheme = 'browser') ifTrue:
> [ newUrl _ BrowserUrl new privateInitializeFromText: remainder
> ].
> (scheme = 'mailto') ifTrue:
> [ newUrl _ MailtoUrl new privateInitializeFromText: remainder
> ].
>
> newUrl ifNil:
> [  newUrl _ GenericUrl new privateInitializeFromText:
> remainder ].
> --------------------------------------------------------------------------------
>
> It checks the contents of the string scheme and depending on it, it
> creates an instance of a subclass of Url.
>
> It looks awfully as a case statement. Is there a better and more OO
> way of doing this sort of thing?
>
> Thanks


Reply | Threaded
Open this post in threaded view
|

Re: Getting rid of 'case statements'

Reinout Heeck
In reply to this post by Fernando Rodriguez
It is worth noting that VisualWorks often relies on pragmas (method
annotations) for this kind of registries.

Essentiallay you establish a well known pragma name that means 'I mark a
method that describes an URL scheme implementation'. The system has hooks
to notify you when methods are changed which you use to keep the various
registries/mappings you need up to date.
Any package that wants to register an URL scheme merely needs to provide one
such marked method per scheme.


HTH,

Reinout
-------


Reply | Threaded
Open this post in threaded view
|

Re: Getting rid of 'case statements'

Sean M-5
In reply to this post by Chris Uppal-3
> The pluggable Collections are rather nice, and it'd be a shame to miss the
> chance to give them a plug...

I didn't know about pluggable collections, thanks for that.

BTW, nice pun ;)


Reply | Threaded
Open this post in threaded view
|

Re: Getting rid of 'case statements'

jtzecher
In reply to this post by Chris Uppal-3
I, too, have not heard about the PluggableLookupTable. I just did a
search on my class library and could not find it. I am using VA 6.0.2.
What dialect are you using that includes it?

However, this was an interesting search. After 12 years of Smalltalk
coding, I noticed the class LookupTable for perhaps the first time.
Maybe it was mentioned during my early years of coding but I was
directed towards using the Dictionary class to handle the association
of keys and values so that is what I have always used (maybe it wasn't
part of the old Digitalk SmalltalkV that I first learned on?).

At any rate, I have been glancing back and forth between Dictionary and
LookupTable classes to look for differences. Dictionary implements a
single collection of associations called elements and Lookup table has
separate collections for keys and values. My question really is whether
there is any guidance given as to when the use of one class is
recommended over the other or is it a matter of developer preference?

Joel

p.s. Interesting discussion - Steven Kelly had a very quick translation
method that will work nicely if you can insure that the scheme and the
class name will match after you add "Url" to the end. Andres had an
elegant solution if you can rely on the presence of the abstract class.
Failing that, you seem to need to rely on some form of
Dictionary/LookupTable.


Reply | Threaded
Open this post in threaded view
|

Re: Getting rid of 'case statements'

Geoff
Joel,

In VAST at least, the main difference between a Dictionary and a
LookupTable (functionally), is that a Dictionary can have a key that is
nil, a LookupTable can't because the keys are directly stored in the
keys collection, and an empty slot has a nil value.  The other
difference that can cause interesting issues (and is why we usually use
LookupTables) is that a copy of a Dictionary just copies the Dictionary
and it's association collection, but shares the associations.  Any
changes to the value for a particular key in one dictionary will also
affect the other dictionary, LookupTables do not have that issue.

Warren.

jtzecher wrote:

> I, too, have not heard about the PluggableLookupTable. I just did a
> search on my class library and could not find it. I am using VA 6.0.2.
> What dialect are you using that includes it?
>
> However, this was an interesting search. After 12 years of Smalltalk
> coding, I noticed the class LookupTable for perhaps the first time.
> Maybe it was mentioned during my early years of coding but I was
> directed towards using the Dictionary class to handle the association
> of keys and values so that is what I have always used (maybe it wasn't
> part of the old Digitalk SmalltalkV that I first learned on?).
>
> At any rate, I have been glancing back and forth between Dictionary and
> LookupTable classes to look for differences. Dictionary implements a
> single collection of associations called elements and Lookup table has
> separate collections for keys and values. My question really is whether
> there is any guidance given as to when the use of one class is
> recommended over the other or is it a matter of developer preference?
>
> Joel
>
> p.s. Interesting discussion - Steven Kelly had a very quick translation
> method that will work nicely if you can insure that the scheme and the
> class name will match after you add "Url" to the end. Andres had an
> elegant solution if you can rely on the presence of the abstract class.
> Failing that, you seem to need to rely on some form of
> Dictionary/LookupTable.
>


--


Warren Stanley
Technical Consultant
R&D team
Application Solutions

Wizard Information Services


To send e-mail, use my name with a dot in the middle,
and the domain is wizardis dot com dot au


Reply | Threaded
Open this post in threaded view
|

Re: Getting rid of 'case statements'

Chris Uppal-3
In reply to this post by jtzecher
jtzecher wrote:

> I, too, have not heard about the PluggableLookupTable. I just did a
> search on my class library and could not find it. I am using VA 6.0.2.
> What dialect are you using that includes it?

Dolphin (this thread is cross-posted into c.l.s.dolphin).


> At any rate, I have been glancing back and forth between Dictionary and
> LookupTable classes to look for differences. Dictionary implements a
> single collection of associations called elements and Lookup table has
> separate collections for keys and values. My question really is whether
> there is any guidance given as to when the use of one class is
> recommended over the other or is it a matter of developer preference?

My own opinion is that the implementation of Dictionary is simply a mistake.  A
cute concept, to think of a map as a Set of Associations, but it doesn't
provide any real benefit, and has definite costs in space/time and has
non-obvious consequences for the programmer.  If it had been given an
appropriate name (AssociationSet, perhaps), and if LookupTable had been given a
snappier name (Dictionary or Map), then I doubt if anyone would ever think of
using it.

FWIW, I have only ever once (deliberately) used a Dictionary instead of a
LookupTable, and I don't suppose it's very likely that I'll ever have to do so
again...

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: Getting rid of 'case statements'

Hans-Martin Mosner
"Chris Uppal" <[hidden email]> wrote:
...
> My own opinion is that the implementation of Dictionary is simply a mistake.  A
> cute concept, to think of a map as a Set of Associations, but it doesn't
> provide any real benefit, and has definite costs in space/time and has
> non-obvious consequences for the programmer.

The original implementation in Smalltalk-80 was probably designed that
way to support variable bindings for static variables. Remember that
Smalltalk as a system was designed to run on severely memory-constrained
systems by today's standards.
Of course, there's no reason today to keep it that way except for
backward compatibility.

Cheers,
Hans-Martin


Reply | Threaded
Open this post in threaded view
|

Re: Getting rid of 'case statements'

Peter van Rooijen
In reply to this post by Fernando Rodriguez
Fernando Rodriguez wrote:

Hi Fernando,

See comments below.

> Hi,
>
> This is from Squeak's Url class>>absoluteFromText:
> ----------------------------------------------------------------------------
> (scheme = 'http') ifTrue:
> [ newUrl _ HttpUrl new privateInitializeFromText: remainder ].
>
> (scheme = 'msw') ifTrue:
> [ newUrl _ MswUrl new privateInitializeFromText: remainder ].
>
> (scheme = 'ftp') ifTrue:
> [ newUrl _ FtpUrl new privateInitializeFromText: remainder ].
>
> (scheme = 'file') ifTrue:
> [newUrl _ FileUrl new privateInitializeFromText: remainder ].
>
> (scheme = 'browser') ifTrue:
> [ newUrl _ BrowserUrl new privateInitializeFromText: remainder
> ].
> (scheme = 'mailto') ifTrue:
> [ newUrl _ MailtoUrl new privateInitializeFromText: remainder
> ].
>
> newUrl ifNil:
> [  newUrl _ GenericUrl new privateInitializeFromText:
> remainder ].
> --------------------------------------------------------------------------------
>
> It checks the contents of the string scheme and depending on it, it
> creates an instance of a subclass of Url.
>
> It looks awfully as a case statement.

It looks like a case statement, yes. It doesn't work like a case
statement does, as it evaluates all the tests. But the end result is
much like that of a case statement.

 > Is there a better and more OO
> way of doing this sort of thing?

A more OO way of doing a case selection? OO has nothing to do with using
case statements or not. If this is the only place where this list of
options appears in the code, there is nothing wrong with it. If you need
to update another part of the code if you change this list, then it is
problematic, OO or not OO.

The case selection is not the problem in the code you quoted. It's the
duplicated code that is this method's worst problem.

Cheers,

Peter

>
> Thanks


Reply | Threaded
Open this post in threaded view
|

Re: Getting rid of 'case statements'

Peter van Rooijen
BTW, Squeak's {} syntax provides a reasonably efficient and elegant way
of writing this is:

schemeSymbol := scheme asSymbol
.
mappingFromSchemeSymbolToClass := {
        {#http . HttpUrl}.
        {#msw . MswUrl}.
        {#ftp . FtpUrl}.
        {#file . FileUrl}.
        {#browser . BrowserUrl}.
        {#mailto . MailtoUrl}.
}
.
urlClass := (
        mappingFromSchemeSymbolToClass
                detect: [:x | (x at: 1) == schemeSymbol]
                ifNone: [{#hunoz . GenericUrl}]
) at: 2
.
newUrl := urlClass new privateInitializeFromText: remainder

This keeps all the required code together in one place.

Note that you can't do this in dialects that don't have compile-time
compilation constructs involving variables (VA Smalltalk supports it
too, but with a different syntax). Other dialects may support equivalent
constructs (I hardly ever use them because they are not portable).

Cheers,

Peter

P.S. Note that the object assigned above to
mappingFromSchemeSymbolToClass prints as something that doesn't evaluate
to an equivalent object. Squeaks printing logic for Arrays presents a
syntactically valid Array literal assuming, naively, that the printed
object is a literal, or at least printable as a literal (the printString
of literals evaluates to an equivalent object). VisualWorks suffers from
this same mistaken assumption. VA Smalltalk avoids the issue by not
printing Arrays as syntactically valid literals ;-).


Reply | Threaded
Open this post in threaded view
|

Re: Getting rid of 'case statements'

Chris Uppal-3
In reply to this post by Peter van Rooijen
Peter van Rooijen wrote:

> A more OO way of doing a case selection? OO has nothing to do with using
> case statements or not. If this is the only place where this list of
> options appears in the code, there is nothing wrong with it.

I'd say that there /is/ something wrong -- perhaps not particularly bad in this
specific example, but hard-wired lists of alternatives have the potential to
become "hot-spots" of change and fragility.

I once worked (in 'C') on a project where the implementation was as lots of
independent modules.  "Very good" you may be thinking, but there was one
source-file where all the active modules had to be listed in order for the
system to include them.  And that file caused problems because it was a "hot
spot" of change.  For instance it was difficult to make changes to it in the
proper (for our culture there) check-out-of-SCC, modify, test, check-into-SCC,
pattern because there were often several people who wanted to make changes to
it at the same time.

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: Getting rid of 'case statements'

Chris Uppal-3
In reply to this post by Hans-Martin Mosner
Hans-Martin Mosner wrote:

> > My own opinion is that the implementation of Dictionary is simply a
> > mistake.  [..]
>
> The original implementation in Smalltalk-80 was probably designed that
> way to support variable bindings for static variables.

Fair point.

(Though I'm not sure I'm convinced by it -- why burden /all/ Dictionaries with
a compromised implementation, when the relatively few "system" Dictionaries
could have been implemented as something like an ordinary Dictionary with
ValueHolder values ?)

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: Getting rid of 'case statements'

Peter van Rooijen
In reply to this post by Peter van Rooijen
Peter van Rooijen wrote:
> BTW, Squeak's {} syntax provides a reasonably efficient and elegant way
> of writing this is:

!!Misinformation Alert!!

I want to correct myself: the solution I presented is *not* efficient.

It may have been convenient (all the code in one place), and even
reasonably elegant. But it's not an efficient solution.

I based the idea that it was efficient on my assumption that Squeak's {}
syntax provides compile-time evaluation (as I explained at the end of my
message).

However, I have discovered that it does not (provide compile-time
evaluation).

In fact Squeak's {} is not an interesting and useful extension of the
language, as I mistakenly thought it was, but merely syntactic sugar. It
avoids the need to write Array with: 1, instead allowing writing {1}.

So, to be clear, {1} does exactly the same as Array with: 1. It in fact
compiles to Array braceWith: 1.

This use of a syntactic construct for sugaring is quite dubious, being
in stark contrast with the general Smalltalk maxim of keeping the syntax
to the minimum required.

I hope this sets the matter straight. And that I didn't give out
incorrect information this time ;-).

Cheers,

Peter


Reply | Threaded
Open this post in threaded view
|

Re: Getting rid of 'case statements'

Peter van Rooijen
In reply to this post by Chris Uppal-3
Chris Uppal wrote:

> Peter van Rooijen wrote:
>
>
>>A more OO way of doing a case selection? OO has nothing to do with using
>>case statements or not. If this is the only place where this list of
>>options appears in the code, there is nothing wrong with it.
> *
>
> I'd say that there /is/ something wrong -- perhaps not particularly bad in this
> specific example, but hard-wired lists of alternatives have the potential to
> become "hot-spots" of change and fragility.

It is my opinion, that it is the *duplication* of such lists, not their
mere occurrence, that is problematic.

> I once worked (in 'C') on a project where the implementation was as lots of
> independent modules.  "Very good" you may be thinking, but there was one
> source-file where all the active modules had to be listed in order for the
> system to include them.  And that file caused problems because it was a "hot
> spot" of change.  For instance it was difficult to make changes to it in the
> proper (for our culture there) check-out-of-SCC, modify, test, check-into-SCC,
> pattern because there were often several people who wanted to make changes to
> it at the same time.

I'm not sure what argument you are making here.

But it sounds like you may have had a duplicated list of modules.

If it is the concurrent modification of the source code that you see as
the problem, I have difficulty seeing that as a programming language
problem, let alone as an OO-related problem.

Maybe I am misunderstanding you.

Regards,

Peter

>     -- chris


Reply | Threaded
Open this post in threaded view
|

Re: Getting rid of 'case statements'

Chris Uppal-3
Peter van Rooijen wrote:

> > I'd say that there /is/ something wrong -- perhaps not particularly bad
> > in this specific example, but hard-wired lists of alternatives have the
> > potential to become "hot-spots" of change and fragility.
>
> It is my opinion, that it is the *duplication* of such lists, not their
> mere occurrence, that is problematic.

I agree that any duplication would be bad, but my point is that the list itself
is (potentially) damaging.

If you like you could see it another way: if there is a potential for
assembling the list by some other technique (introspection, perhaps, as in
identifying test cases in SUnit), then the list is formally redundant, even if
it does not obviously duplicate any other element of the source.

However, I'd go further than that and assert that some lists are fragile /even/
in the case where they form the /only/ record of what should be included (even
up to non-algorithmic considerations).  As my example attempted to illustrate.


> > I once worked (in 'C') on a project where the implementation was as
> > lots of independent modules.  "Very good" you may be thinking, but
> > there was one source-file where all the active modules had to be listed
> > in order for the system to include them.  And that file caused problems
> > because it was a "hot spot" of change.  For instance it was difficult
> > to make changes to it in the proper (for our culture there)
> > check-out-of-SCC, modify, test, check-into-SCC, pattern because there
> > were often several people who wanted to make changes to it at the same
> > time.
>
[...]
> But it sounds like you may have had a duplicated list of modules.

No, not unless you consider that the list "duplicated" the programmers'
(non-algorithmic) knowledge of what was suitable for inclusion in a given
build.

(Actually there was duplication /too/, come to think of it, since the list of
modules was represented both in the 'C' source and in the makefiles, but that
duplication /added/ to the problem, it did not cause it.)


> If it is the concurrent modification of the source code that you see as
> the problem, I have difficulty seeing that as a programming language
> problem, let alone as an OO-related problem.

I see the concurrent modifications problems as /symptomatic/ of an underlying
design problem.  That problem is not OO-specific since it occurs in non-OO
contexts, but problems with a given passage of source (in an OO language) are
not less problematic if the same idiom could also be used in a non-OO language.
And yes, I do think it's a (potential) problem with the language or with the
use of the language.  If the language gives you no way to avoid such constructs
(in the cases where they are likely to cause problems) then its a flaw in the
language.  If it does give you a way to avoid them, and the programmer has not
used them, then that's a flaw in the code.  A programmer's responsibilities
include designing and coding in such a way that all necessary flexibility is
preserved -- including non-semantic concerns such as avoiding SSC hot-spots[*].
I was unable to do so in the case I described; a mixture of inexperience on my
part (I didn't see the problem coming), deficiencies in the 'C' language (I
couldn't arrange for the modules to auto-register themselves), and our own
project culture (which didn't allow me to set up a meta-level in the build
process that could have assembled the list at build-time instead of hand-coding
it).

([*] See Lakos's "Large Scale C++ Software Design" for (much) more on this
topic -- Of course Smalltalk doesn't require so much effort from the programmer
to avoid problems.)

BTW, I'm only saying that such lists /can/ be problematic, not that they always
are.  For instance decoding JVM bytecodes using a "list" hardcoded into the
source would not (IMO) be a problem.  The values of the JVM bytecodes are well
defined, and have historically been very stable, and there's no reason to
expect anything other than very slow change in the future.  OTOH, using a
similar list to decode Dolphin Smalltalk bytecodes would not (IMO) be such a
good idea; the Dolphin image is splashed with warnings that the bytecode values
are subject to change without warning.   Fernando (the OP)'s list of
URL-schemes strikes me as unsuitable for hardcoding, since the range of schemes
that are defined is pretty fluid, as is the sub-range of them for which
Dolphin-accessible implementations exist.

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: Getting rid of 'case statements'

Bruce Samuelson-2
Chris Uppal wrote:

> I see the concurrent modifications problems as /symptomatic/ of an underlying
> design problem...

For your amusement or dismay, here are variations of this design problem
from a recent project.

1. Copy/paste reuse: 'foo' 'foo' 'foo' x 25

I needed to change the literal string 'foo'. A search located it in 25
methods over a wide range of classes.

2. Copy/paste redux: 'abc...foo...abc' repeated 25 times.

Those 25 methods, about 2 pages long each, were nearly identical to each
other.

3. Vehicle (parent class)
       |
       |
    Bicycle (child class)

The creator of the Bicycle subclass defined no methods or instance
variables. It's sole purpose was for use in a case statement:

x class = Wagon ifTrue: [^...]
x class = Bicycle ifTrue: [^...]
x class = Cart ifTrue: [^...].

There were no other references to the Bicycle class in the system. Its
author, having amassed a record of many similar inventions, was promoted
to the architecture team.

4. Refactor not!

On my second week on the job, I asked my mentor whether the team culture
was favorable or unfavorable to refactoring. The answer would determine
the preferred approach to my first assignment. The mentor reported this
indiscretion to my supervisor, who roundly balled me out. My sin was not
in violating the culture, but in seeking to understand it.

5. Postscript

To be fair, I should give examples of my worst blunders, some technical,
and most behavioral. Many exceed the corruption of those above. But
space does not allow it. :-)


12