By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,171 Members | 980 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,171 IT Pros & Developers. It's quick & easy.

Sharing code between cases

P: n/a
I'm wondering what the "best" is way to handle blocks of code that are
shared between two or more cases in a switch statement. Consider the
following code (assuming valid variable and function definitions,
obviously):

switch (a)
{
case 1:
if (x) return false;
y = 6;
foo();
break;

case 2:
if (x) return false;
y = 6;
bar();
break;

case 3:
foo();
break;
}

Of course, this isn't too bad, but when the first two lines turn into a
dozen, or as there are more cases that share common code, the
possibility of a change to one not being reflected to all others
increases. Generally, the solution to common code is to pull it out,
but the ways that I see of doing that here are:

1) Sequential switches
switch (a)
{
case 1:
case 2:
// shared code here
}
switch (a)
{
// unique code here
}
This might also be written like
if (a == 1 || a == 2)
{
// shared code here
}
depending on whether there were multiple different blocks of shared
code.

This method looks potentially confusing, and perhaps causes maintenance
problems.

2) Put the common code in a function that is called from each applicable
case. This would work well in some cases, but not, I think, if there
are multiple possible early return values that might be generated,
multiple variables that may be tested or affected (which now all need to
be parameters to the function), etc.

Exceptions could be a way to solve the "multiple return value" part of
the problem with this solution.
So, are there other methods I've missed that people use in this
situation? Is this perhaps an indication that I'm trying to use one
variable to control two orthogonal values (time to refactor)?

--
Greg Schmidt gr***@trawna.com
Trawna Publications http://www.trawna.com/
Jul 23 '05 #1
Share this Question
Share on Google+
12 Replies


P: n/a

"Greg Schmidt" <gr***@trawna.com> schrieb im Newsbeitrag
news:1o***************@trawna.com...
I'm wondering what the "best" is way to handle blocks of code that
are
shared between two or more cases in a switch statement. Consider
the
following code (assuming valid variable and function definitions,
obviously):

switch (a)
{
case 1:
if (x) return false;
y = 6;
foo();
break;

case 2:
if (x) return false;
y = 6;
bar();
break;

case 3:
foo();
break;
}


I do this - and I know this is considered crappy style and everyone
will flame me now - for it's fast to write:

#define DEF1 {if (x) return false; y=6;}

switch(a)
{
case 1: DEF1
foo();
break;
case 2: DEF2
bar();
break;
case 3:
foo();
break;
}

any, yes, I do this for very long blocks as well.
-Gernot


Jul 23 '05 #2

P: n/a
In message <1o***************@trawna.com>, Greg Schmidt
<gr***@trawna.com> writes

[switch() complications snipped]

So, are there other methods I've missed that people use in this
situation? Is this perhaps an indication that I'm trying to use one
variable to control two orthogonal values (time to refactor)?


Maybe, but don't just do the obvious and split it into two values. When
a variable is controlling complex *behaviour*, it looks like a hint that
you need to represent that behaviour by polymorphic classes. Then
instead of

switch(a)
{
/* lots of cases, lots of stuff */
}

you'll have

p->DoStuff();

--
Richard Herring
Jul 23 '05 #3

P: n/a

Greg Schmidt wrote:
Exceptions could be a way to solve the "multiple return value" part of the problem with this solution.


I am really surprised nobody else jumped on this one.

Exceptions are not another way to return values. Exceptions are for
exceptional situations and should not be used for flow control or
returns. That is a misuse of the feature and contains all sorts of
bugbears that love to eat lost programmers.

Jul 23 '05 #4

P: n/a
Greg Schmidt wrote:
I'm wondering what the "best" is way to handle blocks of code that are
shared between two or more cases in a switch statement. Consider the
following code (assuming valid variable and function definitions,
obviously):

switch (a)
{
case 1:
if (x) return false;
y = 6;
foo();
break;

case 2:
if (x) return false;
y = 6;
bar();
break;

case 3:
foo();
break;
}
...
1) Sequential switches
...


Wouldn't nested switches be more elegant than sequential ones?

