Wie wurde die Trennung von Code und Daten zur Praxis?


29

Bitte lesen Sie die Frage sorgfältig durch: Es wird gefragt, wie und nicht warum .

Ich bin kürzlich auf diese Antwort gestoßen , die die Verwendung einer Datenbank zum Speichern unveränderlicher Daten vorschlägt:

Es hört sich so an, als wären viele der von Ihnen beschriebenen magischen Zahlen - insbesondere wenn sie teileabhängig sind - wirklich Daten, kein Code. [...] Es kann sich um eine SQL-Datenbank handeln oder einfach um eine formatierte Textdatei.

Mir scheint, wenn Sie Daten haben, die Teil Ihrer Programmfunktionen sind, müssen Sie sie in das Programm einfügen . Wenn Ihr Programm beispielsweise die Funktion hat, Vokale zu zählen, was ist dann falsch daran, wenn es Vokale enthält vowels = "aeiou"? Schließlich verfügen die meisten Sprachen über Datenstrukturen, die genau für diese Verwendung ausgelegt sind. Warum sollten Sie sich die Mühe machen, Daten in einer "formatierten Textdatei" zu trennen , wie oben vorgeschlagen? Warum nicht einfach diese Textdatei in der Programmiersprache Ihrer Wahl formatieren? Jetzt ist es eine Datenbank? Oder ist es Code?

Ich bin sicher, einige werden das für eine blöde Frage halten, aber ich stelle sie ernsthaft. Ich habe das Gefühl, dass "Code und Daten trennen" kulturell als eine Art selbstverständliche Wahrheit auftaucht, zusammen mit anderen offensichtlichen Dingen wie "Geben Sie Ihren Variablen keine irreführenden Namen" und "Vermeiden Sie es nicht, Leerzeichen zu verwenden, nur weil Ihre Sprache dies berücksichtigt es ist unbedeutend ".

Nehmen Sie zum Beispiel diesen Artikel: Das Problem mit dem Trennen von Daten vom Puppencode . Das Problem ? Welches Problem? Wenn Puppet eine Sprache zur Beschreibung meiner Infrastruktur ist, warum kann es dann nicht auch beschreiben, dass der Nameserver 8.8.8.8 ist? Es scheint mir, dass das Problem nicht darin besteht, dass Code und Daten vermischt werden 1, sondern dass Puppet nicht über ausreichend umfangreiche Datenstrukturen und Schnittstellen zu anderen Dingen verfügt.

Ich finde diese Verschiebung störend. Die objektorientierte Programmierung sagte, "wir wollen willkürlich reiche Datenstrukturen" und stattete so Datenstrukturen mit Codekräften aus. Als Ergebnis erhalten Sie eine Kapselung und Abstraktion. Sogar SQL-Datenbanken haben gespeicherte Prozeduren. Wenn Sie Daten in YAML- oder Textdateien oder dumme Datenbanken einteilen, als würden Sie einen Tumor aus dem Code entfernen, verlieren Sie all das.

Kann jemand erklären, wie es dazu kam, Daten von Code zu trennen und wohin das führt? Kann irgendjemand Veröffentlichungen von Koryphäen zitieren oder relevante Daten bereitstellen, die "Code von Daten trennen" als aufkommendes Gebot darstellen und dessen Herkunft veranschaulichen?

1: wenn man solche Unterscheidungen überhaupt machen kann. Ich sehe dich an, Lisp-Programmierer.


5
Fühlen Sie sich frei, alle HTML- und CSS-Dateien in der Sprache Ihrer Wahl zu begraben.
JeffO

3
Ich denke, der Autor des Zitats meinte, dass die magischen Zahlen nicht wirklich unveränderlich sind.
Pieter B

4
Es ist nichts Falsches daran, die Vokale hart zu codieren. Wenn Ihre Anwendung nur zum Zählen der Vokale in Englisch verwendet wird.
Michael Paulukonis

3
Ein großer technischer Grund für die Trennung von Code und Daten besteht darin, dass der Code nicht neu kompiliert werden muss, wenn sich die Daten ändern. Daher würde ich fragen, ob dies in gleichem Maße für Skriptsprachen gilt.
user16764

1
@MichaelPaulukonis: Und es in eine Datenbank zu stellen, ist eine gefälschte Lösung. Änderungen für Niederländisch erforderlich? Null (nicht einmal ein DB-Wechsel). Änderungen für Französisch / Deutsch erforderlich? Mindestens ISO-8859-1-Unterstützung. (Mehr als DB). Änderungen für Griechisch / Russisch erforderlich? Unicode-Unterstützung (mehr als DB). Tatsächlich kann ich mir keine Sprache vorstellen, in der diese Datenbank hilfreich ist.
MSalters

Antworten:


22

Es gibt viele gute Gründe, Daten von Code zu trennen, und einige Gründe, dies nicht zu tun. Folgendes fällt mir ein.

Aktualität. Wann ist der Datenwert bekannt? Ist dies der Zeitpunkt, zu dem der Code geschrieben wird, wenn er kompiliert, verknüpft, freigegeben, lizenziert, konfiguriert, ausgeführt oder ausgeführt wird? Zum Beispiel ist die Anzahl der Tage in einer Woche (7) früh bekannt, aber der USD / AUD-Wechselkurs wird ziemlich spät bekannt sein.

