Verstößt "Konvention über Konfiguration" nicht gegen grundlegende Programmierprinzipien?


51

Ich habe mir das WPF MVVM Framework Caliburn.Micro angesehen und gelesen, dass viele Standard-Dinge auf Namenskonventionen basieren .

Beispiel: Automatische Bindung von Eigenschaften in der Ansicht an Eigenschaften im ViewModel. Obwohl dies praktisch zu sein scheint (entfernt einen Teil des Kesselschild-Codes), ist meine erste instinktive Reaktion, dass es für einen neuen Programmierer, der diesen Code liest, nicht völlig offensichtlich ist. Mit anderen Worten, die Funktionalität der Anwendung wird nicht vollständig durch ihren eigenen Code erklärt, sondern auch durch die Dokumentation des Frameworks.

BEARBEITEN:

Dieser Ansatz heißt also Konvention über Konfiguration. Da ich dazu keine Fragen finden konnte, habe ich meine Frage geändert:

Meine Frage ist:

Ist Konvention über Konfiguration eine richtige Art, Dinge zu vereinfachen, oder verletzt sie einige Programmierprinzipien (und wenn ja, welche)?


8
Die meisten Ansätze / Prinzipien verstoßen in gewissem Maße gegen andere Ansätze / Prinzipien. Es geht hauptsächlich um Prioritäten und Kompromisse.
Joachim Sauer

1
Stimmt, aber ich finde den in meiner Frage angegebenen Unterschied etwas merkwürdig, und deshalb interessiere ich mich für die spezifischen Kompromisse und möglicherweise verletzten Prinzipien bei der Verwendung von Konventionen gegenüber Konfigurationen.
Geerten

Das Konzept der Software-Rückverfolgbarkeit ist hier relevant. Programmierer verlassen sich auf Tools wie grep, benötigen jedoch bessere Tools, um die Verwendung des generierten Codes nachzuverfolgen. Tools sollten beispielsweise expliziter machen, dass die CSS-Klasse "user-id" mit der generierten Methode getUserId () und der Tabellenspalte user_id verknüpft ist.
Macneil

Antworten:


49

Ich halte "eine Anwendung sollte vollständig durch ihren eigenen Code erklärt werden" nicht für ein grundlegendes Programmierprinzip. Es gibt viele Dinge, die nicht nur durch den Code einer Anwendung erklärt werden. Abgesehen von den grundlegenden Dingen der Programmiersprache selbst (Syntax und Semantik) müssen Sie die Konventionen kennen. Wenn ein Bezeichner in Java mit einem Großbuchstaben beginnt, handelt es sich um einen Typ. Es gibt viele dieser Konventionen, die Sie kennen müssen.

Bei der Konvention über die Konfiguration geht es darum, die Anzahl der Entscheidungen zu reduzieren, die der Programmierer in Bezug auf bestimmte Dinge treffen muss. Für einige Dinge ist dies offensichtlich - niemand würde in Betracht ziehen, eine Sprache zu haben, in der die Großschreibung von Typen etwas ist, das Sie oben in Ihrem Programm deklarieren müssen - für andere Dinge ist dies jedoch nicht so offensichtlich.

Das Abwägen von Konvention und Konfiguration ist eine schwierige Aufgabe. Zu viele Konventionen können den Code verwirren (zum Beispiel die impliziten Variablen von Perl). Zu viel Freiheit auf Seiten des Programmierers kann das Verständnis von Systemen erschweren, da das Wissen, das aus einem System gewonnen wird, beim Studium eines anderen Systems selten nützlich ist.

Ein gutes Beispiel dafür, wo die Konvention dem Programmierer hilft, ist das Schreiben von Eclipse-Plugins. Wenn ich mir ein Plugin ansehe, das ich noch nie gesehen habe, weiß ich sofort viele Dinge darüber. Die Liste der Abhängigkeiten befindet sich in MANIFEST.MF, die Erweiterungspunkte in plugin.xml, der Quellcode unter "src" und so weiter. Wenn es dem Programmierer überlassen wäre, diese Dinge zu definieren, wäre jedes einzelne Eclipse-Plugin anders, und die Code-Navigation wäre viel schwieriger.


4
+1: Softwareentwicklung ist schon kompliziert genug. Wenn Sie Komplexität in Dingen vermeiden können, auf die Sie Einfluss haben, tun Sie dies. Speichern Sie die Komplexität für Orte, die Sie unbedingt benötigen.
Scrwtp

1
Vielen Dank für die klare Erklärung über den Unterschied und das Gleichgewicht.
Geerten

