[Fwd: Case statements, decision trees, and good OO design]

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

[Fwd: Case statements, decision trees, and good OO design]

Jan Theodore Galkowski
-------- Original Message --------
Subject: Case statements, decision trees, and good OO design
Date: Mon, 30 Oct 2000 23:26:46 -0500
From: Jan Theodore Galkowski <[hidden email]>
Organization: ::dark side of the moon::
CC: [hidden email]
Newsgroups: Dolphin.smalltalk

One of the principles of classical OO design and programming is that
one should shun case structures like case statements, decision trees,
and comparable switches.  The rationale is that, if used, these tend
to couple individual components strongly to the domain the set of
objects is supposed to solve.  Thus, if that domain is to be extended,
and such extended switches are used, many classes will be affected
by the change, something which is clearly undesirable.

This is discussed at length by Meyer in his _Object_ _Oriented_
_Software_ _Construction_ ("OOSC-2", ISBN 0136291554).

The recommended alternative is to give each distinguishing object
a method with a standard name and then implement that method with
function specific to the object to which it is attached.  Thus,
instead of, say, creating a case structure which elects various
arms depending upon the value of a character code, the idea
would be to provide a method called, say, doWhatYouNeedToDo (but
obviously more pertinent to the application) for each of the
character code instances that are to be "decoded" and define
the thing that needs to be done in the doWhatYouNeedToDo for
that instance.  Thus, one extends the function of the application
in a uniform way, namely, by adding methods to objects.

So, I've got this same situation and am wondering if there is a
standard Dolphin class library way of handling it.  I'd like to
be able to take a character and send it the "asSymbol" method and
exploit attaching of specific methods to these instances.  I suppose
I could use a dictionary to collect these, filing away code in
the dictionary under the appropriate symbolic key.

Does anyone have suggestions on this point?

Thanks.

  --jtg




--
-----------------------------------------------------------------------
 Jan Theodore Galkowski        ºoº            [hidden email]
 algebraist.com/   wikiweb.com/   intercot.com/     [hidden email]
***********************************************************************
             "Smalltalk?  Yes, it's really that slick."
***********************************************************************
 Want to know more?  Check out whysmalltalk.com/, object-arts.com/
-----------------------------------------------------------------------


Reply | Threaded
Open this post in threaded view
|

Re: [Fwd: Case statements, decision trees, and good OO design]

Jan Theodore Galkowski
Subject:
             [Fwd: Re: Case statements, decision trees, and good OO
             design]
        Date:
             Tue, 31 Oct 2000 13:46:09 -0500
        From:
             Jan Theodore Galkowski <[hidden email]>
 Organization:
             Cornell University (CIT ASDT)
 Newsgroups:
             comp.lang.smalltalk.dolphin





-------- Original Message --------
Subject: Re: Case statements, decision trees, and good OO design
Date: Tue, 31 Oct 2000 09:29:17 -0500
From: Jan Theodore Galkowski <[hidden email]>
Organization: ::dark side of the moon::
Newsgroups: Dolphin.smalltalk
References: <[hidden email]>

As a followup, a way of doing what I describe I want to below is
to define an additional series of class methods for the class
Character in the manner of defining the constants lf, nl, etc.
Do this for each character in what would be the case switch.
Do this instead of applying "asSymbol" to the character.
Then, on the fly, associate each of the doWhatYouNeedToDo
methods with the individual constant instances just defined.

Thoughts?

   --jt

Jan Theodore Galkowski wrote:

>
> One of the principles of classical OO design and programming is that
> one should shun case structures like case statements, decision trees,
> and comparable switches.  The rationale is that, if used, these tend
> to couple individual components strongly to the domain the set of
> objects is supposed to solve.  Thus, if that domain is to be extended,
> and such extended switches are used, many classes will be affected
> by the change, something which is clearly undesirable.
>
> This is discussed at length by Meyer in his _Object_ _Oriented_
> _Software_ _Construction_ ("OOSC-2", ISBN 0136291554).
>
> The recommended alternative is to give each distinguishing object
> a method with a standard name and then implement that method with
> function specific to the object to which it is attached.  Thus,
> instead of, say, creating a case structure which elects various
> arms depending upon the value of a character code, the idea
> would be to provide a method called, say, doWhatYouNeedToDo (but
> obviously more pertinent to the application) for each of the
> character code instances that are to be "decoded" and define
> the thing that needs to be done in the doWhatYouNeedToDo for
> that instance.  Thus, one extends the function of the application
> in a uniform way, namely, by adding methods to objects.
>
> So, I've got this same situation and am wondering if there is a
> standard Dolphin class library way of handling it.  I'd like to
> be able to take a character and send it the "asSymbol" method and
> exploit attaching of specific methods to these instances.  I suppose
> I could use a dictionary to collect these, filing away code in
> the dictionary under the appropriate symbolic key.
>
> Does anyone have suggestions on this point?
>
> Thanks.
>
>   --jtg
>
> --
> -----------------------------------------------------------------------
>  Jan Theodore Galkowski        ºoº            [hidden email]
>  algebraist.com/   wikiweb.com/   intercot.com/     [hidden email]
> ***********************************************************************
>              "Smalltalk?  Yes, it's really that slick."
> ***********************************************************************
>  Want to know more?  Check out whysmalltalk.com/, object-arts.com/
> -----------------------------------------------------------------------

