La "convenzione sulla configurazione" non viola i principi di base della programmazione?


51

Stavo guardando il framework WPF MVVM Caliburn.Micro e ho letto che molte cose standard sono basate su convenzioni di denominazione .

Ad esempio, l'associazione automatica delle proprietà in Visualizza alle proprietà in ViewModel. Anche se questo sembra essere conveniente (rimuove un po 'di codice boilerplate), la mia prima reazione istintiva è che non è del tutto ovvio per un nuovo programmatore che leggerà questo codice. In altre parole, la funzionalità dell'applicazione non è completamente spiegata dal proprio codice, ma anche dalla documentazione del framework.

MODIFICARE:

Quindi questo approccio è chiamato convenzione sulla configurazione. Dal momento che non sono riuscito a trovare alcuna domanda al riguardo, ho modificato la mia domanda:

La mia domanda è:

La convenzione sulla configurazione è un modo corretto di semplificare le cose o viola alcuni principi di programmazione (e se sì, quali)?


8
La maggior parte degli approcci / principi viola in qualche modo alcuni altri approcci / principi. È principalmente una questione di priorità e compromessi.
Joachim Sauer,

1
Vero, ma trovo la differenza dichiarata nella mia domanda un po 'strana, e quindi sono interessato agli specifici compromessi e ai principi eventualmente violati quando si usa la convenzione sulla configurazione.
Geerten,

Il concetto di tracciabilità del software è rilevante qui. I programmatori si affidano a strumenti come grep, ma hanno bisogno di strumenti migliori per rintracciare gli usi del codice generato. Ad esempio, gli strumenti dovrebbero rendere più esplicito che la classe css "id-utente" è correlata al metodo generato getUserId () e alla colonna della tabella user_id.
Macneil,

Risposte:


49

Non ritengo che "un'applicazione dovrebbe essere spiegata integralmente con il proprio codice" un principio di programmazione fondamentale. Ci sono molte cose che non sono spiegate semplicemente guardando il codice di un'applicazione. Oltre a conoscere le cose di base del linguaggio di programmazione stesso (sintassi e semantica), è necessario conoscere le convenzioni. Se un identificatore in Java inizia con una lettera maiuscola, è un tipo. Ci sono molte di queste convenzioni che devi conoscere.

La convenzione sulla configurazione riguarda la riduzione della quantità di decisioni che il programmatore deve prendere sulle cose. Per alcune cose questo è ovvio - nessuno prenderebbe in considerazione di avere un linguaggio in cui la capitalizzazione dei tipi è qualcosa che devi dichiarare all'inizio del tuo programma - ma per altre cose non è così ovvio.

Equilibrare le convenzioni e la configurazione è un compito difficile. Troppa convenzione può creare confusione nel codice (ad esempio, prendere le variabili implicite di Perl). Troppa libertà da parte del programmatore può rendere i sistemi difficili da comprendere, poiché le conoscenze acquisite da un sistema sono raramente utili quando si studia un altro.

Un buon esempio di dove la convenzione aiuta il programmatore è quando si scrivono plugin Eclipse. Quando guardo un plugin che non ho mai visto, conosco immediatamente molte cose al riguardo. L'elenco delle dipendenze è in MANIFEST.MF, i punti di estensione sono in plugin.xml, il codice sorgente è in "src" e così via. Se queste cose spettassero al programmatore definire, ogni singolo plugin Eclipse sarebbe diverso e la navigazione del codice sarebbe molto più difficile.


4
+1: lo sviluppo del software è abbastanza complicato così com'è. Se riesci a evitare la complessità delle cose di cui hai il controllo, fallo. Salva la complessità per i luoghi di cui hai assolutamente bisogno.
scrwtp,

1
Grazie per la chiara spiegazione della differenza e dell'equilibrio.
Geerten,

