COdE fr3@K

1/25/2006

Feeding Frenzy

上週, 不來爾 (剛取了老婆, 很幸福喔~) msn jserv的blog給我, 問我有沒有沒有在blog. 過去, 有時因為工作需要寫教材有時是自己興趣, 斷斷續續的寫了不少東西. 有threading, networking等等, 但最多還是C++. 而以我這有時會掉東掉西的個性, 不令人意外地, 現在還找得到的 - 幾乎是零. 一聽到不來爾的提議, 馬上就覺得這是個好主意. 雖沒blog過, 以看過的blog形式而言 (沒吃過豬肉的人還是看過豬走路D), 應該會適合我這主題寫一點那主題寫一點, 更省得寫過又找不到.

找個免費blog hosting自然是再也簡單不過的事了 (just google). 不想特別花時間比較 (花時間寫東西實在些), 直接上了google本家的blogger註冊. 沒寫過html更別說blog的敝人在下我, 本以為用blogger網頁內嵌的What You See is What You Get排版編輯器打打字就了事了, 沒想到麻煩就此開始...

也許因為blog的是技術性主題, 需要標題, 分段, 條列, 內縮, 顯示源碼等功能. 也許是blogger的排版編輯器與firefox相容性不是特別好, 反正怎麼用就是無法排成我想要的效果, 只好動手hard code寫html. 學習需要的排版功能 (說穿了不過是少數的幾個tag), 並不困難. 麻煩的是既然是syndicated content (其實我那時候還不知道這個詞), 當然不能只用web browser看看就沒事了, 不訂閱試試看那怎行!?

馬上向我心中的新玩意達人, 大衛劉 (反正想到nano, 新手機, 新科技之類的新東西馬上就想到他) 請教. 他條理分明地對我開示 (阿彌陀佛~~), 說明什麼是syndicated content, feed, Atom, RSS, feed aggregator. 一開始我用thunderbird當aggregator訂閱COdE fr3@K, 結果是不行. 因為blogger捨RSS採用Atom (blogger當然用自家力推的規格), 但雷鳥似乎不喜歡Atom (至少1.0.7不支援). 在blogger的support (還是FAQ?) 提到如果使用者就是要用RSS feed, 建議使用FeedBuner. 用FeedBuner把COdE fr3@K轉成RSS格式以被訂閱似乎不是問題, 可是有幾篇blog用雷鳥會有不同問題狀況. 在經過以Feed Validator數小時debug/修正後, 剩下一個blog依然有嚴重的問題, 但我已經沒氣力繼續與thunderbird奮戰了. 接下來在mozilla找到個firefox的extension, Wizz RSS News Reader. 不確定是否為設定問題 (沒力fine tune), Wizz顯示的blog entry不是news feed的樣式, 而是blog entry URL指向網頁的內容, 也就是跟直接看網站的內容沒兩樣 (包括有iframe, side bar, 背景等等).

正打算棄訂閱者看feed的權利於不顧時 (事實上也只有幾隻小貓訂閱, 根本就是自己愛玩), 我沒報太大希望地試著用了兩個給news (nntp, Atom, RSS) 專用的aggregator (Liferea以及aKregator). 意外地, 不論是訂閱Atom feed或是RSS feed, 兩者都能完全正常顯示每一篇blog! 現在雖無法以我對news feeding的粗淺認識來論斷到底問題出在那個環節, 但至少有兩個news aggregator能正常訂閱以及顯示COdE fr3@K. 呼~ 讓我能先鬆一口氣, 暫時逃避這令人頭疼的feeding frenzy.

1/23/2006

C++ Terminology - 2. Instance and Instanciation

第一次聽到instance, 是在某個template的論述上, 用來表示template的具現. Template prgramming, 是具有上位性 (相對於傳統programming) 的programming, 也就是所謂的meta programming. 而instance指的就是該上位性的實現. 假設有一個function template:

    template <class T>
    T max (T lhs, T rhs);
    

如果程式中呼叫了兩次max<>, 一次給的arguemnt型別為char, 另一次為int. 則兩次呼叫的function為同一個function template (i.e. max<>) 所具現出來的兩個template function, 一個為max<char>, 另一個為max<int>.

一個常被template programming初學者誤解的是, function template本身並不是實體, 當然也不能被呼叫, 被呼叫的是它的instance (實體, 具現化的結果), 也就是 template function. 同樣地, class template並不能用以生成物件, 用來生成物件的是class template的instance, 也就是template class. 只是這些instance, 不存在code裡, 而是在compile-time自動被產生.

不論是template class, template function或物件被具現化的動作, 都被稱為instanciation (動詞為instanciate), 而具現化的結果都稱為instance. 若要確切說明其為template的具現, 則用template instanciation. 相對於instance, object則較為狹義, 只代傳統物件.

