Software entities such as class, modules, functions should be open for extension, but closed for modification.

直接英翻中就是「對擴展開放,對修改關閉。」

換句話說,允許擴展但不允許修改原有的 code。在現有程式運作得好好、通過測試的狀況下,應該以擴展的方式新增系統功能,而非修改原有的 code。OCP 著重於軟體彈性,遵守這原則能在增加新功能時確保原本行為不會被更動,減少在原本運作良好的部分產生 bug 的風險。不過遵循 OCP 可能會引入新的抽象層、增加 code 的複雜度,所以並不是整個系統所有地方都該遵守,而是找出最有可能改變的地方才使用 OCP,沒必要的地方使用也是種浪費。

OCP 是設計層次上的原則。

舉個例子:較 high level 的 class 應該以 interface 使用較 low level 的 class,而非直接使用 low level 的 class。如此需要支援其他種 low level 實作時,便能直接實作 interface 並修改產生 instance 的地方,即可做到「不修改原本 high level 的 code,而能擴充 low level 實作」。

另外像瀏覽器的 plugin、Linux kernel 的 module(即使 C 語言不是所謂的物件導向語言,依然能以物件導向的概念撰寫)同樣都運用了 OCP。

原本想說既然在 Windows 上開發,用 Visual Studio 好了,但打開網站看到價格,呃,我還是繼續用 Eclipse 跟 Qt Creator 吧!謎版?找謎版的時間我都可以處理好了…

Install Windows SDK

安裝 Windows 7 的。

Microsoft Windows SDK for Windows 7 and .NET Framework 4

Troubleshooting

裝 Windows SDK 失敗,像這篇的狀況。移掉 Microsoft Visual C++ 2010 redistributable packages 後再裝 Windows SDK 就可以了。

compile 時遇到 error C2059: syntax error : 'constant'patch

Eclipse

Install CDT Visual C++ Support

在 Eclipse 裝 CDT Visual C++ Support,才有 Visual C++ tool chain。我的 Eclipse 是 Juno。

CDT site:http://download.eclipse.org/tools/cdt/releases/juno

Configuration

Project property

C/C++ Build -> Tool Chain Editor 的 toolchain 設為 Microsoft Visual C++。

C/C++ Build -> Environment 增加 PATH C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin,這樣才找得到 Visual C++ compiler。

C/C++ General -> Paths and Symbols -> Includes -> GNU C++

Eclipse Configuration

Qt Creator

因為想到要有 GUI 介面,所以需要 Qt + Windows SDK,但現在 Eclipse 跟 Qt 的整合不太好,改用 Qt Creator + Windows SDK。

直接裝 Qt 5.3.1 for Windows 32-bit (VS 2010, OpenGL, 537 MB)

Kits

如果已經先裝其他版本的 Qt,應該可以在選項裡加 Kit:

Qt Creator Windows SDK Kits

pro setting

INCLUDEPATH 要加 Windows SDK 的路徑,如 Eclipse Configuration 圖中的路徑。

Troubleshooting

compile 時遇到 LINK : fatal error LNK1123: failure during conversion to COFF: file invalid or corrupt 的錯誤。

Solution:http://qt-project.org/wiki/Category:Tools::msvc

應將 member data 宣告為 private,以 public member function 存取 member data。如此可透過 member function 做細微的 access control,例如以只有 get function 沒有 set function 實作 read-only 的性質。

將 member data 宣告為 private 也提升它的封裝性。一個元件的封裝性跟其內容改變時需修改的 code 量成反比,需修改的 code 越多表示封裝性越低。例如修改一 member data 的名稱時,需要檢查所有 code?還是繼承架構中的 code?還是該 class 的 code?

要注意在 class 提供外界使用並可供繼承時(如 framework、library 的 class),protected 不比 public 來得更有封裝性,兩者幾乎不相上下。雖然 protected member data 的使用範圍僅限於繼承體系,但由於公開給他人使用,使用該 member 的 code 數量跟直接 public 給他人使用沒什麼區別。(就是都很多啦!)

Ref

  • 《Effective C++》item 22 Declare data members private

前置作業

安裝 Node.js

1
2
3
4
$ git clone https://github.com/hexojs/hexo
$ cd hexo
$ npm install
$ git submodule update --init

npm install 應該是為了把需要的 node module 裝起來。

修改後直接 run bin/hexo 即可。

改以 updated 排序 post

http://goo.gl/63S6ui 的,可從 _config.yml 設定 post 以 date 或 updated 排序。如果 post 沒有設 updated,updated 時間會等於 date。

https://github.com/cjwind/Hexx/commit/f72a82107b4f325a4dfe23641aac78533a499bae
https://github.com/cjwind/Hexx/commit/d115baf9e2d516684d637d79d22f0177129daa0b

耍蠢所以變成兩個 commit

Ref

簡單記錄一下。

我把 node_modules/scaffolds/source/themes/_config.ymlpackage.json 放到 bitbucket 的 private git repository,另一台電腦裝 node.js 跟 hexo,clone repository 下來就可以了。

原本順利弄完也就好了,我就手賤的做了 npm update -g 更新 hexo,然後 generate 就爛了。後來約莫是 hexo init .npm install,然後 merge 一些改過的 theme 檔案跟 config,才總算好了。

技術 blog 沒有搜尋挺麻煩的,儘管有設 tag,但還是搜尋最方便。之前在 Octopress 用的 Tapir 不支援中文,看起來沒什麼解,只好另尋新歡(?)。找到 Swiftype 這套,除了基本搜尋功能外,Swiftype 還提供調整搜尋結果、統計分析等功能。