Struktur. Handelt es sich um eine einzelne Datenzeitmenge gemäß einer einzelnen Überlegung, oder ist sie möglicherweise vererbt oder Teil einer größeren Sammlung von Elementen? Sprachen wie YAML und JSON ermöglichen die Kombination von Werten aus mehreren Quellen. Möglicherweise werden einige Dinge, die zunächst unveränderlich zu sein scheinen, besser als Eigenschaften in einem Konfigurationsmanager verfügbar gemacht.

Lokalität. Wenn alle Datenelemente an einer begrenzten Anzahl von Orten gespeichert sind, ist es viel einfacher, sie zu verwalten, insbesondere wenn einige möglicherweise in neue (unveränderliche) Werte geändert werden müssen. Das Bearbeiten des Quellcodes nur zum Ändern von Datenwerten birgt das Risiko unbeabsichtigter Änderungen und Fehler.

Trennung von Bedenken. Die korrekte Funktionsweise von Algorithmen lässt sich am besten von der Überlegung trennen, welche Datenwerte verwendet werden sollen. Daten werden zum Testen von Algorithmen benötigt, um nicht Teil davon zu sein. Siehe auch http://c2.com/cgi/wiki?ZeroOneInfinityRule .

Als Antwort auf Ihre Frage ist dies keine neue Sache. Die Grundprinzipien haben sich in mehr als 30 Jahren nicht geändert und wurden in dieser Zeit wiederholt beschrieben. Ich kann mich an keine wichtigen Veröffentlichungen zu diesem Thema erinnern, da es im Allgemeinen nicht als kontrovers angesehen wird, sondern nur als Erklärung für Neuankömmlinge. Hier gibt es noch ein bisschen mehr: http://c2.com/cgi/wiki?SeparationOfDataAndCode .

Meine persönliche Erfahrung ist, dass die Bedeutung dieser Trennung in einem bestimmten Softwareteil mit der Zeit größer und nicht geringer wird. Fest codierte Werte werden in Header-Dateien verschoben, kompilierte Werte in Konfigurationsdateien, einfache Werte werden Teil hierarchischer und verwalteter Strukturen.

In Bezug auf Trends habe ich bei professionellen Programmierern (über 10 Jahre) keine wesentlichen Einstellungsänderungen festgestellt, aber die Branche ist zunehmend voller junger Leute, und viele Dinge, von denen ich dachte, dass sie bekannt und entschieden sind, werden immer wieder in Frage gestellt und neu erfunden, manchmal aus dem Stand Einsichten aber manchmal aus Unwissenheit.


2
Könnten Sie die Geschichte und den Trend dieser Praxis erläutern? Wenn alle diese Überlegungen gemacht hätten, hätte ich die Frage nicht gestellt. Die Prämisse der Frage ist, dass die Leute nicht genau überlegen, wohin ihre Daten gehen sollen (kompilierte Konstanten, externe Datenbanken, YAML ...), sondern nur "CODE AND DATA MIXED BAD! HULK SMASH!" Warum oder wann ist das eine Sache geworden?
Phil Frost

Es ist nicht Teil meiner Erfahrung, also kann ich es Ihnen nicht sagen. Ich habe meiner Antwort ein paar Absätze hinzugefügt.
david.pfx

Ich denke, "Zuzug von Jugendlichen" ist eine gültige Erklärung, aber ich zögere damit zu akzeptieren, weil ich von einigen dieser Jugendlichen hören möchte, um zu sehen, woher sie die Idee haben. Klar, sie haben den "separaten Code und Daten" Teil, aber ich glaube nicht, dass sie den Rest haben. Haben sie es in einem Blogbeitrag gelesen? Ein Buch? Wo und wann?
Phil Frost

Sie werden immer "_____ BAD! HULK SMASH!" - das heißt nicht, dass es wahr ist. Oft wird diese Art von Dingen (zB "GOTO BAD! HULK SMASH!") Anfängern beigebracht, ohne ihnen zu erklären, warum oder welche Ausnahmen dies sind.
AMADANON Inc.

Localityfunktioniert auch umgekehrt: Wir haben aufgrund von kundenspezifischen Anforderungen für verschiedene Clients eine Art Plug-in-System entwickelt und durch jahrelanges Ausprobieren gelernt, ihre Konstanten (auch Tabellen, anhand von Diktatlisten) fernzuhalten der Datenbank und im Code. Beides, weil die Verwendung an einer anderen Stelle als diesem "Plugin" nicht korrekt ist und weil Änderungen automatisch versioniert werden, wenn Änderungen auftreten.
Izkata

8

Daten skalieren viel besser und können viel einfacher abgefragt und geändert werden, wenn sie vom Code getrennt sind. Selbst wenn Ihre Daten verschlüsselt sind - Ihre Daten stellen beispielsweise Regeln oder Befehle dar -, können Sie die Vorteile einer getrennten Speicherung nutzen, wenn Sie diesen Code als strukturierte Daten darstellen können:

