473,806 Members | 2,944 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Conscious antipattern behavior

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

Jul 22 '05 #1
17 1805
On Sun, 11 Jan 2004 10:13:43 GMT, "Ray Gardener"
<ra**@daylongra phics.com> wrote:
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:
[snipped]
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


Some programmers just plain don't know any better. Then there are
those who don't want to know any better because they have gotten away
with their stuff for years and nobody ever said anything. Then there
are those who know better, but have such ingrained bad habits that the
attempt to adhere to any kind of programming guidelines totally
paralyzes them and they can't get any work done as a result. Then
there are those who would like to change their ways, but management
won't let them for various reasons.

For some companies, in-house software development is only a necessary
evil (or at least treated as such). There is absolutely no budget for
refactoring unless the customer is at the door screaming. Nothing is
allocated money-wise that cannot be billed on a basis of man-hours to
a paying customer. If something works, or seems to work OK, it is sent
into production with a minimum of testing (usually most of the testing
is done by the developer, or there might be some integration tests
with such a limited amount of data that no bugs ever show up before
sending the thing to the customers). Deadlines are totally unrealistic
and are usually not met if the developers try to do any proper design
instead of just ripping out bits and pieces of other software, use 3rd
party components which seem to "do the job" without regard to later
portability or extensibility, etc. etc.

In such an environment, there is very often no code review. Developers
think they are the only ones who will ever have to maintain their own
code, especially if the project has a short life cycle due to other
concerns. Since nothing gets reused, no effort is made to make a good
design. Under these circumstances, copying and pasting often seems to
be the quickest way of implementing "code reuse".

Most of your examples are very good ones. Templates and other advanced
language features, however, were not supported adequately by a lot of
compilers until just recently, so lots of experienced developers avoid
them. As a result, they have no experience using templates and often
don't have the time (or aren't given time) for additional courses so
they can learn how to use them.

Just my 2 cents ...
--
Bob Hairgrove
No**********@Ho me.com
Jul 22 '05 #2
Your list is very good. One of the main problems is
lack of training.

You will not find many training courses on such bread-and-butter
issues. Training sessions often focus on much higher level of
design.

You might find the following articles interesting:

http://www.eventhelix.com/RealtimeMa...esign_tips.htm

http://www.eventhelix.com/RealtimeMa...ign_tips_2.htm

Sandeep
--
http://www.EventHelix.com/EventStudio
EventStudio 2.0 - System Architecture Design CASE Tool
Jul 22 '05 #3
Ray-

Nice post. But if you're looking for someone to cast the first stone you'll
have to look elsewhere. We all have cut a few corners from time to time.

--
Cy
http://home.rochester.rr.com/cyhome/
Jul 22 '05 #4

"Cy Edmunds" <ce******@spaml ess.rochester.r r.com> wrote in
message news:ux******** ***********@twi ster.nyroc.rr.c om...
Ray-

Nice post. But if you're looking for someone to cast the first stone you'll have to look elsewhere. We all have cut a few corners from time

to time.
"We cannot fix what we do not dare speak about"

Ray

Jul 22 '05 #5

"EventHelix.com " <ev********@hot mail.com> wrote in message
news:56******** *************** ***@posting.goo gle.com...
Your list is very good. One of the main problems is
lack of training.

You will not find many training courses on such bread-and-butter issues. Training sessions often focus on much higher level of
design.

You might find the following articles interesting:

http://www.eventhelix.com/RealtimeMa...ented/object_d
esign_tips.htm
http://www.eventhelix.com/RealtimeMa...ented/object_d
esign_tips_2.ht m
Sandeep

Thanks, those are good articles. The topic on hierarchical state
machines was particularly interesting.

I wonder if one could implement a language that does to C++ what
C++ does to C -- abstract it upwards (C++ was even first
implemented as a C code emitter that a C compiler would then
compile). In this language, templates and signals/slots would be
first-class citizens, crossgrain/systemwide features would be
straightforward to implement, some desirable practices would be
easier instead of harder to do, etc. I see some of these ideas
being tried elsewhere in fits and starts but having the language
emit C++ code would let us use the existing compilation
infrastructure.

