談談應用層切面設計

AOP概要理解糾偏

說到AOP,這個東東如今已經不是一個新詞彙了,咱們拿一下百度詞條來看看是下面的樣子的: html

在軟件業,AOP爲Aspect Oriented Programming的縮寫,意爲:面向切面編程,經過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術。AOP是OOP的延續,是軟件開發中的一個熱點,也是Spring框架中的一個重要內容,是函數式編程的一種衍生範型。利用AOP能夠對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度下降,提升程序的可重用性,同時提升了開發的效率。

可是今天我要說,這個定義太過狹義,實際上AOP的概念要比上面的定義要寬泛得多,今天我就給你們來扯扯AOP的事兒。

從AOP這三個單詞來看,它的定義仍是很是準確的,就是面向切面編程。可是後面的這一堆解釋: java

經過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術。AOP是OOP的延續,是軟件開發中的一個熱點,也是Spring框架中的一個重要內容,是函數式編程的一種衍生範型。利用AOP能夠對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度下降,提升程序的可重用性,同時提升了開發的效率。

這明顯是鬼扯了,明顯是把一種具體的實現做爲它定義,這就有點「白馬即馬」的意思了。

主要的變化就是把中間一段與具體的實現有關係的部分去掉。 編程

經過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術。AOP是OOP的延續,是軟件開發中的一個熱點,也是Spring框架中的一個重要內容,是函數式編程的一種衍生範型。

這一段太過狹隘,已經遠遠不能知足軟件技術發展的須要了,面向切面就面向切面,與什麼預編譯的方式有毛關係?與運行期代理有毛關係?與Spring、函數式編程有毛關係? 緩存

所以,今天悠然就把AOP的概念從新縷縷: 性能優化

在軟件業,AOP爲Aspect Oriented Programming的縮寫,意爲:面向切面編程,經過對某一領域進行高內聚低偶合方式進行實現,並經過非偶合的方式與其它業務邏輯進行整合,以對不一樣切面的實現邏輯進行隔離,從而使得不一樣領域的實現邏輯之間的耦合度下降,提升程序的可重用性、提升開發效率,同時也大大下降集成與整合難度的一種編程方法。

嗯嗯,雖然不必定嚴謹,可是比原來的普遍多了,也更能體現AOP的真正意涵。它不只包含原有定義裏的模式,還包含各類各樣其它AOP模式,今天悠然就來給你們試着闡述一下。

AOP在軟件編程中的應用場景

傳統意義上的AOP

傳統意義上的AOP,是針對業務處理過程當中的切面進行提取,它所面對的是處理過程當中的某個步驟或階段,來得到邏輯過程當中各部分之間低耦合性的一些隔離效率,好比:常見的應用場景有: 架構

  1. Authentication 權限
  2. Caching緩存
  3. Context passing內容傳遞
  4. Error handling 錯誤處理
  5. Lazy loading 延時加載
  6. Debugging 調試
  7. logging, tracing, profiling and monitoring 記錄跟蹤 優化 校準
  8. Performance optimization性能優化
  9. Persistence 持久化
  10. Resource pooling資源池
  11. Synchronization 同步
  12. Transactions事務
  13. 全文索引
  14. 等等

確實,AOP的應用場景有許多許多,也取得了良好的應用效果,這個已經通過了充分的實踐,許多書裏也都進行了充分的闡述,這裏再也不贅述。 框架

非傳統意義上的AOP

嗯嗯,今天的重點是這裏,別人說得好的地方悠然說不過,所以最好的辦法就是不說,悠然說別人不說的地方,這樣就壓力小多了:) 模塊化

如下針對@紅薯 的猜想純屬臆斷,若有雷同純屬巧合: 函數式編程

在正式開始以前,咱們來舉個實踐場景: 函數

@紅薯 的開源中國博客1.0

話說,在開源中國的博客列表中,每一篇博客是像下面同樣展現的:

從這一塊內容中,咱們能夠看到以下內容:

  1. 原創的圖標
  2. 置頂的圖標
  3. 博客的標題
  4. 博客的分類
  5. 博客的統計信息30評、2594閱、7贊
  6. 博客的編輯、刪除