Berechtigungen

Wenn die Daten fest codiert sind, müssen Sie die Quelldatei bearbeiten, um diese Daten zu bearbeiten. Das bedeutet entweder:

  • Nur Entwickler können Daten bearbeiten. Das ist schlecht - die Dateneingabe erfordert keine Fähigkeiten und Kenntnisse der Entwickler.

  • Nicht-Entwickler können die Quelldatei bearbeiten. Das ist schlecht - sie könnten die Quelldatei vermasseln, ohne es zu wissen!

  • Die Daten sind in separaten Quelldateien fest codiert, und Nicht-Entwickler haben nur Zugriff auf diese Dateien. Aber das zählt nicht wirklich - jetzt werden die Daten vom Code getrennt und in eigenen Dateien gespeichert ...

Bearbeitung

Wenn Sie also wissen, wer die Daten bearbeiten kann, speichern Sie sie am besten separat. Wie wäre es damit, wie sie die Daten bearbeiten? Wenn Sie viele Daten haben, ist die manuelle Eingabe mühsam und fehleranfällig. Eine Benutzeroberfläche dafür zu haben ist viel besser! Auch wenn Sie immer noch alles eingeben müssen, müssen Sie nicht die Kesselplatte des Formats eingeben, sodass die Wahrscheinlichkeit geringer ist, dass Sie das Format durcheinander bringen und die gesamte Datei verschrauben!

Wenn die Daten fest codiert sind, bedeutet das Erstellen dieser Benutzeroberfläche, dass ein automatisiertes Tool handgeschriebene Quelldateien bearbeitet. Lassen Sie das einwirken - ein automatisiertes Tool öffnet Ihre Quelldateien, versucht herauszufinden, wo sich die Daten befinden sollen, und ändert diesen Code. Brrr ... Microsoft hat Teilklassen in C # eingeführt, um diese Dinge zu vermeiden ...

Wenn die Daten getrennt sind, muss Ihr automatisiertes Tool nur die Datendateien bearbeiten. Ich würde eher glauben, dass Computerprogramme, die Datendateien bearbeiten, heutzutage keine Seltenheit sind ...

Skalierung

Code und Daten skalieren sehr unterschiedlich. Wenn Ihr Code wächst, möchten Sie ihn in weitere Klassen und Methoden (oder Datenstrukturen und -funktionen) aufteilen, aber Ihre Daten - egal wie stark sie wachsen - möchten Sie an einem Ort aufbewahren. Auch wenn Sie es in mehrere Dateien aufteilen müssen, möchten Sie diese Dateien irgendwie bündeln, damit Sie über den Code einfacher auf diese Daten zugreifen können.

Stellen Sie sich also vor, Sie haben Tausende von Datenzeilen in einer Quelldatei. Der Compiler / Interpreter muss all diese Daten jedes Mal durchgehen, wenn er die Datei liest, und sie mit seinem teuren Lexer & Parser analysieren - auch wenn Sie in diesem speziellen Programmlauf nicht auf diese Daten zugreifen. Wenn Sie den eigentlichen Code in dieser Datei bearbeiten, müssen Sie außerdem die Daten umgehen, was den gesamten Prozess umständlich macht. Auch Datendateien können indiziert werden. Fest codierte Daten? Nicht so viel...

suche

Sie haben Tonnen von Daten - es ist nur natürlich, dass Sie sie durchsuchen möchten.

  • Wenn Sie es in einer Datenbank speichern, können Sie die Datenbank-Abfragesprache verwenden.

  • Wenn Sie es in einer XML-Datei speichern, können Sie XPath verwenden.

  • Wenn Sie es in JSON / YAML speichern, können Sie es in REPL Ihrer bevorzugten Skriptsprache laden und durchsuchen.

  • Selbst wenn Sie es in einer einfachen alten Textdatei speichern, können Sie es mit grep / sed / awk durchsuchen, da es eine Struktur hat, die Ihr Programm erkennen kann.

Es stimmt zwar, dass Sie auch hartcodierte Daten in einer Quelldatei mit grep / sed / awk durchsuchen können, dies funktioniert jedoch nicht so gut, da Ihre Abfrage mit anderen, nicht verwandten Zeilen oder fehlenden Zeilen übereinstimmen kann, die auf Grund dessen anders geschrieben wurden Die Datenrepräsentationssyntax der Programmiersprache ermöglicht dies.

Es gibt Tools zum Durchsuchen von Code, aber sie eignen sich gut zum Auffinden von Deklarationen und nicht von fest codierten Daten.

Davon abgesehen ...

Es ist sehr wichtig, zwischen Daten und Code zu unterscheiden. Nur weil etwas als Code geschrieben ist, heißt das nicht, dass es keine Daten sein können. Und nur weil etwas mit einer Datendarstellung geschrieben ist, heißt das nicht, dass es tatsächlich kein Code ist.

Ich hatte eine Klasse, in der wir sehr strenge Regeln für "magische Zahlen" hatten - wir konnten keine Zahlen in unserem Code haben. Das heißt, wir mussten Dinge tun wie:

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

