In che modo la separazione di codice e dati è diventata una pratica?


29

Si prega di leggere attentamente la domanda: si chiede come , non perché .

Di recente ho trovato questa risposta , che suggerisce l'utilizzo di un database per archiviare dati immutabili:

Sembra che molti dei numeri magici che descrivi, in particolare se dipendono in parte, sono in realtà dati, non codice. [...] Può significare un database di tipo SQL o può semplicemente significare un file di testo formattato.

Mi sembra che se disponi di dati che fanno parte di ciò che fa il tuo programma, la cosa da fare è metterli nel programma . Ad esempio, se la funzione del tuo programma è contare le vocali, cosa c'è di sbagliato nell'avere vowels = "aeiou"in essa? Dopotutto, molte lingue hanno strutture di dati progettate proprio per questo uso. Perché dovresti preoccuparti di separare i dati inserendoli in un "file di testo formattato", come suggerito sopra? Perché non solo rendere quel file di testo formattato nel tuo linguaggio di programmazione preferito? Adesso è un database? O è un codice?

Sono sicuro che alcuni penseranno che questa sia una domanda stupida, ma lo faccio con tutta serietà. Sento che "codice e dati separati" stanno emergendo culturalmente come una sorta di verità evidente, insieme ad altre cose ovvie come "non dare alle variabili nomi fuorvianti" e "non evitare di usare spazi bianchi solo perché la tua lingua considera insignificante ".

Prendiamo ad esempio questo articolo: il problema con la separazione dei dati dal codice fantoccio . Il problema ? Che problema? Se Puppet è un linguaggio per descrivere la mia infrastruttura, perché non può anche descrivere che il nameserver è 8.8.8.8? Mi sembra che il problema non sia che codice e dati siano mescolati, 1 ma che Puppet manchi di strutture di dati sufficientemente ricche e di modi per interfacciarsi ad altre cose.

Trovo questo spostamento inquietante. La programmazione orientata agli oggetti diceva "Vogliamo strutture di dati arbitrariamente ricche" e quindi dotava le strutture di dati di poteri di codice. Di conseguenza ottieni incapsulamento e astrazione. Anche i database SQL hanno stored procedure. Quando sequestrate i dati in YAML o file di testo o database stupidi come se steste rimuovendo un tumore dal codice, perdete tutto ciò.

Qualcuno può spiegare come è nata questa pratica di separazione dei dati dal codice e dove sta andando? Qualcuno può citare le pubblicazioni dei luminari o fornire alcuni dati rilevanti che dimostrano "un codice separato dai dati" come un comandamento emergente e ne illustra l'origine?

1: se uno può persino fare tali distinzioni. Ti sto guardando, programmatori di Lisp.


5
Sentiti libero di seppellire tutto l'html e il CSS nella tua lingua preferita.
JeffO,

3
Penso che l'autore della citazione abbia voluto dire che i numeri magici non sono davvero immutabili.
Pieter B,

4
Non c'è niente di sbagliato nel codificare le vocali. Se la tua applicazione sarà sempre e solo utilizzata per contare le vocali in inglese.
Michael Paulukonis,

3
Un grande motivo tecnico per separare codice e dati è di non dover ricompilare il codice quando i dati cambiano. Pertanto, mi chiedo se si applichi nella stessa misura ai linguaggi di scripting.
user16764,

1
@MichaelPaulukonis: E inserirlo in un database è una soluzione falsa. Cambiamenti necessari per l'olandese? Zero (nemmeno una modifica del DB). Cambiamenti necessari per francese / tedesco? Almeno supporto ISO-8859-1. (Più di DB). Cambiamenti necessari per greco / russo? Supporto Unicode (più di DB). In effetti, non riesco a pensare a nessuna lingua in cui quel DB sia di alcun aiuto.
Saluti

Risposte:


22

Esistono molti buoni motivi per separare i dati dal codice e alcuni motivi per non farlo. Mi viene in mente quanto segue.

Tempestività. Quando è noto il valore dei dati? È al momento della scrittura del codice, quando viene compilato, collegato, rilasciato, concesso in licenza, configurato, avviato o durante l'esecuzione. Ad esempio, il numero di giorni in una settimana (7) è noto in anticipo, ma il tasso di cambio USD / AUD sarà noto abbastanza tardi.