咱們從看到的這些信息裏面,能夠猜一下@紅薯 的表結果是怎麼設計的:

表BLOG結構:

  • 博客標識
  • 博客標題
  • 博客標題內容
  • 是否原創
  • 是否置頂
  • 評論次數
  • 閱讀次數
  • 獲贊次數
  • ....

固然這裏應該也有一些其餘的字段,咱們上面的圖片裏看不到,咱們就當它們不存在。

咱們再想一想,估計@紅薯 還有詳細的記錄,好比:誰評論的,評論的內容是什麼?誰閱讀的,是何時閱讀的?誰點讚的,是何時點讚的

因而就有了下面的表:

    評論詳情:

  • 博客標識
  • 評論者
  • 評論時間
  • 評論內容
  • ...

    閱讀詳情:

  • 博客標識
  • 閱讀者
  • 閱讀時間

    點贊詳情:

  • 博客標識
  • 點贊者
  • 點贊時間

嗯嗯,@紅薯 仔細想了一想感受差很少了的樣子,這個時候@紅薯 縷着他的頭髮,點上一支菸進入了寫代碼的酸爽狀態。

好比,功能是這樣寫的:

//博客點贊

保存點贊(博客標識,點贊者標識){
    博客biz.添加點贊(博客標識,點贊者標識);
}

class 博客biz{
     添加點贊(博客標識,點贊者標識){
          博客dao.增長點贊數(博客標識);
          點贊詳情dao.增長點贊詳情(博客標識,點贊者標識);
     }
}

伴隨着一陣陣歡快的噼裏啪啦鍵盤聲,開源中國博客1.0 OK了。

@紅薯 的開源中國新聞1.0

看着開源中國博客1.0的穩步運行,PV+UV雙豐收,@紅薯 縷着頭髮咧着大板牙笑開了花,那就再整個開源中國新聞1.0唄!

因而紅薯開始設計表結構:

表NEWS結構:

  • 新聞標識
  • 新聞標題
  • 新聞標題內容
  • 是否置頂
  • 評論次數
  • 閱讀次數
  • 獲贊次數
  • ....

固然,考慮到新聞也有點贊,也有評語,也有閱讀,因而下面的表結構也是須要的:

    評論詳情:

  • 新聞標識
  • 評論者
  • 評論時間
  • 評論內容
  • ...

    閱讀詳情:

  • 新聞標識
  • 閱讀者
  • 閱讀時間

    點贊詳情:

  • 新聞標識
  • 點贊者
  • 點贊時間

嗯嗯,紅薯看了下,尼瑪除了少個原創,別的都差很少的樣子麼,可是不同仍是不同的,那就再作一遍吧,因而一陣陣噼裏啪啦以後又搞定了,紅薯抹着汗水,再仔細看一下代碼,尼瑪,怎麼這兩邊的代碼幾乎同樣?感受哪裏有些不對的樣子。

管呢,先運行起來再說,哥去泡個妹子放鬆一下,因而紅薯打開了MAC,IPAD,IPHONE7S....

初級AOP方式

運行了一段時間,紅薯以爲要加個動態功能,發現要在兩邊都增長代碼,愈來愈以爲不對勁,因而拿起新買的《企業級JavaEE架構實踐》翻看起來,唉當時看書的時候不仔細,這個用切面來解決不是挺好的?

因而紅薯把表結構重構了一下:

    評論詳情:

  • 評論類型
  • 評論對象標識
  • 評論者
  • 評論時間
  • 評論內容
  • ...

    閱讀詳情:

  • 閱讀類型
  • 閱讀對象標識
  • 閱讀者
  • 閱讀時間

    點贊詳情:

  • 點贊類型
  • 點贊對象標識
  • 點贊者
  • 點贊時間

另外增長一個動態表

  • 動態類型
  • 動態對象標識
  • 動態者
  • 動態時間
