472,958 Members | 2,193 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,958 software developers and data experts.

Is this good code?

I found one of that problems all of us have solve when they begin
programming: given 3 numbers print the greater and the lesser one of
the set.

I was trying to remember the if-then-else structure when something hit
me and I wrote:

// Function returns the greater or lesser numbers of two given numbers,

// specified by a flag: 1 for greater (default), 0 for lesser

int greater_lesser(int a, int b, bool flag=1){

int toBeReturned;

if(flag)
a > b ? toBeReturned = a : toBeReturned = b;
else
a > b ? toBeReturned = b : toBeReturned = a;

return toBeReturned;
}

int main(){

int x, y, z;
cin >> x >> y >> z;
cout << "Greater : " << greater_lesser(greater_lesser(x,y),z) << endl
<< "Lesser : " << greater_lesser(greater_lesser(x,y,0),z,0) << endl;

return 0;
}

The code works all right, but it seems odd, as if it can be improved...

Any thoughts? Thanks!

Feb 5 '06 #1
24 2228
Comments on your code inline:

"Gaijinco" <ga******@gmail.com> wrote in message
news:11**********************@g47g2000cwa.googlegr oups.com...
I found one of that problems all of us have solve when they begin
programming: given 3 numbers print the greater and the lesser one of
the set.

I was trying to remember the if-then-else structure when something hit
me and I wrote:

// Function returns the greater or lesser numbers of two given numbers,

// specified by a flag: 1 for greater (default), 0 for lesser

int greater_lesser(int a, int b, bool flag=1){
bool flag = true

int toBeReturned;
Don't need this.

if(flag)
a > b ? toBeReturned = a : toBeReturned = b;
return a > b ? a : b;
else
a > b ? toBeReturned = b : toBeReturned = a;
return a > b ? b : a;

return toBeReturned;
Don't need this
}

int main(){

int x, y, z;
cin >> x >> y >> z;
cout << "Greater : " << greater_lesser(greater_lesser(x,y),z) << endl
<< "Lesser : " << greater_lesser(greater_lesser(x,y,0),z,0) << endl;

return 0;
}

The code works all right, but it seems odd, as if it can be improved...

Any thoughts? Thanks!


Now, this is not the way I would do it anyway. If I wanted a function to
give me the greater, or lesser of numbers I would allow the number of
elements to be arbitrary. Meaning passing in a reference to a vector and
returning the greater one. There might even already be some STL function
that does that, I don't know enough about all the STL functions to say.

There are many ways to do that, but I'll let others comment on STL methods
to do it before I post anything else cause I'm fairly sure it's simple with
some container iteratation.
Feb 5 '06 #2
Gaijinco wrote:
I found one of that problems all of us have solve when they begin
programming: given 3 numbers print the greater and the lesser one of
the set.

I was trying to remember the if-then-else structure when something hit
me and I wrote:

// Function returns the greater or lesser numbers of two given numbers,

// specified by a flag: 1 for greater (default), 0 for lesser

int greater_lesser(int a, int b, bool flag=1){

int toBeReturned;

if(flag)
a > b ? toBeReturned = a : toBeReturned = b;
else
a > b ? toBeReturned = b : toBeReturned = a;

return toBeReturned;
}

int main(){

int x, y, z;
cin >> x >> y >> z;
cout << "Greater : " << greater_lesser(greater_lesser(x,y),z) << endl
<< "Lesser : " << greater_lesser(greater_lesser(x,y,0),z,0) << endl;

return 0;
}

The code works all right, but it seems odd, as if it can be improved...


Why reinvent the wheel?

#include <algorithm>
#include <iostream>

int main ( void ) {
int x, y, z;
std::cin >> x >> y >> z;
std::cout << "max: " << std::max( std::max( x, y ), z ) << '\n'
<< "min: " << std::min( std::min( x, y ), z ) << '\n';
}
Best

Kai-Uwe Bux

Feb 5 '06 #3

"Gaijinco" <ga******@gmail.com> wrote in message
news:11**********************@g47g2000cwa.googlegr oups.com...
I found one of that problems all of us have solve when they begin
programming: given 3 numbers print the greater and the lesser one of
the set.

I was trying to remember the if-then-else structure when something hit
me and I wrote:

// Function returns the greater or lesser numbers of two given numbers,

// specified by a flag: 1 for greater (default), 0 for lesser

int greater_lesser(int a, int b, bool flag=1){

int toBeReturned;

if(flag)
a > b ? toBeReturned = a : toBeReturned = b;
else
a > b ? toBeReturned = b : toBeReturned = a;

return toBeReturned;
}

int main(){

int x, y, z;
cin >> x >> y >> z;
cout << "Greater : " << greater_lesser(greater_lesser(x,y),z) << endl
<< "Lesser : " << greater_lesser(greater_lesser(x,y,0),z,0) << endl;

return 0;
}

The code works all right, but it seems odd, as if it can be improved...

Any thoughts? Thanks!


No, this is horrible!

Flags which control the behavior of a function in such a radical way are
often
confusing and make code difficult to understand, especially something as
simple
as this. Perhaps in a more complex example where a basic algorithm can be
adapted
to perform different variations, flags might be more appropriate, but I
would generally
make that function private and provide simple wrappers of the basic function
to be more
meaningful to a user.

Flags have a habit of multiplying, so we often see two or three flag
parameters in code which
affect the behavior of the function making code harder to understand.
Surely the following is easier to understand ?

#include <iostream>
int lesser( int a, int b)
{
return a < b ? a : b;
}
int greater( int a, int b)
{
return a > b ? a : b;
}
int main()
{
int x, y, z;
std::cin >> x >> y >> z;
std::cout << "Greater : " << greater ( greater (x,y),z) << "\n"
<< "Lesser : " << lesser( lesser(x,y),z) << "\n";

return 0;
}

Feb 5 '06 #4

Gaijinco wrote:

int greater_lesser(int a, int b, bool flag=1){

int toBeReturned;

if(flag)
a > b ? toBeReturned = a : toBeReturned = b;
else
a > b ? toBeReturned = b : toBeReturned = a;

return toBeReturned;
}