--
-----------------------------------------------------------------------
 Jan Theodore Galkowski        ºoº            [hidden email]
 algebraist.com/   wikiweb.com/   intercot.com/     [hidden email]
***********************************************************************
             "Smalltalk?  Yes, it's really that slick."
***********************************************************************
 Want to know more?  Check out whysmalltalk.com/, object-arts.com/
-----------------------------------------------------------------------


Reply | Threaded
Open this post in threaded view
|

Re: [Fwd: Case statements, decision trees, and good OO design]

Louis Sumberg
JT,

I might not be understanding this right, but it seems as though you'd be
muddying up class Character by adding symbols that seem to be application
specific.  A variant on this is to define another class, e.g., MyChar, but
I'm not sure what you'd gain over the implementation you've already pointed
to, namely using a Dictionary consisting of pairs of character codes and
method names (or code blocks).

I assume you're starting from something like:

MyModel>>myMethod
    "Assume that code already contains a Character."
    code = $A ifTrue: [do stuff with $A].
    " ... other codes"
    code = $K ifTrue: [do other stuff with $K]

So instead of this list of ifTrues, you create a method for each code, e.g.,

doStuffA
    yadayadaA

doStuffB
    yadayadayadaB

then you can dynamically create the message, i.e.,

myMethod
    self perform: ('doStuff', code asString) asSymbol

This will not work, however, if the method name you build is not a valid
Smalltalk name.  For exmaple, if code = $%, this won't work since you can't
have a method named #doStuff%.  The Dictionary approach gets around this and
also keeps myMethod short.

MyModel class>>initialize
    MyCharMap := IdentityDictionary new
        at: $A put: #doStuffA;
        at: $K put: #doStuffK;
        at: $% put: #doStuffPerCent;
        yourself

MyModel>>myMethod
        self perform: (MyCharMap at: code)

-- Louis


Reply | Threaded
Open this post in threaded view
|

Re: [Fwd: Case statements, decision trees, and good OO design]

Costas Menico
In reply to this post by Jan Theodore Galkowski
I have developed a class that is more flexible than Case/Switch called
If. The way to use it is as follows:

If begin
elseIf [bool expr] do: [code];
elseIf [bool expr] do: [code];
..
..
elseIf [boolean expression] do: [code];
elseDo: [bool expr]

Example:

x:=3.
If begin
elseIf: [x = 2] do: [
        res := 1.
        ];
elseIf: [x = 1] do: [
        res := 2.
        ];
elseIf: [x = 3] do: [
        res := 3.
        ];
elseDo: [
        res := 4.
        ].
Transcript cr; show: res printString.

I guess you can use the same concept and make a Case class. The key to
this class is an instance variable called logicState. Once an elseIf
expression is true then the rest of the elseIfs/elseDo do nothing .
Currently the result of the If is not defined.  

E.g.
whichIf :=  If begin
elseIf: [x = 2] do: [res := 1. Transcript cr; show: res printString];
elseDo: [res := 2. Transcript cr; show: res printString];

will not work.

Regards,

Costas Menico

Following is the code I Filed Out for the "If" class. To try it you
should File In.
=======================================

"Filed out from Dolphin Smalltalk 99 release 3.0"!

Object subclass: #If
        instanceVariableNames: 'logicState'
        classVariableNames: ''
        poolDictionaries: ''!

If class instanceVariableNames: ''!

If comment: ''!

If guid: (GUID fromString: '{15E71380-AF8A-11D4-86D8-853A44732C79}')!

!If categoriesForClass!Unclassified! !

!If methodsFor!

elseDo: aBlock
        self logicState ifTrue: [^self].
        logicState := true.
        aBlock value
!

elseIf: aBooleanExpr do: aBlock
        self logicState ifTrue: [^self].
        ^aBooleanExpr value ifTrue: [logicState:= true. aBlock value].

!

logicState
        ^logicState!

logicState: aBoolean
        logicState:=aBoolean.
        ^self.! !

!If categoriesFor: #elseDo:!*-unclassified!public! !
!If categoriesFor: #elseIf:do:!*-unclassified!public! !
!If categoriesFor: #logicState!*-unclassified!private! !
!If categoriesFor: #logicState:!*-unclassified!private! !