was geradezu lächerlich ist! Ja, 0ist technisch "Daten", aber es ist genauso Teil des Codes wie der Rest der forSchleife! Also auch wenn wir können es als Daten und trennen es vom Code repräsentieren, das bedeutet nicht , wir sollten . Nicht weil wir Daten im Code belassen wollen, sondern weil es sich nicht wirklich um Daten handelt - nicht mehr als der Rest des Codes, der auch in Einsen und Nullen kompiliert wird ...


7

Ich denke, es gibt einige Verwirrung. Sie mischen zwei Dinge miteinander: "Code und Daten trennen" und "Programmverhalten als Daten ausdrücken".

In deinem Fall machst du dir tatsächlich Sorgen um die zweite und mischst die erste hinein. Wenn Sie das Verhalten des Programms als Daten ausdrücken, wird die Erweiterung vereinfacht. In Ihrem Beispiel mit vowels = "aeiou"ist das Hinzufügen eines neuen Vokals so einfach wie das Hinzufügen eines Zeichens. Wenn Sie diese Daten extern haben, können Sie dieses Verhalten ändern, ohne das Programm neu kompilieren zu müssen.

Und wenn Sie darüber nachdenken, ist OOP eine Erweiterung dieses Denkens. Durch das Verbinden von Daten und Verhalten können Sie das Verhalten des Programms basierend auf den Programmdaten ändern.


2
Natürlich wird sich die Liste der Vokale ändern.
CHAO

13
@cHao Sobald i18n eintritt, ist es .
Setzen Sie Monica

2
i18n kann dir den Kopf brechen - einige perverse Beispiele in Java finden Sie unter javaspecialists.eu/archive/Issue209.html
Rory Hunter,

2
@Angew: Sobald i18n eintritt, bist du sowieso fertig . Sie benötigen dafür Code. Die naive Lösung ist nicht in der Lage, jeden Fall auch auf Englisch zu behandeln. (Vergiss das ïfür eine Sekunde; lass uns über yund reden w!) Das Verschieben der Liste in eine Datenbank wird das nicht beheben und ist tatsächlich schädlich - es ist Komplexität, die wertlos ist, wenn sie falsch gemacht wird, aber du wirst es nicht Sie wissen sogar, was "falsch" ist, es sei denn, Sie entwerfen von Grund auf für i18n. An diesem Punkt merkt man bereits, dass eine Liste von Vokalen es sowieso nicht schafft.
CHAO

1
@BenLee: Eigentlich wäre ich nicht ein bisschen überrascht. Ich arbeite gerade daran, so einen Code zu ändern, während wir sprechen. Aber alles in die Datenbank auszulagern ist eine andere Art von Wahrsagerei. Wenn Sie nicht bereits wissen, ob etwas geändert werden muss - und vor allem, wenn Sie noch nicht wissen, wie es geändert werden muss -, ist es IMO besser zu warten, bis Sie diese Flexibilität benötigen, bevor Sie es hinzufügen .
CHAO

5

Wenn die Funktion Ihres Programms beispielsweise darin besteht, Vokale zu zählen, was ist dann falsch daran, Vokale = "aeiou" darin zu haben?

Wenn Sie die Konfiguration extern speichern, können Sie eine Version des Codes verwenden, von der erwartet wird, dass sie mit vielen Konfigurationen funktioniert. Alternativ können Sie viele Versionen der Software verwalten, die sich nur durch die Konfiguration unterscheiden.

Sie erwähnen Vokale = "aeiou", was, wenn ich manchmal "y" möchte, muss ich das gesamte Programm neu erstellen? Kann ich jetzt, da ich den Code geändert habe, problemlos Versionen upgraden? Wenn es einen Fehler gibt, habe ich ihn verursacht oder ist das Programm kaputt?

Befindet sich dies in Ihrem Programm, bedeutet dies, dass Ihr Programm nicht erwartet, dass Benutzer die Definition von Vokalen ändern, ohne den Code nach möglichen Nebenwirkungen zu durchsuchen. Wenn die Definition extern gespeichert wird, bedeutet dies, dass das Programm nicht für einen in der Konfiguration festgelegten angemessenen Wert unterbrochen werden sollte.

Wenn Sie Daten in YAML- oder Textdateien oder dumme Datenbanken einteilen, als würden Sie einen Tumor aus dem Code entfernen

Einige sehen es als das Gegenteil, das heißt, Sie entfernen den Code-Tumor aus Ihren wertvollen Daten, siehe: Torvalds Zitat über einen guten Programmierer


4
Das Torvalds-Zitat bezieht sich auf Datenstrukturen, nicht auf Daten.
user949300

Das OP besagt: "Objektorientierte Programmierung sagte," wir wollen willkürlich reiche Datenstrukturen "und stattete so Datenstrukturen mit Code-Potenzen aus."
FMJaguar

1
Wenn Sie die Definition eines Vokals grundlegend ändern, müssen Sie alle automatisierten Tests wiederholen. Systeme haben selten die Möglichkeit, Tests erneut auszuführen, wenn sich eine Konfigurationsdatei auf einem bereitgestellten System ändert. Daher müssen solche Definitionen in das System eingebaut werden. vielleicht als zwei fest codierte Sätze mit einer Konfigurationsoption, um zwischen ihnen zu wählen.
Soru

