Difesa per boilerplate?

14

Per me, il codice boilerplate è ovviamente negativo. Tuttavia ho incontrato uno sviluppatore che mostra resistenza nel tentativo di ridurre la piastra di riscaldamento. Mi sono reso conto che non avevo una discussione ben formata, ben pensata, oltre l'avversione che ho sviluppato nel tempo.

In modo che io possa formulare un argomento convincente per favorire un minore standard, quali sono i controsensi? In altre parole, quali sono gli argomenti (se esistono) a favore di boilerplate?

(Voglio dire, quello che penso è generalmente inteso da boilerplate, ma un buon esempio sono getter e setter in Java.)

    
posta abstracted 14.05.2012 - 20:52
fonte

7 risposte

12

Una cosa importante da ricordare è che il codice viene generalmente ridotto rimuovendo il contesto non necessario. Se il compilatore può capire qualcosa, l'argomento va, non c'è bisogno di scriverlo esplicitamente.

E sarebbe bello se solo il compilatore avesse mai avuto intenzione di leggerlo. Ma ricorda che "i programmi dovrebbero essere scritti affinché le persone possano leggere, e solo incidentalmente per le macchine da eseguire". (Ironicamente, questa citazione arriva da un libro di testo dedicato a una delle lingue più difficili da leggere per gli esseri umani ordinari, dovuto in gran parte alla sua eccessiva severità.)

Ciò che potrebbe sembrare noioso e ripetitivo è quello che stai scrivendo perché può essere un contesto di valore per qualcun altro che arriva dopo un anno (o cinque) e deve mantenere il tuo codice.

WRT l'esempio di Java in particolare, sono d'accordo sul fatto che questo è un buon esempio di brutta norma, dal momento che può essere sostituito da qualcosa che sia più breve e più facile da leggere e anche più flessibile: Proprietà . Ma ciò non significa che tutti gli elementi sintattici standardizzati di tutte le lingue siano tanto dispendiosi quanto i getter ei setter di Java e C ++.

    
risposta data 14.05.2012 - 21:05
fonte
7

Un argomento a favore del codice boilerplate è che se lo si modifica in un punto, influisce solo su un flusso del codice. Questo deve essere bilanciato dal fatto che più spesso che volere, in realtà una modifica influisce su ogni pezzo di codice che la usa. Ma ho visto esempi rari che supportano l'argomento.

Supponiamo che tu abbia un pezzo di codice che dice

public ForTheBar(Foo foo)
{
    Bar bar = foo.bar();
    return bar.BeFooed();
}

Questo è usato in circa 2 posizioni nel tuo codice.

Un giorno arriva qualcuno e dice "ok, solo in questo percorso, vogliamo che tu Grommit la barra prima di spillarlo."

E tu pensi "bene questo è semplice."

public ForTheBar(Foo foo, bool shouldIGrommit)
{
    Bar bar = foo.bar();

    if (shouldIGrommit)
    {
        bar.BeGrommitted();
    }

    return bar.BeFooed();
}

Quindi il tuo utente aggiunge alcune nuove funzionalità e pensi che si adatti bene a FooTheBar. E tu, doverosamente, chiedi loro se dovresti Grommit quel bar prima di Foo e loro dicono "no, non questa volta".

Quindi chiami semplicemente il metodo sopra.

Ma poi il tuo utente dice "ok, aspetta, nel terzo caso, vogliamo che tu scarti la barra prima di chiamare BeFooed."

Nessun problema, pensi, posso farlo.

public ForTheBar(Foo foo, bool shouldIGrommit, bool shouldIDoodle)
{
    Bar bar = foo.bar();

    if (shouldIGrommit)
    {
        bar.BeGrommitted();
    }

    if (shouldIDoodle)
    {
        bar.BeDoodled();
    }

    return bar.BeFooed();
}

Improvvisamente il tuo codice sta diventando meno essenziale. Forse avresti dovuto accettare le due righe di codice ripetute. Ormai avresti tre pezzi di codice, ciascuno lungo 2-3 linee e non sembra più molto ripetuto.

Tutto ciò detto, vorrei ribattere che con "questo non è un caso comune, e quando succede, puoi refactoring".