!If class methodsFor!

begin
        ^super new logicState: false.
! !

!If class categoriesFor: #begin!*-unclassified!public! !


Reply | Threaded
Open this post in threaded view
|

Re: [Fwd: Case statements, decision trees, and good OO design]

David Simmons
"Costas Menico" <[hidden email]> wrote in message
news:[hidden email]...
> I have developed a class that is more flexible than Case/Switch called
> If. The way to use it is as follows:

...snip...

For further reference and ideas, here is the Switch class from
QKS-Smalltalk/SmallScript -- you're free to use it. It inherits from
<IndexedSlotCollection>, but (depending on dialect) you'll probably want to
make it a subclass of something like <OrderedCollection> which supports
ordered #add: value operations.

    (Switch new)
    case: ... do: [
    ];
    case: [...] do: [
    ];
    default: [
        ...
    ];
    on: switchValue.

Or duplicating the previous posters if/else example:

    res := (Switch new)
    case: 2 do: [1];
    case: 1 do: [2];
    case: 3 do: [3];
    default: [4];
    on: x.

Switch class source follows: (No compiler changes are required but a
compiler can easily optimize this form)
---------------------------
Inherited methods required are:
    #add:, #at:
External messages used are:
    #class, #==, #=, #~=, #+
    #to:by:do:, #ifTrue:ifFalse:, #value:

NOTE: QKS Smalltalk allows blocks (and methods) to be valued with more or
less arguments that they were declared with. So, you may want to replace
references to #value: for the <caseValuable,defaultHandlerValuable> with
#value.
---------------------------
<!--BEGIN Switch-->
<class name   ='Switch;
               {BCF183CE-331B-445E-8721-BDB448B456D9};
               {917D20F6-6BAC-4B14-BDE8-BD71222E18E2}'
  extends     ='IndexedSlotCollection;
               {42524DCD-19C0-4106-8347-D547F3F4CC4A}'
  inst-vars   ='defaultHandler'
  authors     ="David Simmons"
  version     ="1.0.0"
>

<!--Switch--><?method [
default: defaultHandlerValuable

   "This registers a default statement to be executed when no other
    on: value matches a statement."
    defaultHandler := defaultHandlerValuable.
]?>

<!--Switch--><?method [
case: caseValuable
  do: handlerValuable

   "This registers a statement to be evaluated and then compared to
    the passed value: parameter."
    self add: caseValuable; add: handlerValuable.
]?>

<!--Switch--><?method [
exactlyOn: switchValue

   "This causes the array of conditions to be tested in the defined
    order. The first condition to evaluate to true has its do: block
    evaluated and the result is returned. Test uses #==."
    1 to: self size by: 2 do:
    [:i||case|
        ((case := self at: i) class == Block) ifTrue:
        [
            ((case value: switchValue) == switchValue) ifTrue:
            [
                "Invoke the <handler>"
                ^(self at: i+1) value: switchValue
            ].
        ] ifFalse:
        [
            (case == switchValue) ifTrue:
            [
                "Invoke the <handler>"
                ^(self at: i+1) value: switchValue
            ].
        ].
    ].
    defaultHandler ? [^nil].
   ^defaultHandler value: switchValue
]?>

<!--Switch--><?method [
equivalentlyOn: switchValue

   "This causes the array of conditions to be tested in the defined
    order. The first condition to evaluate to true has its do: block
    evaluated and the result is returned. Test uses #~=."
    1 to: self size by: 2 do:
    [:i||case|
        ((case := self at: i) class == Block) ifTrue:
        [
            ((case value: switchValue) ~= switchValue) ifTrue:
            [
                "Invoke the <handler>"
                ^(self at: i+1) value: switchValue
            ].
        ] ifFalse:
        [
            (case ~= switchValue) ifTrue:
            [
                "Invoke the <handler>"
                ^(self at: i+1) value: switchValue
            ].
        ].
    ].
    defaultHandler ? [^nil].
   ^defaultHandler value: switchValue
]?>

<!--Switch--><?method [
on: switchValue

   "This causes the array of conditions to be tested in the defined
    order. The first condition to evaluate to true has its do: block
    evaluated and the result is returned. Test uses #=."
    1 to: self size by: 2 do:
    [:i||case|
        ((case := self at: i) class == Block) ifTrue:
        [
            ((case value: switchValue) = switchValue) ifTrue:
            [
                "Invoke the <handler>"
                ^(self at: i+1) value: switchValue
            ].
        ] ifFalse:
        [
            (case = switchValue) ifTrue:
            [
                "Invoke the <handler>"
                ^(self at: i+1) value: switchValue
            ].
        ].
    ].
    defaultHandler ? [^nil].
   ^defaultHandler value: switchValue
]?>