Struttura. Si tratta di un singolo tempo di dati impostato in base a una singola considerazione o potrebbe essere ereditato o parte di una più ampia raccolta di articoli? Lingue come YAML e JSON consentono la combinazione di valore da più fonti. Forse alcune cose che inizialmente sembrano immutabili sono meglio rese accessibili come proprietà in un gestore della configurazione.

Località. Se tutti gli elementi di dati sono memorizzati in un numero limitato di posizioni, è molto più semplice gestirli, in particolare se alcuni potrebbero dover essere cambiati in nuovi valori (immutabili). La modifica del codice sorgente solo per modificare i valori dei dati introduce il rischio di modifiche e bug involontari.

Separazione degli interessi. Far funzionare correttamente gli algoritmi è meglio separarsi dalla considerazione di quali valori di dati usare. I dati sono necessari per testare gli algoritmi, non per farne parte. Vedi anche http://c2.com/cgi/wiki?ZeroOneInfinityRule .

In risposta alla tua domanda non è una novità. I principi fondamentali non sono cambiati in più di 30 anni e sono stati scritti più volte nel corso del tempo. Non ricordo grandi pubblicazioni sull'argomento in quanto generalmente non è considerato controverso, solo qualcosa da spiegare ai nuovi arrivati. C'è un po 'di più qui: http://c2.com/cgi/wiki?SeparationOfDataAndCode .

La mia esperienza personale è che l'importanza di questa separazione in un particolare software aumenta nel tempo, non di meno. I valori codificati vengono spostati in file di intestazione, i valori compilati vengono spostati in file di configurazione, i valori semplici diventano parte di strutture gerarchiche e gestite.

Per quanto riguarda le tendenze, non ho visto grandi cambiamenti nell'atteggiamento tra i programmatori professionisti (oltre 10 anni), ma l'industria è sempre più piena di giovani e molte cose che pensavo fossero conosciute e hanno deciso di continuare a essere sfidate e reinventate, a volte fuori dal nuovo intuizioni ma a volte per ignoranza.


2
Potresti approfondire la storia e le tendenze di questa pratica? Se tutti avessero dato queste considerazioni, non avrei posto la domanda. La premessa della domanda è che le persone non stanno valutando attentamente dove dovrebbero andare i loro dati (costanti compilate, database esterni, YAML ...) ma piuttosto pensano solo "CODICE E DATI MISTI MALE! HULK SMASH!" Perché o quando questo è diventato una cosa?
Phil Frost,

Non fa parte della mia esperienza, quindi non posso dirtelo. Ho aggiunto un paio di par alla mia risposta.
david.pfx,

Penso che "l'afflusso di giovani" sia una spiegazione valida, ma mi sto trattenendo dall'accettare perché mi piacerebbe avere notizie da alcuni di questi giovani per vedere dove hanno avuto l'idea. Chiaramente hanno ottenuto la parte "codice e dati separati", ma non credo che abbiano ottenuto il resto. L'hanno letto in un post sul blog? Un libro? Dove e quando?
Phil Frost,

Riceverai sempre "_____ BAD! HULK SMASH!" - ciò non significa che sia vero. Spesso questo genere di cose (ad es. "GOTO 'BAD! HULK SMASH!") Viene insegnato ai principianti, senza insegnare loro perché o quali siano le eccezioni.
AMADANON Inc.,

Localityfunziona anche al contrario: siamo finiti con una sorta di sistema di tipo plug-in a causa di requisiti personalizzati per diversi client e attraverso diversi anni di tentativi ed errori abbiamo imparato a tenere fuori le loro costanti (anche tabelle, tramite elenchi di dadi) del database e nel codice. Sia perché utilizzarlo in un luogo diverso da quel "plug-in" non è corretto, sia perché le modifiche vengono automaticamente aggiornate quando si verificano modifiche.
Izkata,

8

I dati vengono ridimensionati molto meglio e possono essere interrogati e modificati con molta più facilità, quando sono separati dal codice. Anche se i tuoi dati sono di natura codistica - ad esempio, i tuoi dati rappresentano regole o comandi - se puoi archiviare rappresentano quel codice come dati strutturati, puoi goderti i vantaggi della memorizzazione separatamente:

permessi