+1 für das Torvalds-Zitat. Ich stimme diesem Gefühl zu: Am Beispiel einer Marionette denke ich, dass das Problem darin besteht, dass die Marionette keine gute Datenstruktur hat, um die Informationen darzustellen, die die Leute darin ablegen möchten. Anstatt die Datenstrukturen zu reparieren, stellten die Puppenentwickler fest, dass "Daten im Code" das Problem ist (warum? Das ist die Frage!) Und entwickelten hiera , was meiner Meinung nach nicht viel mehr ist, als das Problem an einen anderen Ort zu verschieben und es zusätzlich unmöglich zu machen Verhalten mit Daten zu verknüpfen.
Phil Frost

2

Ich war an einem Projekt beteiligt, bei dem der Lead darauf bestand, Referenzdaten in kleine Tabellen zu schreiben, und ich fand das albern. Da wir jedoch bereits unsere Persistenzinfrastruktur und Konnektivität eingerichtet hatten, waren die Kosten für die anderen von uns durchgeführten Persistenzvorgänge relativ niedrig.

Ich denke immer noch, dass das eine dumme Entscheidung war, und wenn wir nicht die Infrastruktur zur Hand hätten, hätte ich es einfach nicht getan.

Aber einige der Argumente, die ich dafür sehe, sind:

  • Wenn Sie eine Datenbank-Einstellung haben, können Sie Referenzdaten in die SQL-Datenbank einfügen, um Berichte zu erstellen.
  • Wenn Sie über ein Verwaltungsdienstprogramm verfügen oder auf die Datenbank zugreifen, können Sie die Werte zur Laufzeit optimieren. (Obwohl das mit dem Feuer spielen kann.)

Manchmal stört die Politik auch die Codierungspraktiken. Ich habe beispielsweise in mehreren Geschäften gearbeitet, in denen das Pushen einer XML-Datei mit A-OK bewertet wurde, während das Berühren einer Codezeile einen vollständigen Regressionszyklus und möglicherweise einen Auslastungstest erfordert. Es gab also ein Team, in dem meine .xml-Dateien für das Projekt extrem umfangreich waren (und vielleicht -heh- etwas Code enthielten).

Ich frage mich immer, ob ich den Vorteil genießen kann, Daten aus dem Code in einen externen Datenspeicher zu verschieben, auch wenn es sich nur um eine Textdatei handelt, aber ich habe mit Menschen gearbeitet, die dies nur als ihre erste betrachten Impuls.


3
Guter Kommentar zu Shop-Prozeduren, bei denen das Bearbeiten von XML "in Ordnung" ist, aber das gleiche im Code zu bearbeiten ein großer Aufwand ist.
user949300

arbeitete in einem Geschäft, in dem sich alles in der Datenbank befand, bis auf die Bildschirmtexte. Neben dem Benutzeroberfläche Code, das einzige , was nicht in der Datenbank war die Datenbankposition und Referenzen ...
jwenting

3
Es klingt immer albern, bis eines Tages jemand fragt: "Können wir das für Benutzer X neu konfigurieren, der es verlangt?", und dann scheint es doch nicht so albern. Verdammte Kunden :)
gbjbaanb

2
... und wenn dieser Tag "nie" ist, dann fühlt sich das lange Zeit albern an
Rob

2

Lassen Sie mich Ihnen eine ganz ernste Gegenfrage stellen: Was ist aus Ihrer Sicht der Unterschied zwischen "Daten" und "Code"?

Wenn ich das Wort "data" höre, denke ich "state". Daten sind per Definition das, wofür die Anwendung selbst entwickelt wurde, und daher genau das, was die Anwendung zur Kompilierungszeit niemals wissen kann. Es ist nicht möglich , Daten fest zu codieren, da sie, sobald Sie sie fest codieren, zu Verhalten werden und nicht zu Daten.

Die Art der Daten variiert je nach Anwendung. Ein kommerzielles Fakturierungssystem kann Kunden- und Bestellinformationen in einer SQL-Datenbank speichern, und ein Vektorgrafikprogramm kann Geometriedaten und Metadaten in einer Binärdatei speichern. In beiden Fällen und in allen dazwischen liegenden Fällen besteht eine klare und unzerbrechliche Trennung zwischen Code und Daten. Die Daten gehören dem Benutzer und nicht dem Programmierer, so dass sie niemals fest codiert werden können.

Was Sie zu reden scheinen, ist, die technisch genaueste Beschreibung zu verwenden, die meinem aktuellen Wortschatz zur Verfügung steht: Informationen über das Programmverhalten, die nicht in der primären Programmiersprache geschrieben sind, die zur Entwicklung des Großteils der Anwendung verwendet wurde.

Auch diese Definition, die deutlich weniger mehrdeutig ist als nur das Wort "Daten", weist einige Probleme auf. Was ist zum Beispiel, wenn wesentliche Teile des Programms in verschiedenen Sprachen geschrieben sind? Ich habe persönlich an mehreren Projekten mit etwa 50% C # und 50% JavaScript gearbeitet. Ist der JavaScript-Code "Daten"? Die meisten Leute würden nein sagen. Was ist mit HTML? Sind das "Daten"? Die meisten Leute würden immer noch nein sagen.

