Topic: enums and switch statements based on them


Author: faqtoriX@hotmail.com (Factory)
Date: 1999/03/04
Raw View
On 26 Feb 1999 16:21:15 -0500, James Kuyper <kuyper@wizard.net> wrote:
>C++ has switch statements, just like C; people aren't avoiding them
>because it's a fad; they're using virtual functions because the result,
>when done properly, is usually easier to understand, maintain, and
scale
>up.
  Hmm when I am coding in C++ (in an oo manner) I generally don't come
across situations where I need to use switch statement, that is when I
end up looking at how to implement a member function I very rarely
come to the conclusion that a switch statement could be used. So for
me, there isn't some large philosophical question about using
switches, I use then wherever useful. Same goes for enums.

>> In human planet, (not in geek planet) being able to SEE ALL the
>> code for the special situations TOGETHER without all the unnecessary
>> white noise of virtual fn declarations and accompanying comments
>> is of prime importance.
  Yar, but it's geeks (ie. not humans) who write code. Geeks are funny
ppl they understand stuff that is written in their wierd geek oo
concepts, if you were to write it in non-geek might the geeks find it
a bit hard to understand?
  To who is it far more important to understand src code, geeks or
humans?
...
>> walk-thru all this code, and they don't know a single thing about
>> C++ (a pat on my own back).  If I did virtual fns, the usually
productive
>> meeting would go like this...
>>
>>    Me:  Here, this non-virtual fn does common code 1.
>>    Boss:  Can I see it?
>>    Me:  Its here on these extra pages.
>>    Boss: Ok.  After that's done, ...
>>    Me: then this virtual fn call in invoked, and the "Right Stuff"
gets done.
>>    Boss: <Silence and Shock>
>>    Me: Don't worry boss, it works right.
>>    Boss: What processing is done, when the right thing is done?
>>    Me: here's another set of pages containing that code...
>>    Boss: .....

  Hmm the last time someone thought that it would be a Great Idea (tm)
that ppl who don't know how to code could read code the computer
science world got Cobol. I would like to think that the computer
science world can learn by it's mistakes. :)

 -Factory (faqtori at hotmail.com)

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Jamie Hamilton" <jhamilton@Radix.Net>
Date: 1999/03/02
Raw View
Andrei Alexandrescu wrote in message <36d96103.0@10.1.1.65>...
>
>Not necessarily. What about maps/hashtables of pointers to static
>methods keyed by enums?
>

My point is that you can't do it with virtual functions. You've got
to update something outside the class whenever you add a class.

Ideally, you want to limit that "something" to one place, with
a technique like you describe perhaps, but it's still conceptually
a variation on a switch statement.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: David R Tribble <dtribble@technologist.com>
Date: 1999/02/26
Raw View
Sarma Seetamraju wrote:
> HPP file:
>        enum EEE { One, Two, Three, NO_MORE }
>
> CPP file #1:
>        .....
>        enum EEE variable;
>        .....
>        switch ( variable )
>        {   case One: .....
>                      break;
>            case Two: .....
>                      break;
>            case Three: .....
>                      break;
>        }
>
> Similarly in other CPP files.
>
> If I add another ENUM constant (happens all the time)
> (let's say "Four"), then I want all the code in the
> CPP files to BREAK compilation.  I don't like the
> "default" solution (with a throw/assert), which is
> only detected at run-time the day before my vacation begins.

I always add a "version number" macro to my type declarations which
reflects the "editing revision number" of those types (an enum type
in this case):

    #define EEE_VERS    1   // Enum revision number
    enum EEE { ... }

Then I check the enum version in all my code that uses it at compile
time:

    void foo(EEE v)
    {
    #if EEE_VERS != 1
    #error enum EEE has changed
    #endif
        switch (v)
        {
            ...
        }
    }

Now whenever I change enum EEE, typically by adding a new constant
member to it, I increment its version macro as well.  Viol   !  All
of my code that assumes a particular version of my enum type now
gives a compile error, which forces me to examine, and thus
update, my now-out-of-date code.

The advantage that this approach has over the other suggestion
of checking for 'NO_MORE == Three + 1' is that it does not rely
on the value of any of the enum constants, nor on the knowledge
of their declaration order.  (Consider what happens if I merely
swap the order of Two and Three without adding another constant.)

Another technique is to specify the enum version you're expecting
prior to including its header file in your source files:

    #define NEED_EEE_VERS   1   // Expect version 1
    #include "eee.hpp"

The header file for enum EEE contains a compile-time check:

    #if NEED_EEE_VERS != EEE_VERS
    #error Expected/supplied versions of enum EEE differ
    #endif

I also use these techniques for class and POD declarations.

(Some may argue against using preprocessor macros, but I have yet
to find a suitable sustitute for these kinds of uses.)

-- David R. Tribble, dtribble@technologist.com --

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]






Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 1999/02/26
Raw View
"Andrei Alexandrescu" <alexandrescua@micromodeling.com> writes:

>Fergus Henderson wrote in message <7b0qkh$t3v$1@mulga.cs.mu.OZ.AU>...
>>For example, when you're writing a compiler, it may be far more common
>>to add a new pass over your data structure than it is to add a new
>>alternative, and it is certainly clearer to have all the code for
>>handling e.g. "constant propagation" together rather than having all
>>the code handling e.g. "while statements" in the one spot.
>
>I agree with you. I think a parser is a classic example of a case
>where virtuals aren't the most viable solution. But why you don't like
>Visitor either?

Well, it's just a bit cumbersome in comparison to e.g. pattern matching.