Se i dati sono hardcoded, dovrai modificare il file sorgente per poterli modificare. Ciò significa che:

  • Solo gli sviluppatori possono modificare i dati. Ciò è negativo: l'inserimento dei dati non è qualcosa che richiede competenze e conoscenze dello sviluppatore.

  • I non sviluppatori possono modificare il file sorgente. Questo è male - potrebbero rovinare il file sorgente senza nemmeno saperlo!

  • I dati sono codificati in file di origine separati e i non sviluppatori hanno accesso solo a tali file. Ma questo non conta davvero - ora i dati sono separati dal codice e memorizzati nei suoi file ...

la modifica

Quindi, per quanto riguarda chi può modificare i dati, è meglio conservarli separatamente. Che ne dici di come modificheranno i dati? Se hai molti dati, digitarli a mano è noioso e privo di errori. Avere un po 'di UI per questo è molto meglio! Anche se devi ancora digitare tutto, non dovrai digitare la piastra di caldaia del formato, quindi ci sono meno possibilità che sbagli il formato e rovini l'intero file!

Se i dati sono codificati, la creazione dell'interfaccia utente implica che uno strumento automatizzato modificherà i file di origine scritti a mano. Lascia che affondi - uno strumento automatizzato aprirà i tuoi file sorgente, tenterà di trovare dove dovrebbero essere i dati e modificherà quel codice. Brrr ... Microsoft ha introdotto classi parziali in C # solo per evitare quelle cose ...

Se i dati sono separati, lo strumento automatico dovrà solo modificare i file di dati. Preferirei credere che i programmi per computer che modificano i file di dati non siano così rari al giorno d'oggi ...

scalata

Il codice e i dati si ridimensionano in modo molto diverso. Man mano che il tuo codice cresce, vuoi separarlo in più classi e metodi (o strutture e funzioni di dati), ma i tuoi dati - indipendentemente da quanto crescano - vuoi tenerli in un posto. Anche se devi separarlo in più file, vuoi raggruppare questi file in qualche modo, quindi sarà più facile accedere a quei dati dal codice.

Quindi, immagina di avere migliaia di righe di dati all'interno di un file sorgente. Il compilatore / interprete deve esaminare tutti quei dati ogni volta che legge il file e analizzarlo con il suo costoso lexer e parser, anche se non accederai a quei dati in questa particolare esecuzione del programma. Inoltre, quando modifichi il codice effettivo in quel file, devi andare in giro per i dati, il che ingombrante l'intero processo. Inoltre, i file di dati possono essere indicizzati. Dati codificati? Non così tanto...

ricerca

Hai tonnellate di dati: è naturale che tu voglia cercarli.

  • Se lo memorizzi in un database, puoi utilizzare il linguaggio di query del database.

  • Se lo memorizzi in un file XML, puoi utilizzare XPath.

  • Se lo memorizzi in JSON / YAML, puoi caricarlo nel REPL del tuo linguaggio di scripting preferito e cercarlo.

  • Anche se lo memorizzi in un semplice vecchio file di testo, poiché ha una struttura che il tuo programma può riconoscere, puoi usare grep / sed / awk per cercarlo.

Sebbene sia vero che puoi anche grep / sed / awk attraverso dati codificati in un file sorgente, non funziona altrettanto bene, poiché la tua query può corrispondere con altre linee non correlate o perdere le righe che sono state scritte in modo diverso perché la sintassi della rappresentazione dei dati del linguaggio di programmazione lo consente.

Esistono strumenti per la ricerca nel codice, ma sono utili per trovare dichiarazioni, non dati codificati.

Detto ciò...

È molto importante distinguere tra dati e codice. Solo perché qualcosa è scritto come codice non significa che non possano essere dati. E solo perché qualcosa è scritto con una rappresentazione dei dati non significa che in realtà non sia un codice.

Avevo una lezione quando avevamo regole molto rigide sui "numeri magici" - non potevamo avere numeri nel nostro codice. Ciò significa che abbiamo dovuto fare cose come:

