Introduction
I assume you are downloading some source code from time to time. You can learn a lot about a programmer while looking at his source code. There are some tips to help you write clear and effective code. So let's skip this boring introduction and go strait to the article!
Some tips
When naming a variable or a function, try to choose a significant name to help you (and your co-workers) understand the code. You can also use Hungarian notation.
Check the following code. Can you understand what it does?
a=Func1();
b=Func2();
if (a<b)
{
if (!Func3())
{
Func4(1);
return;
}
Func5(2);
}
Now let's write it again:
dtLastBackup=GetLastBackupDate();
dtCurrent=GetCurrentDate();
if (dtLastBackup<dtCurrent)
{
if (!DoBackup())
{
ErrorMsg(IDS_ERRORBACKUP);
return;
}
MessageBox(IDS_BACKUPSUCCEEDED);
}
Now we can understand the code. It is also a good idea to prefix member variables and global variables.
g_szPath=GetPath();
m_nCount=0;
Here we can understand immediately that g_szPath
is a global string variable while m_nCount
is an integer member variable.
Use uppercase in each word of a variable/name: Use "GetPathString
" instead of "getpathstring
".
Try to avoid using global variables and static functions. Use them only when necessary. Use member variables instead.
Add a comment to each major function and each block in your code. This way you and your co-workers can understand what is the purpose of a block/function.
Try to write "beautiful" code to be able to understand it.
for (int y=0;y<20;y++)
{for (x=0;x<20;x++) cout<<"x";cout<<"\n";}
for (int y=0;y<20;y++)
{
for (x=0;x<20;x++)
cout<<"x";
cout<<"\n";
}
Try to use objects when you need to write initialization code. This way you won't forget to release memory. You can also use smart pointers instead of regular ones.
For example, you can write a class to wrap a database object, so you won't forget to close it. It will be closed automatically when the object is being destroyed.
class DBClass
{
protected:
DB m_db;
public:
~DBClass()
{
Close();
}
bool Open();
bool Close();
DB operator->()
{
return m_db;
}
};
void InsertTable(const char *szTableName)
{
DBClass db;
if (db.Open())
db->Insert(szTableName);
}
Use resources for strings and macros/enums for integers. This way you won't have to follow all your code while changing it.
void ResetBoard(char pBoard[20][20])
{
for (int x=0;x<20;x++)
for (y=0;y<20;y++)
pBoard[y][x]=0;
}
#define BOARD_SIZE 20
void ResetBoard(char pBoard)
{
for (int x=0;x<BOARD_SIZE;x++)
for (y=0;y<BOARD_SIZE;y++)
pBoard[y][x]=0;
}
Split your project into several files grouped by functionality. This way you can reuse your code easily. This is also useful when you follow your functions flow.
Use functions/macros instead of copy/paste your code. If you want to change something, you need change it only at one place.
ALWAYS handle errors/exceptions! Don't let your application crash due to an exception you forgot to catch.
Use TRACE
/ASSERT
as much as possible. They don't affect the release build but they can save you a lot of time while debugging.
Take some time to search for existing code instead of reinventing the wheel. For example: Suppose you want to download a file from the internet. Why open socket, parse headers (HTTP) and read the data when you can use existing objects to download files for you?
When using multithreading programming, don't forget to use critical section/mutex wherever we are using shared variables.
Use _T
and text macros so you'll be able to build a Unicode version of your application. For example, use _tcslen/lstrlen
instead of strlen
.
Use sizeof
and don't assume you know the size of your variable/struct. This creates a portable code. Use fwrite(&nCount,sizeof(nCount));
instead of fwrite(&nCount,2);
. An integer may be 2 bytes or 4 bytes long. Let the compiler define it.
Avoid using the heap. Try to use stack based variables. Don't be afraid of "stack overflow". The stack limit is equal to your memory limit. This way you can also avoid defragmentation of your memory.
Try to use standard libraries instead of others. Consider using STL instead of MFC when possible. This way you write a portable code.
Last but not least: BACKUP, BACKUP and BACKUP! You spend half a year working on your application just to find out that your HD crashed. Consider using CVS to track changes.
These are some basic tips. I am sorry for my poor English but I hope you can understand it anyway. If you have any other tips, you can send me and I'll add it to the article.