3
"Se un identificatore in Java inizia con una lettera maiuscola, è un tipo." - se si tratta di un tipo dipende dal contesto della sintassi e non dal modello di denominazione, le convenzioni di denominazione Java non influiscono sulla "configurazione della compilazione". Sei sicuro che sia un esempio valido? Anche l'ultimo esempio non è corretto: si tratta di "convenzioni di configurazione" e non di "convenzione sulla configurazione". Stai dicendo cose giuste ma hanno poco a che fare con il principio subj.
Den,

4
Non analizzare troppo gli esempi, sono solo esempi. Il primo è solo un esempio di una convenzione, l'ultimo è un esempio in cui la convenzione è una buona cosa. L'esempio Perl è un esempio in cui troppe convenzioni (implicite) sono una cosa negativa (IMO, dovrei aggiungere).
Jesper,

1
La cosa che odio è quando la convenzione sulla configurazione diventa convenzione senza configurazione ... in quest'ultimo caso tendi a rimanere intrappolato con una base di codice può essere difficile integrarlo con altri strumenti.
Andy,

77

Hai dato +1 a @JesperE e ti piacerebbe aggiungere qualcosa:

sta violando alcuni principi di programmazione

Sì, "convenzione sulla configurazione" viola il principio "esplicito è meglio che implicito" (dai un'occhiata, per esempio, a "Zen-Of-Python" ).

D'altra parte, l'opposto "configurazione su convenzione" tende a violare "Semplice è meglio che complesso" e, peggio ancora, viola il principio DRY in modo sottile, poiché è necessario ripetere i nomi utilizzati nel codice anche nella configurazione .


4
Questa è la risposta più diretta alla domanda!
Joachim Sauer,

Questa è la risposta corretta effettiva tra i due più votati.
Den

+1 per "esplicito è meglio che implicito"
Justin Ohms,

12
La mia parte preferita di questa risposta è che evidenzia implicitamente la realtà che spesso i principi di un buon sviluppo software sono in tensione l'uno con l'altro. L'ingegneria consiste nel bilanciare quelle tensioni in modo appropriato per il tuo specifico contesto e applicazione.
Chris Krycho,

Buona risposta. Per espandere il commento di @Chris Krycho, la cosa bella degli standard o dei principi del software è che hai così tanti tra cui scegliere. :-)
user949300

9

Alcune delle "convenzioni sulla configurazione" si riducono a valori predefiniti sensibili. Dovresti solo configurare qualcosa per usarlo per uno scopo non standard. Devo confrontare Struts con Rails qui. In Rails, devi mettere le tue "azioni / schermate" in una cartella e poi funzionano. In Struts, devi ancora metterli in una cartella, ma devi anche trovare un nome-azione E un file JSP E un nome di modulo E un bean di modulo E specificare come queste tre cose funzionano insieme in Struts-config. xml AND specifica che il modulo appartiene alla richiesta (RESTful). Se ciò non bastasse, la mappatura form / form-bean ha una sua sezione in Struts-config che viene quindi mappata indipendentemente alla sezione action nello stesso file e tutto si basa su stringhe scritte a mano nel file JSP per funzionare propriamente. Per ogni schermo, sono almeno 6 le cose che non dovresti fare e tante opportunità per fare un errore. Penso che puoi impostare la maggior parte o tutte queste cose manualmente in Rails, se necessario, ma i 2/3 del tempo di sviluppo di Struts sono occupati per costruire e mantenere livelli di complessità non necessari.

In tutta onestà, Struts 1 è stato progettato quando le persone eseguivano il porting delle applicazioni tra desktop e Web. La flessibilità offerta da Struts lo rende adatto a tutto ciò che fa Rails, oltre a tutto ciò di cui un'applicazione desktop avrebbe bisogno. Sfortunatamente, la montagna di configurazione che consente tale flessibilità è una grande palla a sfera per qualcuno che ha solo bisogno di scrivere un'app Web o solo un'app desktop.