註冊、輸入 URL,它處理完後到 INSTALL 頁面 copy source code 到 theme 中相應 call search_form() 的地方。每個 theme 的位置不太一樣,nut 在 layout/_widget/search.ejs,landscape 在 layout/_partial/header.ejs

發現一個問題:在 overlay 的顯示方式下,搜尋結果的頁面太長,scroll bar 無法捲到最下面。想改成結果直接顯示在頁面,不用 overlay,之後參考這裡看怎麼改。

沒進,只對 A,不過這是我第一次 R1 破蛋……2013 年掛蛋,2011 年也是,其他年份沒參加。

一整個亂……= =

考慮過從最遠古的祖先直接建表,但想想覺得應該不行。就變成往回推的判斷:

  1. 若 Q 是奇數,則 impossible。
  2. Q / P = x (x 為整數) = 2 ^ n,則 ans = n
  3. Q' = Q / 2 直到 Q' < P(記錄除的次數 n),P' = P - Q',recursive 檢查 P'/Q' 是否可能出現。是則 ans = n,否則 impossible。

既然有 code 可以檢討還是檢討一下好了。

  1. 看看那精美的 scanf(),又一次 C++ format input/output 不熟。
  2. 邏輯上有方向但細節沒想清楚,像 Q 一直除 2 的時候原本沒先檢查是不是能整除,原本也沒處理處理特殊值 1。
  3. 大測資一開始沒用 long long int,然後就 segementation fault 了。

屬於 Creational pattern。

確保 class 只有一個 instance,並且給它 global 的存取點。

可以做到延後產生 instance,也就是真正使用到時才 create instance。如果用 global variable,依據不同語言及實作的特性可能在程式一開始就產生 instance。

常用來管理 shared resource。

做法

  • 將 constructor、copy constructor、destructor、assignment operator 宣告為 private 確保外面無法產生第二個 instance 及 destory instance。
  • 使用 static function 讓外界取得唯一的 instance。

C++ 實作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Singleton
{
public:
static Singleton* GetSingleton();

private:
Singleton() { /* implement */ };
~Singleton();
Singleton(const Singleton&);
Singleton& operator=(const Singleton&);
};

Singleton* Singleton::GetSingleton()
{
static Singleton* pSingleton = new Singleton();
return pSingleton;
}

外面要取得 instance 時 call Singleton::GetSingleton()。這邊直接用 C++ 的 static local variable 在 function 第一次 call 時會 initialize 之後不會再 initialize 的特性,而它的 lifetime 會持續到程式結束。

有另一種做法是 GetSingleton() 不 return pointer,而 return reference。

這個實作沒有 thread-safe,有多個 thread 會 call GetSingleton() 就 GG 了。要 thread-safe 可以用 double-checked locking。

Ref

簡單來說,我變心了。

Octopress 隨著文章數越多 rake generate 似乎有越來越慢的趨勢,稍微查一下發現雖然有 generate 加速的方法,但遇到 deploy 還是會慢,索性跳到比較快的 Hexo。

Hexo 也可以配合 Github page 使用。跟 Octopress 的不同的是 Hexo 把 post 跟 draft 分開,還不錯。

從 Octopress 轉到 Hexo 不難,先安裝好 Hexo,再將原本 _posts/ 底下的檔案搬過來便是。Hexo 不像 Octopress 將 source 開成另一個 branch 可以 push 到 repos 上,為了備份跟遠端傳輸 source 檔,我把整個 Hexo 資料夾放在 Dropbox 上。理論上電腦有裝 node.js 跟 Git 的環境就可以直接寫。

偶爾改爛 theme,放在 Dropbox 上就不知道自己改了什麼、改不回去,試驗開另一個 repos 放 source。

新增頁面

1
$ hexo new page <name>

在導覽列加新的頁面要修改 themes/<theme name>/_config.yml,在 menu 底下加,例如:

1
2
3
4
5
menu:
Home: /
Archives: /archives
Toy: /toy
About: /about

這個設定因 theme 而異,以上設定是 default theme landscape 的。

Custom Domain Name

source/ 底下增加一檔案 CNAME,內容為自訂 domain name,如 www.cjwind.idv.tw

Theme

改用 nut

修改 Deploy git repos

除了修改 _config.ymldeployrepo 的設定外,也要刪除 .deploy/,才會套用新的 repos 設定。

Ref

發現兩個問題:Tapir 不支援中文、換過 permalink 會怪怪的。

2014/4/28 updated


Octopress 預設的 search 功能是 Google search,一搜尋就會導到 Google 的頁面。不太喜歡這種方式,把 search 換成 Tapir,可以在自己站內找。

Tapir 的原理是它每 15 分鐘會掃一次網站的 RSS,再透過他們的 API 達到以 RSS 為 base 的搜尋功能。要注意的是,沒在 RSS 中的文章是不會被 search 到的。

修改方式

先到 Tapir 輸入 RSS feed 跟 mail,會得到一組 key,這裡只需要用到 public key。

Octopress Tapir plugin 下載所需檔案並放到對應資料夾。

  • source/search.html
  • source/javascripts/jquery_tapir.js
  • source/images/loading.gif

修改 _config.yml

  • 註解掉 simple_search
  • 加入 tapir_token: [your public key from Tapir]

修改 source/_includes/navigation.html,在 include custom/navigation.html 前面加入:

{% if site.tapir_token %}
{% endif %}

修改 source/atom.xml,拿掉 for post in site.posts limit: 20limit: 20,讓所有 post 都會出現在 RSS feed 。另一個可能的做法是複製 source/atom.xmlsource/atomForSearch.xmlrake generate 後將這個 XML 的 URL 丟給 Tapir 當作 search 的 base。

Ref