Any thoughts? Thanks!


9 times out of 10, if you have a function of the form:

func(bool flag)
{
// no code before if

if (flag)
...
else
...

// no code after if/else
}

such that there is ***no common code*** before or after the if/else,
then you really have 2 completely separate functions, right?

P.S. When I say '9 times out of 10', in this case I really mean 10
times out of 10.

- Tony

Feb 5 '06 #5

Gaijinco wrote:
I found one of that problems all of us have solve when they begin
programming: given 3 numbers print the greater and the lesser one of
the set.

I was trying to remember the if-then-else structure when something hit
me and I wrote:

// Function returns the greater or lesser numbers of two given numbers,
// specified by a flag: 1 for greater (default), 0 for lesser


This is totally bogus, regardless of the implementation.

Feb 5 '06 #6
On Sat, 04 Feb 2006 20:02:46 -0800, Gaijinco wrote:
I found one of that problems all of us have solve when they begin
programming <snip> // specified by a flag: 1 for greater (default), 0 for lesser

int greater_lesser(int a, int b, bool flag=1){


Sticking to general matters, in those situations where you need a boolean
flag (this not being one of them) possibly the very worst name for it is
"flag"! Choose a name that identifies what it is "flagging" when true:

bool candidate_found = false;
bool number_has_dot = strchr(number, '.') != NULL;

and so on.

--
Ben.

Feb 5 '06 #7
It just seemed that a function

int max(int a,int b){
return a > b ? a : b;
}

and another one like

int min(int a,int b){
return a > b ? b : a;
}

Were so similar that they could be rewritten as a single function so
the use of a flag seemed valid. I recognize that a flag named flag is
really dumb.

But if something like

int max_min(int a, int b, bool max=true){

if(max)
return a > b ? a : b;
else
return a > b ? b : a;
}

is a misuse of a flag, then what isn't?

Feb 5 '06 #8
Ben Bacarisse wrote:
Sticking to general matters, in those situations where you need a boolean
flag (this not being one of them) possibly the very worst name for it is
"flag"! Choose a name that identifies what it is "flagging" when true:

bool candidate_found = false;
bool number_has_dot = strchr(number, '.') != NULL;


I find an exception, in practice, for boolean mutators:

private:
bool happy;
public:
void setHappy(bool flag);

Given that the function name and parameter type contain all the
relevant information, what's the point in trying to express something
additional in the name of the parameter? What would you want to call
it? The best alternative I know is along the lines of:

private:
bool happy_; // Sutter-style trailing underscores for private
member data
public:
public setHappy(bool happy);

But I really don't like keeping the same information in two places like
that. "flag" is perfectly descriptive, when there just isn't enough
semantic content that anything else useful could be conveyed.

Luke

Feb 5 '06 #9

Luke Meyers wrote:
Ben Bacarisse wrote:
Sticking to general matters, in those situations where you need a boolean
flag (this not being one of them) possibly the very worst name for it is
"flag"! Choose a name that identifies what it is "flagging" when true:

bool candidate_found = false;
bool number_has_dot = strchr(number, '.') != NULL;


I find an exception, in practice, for boolean mutators:

private:
bool happy;
public:
void setHappy(bool flag);

Given that the function name and parameter type contain all the
relevant information, what's the point in trying to express something
additional in the name of the parameter? What would you want to call
it?


What about setHappy(bool turnOn)

Your's makes the assumption that happy is a bool. What if it is a
string? Maybe setHappy(bool) is something like this:

void setHappy(bool on)
{
happy = on ? "I'm happy":"I'm pissy";
}

Granted, one could see the information in the class definition but you
never know; maybe you'll want to change that later. Might be nice to
call the 'flag' variable by what effect it might have.

On the other hand, IMHO the 'setHappy()' function shouldn't exist.
There should be two of them:

void makeHappy();
void makeUnhappy();

Now there is no knowledge of, nor reference to, any internal data
whatsoever...these functions could have any effect or combination of
effects. It also gets rid of an if since in the original your code
ends up being something like (assuming set happy got more complex, as
it naturally does):

if (?) flag = true;
else flag = false;

if (flag)
...
else
...

Finally, if you have a variable that makes sense as a "flag" then you
have an area that could use improvement in design. What effect does
the "happy" flag have? One would assume that it is later used to base
decisions on in other member variables and possibly client classes;
branches. It would be better to use a more OO design - possibly the
state pattern but others might be better depending on the effects
'happy' has.

Feb 5 '06 #10
On Sun, 05 Feb 2006 11:09:43 -0800, Luke Meyers wrote:
Ben Bacarisse wrote:
Sticking to general matters, in those situations where you need a
boolean flag (this not being one of them) possibly the very worst name
for it is "flag"! Choose a name that identifies what it is "flagging"
when true:

bool candidate_found = false;
bool number_has_dot = strchr(number, '.') != NULL;


I find an exception, in practice, for boolean mutators:

private:
bool happy;
public:
void setHappy(bool flag);


Good point. I've looked over some old code, I find that I opted for "bool
b" in one case -- probably because I had a blanket prejudice against
"flag" which is much better!

<secondary alternative snipped>

--
Ben.

Feb 5 '06 #11

"Gaijinco" <ga******@gmail.com> wrote in message
news:11**********************@o13g2000cwo.googlegr oups.com...
It just seemed that a function

int max(int a,int b){
return a > b ? a : b;
}

and another one like

int min(int a,int b){
return a > b ? b : a;
}

Were so similar that they could be rewritten as a single function so
the use of a flag seemed valid. I recognize that a flag named flag is
really dumb.

But if something like

int max_min(int a, int b, bool max=true){

if(max)
return a > b ? a : b;
else
return a > b ? b : a;
}

is a misuse of a flag, then what isn't?

This is a misuse of a flag because the code otherwise is very simple,
duplicating
the code is better than making it more complicated. True, these functions
have very similar
structure, but would you do the same thing for plus/minus/multiply/divide
since these have the
same basic structure - :

int BinaryArithmetic( int op1, int op2, int code )
{
if (code == 0 ) return op1 + op2;
else if (code ==1 ) return op1 - op2;
else if (code == 2) return op1 * op2;
else if (code ==3) return op1 / op2;
else // uh,oh....
}

( now see what we've got ourselves into, we now have to check that "code" is
a valid value, what do
we do when its not...using separate functions makes this a lot simpler since
we don't have to check).
Perhaps if the code were more complex, say finding the max/min element in a
vector<> , the traversal code is common, you can give a flag to control
the test to find max/min, although this is a bit contrived since STL
algorithms can do this for you. ( C++ world, we'd probably use a functor as
the customizing construct rather than a boolean).

Please don't use flags like this in C++!

dave

Feb 5 '06 #12
ro**********@gmail.com wrote:
Luke Meyers wrote:
Ben Bacarisse wrote:
Sticking to general matters, in those situations where you need a boolean
flag (this not being one of them) possibly the very worst name for it is
"flag"! Choose a name that identifies what it is "flagging" when true:

bool candidate_found = false;
bool number_has_dot = strchr(number, '.') != NULL;
I find an exception, in practice, for boolean mutators:

private:
bool happy;
public:
void setHappy(bool flag);

Given that the function name and parameter type contain all the
relevant information, what's the point in trying to express something
additional in the name of the parameter? What would you want to call
it?


What about setHappy(bool turnOn)


I don't like it. It doesn't scan right. Probably because it's a verb,
which conflicts with the basic concept that variables represent state,
and hence are generally nouns and should be named accordingly absent a
compelling reason to vary.
Your's makes the assumption that happy is a bool. What if it is a
string? Maybe setHappy(bool) is something like this:

void setHappy(bool on)
{
happy = on ? "I'm happy":"I'm pissy";
}
I believe we were discussing the *interface* -- namely, the identifier
associated with the bool parameter to a setter/mutator. The
implementation obviously depends on the actual type being set.

More to the point, this is a rather spurious counterexample. If happy
can be appropriately specified by a bool, it's rather questionable to
store it as a string.
Granted, one could see the information in the class definition but you
never know; maybe you'll want to change that later. Might be nice to
call the 'flag' variable by what effect it might have.
If I change the parameter to something besides a bool, I'd be renaming
it anyway. If I changed the semantics of the function in such a way
that the parameter had a different meaning, I would also consider
changing the name. Basically, a parameter name must only consider
whether it is correct for the interface it is part of *as it currently
exists*, not all future possible changes to it. That's an impossible
and useless generalization. Anything which would require you to change
the name from "flag" to something else would be a big enough change
that all dependent code would have to be inspected and possibly
modified anyway. I say again -- in a boolean mutator (setter), the
entire semantic content of the function's signature is sufficiently
conveyed by the function name and the parameter type.
On the other hand, IMHO the 'setHappy()' function shouldn't exist.
There should be two of them:

void makeHappy();
void makeUnhappy();
How is this better? Happy and Unhappy are obviously related and
mutually exclusive possibilities which, taken together, correspond with
a component of the object's state whose natural representation is
boolean in nature. Of course, it's always possible that later we'll
decide to allow for a whole range of moods. To accommodate this, I
would do the following:

class Person {
public:
enum Mood { happy, sad, ambivalent, angry, content };
void setMood(Mood m) { mood_ = m; }

// deprecated in documentation.
// kept, with implementation changed, for compatibility as needed.
void setHappy(bool flag) { setMood(happy); }

private:
Mood mood_;
};

This is a clean, extensible generalization. Were we to take the
approach you suggest, we'd wind up with something more like:

class Person {
public:
void setHappy();
void setUnhappy();
void setAmbivalent();
void setAngry();
void setContent();
private:
// implementation details
};

So while setHappy() and setUnhappy() can seem like a good idea because
it "separates concerns" or "hides implementation details," really all
you've done is treat two particular data values (true and false) as
special cases and written separate interfaces for each. It's easy to
do this for bool because there are only two values in the domain. With
an enumerated type, it's irritating but possible. With pretty much
anything else, it's completely impractical. It doesn't separate
concerns, it tries to represent one thing as two. It produces tighter
coupling, in fact, because clients are tied to the number of methods in
your interface.
Now there is no knowledge of, nor reference to, any internal data
whatsoever...these functions could have any effect or combination of
effects.
I'd rather have functions that made sense and dealt with cohesive,
discrete responsibilities. I'd rather not have two functions modifying
the same state needlessly.
It also gets rid of an if since in the original your code
ends up being something like (assuming set happy got more complex, as
it naturally does):

if (?) flag = true;
else flag = false;

if (flag)
...
else
...
There is nothing wrong with the introduction of a conditional
statement, if it is a clear and effective representation of the logic
being implemented. A conditional statement within a single function
body is less complexity to manage than two separate, but semantically
interwove, functions. If, as in my example above, the requirements
require you to flex in a direction you didn't plan for, such that your
scheme is not extensible, you wind up having to scrap it and start over
with a totally new interface.

The best protection against future change is not to introduce
additional complexity in the name of being flexible, but to represent
concepts in a clear and expressive manner, use good judgement about
appropriate levels of abstraction, and assume as little as possible
about the nature of future changes.
Finally, if you have a variable that makes sense as a "flag" then you
have an area that could use improvement in design. What effect does
the "happy" flag have? One would assume that it is later used to base
decisions on in other member variables and possibly client classes;
branches. It would be better to use a more OO design - possibly the
state pattern but others might be better depending on the effects
'happy' has.


You're being unreasonable. Values with exactly two alternatives,
corresponding in a natural way to true and false, are an integral part
of the logical state of countless entities we might care to represent
as objects. Representing such values as being of type bool, whether in
interfaces or implementation or both, is completely natural and
difficult to argue with as a general practice. It's the most trivially
simple piece of state one can represent (a single bit), and you want to
replace it with a comparatively massive artifice? To what possible
end? How is this better? Design patterns are wonderful, but they are
not the answer to every question.

Luke

Feb 5 '06 #13
I V
Gaijinco wrote:
Were so similar that they could be rewritten as a single function so
the use of a flag seemed valid. I recognize that a flag named flag is
really dumb.
But they're not really similar in the relevant sense; on the contrary,
they're opposites! You can, to some extent, see this from the code,
because you have to write the two operations completely separately in
your function (i.e., using the flag does not prevent code duplication):
But if something like

int max_min(int a, int b, bool max=true){

if(max)
return a > b ? a : b;
else
return a > b ? b : a;
}

is a misuse of a flag, then what isn't?


It would be less likely to be a misuse if a) the operations with and
without the flag are similar in the relevant sense, b) using a flag
prevented code duplication, and/or c) the flag is likely to vary at
run-time. Maybe something like:

