È una buona idea documentare ogni ipotesi nel codice, anche se va contro lo standard della lingua?

7

Per esempio, questa funzione di c ++ sarebbe una buona idea?

void doSomething(not_nullptr<MyType> arg)
{
    // stuff
}

Poiché not_tullptr è un wrapper di template per i puntatori, genererà un'eccezione se a esso viene mai assegnato un valore nullo. Ha il vantaggio di trovare errori veloci e documenta chiaramente le ipotesi fatte direttamente nel prototipo della funzione.

Il modo tradizionale di fare qualcosa di simile sarebbe:

void doSomething(MyType* arg)
{
    assert(arg != nullptr);
    // stuff
}

Questo metodo raggiunge l'obiettivo di trovare rapidamente errori nulli. Ma di per sé non documenta questa ipotesi nel prototipo. Quindi la mia domanda è: l'idea è al di sopra di una buona? Non è il modo standard di fare cose nel c ++ e potrebbe ovviamente essere esteso ad altre ipotesi.

    
posta OnePie 25.02.2016 - 23:00
fonte

4 risposte

8

Tutto ha un costo, anche se non viene misurato nelle prestazioni di runtime.

Codificare tali ipotesi nel sistema di tipi sembra una buona idea. Ma non è senza i suoi difetti. In particolare, richiede di avere e utilizzare una serie di tipi sempre più specifici per ipotesi sempre più specifiche.

Diciamo che hai una funzione che prende una matrice dall'utente e modifica i primi tre elementi in essa contenuti. Ora, questa funzione fa due presupposti: che in realtà c'è una matrice e che la matrice ha almeno 3 elementi lunghi.

Ci sono tipi che possono codificare entrambi questi presupposti. Il tipo di libreria di supporto delle linee guida span può coprire entrambi. Ma guarda il codice per quel tipo. Se non fosse disponibile, probabilmente non lo scriverebbe da solo.

Più supposizioni di questo tipo hai, e più casi speciali ottengono, più difficile è scrivere un tipo solo per loro. Dopotutto, span risolve solo questo particolare problema come un sottoprodotto parziale di risolvere il suo problema reale : avere un modo per rappresentare una matrice di alcune dimensioni.

Quindi è un atto di bilanciamento. Non vuoi passare più tempo a scrivere tipi di casi speciali, ma ne hai bisogno per coprire molte basi. Dove esattamente si disegna la linea dipende dalle proprie esigenze, ma non credo che sia utile provare a codificare tutto nel sistema di tipi.

Inoltre, avendo contratti come parte di C ++, quali persone stanno lavorando on (PDF) , sarebbe in grado di colmare il divario qui in molti dei casi speciali.

C'è anche il problema di trattare combinazioni di tali contratti. Il contratto not_null è generalmente una buona idea, ma per sua stessa natura non può funzionare con i tipi solo di spostamento che lasciano l'oggetto spostato da null. Pertanto, not_null<unique_ptr<T>> non è un tipo funzionale.

Ancora una volta, non è detto che non dovresti avere questi. Ma hai davvero bisogno di pensare a quando è veramente appropriato avere un tipo che incapsula un contratto e quando non lo è.

    
risposta data 26.02.2016 - 02:23
fonte
3

For instance, would this c++ function be a good idea?

Sì. Questa è una buona idea, che la libreria di supporto delle linee guida contenga un'implementazione di esso.

(Il nome del modello è gsl::not_null<T*> ).

    
risposta data 03.03.2016 - 13:24
fonte
2

Non so se questo particolare esempio sia standard in C ++, ma sì è una buona idea.

Diverse lingue hanno vari modi di gestire il controllo dei null, alcuni di essi consentono di eseguire alcuni controlli Null in fase di compilazione.

Ogni volta che puoi controllare o forzare qualcosa al momento della compilazione, è un grande vantaggio. Il sistema dei tipi è un ottimo modo per farlo, ed è live (rimane aggiornato, o non è obsoleto come può fare la documentazione) e praticamente auto-documentante (è chiaro che o dove alcuni tipi specifici è necessario)!

[Un modo per pensare al sistema dei tipi e compilare il controllo del tempo è che funzionino per prevenire stati di programmi illegali (e inaspettati).

Alcune lingue hanno una capacità opzionale o "forse". Swift, un linguaggio moderno di Apple ha un tale costrutto e incoraggia l'analisi nulla in fase di compilazione. Queste funzionalità richiedono il controllo di null prima dell'uso. Se ricordo correttamente, i tipi di riferimento agli oggetti non possono essere nulli in Swift; devi usare la funzione opzionale per avere anche un riferimento null. Penso che altre lingue lo avrebbero fatto se avessero avuto il vantaggio della preveggenza (anche Haskell lo fa, con il suo "forse").

Ciò che stai proponendo va nell'altro senso (quando si imposta), che è grandioso, se appropriato!

    
risposta data 25.02.2016 - 23:05
fonte
0

No, non va bene.

Il modo migliore per testare il codice a vari livelli e utilizzare i riferimenti, anziché i puntatori non elaborati.

    
risposta data 26.02.2016 - 09:44
fonte

Leggi altre domande sui tag