<!--Switch--><?method [
value: switchValue

   "This causes the array of conditions to be tested in the defined
    order. The first condition to evaluate to true has its do: block
    evaluated and the result is returned. Test uses #=."
   ^self on: switchValue
]?>
</class>
<!--END Switch;{BCF183CE-331B-445E-8721-BDB448B456D9}-->

-- Dave Simmons [www.qks.com / www.smallscript.com]
  "Effectively solving a problem begins with how you express it."


Reply | Threaded
Open this post in threaded view
|

Re: [Fwd: Case statements, decision trees, and good OO design]

David Simmons
"Taylor Corey" <[hidden email]> wrote in message
news:C_ZL5.5131$[hidden email]...
> Ummmmmm, I think Kent Beck had a pattern called 'Death to case
statements'.
> IMHO, switch statements are not very good OO practice.
>
> --tc
>

Aside from the fact that Kent's ideas or words are not gospel...

There are a lot of design and implementation problems and performance
related issues that are either ignored or possibly not understood in making
such a sweeping thesis as 'Death to case statements'.

It is worth noting that Kent's focus is with using OO languages for creating
Business objects and systems. I would suggest that it does not, in general,
address all the issues or cases for software development across the entire
spectrum.

-- Dave Simmons [www.qks.com / www.smallscript.com]
  "Effectively solving a problem begins with how you express it."

Here are snippets from posts I made on a CLS thread earlier this year.

Thread title was:
   "Re: Major differences between Smalltalk and Java"

************************************
************************************

> "Wayne Johnston" <[hidden email] <mailto:[hidden email]>> wrote in
message
> <news:[hidden email]>...
> > Ian Upright wrote:
> > >
> > > "James A. Robertson" <[hidden email] <mailto:[hidden email]>>
wrote:
> > > >If you feel the need for a case
> > > >statement, it's easy enough to do with a Dictionary.
> >
> > > Yes, you can use this trick, but many times I don't want the extra
> > > overhead of creating a dictionary object and filling up the dictionary
> > > with the blocks, evertime the method is invoked.
> >
> > What kind of alternative do you suggest? I can't think of an alternative
> > where you don't have to pass in all the blocks anyway, something which
I'm
> > guessing that you would still resist for performance reasons.
> >
> > What's your extension, James?
> > --
> > Wayne Johnston
>
> I'm not James but I thought you'd find it useful to know that QKS
Smalltalk
> has had a standardized inlineable switch form since 1991. I believe The
QKS

> dialect was the first to define switches and it is my understanding that,
> like a variety of other new QKS Smalltalk constructs, this switch
> implementation was also adopted by both Dolphin and Squeak.
>
> Like cascadable exception guards, the entire expression "(Switch new) and
> its cascaded messages" are always inlineable (and it should be easy for a
> smalltalk compiler to inline them via its parse-tree) for hi-performance
> execution. As with most optimizations for Smalltalk, we designed this
> construct (and a portable <Switch> class) to both compile and execute
> without requiring compiler inline support (it's just a whole lot faster
and

> more efficient to have the compiler inline support).
>
> (Switch new)
> case: "value or Block" do: [...];
> ...
> default: [...];
> on: value. "#= equality matching of cases"
>
> (Switch new)
> case: "value or Block" do: [...];
> ...
> default: [...];
> exactlyOn: value. "#== identity matching of cases"
>
> (Switch new)
> case: "value or Block" do: [...];
> ...
> default: [...];
> equivOn: value. "#~= equivalence matching of cases"
> " or #equivalentlyOn:"
>
> If the case expression is a block, then it is injected with the switch
> argument as in:
> case: [:switchArg| ...] do: [...]
>
> The block is then evaluated and the result of the block valuation is
treated
> as the case value for "...on:" testing.
> ----------------------------------
> ----------------------------------
> SIDEBAR: Transforming and maintaining code (and subsequent updates) from
one

> language or associated style to a Smalltalk usage can be problematic.
>
> In that scenario, it is useful to have constructs to capture and preserve
> the original code's intent...
>
> I.e., It is also the case that switch statements have the value that they
> provide a locality of reference for the human programmer to understand the
> conditional flow of execution.
>
> Switches can outperform message sends and have the ability to efficiently
> combine cases without messaging at all. They should not be used for
general
> patterns of behavioral dispatching but may be quite appropriate for
> maintaining the simplicity (for purposes of understanding) of a specific
> algorithm (while possibly gaining (as opposed to losing) performance
> benefits).
>
> In general, it is important to distinguish control flow design based on
> behavior from that based on value. I.e., it is bad form to write
> control-flow code based on something responding to some suite of behavior;
> it is appropriate to write control-flow-code based on specific values of
one

