

How to make fewer errors at the stage of code writing - Garbage
http://www.viva64.com/en/a/0070/

======
pilif
Tangentially related (section 3 talks about this): why would you ever disable
code using the && false idiom?

You could just remove it (and rely on you source management system to get it
back) or you comment it out (where you will at least get syntax highlighting
to help you spot the dead code).

It happened multiple times to me that I missed a tucked in &&false while I was
porting older code to a new API. As the code was disabled anyways, I could
have spared myself the time of patching it up.

Now sure, if you are just testing something during development, this might be
a viable way to disable code, but something like this should not be committed.
Please use proper comments or better, just remove the code.

In this light I don't understand why the article is even trying to suggest
syntactical "improvements" (adding parentheses doesn't make it more readable
IMHO), when the complicated expression should have just been rewritten to

    
    
        UINT uFlags;
        uFlags = DST_ICON | DSS_NORMAL;
    

No condition, more readable and less runtime overhead. And whoever committed
this got the pleasure of committing "red lines" (git shows removed lines as
red and being able to remove stuff always feels good)

~~~
T-R
I've definitely spent a good while in the past trying to decipher the intent
of someone who used &&alwaysFalseExpression - Is it a bug? Am I overlooking
some subtle side-effect somewhere? If they just wanted to turn the code off,
they would have just commented it out...right?

------
Stormbringer
Understand the problem you are trying to solve. Accept no substitutes.

Get good with your tools (whether that be IDE, knowledge of the language, APIs
etc)

Test your assumptions mercilessly

If you write code as though nobody will ever see it and nobody cares, the code
will suck. If you write code as though for the best, most respected and most
intelligent hacker(s) you know, the then code will be better. Write code as
though you have an important audience that cares deeply about the result.

Yes, you can sprinkle the code with comments explaining to your important
audience how awesome you are and what a clever piece of coding something is.
And this is actually a good thing, since these become focal points for
mercilessly testing your assumptions :D

------
Osiris
It seems to me that the most common errors in C/C++ are memory leak and/or
corruption issues. Coming from someone who's background is in managed/garbage
collected languages, doesn't using a managed language help to avoid these
common mistakes?

I know that it's still possible to leak memory in C#, like not releasing event
handlers, but it's very difficult, if not impossible, to corrupt memory
without using unsafe code. In those cases you're probably more likely to be
careful with how memory is used or manipulated anyway to avoid causing
corruption with the managed code.

~~~
agazso
I would say that the most common errors are because there is no built-in
string type (at least in C) and lot of library function expects null
terminated strings.

And these are hard to get right, because they are very prone to off-by-one
errors, and novice programmers tend to write string manipulation routines from
scratch, which leads to corruption.

Use libraries (e.g. bstring or std::string in C++) that do that for you, and
you won't have problems.

Regarding memleaks: you can leak database handles, file handles and other
resources in managed languages. In C/C++ memory is one of the resources you
also take care of. In C++ there are also destructors and you can use RAII to
handle most of the cases without thinking.

------
T-R
> _Align everything you can in code_

Yes. Makes code easier to read _and_ makes it easier to refactor if you use an
editor with column select/multi-line caret.

~~~
barrkel
I personally detest people who do this, outside of things like tables (i.e.
structured constant initializers) and comments on type definitions. If there's
a high degree of regularity in the source that you're trying to expose,
there's probably a better way of doing it - extracting out common variables,
using a table lookup, adopting acronym conventions for regular parts along any
given axis which have the same length, so that the code naturally lines up
without ugly random rivers of space down the middle.

Unsigned types, on the other hand, are just evil. Way too many people use an
unsigned type because they think it represents an invariant that this value
will never be negative, that it has some kind of documentation or safety
aspect, but that's just wrong. Unsigned types don't act according to the
intuitions of most average programmers, and things as simple as for-loops are
incredibly easy to get wrong with them (e.g. think about the most common idiom
for iterating backwards in C derivatives). If I had my druthers, mixing signed
and unsigned ought to expand the expression to the next larger signed type
that can represent the range of both (and error out if there is none), and
there ought to be separate subtraction / decrement operators specifically for
unsigned types. 'u += -2' where u is unsigned would be a type error -
assigning a signed value to an unsigned location.

