Scrittura di test basati sui riflessi basati sui dati per garantire la completezza del progetto [chiuso]

-1

Quando scrivo software, sono spesso costretto a prendere una decisione che implica un modello di design di nomi e modelli comportamentali "per convenzione". Questo di solito mi fa sentire un po 'magro come uno sviluppatore .NET perché quasi tutto è tipizzato staticamente (probabilmente anche il tipo dinamico è tipizzato staticamente, ma altri lo hanno ben trattato, leggi i loro blog, ti ringrazieranno per questo.)

Naturalmente ho incontrato altri con punti di vista opposti che ritenevano che in molti casi la denominazione e gli schemi comportamentali basati su convenzioni fossero effettivamente utili in quanto consentono un codice più pulito, più leggibile e più coerente. È stato persino affermato che, a seconda di quanto tale convenzione viene adottata, ad esempio in uno scenario di comportamento determinato dal nome di riflessione del tipo, potrebbe persino applicare una buona denominazione interrompendo la funzionalità se si effettua il naming in modo incoerente con le convenzioni stabilite.

Tutto questo mi ha portato nel luogo in cui l'amore e la passione per lo sviluppo vanno a morire, "Testing". Ho trovato la seguente ipotesi:

Using naming conventions and associated behavioral or structural rules associated with those conventions, it should be possible to write tests for the product that enforce that behaviors and structures associated with names are implemented correctly by reflecting the available target binaries. Furthermore it should also be possible to enforce a by convention design that doesn't allow for the misuse of naming conventions by means of having names that fall under the naming conventions that don't follow those same behavioral or structural rules to be used inappropriately (i.e something with the word Locator in the type name that doesn't implement the service locator pattern.)

Qualcuno ha mai studiato questo tipo di test e prove di architettura e design? Quali sono state le tue esperienze con la scrittura di test di architettura e convention? Quali sfide hai affrontato e quali soluzioni hai escogitato? Ci sono quadri o strumenti per fare questo? C'è una ricerca sull'argomento che è stata sottoposta a peer review?

    
posta Daniel Green 17.05.2013 - 20:51
fonte

1 risposta

2

Sì, sarebbe fantastico in teoria ...

In effetti, la denominazione degli schemi di progettazione migliora la leggibilità. Questo è in realtà l'obiettivo degli schemi di progettazione in primo luogo. È molto più semplice dire:

I used an abstract factory, but maybe we should start switching to a builder for more flexibility.

al tuo collega quando spieghi la struttura del tuo codice, piuttosto che:

I made a parent class which is inherited by a few other classes, given that each of those classes have an intent to create complex objects; now, we should start creating those objects by calling different methods which will progressively extend each object, because it will allow us to customize the way we extend them depending on the circumstances.

La prima versione è chiara (a meno che la persona con cui parli non abbia idea di cosa sia una fabbrica o un costruttore). La seconda versione è difficile da capire ed è soggetta a interpretazione.

Anche l'applicazione delle convenzioni di denominazione per i modelli di progettazione è utile. Ciò consentirebbe ai principianti di essere abituati più rapidamente a tali modelli. L'apprendimento e l'applicazione di schemi di progettazione è difficile e l'aiuto di uno strumento di controllo statico migliorerebbe notevolmente la curva di apprendimento. Se hai provato ad implementare un wrapper, ma invece hai creato un adattatore, lo strumento di controllo statico ti mostrerà l'errore, con un punto bonus che ti dice che stai effettivamente utilizzando un adattatore.

... ma è difficile da fare in pratica

Quindi, puoi applicare le convenzioni di denominazione per i modelli di progettazione in pratica?

Non ne sono così sicuro. Ecco alcuni motivi:

  1. Un modello di design è facile da capire per un essere umano, ma non per una macchina. Non è come una regola severa come "Dovresti sempre racchiudere gli oggetti che implementano IDisposable in using " : tale affermazione è facile da controllare per un'applicazione come l'analisi FxCop / Code. Un modello di design è ... beh, un modello. Non ha una struttura rigida; ci sono diversi modi per implementarlo, mentre anche le più piccole modifiche possono destabilizzare un controllore statico.

    Ad esempio, prendi un modello di strategia. Al di fuori di un semplice esempio accademico, il controllore statico avrebbe difficoltà a sapere se il modello è usato o meno. Esempio:

    /// <param name="combine">A function which takes two consecutive entries and combines
    /// them into a single entry to print.</param>
    public void GeneratePdf(
        Consignee consignee,
        IEnumerable<Entry> entries,
        Func<Entry, Entry, ComplexEntry> combine)
    {
    }
    

    Il comportamento può essere commutato in fase di esecuzione utilizzando una funzione diversa come argomento del parametro combine . Questo non significa che questo è un modello di strategia. Forse per combinare diverse voci, dovrebbero essere utilizzate alcune tecniche avanzate, quelle tecniche che sono contenute nella libreria del chiamante, quindi è impossibile utilizzarle da quella chiamata, a causa delle dipendenze circolari.

  2. Allo stesso modo, le definizioni non sono abbastanza severe.

    La regola IDisposable sopra è estremamente severa. Hai un oggetto con un'interfaccia specifica? O lo metti dentro un using , e la regola sarà soddisfatta, oppure no. La maggior parte delle regole (così come quella con IDisposable ) hanno eccezioni, ma quelle eccezioni sono anche estremamente rigide e precise.

    I modelli di progettazione, d'altra parte, hanno definizioni, ma queste definizioni possono essere piegate per adattarsi a situazioni diverse. Ad esempio, un campo static readonly sarebbe un singleton? Che dire di una proprietà con un campo di appoggio e una serratura? Queste due situazioni sono radicalmente diverse e, tuttavia, possono rappresentare un singleton.

    Immagina quanto sarebbe difficile verificare se qualcosa è un adattatore o un'interfaccia fluente. Ad esempio, qualsiasi metodo di una classe che restituisce un'istanza della classe stessa è considerato un'interfaccia fluente?

  3. Il controllo statico è usato principalmente dagli sviluppatori che conoscono il loro lavoro. Per lo più non hanno bisogno di uno strumento che indichi che stanno usando la parola chiave Strategy , ma non utilizzano un modello di strategia. O stanno effettivamente usando un modello di strategia, e il controllo statico è sbagliato, o stanno consigliando consapevolmente la classe / metodo in questo modo, senza alcun intento di usare un modello di strategia reale.

    I principianti, cioè le persone che possono trarre beneficio da un controllore statico, non lo userebbero, perché non sanno usare pedine statiche, e anche se lo sanno, vedono tali strumenti più come un disturbo, un cosa fastidiosa che li infastidisce con un sacco di avvertimenti difficili da capire.

Per concludere, applicare le convenzioni di denominazione per i modelli di progettazione è un compito difficile e molto probabilmente fornirebbe molti falsi positivi e falsi negativi. Non sarà molto utile, ma potrebbe essere molto fastidioso.

A proposito, c'è una sorta di checker statici molto intelligenti: i tuoi pari. Se qualcuno abusa di uno schema di progettazione, verrà evidenziato durante una revisione del codice. I checker statici sono eccellenti per eseguire operazioni ripetitive di base, come controllare la conformità del codice a regole severe. Tieni questo controllo di base per loro, mentre le scelte che richiedono di pensare e prendere decisioni rimarranno un compito degli sviluppatori che controllano il codice durante una revisione del codice.

    
risposta data 17.05.2013 - 21:52
fonte

Leggi altre domande sui tag