0 Errors - 0 Warnings

Are you one of those that don't care about warnings when compiling? Well, if you write conditions like the following,  probably you are:

if (2 == foo)

At first, it seems reasonable: if you forget one "=" by mistake, the compiler will stop the build with an error, making it obvious that you did something wrong. If the condition was written in the opposite way, it only would present you a warning message. But this approach has a big pitfall: the false sense of security.

If you think that whenever your code compiles without errors it is OK and the warnings are just annoying messages that can be easily ignored, you are probably missing the following problem:

if (bar = foo)

Every decent compiler will warn you by telling that, if an assignment is what you really want to do, it's better to surround it with double parenthesis. But if you ignore warnings, you'll get an unexpected (for you) behavior.

In my opinion, compiler warnings are even more important than errors: an error is something that is illegal in the format of a program while a warning is telling you that something looks strange in the logic of your code.

Many warnings are similar to a question: "are you sure you want to do that?" Or better: "doing that you'll get this result: is it what you want?" From my personal experience, many times the answer was "No!"

Bottom line: if you want to be sure that your code won't compile if there are warnings, the flag -Werror of gcc is what you need.

C++ And goto Don't Match Together

As you can see by reading this blog, I'm a fan of goto when used in an appropriate way. Unfortunately it works for C only - not C++.

The issue is all in this short paragraph (6.7/3) of the C++ standard:
It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. A program that jumps from a point where a local variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has POD type (3.9) and is declared without an initializer (8.5).

This means that your C++ compiler will not build many C sources if you have used gotos to bypass initializations.

The solution to maintain the same functionality and the same structure of your code is to use exceptions. I'm sure you are thinking "why cannot I simply use some nested ifs?" My answer is "readability over all!"

An Example

Let's see a quick example, as I would write it in C.
int foo()
{
        int err = 0;
        X *x = NULL;
        Y *y = NULL;

        x = x_factory();
        if (x == NULL) {
                err = 1;
                goto clean_exit;
        }

        y = y_factory(x);
        if (y == NULL) {
                err = 2;
                goto clean_exit;
        }

        while ( /* condition */ ) {
                while ( /* other condition */ ) {
                        /* some code */

                        if ( /* critical error */ ) {
                                err = 3;
                                goto clean_exit;
                        }
                }
        }

        /* some other code */

clean_exit:
        if (x != NULL)
                x_free(x);
        if (y != NULL)
                y_free(y);

        return err;
}
The same code in C++ won't work, if in the code inside or after the loops there is some initialization. So, let's see how you would be tempted to rewrite it.
int foo()
{
        int err = 0;
        X *x = NULL;
        Y *y = NULL;

        x = x_factory();
        if (x != NULL) {
                y = y_factory(x);
                if (y != NULL){
                        while ( /* condition */ ) {
                                while ( /* other condition */ ) {
                                        /* some code */

                                        if ( /* critical error */ ) {
                                                err = 3;
                                                break;
                                        }
                                }

                                if (err != 0)
                                        break;
                        }

                        if (err != 0) {
                                /* some other code */
                        }
                } else {
                        err = 2;
                }
        } else {
                err = 1;
        }

        if (x != NULL)
                x_free(x);
        if (y != NULL)
                y_free(y);

        return err;
}
Too many elses and too indented, in my opinion. Below there is my version, using one of the most powerful constructs of C++: exceptions.
int foo()
{
        int err = 0;
        X *x = NULL;
        Y *y = NULL;

        try {
                x = x_factory();
                if (x == NULL)
                        throw(1);

                y = y_factory(x);
                if (y == NULL)
                        throw(2);

                while ( /* condition */ ) {
                        while ( /* other condition */ ) {
                                /* some code */

                                if ( /* critical error */ )
                                        throw (3);
                        }
                }

                /* some other code */
        } catch (int exception_code) {
                err = exception_code;
        }

        if (x != NULL)
                x_free(x);
        if (y != NULL)
                y_free(y);

        return err;
}
This is my opinion; what's your?

All You Need To Know About Software Development


While I was reading this (long) article, I've felt like all the different pieces of the puzzle in my head go in the right place.

This is the most complete and correct description of the software development best and worst practices I've ever read. Michael Dubakov covered every single aspect and analyzed each factor that can impact on the speed of a software project.

I've only to add a single small note about refactoring: I'm not sure that it is a non-value added activity. Generally speaking it may be so but often, after a refactoring I've found my code run faster and/or have a smaller memory footprint.

That said, it's definitely a great article. Take your time to read and re-read it.


You Are Not A Programmer


So you write code every day, maybe in a nerdy language like C or even in assembly. And a company is paying you for this job. When someone asks you "what do you do?", it's normal for you to reply "I'm a programmer", isn't it?

Well, let's see if you are a liar. This is a simple yes/no questionnaire about what you have done in the last two years.

The Real Programmer Test

  1. Have you studied a new programming language?

  2. Have you used a new technology?

  3. Have you spent some time to optimize your code?

  4. Have you programmed for your pleasure out of the working hours?

  5. Have you eaten at least 50 pizzas?

  6. Have you drunk at least 3 coffees every day?

  7. At least once did you choose to not use your favorite programming language because you thought it was not the best choice for a project?

  8. Have there been more happy days than sad days when doing your job?

If you replied "yes" at more than half of the above questions, congratulations, you are a real programmer!

Explanation of the Test

If you are not a real programmer, maybe you cannot understand how the above questions come from, so here there are some hints.

  • A programmer is curious by nature: he likes to learn new languages and technologies, even if they are not required by his job (questions 1 and 2).

  • A programmer knows that every code needs some refactoring at some point (question 3).

  • A programmer is happy when he can write code (questions 4 and 8).

  • A programmer is realistic: he knows that one-size-fits-all doesn't exists in computer science; in other words, for some purposes a language/technology can be better than another (question 7).

  • A programmer needs to have it's brain constantly fed by carbohydrates (pizza) and sometimes powered by caffeine (questions 5 and 6).

Having said that, you may argue that many of these characteristics are innate. Well, you are right! Many people write code because they think it's just like any other job but they are wrong. Programming needs passion, devotion and the right way of thinking. And over all (as I've read in a pizzeria):

If it were an easy job, everyone would be able to do it

Image by icudeabeach

Authors In The Open Source World

Last week, Seth Godin wrote another great post. This time the argument is the difference between companies and authors. No company would endorse a competitor while writers often suggest books written by others.

The implicit message is that culture is not a product.

Open source logo
Image by Andrew
For FOSS developers it works almost the same. If someone is creating a good software, his project will be not only praised but also improved by other developers. And the good part is that they share their work for free.

For these reasons I think that with the following sentence, Seth is describing a situation wider than he thought.

It's not a zero-sum game. It's an infinite game, one where we each seek to help ideas spread and lives change.