Sunday, November 11, 2007

Good Code

01. Never allocate memory like this way

void MyFunc(CString strText)

{

int size = strText.GetLength();

TCHAR* pszNewText = new TCHAR[size];

// Good practice is: TCHAR* pszNewText = new TCHAR[size+1];

}

02. Never just delete memory say delete pMyObj, always set pMyObj = NULL after delete

03. Although it doesn't make much difference, but always use the [] operator after using delete for arrays.

Example:

// Always better to use [] after delete for array of any sort of datatypes

delete[] myarray;

04. Avoid Using In/Out Parameters.

That is Avoid using the same parameter as Input as well as output parameter.

Example:

Bad code:

BOOL GetMergedCellRect(CRect& rect)

{

rect.top++;

rect.bottom--;

Return TRUE;

}

Good Code:

BOOL GetMergedCellRect(CRect rect, /*OUT*/CRect& mergedRect)

{

mergedRect = rect;

mergedRect.top++;

mergedRect.bottom--;

}

Although if u have a method such as InflateRect, DeflateRect, whose names are obviously and clearly stating you to do some operation on the passed rectangle, in those cases you can off course use the same parameter as input and output.

05. I think it would be a good idea to typedef the parent class as Super inside the child class.

Example:

class wxEdit : public wxWindow

{

typedef wxWindow Super;

public:

void OnPaint()

{

Super::OnPaint();

}

}

This technique is used in Symbian OS.

06. Although we did some ugly hacking because of the circumstances, but the following is not acceptable. You cannot allow your base class to know about your child classes,

For example, you should never declare a child class a friend of your base class unless absolutely necessary.

class CHotListCtrlCellBase : public CObject

{

friend class CHotListCtrlURLCell;

friend class CHotListCtrlCellCombo;

friend class CHotListCtrlCellCheck;

...

};

06. All of us may be confused or do mistake while using memset() function.

Here is an example that shows correct way of using memset():

TCHAR* pBuff = new TCHAR[256];

memset( pBuff, 0, 256);

memset( pBuff, 0, 256*sizeof(TCHAR));

Sunday, November 4, 2007

List of BAD Coding Conventions

1. Using unnecessary double pointers...

GetNodeName(Node** ppNode)

{

return *ppNode->GetName();

}

U should only use a double pointer when you are allocating your memory with new or malloc() inside a method and passing a pointer as argument to get the newly allocated memory address.

Example:

BOOL COM_CREATE_OBJECT(ComObj** pObj)

{

ComObj* pNewObj = new ComObj;

if(pNewObj)

{

*pObj = pNewObj;

return TRUE;

}

return FALSE;

}

void main()

{

ComObj** pObj = NULL;

// in this case you have to use double pointer.

COM_CREATE_OBJECT(&pObj);

}

2. Converting TCHAR to WCHAR (or WCHAR equivalent), or TCHAR to char (or char equivalent), by simple type casting..

Example:

WCHAR* nodeName = xmlPareser->GetNodeName();

TCHAR* convertedName = (TCHAR*) nodeName;

3. Assuming WCHAR, or wchar_t to be a typedef of unsigned short...

4. Using... wierd macro function names such as Z(), W(), X().. etc..

Example:

WCHAR* fileNameW = GetFileNameW();

TCHAR* fileName = X(fileNameW)... // here x is a function which converts wchar to tchar...

5. Returning temporary pointers as return type

Example:

TCHAR* convertUnicodeToTChar(WCHAR* str)

{

TCHAR buf[255];

wcstombs(buf, str);

// returning temporary pointer ... very dangerous indeed.., maybe u can
// use a global or member variables in this case..

return buf;

}

6. Doing Too Much Processing (such as running a big for loop) in OnMouseMove(), OnEraseBkGnd, OnPaint(), OnCmdUI() etc.

Porting Guidelines

  1. Be careful with use of lower-case letter and upper-case letter concerning the file names because Unix platforms are case sensitive.

    If the name of the file is VSessionManager.h

    Bad Code:
    #include "vsessionmanger.h"

    Good Code:
    #include "VSessionManger.h"
  2. Do not use #pragma once. Use #if !defined() #endif

    Bad Code:
    #pragme once

    Goode Code:
    #if !defined(__MYHEADER_H__)
    #define __MYHEADER_H__
    ...
    #endif
  3. To precise a path for include file, use '/' instead of '\', even on Windows.

    Bad Code:
    #include "..\CmdInterpreter\CmdInterpreter.h"

    Good Code:
    #include "../CmdInterpreter/CmdInterpreter.h"
  4. When manipulating string path, do not use '\' as a separator, because the separator can be '/'. You should use the defined variable PATH_SEPARATOR_STR.

    Bad Code:
    ptr = strrchr(font_path, '\\');

    Good Code:
    ptr = strrchr(font_path, PATH_SEPARATOR_STR);
  5. Do not declared a variable within a block if you need to use it after this block.

    Bad Code:
    for( int i = 0; i < nb; i++ ) {…}
    ...
    for( i = 0; i < 10; i++ ) {…}

    Good Code:
    int i;
    for( i = 0; i < nb; i++ ) {…}
    ...
    for( i = 0; i <>
  6. Do not create a function without type.

    Bad Code:
    toto();

    Good Code:
    void toto() or int toto();
  7. Do not use the following CString functions:
    • Append - you have to use the += operator
    • IsEmpty - you have to do a comparison by using GetSize
    • LoadString(HINSTANCE hInstance, UINT nID) - you can use only LoadString(UINT nID)
  8. Do not use the following CStringArray functions:
    • GetCount - you have to use GetSize
  9. Do not use the following CPoint functions:
    • SetPoint - you should use the x and y members
  10. Do not use the following CSize functions:
    • SetSize - you should use the cx and cy members
  11. Do not use the following CMap functions:
    • GetSize - you should use GetCount
  12. Do not use the following CRect functions:
    • MoveToXY
  13. The code automatically generated by Visual Studio in the Message Map are not correct. You have to remove the "&classname::"

    Bad Code:
    ON_LBN_SELCHANGE(IDC_LANGUAGE_LIST, &CLanguageSelDlg::OnLButtonDownLanguageList)

    Good Code:
    ON_LBN_SELCHANGE(IDC_LANGUAGE_LIST, OnLButtonDownLanguageList)
  14. When using DYNAMIC_DOWNCAST we need to make sure we use DECLARE_DYNAMIC and IMPLEMENT_DYNAMIC for the base class and the dereived class. Otherwise, there will be a compile error in unix platforms.
  15. When called a C method from a C++ method, use the extern C convention.

    Bad Code:
    toto.h: int myfunction();
    toto.c: int myfunction() { return 1; }
    toto_called.cpp: void myfunction2() { int i = myfunction(); }

    Good Code:
    toto.h:
    #ifdef __cplusplus
    extern "C" {
    #endif
    int myfunction();
    #ifdef __cplusplus
    }
    #endif
    toto.c: int myfunction() { return 1; }
    toto_called.cpp: void myfunction2() { int i = myfunction(); }