2008年03月25日

關於分割程式功能以及 mix-in 和 include

Tags: php reflection mix-in include
最近碰到一個分割程式功能的問題,不得已必須用到反映的功能,寫了一個簡單的抽象插件類別 http://blog.pixnet.net/HACGIS/post/15612808。 不知道你有沒有更好的解法? tokimeki

關於這個問題,我是用所謂「混成(mix-in)」的概念實踐。先前我寫過2篇: PHP 實踐 mix-in 概念PHP 實踐 mix-in 概念 part 2

另外一位網友是用 include ,參考: mix-in?。嚴格來說那不是 mix-n ,稍後說明。這有3個缺點。


第一,因為 include 會進行檔案開啟動作,當你大量使用這技巧時,將會降低效能。

第二,一個小小的語法缺點,程式外觀不甚雅觀。例如:

當然,這不算什麼大缺點。但從動態性來說,卻可以一眼看出問題。稍後說明。

第三,也是最重要的一點:嚴格來說它不具動態性,不算混成(mix-in)。

混成(mix-in)的特點是「由外而內的重構」。你要混入新方法的程式碼寫在目標類別定義之外。但用 include 時,你要把它 (也就是 'include xxx' 的程式碼) 寫在目標類別定義中。而且不能在運行時變更。

使用混成(mix-in)添加新的行為時,我並不需要回頭修改目標類別的程式碼內容。而是在目標類別以外的地方做這件事。如下例,使用我之前實作的 MixableClass

A.php
others.php

透過混成,我不用回頭修改 A.php 這個源碼的內容,而是在別的地方做這件事。是「由外而內」的重構,所以說是 "mix-in"。


Posted by shirock at 樂多Roodo! │17:59 │回應(6)引用(0)PHP
樂多分類:學術/學習 工具:編輯本文
Ads by Roodo! 

引用URL

http://cgi.blog.roodo.com/trackback/5751881
回應文章
你的mix-in可以把外部的function加入類別內,可問題是,既然已經在外部定義了function,直接調用function不就好了嗎?

我所需要的是「擴充」該類別的功能,換言之,他必須能像繼承一般,可以調用類別內protected的方法(存取屬性的問題不考慮)。

在分割程式功能時,我是把一些不常用的方法移出核心類別,以插件的方式寫在另外一個類別中,藉由我設計的那個「插件」類別把核心與插件類別的非private方法用__call這個魔術方法掛入。

由於我不想手動寫函數表,所以利用反映的方式自動產生該函數表。

我知道那個算是奇技淫巧,不過我實在沒有比較好的方式來作~
Posted by tokimeki at 2008年03月25日 21:04
我在補充一點,我給出的範例,核心類別是「測試」,裡面有一個protected的「測試01」方法,我在插件類別「測試:test02」中的「測試02」方法中有呼叫$this->測試01()。

這樣子為何不會出現錯誤呢?這是因為那個「_插件」類別搞的鬼,他把「測試:test02」和「測試」類別的方法公開給這兩個類別來使用。
Posted by tokimeki at 2008年03月25日 21:23
回應見:

延續討論
Posted by 遊手好閒的石頭成 at 2008年03月27日 13:56
===============================================================

http://lp81sam.spaces.live.com/blog/cns!FE9AB5CD84013FC2!324.entry

------------------------------------------------------------------

...
function __call($name, $args)
{
$file = dirname(__FILE__) . '/module_' . $this.moduleName . '/' . $name . '.php';
if(file_exists($file)) {
return include($file);
}
}
...
------------------------------------------------------------------

------------------------------------------------------------------
現在才看到這篇文章 :p

我覺得要達到「由外而內」的重構效果
只要在__call動手腳就好拉
透過檔案去Mix-in
我寫那篇的時候就這麼想
只是沒說明,我只是在展現原理
其實我沒要跟你爭論這樣的作法是不是Mix-in
因為目前php應該本來就沒有這樣的機制
當然有你說的runkit
我只是要利用php既有的特性
去達到你要的效果
當然作法我覺得是越簡單越好
因為這些問題都是可以從底層就處理的
所以現階段的功能到哪,我就善用它
原則就是"簡單易用powerful少寫code"
當然這樣的代價
就是機器去跑
否則怎麼有哪麼多的動態語言
我想未來應該寫程式應該會變成
用說的
或是用比的
或是用眼睛瞄的吧
這樣才會符合人類的習慣 :-)

===============================================================
Posted by lp81sam at 2008年12月8日 19:45
歹勢
關於上面的回應
因為有部份的程式碼被截掉了
預覽的時候是沒有問題的
所以我把回應貼在這

http://lp81sam.spaces.live.com/blog/cns!FE9AB5CD84013FC2!452.entry

PS:
因為我滿懶的 :p
所以直接就複製貼上
然後也沒有加一些特殊的標籤
Posted by lp81sam at 2008年12月8日 19:53
to lp81sam:

__call() 的解除方案有些缺點。例如效能,它把 __call() 當成行為函數的 gateway ,在小系統中尚可快速回應,但在大系統就會是瓶頸。

另一方面,它是全域性的影嚮,而不能區域性。在 mix-in 的概念中,你可以針對一個類別混入新行為,也可以針對一個實例(instance)混入新行為。但用 __call() 的話,影嚮的是 global 環境,而不是區域性的單一類別或單一實例。
Posted by 遊手好閒的石頭成 at 2009年01月23日 15:47