Consider the following Haskell code:

 data Tree a = Empty | Branch { elem::a, left::Tree A, right::tree A }

 contains :: (a -> a -> Bool) -> a -> Tree a -> Bool
 contains less searchval tree = search tree where
  search Empty = False
  search (Branch x l _) | less searchval x = search l
  search (Branch x _ r) | less x searchval = search r
  search _ = True

Or even consider the following more verbose Pizza equivalent:

 class Tree<A> {
     case Empty;
     case Branch(A elem, Tree<A> left, Tree<A> right);

     public boolean contains((A, A) -> boolean less, A searchval) {
  switch (this) {
  case Empty:
      return false;
  case Branch(A elem, Tree<A> left, Tree<A> right):
      if (less(searchval, elem))
   return left.contains(less, searchval);
      else if (less(elem, searchval))
   return right.contains(less, searchval);
      else
   return true;
  }
     }
 };

That's nice, simple, and it all fits on a single screen.
You could do the same kind of thing with the visitor pattern,
but instead of one class and one function, you'll have two interfaces,
three classes, and lots of functions:

 interface Tree<A> {
     void accept(TreeVisitor<A> v);
 }

 class Empty<A> implements Tree<A> {
     public void accept(TreeVisitor<A> v) { v.visitEmpty(this); }
 }

 class Branch<A> implements Tree<A> {
     A elem;
     Tree<A> left, right;
     public void accept(TreeVisitor<A> v) { v.visitBranch(this); }
 }

 interface TreeVisitor<A> {
     void visitEmpty(Empty<A> x);
     void visitBranch(Branch<A> x);
 }

 class SearchVisitor<A> implements TreeVisitor<A> {
     A searchval;
     (A, A) -> boolean less;
     bool result;
     SearchVisitor<A> ((A, A) -> boolean l, A s) {
  less = l;
  searchval = s;
     }
     public bool succeeded() { return result; }
     public void visitEmpty(Empty x) { result = false; }
     public void visitBranch(Branch x) {
         if (less(searchval, x.elem))
      x.left.accept(this);
         else if (less (searchval, x.elem)
      x.right.accept(this);
         else
      result = true;
     }
 }

That's significantly more code.  And then calling it is also more difficult:
instead of

 Tree<Foo> t;
 ...
 if (t.contains(Foo.less, 42)) { ... }

we now have

 Tree<Foo> t;
 ...
 SearchVisitor<foo> v(Foo.less, 42);
 v.accept(t);
 if (v.succeeded) { ... }

Of course we could encapsulate that calling sequence in yet another
function, but by now its all starting to get rather complex in
comparison to the eight-line Haskell program that we started off with.

If you were doing pattern matching more than one level deep, the
visitor pattern would come out even worse.

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "Binaries may die
WWW: <http://www.cs.mu.oz.au/~fjh>  |   but source code lives forever"
PGP: finger fjh@128.250.37.3        |     -- leaked Microsoft memo.

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]






Author: James Kuyper <kuyper@wizard.net>
Date: 1999/02/26
Raw View
Sarma Seetamraju wrote:
...
> But consider the following flow of business logic (which actually
> quite well maps to human/english descriptions of the same).
>
>            business-logic-begins...
>            ....
>            do common handling #1
>            ....
>            switch() {
>               special situation #1 : ....
>               special situation #2 : ....
>               special situation #3 : ....
>               ....
>            }
>            ....
>            do common handling #2
>            ....
>            switch () again on the same variable...
>                ......
>            }
>            ....
>            do common handling #3
>            ....
>
> Imagine writing that in OO fashion.  Using virtual functions
> to describe the above business logic is using a spatula to
> eat cereal from the cereal bowl, just because you have a spatula :-)

C++ has switch statements, just like C; people aren't avoiding them
because it's a fad; they're using virtual functions because the result,
when done properly, is usually easier to understand, maintain, and scale
up.

...
> In human planet, (not in geek planet) being able to SEE ALL the
> code for the special situations TOGETHER without all the unnecessary
> white noise of virtual fn declarations and accompanying comments
> is of prime importance.

To put all the code for special situations together is the purpose of
polymorphic classes. Each derived class represents a single special
case, and all of the code needed to handle that special case is part of
that class, rather than being distributed across many different switch()
statements throughout your program.

>
> I wish I was doing 'neat' stuff like others, but once I had the
> 'core' stuff finished, all code looks like COBOL :-)
> After all, its business logic, and humans (not geeks) think
> in unequivably procedural manner.  Me and my bosses actually

Actually, when you have more experience with object-oriented design,
you'll find that a lot of the thinking you done all your life was
object-oriented; you just didn't recognize it as such.

> walk-thru all this code, and they don't know a single thing about
> C++ (a pat on my own back).  If I did virtual fns, the usually productive
> meeting would go like this...
>
>    Me:  Here, this non-virtual fn does common code 1.
>    Boss:  Can I see it?
>    Me:  Its here on these extra pages.
>    Boss: Ok.  After that's done, ...
>    Me: then this virtual fn call in invoked, and the "Right Stuff" gets done.
>    Boss: <Silence and Shock>
>    Me: Don't worry boss, it works right.
>    Boss: What processing is done, when the right thing is done?
>    Me: here's another set of pages containing that code...
>    Boss: .....

Virtual functions embody encapsulation. When examining the design of a
polymorphic class, you SHOULD be describing only what the virtual
function is responsible for doing; not worrying about whether it's doing
it "Right". The time to discuss how the virtual function works is when
reviewing each of the derived classes that actually override it, and
when you do, you'll find all of the relevant code there, right in front
of you. The ability to seperate what it does from the details of how it
does it, is one of the cornerstones of OO design.

If your boss is perplexed by your description of the design, then either
the description or the design or the boss is defective. Object-oriented
design using virtual functions can be good design (it can also be
lousy). When you're using C++, switches are seldom the better design
choice.