Was ist mit CSS? Sind das Daten oder Code? Wenn wir uns Code als etwas vorstellen, das das Programmverhalten steuert, dann ist CSS nicht wirklich Code, da es nur (nun ja, meistens) das Erscheinungsbild beeinflusst, nicht das Verhalten. Aber es sind auch keine wirklichen Daten; der Benutzer besitzt es nicht, die Anwendung besitzt es nicht einmal wirklich. Dies entspricht dem Code eines UI-Designers. Es ist Code- ähnlich , aber nicht ganz Code.

Ich könnte CSS als eine Art Konfiguration bezeichnen, aber eine praktischere Definition ist, dass es sich einfach um Code in einer domänenspezifischen Sprache handelt . Das ist es, was Ihre XML-, YAML- und anderen "formatierten Dateien" oft darstellen. Der Grund, warum wir eine domänenspezifische Sprache verwenden, ist, dass sie in der Regel in ihrer jeweiligen Domäne präziser und aussagekräftiger ist als die Codierung derselben Informationen in einer universellen Programmiersprache wie C oder C # oder Java.

Erkennen Sie das folgende Format?

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

Ich bin sicher, dass die meisten Leute das tun. Es ist JSON . Und hier ist das Interessante an JSON: In JavaScript ist es klarer Code und in jeder anderen Sprache sind es klar formatierte Daten. Fast jede Mainstream-Programmiersprache verfügt über mindestens eine Bibliothek zum "Parsen" von JSON.

Wenn wir genau dieselbe Syntax in einer Funktion in einer JavaScript-Datei verwenden, kann es möglicherweise nichts anderes als Code sein. Und doch, wenn wir diesen JSON nehmen, ihn in eine .jsonDatei schieben und in einer Java-Anwendung analysieren, sind es plötzlich "Daten". Ist das wirklich sinnvoll?

Ich behaupte, dass die "Daten-Ness" oder "Konfigurations-Ness" oder "Code-Ness" dem innewohnt, was beschrieben wird, und nicht, wie es beschrieben wird.

Wenn Ihr Programm ein Wörterbuch mit 1 Million Wörtern benötigt, um beispielsweise eine zufällige Passphrase zu generieren, möchten Sie sie folgendermaßen codieren:

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

Oder würden Sie einfach alle diese Wörter in eine durch Zeilen getrennte Textdatei schieben und Ihrem Programm anweisen, daraus zu lesen? Es spielt keine Rolle, ob sich die Wortliste nie ändert, es geht nicht darum, ob Sie hart oder weich codieren (was zu Recht von vielen als Antimuster angesehen wird, wenn es nicht richtig angewendet wird), es geht einfach darum, Welches Format ist am effizientesten und macht es am einfachsten, das "Zeug" zu beschreiben, was auch immer das "Zeug" ist. Es ist ziemlich irrelevant, ob Sie es Code oder Daten nennen; Es sind Informationen, die Ihr Programm benötigt, um ausgeführt zu werden, und ein Flat-File-Format ist die bequemste Methode, um es zu verwalten und zu warten.

Vorausgesetzt, Sie befolgen die richtigen Vorgehensweisen, wird all dieses Zeug sowieso in die Quellcodeverwaltung verschoben. Sie können es also genauso gut als Code bezeichnen, nur als Code in einem anderen und vielleicht sehr minimalistischen Format. Sie können es auch Konfiguration nennen, aber das einzige, was Code wirklich von Konfiguration unterscheidet, ist, ob Sie es dokumentieren und den Endbenutzern mitteilen, wie sie es ändern sollen oder nicht. Sie könnten sich vielleicht ein falsches Argument über die Interpretation der Konfiguration zum Startzeitpunkt oder zur Laufzeit und nicht zur Kompilierungszeit ausdenken, aber dann würden Sie damit beginnen, mehrere dynamisch typisierte Sprachen und mit ziemlicher Sicherheit alles mit einer darin eingebetteten Skript-Engine zu beschreiben (z. B. die meisten Spiele). Code und Konfiguration bestimmen Sie, ob Sie sie als, nicht mehr, nicht weniger, bezeichnen möchten.

Jetzt besteht die Gefahr, dass Informationen, deren Änderung nicht sicher ist, nach außen verlagert werden (siehe Link "Soft Coding" oben). Wenn Sie Ihr Vokalarray in einer Konfigurationsdatei externalisieren und es als Konfigurationsdatei für Ihre Endbenutzer dokumentieren, bieten Sie ihnen eine nahezu kinderleichte Möglichkeit, Ihre App sofort zu unterbrechen, indem Sie beispielsweise "q" als Vokal eingeben. Aber das ist kein grundsätzliches Problem bei der "Trennung von Code und Daten", es ist einfach ein schlechter Gestaltungssinn.

