剖面導向程式設計

剖面導向程式設計(Aspect-oriented programming,AOP,又譯作面向方面程序設計面向切面程序設計面向方面的程式設計),是計算機科學中的一種編程范型,旨在將交叉切入關注與作為業務主體的核心關注進行分離,以提高程序代碼的模塊化程度。「方面」(aspect)通過規定叫做「點切入」(pointcut)的一種量化或查詢,在各種接合點(join point)上應用通告(advice),從而改變現有基礎代碼的行為(behavior)。比如點切入與通告的一個實例:「對所有方法名以set*開頭的方法添加後台日誌」。該思想使得開發人員能夠將與代碼核心業務邏輯關係不那麼密切的功能(如日誌功能)添加至程序中,同時又不降低業務代碼的可讀性。

簡介

面向方面編程將代碼邏輯切分為不同的模塊(即關注,一段特定的邏輯功能)。幾乎所有的編程思想都涉及代碼功能的分類,將各項關注(concern)封裝成獨立的抽象模塊(如函數、過程、模塊、類以及方法等),後者又可供進一步實現、封裝和重寫。部分關注「交叉切入」程序代碼中的數個模塊,即在多個模塊中都有出現,它們即被稱作交叉切入關注

日誌功能即是交叉切入關注的一個典型案例,因為日誌功能往往跨越系統中的每個業務模塊,即交叉切入(crosscut)所有有日誌需求的類及方法體。而對於一個信用卡應用程序來說,存款、取款、帳單管理是它的核心關注,日誌和持久化將成為交叉切入整個對象結構的交叉切入關注。

方面的概念源於對面向對象編程計算反射的融合。面向方面編程語言擁有很多類似於元對象協議的功能,但有更多的限制。方面相關的編程概念包括主題英語Subject-oriented programming混入委託英語Delegation (computing)。使用面向方面范型的其他方式有複合過濾器英語Composition filters和Hyper/J的hyperslices方式。

歷史

「面向方面編程」這一術語由施樂帕洛阿爾托研究中心的Chris Maeda首先提出,但其具體時間已經不可考證了。術語「交叉切入」(crosscut)是由Gregor Kiczales英語Gregor Kiczales提出的。同許多重大的技術創新一樣,面向方面編程,也是在不同的地方被獨立發展出來。面向方面編程的早期工作,主要是由下面幾個機構和人員作出的:

基本概念

關注是對軟件工程有意義的小的、可管理的、可描述的軟件組成部分,一項關注通常只同一個特定概念或目標相關聯。傳統的編程語言,以一種線性的文本來描述軟件,只採用一種方式比如類,將軟件分解成模塊;這導致某些關注比較好的被捕捉,容易進一步組合、擴展;但還有一些關注沒有被捕捉,彌散在整個軟件內部。

關注分離(SOC)是標識、封裝和操縱只與特定概念、目標相關聯的軟件組成部分的能力,即標識、封裝和操縱關注的能力。分離關注使得解決特定領域問題的代碼從業務邏輯中獨立出來,業務邏輯的代碼中不再含有針對特定領域問題代碼的調用,業務邏輯同特定領域問題的關係通方面來封裝、維護,這樣原本分散在在整個應用程序中的變動就可以很好的管理起來。

核心關注是一個軟件最主要的關注。在傳統的編程語言中,將軟件分解成模塊的主要方式,是支配性分解,即按主關注進行模塊分解。用來描述、設計、實現一項給定關注的軟件構造單位是方法。如果兩個關注的實現的方法存在交集,則稱謂這兩個關注相互交叉切入(crosscut)。

面向方面編程的核心概念,是從核心關注中分離出交叉切入關注。面向方面編程,在支配性分解的基礎上,提供叫做方面英語Aspect (computer programming)(aspect)的一種輔助的模塊化機制,這種新的模塊化機制可以捕捉交叉切入關注。

接合點模型

面向方面編程語言的通告相關構件,定義了一個接合點模型(JPM)。一個JPM定義了三種東西:

  1. 何時通告可以運行。這些叫做接合點英語join point,因為在一個運行的程序中,它們是可以有用的接合上額外行為的點。一個接合點想要有用,它必需是可尋址的,並且對普通程序員是可理解的。它還應該經歷無關緊要的程序變更而保持穩定,使得一個方面經歷這種變更而保持穩定。很多AOP實現支持方法執行和字段引用作為接合點。
  2. 規定(或量化)接合點的方式,這叫做點切入英語pointcut。點切入確定是否匹配一個給定接合點。最有用的點切入語言使用像基礎語言的語法(例如AspectJ英語AspectJ使用Java簽名),並允許通過命名和組合來重新使用。
  3. 指定在接合點要運行的代碼的手段。AspectJ英語AspectJ稱之為通告英語Advice (programming),並且可以在接合點之前、之後和周圍運行。一些實現還支持在一個方面中定義另一個類上的一個方法。