void doComplexOperation(MyClass data, bool debug=false)
{
if( debug )
logOperation("Complex operation started");

/* ... insert long, complicated sequence of operations on data ...
*/

if( debug )
logOperation("Complex operation finished")
}

Feb 6 '06 #14
In article <11**********************@f14g2000cwb.googlegroups .com>,
"Luke Meyers" <n.***********@gmail.com> wrote:
Ben Bacarisse wrote:
Sticking to general matters, in those situations where you need a boolean
flag (this not being one of them) possibly the very worst name for it is
"flag"! Choose a name that identifies what it is "flagging" when true:

bool candidate_found = false;
bool number_has_dot = strchr(number, '.') != NULL;


I find an exception, in practice, for boolean mutators:

private:
bool happy;
public:
void setHappy(bool flag);

Given that the function name and parameter type contain all the
relevant information, what's the point in trying to express something
additional in the name of the parameter? What would you want to call
it? The best alternative I know is along the lines of:

private:
bool happy_; // Sutter-style trailing underscores for private
member data
public:
public setHappy(bool happy);

But I really don't like keeping the same information in two places like
that. "flag" is perfectly descriptive, when there just isn't enough
semantic content that anything else useful could be conveyed.


I would more likely do something like this:

class Foo {
public:
void makeHappy() { _happy = true; }
void makeUnhappy() { _happy = false; }
};

