從CEGUI源碼看代碼規範

來源:互聯網
上載者:User

CEGUI(Crazy Eddie’s GUI)是一個使用C++實現的基於LGPL協議的的開源GUI庫,主要應用於遊戲介面。連著名的開源遊戲引擎Orge3D也放棄了自己的介面引擎而使用第三方的開源介面引擎CEGUI。

對於開源的代碼工程,我首先會觀察它的代碼規範。比如,使用什麼命名法,是否使用異常等等,這很有用。看不同的開源工程,可以看到各種不同的代碼規範,其中有很多是值得借鑒的。

代碼規範本身並沒有絕對的對錯之分,但我們往往為了某一個代碼規範爭論的面紅耳赤。比如,是否使用匈牙利命名法,使用BOOL還是bool等等。這時,就必須綜合考慮團隊現有的使用習慣和既有代碼的風格,制定出一套適合自己的統一的規範。所以,規範除了對與錯,最關鍵的地方還是要統一。存在即合理,我們不要一味去排斥其他人的使用習慣和規範,而應該多讀讀別人的代碼,看看著名的開原始碼,瞭解別人的做法,然後對自己的做法進行一些反思。這才是面對代碼規範正確的心態。

CEGUI是一套不錯的介面庫,介面布局使用XML來描述,提供了專用的介面編輯器,讓介面製作變得更簡單。CEGUI作為一個成熟的開源產品,代碼已經經曆了無數的千錘百鍊,整體風格比較統一,是一個很好的學習範本。接下來,我粗淺的分析一下CEGUI一些值得學習的地方。

1. Camel命名法

CEGUI完全擯棄了匈牙利命名法,而使用更貼近語義的不使用變數類型首碼的Camel(駱駝)命名法,這也是現今代碼通用的做法。匈牙利命名法在較老的工程中比較常見。無數使用Camel的著名開源工程,很好的告訴了匈牙利命名法的支援者,不使用匈牙利命名法,代碼依然清晰可讀,甚至會更好。

2. 成員變數首碼

CEGUI中無論是class還是struct,成員變數都統一加d_首碼。通常的兩種做法是不加首碼和加m_首碼。

3. struct

CEGUI中,struct的命名沒有使用全大寫,而是和class的大小寫命名一樣。在struct中,只可能出現資料成員,操作符重載函數,建構函式等。struct只用來資料結構儲存使用,不使用任何其他的成員函數。

4. 字串處理

CEGUI中的字串處理沒有使用char, wchar_t, TCHAR,std:string,ATL::CString,而是自己實現了一套String類(CEGUIString.h)。自己實現的String類優勢非常明顯,可以讓程式員從繁瑣的字元指標操作中解脫出來,將更多的精力放在功能的實現上。自訂的String可以實現更多方便、切合實際使用的函數。(比如CEGUI中的find_first_not_of,replace等函數。)如果要實現一個String類,CEGUI中的CEGUIString是一個很好的範本。

5. 使用bool

使用bool和BOOL都有各自的理由,CEGUI中全部使用bool,是現在流行,最常見的,也是我喜歡的做法。

6. 異常機制

CEGUI中完全使用異常機制,通過重載std::exception定義了一套完整的異常機制。通過異常的處理,使得程式員從繁瑣的錯誤檢查和錯誤傳回值中解放出來。如果想瞭解C++中如何能夠很好的使用異常,看看CEGUI中異常的實現吧(CEGUIExceptions.h)。

7. 不用goto

幾乎每一本教材都會告誡使用者,不要使用goto,這會讓你的代碼變得淩亂不堪。然而當真正成為一個程式員,加入一個公司甚至大型公司,裡面的代碼照樣充斥了無數的goto語句。goto的濫用是絕對不允許的,goto在某些情況下的確有它的合理之處(比如保證函數單一出口,釋放資源)。還是那句話,存在即合理。CEGUI中完全不使用goto,有了錯誤,立即拋異常,或者直接返回。我本人也是比較喜歡這種提前返回的方式。

8. 簡單易用的Log系統

如果想實現一個既簡單,又易用的Log系統,就看看CEGUI中的實現吧(CEGUILogger)。支援Log等級(Error,Warning等),輸出日期、當前程式碼等功能。

9. Singleton的實現

CEGUI中使用了一個通用的Singleton<T>模板基類,這個技巧非常好使。實現也非常簡單:

template <typename T> class CEGUIEXPORT Singleton
{
protected:
    static
#ifdef __MINGW32__
    CEGUIEXPORT
#endif
    T* ms_Singleton;
public:
    Singleton( void )
    {
        assert( !ms_Singleton );
        ms_Singleton = static_cast<T*>(this);
    }
   ~Singleton( void )
        {  assert( ms_Singleton );  ms_Singleton = 0;  }
    static T& getSingleton( void )
        {  assert( ms_Singleton );  return ( *ms_Singleton );  }
    static T* getSingletonPtr( void )
        {  return ( ms_Singleton );  }
private:
    Singleton& operator=(const Singleton&) { return this; }
    Singleton(const Singleton&) {}
};

如上面的Logger類,要使用Singleton,則這樣定義:

class CEGUIEXPORT Logger : public Singleton <Logger>
{
}

這樣做最大的一個好處是統一,不會在代碼中出現各種稀奇古怪不同的Singleton實現。同時哪個class是Singleton也一目瞭然。

總結   

本文僅僅討論CEGUI中的代碼規範,而且也只是其中很小的一部分,如有疏漏歡迎一起討論。之後我會更加關注CEGUI現細節,如有收穫將與大家分享。
最後,我還是那句話:不要完全排斥任何一種規範,將每種規範瞭解和使用過後,再來思考自己應該怎樣做。


CEGUI首頁:http://www.cegui.org.uk

源碼下載 :http://www.cegui.org.uk/wiki/index.php/Downloads

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.