> or more types.
>
> NOTE: The following snippets are written in SmallScript which has an XML
> source form; within method source the SmallScript annotation operator
> '<...>' is used. SmallScript is a new language that fully incorporates and
> extends the QKS' Smalltalk-2000 dialect.
>
> "" Bad form -- it is based on behavioral/type intent
> "" Use polymorphism instead
> if (t class == XX)
> ...
> else if (t class == Y)
> ...
>
> "" Appropriate and more efficient than messaging
> "" since messaging will not discriminate a 'foo'
> "" value from a 'bar' value unless they are of
> "" different types (and even if they were, the
> "" intent was to distinguish the 'foo' value from
> "" the 'bar' value not their behavior types.
> if (t = foo)
> ...
> else if (t = bar)
> ...
>
> "" Or a SmallScript switch form
> switch (obj)
> [
> case foo: "" Case 'foo' will do both
> action1... "" action1 and action2
> case bar:
> action2...
> break.
> case [... abc ...]: "" a completely dynamic-case
> action3...
> break.
> ].
>
> Similarly, if/unless/assert can provide similar value.
> --
> if (cond) "" #ifEquivTrue:
> expr
> else if "or 'unless'" (...)
> --
> unless (cond) "" #ifEquivFalse:
> expr
> else if "or 'unless'" (...)
> --
> assert (cond) "" if assert-level-enabled on thread
> expr "" and (cond) ifEquivTrue:
> else ...
> --
> assert:level (cond)
> expr
> ...
> --
> ==============================
>
> -- Dave S. [www.qks.com]

************************************
************************************

> > Similarly, chains of if-then-elseif-then-else or
> > switch statements generally indicate that someone hasn't thought very
> > carefully, as these constructs are usually what polymorphism is for.
> >
> > ---
> > Doug Palmer "I've got that certain nothing,
> > <mailto:[hidden email]> No one can do without."
> > <http://www.charvolantSPAMUNOT.org/~doug>
>
> This is only makes sense if everything is already an object and if all
> "data" has a behavioral representation. This is a limited and perhaps
> impossible way to view the world.
>
> Ask yourself:
>
> Is "1" a different class from "2"?
> Is "'asString'" as different class from "'new'".
>
> Obviously, the word "class" itself tells us there is a "grouping" and we
> know that implies similar characteristics ("behavior" in OO-terms and
> structure in procedural-terms). However, the members of the group are
> "values" that share the same "behavior".
>
> So, obviously we need some way to express distinctions between the values
> and sometimes to "marshal" values between one behavioral group and
another.
> The need for this and the solutions to addressing that need have nothing
to
> do with "behavior" and thus nothing to do with OO concepts as you're
trying

> to express them.
>
> Control flow is about the expression of decision making. Not all decisions
> are of a "behavioral" form -- this is the flaw in "pure" OO thinking as it
> leaves no room for all the rest.
>
> if (aString = 'abc')
> ...body...
> else if (aString = 'def')
> else if (aString = 'xyz')
>
> if (interest > 0.05 and: [cost < 50])
> else if (interest > 0.08 and: [cost > 200 and: [balance < 4000]])
> ...
>
> What is behavioral about the preceding types of constructs? These
examples,
> while not from any real code, are not atypical of what one encounters in
> general programming problems. This kind of expression of relationships
> between values (or sets of values) is one of the basic elements that forms
> the basis for functional languages. And it is the basic kind of problem
from
> which procedural languages evolved.
>
> The above two examples take a form that provides "locality of reference"
for
> a human reader. Which means that one can go to one location to understand
> the decision process. Whether they are an appropriate use of control-flow
or
> a misuse in view of behavioral constructs depends on what the various
> control flow body statements contain -- one would assume they would be
short
> and succinct often translating the value operation into some behavioral
> construct.
>
> Given one is working in a language that has OO facilities, syntactic
> constructs can be easily misused, just like OO semantics can be easily
> misused for things like value operations. One can take an otherwise
concise
> and clear set of value relationships and completely obscure and obfuscate
> them with extra effort to "objectify" the implementation of the problem
> solution. This is not a black and white issue. It often has to do with the
> granularity/scale of the problem and as a problem evolves it may well need
> to be "refactored" to express the solution using more or less of the
"pure"
> object facilities available.
>

************************************
************************************

> From a design point of view the question of using some form of "if"
> conditionals versus a dispatched behavior mechanism cannot be determined
> without understanding more about the problem itself.
>
> Under what situation is this better (before answering look at the more
> reasonable approach next):
> ---------------------------------------------------------
> | dispatchTable |
> (dispatchTable := Dictionary new)
> at: 'abc' put: #someSelectorA:with:;
> at: 'def' put: #someSelectorB;
> at: 'xyz' put: #someSelectorC:.
> selector := dispatchTable at: aString ifAbsent: [...].
> (expr) perform: selector withArguments: ("what goes here?")
>
> The above approach introduces many questions and does nothing to clarify
> intent, improve readability, consistency, maintainability.
>
> Or (one possibly reasonable solution for a complex case):
>
> Noting that in the "simple localized case" even this is slower, more
effort
> to code and potentially understand, and requires more complex logic for
the

> programmer because now there are two methods and one of them requires some
> initialize lifecycle design (why do this unless the problems
> scope/complexity makes it appropriate?)
> ---------------------------------------------------------
> SomeClass metaclass>>initialize
> (dispatchTable := Dictionary new)
> ...
> SomeClass>>aMethodSelector...
> selector := dispatchTable at: aString ifAbsent: [...].
> (expr)
> perform: selector
> withArguments: ("what goes here? -- could use blocks")
> ---------------------------------------------------------
>
> As my original comments stated, the decision about when to choose one or
> another form of decision making algorithm depends on the problem and its
> level of complexity:
>
> I.E., Once Again:
> Given one is working in a language that has OO facilities, syntactic
> constructs can be easily misused, just like OO semantics can be easily
> misused for things like value operations. One can take an otherwise
concise
> and clear set of value relationships and completely obscure and obfuscate
> them with extra effort to "objectify" the implementation of the problem
> solution. This is not a black and white issue. It often has to do with the
> granularity/scale of the problem and as a problem evolves it may well need
> to be "refactored" to express the solution using more or less of the
"pure"
> object facilities available.
>


Reply | Threaded
Open this post in threaded view
|

Re: [Fwd: Case statements, decision trees, and good OO design]

tcorey
re:  'I would suggest that it does not, in general, address all the
issues or cases for software development across the entire spectrum.'

Of course it doesn't.

I worked in an engineering environment writing software for an
intelligent gripper (for a robot) that had to process real time data.
The project manager made most of the decisions about what language to
use (which was Pascal), environment, etc.  After the system was
implemented, it was found to be too slow.  The PM had us go thru the
code and short circuit loops by doing a break as soon as possible, use
case statements, etc.  The code improved by only a few milliseconds.

What I am saying is, I find it to believe that an ST switch statement
makes the difference between an acceptable software solution and an
unacceptable one.  However, good OO practice is sacrificed by using
them, IMHO.

--tc


Sent via Deja.com http://www.deja.com/
Before you buy.


Reply | Threaded
Open this post in threaded view
|

Re: [Fwd: Case statements, decision trees, and good OO design]

lopemanc
Simple fact is that every version of Smalltalk is littered with the
equivalent of case statements.  All you need to do is look for a nested if
statement and you have a pretty good chance of replacing it with a case
statement and making more readable and probably faster.

Chris Lopeman
Object Link Inc.

[hidden email] wrote:

> re:  'I would suggest that it does not, in general, address all the
> issues or cases for software development across the entire spectrum.'
>
> Of course it doesn't.
>
> I worked in an engineering environment writing software for an
> intelligent gripper (for a robot) that had to process real time data.
> The project manager made most of the decisions about what language to
> use (which was Pascal), environment, etc.  After the system was
> implemented, it was found to be too slow.  The PM had us go thru the
> code and short circuit loops by doing a break as soon as possible, use
> case statements, etc.  The code improved by only a few milliseconds.
>
> What I am saying is, I find it to believe that an ST switch statement
> makes the difference between an acceptable software solution and an
> unacceptable one.  However, good OO practice is sacrificed by using
> them, IMHO.
>
> --tc
>
> Sent via Deja.com http://www.deja.com/
> Before you buy.


Reply | Threaded
Open this post in threaded view
|

Re: [Fwd: Case statements, decision trees, and good OO design]

Richard MacDonald
Chris Lopeman <[hidden email]> wrote in message
news:[hidden email]...
> Simple fact is that every version of Smalltalk is littered with the
> equivalent of case statements.  All you need to do is look for a nested if
> statement and you have a pretty good chance of replacing it with a case
> statement and making more readable and probably faster.
>
Right. Or. . .
I have a parent object aggregating a collection of children stored
by keys, i.e., using a Dictionary. Very common pattern, is it not :-?
Now I need to send a message to one of the children based on
matching a key.
So, its match the key, find the value and send a message to it.
Uh, that's a case statement.


Reply | Threaded
Open this post in threaded view
|

Re: [Fwd: Case statements, decision trees, and good OO design]

Costas Menico
No matter how bad it is, people  make their own case/if elseif
classes.  But the bigger problem is that there is no standardized
class that we all can adhere to. And thats the shame of it.  

Costas Menico

"Richard MacDonald" <[hidden email]> wrote:

>Chris Lopeman <[hidden email]> wrote in message
>news:[hidden email]...
>> Simple fact is that every version of Smalltalk is littered with the
>> equivalent of case statements.  All you need to do is look for a nested if
>> statement and you have a pretty good chance of replacing it with a case
>> statement and making more readable and probably faster.
>>
>Right. Or. . .
>I have a parent object aggregating a collection of children stored
>by keys, i.e., using a Dictionary. Very common pattern, is it not :-?
>Now I need to send a message to one of the children based on
>matching a key.
>So, its match the key, find the value and send a message to it.
>Uh, that's a case statement.
>
>


Reply | Threaded
Open this post in threaded view
|

Re: [Fwd: Case statements, decision trees, and good OO design]

tcorey
In reply to this post by lopemanc
What your saying is there is bad code in any language.  I don't
disagree with you.

--tc


In article <[hidden email]>,
  Chris Lopeman <[hidden email]> wrote:
> Simple fact is that every version of Smalltalk is littered with the
> equivalent of case statements.  All you need to do is look for a
nested if
> statement and you have a pretty good chance of replacing it with a
case
> statement and making more readable and probably faster.
>
> Chris Lopeman
> Object Link Inc.
>
> [hidden email] wrote:
>
> > re:  'I would suggest that it does not, in general, address all the
> > issues or cases for software development across the entire
spectrum.'
> >
> > Of course it doesn't.
> >
> > I worked in an engineering environment writing software for an
> > intelligent gripper (for a robot) that had to process real time
data.
> > The project manager made most of the decisions about what language
to
> > use (which was Pascal), environment, etc.  After the system was
> > implemented, it was found to be too slow.  The PM had us go thru the
> > code and short circuit loops by doing a break as soon as possible,
use
> > case statements, etc.  The code improved by only a few milliseconds.
> >
> > What I am saying is, I find it to believe that an ST switch
statement

> > makes the difference between an acceptable software solution and an
> > unacceptable one.  However, good OO practice is sacrificed by using
> > them, IMHO.
> >
> > --tc
> >
> > Sent via Deja.com http://www.deja.com/
> > Before you buy.
>
>


Sent via Deja.com http://www.deja.com/
Before you buy.


Reply | Threaded
Open this post in threaded view
|

Re: [Fwd: Case statements, decision trees, and good OO design]

lopemanc
No, that is not what I am saying.  What I am saying is that since most of us
admired Smalltalk (The base system) even to the point of basing our careers
on it,  and it has many occurrences of the type of statement, then that type
of statement cant be all that bad.

To add to this, I have seen far too many object oriented systems that have
created far too many objects to do the job.  Making them nearly impossible
to understand, and delegate responsibility so much that nothing ever
actually gets done.  I will not create a new class or classes to do the job
of a flag.  Nor will I do it to do the job of a nested if statement that is
used by one place; and would have each new class with a single method used
to handle what the case statement can do.

Chris Lopeman
Object Link Inc.

[hidden email] wrote:

> What your saying is there is bad code in any language.  I don't
> disagree with you.
>
> --tc
>
> In article <[hidden email]>,
>   Chris Lopeman <[hidden email]> wrote:
> > Simple fact is that every version of Smalltalk is littered with the
> > equivalent of case statements.  All you need to do is look for a
> nested if
> > statement and you have a pretty good chance of replacing it with a
> case
> > statement and making more readable and probably faster.
> >
> > Chris Lopeman
> > Object Link Inc.
> >
> > [hidden email] wrote:
> >
> > > re:  'I would suggest that it does not, in general, address all the
> > > issues or cases for software development across the entire
> spectrum.'
> > >
> > > Of course it doesn't.
> > >
> > > I worked in an engineering environment writing software for an
> > > intelligent gripper (for a robot) that had to process real time
> data.
> > > The project manager made most of the decisions about what language
> to
> > > use (which was Pascal), environment, etc.  After the system was
> > > implemented, it was found to be too slow.  The PM had us go thru the
> > > code and short circuit loops by doing a break as soon as possible,
> use
> > > case statements, etc.  The code improved by only a few milliseconds.
> > >
> > > What I am saying is, I find it to believe that an ST switch
> statement
> > > makes the difference between an acceptable software solution and an
> > > unacceptable one.  However, good OO practice is sacrificed by using
> > > them, IMHO.
> > >
> > > --tc
> > >
> > > Sent via Deja.com http://www.deja.com/
> > > Before you buy.
> >
> >
>
> Sent via Deja.com http://www.deja.com/
> Before you buy.


Reply | Threaded
Open this post in threaded view
|

Re: [Fwd: Case statements, decision trees, and good OO design]

tcorey
In article <[hidden email]>,
Chris Lopeman <[hidden email]> wrote:

>No, that is not what I am saying.  What I am saying is that since most
>of us admired Smalltalk (The base system) even to the point of basing
>our careers on it,

Okay that is pretty clear . . .

>and it has many occurrences of the type of statement,

Okay.

>then that type of statement cant be all that bad.

Now I am having trouble relating the pieces of the sentence.  I've
known people that have based their careers on Smalltalk and have
written terrible code.  I don't see how one relates to the other tho.
Should someone strive to become better at their chosen career?  My
answer would be yes but not everyone agrees with that and 'strive to be
better' has different meanings to different people.  The result can be
bad code.  Also, sometimes a project has time and budget constraints
and the code suffers.

>To add to this, I have seen far too many object oriented systems that
>have created far too many objects to do the job.

You've seen bad code, so have I.

>Making them nearly impossible to understand, and delegate
>responsibility so much that nothing ever actually gets done.

Yes, we've both seen bad code.

>I will not create a new class or classes to do the job of a flag.  Nor
>will I do it to do the job of a nested if statement that is used by
>one place; and would have each new class with a single method used
>to handle what the case statement can do.

And that is your decision to make.  I don't think we are going to be
able to enumerate all the cases and how to handle them in a forum
message.

>Chris Lopeman
>Object Link Inc.

--tc


Sent via Deja.com http://www.deja.com/
Before you buy.


Reply | Threaded
Open this post in threaded view
|

Re: [Fwd: Case statements, decision trees, and good OO design]

Richard MacDonald
In reply to this post by lopemanc
Chris Lopeman <[hidden email]> wrote in message
news:[hidden email]...
> No, that is not what I am saying.  What I am saying is that since most of
us
> admired Smalltalk (The base system) even to the point of basing our
careers
> on it,  and it has many occurrences of the type of statement, then that
type
> of statement cant be all that bad.
>
I believe we should minimize case statements and use
polymorphism wherever possible, but:

(1) too much of a good thing makes code hard to read, as stated by Chris

(2) there is a point where it "bottoms out" and if-then-else is required,
i.e,.
case is *required*. I think :-)

