Supponiamo che abbia una classe che rappresenta un'immagine e ha un numero di metodi.
class Image
{
circle(x,y,radius,color);
square(x,y,w,h,color);
floodfill(x,y,color)
clear();
}
Inoltre, voglio avere la funzionalità di annullamento. Un modo semplice per implementare questo è mantenere un elenco di tutte le azioni che sono state eseguite. Quando annullo, eseguo nuovamente tutte le azioni. Una soluzione sarebbe quella di implementare un aspetto, qualcosa del genere:
aspect ImageUndo
{
on Image::circle, Image::square, Image::floodfill
precall(object, args)
{
object.actions_list.add(args)
}
}
In sostanza, questo aspetto ha ora modificato il comportamento di Image. Questo mi preoccupa. In particolare, un altro programmatore che non ha familiarità con l'esistenza dell'aspetto ImageUndo può incontrare i seguenti problemi:
- Aggiunge un metodo e non funziona con la funzionalità di annullamento.
- Tentativo di eseguire il debug del meccanismo di annullamento, non è chiaro dove viene aggiunto l'elenco_selezioni.
D'altra parte potremmo avere
class Image
{
@undoable_action
circle(x,y,radius,color);
@undoable_action
square(x,y,w,h,color);
@undoable_action
floodfill(x,y,color)
@undoable_action
clear();
}
Il che non mi infastidisce più di tanto perché dà un'idea di dove cercare il codice di annullamento e fa sì che il nuovo programmatore noterà probabilmente che lo aggiungerà automaticamente a un nuovo metodo.
Per riassumere: aspetti (almeno quelli come quello che ho mostrato) sembrano portare "magia implicita" in ciò che fa il codice. Mi sembra che l'implicità sia pericolosa e dovremmo renderla esplicita.
Ci sono buone ragioni per l'implicito? Le persone che effettivamente usano il codice di scrittura AOP che esegue questo tipo di modifica?
Nota: questa è una rielaborazione di Sono sicuro problemi risolti in modo più elegante con AOP? che è stato chiuso perché la mia versione precedente si era imbattuta, involontariamente, come un ranting.