Ray
Jul 22 '05 #6
"Ray Gardener" wrote
: I wonder if one could implement a language that does to C++ what
: C++ does to C -- abstract it upwards (C++ was even first
: implemented as a C code emitter that a C compiler would then
: compile). In this language, templates and signals/slots would be
: first-class citizens, crossgrain/systemwide features would be
: straightforward to implement, some desirable practices would be
: easier instead of harder to do, etc. I see some of these ideas
: being tried elsewhere in fits and starts but having the language
: emit C++ code would let us use the existing compilation
: infrastructure.

Generative programming has been a developing science for quite a few years
now. With template metaprogramming , much of this can be done inside the
type-checked part of translation, and the rest can usually be done in the
preprocessor. There are some good pattern libraries out, perhaps the most
famous being Loki, and it certainly seems to be a fertile field.

If you do not already have it, I would strongly suggest getting the book on
Generative Programming by Czarnecki and Eisenecker. It is the best textbook
I have found on these issues, though of course there are many pattern and
conference-proceedings-type books that cover fragments of the research.

--
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

galathaea: prankster, fablist, magician, liar
Jul 22 '05 #7
"Ray Gardener" wrote
: 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).

I don't think they are that vague. I think for many of the issues you
discuss, there are objective metrics which can be applied to at least
partially order the usefulness of approaches. I think for the most part,
though, it has taken years of research and experience with the c++ language
for these metrics to be developed in the community. And along the way, some
developers did not keep up. It is rarely taught that programmers should
read conference proceedings, IEEE Software, or other more technical sources
outside of the academic setting, and a lot of initial work on such metrics
originate in those types of places. So usually, these things come to the
working developer either through personal insight and experience or through
popularisations . In fact, my experience has been that many developers do
not even read about their art except when a new skill is required, and then
not often deeply. Some people are just not readers...

However, that is not the particular interest here. The conscious
antipattern behavior is, in my experience, a phase that most people go
through when trying to adjust their habits. Because really, I believe
programming is rarely a task limited only by time. I believe that much of
the effort in programming is mental, as trying to solve complicated logical
problems and keep all the relevant pieces juggled in short term memory can
be quite a draining endeavor. People build habits to make things easier.
Sometimes suboptimal habits get formed, and when this is discovered, the
habits must change. But changing habits can take more energy than forming
fresh, uninfluenced ones, so you need to give it time. Sometimes people
don't give it the time or effort, and the habits don't change.

So, even if the "more correct" way to do something requires less typing /
clicking / manual work overall (including future refactoring considerations
and reuse), the habituated suboptimal behavior may manifest because it
requires less mental energy. And when you are being hounded by management
and deadlines for large subsystem work, mental energy can be a rare
commodity. Only when breathing time is found, can the work on changing a
habit occur.

[...]
: 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?

I do believe the development environment is an important factor. I think
this is one of the driving forces for the intensional programming movement.

--
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

galathaea: prankster, fablist, magician, liar
Jul 22 '05 #8
Ray Gardener wrote:
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 [defining and calling functions].
You mean "manual inlining" to save the cost of a function call
and permit the C++ compiler to optimize the code.
The alternative is to declare functions *inline*
so that the compiler will automatically inline them.
- Failing to make methods and other things 'const'
when they should be.
When should they be const?
- Failing to assert what should be asserted.
An example would help.
The C preprocessor assert macro is only useful
for detecting and debugging programming errors.
- Not using templates when they would be suitable.
When are templates suitable?
- Trying patches instead of refactoring
(only to sooner or later refactor anyway
and then feeling sheepish about it).
Refactoring takes time and costs money.
Feeling sheepish is free.
- Passing references to objects to functions
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.
Never reference STL container classes
(or any built-in type) directly in your application source code.
Wrap the STL container class is your own class definition
so that you can substitute something else later if necessary.
- 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.
Group the members into classes as appropriate.
- Using pointers instead of references
when references would have been better.
When are references 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.
You can return an exception object instead of an error code
but you can use the function in an expression.
- Letting class members be public that shouldn't be.
When should class members be public?
- 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.
Functional decomposition helps make your code
easier to read, understand and maintain.
- 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.
Where do they make sense?
- [Implementing functions] 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.
When is it *necessary* to declare global objects?
- 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).
There is *no* difference between a struct and a class in C++
except that class members are private by default and
struct members are public by default.
- 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?


The C++ computer programming language introduced
many subtle new features to C programmers.
They are still learning to use them. It takes time
and many of the older, more experienced programmers
will never fully appreciate them and take advantage of them.
Most C++ programmers are amateur programmers.
They write C++ programs to help them do the work
that they were hired and paid to do.
They typically learn just one language
and they try to use it for everything.
They learn just enough about the language
to do what they need to do.
They avoid the more complicated and subtle features
of the language and use the subset of features
with which they have experience and that
they believe they really understand.