As someone earlier said, what if the implementation changes and 'happy'
is no longer represented as a bool? With 'setHappy(bool)' you would end
up having to put an 'if' statement in the member-function (making it
more complex,) by making two different functions the complexity of each
remains the same.

--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Feb 6 '06 #15
Daniel T. wrote:
I would more likely do something like this:

class Foo {
public:
void makeHappy() { _happy = true; }
void makeUnhappy() { _happy = false; }
};

As someone earlier said, what if the implementation changes and 'happy'
is no longer represented as a bool? With 'setHappy(bool)' you would end
up having to put an 'if' statement in the member-function (making it
more complex,) by making two different functions the complexity of each
remains the same.


The specification of the parameter as a bool in no way ties the
implementation to anything. You can take in a boolean value and
perform whatever logic is appropriate. Happy and unhappy are obviously
related, mutually exclusive alternatives. The total amount of
information regarding them which we are prepared to receive from the
client is a single bit. Don't you think it's a bit excessive to write
two functions to handle a single bit of information? Also, as I
pointed out in response to Mr. Roberts, your solution doesn't scale
when there are more than two values in the domain.

Really, you're both just overthinking it, looking for a problem where
none exists. The client needs to indicate a single bit of information;
absent any other information, the best thing is to provide a single
function which takes a bool.

Luke

Feb 6 '06 #16
In article <M5*****************@fe06.lga>,
"Jim Langston" <ta*******@rocketmail.com> wrote:
There are many ways to do that, but I'll let others comment on STL methods
to do it before I post anything else cause I'm fairly sure it's simple with
some container iteratation.


int main() {
cout << "Input numbers to compare (non-number to end):\n";
vector<int> vec;
copy( istream_iterator<int>(cin), istream_iterator<int>(),
back_inserter( vec ) );
cout << '\n';
if ( !vec.empty() ) {
cout << "Greatest: " << *max_element( vec.begin(), vec.end() )
<< '\n';
cout << "Least: " << *min_element( vec.begin(), vec.end() )
<< '\n';
}
}

It's instructive to see how max_element works:

template < typename FwIt >
FwIt max_element( FwIt first, FwIt last ) {
if ( first == last ) return first;
FwIt result = first;
while ( ++first != last )
if ( *result < *first )
result = first;
return result;
}

'min_element' is the same except in the "if (*result < *first)" line
where 'first' and 'result' are reversed.

I'm sure Mr. Pibinger will find all of the above simply horrible
"geek-code" including the definition of 'max_element'

To the OP. Whenever you have a requirement dealing with 'x' items (in
this example it was '3' numbers) remember the phrase "one, optional,
many." These are the only ones that matter, either the code deals with
exactly one of them, the item is optional, or otherwise (as in this
case) there are just "a bunch".

--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Feb 6 '06 #17
In article <11*********************@g47g2000cwa.googlegroups. com>,
"Luke Meyers" <n.***********@gmail.com> wrote:
Daniel T. wrote:
I would more likely do something like this:

class Foo {
public:
void makeHappy() { _happy = true; }
void makeUnhappy() { _happy = false; }
};

As someone earlier said, what if the implementation changes and 'happy'
is no longer represented as a bool? With 'setHappy(bool)' you would end
up having to put an 'if' statement in the member-function (making it
more complex,) by making two different functions the complexity of each
remains the same.
The specification of the parameter as a bool in no way ties the
implementation to anything. You can take in a boolean value and
perform whatever logic is appropriate.


We're just picking nits here so I'm not going to go much further with
this...

In the 'setHappy(bool flag)' function you probably need some "if (flag)
doX(); else doY();" code. It is likely that the client code *also* must
use a decision ('if' or '?:') to set the flag that is being sent to the
member-function... That's some obvious redundancy that can easily be
removed by creating two member-functions.
Don't you think it's a bit excessive to write two functions to handle
a single bit of information?
Not if it removes redundant decision code.
Also, as I pointed out in response to Mr. Roberts, your solution
doesn't scale when there are more than two values in the domain.
Obviously, if decision code is not at issue, then a different construct
should be used.
Really, you're both just overthinking it, looking for a problem where
none exists. The client needs to indicate a single bit of information;
absent any other information, the best thing is to provide a single
function which takes a bool.


