mardi 20 janvier 2009

functional abstraction of data members with boost::bind

I just wanted to share a little trick I learned some time ago : you can use boost::bind to transform pointers to data members into functors.

For example, if you have a struct that looks like this :


struct my_struct
{
explicit my_struct( int value )
:m_some_member( value )
{
}
int m_some_member;
};


You can use boost::bind( &my_struct::m_some_member, _1 ) as a valid functor that will take an instance of my_struct as a parameter and return an int.

Admit it, it's pretty cool :-) You don't have to write the getter, bind will generate it for you.

What this kind of technique does to code readability is a matter you have to consider if you want to use it in a professional environment... I myself would most definitely write the getter in the vast majority of situations.

It's always fun to close with a little program that shows I cared enough to test the subject prior to publication ; here it is


#include <iostream>
#include <algorithm>
#include <vector>
#include <boost/bind.hpp>

struct my_struct
{
explicit my_struct( int value )
:m_some_member( value )
{
}
int m_some_member;
};

struct printer
{
typedef void result_type;
template< typename T >
inline void operator()( const T& anything )
{
std::cout << anything << std::endl;
}
};

int main()
{
std::vector< my_struct > my_vector;
my_vector.push_back( my_struct( 0 ) );
my_vector.push_back( my_struct( 1 ) );
my_vector.push_back( my_struct( 1 ) );
my_vector.push_back( my_struct( 2 ) );
my_vector.push_back( my_struct( 3 ) );
my_vector.push_back( my_struct( 5 ) );
std::for_each(
my_vector.begin(), my_vector.end(),
boost::bind( printer(),
boost::bind( &my_struct::m_some_member, _1 ) ) );
return 0;
}

samedi 17 janvier 2009

The selfish idiom

This is yet another post inspired by neodarwinism.

Code duplication happens all the time, no programmer doubts that. Because duplicating a piece of code is easy as hell and initially very cheap you quickly get yourself into some kind of a living mess. Big code bases do have a life of their own and the forces driving it are most interesting.

What makes a code fragment successful? It's like our own genes, it has to be reproduced at a high rate without copying errors. When that happens the replicating idiom slowly invades the code base. A growing number of similar duplicates increases the probabilities that one of them will be noticed by a programmer and copy-pasted once more ; so there is a positive feedback loop. Even if all programmers will tell you it's bad practice to help a piece of code multiply, when a specific instance of an idiom is all over the place it becomes standard practice. Give it a few more months, and it's a local 'best practice'.

The fragments of code that get copy-pasted are over-represented in our code bases... that says almost nothing about them. After all, they don't really replicate by themselves, they need our help. All these little code samples must have some kind of mind controlling power to force us to do their bidding. Successful code knows how to exploit our pride and laziness. I think that one of the super-powers self-duplicating code have is incomprehensibility.

survival of the misunderstood

That was the original title of the post. Control-C control-V is the standard prayer of our cargo cults. It's also the fertility dance that our code gene overlords make us do on those last-night hacking sessions. We get ourselves in a caffeinated transe and dance the dance of life!

Actually, the whole process is celebrated in a long mass. First we have the high priest creating the original code, with the original sin hidden inside of it. Then it's presented as an offering to a less experienced follower, that will a little while later pass the good news to colleague. It's very important that the followers don't quite understand what is going on inside the code, or else they might be tempted to factor it as a function and put an end to an evolution branch. The use of global state, counter-intuitive interfaces and weird 3rd-party libraries are all on the code's side.

how to kill it

What do we do now? It's very tempting to simply say "writer simpler code" ; but that would be very wrong. Of course you should not write code that's needlessly complicated, but stating the obvious never helps. My point is that there is very often a true need for the complexity we put in code. The complexity in good code simply represents the true complexity of the underlying problem and helps prevent code duplication. Otherwise you get simplexity.

There are two players in this game : the code and the coders. If we can't simply make the code simple, maybe we can make the coders better. After all, this high priest that created the original sin probably understands a good deal of it. He should work more at explaining his creations to his followers, and put a little less time in changing the colors of buttons, documenting, or whatever the boss of his boss thinks is valuable, billable hours.

jeudi 15 janvier 2009

Beauty in code

We should write beautiful code.