Incidentally, your bosses shouldn't be walking through your code unless
he's competent to understand it. He should only be involved in the
design walk-throughs. The design documents should be written as much as
possible in a language independent way. How object-oriented designs
should be documented is something I've less experience with than I'd
like, but it can be done.


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]





Author: sbnaran@localhost.localdomain (Siemel Naran)
Date: 1999/02/26
Raw View
On 26 Feb 1999 15:51:21 GMT, David R Tribble <dtribble@technologist.com> wrote:

>I always add a "version number" macro to my type declarations which
>reflects the "editing revision number" of those types (an enum type
>in this case):
>
>    #define EEE_VERS    1   // Enum revision number
>    enum EEE { ... }

Cool.  But use constants instead of #defines.  This way you can have
many variables EEE_VERS, each in its own namespace.


>Then I check the enum version in all my code that uses it at compile
>time:
>
>    void foo(EEE v)
>    {
>    #if EEE_VERS != 1
>    #error enum EEE has changed
>    #endif

     assert(EEE_VERS==1 && "enum EEE should be version 1");

If you compile with NDEBUG on and EEE_VERS is known to be 1, then
the compiler should optimize away the above line -- this is the
optimization of dead code elimination.  But the compiler may give
you the warning "assertion is always #true", which is something
you don't want to see.  If you compile with NDEBUG on and EEE_VERS
is known to be different from 1, then, unfortunately, the best you
get is a runtime error.  However, a compiler may give the warning
"assertion is always #false", and this is a warning you do want to
see.  I'm not sure if any compilers give such warnings.


>Now whenever I change enum EEE, typically by adding a new constant
>member to it, I increment its version macro as well.  Viol   !  All
>of my code that assumes a particular version of my enum type now
>gives a compile error, which forces me to examine, and thus
>update, my now-out-of-date code.

Good.  But another idea is to use using-declarations and typedefs.

// EEE.h
// include guard
namespace E { namespace v1 { enum EEE { ... }; } }

// file.c
#include "file.h" // uses namespace File
#include "EEE.h"
typedef E::v1::EEE EEE; // enforce that we're using version 1
//using E::v1;
void File::f() { ... } // use EEE



>The advantage that this approach has over the other suggestion
>of checking for 'NO_MORE == Three + 1' is that it does not rely
>on the value of any of the enum constants, nor on the knowledge
>of their declaration order.  (Consider what happens if I merely
>swap the order of Two and Three without adding another constant.)

Good.


>Another technique is to specify the enum version you're expecting
>prior to including its header file in your source files:
>
>    #define NEED_EEE_VERS   1   // Expect version 1
>    #include "eee.hpp"
>
>The header file for enum EEE contains a compile-time check:
>
>    #if NEED_EEE_VERS != EEE_VERS
>    #error Expected/supplied versions of enum EEE differ
>    #endif

Good too.
One can supply NEED_EEE_VERS in the command line invocation of
the compiler (which one actually writes in the Makefile).


>I also use these techniques for class and POD declarations.
>
>(Some may argue against using preprocessor macros, but I have yet
>to find a suitable sustitute for these kinds of uses.)

--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: sbnaran@fermi.ceg.uiuc.edu (Siemel Naran)
Date: 1999/02/27
Raw View
On 26 Feb 1999 22:55:26 -0500, Siemel Naran

Got a typo.  Should be
   "If you compile with NDEBUG off"
in both places:

>If you compile with NDEBUG on and EEE_VERS is known to be 1, then
>the compiler should optimize away the above line -- this is the
>optimization of dead code elimination.  But the compiler may give
>you the warning "assertion is always #true", which is something
>you don't want to see.  If you compile with NDEBUG on and EEE_VERS
>is known to be different from 1, then, unfortunately, the best you
>get is a runtime error.  However, a compiler may give the warning
>"assertion is always #false", and this is a warning you do want to
>see.  I'm not sure if any compilers give such warnings.

--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]





Author: "Jamie Hamilton" <jhamilton@Radix.Net>
Date: 1999/02/28
Raw View

Sarma Seetamraju <sarma@usa.net> writes:

>
>In human planet, (not in geek planet) being able to SEE ALL the
>code for the special situations TOGETHER without all the unnecessary
>white noise of virtual fn declarations and accompanying comments
>is of prime importance.


I think there are a lot of appropriate places to uses enums over
inheritance, and I certainly agree that inheritance tends
to be overused by many C++ programmers. In at least one
case -- polymorphic object creation -- it looks like we will
always be stuck with some variation of switching on enums,
so we need a good way to deal with it.

However, I think "seeing all the code in one place" just
isn't a relevant factor. You're basically saying that function
call, whether virtual or not, is an unnecessary fluff that
generates "white noise". You'll find few takers for that
opinion. Although I have had programmers who insisted
on putting all their code in main(), they found higher happiness
with an alternative career choice.

If you want to quickly see what all the different classes do in a given
case, just reorganize your .cpp files so that all the implementations
of a given virtual function are in a single file, right next
to each other. There's no law saying you have to organize your source
files around classes -- organize them around yourself, and the
way you use them.






[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]






Author: "Andrei Alexandrescu" <alexandrescua@micromodeling.com>
Date: 1999/03/01
Raw View
Jamie Hamilton wrote in message <7b99l6$326$1@news1.Radix.Net>...
[snip]
>I think there are a lot of appropriate places to uses enums over
>inheritance, and I certainly agree that inheritance tends
>to be overused by many C++ programmers. In at least one
>case -- polymorphic object creation -- it looks like we will
>always be stuck with some variation of switching on enums,
>so we need a good way to deal with it.