We had a discussion about this perhaps a year ago and I'm sure we determined
case statements were necessary at some point. Unfortunately, I'm drawing a
blank on the definitive argument. Perhaps its was just that eliminating them
would require doing self-brain-surgery on the base classes, such as Number.

Interesting subject: Are case statements necessary for even a pure OO
language?


Reply | Threaded
Open this post in threaded view
|

Re: [Fwd: Case statements, decision trees, and good OO design]

Terry Raymond
Case statements are quite useful when parsing external information,
i.e. data from other software or external files.  However, for code
that is completely under control of a smalltalk developer, and information
that is completely internal, I don't know of any reason to use a case
statement.

--
Terry
===========================================================
Terry Raymond       Smalltalk Professional Debug Package
Crafted Smalltalk   *Breakpoints* and *Watchpoints* for
19 Tilley Ave.                  VW and ENVY/Developer
Newport, RI  02840
(401) 846-6573      [hidden email]
http://www.craftedsmalltalk.com
===========================================================


"Richard MacDonald" <[hidden email]> wrote in message
news:kYnM5.15194

> We had a discussion about this perhaps a year ago and I'm sure we determined
> case statements were necessary at some point. Unfortunately, I'm drawing a
> blank on the definitive argument. Perhaps its was just that eliminating them
> would require doing self-brain-surgery on the base classes, such as Number.
>
> Interesting subject: Are case statements necessary for even a pure OO
> language?
>
>


Reply | Threaded
Open this post in threaded view
|

Re: [Fwd: Case statements, decision trees, and good OO design]

Bob Jarvis
In article <8tt3ii$[hidden email]>,
  "Terry Raymond" <[hidden email]> wrote:
> Case statements are quite useful when parsing external information,
> i.e. data from other software or external files.  However, for code
> that is completely under control of a smalltalk developer, and
information
> that is completely internal, I don't know of any reason to use a case
> statement.

In my experience both of the above statements are correct.  The only
time I've "really needed" a case statement, and devolved to writing a
bunch of 'if' statements, was when trying to make decisions about the
proper classes to create based on values returned from system calls.
Other than that, my desire for a case statement has always turned out
to be my brain being lazy, recalling years of using case statements in
other languages, and not wanting to think about how to use objects to
solve the problem at hand.

Interestingly, even in the cases where I've used a case statement to
handle those nasty values returned by the operating system, in the end
I've gotten better performance out of a more object-oriented solution.
If anyone wants specifics I'll be happy to discuss it.
--
Bob Jarvis
Compuware @ Timken


Sent via Deja.com http://www.deja.com/
Before you buy.