#define THE_NUMBER_ZERO 0
//....
for(int i=THE_NUMBER_ZERO;i<cout;++i){
//....

che è assolutamente ridicolo! Sì, 0tecnicamente sono "dati", ma fanno parte del codice come il resto del forciclo! Quindi, anche se siamo in grado di rappresentarlo come dati e separarlo dal codice, questo non significa che ci dovrebbe . Non perché vogliamo lasciare i dati all'interno del codice, ma perché non è in realtà un dato, non più del resto del codice, che è anche compilato per uno e zero ...


7

Penso che ci sia un po 'di confusione in corso. Stai mescolando due cose insieme: "Separare codice e dati" ed "esprimere il comportamento del programma come dati".

Nel tuo caso, sei effettivamente preoccupato per il secondo e mescolando il primo in esso. Quando si esprime il comportamento del programma come dati, è più facile estenderlo. Nel tuo esempio con vowels = "aeiou", quindi aggiungere una nuova vocale è semplice come aggiungere un carattere. Se si dispone di questi dati esternamente, è possibile modificare questo comportamento senza dover ricompilare il programma.

E quando ci pensi, OOP è l'estensione di questo pensiero. Associare dati e comportamento insieme ti permetterà di cambiare il comportamento del programma in base ai dati del programma.


2
Perché naturalmente l'elenco delle vocali cambierà.
cao

13
@cHao Non appena i18n entra, lo è.
Ripristina Monica il

2
i18n può spezzarti la testa - vedi alcuni esempi perversi in Java in javaspecialists.eu/archive/Issue209.html
Rory Hunter

2
@Angew: Non appena i18n entra, sei comunque fregato . È necessario il codice per questo; la soluzione ingenua è incapace di gestire ogni caso, anche in inglese. (Dimentica ïper un secondo; parliamo di ye w!) Spostare l'elenco in un database non risolverà il problema ed è effettivamente dannoso - è la complessità che sarà inutile se fatta male, ma non lo farai nemmeno cosa "sbagliato" è a meno che non si sta progettando per i18n da zero. A quel punto ti stai già rendendo conto che un elenco di vocali non lo taglierà comunque.
cHao,

1
@BenLee: non sarei un po 'sorpreso, in realtà. Attualmente sto lavorando per modificare alcuni codici come quello mentre parliamo. Ma esternalizzare qualsiasi cosa nel database è una predizione di un altro tipo. Se non sai già se qualcosa dovrà essere modificato - e, soprattutto, se non sai ancora come dovrà essere modificato - allora IMO è meglio aspettare fino a quando non avrai bisogno di quella flessibilità prima di aggiungerlo .
cHao,

5

Ad esempio, se la funzione del tuo programma è contare le vocali, cosa c'è di sbagliato nell'avere vocali = "aeiou" in essa?

Memorizzare la configurazione esternamente consente di disporre di una versione del codice che dovrebbe funzionare con molte configurazioni, l'alternativa è mantenere molte versioni del software che differiscono solo per la configurazione.

Hai menzionato vocali = "aeiou", e se a volte volessi "y", dovrei ricostruire l'intero programma? Posso aggiornare facilmente le versioni ora che ho modificato il codice? Se c'è un errore, l'ho causato o il programma è rotto?

Se questo è all'interno del tuo programma, implica che il tuo programma non si aspetta che gli utenti cambino la definizione di vocali senza scansionare il codice per vedere i possibili effetti collaterali. Se la definizione è memorizzata esternamente, implica che il programma non deve essere interrotto per un valore ragionevole impostato nella configurazione.

Quando sequestrate i dati in YAML o file di testo o database stupidi come se steste rimuovendo un tumore dal codice

Alcuni lo vedono come l'opposto, cioè rimuovendo il tumore del codice dai tuoi preziosi dati, vedi: la citazione di Torvalds sul buon programmatore


4
La citazione di Torvalds si riferisce alle strutture di dati, non ai dati.
user949300,

Il PO afferma: "La programmazione orientata agli oggetti diceva" vogliamo strutture di dati arbitrariamente ricche ", e quindi dotato di strutture di dati con poteri di codice".
FMJaguar,

1
Se apporti una modifica fondamentale alla definizione di vocalica, dovrai ripetere tutti i test automatizzati. I sistemi raramente hanno la possibilità di rieseguire i test quando un file di configurazione cambia su un sistema distribuito. Pertanto, tali definizioni devono essere integrate nel sistema; forse come due set hard coded con un'opzione di configurazione per selezionare tra di loro.
soru,

+1 per la citazione di Torvalds. Sono d'accordo con questo sentimento: nell'esempio del burattino, penso che il problema sia che il burattino non ha una buona struttura di dati per rappresentare le informazioni che le persone vogliono inserire. Anziché correggere le strutture dei dati, gli sviluppatori di marionette hanno affermato che "i dati nel codice" sono il problema (perché? Questa è la domanda!) E hanno sviluppato hiera , che vedo poco più che spostare il problema da qualche altra parte e renderlo inoltre impossibile associare il comportamento ai dati.
Phil Frost,

2

Ero su un progetto in cui il lead ha insistito per inserire i dati di riferimento in piccoli tavoli e ho pensato che fosse sciocco. Ma dal momento che avevamo già impostato la nostra infrastruttura di persistenza e la connettività, alla fine ci fu un costo piuttosto basso rispetto alle altre operazioni di persistenza che stavamo facendo.

Ora, penso ancora che sia stata una decisione sciocca, e se non avessimo l'infrastruttura a portata di mano, non l'avrei fatto.

Ma alcuni degli argomenti a favore che vedo sono:

  • Se si dispone di una mentalità di database, l'inserimento di dati di riferimento nel database SQL consente di unirsi a esso per il reporting.
  • Se si dispone di un'utilità di amministrazione o dell'accesso al database, è possibile modificare i valori in fase di esecuzione. (Anche se può giocare con il fuoco.)

Inoltre, a volte la politica ostacola le pratiche di codifica. Ad esempio, ho lavorato in diversi negozi in cui il push di un file .xml è A-OK, mentre toccare una riga nel codice richiede un ciclo di regressione completo e forse un test di carico. Quindi c'era un team in cui mi trovavo dove i miei file .xml per il progetto erano estremamente ricchi (e forse -heh- avrebbe potuto contenere del codice).

Mi chiedo sempre se mi godrò il vantaggio di spingere i dati fuori dal codice in un archivio dati esterno, anche se è solo un file di testo, ma ho lavorato con persone che lo vedono come il loro primo impulso.


3
Un buon commento sulle procedure del negozio, in cui la modifica di XML è "ok" ma la modifica della stessa cosa nel codice è una seccatura.
user949300,

ha lavorato in un negozio in cui tutto era nel database che poteva essere, fino ai testi sullo schermo. A parte il codice dell'interfaccia utente, l'unica cosa non presente nel database era la posizione e le credenziali del database ...
jwenting,

3
suona sempre sciocco fino a quando, un giorno, qualcuno chiede "possiamo riconfigurarlo per l'utente X che lo richiede", e dopo tutto non sembra così sciocco. Dannati clienti :)
gbjbaanb,