因而紅薯把原來的代碼重構了一下,把原來重複作了兩遍的的評論、閱讀、點贊都抽到了一個裏面,而後把原來在業務代碼裏調用相關評論、閱讀、點讚的業務邏輯都抽到了切面當中。嗯嗯,紅薯感受棒極了,腦海中又出現了妹子的身影,對了,IPHONE8P哪裏去了?

高級AOP方式

自從引入了切面功能,紅薯的工做明顯輕鬆多了,可是惟一不爽的是 隨着開源中國的用戶愈來愈多,投資人要求功能方面也要快速推動,如今的紅薯幾乎已經沒有能夠縷的頭髮了,投資人要增長日曆、要增長勳章、要增長TAG、要增長提醒,要增長的東西愈來愈多,同時開源中國的訪問者們的眼界又愈來愈寬了,要求愈來愈高了,今天這個作的醜了,明天那個作得不人性化了, 紅薯開發、測試、發佈、切面配置、界面調整、控制層啥都要作,這不又出問題了:


紅薯的手習慣的擡起來縷頭髮了,可是隨着OSC功能的增長,頭髮已經幾乎找不到了,紅薯狠的把菸屁股擰進菸灰缸,是要完全解決這個問題了,看起來還得讀書啊,再翻企業級JavaEE架構實踐,看看有沒有啥思路。

Think Big, Start small , Scale Fast.

這是什麼鬼?
好的軟件是品出來的。
品個屁,如今解決問題纔是正點,能不能讓我不要每次都改這麼多東西?再翻翻目錄,看看有啥值得研究的?

仔細看了幾遍,紅薯的眼睛突然亮了起來,只要把全部的評論、點贊、評論、動態、以及其它雜7雜8的東西都讓它高內聚,低耦合,我作博客只管作博客、作新聞只管作新聞,哪怕再作他多少個,也是僅僅關注我要作的東西,而把這些東西都作成一個個的切面讓這些切面去完整的解決這些問題,這樣我不就輕鬆了?原來雖然也引入了AOP技術,可是因爲只是初級切面,因此只解決了部分問題,並無完全的解決問題。若是我能把切面也切到控制層、界面層,這樣就能夠真正的作到高內聚、鬆耦合,並且是真正的業務切面。

技術的切面仍是初級的,業務層級的切面纔是終級的。

具體實現起來,仍是沒有什麼思路,聽聽悠然有沒有什麼思路?

終級解決方案

經過上面對開源中國兩個功能模塊的分析,咱們大體清楚了問題的癥結所在,並經過對紅薯的心路歷程進行分析,大體引入了問題的解決思路,可是真正的落地卻不是那麼簡單的。一個問題的抽象的程度越高,其通用性越好,可是它的易理解程度和易實現程度也就越難。我對實現者面對面屢次溝通這個思路時,更多的時候看到的是他們茫然的眼神,以及屢次感受理解了,可是真正實現的時候卻又達不到要求,直到許屢次反覆以後,才慢慢進入狀態。

因此我會盡力講清楚,可是不能保證你必定能理解到我心裏所想。

要解決的問題

咱們在應用開發過程當中,一部分是與具體的業務相關的,另一部分它與具體的業務並不相關,可是在業務過程當中又是有這樣那樣關係的。若是咱們能把這些與具體業務沒有直接關係,但又是對業務數據的一種維度的補充或描述能獨立出來,想用或不想用僅在一念間,那麼這個時候作軟件就是一種享受了,並且業務和切面均可以獨立變化,而沒必要考慮彼此的影響。

這個時候從開發效率來講,因爲你們各自高內聚低耦合,因此開發、測試、驗證、發佈都會方便快速許多,集成的時候因爲也沒必要有配置和代碼及界面上的協做和引用,這樣就能夠大大的下降系統集成過程當中的開發、測試工做,也避免了由此致使的一系列的可能出現的問題。

那麼接下來,咱們就用上面分析問題時的例子來闡述,如何解決這個問題,整個實現思路採用Tiny框架相關技術進行解決,非TINY技術平臺或框架也是能夠實現的,固然實現細節可能會有不一樣,須要相關的架構師進行相應的調整。

解決問題的思路

每一個切面的內容都在本身的業務單元中實現,同時要能在能出來的時候它就能出來。