Was ich Junior-Entwicklern sage, ist, dass sie immer Einstellungen externalisieren sollten, die sich erwartungsgemäß pro Umgebung ändern. Dazu gehören beispielsweise Verbindungszeichenfolgen, Benutzernamen, API-Schlüssel, Verzeichnispfade usw. Sie können auf Ihrer Entwickler-Box und in der Produktion identisch sein, aber wahrscheinlich auch nicht. Die Systemadministratoren entscheiden, wie es in der Produktion aussehen soll, nicht die Entwickler. Sie müssen also die Möglichkeit haben, eine Gruppe von Einstellungen auf einige Maschinen und andere Einstellungen auf andere Maschinen anzuwenden - also externe Konfigurationsdateien (oder Einstellungen in einer Datenbank usw.).

Ich betone jedoch, dass es nicht gleichbedeutend ist, einige "Daten" in eine "Datei" einzufügen, wenn man sie als Konfiguration auslagert. Das Einfügen eines Wörterbuchs in eine Textdatei bedeutet nicht, dass Sie möchten, dass Benutzer (oder IT-Abteilung) es ändern. Es ist nur eine Möglichkeit, Entwicklern das Verstehen der Vorgänge zu erleichtern und erforderlichenfalls Änderungen vorzunehmen gelegentliche Änderungen. Ebenso gilt das Speichern derselben Informationen in einer Datenbanktabelle nicht unbedingt als Externalisierung des Verhaltens, wenn die Tabelle schreibgeschützt ist und / oder Datenbankadministratoren angewiesen werden, sich niemals damit zu beschäftigen. Die Konfiguration impliziert, dass die Daten veränderlich sind, in Wirklichkeit jedoch eher durch den Prozess und die Verantwortlichkeiten als durch die Wahl des Formats bestimmt werden.

Also, um zusammenzufassen:

  • "Code" ist kein fest definierter Begriff. Wenn Sie Ihre Definition um domänenspezifische Sprachen und alles andere erweitern, was das Verhalten beeinflusst, wird ein Großteil dieser offensichtlichen Reibung einfach verschwinden und alles wird Sinn machen. Sie können nicht kompilierten DSL- "Code" in einer Flatfile haben.

  • "Daten" implizieren Informationen, die den Benutzern oder zumindest einer anderen Person als den Entwicklern gehören und zur Entwurfszeit nicht allgemein verfügbar sind. Es könnte nicht hartcodiert werden, selbst wenn Sie dies wollten. Mit der möglichen Ausnahme von selbstmodifizierendem Code ist die Trennung zwischen Code und Daten eine Definitionssache und keine persönliche Präferenz.

  • "Soft-Codierung" kann eine schreckliche Praxis sein, wenn sie übermäßig angewendet wird, aber nicht jeder Fall von Externalisierung stellt notwendigerweise eine Soft-Codierung dar, und viele Fälle des Speicherns von Informationen in "flachen Dateien" sind nicht notwendigerweise ein ernsthafter Versuch der Externalisierung.

  • Die Konfiguration ist eine spezielle Art der Softcodierung, die aufgrund der Kenntnisse erforderlich ist , die die Anwendung möglicherweise in verschiedenen Umgebungen ausführen muss. Das Bereitstellen einer separaten Konfigurationsdatei zusammen mit der Anwendung ist weitaus weniger arbeitsaufwendig (und auch weniger gefährlich) als das Bereitstellen einer anderen Version des Codes in jeder Umgebung. So einige Arten von Soft-Codierung ist wirklich nützlich.


1

Ich schlage vor, diesen klassischen Artikel von Oren Eini (aka Ayende Rahien) zu lesen

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

Ich gehe davon aus, dass ich mich auf Einfachheit und Lesbarkeit konzentriere. Dies kann bedeuten, dass Dinge, die wahrscheinlich nicht neu konfiguriert werden, am besten (lesbar) fest codiert bleiben. Auf diese Weise können Sie die vollständige Syntax einer Programmiersprache verwenden, um die Parameter auszudrücken, und nützliche Nebenwirkungen wie die Vervollständigung des Codes und Compilerfehler bei Missbrauch erzielen.

Auf diese Weise vermeiden Sie möglicherweise die Komplexität des Parsens / Interpretierens ("aber jemand anderes analysiert mein YAML / JSON" - das Zuordnen von analysiertem Text zu den spezifischen API-Aufrufen kann eine Form des Interpretierens sein) und die Komplexität eines weiteren Schritts zwischen den "Daten" "und seine Verwendung.

In einigen Fällen ist es sogar in einem Szenario wie diesem möglich, in Daten ausgedrückt zu werden: Beispielsweise kann die Angabe von Tausenden von Punkten im 3D-Raum für eine Textdatei besser geeignet sein als Code, obwohl in einigen Sprachen, einschließlich C unter Verwendung von Strukturinitialisierern, Code kann auch dafür angemessen sein.


1