Not necessarily. What about maps/hashtables of pointers to static
methods keyed by enums?

Andrei

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]





Author: hoshi@sra.co.jp (Hoshi Takanori)
Date: 1999/02/25
Raw View
In article <7af5nn$i2k$1@nnrp1.dejanews.com> Sarma Seetamraju <sarma@usa.net> writes:

> If I add another ENUM constant (happens all the time)
> (let's say "Four"), then I want all the code in the
> CPP files to BREAK compilation.  I don't like the
> "default" solution (with a throw/assert), which is
> only detected at run-time the day before my vacation begins.

gcc -Wall issues a warning:

foo.cc: In function `void foo(enum EEE)':
foo.cc:12: warning: enumeration value `NO_MORE' not handled in switch

hoshi

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]





Author: "Andrei Alexandrescu" <alexandrescua@micromodeling.com>
Date: 1999/02/25
Raw View
Fergus Henderson wrote in message <7b0qkh$t3v$1@mulga.cs.mu.OZ.AU>...
>For example, when you're writing a compiler, it may be far more
common
>to add a new pass over your data structure than it is to add a new
>alternative, and it is certainly clearer to have all the code for
>handling e.g. "constant propagation" together rather than having all
>the code handling e.g. "while statements" in the one spot.


I agree with you. I think a parser is a classic example of a case
where virtuals aren't the most viable solution. But why you don't like
Visitor either?
As I learned in one of Scott Meyers' talks, Visitor doesn't have much
to do with visitation. It's a pattern that reverses the tradeoffs of
the virtuals:
1. With virtuals: add a method: hard; derive: simple
2. With Visitor: add a method: simple; derive: hard

>There's a lot to be said for languages such as
>Pizza (a Java extension) and Ada, which have good support for
>discriminated unions, as do most modern functional languages.
>C++ unfortunately does not have good support for discriminated
>unions.  Using switches, enums and unions works, but there's much
>less static checking than you can get in other languages.


What would be a good example of a discriminated union usage that you
are thinking of? Could you dwell on this subject a bit? Thanks.

Andrei


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]





Author: David R Tribble <dtribble@technologist.com>
Date: 1999/02/26
Raw View
"Andrei Alexandrescu" <alexandrescua@micromodeling.com> wrote:
>> Aside from the fact that you actually describe why switch-based
>> programming is bad, here's the solution to your problem (I resume an
>> older thread over here):

Sarma Seetamraju wrote:
> Your simple solution does the job, and I will try to implement such a
> one soon -- no copyrights here right?
>
> But consider the following flow of business logic (which actually
> quite well maps to human/english descriptions of the same).
>
[omitted code which uses virtual funcs instead of switches]
>
> Imagine writing that in OO fashion.  Using virtual functions
> to describe the above business logic is using a spatula to
> eat cereal from the cereal bowl, just because you have a spatula :-)
> Ever try maintaining code full of virtual fn calls (even if you
> are the only person writing such code)?
>
> In human planet, (not in geek planet) being able to SEE ALL the
> code for the special situations TOGETHER without all the unnecessary
> white noise of virtual fn declarations and accompanying comments
> is of prime importance.

I agree; sometimes using virtual functions in place of a few switches
and enum constants is overkill.

Consider how little work is actually required for a simple
three-state switch (with values ON, OFF, and UNSET) when
implemented with an enum, compared to the effort required to
implement a base class and three derived classes with virtual
functions.  Sometimes you need the virtual functions, but many
times it's simply not worth the extra effort to achieve "object-
oriented purity".

-- David R. Tribble, dtribble@technologist.com --


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]





Author: Gerhard Menzl <gerhard.menzl@sea.ericsson.se>
Date: 1999/02/24
Raw View
Sarma Seetamraju wrote:

> In human planet, (not in geek planet) being able to SEE ALL the
> code for the special situations TOGETHER without all the unnecessary
> white noise of virtual fn declarations and accompanying comments
> is of prime importance.

For humans, it is impossible to see all the code together. It is a well-known
psychological fact that the human mind is capable of keeping seven things
(plus/minus two) in mind at a time. If you look at a switch statement with just
five special situations, and every special situation requires code that consists
of just five invididual statements, you get more than you can digest at a time.
Unless you completely forego blank lines and comments, it's not even going to fit
on most screens. In any case, you will have to jump back and forth, but you will
never be able to grasp everything at once. As has been explained most aptly by my
co-posters, polymorphism is an excellent way to beat this complexity. It is a way
of saying "handle it accordingly", which is a context-dependent and hence very
human way of looking at things.

But there is more to it than readability. It is much easier to add special cases
when all the special code is contained in one place, i.e. in a specialized class.
Switch statements, on the other hand, behave very much like rabbits. They
multiply. Every time you add (or remove) a special case, you have to scan the
entire application for those switch statements and change them all. Forget but
one, and your program will fail.

>    Me:  Here, this non-virtual fn does common code 1.
>    Boss:  Can I see it?
>    Me:  Its here on these extra pages.
>    Boss: Ok.  After that's done, ...
>    Me: then this virtual fn call in invoked, and the "Right Stuff" gets done.
>    Boss: <Silence and Shock>
>    Me: Don't worry boss, it works right.
>    Boss: What processing is done, when the right thing is done?
>    Me: here's another set of pages containing that code...
>    Boss: .....
>
> I'm not making my bosses look neanderthal, but I think their attitude
> is dead right.   They help the business make the money, consistently.

If your boss feels he has to get into every minute detail of your code, what does
he pay your for? This kind of micro-management is actually a waste of money and
does not help the business at all.

Once upon a time I had a boss like that.

I quit.

