Aspect-Oriented Programming

因為近來用 Spring 的緣故,順道也接觸了一點關於 (觀點導向編程) 的知識。

傳統 OOP,就拿 MVC 這套 pattern 來說吧–例如我們要建立一個留言板的話,Controller 的結構大概是這樣的:

class MsgBoard implements Controller {
private void post(name, title, content) {
Validator.isSpam(getIP());
Validator.sanityCheck(name);
Validator.sanityCheck(title);
Validator.sanityCheck(content);
Post p = new Post(name, title, content);
post_id = DB.store(p);
Logger.log(getIP(), post_id);
displayView('result');
}
private void reply(post_id, name, title, content) {
Validator.isSpam(getIP());
if (!DB.exists(post_id)) displayError();
Validator.sanityCheck(name);
Validator.sanityCheck(title);
Validator.sanityCheck(content);
Post p = new Post(post_id, name, title, content);
reply_id = DB.store(p);
Logger.log(getIP(), reply_id);
displayView('result');
}
void handleRequest() {
if (IS_POST) post();
if (IS_REPLY) reply();
}
...
}

以上的結構,有兩個問題:

  1. 程式碼混亂
    一件簡單的動作,因為不同方面的要求(例如怕留言者破壞皮面而檢查留言有沒有不合規的 HTML tag,檢查來源是不是垃圾郵件黑名單,IP 記錄等等)而使程式碼穿插多個不相關的模組/類別,修改上來得穿插多個不同模組逐個修改,費時得很。
  2. 程式結構鬆散
    同時是 post,reply,性質上不太相近但卻要進行多項同類的檢查和記錄,但又不是完全相同可以簡單到用一個程序包著(例如 post() 不用檢查原post的存在),修改某部份之時很可能會忽略其餘地方而造成錯誤,難以維護。

於是研究人員向「分離不同關注點」這個方向下手,AOP 是。AOP 的規劃可以分為三個部份,包括「觀點分離」(Aspectual Decomposition),「關連實作」(Concern Implementation) 和「觀點重組」(Aspectual Recomposition)。

譬如上述例子,真正的工作是把新文章儲存到資料庫裏去,其他檢查,記錄等等分散在不同程序,位於外部的附加工作,在 AOP 的世界裏被稱之為橫切關注點 (cross-cutting concern)。為了有效可以管理這堆散漫在程式結構裏的步驟,便有了觀點 (Aspect) 這個容器。每一個 Aspect 可以對某個工作的不同階段(AOP 稱之為 Pointcut)附上不同的關注點工作。例如:

public aspect storePost {
pointcut sanityCheck(name, title, content) : call (Post.new(name, title, content)) && args(name, title, content) {
if (Validator.sanityCheck(name) && Validator.sanityCheck(title) && Validator.sanityCheck(content)) proceed(p);
}
pointcut log(*) : call (* DB.store(Post p)) && args(*) {
Logger.log(getIP(), *);
}
}

每一個觀點限定了在程式執行到某一個pointcut 的時候(例如某個封包裏某個方法被執行,又或是某個類別的實體被當作傳回值),定義的 pointcut (可以當作執行條件) 內容便會被執行。諸如上面,每當 Post (文章)物件的建構子被呼叫的時候,便會先執行 Validator.sanityCheck()檢查每項參數,通過才可以繼續。資料庫儲存部份亦一樣(我不太跟語法了),每當儲存指令被執行的時候(無論是甚麼地方也好),Logger 便會將一切記錄在案。

AOP 可以簡化程式的邏輯,達到不用修改源程式碼而添加功能。不但如此,AOP 也可透過設立不同的 point cut 來限制條件(Design by Contract),而限制程式碼不會跟真正工作的程式碼糾纏在一起。

我們且看看 AOP 會否流行起來吧。

延伸閱讀:
Javaworld: I want my AOP!
AspectJ – Java AOP Implementation
Wikipedia – Aspect-Oriented Programming – Implementations on various languages

2 thoughts on “Aspect-Oriented Programming

  1. 我覺得 AOP 的強項在於可以透過添加 aspect 和 pointcut,不用修改原程式碼也可以添加程式功能。朝這個方向想想,應用不少。例如可以把快取的程式碼(在載入資源時,先檢查記憶體)寫到 Aspect 裏,那麼就不用修改原先的程式碼(讓程式主要部份看起來更簡潔),一舉兩得。
    不過可以推想將來的 anti-pattern 會是一大堆 code 寫到 aspect 裏,讓人難以追查 = =

Leave a Reply

Your email address will not be published. Required fields are marked *