Come imporre il modo in cui viene consumata un'interfaccia

4

Immagina di avere un'interfaccia:

public interface MyInterface
{
    void CallMeFirst();
    void CallMeDuringApplicationLifecycle();
    void CallMeOnApplicationExit();
}

Qual è il modo migliore di applicare l'ordine in cui i metodi su questa interfaccia vengono utilizzati chiamando il codice?

Dovrebbe essere un'eccezione se i metodi sono chiamati nell'ordine sbagliato.

Dovrebbe anche essere un'eccezione se uno dei metodi è non chiamato affatto .

    
posta James Bateson 09.03.2016 - 15:59
fonte

4 risposte

5

What is the best way of enforcing the order in which the methods on this interface are consumed by calling code?

Non puoi. Anche se le tue implementazioni impongono delle eccezioni, non puoi garantire che altri lo facciano.

I metodi che si preoccupano del loro ordine hanno quello che viene chiamato accoppiamento temporale, che aggiunge un mucchio di fragilità al codice. Ove possibile, dovresti riprogettare il codice in modo che i metodi possano agire in modo indipendente.

Detto questo, ci sono alcune cose che puoi fare in determinate situazioni:

  1. Utilizza una classe base astratta . Puoi quindi applicare alcuni comportamenti lasciando altri elementi astratti da fornire agli implementatori.

  2. ha più classi . Quando chiami il primo metodo, restituisce un nuovo oggetto che ti consente di fare il secondo passo. Il secondo metodo restituisce un nuovo oggetto che ti consente di eseguire il terzo passaggio e così via.

Nessuno di questi risolve lo scenario "se nessun metodo viene chiamato" - devi necessariamente qualcosa per controllare, ma senza ulteriori dettagli non sono sicuro di come affrontare il problema.

    
risposta data 11.03.2016 - 04:05
fonte
5

Una soluzione accurata sarebbe:

public interface First 
{
    Second doFirst();
}

public interface Second
{
    Third doSecond();
}

public interface Third 
{
    void doThird();
}

Si potrebbe chiamare:

FirstFactory.create()
    .doFirst()
    .doSecond()
    .doThird();

ma non può chiamare:

FirstFactory.create()
    .doFirst()
    .doThird()
    .doSecond();

Un'altra soluzione tecnica (ma piuttosto negativa dal punto di vista del design):

public interface MyInterface
{
    First CallMeFirst();
    Second CallMeDuringApplicationLifecycle(First first);
    void CallMeOnApplicationExit(Second second);
}

e crea in qualche modo First e Second classi interne della classe di implementazione di MyInterface . La chiamata potrebbe essere:

CallMeOnApplicationExit(CallMeDuringApplicationLifecycle(CallMeFirst()));
    
risposta data 11.03.2016 - 09:29
fonte
4

Forse consideri il modello di design Metodo modello . Il tuo design introduce il accoppiamento temporale , che introduce il rischio e potrebbe essere considerato un difetto di progettazione.

    
risposta data 09.03.2016 - 16:20
fonte
4

m3th0dman ha mostrato il principio generale, ma la sua soluzione non si adatta al problema come ho capito, dal momento che i nomi dei metodi mi fanno pensare che CallMeDuringAPplicationLifecycle possa essere chiamato più volte.

In C #, una risorsa che ha bisogno di pulizia (come il lavaggio dei buffer o la chiusura delle connessioni) dovrebbe usare l'implementazione IDisposable .

interface IConnectionFactory
{
  IConnection connect(); // This is CallMeFirst
}

interface IConnection : IDisposable
{
  void send(); // This is CallMeDuringApplicationLifecycle
}
// And the Dispose() method of IDisposable is CallMeOnApplicationExit.

In questo modo, imponi che CallMeFirst venga chiamato per primo, perché non c'è altro modo per ottenere un IConnection . E poiché i programmatori C # riconoscono IDisposable , sanno che devono chiamare Dispose quando hanno terminato la connessione. In realtà non è possibile applicarlo in C #, quindi è il più vicino possibile. (Puoi anche scrivere un finalizzatore che controlli che sia stato chiamato Dispose , ma non puoi fare altro che registrare l'errore lì, e non c'è alcuna garanzia che i finalizzatori saranno chiamati.)

    
risposta data 11.03.2016 - 10:45
fonte

Leggi altre domande sui tag