iT邦幫忙

2

AOP(Aspect-oriented programming)

名詞解釋

Aspect意思為剖面,Oriented意思為導向,所以翻譯為剖面導向程式設計,這意思恐怕很難直接從字面上理解,技術人員就直接用程式來說明吧。

一般我們在寫程式時,很常需要處理譬如錯誤紀錄權限驗證,乃至於額外可能增加使用者查詢歷程等等,就以錯誤紀錄來說,一個方法(Function)要用Nlog進行錯誤紀錄,通常會是這樣子。

public int TestFunction(int num1, int num2)
{
    int result;
    try{
        result = num1 + num2;
    }
    catch (Exception ex){
        var logger = LogManager.GetLogger(invocation.GetType().FullName);
        logger.Error(ex, ex.Message);
    }
    return result;
}

如果系統不大,就那十幾個方法,複製貼上也就解決,但如果是個大系統,幾百個方法要寫的話,勤勞的人也許可以做幾百次複製貼上,但是生性懶惰的我根本不會想這樣蠻幹,而AOP這個架構的誕生,就是基於要減少類似這樣的重工。

架構

畫個圖來看,一般我們寫的方法流程,基本是這個樣子的。

https://ithelp.ithome.com.tw/upload/images/20200116/20116204aCz5FiZzq5.png

舉例,每個方法都有自己的兩個驗證機制以及一個錯誤處理,若是有200個方法的話就要做597次的重工,而改採用AOP的架構的話,驗證機制與錯誤處理只要各寫一次,其他方法只要在方法上或者是Service上加個標籤(Attribute),馬上省掉這597次的重工,而此時方法的流程就會呈現如下。

https://ithelp.ithome.com.tw/upload/images/20200116/20116204YwidNAsuwj.png

這個圖也就是AOP的中心思想,將直向流程的方法,抽離出共用邏輯,再將共通邏輯從側面橫切插入到原本的方法,透過AOP,我們可以達成軟體工程的兩個概念。

  • 關注點分離(Separation of concerns, SOC):分離商業邏輯與共通邏輯,使程式設計師能將更多心力放在主邏輯上,更好的避免錯誤的發生。
  • 開放封閉原則(Open–closed principle, OCP):OCP是這樣解釋的,對於擴展是開放的,對於修改是封閉的,當套用AOP概念後,如果要對方法加入更多驗證,或是更多雜七雜八的機制,我們都可以透過AOP,完成後掛載在方法之上,這就是對擴展的開放,但相對的我們並不會修改到主邏輯本身,這也應證了對修改是封閉的。

如何實作

如果是.Net MVC專案的話,在Controller上可以透過ActionFilter這個標籤來完成AOP的功能,但無法套用在普通的方法上,目前也沒有Nuget套件可以直接拿來用,要實作的話,可以用Autofac.Extras.DynamicProxyIntercept(攔截)標籤,但是要額外加工,並且自訂Interceptor(攔截器)的內容,攔截,顧名思義就是在方法執行的時候,先把方法暫停一下,可以取得他傳入的參數以及回傳值的類型,而攔截器定義的內容就是你要為方法進行甚麼樣的處理,例如錯誤紀錄。

使用Autofac的Intercept,在interface或service class上加上這樣的標籤,而方法內容只要專注於商業邏輯就好,如下。

using Autofac.Extras.DynamicProxy;

//例外處理的AOP標籤
[Intercept(typeof(ExceptionLogInterceptor))]
public class Service
{
    public int TestFunction(int num1, int num2)
    {
        return num1 + num2;
    }
}

ExceptionLogInterceptor,就是自訂的Interceptor(攔截器),以這個例子來說,這個Interceptor是我用來處理錯誤紀錄的,如此一來,這個Service的方法都可以處理錯誤紀錄。

要使用Autofac.Extras.DynamicProxy記得也要裝Autofac(DI Container)更詳細的實作方法,在接下來的系列文章當中會有更加詳細的說明,請原諒我在這邊賣個關子,敬請期待。

總結

使用AOP架構好處多多,減少重工又可以讓你的程式碼更加簡單易懂,因為共用的邏輯抽離之後,就只需要專注於商業邏輯的撰寫,只是對於C#新手來說,可能門檻比較高,不過整體來說,專案若是套用了AOP架構後,整個大升級,不管幾百幾千的方法,如果要加上一堆共用基制的話,都不用怕啦,人擋殺人,佛擋殺佛,不好意思有點激動:D

後記

  • 這邊文章比較少講到一些AOP專業術語或者是更詳細的原理,是基於我個人對AOP的認識,來與大家分享,請各位鞭小力一點 :P
  • 好像一直講到抽離共用邏輯,專注於商業邏輯,不過因為真的很重要,多提幾次應該也無妨(?)

參考資源

AOP 觀念與術語
Autofac
Autofac.Extras.DynamicProxy


1 則留言

1
WadeHuang
iT邦新手 5 級 ‧ 2020-01-17 17:23:43

AOP 是不是也開放封閉原則的另一種實現呢?

之前查 AOP 的文章,範例的使用場景都是利用 AOP 來做「權限驗證、資料驗證、紀錄 Logger」。
好奇大大在實踐經驗中,會不會利用 AOP 來擴充商業邏輯呢(如:撈取 UI 所需資料)?

嗨,首先感謝你的回覆

我認為AOP也是OCP的另一種實現,例如我想修改錯誤處理的一些邏輯,只要在AOP架構中修改,而不用去改到原本的Function。

至於目前實踐的專案當中,還是先處理一些老問題(錯誤紀錄、資料驗證等),有部分客戶是有特殊需求,例如要記錄資料增刪改查的動作,但按照你所建議的,撈取UI所需資料,也許我可以透過AOP所攔截到的回傳類型與參數等資源,來回傳所需要的資料,或者傳入一段SQL語法,其他的讓AOP去解決,感謝你的建議 :D

我要留言

立即登入留言