switch (a)
{
case 1:
case 2:

// Common prologue
if (x) return false;
y = 6;

// Specific code (branched with 'if' or 'switch')
switch (a)
{
case 1: foo(); break;
case 2: bar(); break;
}

// Common epilogue
// ...

break;

case 3:
foo();
break;
}

--
Best regards,
Andrey Tarasevich
Jul 23 '05 #5

P: n/a
On Wed, 9 Feb 2005 16:54:42 +0000, Richard Herring wrote:
In message <1o***************@trawna.com>, Greg Schmidt
<gr***@trawna.com> writes

[switch() complications snipped]

So, are there other methods I've missed that people use in this
situation? Is this perhaps an indication that I'm trying to use one
variable to control two orthogonal values (time to refactor)?


Maybe, but don't just do the obvious and split it into two values. When
a variable is controlling complex *behaviour*, it looks like a hint that
you need to represent that behaviour by polymorphic classes. Then
instead of

switch(a)
{
/* lots of cases, lots of stuff */
}

you'll have

p->DoStuff();


You may be right. The library where I'm currently having this issue
(which I did most of the design for) actually makes extensive use of
polymorphism, but for some reason I had a mental block to seeing that it
might work in this case too.

--
Greg Schmidt gr***@trawna.com
Trawna Publications http://www.trawna.com/
Jul 23 '05 #6

P: n/a
On 9 Feb 2005 09:12:08 -0800, Noah Roberts wrote:
Greg Schmidt wrote:
Exceptions could be a way to solve the "multiple return value" part

of
the problem with this solution.


I am really surprised nobody else jumped on this one.

Exceptions are not another way to return values. Exceptions are for
exceptional situations and should not be used for flow control or
returns. That is a misuse of the feature and contains all sorts of
bugbears that love to eat lost programmers.


I'm sure if you search the archives, you'll find that this is another
one of the religious issues that comes up from time to time. I think it
depends largely on the situation. When I wrote that, I was thinking
that the multiple return values would actually tend to be codes for
different error situations, in which case an argument can be made that
"error" and "exception" can be (close to) synonymous. Certainly, using
an exception to return the result of, say, a mathematical calculation is
an abuse of the feature.

In my original, hypothetical situation, since the exception would be
thrown from the newly-created "shared code" function, which won't be
useful anywhere except very locally, the switch could be nested inside a
try block, and the catch would be right there to trap the exception and
return a "normal" result back to the caller. No need to worry about the
exception biting the unwary when its use is so limited.

--
Greg Schmidt gr***@trawna.com
Trawna Publications http://www.trawna.com/
Jul 23 '05 #7

P: n/a
Greg Schmidt wrote:
I'm sure if you search the archives, you'll find that this is another
one of the religious issues that comes up from time to time. I think it
depends largely on the situation. When I wrote that, I was thinking
that the multiple return values would actually tend to be codes for
different error situations, in which case an argument can be made that
"error" and "exception" can be (close to) synonymous. Certainly, using
an exception to return the result of, say, a mathematical calculation is
an abuse of the feature.
In "Thinking in C++" Eckel explains the use of exceptions as to deal
with 'exceptional' situations. In other words, the unexpected. He also
uses them to enforce function contract (or preconditions). So for
instance you wouldn't use an exception upon end of file, because that is
an expected situation, but you would if the file suddenly became
unreadable or disconnected without an eof.

I would say that is a pretty reasonable explaination.

In my original, hypothetical situation, since the exception would be
thrown from the newly-created "shared code" function, which won't be
useful anywhere except very locally, the switch could be nested inside a
try block, and the catch would be right there to trap the exception and
return a "normal" result back to the caller. No need to worry about the
exception biting the unwary when its use is so limited.


Oh I don't think so. I think it poorly advised to allow bad design to
creap into "local" functions that won't be used elsewhere for some
unforseen reason down the road. Simply because those reasons are
unforseen. When you make a function you should always assume you might
use it in ways you are not expecting to right now.
Jul 23 '05 #8

P: n/a
Noah Roberts wrote:
In "Thinking in C++" Eckel explains the use of exceptions as to deal
with 'exceptional' situations. In other words, the unexpected. He also
uses them to enforce function contract (or preconditions). So for
instance you wouldn't use an exception upon end of file, because that is
an expected situation, but you would if the file suddenly became