~~~
Stormbringer
Sometimes I arrange my variable declarations so that they make a picture of
something in profile...

... don't hate me because I'm beautiful ... :D

\----

On a more serious note, something I have noticed working on large projects
with other programmers, is that if each programmer has their own distinctive
style and conventions, then you can tell straight away by looking at it who
wrote it, and more importantly _who modified it_.

Thus if Billy (who is an idiot) modified something written by Sheila (who is
like unto the goddess of inspired poetry in wisdom and understanding), and the
whole is broken, you can pretty much bet that it is Billy's modification that
has broken it, and you can spot his bits straight away, this makes debugging a
_lot_ easier.

I think this is one of the more unfortunate side-effects of things like
checkstyle and other forms of overly restrictive style enforcement. The more
we sand-paper everybody back to the same (low) level of code appearance, the
more information is lost for what I like to call "forensic debugging".

~~~
barrkel
I strongly agree with this as well - however, when I need to overhaul a huge
portion of the codebase, I may end up normalizing tabs and spacing somewhat;
e.g. tabs between 'if', 'while', 'for' and '(', spaces between function /
array name and '(' or '[', etc.

That is to say, I don't mind everyone being free to format code how they see
fit, just don't be surprised if in rewriting or modifying it, it gets "fixed"
differently.

I'm currently doing this right now at work, hence my vehemence. There's even
things like this in class definitions:

    
    
        int const * const	FooBar // Yes, that's a tab
            (Foo foo, Bar bar)
    

which at first glance can end up looking like instance variable declarations
instead of methods.

------
kstenerud
A better approach to #5 (Do not copy a line more than once) is to make a
"template" copy of the line, which will fail to compile, and then make a bunch
of copies of that.

Example:

Template line:

    
    
        EnableWindow(GetDlgItem(hwndDlg,),);
    

Copy/paste:

    
    
        EnableWindow(GetDlgItem(hwndDlg,),);
        EnableWindow(GetDlgItem(hwndDlg,),);
        EnableWindow(GetDlgItem(hwndDlg,),);
    

Final edit:

    
    
        EnableWindow(GetDlgItem(hwndDlg, IDC_PRIMARYSTATUS), TRUE);
        EnableWindow(GetDlgItem(hwndDlg, IDC_CYCLETIMESPIN), FALSE);
        EnableWindow(GetDlgItem(hwndDlg, IDC_CYCLETIME),);
    

Now when you try to compile, but forgot to update something (such as the
missing boolean in the last line), the compiler will complain.

------
mraybman
For languages that support it, use lambda functions judiciously - too much of
them make code really error-prone and hard to debug. (Not the most wide-spread
problem, but came across this today)

Also check for null!!! ;)

~~~
dpritchett
Your experience is _the exact opposite_ of what I was promised by the
functional programming community. Can you please elaborate on how lambdas are
giving you trouble?

~~~
mraybman
Don't get me wrong, lambdas are really useful and elegant, I just think they
should be used when there is a purpose other than simply making the code
succinct - such as limiting scope. I've seen people use them instead purely to
reduce the number of lines of code, which I think in the end makes it less
readable and harder to debug.

------
narag
Well, this one is not impressive, but I find it useful for C-like languages,
Java included:

    
    
        if (5 == somevar) { ....
    

If you accidentally write "=", you'll notice.

~~~
Jach
Many compilers (gcc and mxmlc come to mind) simply warn you if you try to do
"if (somevar = 5)" and suggest an extra set of parenthesis to shut up the
warning, if that's really what you wanted. Python throws a syntax error.

------
pelotom
7\. Don't write code in C

~~~
loup-vaillant
I know it sound unhelpful, but it isn't. If you can avoid low-level, unsafe
languages like C and C++, by all means do so.

Chose a high-level language like Python, Haskell, Lisp… Anything with closures
and automatic memory management, provided it let you fall back to C when you
really need it.

Outside maintenance, few project need to use C or C++ _all the time_.

------
jey
In C++ you should be using the typesafe functions std::fill and std::copy
instead of memset and memcpy.

