La programmazione orientata agli aspetti promette di affrontare questioni trasversali, ma non sono ancora completamente venduta. Ci sono stati altri tentativi di affrontare questo problema?
La programmazione orientata agli aspetti promette di affrontare questioni trasversali, ma non sono ancora completamente venduta. Ci sono stati altri tentativi di affrontare questo problema?
Risposte:
Se possibile, è possibile incapsulare le preoccupazioni trasversali in moduli separati che vengono quindi utilizzati in tutta l'app tramite l'iniezione delle dipendenze. Ciò consente di disaccoppiare in qualche modo l'implementazione trasversale delle preoccupazioni dal suo utilizzo in tutto il codice.
Tuttavia, non sempre funziona in modo elegante. Questo è il motivo per cui le persone stanno cercando di affrontare il problema con cose come AOP.
Altre due opzioni che non ho ancora visto esplorate:
Programmazione funzionale con monadi e frecce
In FP rappresenti una preoccupazione trasversale come qualsiasi altra cosa: come qualcosa che passi in una chiamata di funzione. Dato che farlo diventa esplicitamente noioso, puoi usare Monads (o forse le frecce) per nascondere le informazioni extra che vengono trasmesse.
L'esempio AOP più comune è la registrazione. Con Monads, creeresti una monade "Logger" che conserva un elenco di messaggi. Qualsiasi funzione eseguita tramite LoggerMonad ha la possibilità di pubblicare un messaggio di registro. Con le frecce, modelleresti l'intero flusso di dati dell'applicazione e, se del caso, lavoreresti nel modello di una registrazione. Penso. Le frecce sono piuttosto complesse.
Programmazione basata su entità / componenti
Qualcosa che ho cercato e sperimentato per un motore di gioco. Invece di "oggetti" come in OOP, si decompone tutto in pacchetti di dati (componenti) e servizi che operano su un tipo di componente. I componenti sono raggruppati in base a ID comuni, come in un database relazionale, e i gruppi di componenti collegati sono le Entità. Per aggiungere la registrazione in tale sistema, aggiungere un nuovo servizio di registrazione i trigger in base ai componenti che lo attraversano.
Entrambi i metodi consentono di lavorare facilmente un cambiamento trasversale molto facilmente, ma entrambi sono modelli architettonici di alto livello. Quindi probabilmente dovresti usarli dall'inizio. In teoria, il modello Component può essere elaborato in un sistema OOP esistente. Immagino che anche le monadi potrebbero esserlo se la tua lingua è abbastanza potente.
Esistono diversi modi per affrontare i problemi delle preoccupazioni trasversali:
Usa modelli di progettazione, modi di dire o meccanismi di astrazione migliori : il codice può essere incrociato anche se può essere modulare. Al fine di mantenere il codice, è necessario refactoring per utilizzare la tecnica di progettazione in grado di modularizzarlo. Tale refactoring può introdurre un taglio trasversale di tipo diverso, ma si spera che i tagli incrociati siano stabili e che non possano cambiare.
Sviluppa funzionalità linguistiche più ricche : molte manifestazioni del taglio incrociato possono essere risolte attraverso meccanismi di astrazione migliori e talvolta sono necessarie nuove funzionalità linguistiche. Ad esempio, linguaggi più avanzati che includono funzionalità funzionali e orientate agli oggetti spesso non impiegano altrettanti modelli di progettazione, perché non sono necessari. Si noti che gli stessi modelli di progettazione possono essere trasversali in natura , poiché descrivono i ruoli di diversi oggetti e classi. In Java, la riflessione può spesso essere utilizzata al posto di un aspetto, sebbene a costi di runtime più elevati. Ad esempio, usando reflection, è possibile supportare il modello visitatore su centinaia di classi con solo un paio di righe di codice. La libreria DJdal nordest è una soluzione riflessiva che fa proprio questo. I mixin sono una potente tecnica disponibile in C ++ (ma non Java) e possono darti alcuni degli stessi casi d'uso di un aspetto.
Fornire un migliore supporto agli strumenti : tecniche come l'uso grep
e l'esecuzione di operazioni di refactoring possono gestire i problemi relativi al codice di taglio incrociato. Ad esempio, il nome di un metodo dichiarato in un'interfaccia può attraversare il programma. (Nota la differenza tecnica qui: è il nome del metodo, non l'implementazione del metodo, che taglia i tagli incrociati). Di solito questo non è un problema in un IDE come Eclipse, dove puoi usare il "rinominare refactoring" per cambiare tutto i luoghi nel tuo codice che usano il nome. In questo modo, è possibile che non siano necessarie funzionalità linguistiche quando l'ambiente di programmazione è abbastanza espressivo per te.
Usa linguaggi specifici del dominio : i primi aspetti linguistici, che precedevano AspectJ, erano specifici del dominio e applicati solo a determinati problemi, come la sincronizzazione dei thread o l'analisi del flusso di dati per combinare in modo efficiente composizioni di funzioni. Questi linguaggi erano sperimentali, ma sembravano avere un grande successo nel modulare le preoccupazioni che altrimenti sarebbero state trasversali.
Usa tecniche di programmazione generativa : il passaggio al livello meta potrebbe essere considerato una tecnica di implementazione per la programmazione orientata all'aspetto, ma è un'area abbastanza grande da trascendere aspetti semplici. Le tecniche generative (in cui un programma genera codice sorgente per un altro programma) sono anche correlate a linguaggi specifici del dominio.
Per tutti questi, penso che studiare AOP sia appropriato. AOP può aiutarti ad espandere le tue concezioni di codice, anche se non usi un linguaggio AOP.
In generale taggare elementi di codice con una funzione dichiarativa, ma in particolare il sistema di attributi nel mondo C # /. NET / Mono.
Non sono un esperto di AOP, ma dalla sua lettura nel corso degli anni, è sempre sembrata una forma più debole della metaprogrammazione offerta da Lisp , in particolare parti come il suo protocollo metaobject.
Ciò non dovrebbe sorprendere, suppongo: Gregor Kiczales fu uno degli autori di AMOP, e in seguito scrisse AspectJ per Java!