2
... e se quel giorno non è "mai", è molto sciocco sentirsi a lungo
Rob,

2

Permettetemi di farvi una contro-domanda completamente seria: qual è, secondo voi, la differenza tra "dati" e "codice"?

Quando sento la parola "dati", penso "stato". I dati sono, per definizione, la cosa che l'applicazione stessa è progettata per gestire, e quindi la cosa che l'applicazione non può mai conoscere al momento della compilazione. Non è possibile codificare i dati perché non appena li codifichi, diventano comportamenti, non dati.

Il tipo di dati varia in base all'applicazione; un sistema di fatturazione commerciale può archiviare informazioni su clienti e ordini in un database SQL e un programma di grafica vettoriale può archiviare dati geometrici e metadati in un file binario. In entrambi questi casi e in tutto ciò che c'è nel mezzo, c'è una chiara e indistruttibile separazione tra codice e dati. I dati appartengono all'utente , non al programmatore, quindi non possono mai essere codificati.

Quello di cui sembra parlare è usare la descrizione tecnicamente più accurata disponibile per il mio attuale vocabolario: informazioni che governano il comportamento del programma che non sono scritte nel linguaggio di programmazione principale usato per sviluppare la maggior parte dell'applicazione.

Anche questa definizione, che è considerevolmente meno ambigua della sola parola "dati", presenta alcuni problemi. Ad esempio, cosa succede se parti significative del programma sono scritte ciascuna in lingue diverse? Ho lavorato personalmente su diversi progetti che sono circa il 50% di C # e il 50% di JavaScript. Il codice JavaScript è "dati"? Molte persone direbbero di no. Che dire dell'HTML, sono "dati"? Molte persone direbbero ancora di no.