對接合點模型進行比較可以基於:所暴露的接合點,如何規定接合點,在接合點上允許的操作,能夠表達的結構性增強機制。

AspectJ的接合點模型

所有有效的Java程序也是有效的AspectJ程序,但是AspectJ容許編程者定義叫方面英語Aspect (computer programming)的特殊構造。方面包含一些對於標準類不能獲得到的實體。它們是擴展方法、點切入和通告。

擴展方法

擴展方法英語Extension method允許編程者在這個方面之內向現存的類增加方法、字段或接口。下面例子中,方面VisitAspect向類Point增加一個acceptVisitor方法(參見訪問者模式):

aspect VisitAspect {
  void Point.acceptVisitor(Visitor v) {
    v.visit(this);
  }
  
}

點切入

在AspectJ中接合點包括:方法或構造子調用或執行,一個類或對象的初始化,字段讀或寫訪問,異常處理等。接合點不包括:循環、super調用,throw子句,多個語句等。

點切入是通過組合「原始點切入指示符」(PCD - primitive pointcut designator)來規定的。例如:

aspect VisitAspect {
  
  pointcut set() : execution(* set*(*) ) && this(Point) && within(com.company.*);
  
}

這個點切入匹配一個方法執行接合點,如果這個方法名字開始於set,並且此對象(this)是在com.company包中類型Point的實例。這個點切入可以使用名字set()來提及。點切入可以複合和命名來重新使用。

「種類」PCD匹配特定種類的接合點(比如方法執行),並且傾向於接受類似Java模樣的簽名作為輸入:

execution(* set*(*))

這個點切入匹配一個方法執行接合點,如果這個方法名字開始於set,並且精確的只有一個任何類型的實際參數。

「動態」PCD檢查運行時間類型和綁定變量:

this(Point)

這個點切入在當前執行對象是類Point的實例之時匹配。注意一個類的未限定名字可以通過Java的正常類型查找來使用。

「範圍」PCD限制接合點的詞法作用域:

within(com.company.*)

這個點切入匹配在com.company包中任何類型的任何接合點。*是一種形式的通配符,它用來匹配具有一個簽名的任何東西。

通告

通告規定在(通過點切入指定的)一個接合點(之前、之後或周圍)運行特定代碼(指定如若一個方法中的代碼)。面向方面編程的運行時間系統,在這個點切入匹配一個接合點的時候,自動調用通告。例如:

aspect VisitAspect {
  
  after() : set() {
    Display.update();
  }
}

這在效果上指定了:「如果set()點切入匹配這個接合點,在接合點完成之後,運行代碼Display.update()。」

實現

下列編程語言已經實現了AOP,於語言之內或外部庫:

