AOP vs Funktionen

Aspect Oriented Programming (AOP) ist ein recht beliebtes Programmierparadigma. Der Wikipedia-Artikel erklärt die Motivation für diesen Ansatz gut.

Bild

AOP ist ein hervorragendes Werkzeug für globale Konzepte wie die Protokollierung, die sich direkt nicht auf die Logik des Codes auswirkt.

Probleme mit AOP werden jedoch entdeckt, wenn es für geschäftliche Anforderungen wie die Autorisierung verwendet wird. Solche Aspekte sollten im entsprechenden Code deutlich sichtbar sein, damit der Entwickler beim Lesen des Quellcodes sofort sehen kann, ob sie korrekt implementiert sind. AOP-Frameworks lösen dieses Problem normalerweise mit Anmerkungen:

@RequireRole(Role.Admin) // clearly visible aspect fun updateUserPermissions(…) { // logic here } 

In Bezug auf die Lesbarkeit unterscheidet es sich jedoch nicht wesentlich vom funktionalen Ansatz, bei dem anstelle der Annotation die requireRole- Methode verwendet wird.

Anmerkung des Übersetzers : Im Originalartikel wird der Ausdruck verwendet, wenn er auf funktionale Weise oder mit funktionalem Ansatz umgeschrieben wird. Dies kann als Verwendung eines funktionalen Ansatzes oder eines direkten / spezifischen Funktionsaufrufs interpretiert werden. Der Artikel enthält Beispiele, die auf unterschiedliche Weise interpretiert werden können.

Auch:

1. In Zukunft werden wir zum Konzept der Funktionen höherer Ordnung zurückkehren

2. Der Artikel trifft auf den Wortaspekt, den Engländerismus, und das Konzept im AOP- Aspekt


 fun updateUserPermissions(…) { requireRole(Role.Admin) // throws SecurityException // logic here } 

Darüber hinaus hat der funktionale Ansatz den Vorteil, dass er auf komplexere Zugriffskontrollprüfungen wie die Analyse von Methodenparametern skaliert werden kann, bevor entschieden wird, welche Benutzerrolle erforderlich ist.

Gleiches gilt für andere Arten von Aspekten, z. B. Transaktionen. Leider ist die funktionale Darstellung komplexerer Konzepte in Java umständlich und unpraktisch, was die künstliche Popularität von AOP-Frameworks im Java-Ökosystem hervorruft.

In Kotlin anstelle eines Java-ähnlichen Transaktionsansatzes mit AOP und Anmerkungen wie diesen:

 @Transactional fun updateUserPermissions(…) { // logic here } 

Es ist auch lesbar und sieht sauber aus, wenn es ohne Anmerkungen neu geschrieben wird, mit einem funktionalen Ansatz.

 fun updateUserPermissions(…) = transactional { // logic here } 

Der Vorteil dieses Ansatzes ist, dass Sie jederzeit Strg / Befehlstaste drücken können. Klicken Sie auf die Transaktionsfunktionsdeklaration in Ihrer IDE und sehen Sie sofort, was genau sie tut. Dies ist normalerweise mit keinem der häufig verwendeten AOP-Frameworks möglich. Selbst wenn die Navigation zum Aspektcode mithilfe des IDE-Plugins bereitgestellt wird, erfordert die Entschlüsselung seiner Logik die Kenntnis einer separaten multifunktionalen API und / oder Konventionen.

Leider gibt es Probleme bei der Skalierung des Ersetzens von AOP-Annotationen in Kotlin. Für den Fall, dass mehrere Aspekte auf dieselbe Funktion angewendet werden, wobei sich geschweifte Klammern und Einrückungen ansammeln:

 fun updateUserPermissions(…) = logged { transactional { // logic here } } 

Eine Problemumgehung besteht darin, eine Funktion höherer Ordnung zu erstellen, um akzeptablen Code zu erhalten, wenn mehrere Aspekte angewendet werden :

 fun updateUserPermissions(…) = loggedTransactional { // logic here } 

Ein weiterer Nachteil des funktionalen Ansatzes besteht darin, dass Aspekte wie die Protokollierung den Zugriff auf die Methodenparameter erfordern. Sie sind normalerweise in AOP-Frameworks über spezielle APIs verfügbar, aber mit Standardfunktionen der Kotlin-Sprache können Sie nicht einfach darauf zugreifen. Um also ein reales Beispiel für den Aspekt der Protokollierung in einer rein funktionalen Form zu präsentieren, müssen Sie noch eine erhebliche Menge an Kesselplattencode schreiben:

 fun updateUserPermissions(params: Params) = logged("updateUserPermissions($params)") { // logic here } 

Diese Überlegung macht AOP immer noch zum bevorzugten Protokollierungswerkzeug, wenn Sie es wirklich global und konsistent in Ihrer Anwendung benötigen. Gleichzeitig ist die Verwendung von AOP für Funktionen wie Autorisierung und Transaktionen angesichts der umfangreichen funktionalen Abstraktionen, die in Kotlin verfügbar sind, ein Missbrauch. Funktionen erfüllen diese Anforderungen besser und sauberer.

Abschließend würde ich sagen, dass eine weitere Verbesserung der funktionalen Abstraktionen, um AOP noch besser zu ersetzen, ein vielversprechender Vektor für die zukünftige Entwicklung der Kotlin-Sprache sein könnte. Java-basierte AOP-Frameworks sind in der Regel JVM-spezifisch und werden als magisch empfunden, während Kotlins funktionale Abstraktionen wirklich plattformübergreifend und für den Benutzer transparent sind.
Anmerkung des Übersetzers :
1. Artikel auf Medium (deu) .
2. Der Autor des Originalartikels ist Roman Elizarov (Teamleiter JetBrains, der an Kotlin-Coroutinen und -Bibliotheken, Sportprogrammierung / ICPC, Parallelität und Algorithmen, Mathematik / quantitative Finanzen; ehemals Devexperts) arbeitet. Auf Habr elizarov

Source: https://habr.com/ru/post/de435454/


All Articles