3
"Wenn ein Bezeichner in Java mit einem Großbuchstaben beginnt, handelt es sich um einen Typ." - Ob es sich um einen Typ handelt, hängt vom Syntaxkontext und nicht vom Namensmuster ab. Die Java-Namenskonventionen wirken sich nicht auf die 'Kompilierungskonfiguration' aus. Sind Sie sicher, dass es ein gültiges Beispiel ist? Das letzte Beispiel ist ebenfalls nicht korrekt - es geht um "Konfigurationskonventionen", nicht um "Konvention über Konfiguration". Sie sagen die richtigen Dinge, aber sie haben wenig mit dem Subjektprinzip zu tun.
Den

4
Überanalysieren Sie die Beispiele nicht, sie sind nur Beispiele. Der erste ist nur ein Beispiel für eine Konvention, der letzte ist ein Beispiel für eine gute Konvention. Das Perl-Beispiel ist ein Beispiel, in dem zu viele Konventionen (Impliziten) eine schlechte Sache sind (IMO, sollte ich hinzufügen).
JesperE

1
Das, was ich hasse, ist, wenn Konvention über Konfiguration zu Konvention ohne Konfiguration wird. In letzterem Fall neigt man dazu, mit einer Codebasis gefangen zu sein. Es kann schwierig sein, sie in andere Tools zu integrieren.
Andy

77

Hat @JesperE +1 gegeben und möchte etwas hinzufügen:

Verstößt es gegen einige Programmierprinzipien?

Ja, "Konvention über Konfiguration" verstößt gegen das Prinzip "explizit ist besser als implizit" (siehe beispielsweise "Zen-Of-Python" ).

Andererseits verstößt die entgegengesetzte "Konfiguration über Konvention" tendenziell gegen "Einfach ist besser als komplex", und noch schlimmer, sie verstößt auf subtile Weise gegen das DRY-Prinzip , da Sie die in Ihrem Code verwendeten Namen auch in Ihrer Konfiguration wiederholen müssen .


4
Das ist die direkteste Antwort auf die Frage!
Joachim Sauer

Dies ist die eigentliche richtige Antwort unter den zwei am meisten verärgerten.
Den

+1 für "explizit ist besser als implizit"
Justin Ohms

12
Mein Lieblingsteil an dieser Antwort ist, dass sie implizit die Realität hervorhebt, während Prinzipien guter Softwareentwicklung oft in Spannung miteinander stehen. Beim Engineering geht es darum, diese Spannungen entsprechend Ihrem spezifischen Kontext und Ihrer Anwendung auszugleichen.
Chris Krycho

Gute Antwort. Um den Kommentar von @Chris Krycho zu erweitern, ist das Schöne an Software-Standards oder -Prinzipien, dass Sie so viele zur Auswahl haben. :-)
user949300

9

Ein Teil der "Konvention über Konfiguration" läuft nur auf vernünftige Standardeinstellungen hinaus. Sie sollten nur etwas konfigurieren müssen, um es für einen nicht standardmäßigen Zweck zu verwenden. Ich muss hier Struts mit Rails vergleichen. In Rails musst du deine "Actions / Screens" in einen Ordner legen und dann funktionieren sie einfach. In Struts müssen Sie sie noch in einem Ordner ablegen, aber Sie müssen auch einen Aktionsnamen UND eine JSP-Datei UND einen Formularnamen UND eine Formular-Bean erstellen UND angeben, wie diese drei Dinge in Struts-config zusammenarbeiten. xml UND geben Sie an, dass das Formular zur Anforderung gehört (RESTful). Wenn dies nicht ausreicht, verfügt das Form / Form-Bean-Mapping über einen eigenen Abschnitt in Struts-config, der dann unabhängig dem Aktionsabschnitt in derselben Datei zugeordnet wird und für die Arbeit auf handgeschriebene Zeichenfolgen in der JSP-Datei angewiesen ist richtig. Für jeden Bildschirm Das sind mindestens 6 Dinge, die Sie nicht tun sollten, und ebenso viele Möglichkeiten, einen Fehler zu machen. Ich denke, Sie können die meisten oder alle diese Dinge in Rails manuell einstellen, wenn Sie müssen, aber 2/3 der Struts-Entwicklungszeit wird für den Aufbau und die Aufrechterhaltung unnötiger Komplexitätsebenen benötigt.

Um ehrlich zu sein, wurde Struts 1 entwickelt, als Benutzer Anwendungen zwischen dem Desktop und dem Web portierten. Die Flexibilität, die Struts eingebaut hat, macht es für alles, was Rails macht, sowie für alles, was eine Desktop-Anwendung benötigen würde, geeignet. Leider ist der Konfigurationsberg, der diese Flexibilität ermöglicht, ein riesiger Ball und eine riesige Kette für jemanden, der nur eine Web-App oder nur eine Desktop-App schreiben muss.