這裏咱們就拿上面說的一個場景"評論"來示例

   評論詳情:

  • 評論類型
  • 評論對象標識
  • 評論者
  • 評論時間
  • 評論內容
圍繞着這個,當能夠能夠知道它的DAO層代碼怎麼寫,邏輯層代碼怎麼寫(若是是SOA體系還有服務層代碼怎麼寫),最後還有就是界面層的部分。

既然是高內聚低耦合,那固然主是要統一界面的樣式。

評價的使用場景通常來講是在顯示完主要業務內容以後(如:博客、新聞、文檔、軟件、etc),能夠進行評論,能夠進行回覆,能夠進行引入,固然也要能把已經評論的內容顯示出來。

可是須要搞清楚的是,這些內容的展示與人機交互過程明顯與不一樣的業務內容沒有一點關係,這也就爲進行切面提供了基礎。爲了便於進行說明問題,這裏採用AJAX模式進行解釋,雖然採用非AJAX方式也是能夠解釋得通的,可是應用到的技術的複雜度與解釋起來的困難都很是更加複雜。

舉個例子,作出來的效果是相似下面的樣子:

這個時候,問題就轉換爲,如何把當前要處理的業務類型和業務數據的標識讓評論部分知曉,這個也很是簡單,只要用下面的樣子寫一段模板便可:

#comment("BLOG",blog.blogId)
上面的模板語言是指:如今我是在給一個BLOG類型的業務對象作評論,業務對象的標識是blog對象的blogId屬性。

嗯嗯,這個時候較之前的開發,已經省了很是大的工做量了,只是簡單的聲明一下就能夠了。

更進一步的思考

雖然上面的思路已經比較好的解決了問題,可是這裏有一個問題:那就是實現時序問題。

也就是說,博客功能是紅薯先加的,而評論功能是紅薯後加的。這裏就出現一個問題:爲何後增長的功能,須要我在已經實現的妥妥的功能要進行調整??這豈不是說,你後面不斷的增長功能,我這裏都要不斷的進行聲明?雖然也有必定的道理,可是是不符合好萊塢原則的。實際上也是違反常理的===我是先來的,爲何要爲你一個後到的作調整?我根本就不知道你的存在好麼?!

出於咱們對完美架構的追求之前咱們不將就的態度,咱們固然要更好的解決此問題。

咱們能夠在應用當中預設一些擴展點,可是具體擴展些什麼東西我是無論的。

這個時候,咱們就能夠只在界面中增長以下的一段模板語言:

#extendPoint("VIEW","BLOG",blog.blogId)

上面的腳本表示,我這裏是一個VIEW類型的擴展點,業務類型是BLOG,業務對象標識是blog對象的blogId屬性。

而後由extendPoint決定往裏面塞哪些東西。

這個時候,我只要在評論工程裏增長以下的配置:

<extend-points>
    <extend-point type="page" order="10">
        #comment(bizType,bizId)
    </extend-point>
</extend-points>
而後若是這個時候,咱們又要增長一個留腳印的功能

咱們只要增長一個留腳本的功能模塊,在這個模塊中增長下面的配置:

<extend-points>
    <extend-point type="page" order="9">
        #footprint(bizType,bizId)
    </extend-point>
</extend-points>

總結

經過上面的改進,紅薯同窗不再用薅頭髮了,原有的業務代碼不再用動,這功能竟然自動在全部功能中自動出現了。

想到這裏,悠然就深深的自責,早點給紅薯出主意,紅薯同窗的一頭黑髮就留下來了。

固然,上面只是說了一個思想,真正的實現的時候用到的技術仍是很是多的:
  • 模塊化
  • AOP
  • SOA(若是是互聯網應用是須要的,普通的小工程能夠不用)
  • 模板語言或相似技術

若是本人沒有說清楚,或者讀者朋友們沒有理解,本人深感自責,也但願同窗們可以理解,並在下面的回覆博客提問,本人定盡力給出解釋。

有喜歡本人博客內容的同窗請加關注,以便及時獲知本人精品內容!

相關文章
相關標籤/搜索