Annotazione per definire i valori per l'argomento del metodo

0

In un progetto, ho un servizio di pianificazione delle attività, che è autorizzato ad eseguire determinati metodi pubblici da altri servizi. Ogni servizio decide da solo, quali metodi rendere disponibili per il servizio di pianificazione delle attività annotandoli con @Operation . Il servizio di pianificazione delle attività analizzerà semplicemente tutti i servizi forniti per questa annotazione per ottenere informazioni sui metodi che è possibile configurare per l'esecuzione. Ciò significa che un utente che desidera creare un'attività avrà un elenco di metodi @Operation presentati.

Prendiamo l'esempio che segue di un servizio di aggiornamento (un servizio tra pochi)

public interface UpdateService extends Service{

    @Operation
    public void update(String updateFileName);

    public List<String> getAvailableUpdateFileNames();

    @Operation
    public void ...

    ...
}

Il modo in cui viene dichiarata l'interfaccia UpdateService , un utente può creare un'attività sul servizio delle attività eseguendo il metodo update . Consentendo all'utente di configurare liberamente un'attività con qualsiasi stringa è per lo più certo errata. L'interfaccia, in questo caso, dovrebbe quindi presentare un elenco di valori predefiniti che possono essere utilizzati con il metodo update .

Allo stesso modo, il servizio di aggiornamento conosce anche un metodo getter che rivela tutti gli aggiornamenti disponibili. Questo sarebbe ideale come fonte per i valori predefiniti.

Ecco perché sono arrivato con il seguente approccio:

public interface UpdateService extends Service{

    @Operation(sourceClass=UpdateService.class,sourceMethod="getAvailableUpdateFileNames")
    public void update(String updateFileName);

    public List<String> getAvailableUpdateFileNames();
}

L'interfaccia @Operation viene introdotta in un paio di parametri. Il servizio attività esegue ancora la scansione di tutte le interfacce di servizio fornite per le annotazioni @Operation , per presentare all'utente un elenco definito.

Il Task Manager comprende anche gli argomenti:

  • sourceClass: questa classe deve contenere il metodo source
  • sourceMethod: questo metodo restituisce valori che possono essere utilizzati per la funzione di interfaccia annotata.

Con l'aiuto della reflection, il servizio task esegue il metodo sourceMethod e offrirà i valori restituiti genericamente come valori predefiniti per la configurazione dell'attività del metodo update(String updateFileName) nell'interfaccia utente. L'utente può selezionare tale valore e pianificare il metodo update con questo valore selezionato come argomento.

Questo esempio è molto semplice e al momento funzionerebbe solo se il metodo annotato avesse 1 argomento. Anche se sarebbe completamente generico e disaccoppiato.

C'è un modo migliore per risolvere questo problema? O questo approccio non è affatto male?

    
posta Herr Derb 15.08.2017 - 13:33
fonte

2 risposte

1

Il design presentato presenta problemi

  • Stai utilizzando un'annotazione dove probabilmente dovrebbe essere usato un metodo aggiuntivo dell'interfaccia Service . Qualcosa come un metodo execute() che può chiamare getAvailableUpdateFileNames e quindi richiamare update . Stai già implementando Service . Perché progettare questo sistema complesso basato sulla riflessione per richiamare update ?
  • La soluzione al problema che hai progettato con un'annotazione con parametri è miope. Può risolvere i tuoi problemi immediati con UpdateService , ma probabilmente incontrerai un altro servizio che vorresti comportarti in modo leggermente diverso (come avere due parametri come hai riconosciuto) e hai impostato un precedente per l'introduzione dei parametri di annotazione in risolvi questi problemi.
  • Le annotazioni, anche se di fantasia e ampiamente utilizzate, introducono diversi problemi che influiscono sul tuo leggibilità, manutenibilità e testabilità del codice. Non li userei quando un altro design è chiaramente presente.

Se desideri separare le preoccupazioni relative all'aggiornamento e al servizio che lo esegue, ti suggerisco di collaborare.

Dove UpdateService.execute è implementato come:

List<String> fileNames = updater.getAvailableFileNames();
updater.update(fileNames.get(0));

Questo design ha il vantaggio di poter eseguire qualsiasi metodo su qualsiasi oggetto invece di solo quelli con un singolo parametro. Le preoccupazioni sono separate e ogni pezzo può essere testato unitariamente in modo indipendente.

    
risposta data 15.08.2017 - 22:11
fonte
0

Mi sembra che tu stia reinventando le interfacce. Le annotazioni hanno i loro usi, ma qui si stanno combinando i metodi ( update() e getAvailableUpdateFileNames() ) attraverso le annotazioni. Questo sta andando giù in una tana del coniglio, dal momento che è anche necessario verificare i tipi di raccolta restituiti dal getter corrisponde al tipo previsto dall'operazione. Questo non sarà banale, ed è esattamente ciò che le interfacce intendono risolvere.

Capisco che vuoi una singola classe per implementare più operazioni. Penso che dovresti riconsiderare questo requisito. Se un'operazione fosse un singolo metodo, potrebbe funzionare, ma poiché un'operazione è un insieme di metodi interdipendenti, penso che sarebbe una violazione del principio di responsabilità singola.

Ti suggerisco di definire un'interfaccia Operation . Quindi potresti avere una classe Service che espone una raccolta di Operation s.

    
risposta data 16.08.2017 - 08:55
fonte

Leggi altre domande sui tag