Ich habe irgendwo gearbeitet, wo sie den nächsten Schritt unternahmen und argumentierten: "Konfiguration über Code ", aber nachdem sie gesehen haben, dass dies zu einem logischen Extrem wurde, ist das Ergebnis, dass die Konfiguration zu einer neuen Codierungssprache wird. Es war ein Shell-Spiel, bei dem die Komplexität gesteigert wurde, ohne in irgendeiner Weise gezähmt zu werden. Und es gab mir eine Anerkennung für all die Typenkontrollen und anderen Sicherheitsnetze, die eine gut gestaltete Programmiersprache hat. Einige halbfertige Konfigurationsdateiformate, die beim Hinzufügen eines Leerzeichens oder eines Apostrophs ohne Fehlermeldung in die Luft gejagt werden, sind KEINE Verbesserung gegenüber einer hochwertigen Programmiersprache, die über eine Reihe von Bearbeitungswerkzeugen und einen dafür geschriebenen Qualitätscompiler verfügt.

Ich kann mir nicht vorstellen, dass vernünftige Standardeinstellungen gegen theoretische Prinzipien in Bezug auf Erweiterbarkeit und Modularität verstoßen. Ein Ruby / Rails-Programmierer würde eher ein heißes Poker in die Augen bekommen, als zu einem Framework wie Struts 1 zu wechseln, bei dem alle Konfigurationen explizit in mehreren XML-Dateien vorgenommen werden. Ich diskutiere nicht generell über Rails vs. Struts, aber diese Konvention kann einen enormen Produktivitätsgewinn bedeuten. Diese beiden Technologien sind die extremsten Vergleiche in der Praxis, die mir begegnet sind.

Wenn Sie überhaupt in Java arbeiten, lesen Sie Joshua Blochs "Effective Java", Punkt 2: "Betrachten Sie einen Builder, wenn Sie mit vielen Konstruktorparametern konfrontiert werden", S. 11-16. Für die meisten Zwecke sind einige Parameter (Konfiguration) erforderlich, andere sind optional. Die Grundidee besteht darin, nur die erforderliche Konfiguration zu erfordern und den Benutzer (bei dem es sich auch um ein anderes Programm handeln könnte) zu veranlassen, bei Bedarf zusätzliche Optionen anzugeben. Ich habe vor einem Monat eine Menge Code mit diesem Muster aufgeräumt und es funkelt positiv.


7

Mit anderen Worten, die Funktionalität der Anwendung wird nicht vollständig durch ihren eigenen Code erklärt, sondern auch durch die Dokumentation des Frameworks.

Die Funktionalität einer Anwendung, die ein Framework verwendet, hängt immer vom Framework ab. Die Konvention über die Konfiguration spielt in dieser Hinsicht keine Rolle.

Nach meiner Erfahrung macht die Konvention über die Konfiguration nicht nur den Code lesbarer, sondern verringert auch die Möglichkeit, subtile Fehler einzuführen (insbesondere Fehler beim Kopieren und Einfügen).

Nehmen wir beispielsweise an, dass in einem Framework A das Ereignis FooBareinen Aufruf von auslöst handleFooBar. In einem anderen Framework B wird diese Korrelation irgendwo in einer XML-Datei konfiguriert.

In A ist es einfach

handleFooBar() {
   ...
}

und es sei denn, Sie haben FooBar falsch geschrieben, wird es aufgerufen, wann immer FooBar passiert.

In B ist es wieder

handleFooBar() {
   ...
}

aber auch

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

Mit Hunderten von Dingen, die auf diese Weise konfiguriert werden müssen, ist es allzu einfach, versehentlich einen subtilen Fehler wie diesen zu erzeugen

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

Denn nach dem Einfügen haben wir uns nur geändert, <type>aber vergessen , uns zu ändern <handler>.

Da diese Konfigurationsdateien groß und eintönig sind, ist es weniger wahrscheinlich, dass jemand den Fehler durch Korrekturlesen findet, als dass er einen ähnlichen Fehler im tatsächlichen Programmcode findet.


1
+1: Das Vermeiden von sich wiederholenden, langweilig zu schreibenden, schwer zu lesenden, fast immer offensichtlichen Konfigurationen ist der Hauptvorteil von Konventionen gegenüber Konfigurationen.
Joachim Sauer

-1

Es verstößt möglicherweise gegen einige wenige Prinzipien, befolgt jedoch gleichzeitig eines der grundlegendsten Designprinzipien, das SRP (Single Responsibility Principle).


2
Die Verwendung von Konventionen hat nichts mit der alleinigen Verantwortung zu tun. Ich könnte eine Konvention verwenden und 100 Dinge darin tun.
Suamere,
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.