Ho lavorato da qualche parte per fare il passo successivo e ho discusso "Configurazione su codice ", ma visto che è arrivato al suo estremo logico, il risultato è che la configurazione diventa un nuovo linguaggio di codifica. Era un gioco di conchiglie in cui la complessità veniva aggirata senza essere domata in modo significativo. E mi ha dato un apprezzamento per tutte le verifiche del tipo e altre reti di sicurezza di un linguaggio di programmazione ben progettato. Qualche formato di file di configurazione semi-cotto che esplode senza alcun messaggio di errore se aggiungi uno spazio o un apostrofo NON è un miglioramento rispetto a un linguaggio di programmazione di qualità che ha suite di strumenti di modifica e un compilatore di qualità scritto per esso.

Non riesco a immaginare che avere impostazioni predefinite sensibili violi i principi teorici sull'estensibilità e la modularità. Un programmatore di Ruby / Rails si accalcherebbe presto un poker caldo negli occhi piuttosto che passare a un framework come Struts 1 in cui tutte le configurazioni sono fatte esplicitamente in più file XML. Non sto discutendo di Rails vs. Struts IN GENERALE, ma quella convenzione può essere un enorme successo in termini di produttività. Queste due tecnologie sono il confronto più estremo del mondo reale che abbia mai incontrato.

Se lavori in Java, controlla Joshua Bloch, "Effective Java", elemento 2: "Considera un costruttore di fronte a molti parametri del costruttore" pagg. 11-16. Per la maggior parte degli scopi, alcuni parametri (configurazione) sono richiesti e alcuni sono facoltativi. L'idea di base è richiedere solo la configurazione necessaria e fare in modo che l'utente (che potrebbe essere un altro programma) specifichi opzioni aggiuntive in base alle esigenze. Ho ripulito un sacco di codice con questo modello un mese fa e brilla positivamente.


7

In altre parole, la funzionalità dell'applicazione non è completamente spiegata dal proprio codice, ma anche dalla documentazione del framework.

La funzionalità di un'applicazione che utilizza un framework dipende sempre dal framework, la convenzione sulla configurazione non fa differenza in questo senso.

Nella mia esperienza, la convenzione sulla configurazione non solo rende il codice più leggibile, ma riduce anche la possibilità di introdurre bug sottili (specialmente i copia-incolla-bachi).

Ad esempio, supponiamo che in alcuni framework A, l'evento FooBarattivi una chiamata a handleFooBar. In un altro framework B, questa correlazione è configurata da qualche parte in un file XML.

Quindi, in A, è semplicemente

handleFooBar() {
   ...
}

e, a meno che tu non abbia scritto male FooBar, verrà chiamato ogni volta che accade FooBar.

In B, è di nuovo

handleFooBar() {
   ...
}

ma anche

<eventconfiguration>
  <event>
    <type>FooBar</type>
    <handler>handleFooBar</handler>
  </event>
</eventconfiguration>

Con centinaia di cose da configurare in questo modo, è fin troppo facile creare accidentalmente un bug sottile come

<eventconfiguration>
  <event>
    <type>BarFoo</type>
    <handler>handleFooBar</handler>
  </event>
</eventconfiguration>

perché dopo aver incollato la copia, abbiamo solo cambiato, <type>ma ci siamo dimenticati di cambiare <handler>.

Dato che quei file di configurazione sono grandi e monotoni, è meno probabile che qualcuno trovi il bug nella correzione di bozze di quanto troverebbe un bug simile nel codice del programma reale.


1
+1: evitare una configurazione ripetitiva, noiosa da scrivere, difficile da leggere, quasi sempre ovvia è il vantaggio principale della configurazione da convenzione.
Joachim Sauer,

-1

Potrebbe violare alcuni principi, ma allo stesso tempo obbedisce a uno dei principi di progettazione più fondamentali, SRP (Single Responsibility Principle).


2
L'uso delle convenzioni non ha nulla a che fare con la sola responsabilità. Potrei usare una convenzione e farci 100 cose.
Suamere,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.