I agree, it's not a big deal either way.

--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Feb 6 '06 #18
Daniel T. wrote:
In article <11*********************@g47g2000cwa.googlegroups. com>,
"Luke Meyers" <n.***********@gmail.com> wrote:
We're just picking nits here so I'm not going to go much further with
this...
:)
In the 'setHappy(bool flag)' function you probably need some "if (flag)
doX(); else doY();" code. It is likely that the client code *also* must
use a decision ('if' or '?:') to set the flag that is being sent to the
member-function... That's some obvious redundancy that can easily be
removed by creating two member-functions.


I think it's unreasonable to expect that client code will usually have
a conditional statement whose semantice are essentially the same as the
decision between happy and unhappy. Not every invokation is going to
look like:

if (cond) setHappy(true);
else setHappy(false);

It's as likely to be:

void f() {
doStuff();
setHappy(true);
doMoreStuff();
}

void g() {
doDifferentStuff();
setHappy(false);
doMoreDifferentStuff();
}

Here, setting the state of happy is part of a larger chunk of logic --
the decision to perform all this logic is at a higher level than the
happy/unhappy decision. So, it is not in any way redundant with any
conditional logic within the implementation of setHappy()! There are a
*lot* of ways to generate a boolean value, as well.
Don't you think it's a bit excessive to write two functions to handle
a single bit of information?


Not if it removes redundant decision code.


It doesn't do that at all. At some point, I've got to decide which
function to call. If I could just pass a boolean value, I could let
setHappy() worry about the conditional structure. But since you've
separated one responsibility into two functions, the client must
generate a boolean value, inspect it, and decide which function to call
accordingly. E.g.:

bool decide(char c);

void f(char c) {
bool cond = decide(c);
cond ? setHappy() : setUnhappy();
}

// versus:

void g(char c) {
setHappy(decide(c));
}

Consider a class which provided all of setHappy(bool flag), setHappy(),
and setUnhappy(). Which of the three do you imagine would see the most
use by clients?
Also, as I pointed out in response to Mr. Roberts, your solution
doesn't scale when there are more than two values in the domain.


Obviously, if decision code is not at issue, then a different construct
should be used.


Are you suggesting that the appellation "decision code" only applies to
behavior that depends on the value of an expression whose type is bool,
as opposed to any other type? Why treat bool differently in this
respect?
Really, you're both just overthinking it, looking for a problem where
none exists. The client needs to indicate a single bit of information;
absent any other information, the best thing is to provide a single
function which takes a bool.


I agree, it's not a big deal either way.


Well, I'm not worked up about it or anything, but I maintain that your
way is poor design, and poor design is very much a big deal, at least
in my line of work.

Consider one more argument. A class's actual state is an
implementation of its logical state, which is visible through the
class's interface. The simpler the interface, the easier for clients
to use. The mapping between interface and logical state should be
intuitive and avoid unnecessary proliferation of entities or
relationships (couplings). A simple (well, trivial) example of this
is:

class Foo {
int x_;
public:
void setX(int x) { x_ = x; }
int getX() const { return x_; }
};

Here, there is a direct mapping between logical state and its
implementation. setHappy(bool) possesses this same simplicity.
Conversely, setHappy()/setUnhappy() introduces an extra entity and an
implicit (in programmatic terms) semantic relationship between them,
because they manipulate the same piece of logical state.

Incidentally, what about accessors? Would you write:

bool isHappy() const { return happy_; }
bool isUnhappy() const { return not happy_; } // ?

See what a problem this coupling presents? A good program is concisely
expressive, and contains as much of the designer's intent as possible.
Where does your implementation express the invariant that (isHappy() ==
not isUnhappy()) is always true? Why do people generally implement
operator!= in terms of operator==?

Luke

Feb 6 '06 #19

Luke Meyers wrote:
More to the point, this is a rather spurious counterexample. If happy
can be appropriately specified by a bool, it's rather questionable to
store it as a string.
I was just giving an example to show that there could be a lot more
going on.
On the other hand, IMHO the 'setHappy()' function shouldn't exist.
There should be two of them:

void makeHappy();
void makeUnhappy();


How is this better?


For one thing it makes more sense. The specifics of what
setHappy(true) vs. setHappy(false) are not entirely clear: is
setHappy(false) just not being happy or being unhappy? There is no
doubt what the intention of the above is.
class Person {
public:
enum Mood { happy, sad, ambivalent, angry, content };
void setMood(Mood m) { mood_ = m; }

// deprecated in documentation.
// kept, with implementation changed, for compatibility as needed.
void setHappy(bool flag) { setMood(happy); }

private:
Mood mood_;
};

This is a clean, extensible generalization.
You have changed the behavior of setHappy!! Now there is absolutely no
use in the parameter at all!! You are implementing my "solution" even
as you argue against it only you are just implementing half of it,
leaving the rest undone.

Yes, it is a silly mistake and not what you meant...but look how easily
that happened. When you see "setHappy" you are not considering the
alternative. It happened because it is more natural to think of
setHappy as having the effect of making the object happy, not in making
it not so. This is actually a rather important part of the discussion
and a fundamental issue.

Were we to take the approach you suggest, we'd wind up with something more like:

class Person {
public:
void setHappy();
void setUnhappy();
void setAmbivalent();
void setAngry();
void setContent();
private:
// implementation details
};
Incorrect. First as I mentioned before when there is a "flag" variable
you usually have room to improve your design. Second none of those
functions should exist. Just like you can't reach into someone's brain
and make them happy, angry, whatever...you shouldn't be able to do so
with an object. "setter" functions are another indication of bad
design; by what right does one object have to touch the privates of
another? Instead, actions that Person takes or that are performed on
Person should create this effect. In other words there should be no
interface for *setting* a person's mood although there may be reason
enough to "interpretMood()" (just in case you might behave differently
with an angry person vs. a happy one) which would likely return some
sort of mood object (that might have query functions like
"mightBeSnappy()" better yet you might want that query in Person itself
and avoid returning a mood at all) for unlike you are expressing, moods
are not mutually exclusive and can be very complex.