C++ Terminology - 1. Variety of Types

Fundamental Type

    Aka. built-in type, primitive type, native type and etc.
    C++ core language原生支援型別. 包含pointer, reference以及用const或volatile修飾過的型別 (不包含C++ Standard Library定義的型別!), e.g.:

    • float
    • volatile unsigned int
    • const char*
    • double&

Integral Type

    為fundamental type的subset. 代表整數的fundamental type, e.g.:

    • char
    • unsigned short
    • long

User-defined Type

    Aka. class type.
    使用者自訂型別, 也稱為類或類別. 泛指所有的struct與class, 包含C++ Standard Library定義的型別, e.g.:

      class SomeClass;
      struct SomeStruct;
      template <class, class> class basic_string;
    對C++來說, 在定義user-defined type時, class與struct幾乎是沒有差別且能互相替換 (interchangable). 唯一的差別是預設(默認)的存取權限:
      class DerivedClass : /*private*/ BaseClass
      {
      /*private:*/
          int data;
      };
      struct DerivedStruct : /*public*/ BaseStruct
      {
      /*public:*/
          int data;
      };

POD

    Acronym for Plain Old Data.
    User-defined C-style structure. 為user-defined type的subset, 需符合下列條件:

    1. 沒有user-defined constructor, destructor以及assignment operator
    2. 沒有base class type, 換句話說非derive自user-defined type
    3. 如果有data member, 其所有data member必須為fundamental type或POD
    下兩例皆為POD:
      class SomePodType
      {
      public:
          unsigned int data0;
      };
      struct AnotherPodTypeWithDataMember
      {
          SomePodType data1;
          char data2;
      }; 

Template Class

    也是user-defined type的subset. 為Class template的instance (具現), e.g.:

      typedef list<char> IntList;
    上例中list<>為class template, IntList為template class.

Type

    泛指任何fundamental type或user-defined type.

1/22/2006

Naming Notation - 1. the Hungarian Notation

在open source的世界也好, 在公司內部也好, 任何像樣的project, 大都免不了採用或自訂一套coding convention. 不同coding convention所要達成的目標並不盡相同, 但都有個共同點 - 讓你寫的code看起來像是別人寫的. 主要原因是 - 這樣做應該可以讓他人容易閱讀/理解/修改你寫的code.

Coding convention主要分為兩個部份:

  • Naming notation (命名法)
  • Formatting (程式格式/排版)

以我個人經驗以及從朋友處得到的消息來看, 公司內部最常採用的naming notation是Hungarian Notation (匈牙利命名法). Hungarian notation的歷史我不清楚, 但把它傳播到世界各地, 甚至錯誤地使用在例如C++之類的strong-typed (或是接近strong-typed) 語言上, M$ (危軟) 功不可沒, Win32 SDK與MFC是其中經典之作. 時至今日, 就連M$內部也已展開了反撲, 最好的例子就是.NET丟開M$過去採用hungarian notation的包袱.

痛恨hungarian notation, 但這通常不會造成我在工作上的困擾. 我總是能幸運地說服同事與上司放棄它, 或至少不強迫我採用它. 不過還是常會有朋友跟我抱怨公司強迫他們採用hungarian notation, 他們多是無奈接受. 這帖blog, 就是為了這些朋友寫的, 如果你剛好在這些公司工作, 不妨把這帖blog的link轉給你的同事或上司.

Annoyances of the Hungarian Notation:

  • 視你為弱智. 認為你替變數取的名字大都不好, 很難從名字辨認大約的型別
  • 視你為白痴. 認為你有可能會 - 把一個叫做size的變數 (不是integral type還能是什麼?) 誤判為一個ifstream的instance
  • 視strong-typed compiler (如C++編譯器) 為無能. 認為compiler有可能會 - 在你把一個叫name的變數 (不是某種字串還能是什麼?) 當作ComboBox來操作時, 不產生compile error

我常用的命名法則是盡量口語化, 並試著恰如其分地命名. 舉例說明較快:

  • Instance of integral type
    • unsigned long user_count;
      int offset;
      size_t index, received_bytes;
  • User-defined type
    • class Contact;
      class FastString;
      typedef list<Contact> Contacts; // or ContactList
  • Instance of user-defined type
    • string english_name;
      Contacts kens_contacts; // or contacts_of_ken
      Window main_window;
誤判以上所舉例子型別的人, 或許該考慮換個工作:(.

當然, 上例都是淺顯的例子, 從我個人經驗來說, 應用這原則倒也沒遇過特別困難的狀況. 我想blog的並不是我用的方法多好, 而是希望別再有更多人強迫他人或被他人強迫用什麼彆腳的 dwData, wndMain, ctrlBrowser, nCount, szName來寫C++.