Saying that of course begs the question, what is beautiful code? And I won't answer it... not really. We should write beautiful code because we are equipped with hardware that can tell really really fast if something is beautiful.

Beauty is not useless

Without getting into the usefulness of live, physical beauty is synonymous with sexy for really good reasons. It is supposed to be an indicator of health in us, humans. Facial asymmetry, for example, can be an indicator of brain damage in early life. Someone with a koala face has more chances of being healthy. I am not sure of that at all, but for the argument's sake, let's say it's true. {When you think about it, beauty is not in the eye of beholder. It's in the dick of the fucker :-) }

So, should we abandon the use of our consciousness in favor of our guts when programming? {Let's call that Colbert style} Kind of, I guess :-) It would be more fun for the guy creating the new code, that's for sure!

We can do something a little less stupid by teaching us what should be beautiful code. But how?

The first thing to do is to reject beauty as criteria when programming and conducting code inspections. There is no contradiction! If you surround yourself with code you feel is beautiful, than you get beauty for beauty's sake - that's circular and retarded. You should surround yourself with code that's right, with the hope that in time you'll get used to it. Familiar code quickly becomes beautiful.

If we ever get to the point where ugly code is probably wrong, life will be sweet! Coding will be so much easier - but don't get comfortable! You'll still have to refrain from rejecting code on the basis of ugliness, or your sense of beauty will drift and once again become your worst enemy.

dimanche 11 janvier 2009

C++ interview questions/inspiration - part 2

So, the candidate has given an ok answer to the first question and/or you feel they deserve a second chance to impress you. I looooove this second question. It can really show how much of a professional the candidate is.

Here is the question :

Read the following program (the code is at the end of the post).

a) If the second dynamic memory allocation fails by throwing an exception, what is printed on the console?

b) Where is the bug in the application ; how would you fix it?


I love it because there is fun to be had for everyone. If the candidate is kinda junior, make sure he can tell the difference between the objects that are dynamically allocated vs those that are allocated on the stack. If the candidate can't tell the stack from the heap, you can skip the rest ; it's hopeless.

The key to the first part of the answer is to know that the members of an object are initialized in the order they are declared in the class, not in the order of the initialization list. The door class is written with that in mind. All the rest is straightforward for the first part of the test.

The question b) is much more interesting. The idea here is to make sure the candidate understands RAII. Bonus if he can mention it by name, but that's not what is important.

A senior programmer will jump on the memory leak like a wolf on a sheep, but others might not. I suggest you don't fail those that don't get it right away. Ask them if they know what a smart pointer is ; if they ever used one. If you can get someone to say that it's a good idea to use boost::scoped_ptr in this case, it's a keeper :-)

I also always ask the hidden sub-question c) What's the difference between boost::shared_ptr and boost::scoped_ptr ; and what is wrong with std::auto_ptr? There is no such thing as a senior C++ programmer that has never heard of boost. Call me elitist all you want, you won't be able to convince me otherwise.

Now, my favorite interview questions always allows exceptionnal candidates to distinguish themselves. In this case, if you get a pretty good answer to question b), repeat the question a) with the fixed program. It's harder, because the candidate has to know how destructors are called in the stack unwiding process. Once again, if he can't quite do it, help him a little. Tell him "The destructor is called if the object was fully constructed, and an object is fully constructed when the flow of the program leaves a constructor normaly." ; it should help.

If you ever try it on a candidate, tell me how it goes :-) I hope it will be as usefull to you as it has been to me.

#include <iostream>

struct door_handle
{
door_handle()
{
std::cout << "c-door_handle\n";
}

~door_handle()
{
std::cout << "d-door_handle\n";
}
};

struct window
{
window()
{
std::cout << "c-window\n";
}

~window()
{
std::cout << "d-window\n";
}
};

struct door
{
door_handle* m_door_handle;
window* m_window;
door()
: m_window( new window() )
, m_door_handle( new door_handle() )
{

}

~door()
{
delete m_window;
delete m_door_handle;
}
};

struct car
{
door m_left_door;
door m_right_door;
};

struct acura : public car
{
};

int main()
{
try
{
acura some_car;
std::cout << "we have a car!\n";
}
catch( ... )
{
std::cout << "error\n";
return 1;
}
std::cout << "bye-bye\n";
return 0;
}


Update

Parts three and four are now available.