Thursday, May 26, 2011

Commenting Code

Meh...Most comments I've encountered in my life are written under the assumption that comments can make up for poorly written code.. – Stargazer712 Oct 14 '10 at 20:53

I saw the above comment on this page, and I highly agree with what Stargazer712 said.

So often I hear people talking about commenting code as a 'solution' to making crap code understandable. Using comments in this manner is not a solution, but instead a hacky work-around for the in-ability to produce quality code.

If code is well written and structured, then the amount of comments you need can be greatly reduced, as the code itself would be pretty self explanatory.

Furthermore comments can be misleading and do more harm than good. I've seen many cases where a comment says code does one thing, but its really doing another. Or I've seen bad coders change code, but leave in their old comments which are now totally irrelevant, just making the reader more confused.

I'm not saying comments are bad, but I am saying that they are no excuse to be writing crap code. Sometimes code gets very complex, and its not due to the programmer being bad, but instead because they are heavily optimizing something or they are implementing something that's very involved and tricky. In these cases commenting code is very helpful and justified.

Something I personally don't like to see is a lot of comments in the main .cpp files of a project, mainly because it gets in the way of code. Instead I like comments to be placed in the headers and next to the function prototypes away from the main implementation of the code so that when you are actually looking at the .cpp file, you can focus on the real code instead of seeing a wall of green-text getting in the way.
If they're 1 or 2-liner comments then its fine to put them in the .cpp file, but if you're going to write a paragraph then save it for the .h file because I don't want to see that when I'm trying to understand your code (your real code, not what you 'say' your code does!).

Another thing I see often that newbie coders love to do is write obvious comments. Stuff like "i = 1; // set i to 1", these comments are not at all helpful, and they only serve to bloat code.

Anyways I guess I can rant more, especially about bloated code, but I'll think I'll save that for a future post.

Wednesday, May 11, 2011

Checking if variables are of certainin type in C++

Okay this problem is something I often see people do incorrectly in c++.

I've seen people use the sizeof() operator to try and distinguish types such as:
template<typename T> void foo(T x) {
if (sizeof(x) == sizeof(string)) cout << "x is a string\n";
if (sizeof(x) == sizeof(char)) cout << "x is a char\n";
if (sizeof(x) == sizeof(int)) cout << "x is a int\n";

The above is obviously wrong because different types can have the same size. In many 32bit implementations sizeof(std::string) will be equal to sizeof(int).

Now how can we do this better?
Well there's a few ways to do this, one way can be to use template specialization for each of the above cases and make separate functions.

But I'll explain another way. Boost has a templated struct called is_same which we can use in this case. However if you're like me and don't like using a lot of dependencies or over-engineered libraries in your code, then we can write our own code to tell us if two types are the same or not.
It looks like this:
template<typename A, typename B>
struct _isSame { static const bool value = false; };
template<typename A>
struct _isSame<A, A> { static const bool value = true; };

We can now use the above code like this:
template<typename T> void foo(T x) {
if (_isSame<T, string>::value) cout << "x is a string\n";
if (_isSame<T, char>::value) cout << "x is a char\n";
if (_isSame<T, int>::value) cout << "x is a int\n";

Lastly, we can make a helper function that lets us know if two variables are of the same type.
template<typename A, typename B>
inline bool isSame(A a, B b) { return _isSame<A, B>::value; }

And here's an example using the above function:
int main() {
int x = 0;
int y = 0;
float z=0;

cout << "Is x's type the same as y's type? ";
cout << (isSame(x, y) ? "Yes" : "No") << endl;

cout << "Is x's type the same as z's type? ";
cout << (isSame(x, z) ? "Yes" : "No") << endl;