That depends. If you are reading a text file, the end of file is the normal
condition to mark the end of the text, but if you are reading for example a
file in a format that defines precisely what contains and what are the
lengths of each part, reaching end of file in the middle of a file can be
considered an excpetional condition (file is corrupt or is not in the
required format).

--
Salu2
Jul 23 '05 #9

P: n/a

Julián Albo wrote:
Noah Roberts wrote:
In "Thinking in C++" Eckel explains the use of exceptions as to deal with 'exceptional' situations. In other words, the unexpected. He also uses them to enforce function contract (or preconditions). So for
instance you wouldn't use an exception upon end of file, because that is an expected situation, but you would if the file suddenly became
That depends. If you are reading a text file, the end of file is the

normal condition to mark the end of the text, but if you are reading for example a file in a format that defines precisely what contains and what are the lengths of each part, reaching end of file in the middle of a file can be considered an excpetional condition (file is corrupt or is not in the
required format).


Sure. Good point.

Jul 23 '05 #10

P: n/a
On Thu, 10 Feb 2005 00:02:07 -0800, Noah Roberts wrote:
Greg Schmidt wrote:
I'm sure if you search the archives, you'll find that this is another
one of the religious issues that comes up from time to time. I think it
depends largely on the situation. When I wrote that, I was thinking
that the multiple return values would actually tend to be codes for
different error situations, in which case an argument can be made that
"error" and "exception" can be (close to) synonymous. Certainly, using
an exception to return the result of, say, a mathematical calculation is
an abuse of the feature.


In "Thinking in C++" Eckel explains the use of exceptions as to deal
with 'exceptional' situations. In other words, the unexpected. He also
uses them to enforce function contract (or preconditions). So for
instance you wouldn't use an exception upon end of file, because that is
an expected situation, but you would if the file suddenly became
unreadable or disconnected without an eof.


http://groups-beta.google.com/group/...c713555b51a81c
is a lengthy thread with various views on this. It seems that Herb
Sutter (who knows a thing or two about exceptions) perhaps falls closer
to my view than yours, but then I may be reading my own bias into his
posts, or he may have changed his views since then (it was over 4 years
ago).
In my original, hypothetical situation, since the exception would be
thrown from the newly-created "shared code" function, which won't be
useful anywhere except very locally, the switch could be nested inside a
try block, and the catch would be right there to trap the exception and
return a "normal" result back to the caller. No need to worry about the
exception biting the unwary when its use is so limited.


Oh I don't think so. I think it poorly advised to allow bad design to
creap into "local" functions that won't be used elsewhere for some
unforseen reason down the road. Simply because those reasons are
unforseen. When you make a function you should always assume you might
use it in ways you are not expecting to right now.


I used to agree with you, but I've since discovered that it is more
efficient to design for what you need now, and accept that the design
may need to be changed in the future, than it is to design for any
possible eventuality. If only I could get back all the time I spent
coding for possible future cases that never happened!

--
Greg Schmidt gr***@trawna.com
Trawna Publications http://www.trawna.com/
Jul 23 '05 #11

P: n/a

Greg Schmidt wrote:
I used to agree with you, but I've since discovered that it is more
efficient to design for what you need now, and accept that the design
may need to be changed in the future, than it is to design for any
possible eventuality. If only I could get back all the time I spent
coding for possible future cases that never happened!


You don't need to code for all possibilities, not even possible. Just
don't code assuming things that shouldn't be assumed.

Jul 23 '05 #12

P: n/a
Greg Schmidt wrote:
I'm wondering what the "best" is way to handle blocks of code that are
shared between two or more cases in a switch statement. Consider the
following code (assuming valid variable and function definitions,
obviously):

switch (a)
{
case 1:
if (x) return false;
y = 6;
foo();
break;

case 2:
if (x) return false;
y = 6;
bar();
break;

case 3:
foo();
break;
}

What about this:
if(x)
{
// Or switch for more
if(a!=3)
return false;

// ...

}

else
{
switch(a)
{
case 1:
{
y = 6;
foo();
break;
}

case 2:
{
y = 6;
bar();
break;
}
}
}


--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #13

This discussion thread is closed

Replies have been disabled for this discussion.