Un altro argomento che ho sentito di recente è che il codice boilerplate può talvolta aiutarti a navigare nel codice. L'esempio di cui stavamo discutendo era il punto in cui avevamo rimosso tonnellate di codice di mappatura boilerplate e l'abbiamo sostituito con AutoMapper. Ora, è stato discusso, perché tutto è basato sulla convenzione, non è possibile dire "Dove è questa proprietà impostata", all'IDE e aspettarsi che lo sappia.

Ho visto persone discutere argomenti simili sui contenitori IoC.

Per non dire che sono d'accordo con loro, ma è comunque un argomento equo.

    
risposta data 14.05.2012 - 21:46
fonte
6

L'evoluzione dell'efficienza

Inizi con questo:

<p>
    <label for="field">My field</label>
    <input type="text" id="field">
</p>

quindi ti sbarazzi di tutta quella fastidiosa caldaia e la metti in una funzione:

  1. createFieldHtml( id, label )

    questo è buono, mi sto risparmiando così tante righe!

  2. createFieldHtml( id, label, defaultValue )

    Sì, ho bisogno anche di un valore predefinito, che è stato facile aggiungere.

  3. createFieldHtml( id, label, defaultValue, type )

    bello, adesso posso usarlo anche per le caselle

  4. createFieldHtml( id, label, defaultValue, type, labelFirst )

    Il progettista UX ha detto che l'etichetta deve essere dopo la casella di controllo.

  5. createFieldHtml( id, label, defaultValue, type, labelFirst, isDate )

    ora esegue il rendering di un selezionatore di date quando necessario. Hm .. i parametri stanno diventando un po 'fuori mano

  6. createFieldHtml( id, label, defaultValue, type, labelFirst, isDate, containerCssClasses )

    c'era questo caso in cui ho bisogno di aggiungere le classi CSS

  7. createFieldHtml( id, label, defaultValue, type, labelFirst, isDate, containerCssClasses, fieldCssClasses, disabled, clearAfter, helpText, uploadPath )

    aaaaaaaaaaaaaaaaaaaaa

In difesa del boilerplate

Mi diverto a metterlo in parole perché è qualcosa che ho notato solo di recente, quindi creerò un elenco:

  1. Mi sembra che ci sia una certa paura di avere linee duplicate che si allungano un po '. Se sono solo poche righe potrebbe non essere affatto un problema. alcune cose sono intrinsecamente "quasi ripetitive" (come nell'esempio sopra). Vedo poche possibilità di ottimizzarlo a lungo termine.
  2. Le persone amano incapsulare la funzionalità da qualche parte; se guardi obiettivamente e sembra che stia solo "nascondendo il casino" - sii sospettoso! potrebbe essere il momento per qualche buona vecchia scheda tecnica
  3. Quando hai una funzione che diventa sempre più potente; che prende molti percorsi di esecuzione diversi a seconda dell'input e in definitiva fa molto poco - potrebbe essere il tempo di caldaia!
  4. Quando aggiungi uno strato di astrazione sopra un altro livello di astrazione, ma solo per rendere il tuo codice più corto (il livello sottostante non è destinato a essere modificato) - tempo standardizzato!
  5. Quando hai una funzione che richiede così tanti parametri che hai bisogno di avere parametri con nome - forse è l'orario di partenza.

Una cosa che di recente mi chiedo sempre è questa:
Posso copiare e incollare in un altro progetto senza modificare nulla? se sì, va bene incapsulare o mettere in una biblioteca, se no: è il tempo di un boilerplate.

Questo è molto contrario alla percezione generale che il boilerplate sia copiato e copi il codice. Per me il boilerplate riguarda la copia e l'incolla, ma deve sempre essere ritoccata un pochino.

Aggiornamento : ho appena trovato un articolo che riporta il mio esempio sopra un nome effettivo: "troppo DRY anti-pattern".

The function gets more parameters and has increasingly complex internal logic to control its behavior in different cases. Too DRY functions are easy to spot. They have lots of intricate if-then logic that try to address a wide diversity of usage. [...] Also, repeating code isn’t always a bad thing if the code is small and performs a discrete function.

È una lettura breve e interessante, puoi trovare l'articolo qui: Anti-Pattern troppo secco

    
risposta data 15.05.2012 - 04:04
fonte
4

I disprezzo codice boilerplate, ma essere in grado di rimuovere il codice boilerplate non significa sempre che è il modo migliore per andare.

