Opzioni per la programmazione per contratto in Java

5

Sto lavorando a un progetto (che include app Web JavaEE e app JavaSE) che è passato da un singolo sviluppatore a un team di tre persone e stanno emergendo problemi di leggibilità e solidità.

Un'omissione evidente dal linguaggio Java ha riguardato i contratti perfezionati e la facilità con cui questi sono esposti ad altri sviluppatori. (Con i contratti intendo principalmente la convalida dei parametri del metodo e delle condizioni pre / post dell'oggetto).

Ci sono alcune soluzioni che sto osservando e vorrei ricevere feedback dagli altri che hanno qualche esperienza pratica.

Sembrerebbe che Java abbia attualmente due modi supportati per definire un contratto:

  1. La dichiarazione di asserzione
  2. Eccezioni di lancio (come IllegalArgumentException)

Gli avvisi sembrano avere solo valore come strumento di debug. Poiché gli assert non sono abilitati per impostazione predefinita, l'aspettativa è che gli sviluppatori si baseranno su di loro solo durante un periodo di test formalizzato, dopo il quale verranno ignorati.

Lanciare le eccezioni sembra una valida opzione in quanto consentono di effettuare quasi tutti i tipi di controlli. Tuttavia, l'intervallo di eccezioni definito dalla libreria Java sembra essere poco adatto alla definizione dei contratti (per le sottoclassi examply di IllegalArgumentException non specificamente con problemi di intervallo, assegni nulli ecc. e sottoclassi di IllegalStateException sembra riguardare la connessione di rete e gli stati dei file), il che costringe ciascun gruppo a definire il proprio intervallo di classi di eccezioni.

Ma il problema più grande è che né le affermazioni né le affermazioni esplicitamente mappano i requisiti del contratto a parametri o concetti come le condizioni pre e post. Si prevede che lo sviluppatore manterrà manualmente i commenti JavaDoc con il codice per chiarire in quali condizioni un assert fallirà o verrà lanciata un'eccezione.

Mi è chiaro che le librerie Java standard non supportano adeguatamente la progettazione per contratto, il che mi porta alle mie domande:

Le mie supposizioni sono corrette o mi sono perso alcune proprietà di asserzioni ed eccezioni che in realtà le rendono piuttosto utili per questo tipo di problema?

    
posta Phyxx 06.05.2012 - 23:17
fonte

2 risposte

2

Le tue ipotesi sono corrette. Java richiede una libreria di terze parti per implementare la progettazione per contratto.

Ecco alcune librerie di terze parti elencate nell'articolo di Wikipedia su design per contratto .

Contract4J, jContractor, Jcontract, C4J, Google CodePro Analytix, STclass, Jass preprocessor, OVal with AspectJ, Java Modeling Language (JML), SpringContracts for the Spring framework, Modern Jass, Custos using AspectJ,JavaDbC using AspectJ, JavaTESK using extension of Java, chex4j using javassist, or Contracts for Java, and the highly customizable java-on-contracts.

    
risposta data 07.05.2012 - 16:40
fonte
2

Di solito trovo che i buoni test più un ragionevole livello di convalida del runtime offrono la maggior parte dei vantaggi della progettazione per contratto. Non sono sicuro che valga la pena di introdurre un set di strumenti completamente nuovo per la progettazione per contratto nei normali programmi Java.

Tecniche che puoi utilizzare senza uscire da Java standard:

  • Utilizza i test JUnit per pubblicare esplicitamente le condizioni su un'ampia varietà di input
  • Per qualsiasi API pubblica (ad esempio quella destinata a essere utilizzata da utenti esterni / altri gruppi nell'organizzazione) eseguire esplicitamente la convalida dei parametri in runtime. Genera eccezioni con un messaggio di errore significativo in caso di input non validi (una IllegalArgumentException va bene, ma assicurati che il messaggio abbia senso!)
  • Per qualsiasi funzione che convalida i loro argomenti, è necessario scrivere test JUnit con input non validi e verificare che venga generata un'eccezione (questo è effettivamente un test preliminare)
  • Scrivi un metodo validate () per tutti gli oggetti personalizzati complessi che verificano lo stato / consistenza interni dell'oggetto e qualsiasi oggetto secondario composto. È possibile chiamare questo metodo durante il test o in fase di esecuzione per garantire che l'intera struttura sia valida. In effetti si tratta di un controllo invariante su una struttura dati.
  • Usa gli asserti all'interno delle funzioni per testare gli invarianti durante l'esecuzione. Questi possono essere costosi, quindi ha senso utilizzare gli asserimenti in modo che i controlli non vengano applicati nel codice di produzione, ma questi controlli sono molto preziosi durante il test e il debug. Ricorda che le tue risorse dovrebbero anche essere utilizzate durante l'esecuzione della suite di test automatizzata JUnit, quindi dovresti rilevare la maggior parte degli errori logici durante lo sviluppo.
risposta data 07.05.2012 - 16:55
fonte

Leggi altre domande sui tag