E i CSS? Sono dati o codice? Se pensiamo al codice come qualcosa che controlla il comportamento del programma, allora il CSS non è in realtà un codice, perché influenza solo (bene, principalmente) l'aspetto, non il comportamento. Ma non sono nemmeno dei dati; l'utente non lo possiede, l'applicazione non lo possiede nemmeno. È l'equivalente del codice per un designer dell'interfaccia utente. È simile al codice, ma non del tutto.

Potrei chiamare CSS un tipo di configurazione, ma una definizione più pratica è che si tratta semplicemente di un codice in un linguaggio specifico del dominio . Questo è ciò che spesso rappresentano XML, YAML e altri "file formattati". E la ragione per cui usiamo un linguaggio specifico del dominio è che, in generale, è simultaneamente più conciso ed espressivo nel suo particolare dominio rispetto alla codifica delle stesse informazioni in un linguaggio di programmazione generico come C o C # o Java.

Riconosci il seguente formato?

{
    name: 'Jane Doe',
    age: 27,
    interests: ['cats', 'shoes']
}

Sono sicuro che molte persone lo fanno; è JSON . Ed ecco la cosa interessante di JSON: in JavaScript, è chiaramente un codice, e in ogni altra lingua, sono dati chiaramente formattati. Quasi ogni singolo linguaggio di programmazione tradizionale ha almeno una libreria per "analizzare" JSON.

Se utilizziamo la stessa identica sintassi all'interno di una funzione in un file JavaScript, non può essere altro che un codice. Eppure, se prendiamo quel JSON, lo inseriamo in un .jsonfile e lo analizziamo in un'applicazione Java, improvvisamente sono "dati". Ha davvero senso?

Io sostengo che "data-ness" o "configuration-ness" o "code-ness" è inerente a ciò che viene descritto, non al modo in cui viene descritto.

Se il tuo programma ha bisogno di un dizionario di 1 milione di parole per, per esempio, generare una passphrase casuale, vuoi codificarla in questo modo:

var words = new List<string>();
words.Add("aa");
words.Add("aah");
words.Add("ahhed");
// snip 172836 more lines
words.Add("zyzzyva");
words.Add("zyzzyvas");

O semplicemente spingeresti tutte quelle parole in un file di testo delimitato da righe e diresti al tuo programma di leggere da esso? Non importa se l'elenco di parole non cambia mai, non è una questione di codifica hard o soft-coding (che molti considerano giustamente un anti-pattern se applicato in modo inappropriato), è semplicemente una questione di quale formato è più efficiente e semplifica la descrizione delle "cose", qualunque esse siano. È abbastanza irrilevante se lo chiami codice o dati; sono le informazioni che il tuo programma richiede per funzionare, e un formato di file flat è il modo più conveniente per gestirlo e mantenerlo.

Supponendo che tu segua le pratiche appropriate, tutte queste cose andranno comunque al controllo del codice sorgente, quindi potresti anche chiamarlo codice, solo codice in un formato diverso e forse molto minimalista. Oppure puoi chiamarlo configurazione, ma l'unica cosa che distingue veramente il codice dalla configurazione è se lo documenti e dici agli utenti finali come modificarlo. Potresti forse inventare qualche argomento falso sulla configurazione interpretata in fase di avvio o di runtime e non in fase di compilazione, ma poi inizieresti a descrivere diversi linguaggi tipizzati dinamicamente e quasi sicuramente qualsiasi cosa con un motore di scripting incorporato al suo interno (ad es. la maggior parte dei giochi). Codice e configurazione sono qualunque cosa tu decida di etichettarli come, niente di più, niente di meno.

Ora, non v'è un pericolo per esternalizzare le informazioni che in realtà non è sicura di modificare (si veda il link "soft codifica" di cui sopra). Se estrai l'array di vocali in un file di configurazione e lo documenti come file di configurazione per gli utenti finali, stai offrendo loro un modo quasi infallibile per rompere istantaneamente la tua app, ad esempio inserendo "q" come vocale. Ma questo non è un problema fondamentale con la "separazione di codice e dati", è semplicemente un cattivo senso del design.