Il framework WPF ha proprietà di dipendenza , che implica una quantità folle di codice boilerplate. Durante il mio tempo libero ho studiato una soluzione che riduce notevolmente l'importo di codice che deve essere scritto. Più di un anno dopo sto ancora migliorando questa soluzione , e ho ancora bisogno di estendere sulla sua funzionalità o bug di correzione.

Qual è il problema? Questo è ottimo per imparare nuove cose ed esplorare soluzioni alternative, ma probabilmente non è la migliore decisione commerciale .

Il framework WPF è ben documentato. correttamente documenta come scrivere il codice di riferimento. Cercare di rimuovere questo codice è un buon esercizio e qualcosa che vale sicuramente la pena esplorare, ma raggiungere lo stesso livello di "lucidatura" delle offerte msdn richiede molto tempo, cosa che non sempre è possibile.

    
risposta data 14.05.2012 - 21:34
fonte
1

Il problema con boilerplate è che viola DRY. In sostanza, quando si scrive lo standard, si sta ripetendo lo stesso codice (o codice molto simile) su un certo numero di classi. Quando quel codice deve essere cambiato, non è affatto certo che lo sviluppatore ricorderà tutte le posizioni che il codice è stato ripetuto. Ciò porta a bug in cui vengono utilizzate vecchie API o vecchi metodi.

Se ridicherai lo standard in una biblioteca comune o in una classe genitore, dovrai modificare il codice in un unico posto solo quando la tua API cambia. Ancora più importante, quando si verificano cambiamenti imprevisti, il codice si rompe in un posto e ti consente di sapere esattamente cosa devi correggere per far funzionare di nuovo tutto. Questo è di gran lunga preferibile a uno scenario in cui un cambiamento causa guasti a dozzine o addirittura a centinaia di classi.

    
risposta data 14.05.2012 - 21:15
fonte
0

Avrò un tatto diverso. La coerenza nello sviluppo è una delle caratteristiche più importanti della progettazione del software, è uno strumento fondamentale per rendere le applicazioni estendibili e manutenibili ma può essere difficile da ottenere quando si gestisce un team su più siti, lingue e fusi orari.

Se raggiunto, la coerenza rende il codice molto più accessibile "una volta che ne hai visto uno, li hai visti tutti", molto meno costoso da mantenere e refactoring, ma soprattutto molto più facile da estendere. Quando scrivi una libreria che richiede alcuni standard, insieme alla potenza della tua libreria hai anche dato allo sviluppatore:

  • Un punto di partenza comprende il preambolo (standard) nella tua funzionalità, la maggior parte delle classi chiave e dei punti di accesso di solito sono presenti come parte del boilerplate. Questo dà agli sviluppatori un punto di partenza nella documentazione
  • Le aspettative che il posizionamento sugli sviluppatori diventerà evidente, ad esempio se imposti un oggetto di tracciamento come parte del preambolo, gli sviluppatori sapranno dove registrare le eccezioni e le informazioni
  • Comprensione implicita mentre costringi lo sviluppatore a passare attraverso il tuo processo di istanziazione delle classi, possono dedurre le tecniche di cui avranno bisogno per accedere al resto del tuo grimorio e avere l'opportunità di presentarle a qualsiasi convenzione tu abbia " usato in tutta la tua libreria
  • Facile convalida quando è necessario il codice boilerplate, in genere è in grado di convalidare facilmente se stesso con eccezioni e clausole di salvaguardia, impedendo ai consumatori di rimanere bloccati molto più avanti quando si è già impegnati in un processo difettoso
  • La configurazione di una libreria che richiede il codice boilerplate è facile in quanto esiste già un ovvio punto di implementazione per personalizzare la funzionalità per un singolo percorso di esecuzione. Ciò è particolarmente utile se il codice di codice di richiesta richiesto è migliorato con il modello di fabbrica o di comando

Quando i consumatori della tua biblioteca si occupano dell'istanza, possono facilmente creare metodi di private / extension, parent classi o persino modelli per implementare il codice boilerplate.

    
risposta data 05.12.2014 - 12:56
fonte
-3

L'unico vero problema con il codice boilerplate è che quando trovi un bug in esso devi correggere ovunque che lo hai usato piuttosto che nel posto in cui hai riutilizzato .

    
risposta data 14.05.2012 - 23:27
fonte