Gerhard Menzl


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]





Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 1999/02/24
Raw View
Those who are arguing that you should use inheritance and virtual functions
instead of enums and switches are overstating their case a bit, IMHO.
Certainly there are many times that inheritance and virtual functions
are definitely the best way to do things.  But there are other times
when it's better to group all the code for performing a particular
function together, rather than grouping all the code that handles
a particular alternative.

For example, when you're writing a compiler, it may be far more common
to add a new pass over your data structure than it is to add a new
alternative, and it is certainly clearer to have all the code for
handling e.g. "constant propagation" together rather than having all
the code handling e.g. "while statements" in the one spot.

You can use virtual functions and still group the virtual function
definitions in the way that I have described.  If you do that, you
will get the desired static checking to ensure that you haven't
missed any alternatives.  However, with that organization, every time
you add a new pass, you need to recompile everything.

Another alternative is to use the "Visitor" pattern.  However, that can
be quite cumbersome.  There's a lot to be said for languages such as
Pizza (a Java extension) and Ada, which have good support for
discriminated unions, as do most modern functional languages.
C++ unfortunately does not have good support for discriminated
unions.  Using switches, enums and unions works, but there's much
less static checking than you can get in other languages.

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "Binaries may die
WWW: <http://www.cs.mu.oz.au/~fjh>  |   but source code lives forever"
PGP: finger fjh@128.250.37.3        |     -- leaked Microsoft memo.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Sarma Seetamraju <sarma@usa.net>
Date: 1999/02/18
Raw View
HPP file
       enum EEE { One, Two, Three, NO_MORE }

CPP file # 1
       .....
       enum EEE variable;
       .....
       switch ( variable )
       {   case One: .....
                     break;
           case Two: .....
                     break;
           case Three: .....
                     break;
       }

Similarly in other CPP files.

--------------------------------------------

If I add another ENUM constant (happens all the time)
(let's say "Four"), then I want all the code in the
CPP files to BREAK compilation.  I don't like the
"default" solution (with a throw/assert), which is
only detected at run-time the day before my vacation begins.

A 'grep' could work fine, but for the fact that some
of the files are owned by other developers, and I can't
edit them.

Whenever new ENUM constants are added, there is definitely
new business logic too :-)

Can I do something like the following 3 lines which I can
enforce before/after every switch in every CPP (We developers
are very cooperative and quite sociable) :-

#if Three + 1 != NO_MORE
#error  Drag yourself over to my desk to discuss new ENUM values
#endif

Sarma

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Andrei Alexandrescu" <alexandrescua@micromodeling.com>
Date: 1999/02/18
Raw View
Sarma Seetamraju wrote in message <7af5nn$i2k$1@nnrp1.dejanews.com>...
[snip]

Aside from the fact that you actually describe why switch-based programming
is bad, here's the solution to your problem (I resume an older thread over
here):

template <bool> class static_checker;
template <> class static_checker<true> {};

Now you have to put static_checker to work like this:

static_checker<NO_MORE == Three + 1>();
switch ( variable )
{   case One: .....
        break;
    case Two: .....
        break;
    case Three: .....
        break;
}

You'll get a compile-time error whenever you bump NO_MORE.

Andrei


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]







Author: Marco Dalla Gasperina <marcodg@pacifier.com>
Date: 1999/02/19
Raw View
In comp.lang.c++.moderated Sarma Seetamraju <sarma@usa.net> wrote:
> HPP file
>        enum EEE { One, Two, Three, NO_MORE }

> CPP file # 1
>        .....
>        enum EEE variable;
>        .....
>        switch ( variable )
>        {   case One: .....
>                      break;
>            case Two: .....
>                      break;
>            case Three: .....
>                      break;
>        }

> Similarly in other CPP files.

> --------------------------------------------

> If I add another ENUM constant (happens all the time)

I assume that you can't change the design... otherwise
this is what virtual functions are for... in fact, I
wouldn't be surprised if this very example is their
"raggione d'esistenza" (cheers to Mr. Alexandrescu :-)


> (let's say "Four"), then I want all the code in the
> CPP files to BREAK compilation.  I don't like the
> "default" solution (with a throw/assert), which is
> only detected at run-time the day before my vacation begins.

Here's something, but I fear anything we come up with can be
circumvented.  But, let's assume you're guarding against
Murphy and not Macchiavelli

enum EEEE { One, Two, Three }; // don't need "NO_MORE"

// when an enum is added to the end of the list, change the
// conditional expression inside this struct to test for
// the equality with the last element
template< EEE n > struct EEEChecker {
   char x[ (n==Three) ? 1 : -1 ];
};

Then, before every switch statement place the line

EEEChecker<Three> dummy;

This way, if 'Three' is no longer the last enum, the code
won't compile because it will attempt to create an array
with -1 elements.

The obvious way to circumvent this is to forget to change
the template definition.  Maybe there's a clever way to
munge the two definitions so only one textual change is
required?

marco
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/02/19
Raw View
Sarma Seetamraju wrote:
>
> HPP file
>        enum EEE { One, Two, Three, NO_MORE }
>
> CPP file # 1
>        .....
>        enum EEE variable;
>        .....
>        switch ( variable )
>        {   case One: .....
>                      break;
>            case Two: .....
>                      break;
>            case Three: .....
>                      break;
>        }
>
> Similarly in other CPP files.
>
> --------------------------------------------
>
> If I add another ENUM constant (happens all the time)
> (let's say "Four"), then I want all the code in the
> CPP files to BREAK compilation.  I don't like the
> "default" solution (with a throw/assert), which is
> only detected at run-time the day before my vacation begins.
>
> A 'grep' could work fine, but for the fact that some
> of the files are owned by other developers, and I can't
> edit them.
>
> Whenever new ENUM constants are added, there is definitely
> new business logic too :-)
>
> Can I do something like the following 3 lines which I can
> enforce before/after every switch in every CPP (We developers
> are very cooperative and quite sociable) :-
>
> #if Three + 1 != NO_MORE
> #error  Drag yourself over to my desk to discuss new ENUM values
> #endif

No. But you can do the following (untested):

template<bool b> struct assertion {};
template<> struct assertion<true> { class passed {}; }

switch (variable)
{
  assertion<Three+1==NO_MORE>::passed();

  case One:
    ...
    break;
  case Two:
    ...
    break;
  case Three:
    ...
    break;
}

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]