Quello che dico agli sviluppatori junior è che dovrebbero sempre esternalizzare le impostazioni che si aspettano di cambiare per ambiente. Ciò include elementi quali stringhe di connessione, nomi utente, chiavi API, percorsi di directory e così via. Essi potrebbero essere gli stessi sulla propria macchina dev e in produzione, ma probabilmente non, e gli amministratori di sistema potranno decidere come vogliono farlo sembrare in produzione, non gli sviluppatori. Quindi hai bisogno di un modo per avere un gruppo di impostazioni applicate su alcune macchine e altre impostazioni applicate su altre macchine - ergo, file di configurazione esterni (o impostazioni in un database, ecc.)

Ma sottolineo che semplicemente inserire alcuni "dati" in un "file" non equivale a esternalizzarli come configurazione. Mettere un dizionario di parole in un file di testo non significa che vuoi che gli utenti (o IT) lo cambino, è solo un modo per rendere molto più facile per gli sviluppatori capire cosa diavolo sta succedendo e, se necessario, fare cambiamenti occasionali. Allo stesso modo, inserire le stesse informazioni in una tabella di database non conta necessariamente come esternalizzazione del comportamento, se la tabella è di sola lettura e / o ai DBA viene chiesto di non rovinarsene. La configurazione implica che i dati sono mutabili, ma in realtà ciò è determinato dal processo e dalle responsabilità piuttosto che dalla scelta del formato.

Quindi, per riassumere:

  • "Codice" non è un termine rigidamente definito. Se estendi la tua definizione per includere linguaggi specifici del dominio e qualsiasi altra cosa che influenzi il comportamento, gran parte di questo apparente attrito semplicemente scomparirà e tutto avrà un senso. Puoi avere un "codice" DSL non compilato in un file flat.

  • "Dati" implica informazioni di proprietà dell'utente (i) o almeno di un soggetto diverso dagli sviluppatori e generalmente non disponibili in fase di progettazione. Non potrebbe essere hardcoded anche se si desidera farlo. Con la possibile eccezione del codice automodificante , la separazione tra codice e dati è una questione di definizione, non di preferenza personale.

  • Il "soft-coding" può essere una pratica terribile se applicato in modo eccessivo, ma non tutte le istanze di esternalizzazione costituiscono necessariamente un soft-coding e molti casi di memorizzazione di informazioni in "file flat" non sono necessariamente un tentativo in buona fede di esternalizzazione.

  • La configurazione è un tipo speciale di soft-coding che è necessario a causa della conoscenza che potrebbe essere necessario eseguire l'applicazione in ambienti diversi. La distribuzione di un file di configurazione separato insieme all'applicazione richiede molto meno lavoro (e molto meno pericoloso) rispetto alla distribuzione di una versione diversa del codice in ogni ambiente. Quindi alcuni tipi di soft-coding sono effettivamente utili.


1

Suggerisco di leggere questo classico articolo di Oren Eini (aka Ayende Rahien)

http://ayende.com/blog/3545/enabling-change-by-hard-coding-everything-the-smart-way

Il mio da asporto è concentrarmi sulla semplicità e sulla leggibilità. Ciò può significare che le cose che è improbabile che vengano riconfigurate devono essere lasciate codificate (leggibile). Ciò consente di utilizzare la sintassi completa di un linguaggio di programmazione per esprimere i parametri, nonché ottenere effetti collaterali benefici come il completamento del codice e errori del compilatore in caso di uso improprio.

In questo modo si evitano potenzialmente le complessità dell'analisi / interpretazione ("ma qualcun altro analizza il mio YAML / JSON" - mappare il testo analizzato nelle chiamate API specifiche può essere una forma di interpretazione) ed evitare la complessità di un altro passaggio tra i "dati "e il suo utilizzo.

Alcuni casi si prestano ad essere espressi nei dati anche in uno scenario come questo: ad esempio, specificare migliaia di punti nello spazio 3D può essere più adatto per un file di testo rispetto al codice, sebbene in alcune lingue, incluso C usando inizializzatori di struttura, codice può essere appropriato anche per quello.


1