Ok, nehmen wir an, Sie möchten eine Art C ++ - Programm für Ihre Freizeit schreiben. Sie wissen genau, was es zu tun hat und was es niemals tun muss. Nehmen Sie jetzt ein Buch zum Thema "Modernes Softwaredesign". Hier ist die Spielregel: Für jede Klasse in Ihrem Projekt und für jeden noch so kleinen Fall müssen Sie jedes ausgefallene Muster implementieren, das Sie in diesem Buch beschrieben haben, um Ihren Code zu einem "sauberen Design" zu machen. Nun, "Abhängigkeitsinjektion" wird für viele Menschen ausreichen, denke ich. (Es ist C ++, nicht Java!) Die Programmierung wird von einem immer theoretischeren Standpunkt aus gelehrt. Es reicht nicht aus, dass Sie die Arbeit erledigen, Sie müssen Code schreiben, der wartbar ist, sich als Narr erweisen ... alles in Ordnung und in Ordnung. Das Problem beginnt, wenn ppl. hör auf über den eigentlichen grund nachzudenken, entwurfsmuster wurden erfunden und werden dogmatisch.

Ich möchte Sie davon abhalten, Ihr Briefzählwerkzeug nach einem einfachen Prinzip (über) zu schreiben: Wenn Sie Code schreiben, der einen bestimmten Job mit Eingabedaten eines bestimmten Typs ausführt, stellen Sie sicher, dass er diese Aufgabe für eine bestimmte Eingabe ausführen kann Daten dieses Typs. - Wenn Sie ein Buchstabenzählwerkzeug schreiben möchten, ist es natürlich sinnvoll, es so zu schreiben, dass es nicht nur Vokale, sondern "jeden Buchstaben" zählen kann. - Da Sie möglicherweise nicht wissen, was der Korpus ist, den Sie gerade analysieren, können Sie auch eine sehr allgemeine Codierung (UTF-16) auswählen und die meisten (alle?) Geschriebenen Sprachen und ihre Symbole abdecken.

Bis zu diesem Punkt haben wir eine Funktion mit zwei Argumenten (dem Korpus und den zu zählenden Buchstaben). Es geht uns nur darum, einen einigermaßen allgemeinen "Typ" oder "Klasse" zu finden, zu dem auch die Buchstaben gehören: Wir können es mit Sicherheit besser als ASCII-Symbole!

Geben Sie einen Dämon ein, der das Dogma "Verallgemeinerung und Wiederverwendbarkeit" führt: - Warum nicht ein Symbol einer Klasse in einem Eingabestream dieser Klasse zählen? (Zusammenfassung von Buchstaben zu Bitfolgen beliebiger, aber endlicher Länge, da dies die allgemeinste Methode ist, die Sie mit einem Computer erreichen können ...) - Warten Sie, auch dann zählen wir immer noch in natürlichen Zahlen. Das Zählen kann jedoch als Abbildung von einer abzählbaren Menge auf sich selbst verallgemeinert werden, wobei die Axiome erfüllt werden ...

Dieses Beispiel mag albern sein, aber wenn Sie komplexere Entwurfsaufgaben als ein Zählwerkzeug in Betracht ziehen, finden Sie möglicherweise alle Möglichkeiten, eine zusätzliche Abstraktion einzuführen, die für eine Art Entwurfsmuster erforderlich ist, das Sie in Ihrem Buch gefunden haben.

Die Trennung von "Daten" und "Code" ist wahrscheinlich entweder trivial (Funktionsargumente) oder Sie werden feststellen, dass Sie Invarianten als Variable ("Daten") behandeln.

Wenn es jemals Verwirrung gibt, ist es wahrscheinlich, dass "Schnittstellen" und "Dienste" und alle Klassenspezifikationen (z. B. Typen) plötzlich "Daten" sind, dh Abhängigkeiten, die von außen injiziert werden müssen. Ich bin der Meinung, dass Informatikkurse, die an der Universität unterrichtet werden, eher wie Vorlesungen in Philosophie geworden sind und weniger Zeit für echte Projekte bleibt, damit die Studenten Erfahrungen sammeln können, wie man Software macht, die funktioniert. Wenn Sie sich jemals fragen, warum Sie ein wahnsinnig komplexes Muster anstelle einer offensichtlichen Lösung verwenden müssen, ist diese Entwicklung (wahrscheinlich), wie diese Anforderung "geschaffen" wurde ...

Zu Ihrem spezifischen Problem: Wenn Sie 1.) ein Programm mit maximaler Hardcodierung für Ihren speziellen Fall schreiben könnten und dann 2.) diesen Code auf einfache Weise verallgemeinern könnten, indem Sie z. Wenn Sie mehr Funktionsargumente einführen und andere "triviale Muster" verwenden, können Sie sicher sein, dass Sie Code und Daten auf die naheliegende Weise trennen, wie es seit der Erfindung der funktionalen Programmierung der Fall war. (ofc du überspringst 1. und machst 2. sofort ...)

Alles, was hier nicht offensichtlich ist, ist wahrscheinlich ein Fall von "Theorie-Deadlock": Als würde man eine Schnittstelle schreiben, die sich auf eine Schnittstelle und eine weitere Schnittstelle bezieht ... und am Ende haben Sie eine nette kleine XML-Datei, um all diese Schnittstellen zu konfigurieren und die Abhängigkeiten, die in Ihr Klassen-Interface-Durcheinander eingefügt werden sollen.

Hoffen wir nur, dass der von Ihnen benötigte XML-Parser keine XML-Konfiguration benötigt, um zu funktionieren ...

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.