Also, why shouldn't there be setX() for certain common sets of moods?
For instance, setContent() might also make a person happy, no?
Operations that are commonly done in a set might well be implemented in
a function instead of leaving it all to the client every time.

Finally you are unfairly misrepresenting the possiblities. Just as you
can "adjust" your interface with the addition of an extra function so
can I:

setMood(Mood m) { mood_ |= m; }
unsetMood(Mood m) { mood_ &= ~m; }
makeHappy() { setMood(happy); }
makeUnhappy() { unsetMood(happy); }

I have just performed the same refactoring algorithm you did and the
result is very much the same. There is no /comparitive/ scaling issues
here. In fact as you can see, my code can represent a vast count more
moods and combination of moods than yours can. Your way would require
that I build my mood mask and pass it in even though I probably only
want to change a particular aspect of the mood.

So while setHappy() and setUnhappy() can seem like a good idea because
it "separates concerns" or "hides implementation details," really all
you've done is treat two particular data values (true and false) as
special cases and written separate interfaces for each. It's easy to
do this for bool because there are only two values in the domain. With
an enumerated type, it's irritating but possible. With pretty much
anything else, it's completely impractical. It doesn't separate
concerns, it tries to represent one thing as two. It produces tighter
coupling, in fact, because clients are tied to the number of methods in
your interface.
Such drastic growth indicates to me that an object is needed to
represent mood. Neither of our "solutions" scale. The problem
actually stems from the very fundamental issue of having setter
functions and state flags.
Now there is no knowledge of, nor reference to, any internal data
whatsoever...these functions could have any effect or combination of
effects.
I'd rather have functions that made sense and dealt with cohesive,
discrete responsibilities. I'd rather not have two functions modifying
the same state needlessly.


Well that depends. What is a person likely to do upon becomming happy
vs. unhappy? Such things could easily grow beyond the feasability of
being done in a single function. At this point you have a function
performing two responsibilities...doing a bunch of stuff to make a
person happy as well as doing a bunch of stuff to make a person not
happy. Is a person likely to do the same thing when becomming happy as
they would when becomming not happy? I doubt it. Now you have a
single function performing two *unrelated* tasks that have the sole
relation of an input flag.

Imagine:

setHappy(bool flag)
{
if (flag)
{ laugh(); smile(); beNice(); throwParty(); }
else
{ cry(); drownInBooze(); beAntisocial(); }
happy = flag;
}

And that is a very simple case but notice how very little is actually
related at all. Becomming happy vs. unhappy have drastically different
effects on the Person in question.

Consider now that you have people with different cultures that have
different moods based on different events. Obviously the very concept
of having a setter for happyness is flawed as this should be done by
the object itself in response to what is done with/to it.
It also gets rid of an if since in the original your code
ends up being something like (assuming set happy got more complex, as
it naturally does):

if (?) flag = true;
else flag = false;

if (flag)
...
else
...
There is nothing wrong with the introduction of a conditional
statement, if it is a clear and effective representation of the logic
being implemented. A conditional statement within a single function
body is less complexity to manage than two separate, but semantically
interwove, functions. If, as in my example above, the requirements
require you to flex in a direction you didn't plan for, such that your
scheme is not extensible, you wind up having to scrap it and start over
with a totally new interface.


You do anyway. My functionality is almost exactly as "extensible"
(actually should say non-extensible) as yours.

The best protection against future change is not to introduce
additional complexity in the name of being flexible, but to represent
concepts in a clear and expressive manner, use good judgement about
appropriate levels of abstraction, and assume as little as possible
about the nature of future changes.
Finally, if you have a variable that makes sense as a "flag" then you
have an area that could use improvement in design. What effect does
the "happy" flag have? One would assume that it is later used to base
decisions on in other member variables and possibly client classes;
branches. It would be better to use a more OO design - possibly the
state pattern but others might be better depending on the effects
'happy' has.


You're being unreasonable.


