框架,與物件導向程式設計。

最近分析Codeigniter框架的原始碼,開始思考一件事情:

一個框架的各個元件,是否應該要盡量能夠獨立於框架之外?

有人認為,框架的元件本來就附屬於框架之下,不需要也不應該獨立於框架之外使用。

我個人認為,只要是類別就應該盡量降低相依性,這樣重用性、擴充性、可讀性才高。

開始討論這個問題之前,我想先引用某位PHP programmer的一段話:

「所有框架都很爛!」(They All suck!)

http://www.phpclasses.org/blog/post/226-4-Reasons-Why-All-PHP-Frameworks-Suck.html

主要理由如下:

  • 同樣的code非必要地不斷重複執行
  • 需要太多相依的類別
  • 非必要的複雜解法
  • 重複做了伺服器提供的功能

他點出了框架的幾個缺陷。

我認為期待各元件能彼此獨立很好、不期待各元件能彼此獨立也沒錯。這似乎是一個個人喜好的問題,而沒有對錯之分。

下面是我認為正方以及反方的論點。

為什麼框架的元件應該可以搬出框架之外使用?

我認為,如果框架底下的元件相依性很低,那麼當開發者只喜歡其中幾個功能、而不喜歡整個框架的時候,便可以把元件搬到外面,另外拼裝或是手刻一個自用的framework。

若是框架能夠做到這樣,則上述PHP programmer的四項批評便幾乎不再是問題。

反之,像CI這種core功能嚴重相依的框架,則只能選擇全盤接受、或是不使用CI。

另外,也可以理解為某個功能在PHP的世界被創造過,你不應該重新創造、也不應該創造不能被重新使用的類別。這不正是物件導向程式設計的一個重點嗎?

為什麼框架的元件不應該搬出框架之外使用?

框架本身就代表了底下的眾多「元件」,以及某一種「使用這些元件的方式」。

以CI來說,許多元件使用了全域函數去讀取類別(load_class函數)、讀取config值(config_item函數)、記錄log訊息(log_message函數)、計算執行時間(benchmark類別),等等。

CI的元件本來就預設在CI之下使用,所以這樣設計確實很方便。否則為了能讓元件搬出去使用,要加上一大堆dependency injection技法、一堆地方要寫得比較general、彈性,也是麻煩。

話說如此,某些程度還是能同時兼顧所有優點的。例如Laravel的Eloquent ORM,在框架之內很優秀,搬出去用依然出色。

關於我對CI架構的批評,可參考:

http://howtomakeaturn.github.io/ci/common.html

http://howtomakeaturn.github.io/ci/output.html

(Photo via Akira ASKR, CC licensed)