特性導向程式設計

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

簡介

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

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

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

歷史

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

基本概念

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

關注分離(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). 

站外部連結接