R
Ray Gardener
I've always wondered what other C++ programmers
fail to do while coding even though they know
what they're doing is... naughty (and some of the
items below occur in other languages, of course).
People make these slip-ups all the time accidentally,
but what I'm getting at is when we make them while
we consciously _know_ that we're being bad. This is
the more interesting phenomenon because I tend to
interpret consciously "fighting the language" or
consciously "not using the language as intended"
as an indication that the language or the
development environment could be improved.
(Granted, in C++ the "right way" is vague because
C/C++ has broad expressive capability, but there
are informal standards of good coding practice
that we all more or less know).
Examples:
- Duplicating code via copy/paste instead of
making subroutines.
- Failing to make methods and other things 'const'
when they should be.
- Failing to assert what should be asserted.
- Not using templates when they would be suitable.
- Trying patches instead of refactoring (only
to sooner or later refactor anyway, and then
feeling sheepish about it).
- Passing to functions references to objects
that give too much info to the function,
when it only needs a few members of the object.
- Making "incestuous" calls instead of using
signal/slots/broadcasters/listeners or similar
design patterns.
- Using your own container classes instead of STL,
when STL would have been the better choice.
- Using #define macros instead of template functions.
- Using boolean types instead of enums even though
you know that the type will soon grow beyond
two possible states.
- Letting a class grow until it has a zillion members.
- Using pointers instead of references when refs
would have been better.
- Putting "is-a" members inside a class instead of
making a new subclass, and having callers query
those members in a roll-your-own form of RTTI.
- Using error code returns or object error states
instead of exceptions.
- Letting class members be public that shouldn't be.
- Letting a function grow really long only because
technically it doesn't actually have to be broken
down into subroutines because none of them would
be called from anywhere else anyway.
- Using more and more preassigned function args
to avoid having to declare another function of
a similar name, or the reverse -- not using
preassigned args where they make sense.
- Making methods with names like "add" and "mul"
instead of using operator overloading.
- Being inconsistent in naming, spelling,
interface strategies, etc.
- Declaring more global objects than necessary.
- Placing code that makes sense in a shareable library
into application-side classes (or just letting it
sit and evolve on the app side while telling yourself
that you'll factor it out "someday").
- Using char* instead of a more Unicode-friendly string type.
- Using two member vars to track a state of only
one logical member (e.g., a bool and a pointer when
the pointer's being null will suffice to indicate
a false state).
- Specifying constants by value instead of by macro or enum.
- Using int instead of size_t when size_t is the
better type (e.g., you're declaring a zero-based counter).
- Using #define's instead of enums.
- Using external enums instead of class member enums.
- Using a struct instead of a class (even when it becomes
painfully obvious that it should be a class).
- Solving a typical problem one way, then the same
problem a different way somewhere else because
it is superior, but failing to go back and upgrade
the usages of the first implementation.
- Using malloc/free in some places and operator new/delete
in others, for no particular reason.
Obviously some of the above are rational tactical
decisions under certain situations, so I'm not
including those combinations of choice and context.
I'm interested in finding out what poor choices
C++ programmers consciously make and why. Was it
easier at the time? More expedient? Force of habit?
Does the dev environment foster those habits
(e.g., an editor with great copy/paste might
actually be bad)? Is good coding a matter of
willpower or do certain tools turn the tide?
Does extreme or paired-up programming help
combat these tendencies? Is perfect discipline
even desirable?
Ray
fail to do while coding even though they know
what they're doing is... naughty (and some of the
items below occur in other languages, of course).
People make these slip-ups all the time accidentally,
but what I'm getting at is when we make them while
we consciously _know_ that we're being bad. This is
the more interesting phenomenon because I tend to
interpret consciously "fighting the language" or
consciously "not using the language as intended"
as an indication that the language or the
development environment could be improved.
(Granted, in C++ the "right way" is vague because
C/C++ has broad expressive capability, but there
are informal standards of good coding practice
that we all more or less know).
Examples:
- Duplicating code via copy/paste instead of
making subroutines.
- Failing to make methods and other things 'const'
when they should be.
- Failing to assert what should be asserted.
- Not using templates when they would be suitable.
- Trying patches instead of refactoring (only
to sooner or later refactor anyway, and then
feeling sheepish about it).
- Passing to functions references to objects
that give too much info to the function,
when it only needs a few members of the object.
- Making "incestuous" calls instead of using
signal/slots/broadcasters/listeners or similar
design patterns.
- Using your own container classes instead of STL,
when STL would have been the better choice.
- Using #define macros instead of template functions.
- Using boolean types instead of enums even though
you know that the type will soon grow beyond
two possible states.
- Letting a class grow until it has a zillion members.
- Using pointers instead of references when refs
would have been better.
- Putting "is-a" members inside a class instead of
making a new subclass, and having callers query
those members in a roll-your-own form of RTTI.
- Using error code returns or object error states
instead of exceptions.
- Letting class members be public that shouldn't be.
- Letting a function grow really long only because
technically it doesn't actually have to be broken
down into subroutines because none of them would
be called from anywhere else anyway.
- Using more and more preassigned function args
to avoid having to declare another function of
a similar name, or the reverse -- not using
preassigned args where they make sense.
- Making methods with names like "add" and "mul"
instead of using operator overloading.
- Being inconsistent in naming, spelling,
interface strategies, etc.
- Declaring more global objects than necessary.
- Placing code that makes sense in a shareable library
into application-side classes (or just letting it
sit and evolve on the app side while telling yourself
that you'll factor it out "someday").
- Using char* instead of a more Unicode-friendly string type.
- Using two member vars to track a state of only
one logical member (e.g., a bool and a pointer when
the pointer's being null will suffice to indicate
a false state).
- Specifying constants by value instead of by macro or enum.
- Using int instead of size_t when size_t is the
better type (e.g., you're declaring a zero-based counter).
- Using #define's instead of enums.
- Using external enums instead of class member enums.
- Using a struct instead of a class (even when it becomes
painfully obvious that it should be a class).
- Solving a typical problem one way, then the same
problem a different way somewhere else because
it is superior, but failing to go back and upgrade
the usages of the first implementation.
- Using malloc/free in some places and operator new/delete
in others, for no particular reason.
Obviously some of the above are rational tactical
decisions under certain situations, so I'm not
including those combinations of choice and context.
I'm interested in finding out what poor choices
C++ programmers consciously make and why. Was it
easier at the time? More expedient? Force of habit?
Does the dev environment foster those habits
(e.g., an editor with great copy/paste might
actually be bad)? Is good coding a matter of
willpower or do certain tools turn the tide?
Does extreme or paired-up programming help
combat these tendencies? Is perfect discipline
even desirable?
Ray