Computer programming is *evolutionary* -- not revolutionary.
You must wait until this older generation of programmers
retires (or passes away) before you can expect real improvement.

Jul 22 '05 #9
"E. Robert Tisdale" <E.************ **@jpl.nasa.gov > wrote in message
news:40******** ******@jpl.nasa .gov...
Ray Gardener wrote:

- Using your own container classes instead of STL,
when STL would have been the better choice.


Never reference STL container classes
(or any built-in type) directly in your application source code.
Wrap the STL container class is your own class definition
so that you can substitute something else later if necessary.


How can you reference STL containers other than directly in your
source code? Maybe if you said 'rarely use STL containers in your
public interfaces' I could agree.

Do you really think one should never use built-in types, such as int?

There is *no* difference between a struct and a class in C++
except that class members are private by default and
struct members are public by default.


And struct inheritance is public by default.

Jonathan
Jul 22 '05 #10

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

Similar topics

1
8330
by: Stanimir Stamenkov | last post by:
Here's an example: <form action="bogus" method="post"> <p> <a href="prev.cgi"><input type="submit" name="prev" value="< Back"></a> <a href="next.cgi"><input type="submit" name="next" value="Next >"></a> </p> </form>
12
3808
by: Dave Rahardja | last post by:
Does the C++ standard specify the behavior of floating point numbers during "exceptional" (exceptional with respect to floating point numbers, not exceptions) conditions? For example: double a = 1.0 / 0.0; // What is the value of a? Infinity? double b = 0.0 / 0.0; // What is the value of b? NaN? What about overflow/underflow conditions in the library? Is HUGE_VAL always a
19
2599
by: E. Robert Tisdale | last post by:
In the context of the comp.lang.c newsgroup, the term "undefined behavior" actually refers to behavior not defined by the ANSI/ISO C 9 standard. Specifically, it is *not* true that "anything can happen" if your C code invokes "undefined behavior". Behavior not defined by the ANSI/ISO C 9 standard may be defined by some other standard (i.e. POSIX) or it may be defined by your compiler, your operating system or your machine architecture.
23
3220
by: Ken Turkowski | last post by:
The construct (void*)(((long)ptr + 3) & ~3) worked well until now to enforce alignment of the pointer to long boundaries. However, now VC++ warns about it, undoubtedly to help things work on 64 bit machines, i.e. with 64 bit pointers. In the early days of C, where there were problems with the size of int being 16 or 32 bits, the response was that an int was guaranteed to hold a pointer (yes, there were 64Kb address spaces at one time!)....
7
22499
by: Mike Livenspargar | last post by:
We have an application converted from v1.1 Framework to v2.0. The executable references a class library which in turn has a web reference. The web reference 'URL Behavior' is set to dynamic. We added an entry to the executable's .exe.config file to specify the URL, and under the 1.1 framework this worked well. Unfortunately, this is not working under the 2.0 framework. I see in the Reference.cs file under the web service reference the...
12
3080
by: Rajesh S R | last post by:
Can anyone tell me what is the difference between undefined behavior and unspecified behavior? Though I've read what is given about them, in ISO standards, I'm still not able to get the difference. For example: Consider the following code: a = i; We say that the above expression statement produces undefined
28
2580
by: v4vijayakumar | last post by:
#include <string> #include <iostream> using namespace std; int main() { string str; str.resize(5); str = 't';
35
2257
by: bukzor | last post by:
I've found some bizzare behavior when using mutable values (lists, dicts, etc) as the default argument of a function. I want to get the community's feedback on this. It's easiest to explain with code. This example is trivial and has design issues, but it demonstrates a problem I've seen in production systems: def main(argv = ): 'print out arguments with BEGIN and END' argv.insert(1, "BEGIN")
33
2849
by: coolguyaroundyou | last post by:
Will the following statement invoke undefined behavior : a^=b,b^=a,a^=b ; given that a and b are of int-type ?? Be cautious, I have not written a^=b^=a^=b ; which, of course, is undefined. I am having some confusion with the former statement! Also, state the reason for the statement being undefined!
0
9719
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9597
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10620
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10369
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10372
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9187
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6877
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5682
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3851
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.