參考文獻

  1. ^ Kiczales, G.; Lamping, J.; Mendhekar, A.; Maeda, C.; Lopes, C.; Loingtier, J. M.; Irwin, J. Aspect-oriented programming (PDF). ECOOP'97. Proceedings of the 11th European Conference on Object-Oriented Programming. LNCS 1241. 1997: 220–242. CiteSeerX 10.1.1.115.8660 . ISBN 3-540-63089-9. doi:10.1007/BFb0053381. (原始內容存檔 (PDF)於2016-01-12). 
  2. ^ "Adaptive Object Oriented Programming: The Demeter Approach with Propagation Patterns" Karl Liebherr 1996 ISBN 0-534-94602-X presents a well-worked version of essentially the same thing (Lieberherr subsequently recognized this and reframed his approach).
  3. ^ Numerous: Afterthought 網際網路檔案館存檔,存檔日期2016-03-15., LOOM.NET 網際網路檔案館存檔,存檔日期2008-08-27., Enterprise Library 3.0 Policy Injection Application Block 網際網路檔案館存檔,存檔日期2007-01-19., AspectDNG 網際網路檔案館存檔,存檔日期2004-09-29., DynamicProxy 網際網路檔案館存檔,存檔日期2015-12-05., Compose* Wikiwix的存檔,存檔日期2005-08-21, PostSharp 網際網路檔案館存檔,存檔日期2016-05-03., Seasar.NET 網際網路檔案館存檔,存檔日期2006-07-25., DotSpect (.SPECT) 網際網路檔案館存檔,存檔日期2006-03-31., Spring.NET 網際網路檔案館存檔,存檔日期2006-04-02. (as part of its functionality), Wicca and Phx.Morph 網際網路檔案館存檔,存檔日期2006-12-07., SetPoint 網際網路檔案館存檔,存檔日期2008-10-07.
  4. ^ PostSharp. [2022-02-13]. (原始內容存檔於2022-07-05). 
  5. ^ Welcome to as3-commons-bytecode. as3commons.org. [5 May 2018]. (原始內容存檔於3 October 2014). 
  6. ^ Ada2012 Rationale (PDF). adacore.com. [5 May 2018]. (原始內容存檔 (PDF)於18 April 2016). 
  7. ^ Function Hooks. autohotkey.com. [5 May 2018]. (原始內容存檔於17 January 2013). 
  8. ^ Several: AspectC++, FeatureC++頁面存檔備份,存於網際網路檔案館), AspectC 網際網路檔案館存檔,存檔日期2006-08-21., AspeCt-oriented C 網際網路檔案館存檔,存檔日期2008-11-20., Aspicere
  9. ^ Cobble. vub.ac.be. [5 May 2018]. [永久失效連結]
  10. ^ AspectCocoa. neu.edu. [5 May 2018]. (原始內容存檔於26 October 2007). 
  11. ^ ColdSpring Framework: Welcome. 5 November 2005 [5 May 2018]. (原始內容存檔於5 November 2005). 
  12. ^ Closer Project: AspectL.. [11 August 2015]. (原始內容存檔於23 February 2011). 
  13. ^ infra - Frameworks Integrados para Delphi - Google Project Hosting. [11 August 2015]. (原始內容存檔於9 September 2015). 
  14. ^ meaop - MeSDK: MeObjects, MeRTTI, MeAOP - Delphi AOP(Aspect Oriented Programming), MeRemote, MeService... - Google Project Hosting. [11 August 2015]. (原始內容存檔於10 September 2015). 
  15. ^ Google Project Hosting. [11 August 2015]. (原始內容存檔於25 December 2014). 
  16. ^ RemObjects Cirrus. codegear.com. [5 May 2018]. (原始內容存檔於23 January 2012). 
  17. ^ Emacs Advice Functions. gnu.org. [5 May 2018]. (原始內容存檔於24 October 2011). 
  18. ^ Monads allow program semantics to be altered by changing the type of the program without altering its code: De Meuter, Wolfgang. Monads As a theoretical basis for AOP. International Workshop on Aspect-Oriented Programming at ECOOP. 1997: 25. CiteSeerX 10.1.1.25.8262 .  Tabareau, Nicolas; Figueroa, Ismael; Tanter, Éric. A Typed Monadic Embedding of Aspects. Proceedings of the 12th Annual International Conference on Aspect-oriented Software Development. Aosd '13. March 2013: 171–184 [2022-03-02]. ISBN 9781450317665. S2CID 27256161. doi:10.1145/2451436.2451457. (原始內容存檔於2018-11-06).  Type classes allow additional capabilities to be added to a type: Sulzmann, Martin; Wang, Meng. Aspect-oriented programming with type classes. Proceedings of the 6th Workshop on Foundations of Aspect-oriented Languages. March 2007: 65–74. ISBN 978-1595936615. S2CID 3253858. doi:10.1145/1233833.1233842. .
  19. ^ Numerous others: CaesarJ 網際網路檔案館存檔,存檔日期2008-12-19., Compose* Wikiwix的存檔,存檔日期2005-08-21, Dynaop 網際網路檔案館存檔,存檔日期2007-07-24., JAC 網際網路檔案館存檔,存檔日期2004-06-19., Google Guice (as part of its functionality), Javassist 網際網路檔案館存檔,存檔日期2004-09-01., JAsCo (and AWED) 網際網路檔案館存檔,存檔日期2005-04-11., JAML 網際網路檔案館存檔,存檔日期2005-04-15., JBoss AOP 網際網路檔案館存檔,存檔日期2006-10-17., LogicAJ 網際網路檔案館存檔,存檔日期2006-05-04., Object Teams 網際網路檔案館存檔,存檔日期2005-08-31., PROSE 網際網路檔案館存檔,存檔日期2007-01-24., The AspectBench Compiler for AspectJ (abc) 網際網路檔案館存檔,存檔日期2014-12-16., Spring framework (as part of its functionality), Seasar, The JMangler Project 網際網路檔案館存檔,存檔日期2005-10-28., InjectJ 網際網路檔案館存檔,存檔日期2005-04-05., GluonJ 網際網路檔案館存檔,存檔日期2007-02-06., Steamloom 網際網路檔案館存檔,存檔日期2007-08-18.
  20. ^ Many: Advisable 網際網路檔案館存檔,存檔日期2008-07-04., Ajaxpect 網際網路檔案館存檔,存檔日期2016-07-09., jQuery AOP Plugin 網際網路檔案館存檔,存檔日期2008-01-13., Aspectes Wikiwix的存檔,存檔日期2006-05-08, AspectJS 網際網路檔案館存檔,存檔日期2008-12-16., Cerny.js 網際網路檔案館存檔,存檔日期2007-06-27., Dojo Toolkit 網際網路檔案館存檔,存檔日期2006-02-21., Humax Web Framework 網際網路檔案館存檔,存檔日期2008-12-09., Joose 網際網路檔案館存檔,存檔日期2015-03-18., Prototype - Prototype Function#wrap 網際網路檔案館存檔,存檔日期2009-05-05., YUI 3 (Y.Do) 網際網路檔案館存檔,存檔日期2011-01-25.
  21. ^ Using built-in support for categories (which allows the encapsulation of aspect code) and event-driven programming (which allows the definition of before and after event handlers).
  22. ^ AspectLua. [11 August 2015]. (原始內容存檔於17 July 2015). 
  23. ^ MAKAO, re(verse)-engineering build systems. [11 August 2015]. (原始內容存檔於24 July 2012). 
  24. ^ McLab. [11 August 2015]. (原始內容存檔於24 September 2015). 
  25. ^ AspectML - Aspect-oriented Functional Programming Language Research. [11 August 2015]. (原始內容存檔於5 December 2010). 
  26. ^ Adam Kennedy. Aspect - Aspect-Oriented Programming (AOP) for Perl - metacpan.org. [11 August 2015]. (原始內容存檔於31 August 2013). 
  27. ^ Several: PHP-AOP (AOP.io) Wikiwix的存檔,存檔日期2014-08-18, Go! AOP framework 網際網路檔案館存檔,存檔日期2013-03-01., PHPaspect 網際網路檔案館存檔,存檔日期2016-08-22., Seasar.PHP 網際網路檔案館存檔,存檔日期2005-12-26., PHP-AOP, Flow 網際網路檔案館存檔,存檔日期2018-01-04., AOP PECL Extension 網際網路檔案館存檔,存檔日期2017-04-11.
  28. ^ bigzaphod.org is coming soon. www.bigzaphod.org. [5 May 2018]. (原始內容存檔於20 April 2016). 
  29. ^ Several: PEAK 網際網路檔案館存檔,存檔日期2005-04-09., Aspyct AOP, Lightweight Python AOP 網際網路檔案館存檔,存檔日期2004-10-09., Logilab's aspect module 網際網路檔案館存檔,存檔日期2005-03-09., Pythius 網際網路檔案館存檔,存檔日期2005-04-08., Spring Python's AOP module 網際網路檔案館存檔,存檔日期2016-03-04., Pytilities' AOP module 網際網路檔案館存檔,存檔日期2011-08-25., aspectlib 網際網路檔案館存檔,存檔日期2014-11-05.
  30. ^ PLaneT Package Repository : PLaneT > dutchyn > aspectscheme.plt. [11 August 2015]. (原始內容存檔於5 September 2015). 
  31. ^ AspectR - Simple aspect-oriented programming in Ruby. [11 August 2015]. (原始內容存檔於12 August 2015). 
  32. ^ Dean Wampler. Home. [11 August 2015]. (原始內容存檔於26 October 2007). 
  33. ^ gcao/aspector. GitHub. [11 August 2015]. (原始內容存檔於4 January 2015). 
  34. ^ AspectS. tu-ilmenau.de. [5 May 2018]. (原始內容存檔於6 January 2006). 
  35. ^ MetaclassTalk: Reflection and Meta-Programming in Smalltalk. [11 August 2015]. (原始內容存檔於29 July 2015). 
  36. ^ WEAVR. iit.edu. [5 May 2018]. (原始內容存檔於12 December 2008). 
  37. ^ aspectxml - An Aspect-Oriented XML Weaving Engine (AXLE) - Google Project Hosting. [11 August 2015]. (原始內容存檔於12 September 2015). 

站外鏈接