2009-04-13 11 views
7

Quali sono le migliori pratiche per la programmazione Design by Contract.Quali sono le migliori pratiche per la programmazione Design by Contract

Al college ho imparato la progettazione per contratto paradigma (in un ambiente OO) Abbiamo imparato tre modi per affrontare il problema:

1) Programmazione Totale: Copre tutti i possibili casi eccezionali nei suoi effetti (Matematica)

2) Programmazione nominale: Solo "promette" gli effetti giusti quando sono soddisfatte le condizioni preliminari. (Altrimenti l'effetto non è definito)

3) Programmazione difensiva: utilizzare le eccezioni per segnalare invocazioni illegali di metodi

Ora, ci siamo concentrati in diversi scenari OO sull'uso corretto in ogni situazione, ma non abbiamo imparato QUANDO usare QUELLO ... (Principalmente le tattiche in cui l'esercizio è eccitato ..)

Ora penso che sia molto molto strano che non abbia chiesto il mio insegnante (ma di nuovo, durante le lezioni, nessuno lo ha)

Personalmente, non uso mai nominale ora, e tendono a sostituire la precondizione s con eccezioni (quindi preferisco usare: lancia IllegalDivisionByZero, che affermare 'precondizione: il divisore dovrebbe differire da zero) e solo il totale del programma che ha senso (quindi non restituirei un valore convenzionale alla divisione per zero), ma questo metodo è semplicemente basato su risultati personali e mi piace.

quindi vi chiedo ragazzi:

Ci sono delle migliori pratiche ??

risposta

5

Non sapevo di questa divisione, e in realtà non riflette la mia esperienza.

La programmazione totale è praticamente impossibile. Non puoi garantire di coprire tutti i casi eccezionali. Quindi, in pratica si dovrebbe limitare la portata e respingere le situazioni che sono fuori del campo di applicazione (che è il ruolo dei pre-condizioni)

programmazione nominale non è desiderata. L'effetto indefinito dovrebbe essere vietato.

Programmazione difensiva è un must. Dovresti sempre segnalare le invocazioni illegali dei metodi.

Sono a favore della realizzazione di elementi di design completo per contratto, che è, in mie opinioni una versione pratico e affortable del Programmazione Total

Presupposti (una sorta di Programmazione difensiva) per segnalare l'invocazione illegale del metodo. Cerca di limitare il tuo ambito il più possibile in modo da poter semplificare il codice. Evita l'implementazione complessa, se possibile, restringendo leggermente l'ambito.

Postconditions per generare un errore se non si ottiene l'effetto desiderato. Anche se è colpa tua, devi avvisare il chiamante che ti sei perso il tuo obiettivo.

Invarianti per verificare che la coerenza dell'oggetto sia preservata.

+0

davvero come l'ovvia ma pertinente asserzione che limita l'ambito in modo da poter semplificare il codice ... consiglio eccellente! – Rob

1

Tutto si riduce a quali responsabilità si desidera assegnare al cliente e all'implementatore del contratto.

Nella programmazione difensiva si forza l'implementatore a verificare condizioni di errore che possono essere costose o addirittura impossibili in alcuni casi. Immagina un contratto specificato da binarySearch, ad esempio, l'array di input deve essere ordinato. non è possibile rilevarlo mentre si esegue l'algoritmo. devi fare un controllo manuale per questo, che in realtà farà saltare il tempo di esecuzione di un ordine di grandezza. sostenere la mia opinione su è la firma del metodo dal javadocs.

Un altro punto è Persone e quadri ora tendono a implementare meccanismi di traduzione eccezione che viene utilizzato principalmente per tradurre eccezioni controllate (stile difensivo) a runtime eccezioni che sarà solo pop-up se succede qualcosa di sbagliato. in questo modo il cliente e l'esecutore del contratto hanno meno preoccupazioni mentre si trattano l'un l'altro.

Anche in questo caso la mia opinione personale è supportata solo dalla mia esperienza limitata, mi piacerebbe saperne di più su questo argomento.

+0

È possibile controllare che l'array sia ordinato come precondizione. Facciamo questo nel C++ con asserzioni. –

+0

controllare che l'intero array sia ordinato richiede più tempo rispetto a fare effettivamente una ricerca binaria in esso :) – MahdeTo

+0

Solo alcuni pensieri: è possibile verificare le condizioni preliminari solo in determinate modalità, ad esempio per l'unittest no? Inoltre, una precondizione può essere appena enunciata e non testata, ovviamente – Peter

1

... ma non abbiamo ancora imparato quando di uso che ...

penso che la migliore pratica è di essere "come difesa il più possibile". Fai il tuo runtime controlla se puoi. Come @MahdeTo ha menzionato a volte è impossibile per motivi di prestazioni; in tali casi ricorrere a comportamenti indefiniti o insoddisfacenti.

Detto questo, essere esplicito nella documentazione su cosa ha i controlli di runtime e cosa no.

0

Come gran parte del calcolo "dipende" è probabilmente la risposta migliore.

La progettazione per contratto/programmazione per contratto può aiutare notevolmente lo sviluppo documentando esplicitamente le condizioni di una funzione. Solo la documentazione può essere di aiuto senza nemmeno inserirla nel codice (compilato).

Dove possibile, raccomando difensivo - controllando ogni condizione. MA solo per build di sviluppo e debug. In questo modo le ipotesi non valide vengono catturate quando le condizioni sono interrotte. Un buon sistema di compilazione consente di attivare e disattivare i diversi tipi di condizione a livello di modulo o di file, nonché a livello globale.

Le azioni eseguite nelle versioni di rilascio del software dipendono quindi dal sistema e da come viene attivata la condizione (solita distinzione tra interfacce esterne e interne). La versione di rilascio potrebbe essere "programmazione totale" - tutte le condizioni danno un risultato definito (che può includere errori o NaN)

Per me "programmazione nominale" è un vicolo cieco nel mondo reale. Presumi che se hai inserito i giusti valori in (che ovviamente hai fatto), allora il valore che ricevi è buono. Se la tua ipotesi era sbagliata, ti abbatti.

0

Penso che la programmazione guidata dai test sia la risposta. Prima di implementare il modulo, devi prima creare un test unitario (chiamalo un contratto). Quindi implementa gradualmente la funzionalità e assicurati che il contratto sia ancora valido. Di solito comincio con mozziconi e mockup semplici, poi gradualmente riempio il resto sostituendo le pugnalate con cose reali. Continua a migliorare e rendere il test più forte. Alla fine si finisce con una solida implementazione di detto modulo oltre a un fantastico letto di prova - implementazione codificata del contratto. Più tardi, se qualcuno modifica il modulo, prima vedi se può ancora adattarsi al banco di prova. In caso contrario, il contratto è rotto - respingere le modifiche. Oppure, il contratto è obsoleto, - risolvere i test unitari. E così via .. Ciclo noioso dello sviluppo del software :)

+0

Sebbene sia una buona idea, non penso che risponda alla domanda. Non è possibile scrivere test per valori non validi se non si è deciso in che modo il sistema deve rispondere prima a valori non validi. – Mark

+0

@ Marco Non puoi. Quindi, 1) decidere, 2) iniziare a scrivere test per la maggior parte dei valori non validi di base 3) quando il test fallisce a causa di codice mancante, codice iterate fino a test pass, 4) test refactoring e codice di produzione 5) decidere il prossimo valore non valido e fare un altro rosso -green-refactor iterazione fino a quando non si esauriscono possibili gruppi di valori non validi per testare e quindi iniziare a scrivere test per casi felici, iniziando con la maggior parte di base, come consigli di Uncle Bob :) – Tom

+0

@Tom Questo è solo più spiegazione di TDD e ancora non lo è rispondi alla domanda. Si tratta di scegliere tra approcci per Design by Contract. Devi scegliere l'approccio prima di poter scrivere i test. Ad esempio, se si sceglie il valore nominale, utilizzando la definizione nella domanda, non si verificheranno affatto i valori non validi. – Mark

Problemi correlati