一屏之地,盡收眼底!對的!要的就是短小精悍!c++
翻開項目的代碼,到處可見成百上千行的函數,函數體裏面switch-case、if、for等交錯在一塊兒,一眼望不到頭的感受。有些變態的函數,長度可能得按千米計算了。神啊,請賜予我看下去的勇氣吧!先不論邏輯如何,首先這長度直接就把人給嚇到了。這些超大號函數是怎麼來得呢?redis
這些超長的函數,給咱們形成了很大的麻煩:閱讀代碼找BUG幾乎是不可能的事情,沒有調試器估計撞牆的心都有了;重複代碼形成修改困難,漏掉任何一處早晚是要出問題的;各個層次的代碼混在一塊兒,閱讀代碼至關吃力,人的臨時記憶是有限的,不斷在各個層次之間切換,一下子就給繞暈了。ide
更多內容:http://game-lab.org/posts/zoc-cleancode-5/函數
解決這些問題最重要的就是要保持函數的短小,短小的函數閱讀起來要好得多,同時短小的函數意味着較好的封裝。下面談談關於函數,應該遵循的一些原則:post
在編碼之道:取個好名字中已經介紹過,好名字的重要性,再也不贅述。ui
bool isBossNpc(); void summonNpc(int id); void summonNpc(int id, int type); void summonNpc(int id, int state, int type); // 還能記得參數順序嗎? void showCurrentEffect(int state, bool show); // Bad!!! void showCurrentEffect(int state); // Good!! void hideCurrentEffect(int state); // 新加個函數也沒多難吧? bool needWeapon(DWORD skillid, BYTE& failtype); // Bad!!!
bool RedisClient::connect(const std::string& host, uint16_t port) { this->host = host; this->port = port; this->close(); try { redis_cli = new redis::client(host, port); return true; } catch (redis::redis_error& e) { redis_cli = NULL; std::cerr << "error:" << e.what() << std::endl; return false; } return false; }
重複是一些邪惡的根源!!!this
BAD:編碼
bool saveBinary(type, data) { switch (type) { case TYPE_OBJECT: .... break; case TYPE_SKILL: ... break; .... } } bool needSaveBinary(type) { switch (type) { case TYPE_OBJECT: return true; case TYPE_SKILL: ... break; .... } }
class BinaryMember { BinaryMember* createByType(type){ switch (type) { case TYPE_OBJECT: return new ObjectBinaryMember; case TYPE_SKILL: return new SkillBinaryMember; .... } virtual bool save(data); virtual bool needSave(data); }; class ObjectBinaryMember : public BinaryMember { bool save(data){ .... } bool needSave(data){ .... } };")))
上面提到的原則,若要理解的更加深入,建議去閱讀《代碼整潔之道》,裏面有許多詳盡的例子,對於寫過幾年代碼的人來講,總會發現一些本身所在項目常常犯的毛病。spa
知道了這些原則,咱們應該這樣作:調試
當在添加新函數的時候:
重構現有的函數,有下面狀況的,見一個消滅一個: