2009-06-24 10 views
6

ho le seguenti API:API Java pausa

public interface MyApi { 

    /** 
    * Performs some stuff. 
    * @throws MyException if condition C1 
    */ 
    public void method() throws MyException; 
} 

ora sto eseguendo la seguente modifica nella mia implementazione dell'API

public class MyApiImpl { 

    public void method() throws MyException { 
    if (C1) { 
     throw new MyException("c1 message"); 
    } 
    ... 
    } 
} 

è sostituito dal seguente:

public class MyApiImpl { 

    public void method() throws MyException { 
    if (C1) { 
     throw new MyException("c1 message"); 
    } else if (c2) { 
     throw new MyException("c2 message"); 
    } 
    ... 
    } 
} 

Ti consideri questo come una rottura di API?

Il codice del client verrà comunque compilato, ma il contratto del metodo definito dall'API javadoc non è più rispettato poiché MyExcepiton viene generato da una condizione "nuova".

Se solo il mio file jar API viene aggiornato, l'applicazione client sarà ancora lavorare, ma a seconda del modo in cui i clienti intercettare l'eccezione il comportamento dell'applicazione può cambiare molto.

Qual è il tuo punto di vista al riguardo?

risposta

7

Sì, si sta rompendo il contratto dell'interfaccia lanciando un'eccezione quando C1 non si verifica.

Come regola generale, il più vago il contratto di interfaccia, più facile, non è quello di rompere :) Se l'interfaccia non è definito in termini di C1 esplicita, ma in termini più generali, che dà molto di più flessibilità.

6

Il mio punto di vista è che non si deve modificare il contratto definito dall'API nella documentazione. Se hai bisogno di un nuovo comportamento dovresti a.) Creare un nuovo metodo che può essere chiamato dal client che riflette questo nuovo comportamento o b). Discuti con il cliente la necessità del cambiamento e rendilo consapevole di ciò.

Questo in realtà può andare in entrambe le direzioni, è tra voi ei vostri clienti come a quello che sarà il vostro approccio.

1

Dipende in gran parte da ciò che c2 è. È nei limiti logici del contratto preesistente? Se è così, stai soddisfacendo il contratto lanciando un MyException. In caso contrario, forse è necessario lanciare un nuovo tipo di eccezione.

Tengo a precisare che io non sono un grande fan di eccezioni controllate. In definitiva, forzare qualcuno a gestire un'eccezione non rende necessariamente il loro codice migliore o più sicuro (in effetti può avere l'effetto opposto in quanto può ingoiare in modo sleale eccezioni spurie).

1

direi "no", senza API rottura, a meno che non MyException è un RuntimeException. Allora lo è.

In ogni caso, mi piacerebbe sottoclasse MyException per la condizione C2

Ed entrambi condizioni C1 e C2 dovrebbe essere IMHO "eccezionali", non vorrei fare un'abitudine di gettare eccezioni

1

E 'una rottura. Se l'API è applicata da costrutti linguistici o semplicemente documentata è irrilevante.

Se questa rottura causa un problema per il codice cliente è una questione diversa. Può darsi che tu stia correggendo un difetto e hai bisogno di coprire il caso C2 in questo modo per risolverlo. Da questo punto di vista, gli sviluppatori di codice client potrebbero essere contenti di aver apportato questo cambiamento (supponendo che attualmente non stiano lavorando attorno al difetto in modo tale da infrangere il cambiamento!)

1

Penso che il problema qui sia che hai fatto parte della tua interfaccia, condizioni specifiche di implementazione. Se la condizione "C1" fosse solo una parte della tua implementazione, allora avresti potuto semplicemente creare una nuova implementazione che genera un'eccezione su "C1" o "C2" senza rompere l'interfaccia.