Sunday, October 11, 2009

What are you assuming?

Last week, I was reading src code and found that it used zero as an initial value for a handle.

MY_HANDLE handle = 0;

But, it also used INVALID_HANDLE for the same purporse.
class A
{
public:
A() : m_handle(INVALID_HANDLE) {}

private:
MY_HANDLE m_handle;
};
Well, I thought that INVALID_HANDLE was zero. However, it turned out that it's not. INVALID_HANDLE was defined with some weird value. Anyway, the exact value is not important. The importatnt thing is how I know what should be an initial value for MY_HANDLE?

Suprisingly, I'm told that some code use INVALID_HANDLE as a VALID value and there is a legitimate situation that a handle of an object is INVALID_HANDLE. Wow. Okay, so the real invalid value which is supposed to be used as an initial value is zero, not INVALID_HANDLE.

Yeah, I know this kind of things always happens in real world as we always see this comment;"Fix me!". But, before we fix this, I'd like to ask this question.

How can we communicate with other programmers who will work with the code we write in future? More specifically, how can we show our assumption in the code? Or, do we even need to do it? why?

Why?

Because we are all different humans. All of us have an unique appearance, personality and assumption. It's perfectly fine with having your own assumption like your own habits. But, there is no guarantee that your assumption makes sense to others. That's why we should say it very loudly whenever we assume something.

How?

First of all, name it correctly. If it is a function returning a size of array, name it "GetSizeOfArray()". If it's a value containing your grade, name it "myGrade". If it's a constant value for an invalid handle, name it "INVALID_HANDLE" and use it as it is called. You can follow your "common" sense but don't hesitate to spend enough time naming something.

Second, use assertion whenever you can. It can correct your assumption quickly if it is wrong, it is crystal clear for other programmers and you can turn it off easily so that it doesn't cost anything in your retail build. Yeah, it's cheap (almost free) but powerful enough to save your project.

One thing I should mention about assersion is that you should not mix assertions with error handling. If there is an error and you need to handle it, just handle it without writing asserion.
See the below code.
assert(pRect != NULL);
if(pRect != NULL)
pRect->Draw();
The code says two things at the same time and they conflict with each other. It says "pRect must not be NULL." and "Call Draw() if pRect is not NULL". The latter one implicitly assumes that pRect might be NULL but the assertion says that pRect should never be NULL.

As Scott Meyers said that a female is either pregnant or she's not (in Effective C++), you should choose only one of them. Is it a part of program flow? or should it never happen? It's not possible to be partially pregnant.

No comments:

Post a Comment