oop - programming - 面向方面編程與面向對象編程




spring aspect oriented (4)

AOP是一個處理這個概念的新的編程範例。 一個方面是實現應用程序的特定非功能部分的軟件實體。

我認為這篇文章是開始使用面向方面編程的好地方: http://www.jaftalks.com/wp/index.php/introduction-to-aspect-oriented-programming/ : http://www.jaftalks.com/wp/index.php/introduction-to-aspect-oriented-programming/

像大多數開發人員在這里和全世界一樣,我一直在使用面向對象編程(OOP)技術開發軟件系統多年。 所以當我讀到面向方面編程(AOP)時,解決了許多傳統OOP並未完全或直接解決的問題,我停下來思考一下,它是真的嗎?

我已經閱讀了大量的信息,試圖學習這種AOP範例的關鍵,並且我在同一個地方,所以我想更好地理解它在現實世界應用程序開發中的好處。

有人有答案嗎?


OOP和AOP不是相互排斥的。 AOP可以成為面向對象的良好補充。 AOP特別方便用於將標準代碼(如日誌記錄,性能跟踪等)添加到方法中,而不用此標準代碼堵塞方法代碼。


為什麼“vs”? 這不是“vs”。 您可以將面向方面編程與功能編程結合使用,也可以與面向對象相結合。 它不是“vs”,它是“面向對象編程面向方面編程”。

對我而言,AOP是一種“元編程”。 只需添加更多的代碼,AOP所做的一切都可以在沒有它的情況下完成。 AOP只是節省你編寫這段代碼。

維基百科有這個元編程的最好例子之一。 假設你有一個包含許多“set ...()”方法的圖形類。 在每種設置方法之後,圖形的數據發生改變,因此圖形改變並且因此圖形需要在屏幕上更新。 假設重新繪製圖形,您必須調用“Display.update()”。 傳統的方法是通過添加更多的代碼來解決這個問題。 在你寫的每一套方法的末尾

void set...(...) {
    :
    :
    Display.update();
}

如果你有3個設置方法,那不是問題。 如果你有200個(假設的),那麼到處添加這個就變得非常痛苦。 同樣,無論何時添加新的set-method,您都必須確保不要忘記將其添加到最後,否則您只是創建了一個bug。

AOP在不添加大量代碼的情況下解決了這個問題,而是增加了一個方面:

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

就是這樣! 您不要自己編寫更新代碼,而只需告訴系統在達到set()切入點後,它必須運行此代碼並運行此代碼。 無需更新200個方法,無需確保您不會忘記在新的set-method中添加此代碼。 另外你只需要一個切入點:

pointcut set() : execution(* set*(*) ) && this(MyGraphicsClass) && within(com.company.*);

那是什麼意思? 這意味著如果一個方法被命名為“set *”(*表示設置後可能有任何名字),無論該方法返回的是什麼(第一個星號)或它需要什麼參數(第三個星號), 並且它是MyGraphicsClass的一個方法, 並且這個類是包“com.company。*”的一部分,那麼這是一個set()切入點。 我們的第一個代碼表示“ 運行任何設置切入點的方法之後 ,運行以下代碼”。

看看AOP如何在這裡優雅地解決問題? 實際上這裡所描述的一切都可以在編譯時完成。 AOP預處理器可以在編譯類本身之前修改源代碼(例如,將Display.update()添加到每個set-pointcut方法的末尾)。

但是,這個例子也顯示了AOP的一個大缺點。 AOP實際上正在做許多程序員認為的“ Anti-Pattern ”。 確切的模式被稱為“ 在遠處行動 ”。

遠距離行動是一種反模式(一種公認的常見錯誤),其中一個程序的某一部分的行為根據難以或無法識別該程序的另一部分中的操作而變化很大。

作為項目的新手,我可能只是讀取任何set-method的代碼,並認為它已損壞,因為它似乎沒有更新顯示。 我看不到通過查看set-method的代碼,在執行它之後,其他代碼將“神奇地”執行以更新顯示。 我認為這是一個嚴重的缺點! 通過修改方法,可能會引入奇怪的錯誤。 進一步理解代碼在某些事情似乎正常工作的代碼流程中,但並不明顯(正如我所說的,他們只是神奇地工作......不知何故),真的很難。

更新

只是為了澄清:有些人可能會有印象,我說AOP是壞東西,不應該使用。 這不是我說的! AOP實際上是一個很棒的功能。 我只是說“小心使用它”。 如果您將相同方面的普通代碼和AOP混合使用,AOP只會導致問題。 在上面的例子中,我們具有更新圖形對象值並繪製更新對象的方面。 這實際上是一個方面。 將它的一半編碼為正常的代碼,另一半作為方面是什麼增加了這個問題。

如果您將AOP用於完全不同的方面,例如用於日誌記錄,則不會遇到反模式問題。 在這種情況下,項目的新手可能會想知道“所有這些日誌消息來自哪裡?我在代碼中看不到任何日誌輸出”,但這不是一個大問題。 他對程序邏輯的改變幾乎不會破壞日誌設施,對日誌設施所做的更改幾乎不會破壞他的程序邏輯 - 這些方面是完全分開的。 使用AOP進行日誌記錄有一個優點,即您的程序代碼可以完全專注於做它應該做的任何事情,並且您仍然可以進行複雜的日誌記錄,而不必讓任何地方的數百條日誌消息混淆您的代碼。 此外,當新代碼被引入時,神奇的日誌消息將在正確的時間顯示正確的內容。 新手程序員可能不明白他們為什麼會在那里或他們來自哪裡,但由於他們會在“正確的時間”記錄“正確的事情”,他只能高興地接受他們在那裡並繼續前進的事實。

因此,在我的示例中,AOP的一個很好的用法是,如果通過set方法更新了任何值,則總是記錄日誌。 這不會產生反模式,也不會成為任何問題的原因。

有人可能會說,如果你可以輕易地濫用AOP來創建這麼多問題,那麼全部使用它是一個壞主意。 但是哪種技術不能被濫用? 你可以濫用數據封裝,你可以濫用繼承。 幾乎所有有用的編程技術都可能被濫用。 考慮一種如此有限的編程語言,它只包含不能被濫用的功能; 一種功能只能用於最初打算使用的語言。 這種語言如此有限,以至於它甚至可以用於真實世界的程序設計是有爭議的。


面向方面的pogramming提供了一個很好的方式來實現橫切關注,如日誌記錄,安全性。 這些橫切的外觀是一些邏輯,必須在許多地方應用,但實際上與業務邏輯沒有任何關係。

您不應該將AOP看作是OOP的替代品,更像是一個不錯的附加組件,它使您的代碼更加干淨,鬆散耦合併專注於業務邏輯。 所以通過應用AOP,您將獲得兩項主要優勢:

  1. 每個問題的邏輯現在都集中在一個地方,而不是遍布整個代碼庫。

  2. 類更清潔,因為它們只包含主要關注(或核心功能)的代碼,而次要關注已轉移到方面。







paradigms