Ok, supponiamo che tu voglia scrivere una sorta di programma c ++ per il tuo tempo libero. Sai esattamente cosa deve fare e cosa non dovrà mai fare. Ora prendi qualsiasi libro sul "design moderno del software". Ecco la regola del gioco: per ogni classe del tuo progetto e per ogni caso anche così piccolo devi implementare ogni modello di fantasia che trovi descritto in quel libro per rendere il tuo codice un "design pulito". Bene, "iniezione di dipendenza" sarà sufficiente per molti ppl, immagino. (È c ++, non java!) La programmazione viene insegnata da un punto di vista sempre più teorico. Non è sufficiente che tu finisca il lavoro, devi scrivere un codice che sia mantenibile, stupido dimostrare ... tutto bene e bene. Il problema inizia quando ppl. smetti di pensare al motivo reale, i modelli di design sono stati inventati e diventano dogmatici.

Lascia che ti smetta di scrivere il tuo strumento di conteggio delle lettere utilizzando (oltre) un unico principio di progettazione semplice: quando scrivi un codice che esegue un determinato lavoro su dati di input di un certo tipo, assicurati che sia in grado di eseguire quell'attività per un determinato input dati di quel tipo. - Quando si desidera scrivere uno strumento di conteggio delle lettere, ha chiaramente senso scriverlo in un modo in modo che non sia solo in grado di contare le vocali, ma "qualsiasi lettera". - Dato che potresti non sapere quale sia effettivamente il corpus che stai analizzando, puoi anche scegliere una codifica molto generale (UTF-16) e coprire la maggior parte (tutte?) Le lingue scritte e i loro simboli.

Fino a quel momento, abbiamo una funzione con due argomenti (il corpus e le lettere da contare). Ci preoccupiamo solo di trovare un "tipo" o una "classe" ragionevolmente generale di cui appartengano anche le lettere: possiamo certamente fare meglio dei simboli ASCII!

Inserisci un demone che esercita il "dogma di generalizzazione e riusabilità": - Perché non contare alcun simbolo di qualsiasi classe in un flusso di input di quella classe? (abstract dalle lettere alle sequenze di bit di lunghezza arbitraria ma limitata in quanto questa è la più generale che puoi ottenere con un computer ...) - Aspetta, anche allora contiamo ancora in numeri naturali. Tuttavia il conteggio può essere generalizzato come una mappatura da un insieme numerabile a se stesso che soddisfa gli assiomi ... [si ottiene l'idea]

Ora questo esempio potrebbe essere sciocco, ma se consideri le attività di progettazione più complesse di uno strumento di conteggio, potresti trovare tutte le opportunità per introdurre l'astrazione aggiuntiva richiesta in base a un tipo di modello di progettazione che hai trovato nel tuo libro.

La separazione di "dati" e "codice" sarà probabilmente banale (argomenti di funzione) o ti ritroverai a trattare gli invarianti come variabili ("dati").

Se c'è mai confusione, è probabile che "interfacce" e "servizi" e tutte le specifiche di classe (ad es. Tipi) siano improvvisamente "dati", ovvero dipendenze da iniettare dall'esterno. Sento che i corsi di informatica tenuti all'università sono diventati molto simili alle lezioni di filosofia e c'è meno tempo per progetti reali in modo che gli studenti possano acquisire esperienza su come realizzare software che funzioni. Se ti chiedi mai perché ti viene richiesto di utilizzare un modello follemente complesso invece di una soluzione ovvia, questo sviluppo è (probabilmente) il modo in cui tale requisito è stato "creato" ...

Al tuo problema specifico: se potessi 1.) scrivere un programma con un massimo di hard-coding per il tuo caso specifico e quindi 2.) generalizzare da quel codice in modo semplice, ad es. introducendo più argomenti di funzione e usando altri "schemi banali" puoi essere sicuro di separare codice e dati, nel modo ovvio, come è stato fatto da quando è stata inventata la programmazione funzionale. (spesso salti 1. e fai 2. immediatamente ...)

Qualcosa di non ovvio qui è probabilmente un caso di "teoria-deadlock": come scrivere un'interfaccia che si riferisce a un'interfaccia e ancora un'altra interfaccia ... e alla fine hai un piccolo file xml pulito per configurare tutte queste interfacce e le dipendenze da iniettare nel disordine dell'interfaccia di classe.

Speriamo solo che il parser xml richiesto non abbia bisogno di una configurazione xml per funzionare ...

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.