Author: stephen.clamage@sun.com (Steve Clamage)
Date: 1999/02/20
Raw View
Sarma Seetamraju <sarma@usa.net> writes:

>HPP file
>       enum EEE { One, Two, Three, NO_MORE }

>CPP file # 1
>       .....
>       enum EEE variable;
>       .....
>       switch ( variable )
>       {   case One: .....
>                     break;
>           case Two: .....
>                     break;
>           case Three: .....
>                     break;
>       }

>Similarly in other CPP files.

>--------------------------------------------

>If I add another ENUM constant (happens all the time)
>(let's say "Four"), then I want all the code in the
>CPP files to BREAK compilation.  I don't like the
>"default" solution (with a throw/assert), which is
>only detected at run-time the day before my vacation begins.

Have you considered using inheritance and virtual functions
instead of enums and switch statements? Such a design is not
always feasible, but when it is, the problem solves itself.
You derive a new class and implement the virtual functions,
and you are done.

--
Steve Clamage, stephen.clamage@sun.com

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]






Author: Sarma Seetamraju <sarma@usa.net>
Date: 1999/02/20
Raw View
"Andrei Alexandrescu" <alexandrescua@micromodeling.com> wrote:
> Aside from the fact that you actually describe why switch-based programming
> is bad, here's the solution to your problem (I resume an older thread over
> here):

Your simple solution does the job, and I will try to implement such a one
soon -- no copyrights here right?

But consider the following flow of business logic (which actually
quite well maps to human/english descriptions of the same).

           business-logic-begins...
           ....
           do common handling #1
           ....
           switch() {
              special situation #1 : ....
              special situation #2 : ....
              special situation #3 : ....
              ....
           }
           ....
           do common handling #2
           ....
           switch () again on the same variable...
               ......
           }
           ....
           do common handling #3
           ....

Imagine writing that in OO fashion.  Using virtual functions
to describe the above business logic is using a spatula to
eat cereal from the cereal bowl, just because you have a spatula :-)
Ever try maintaining code full of virtual fn calls (even if you
are the only person writing such code)?

In human planet, (not in geek planet) being able to SEE ALL the
code for the special situations TOGETHER without all the unnecessary
white noise of virtual fn declarations and accompanying comments
is of prime importance.

I wish I was doing 'neat' stuff like others, but once I had the
'core' stuff finished, all code looks like COBOL :-)
After all, its business logic, and humans (not geeks) think
in unequivably procedural manner.  Me and my bosses actually
walk-thru all this code, and they don't know a single thing about
C++ (a pat on my own back).  If I did virtual fns, the usually productive
meeting would go like this...

   Me:  Here, this non-virtual fn does common code 1.
   Boss:  Can I see it?
   Me:  Its here on these extra pages.
   Boss: Ok.  After that's done, ...
   Me: then this virtual fn call in invoked, and the "Right Stuff" gets done.
   Boss: <Silence and Shock>
   Me: Don't worry boss, it works right.
   Boss: What processing is done, when the right thing is done?
   Me: here's another set of pages containing that code...
   Boss: .....

I'm not making my bosses look neanderthal, but I think their attitude
is dead right.   They help the business make the money, consistently.

> template <bool> class static_checker;
> template <> class static_checker<true> {};
>
> Now you have to put static_checker to work like this:
>
> static_checker<NO_MORE == Three + 1>();
> switch ( variable )
> {   case One: .....
>         break;
>     case Two: .....
>         break;
>     case Three: .....
>         break;
> }
>

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]






Author: Mike Davies <mike_davies@noco.demon.co.uk>
Date: 1999/02/21
Raw View
In article <7aklfg$cc2$1@nnrp1.dejanews.com>, Sarma Seetamraju
<sarma@usa.net> writes
>In human planet, (not in geek planet) being able to SEE ALL the
>code for the special situations TOGETHER without all the unnecessary
>white noise of virtual fn declarations and accompanying comments
>is of prime importance.

You can't anyway, not if the special code has to occur
in several places in your program.
Virtual functions remove "noise" by putting the code
 that has to be different in the place it belongs, not
strung out all over the shop.

Regards,

--
Mike Davies
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1999/02/21
Raw View
Sarma Seetamraju <sarma@usa.net> writes:

>But consider the following flow of business logic (which actually
>quite well maps to human/english descriptions of the same).

>           business-logic-begins...
>           ....
>           do common handling #1
>           ....
>           switch() {
>              special situation #1 : ....
>              special situation #2 : ....
>              special situation #3 : ....
>              ....
>           }
>           ....
>           do common handling #2
>           ....
>           switch () again on the same variable...
>               ......
>           }
>           ....
>           do common handling #3
>           ....

>Imagine writing that in OO fashion.

I can not only imagine it, I do it and teach others how to do it.
Polymorphism is intended to solve exactly this sort of problem.

> Using virtual functions
>to describe the above business logic is using a spatula to
>eat cereal from the cereal bowl, just because you have a spatula :-)