So you say but the whole thing fell appart, didn't it. Think about how
much of the behavior of a Person would be altered by a mood. Would
"performGreeting()" be the same for example? ( happy ? say("Nice to see
you"):say("Go to hell.") ) I think you are looking at a state and when
you look at a state there is a pattern that can be used, even in simple
cases, that is VERY extensible and clean.

Consider also how much of a person's mood is based on how they
interpret what happens to them and how little is actually based on the
events themselves. No two people feel the same way about the same
thing. Public setter functions take responsibility from where it
belongs, the object itself, and place it in objects that have no
business making these decisions.

There is a difference between thinking ahead a little, or just using
common tools available to you that are known to scale, and "analysis
paralysis". Just looking at something like a public setter and state
flag warned me that there were issues...and there are. Counter and
switch variables have their place but usually limited to a small scope
like a single function or less. If there IS a good reason to have a
flag variable embedded in an object then it is almost never a good
thing to have public setter functions for that flag...why do external
objects need to set your internal state?? Truely there is almost never
a good reason and such constructs almost always indicade poor design
decisions.

In other words your argument for using "flag" in a variable name under
such circumstances is flawed by the fact that such circumstances are
flawed.

Now, occasionally you may run into a reason why it is necessary to do
all of those things that indicate bad design but I have yet to run into
one that wasn't, "because it is already like that and I'm not allowed
(or don't have time) to change it." Occasionally there is, "I couldn't
think of nothing better," but I don't think of that as a *good* reason.

Feb 6 '06 #20
In article <11**********************@z14g2000cwz.googlegroups .com>,
"Luke Meyers" <n.***********@gmail.com> wrote:
Daniel T. wrote:
In article <11*********************@g47g2000cwa.googlegroups. com>,
"Luke Meyers" <n.***********@gmail.com> wrote:
We're just picking nits here so I'm not going to go much further with
this...
:)
In the 'setHappy(bool flag)' function you probably need some "if (flag)
doX(); else doY();" code. It is likely that the client code *also* must
use a decision ('if' or '?:') to set the flag that is being sent to the
member-function... That's some obvious redundancy that can easily be
removed by creating two member-functions.


I think it's unreasonable to expect that client code will usually have
a conditional statement whose semantice are essentially the same as the
decision between happy and unhappy. Not every invokation is going to
look like:

if (cond) setHappy(true);
else setHappy(false);

It's as likely to be:

void f() {
doStuff();
setHappy(true);
doMoreStuff();
}

void g() {
doDifferentStuff();
setHappy(false);
doMoreDifferentStuff();
}

Here, setting the state of happy is part of a larger chunk of logic --
the decision to perform all this logic is at a higher level than the
happy/unhappy decision. So, it is not in any way redundant with any
conditional logic within the implementation of setHappy()!


Of course it is! You say yourself that some "chunk of logic" outside the
object is making the decision between 'happy' and 'unhappy', so why
would you *also* want a chunk of logic *inside* the object making the
exact same decision?
Don't you think it's a bit excessive to write two functions to handle
a single bit of information?


Not if it removes redundant decision code.


It doesn't do that at all. At some point, I've got to decide which
function to call. If I could just pass a boolean value, I could let
setHappy() worry about the conditional structure. But since you've
separated one responsibility into two functions, the client must
generate a boolean value, inspect it, and decide which function to call
accordingly. E.g.:

bool decide(char c);

void f(char c) {
bool cond = decide(c);
cond ? setHappy() : setUnhappy();
}


I'd consider the above poor design as well. A decision is being made in
the 'decide' function, then again in the 'f' function. Duplicated
decision logic is bad, not good. But I think I understand your point.
// versus:

void g(char c) {
setHappy(decide(c));
}
Again, somewhere inside the 'decide' method, a decision is being made as
to wether or not this object should be happy or unhappy. By putting
conditional logic inside the 'setHappy' method, you are forcing the
decision to be made yet again.
Also, as I pointed out in response to Mr. Roberts, your solution
doesn't scale when there are more than two values in the domain.


Obviously, if decision code is not at issue, then a different construct
should be used.


Are you suggesting that the appellation "decision code" only applies to
behavior that depends on the value of an expression whose type is bool,
as opposed to any other type? Why treat bool differently in this
respect?


Because 'bool' is a logical, rather than mathematical entity. It's the
old "one, optional, many" chestnut of programming. If there is a
one-to-one relationship then it should be treated one way, an optional
relationship should be treated another, and a 0 to many relationship
should be treated yet a third.

The example used in the other sub-thread is a great example:

class Object {
public:
enum emotion {happy, sad, angry};
void setEmotion( emotion e );
};

The above makes sense because it is reasonable to assume that more
emotions will be added.

There is a fundamental difference between 1, 0..1, and 0..*. Trying to
make a 0..1 relationship look like a 0..* relationship needlessly
increases maintenance and demonstrates a misunderstanding of the problem
space.
Really, you're both just overthinking it, looking for a problem where
none exists. The client needs to indicate a single bit of information;
absent any other information, the best thing is to provide a single
function which takes a bool.


I agree, it's not a big deal either way.


Well, I'm not worked up about it or anything, but I maintain that your
way is poor design, and poor design is very much a big deal, at least
in my line of work.


Poor design is always a bid deal, but maybe this isn't a issue for
comp.lang.c++. Care to continue in comp.object? (I've already started a
thread on it.)
Consider one more argument. A class's actual state is an
implementation of its logical state, which is visible through the
class's interface. The simpler the interface, the easier for clients
to use. The mapping between interface and logical state should be
intuitive and avoid unnecessary proliferation of entities or
relationships (couplings). A simple (well, trivial) example of this
is:

class Foo {
int x_;
public:
void setX(int x) { x_ = x; }
int getX() const { return x_; }
};

Here, there is a direct mapping between logical state and its
implementation. setHappy(bool) possesses this same simplicity.
No, it doesn't. All over the inside of Foo, are decisions "if (_happy)"
and even if we later factor those decisions out using a strategy
pattern, there will still have to be a decision made in the setHappy
method itself, despite the fact that the decision was *already made*
before the method was called.
Conversely, setHappy()/setUnhappy() introduces an extra entity and an
implicit (in programmatic terms) semantic relationship between them,
because they manipulate the same piece of logical state.

Incidentally, what about accessors? Would you write:

bool isHappy() const { return happy_; }
bool isUnhappy() const { return not happy_; } // ?


This is a completely different issue. The client code is ether doing "if
(object.isHappy() == true)" or "if (object.isHappy() == false)", nothing
at all is to be gained by providing the second 'isUnhappy' method
because it does not serve to remove duplicated logic. Having two
separate set methods *does* remove duplicated logic.

And that's my final word in this forum at least. I'm interested to see
what the question generates in comp.object...

--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Feb 6 '06 #21
Gaijinco wrote:
It just seemed that a function

int max(int a,int b){
return a > b ? a : b;
}

and another one like

int min(int a,int b){
return a > b ? b : a;
}

Were so similar that they could be rewritten as a single function so
the use of a flag seemed valid. I recognize that a flag named flag is
really dumb.


// Instead of a flag, write a generic compare routine and pass in a
// function object which does the acutal comparison.

#include<iostream>
#include<algorithm>

using namespace std;

template<class T, class F> T cmp(T a, T b, F f)
{
return f(a,b) ? a : b;
}

int main()
{
cout << cmp(2, 3, less<int>()) << "\n";
cout << cmp(2.0,3.0,greater<double>()) << "\n";

return 0;
}

Feb 6 '06 #22
In article <11**********************@g43g2000cwa.googlegroups .com>,
"Greg Buchholz" <sl**************@yahoo.com> wrote:
Gaijinco wrote:
It just seemed that a function

int max(int a,int b){
return a > b ? a : b;
}

and another one like

int min(int a,int b){
return a > b ? b : a;
}

Were so similar that they could be rewritten as a single function so
the use of a flag seemed valid. I recognize that a flag named flag is
really dumb.


// Instead of a flag, write a generic compare routine and pass in a
// function object which does the acutal comparison.

#include<iostream>
#include<algorithm>

using namespace std;

template<class T, class F> T cmp(T a, T b, F f)
{
return f(a,b) ? a : b;
}

int main()
{
cout << cmp(2, 3, less<int>()) << "\n";
cout << cmp(2.0,3.0,greater<double>()) << "\n";

return 0;
}


Your supposed to be comparing three numbers, not just two...

--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Feb 6 '06 #23
Daniel T. wrote:
In article <M5*****************@fe06.lga>,
"Jim Langston" <ta*******@rocketmail.com> wrote:
There are many ways to do that, but I'll let others comment on STL methods
to do it before I post anything else cause I'm fairly sure it's simple with
some container iteratation.


#include<iostream>
#include<algorithm>

int main()
{
int nums[] = { 3,1,4,1,5,9,2,6,5,4 };

std::cout << "min: " << *(std::min_element(nums,nums+10))
<< ", max: " << *(std::max_element(nums,nums+10));

return 0;
}
....Then, if you still wanted to roll your own you could use...

int maximum = accumulate(nums,nums+10,*nums,std::max<int>);

....but that doesn't compile (complaining about <unknown type>) with my
copy of g++-3.4.2. But it does work if you define...

template<class T> T my_max(T a, T b) { return std::max(a,b); }

....and then use it like...

int maximum = accumulate(nums,nums+10,*nums,my_max<int>);

....I'd be interested in knowing if it is possible to get the accumulate
version to work without the wrapper function.

Thanks,

Greg Buchholz

Feb 6 '06 #24
In article <11**********************@g43g2000cwa.googlegroups .com>,
"Greg Buchholz" <sl**************@yahoo.com> wrote:
Daniel T. wrote:
In article <M5*****************@fe06.lga>,
"Jim Langston" <ta*******@rocketmail.com> wrote:
There are many ways to do that, but I'll let others comment on STL
methods
to do it before I post anything else cause I'm fairly sure it's simple
with
some container iteratation.


#include<iostream>
#include<algorithm>

int main()
{
int nums[] = { 3,1,4,1,5,9,2,6,5,4 };

std::cout << "min: " << *(std::min_element(nums,nums+10))
<< ", max: " << *(std::max_element(nums,nums+10));

return 0;
}
...Then, if you still wanted to roll your own you could use...

int maximum = accumulate(nums,nums+10,*nums,std::max<int>);

...but that doesn't compile (complaining about <unknown type>) with my
copy of g++-3.4.2. But it does work if you define...

template<class T> T my_max(T a, T b) { return std::max(a,b); }

...and then use it like...

int maximum = accumulate(nums,nums+10,*nums,my_max<int>);

...I'd be interested in knowing if it is possible to get the accumulate
version to work without the wrapper function.


It can be done, but it isn't very pretty.

int main() {
int nums[] = { 3,1,4,1,5,9,2,6,5,4 };
const int& (*m)(const int&, const int&) = max<int>;
int i = accumulate( nums, nums + 10, *nums, m );
assert( i == 9 );
}

I think the problem is that there are two 'max' functions, you need some
way to explicitly tell the compiler which one to use otherwise max<int>
is ambiguous.

--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Feb 7 '06 #25

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

24
by: matty | last post by:
Go away for a few days and you miss it all... A few opinions... Programming is a craft more than an art (software engineering, not black magic) and as such, is about writing code that works,...
226
by: Stephen C. Waterbury | last post by:
This seems like it ought to work, according to the description of reduce(), but it doesn't. Is this a bug, or am I missing something? Python 2.3.2 (#1, Oct 20 2003, 01:04:35) on linux2 Type...
29
by: RAY | last post by:
Hi , my boss has asked I sit in on an interview this afternoon and that I create some interview questions on the person's experience. What is C++ used for and why would a company benefit from...
20
by: Clark | last post by:
Hi all. I'm looking for good C source code to study and be able to advance my C programming skills. Do you recomend any open source project in particular that in your opinion has good writen C...
39
by: Suresh | last post by:
Hi, I am new to C and curious to know some basic questions about C. Why C is good? In what way its better than any other languages? If it is no longer a choice of programming language...why...
8
by: markus | last post by:
Hi, As I been programming in C I have discovered more and more tools that really helps to speed up the development process when writing programs. Examples of such tools are cscope, cbrowser,...
59
by: Alan Silver | last post by:
Hello, This is NOT a troll, it's a genuine question. Please read right through to see why. I have been using Vusual Basic and Classic ASP for some years, and have now started looking at...
30
by: mistral | last post by:
Neeed good javascript unescape encoder, to protect javascript code. Some advices? Online tool, or ready javascript only. Any opinions about the Javascript Obfuscator:...
206
by: WaterWalk | last post by:
I've just read an article "Building Robust System" by Gerald Jay Sussman. The article is here: http://swiss.csail.mit.edu/classes/symbolic/spring07/readings/robust-systems.pdf In it there is a...
244
by: Ajinkya | last post by:
Can anyone suggest me a good compiler for(c/cpp) for windows? I tried dev cpp but its debugging facility is very poor.
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
0
by: Aliciasmith | last post by:
In an age dominated by smartphones, having a mobile app for your business is no longer an option; it's a necessity. Whether you're a startup or an established enterprise, finding the right mobile app...
0
tracyyun
by: tracyyun | last post by:
Hello everyone, I have a question and would like some advice on network connectivity. I have one computer connected to my router via WiFi, but I have two other computers that I want to be able to...
2
by: giovanniandrean | last post by:
The energy model is structured as follows and uses excel sheets to give input data: 1-Utility.py contains all the functions needed to calculate the variables and other minor things (mentions...
4
NeoPa
by: NeoPa | last post by:
Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM) Please note that the UK and Europe revert to winter time on...
3
by: nia12 | last post by:
Hi there, I am very new to Access so apologies if any of this is obvious/not clear. I am creating a data collection tool for health care employees to complete. It consists of a number of...
0
isladogs
by: isladogs | last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, Mike...
2
by: GKJR | last post by:
Does anyone have a recommendation to build a standalone application to replace an Access database? I have my bookkeeping software I developed in Access that I would like to make available to other...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.