I would say rather the reverse. The only tool you are willing to
use is switch-based programming, so you bend the design to fit.

>Ever try maintaining code full of virtual fn calls (even if you
>are the only person writing such code)?

I can and do. We maintain large applications here at Sun that
use polymorphism extensively. So do our major customers. By
"large applications" I mean hundreds of thousands of lines of
code (per application) for us, and millions of lines of code (per
application) for some of our customers. By "extensively", I
mean the designs are based on polymorphism.

We wouldn't try to manage a large project using switch-based
programming, and I don't know how you expect to manage it either.
Your question shows that you don't expect to manage it. You are
looking for a hack to get around the inappropriate design.

>In human planet, (not in geek planet) being able to SEE ALL the
>code for the special situations TOGETHER without all the unnecessary
>white noise of virtual fn declarations and accompanying comments
>is of prime importance.

By your argument, you should not use ANY function calls at all,
because you then cannot see all the code in one place.  The
flow of control jumps here and there around the program listing.

Do you in fact write your entire application as a single "main"
function? If not, you apparently do not object to using function
calls. In that case, you should welcome a polymorphic design,
because it unifies and simplifies the design. It brings
together into one place (the derived class) all the logic for
the the special case (modeled by the class). You don't have
to search throughout the whole program to find all the
special handling for one case.

If you see virtual functions as noise, you don't have a good design.

--
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: sbnaran@fermi.ceg.uiuc.edu (Siemel Naran)
Date: 1999/02/21
Raw View
On 20 Feb 1999 17:09:05 GMT, Sarma Seetamraju <sarma@usa.net> wrote:

>I'm not making my bosses look neanderthal, but I think their attitude
>is dead right.   They help the business make the money, consistently.

But it's always difficult to learn a new concept.  New concepts seem
pointless at first, because they're so complicated and difficult to
apply.  But if we try hard enough, they'll eventually make sense, and
they'll start to make money for us.

--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/02/21
Raw View
In article <7aklfg$cc2$1@nnrp1.dejanews.com>, Sarma Seetamraju
<sarma@usa.net> writes
>I'm not making my bosses look neanderthal, but I think their attitude
>is dead right.   They help the business make the money, consistently.

So how are they coping with Object COBOL or whatever it is called?  Or
doesn't that provide polymorphism?



Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Andrei Alexandrescu" <alexandrescua@micromodeling.com>
Date: 1999/02/21
Raw View
Sarma Seetamraju wrote in message <7aklfg$cc2$1@nnrp1.dejanews.com>...
>
>"Andrei Alexandrescu" <alexandrescua@micromodeling.com> wrote:
>> Aside from the fact that you actually describe why switch-based
programming
>> is bad, here's the solution to your problem (I resume an older thread
over
>> here):

>Your simple solution does the job, and I will try to implement such a one
>soon -- no copyrights here right?


Copyright (c) 1998-1999 comp.lang.c++.moderated :o)

>...
[reasonable argument for using switch instead of virtuals in certain social
circumstances snipped]

It seems to me that you describe an instance of a more general assertion
that sounds like: "Yes, yes, I know, I KNOW, this is wrong, I agree, but
either:
1. In my particular function/program/language/situation [thorough
description] it doesn't apply because [multiple reasons];
and/or
2. This is industry, man, wake up, this is the real world and in the real
world those nice rules in books and academia don't apply as much as you'd
expect."

Maybe this is true; after all, rules have exceptions, and exceptions have
exceptions.

Andrei
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: AllanW@my-dejanews.com
Date: 1999/02/22
Raw View
In article <7aklfg$cc2$1@nnrp1.dejanews.com>,
  Sarma Seetamraju <sarma@usa.net> wrote:
>
> "Andrei Alexandrescu" <alexandrescua@micromodeling.com> wrote:
> > Aside from the fact that you actually describe why switch-based programming
> > is bad, here's the solution to your problem (I resume an older thread over
> > here):
>
> Your simple solution does the job, and I will try to implement such a one
> soon -- no copyrights here right?

Andrei presented a common and well-documented C++ idiom. You are
not only allowed to use it, but highly recommended to do so.

> But consider the following flow of business logic (which actually
> quite well maps to human/english descriptions of the same).
>
>            business-logic-begins...
>            ....
>            do common handling #1
>            ....
>            switch() {
>               special situation #1 : ....
>               special situation #2 : ....
>               special situation #3 : ....
>               ....
>            }
>            ....
>            do common handling #2
>            ....
>            switch () again on the same variable...
>                ......
>            }
>            ....
>            do common handling #3
>            ....
>
> Imagine writing that in OO fashion.

    void businessLogic(BusinessObject obj) {
        obj.commonHandling1();
        obj.specialHandling1();
        obj.commonHandling2();
        obj.specialHandling2();
        obj.commonHandling3();
    }

If we had used descriptive names instead of "common handling" and
"special handling", then it would be easy to see that this version
of the function is actually *EASIER* to read than the version
above, not harder.

The exception is when the audience has a lot of experience, but
only with one language, which was procedural. If, for instance,
you know COBOL very well but no other language, then you might
be surprised at the fact that obj.specialHandling2() does the
same thing in different ways for different objects. The surprise
wanes after a few weeks exposure, though.

> Using virtual functions
> to describe the above business logic is using a spatula to
> eat cereal from the cereal bowl, just because you have a spatula :-)
> Ever try maintaining code full of virtual fn calls (even if you
> are the only person writing such code)?

Yes.

Always avoiding virtual functions just because it takes longer to
learn all the rules about what code is called when, is driving from
New York to Chicago via Los Angeles, simply because you've travelled
from New York to Los Angeles, and you've travelled from Los Angeles
to Chicago, but you've never travelled from New York directly to
Chicago before.

> In human planet, (not in geek planet) being able to SEE ALL the
> code for the special situations TOGETHER without all the unnecessary
> white noise of virtual fn declarations and accompanying comments
> is of prime importance.

My experience is exactly the opposite. Being able to SEE everything
that's done to the object WITHOUT all the trivial differences between
otherwise identical cases makes the overall program flow much more
obvious. Furthermore, the program is 1000 times easier to maintain,
because when business rules change or new cases are introduced the
high level logic generally does not need to be fixed. I can make the
change in one or two places within the affected objects, rather than
in dozens or hundreds of places throughout the code.

If you think that doing this makes me a geek, then you don't really
understand the term.

> I wish I was doing 'neat' stuff like others, but once I had the
> 'core' stuff finished, all code looks like COBOL :-)

This is a natural impulse for any second language. When I first
learned BASIC, 25 years ago, I tended to write it as if it was a
dialect of Fortran. BASIC programs written in Fortran style do
work correctly, which is unfortunate because it helps to mask the
problems for a very long time. My Fortranish BASIC programs never
were fixed; instead, they were eventually re-written. The cost for
re-writing the programs is probably 100s of times as much money as
would have been required had normal maintenance been possible.

> After all, its business logic, and humans (not geeks) think
> in unequivably procedural manner.

Unequivably? I doubt it. When no computers are involved, your
boss can tell you to mail a promotional letter to the biggest
100 customers. When computers are involved you must specify in
excruciating detail how to determine which 100 customers are the
biggest (item count? Dollar sales? Profit margin?), what to do
if there's a tie for 100th place, which ones are not eligible
(i.e. exclude internal customers from your own company), and
which of their many addresses are to be used for promotions as
opposed to billing or shipping.

> Me and my bosses actually
> walk-thru all this code, and they don't know a single thing about
> C++ (a pat on my own back).  If I did virtual fns, the usually productive
> meeting would go like this...
>
>    Me:  Here, this non-virtual fn does common code 1.
>    Boss:  Can I see it?
>    Me:  Its here on these extra pages.
>    Boss: Ok.  After that's done, ...
>    Me: then this virtual fn call in invoked, and the "Right Stuff" gets done.
>    Boss: <Silence and Shock>
>    Me: Don't worry boss, it works right.
>    Boss: What processing is done, when the right thing is done?
>    Me: here's another set of pages containing that code...
>    Boss: .....
>
> I'm not making my bosses look neanderthal, but I think their attitude
> is dead right.   They help the business make the money, consistently.

This is quite humorous. But imagine what would happen if you and
your not-neanderthal bosses walked through code that used virtual
functions PROPERLY, instead of hiding the "Right Stuff" in
obscure locations.

    You:  Here, this function prints out the billing information.
    Boss: Can I see it?
    You: Sure, it's right here.
    Boss: But look here: "GetShipAddress." We don't store the
         shipping address for retail customers, just wholesale
         customers.
    You: That's why I created this virtual function. For wholesale
         customers it gets the shipping address, and for retail
         customers it gets the one and only address. That way the
         printing function doesn't need to bother with it.
    Boss: Show me.
    You: Okay, here's the code for retail customers, and here's
         the code for wholesale customers. Also, when we implement
         distributors next month it will automatically figure out
         where to get the shipping address.
    Boss: But we haven't even started to work on distributors yet,
         so we don't know what information they will have.
    You: That's right, but when we do all we need to do is make
         sure it has a GetShipAddress function, and then we don't
         need to modify this function at all.
    Boss: <Silence and Shock>
    You: Boss? Are you okay?
    Boss: These functions are so short! Can they really simplify
         the code that much?
    You: Absolutely. See, here's where the printing function gets
         the tax rate.
    Boss: And it knows that some of our wholesale customers...
    You: ...don't pay tax. Yes, it figures it out automatically.
         You know how in the old system, every single function
         had to check the resale-number flag? Now we just call
         the taxrate function and let the object figure it out
         by itself.
    Boss: Wow. The old version was 6 pages long, and really hard
         to follow. But the new version is only 20 lines long,
         and even my nephew in the shipping department could
         understand it. You made it all so clear!
    You: Remember that training course I took late last year?
         It's really paying off. The planning for this function
         took four days instead of one, but the actual coding
         was done in a week instead of the 3 months I had predicted.
    Boss: That's fantastic; getting this done early is going to
         save us about $100,000 this month.  ... I have an idea.
         You can have your bonus in cash, if you like, or instead you
         can take your whole family on the company jet to my personal
         Hawaii condo for a week, all expenses paid...
    You: <Silence and Shock>
    Boss: Better yet, take the cash AND the vacation. This is great!
    You: ...

----
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: sbnaran@fermi.ceg.uiuc.edu (Siemel Naran)
Date: 1999/02/22
Raw View
On 22 Feb 1999 21:10:12 GMT, AllanW@my-dejanews.com

>    You:  Here, this function prints out the billing information.
>[snip]
>    Boss: Wow. The old version was 6 pages long, and really hard
>         to follow. But the new version is only 20 lines long,
>         and even my nephew in the shipping department could
>         understand it. You made it all so clear!
>[snip]
>    Boss: Better yet, take the cash AND the vacation. This is great!
>    You: ...


Your plot is unrealistic.  Here's why.  To convince the Boss that
the design works, you need a working implementation to show off.
In order to have a working implementation to show off, you need to
write one.  In order to write one, you need the go-ahead. In order
to get the go-ahead, you need to convince your Boss that the design
is sound, and that with some investment (ie, time and money) it
will work.  This is the great barrier.

In fact, it's interesting to consider how any features made it to
the language (or to any language).

--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]