Wollte Dijkstra eine Modularisierung des Codes, als er über die Trennung von Bedenken schrieb?

9

Zuerst las ich einen Auszug aus Edsger W. Dijkstras 1974 erschienenem Artikel "Über die Rolle des wissenschaftlichen Denkens":

Lassen Sie mich versuchen, Ihnen zu erklären, was nach meinem Geschmack für jedes intelligente Denken charakteristisch ist. Es ist so, dass man bereit ist, einen Aspekt seines Themas aus Gründen seiner eigenen Konsistenz isoliert zu untersuchen, wobei man ständig weiß, dass man sich nur mit einem der Aspekte beschäftigt. Wir wissen, dass ein Programm korrekt sein muss, und wir können es nur unter diesem Gesichtspunkt studieren. Wir wissen auch, dass es effizient sein sollte und wir können seine Effizienz sozusagen an einem anderen Tag untersuchen. In einer anderen Stimmung fragen wir uns vielleicht, ob und warum das Programm wünschenswert ist. Aber nichts wird gewonnen - im Gegenteil! - wenn diese verschiedenen Aspekte gleichzeitig angegangen werden. Es ist das, was ich manchmal als "Trennung von Bedenken" bezeichnet habe, was, wenn auch nicht vollkommen möglich, ist noch die einzige verfügbare Technik zur effektiven Ordnung der eigenen Gedanken, die ich kenne. Das meine ich mit "die Aufmerksamkeit auf einen Aspekt lenken": Es bedeutet nicht, die anderen Aspekte zu ignorieren, sondern nur der Tatsache gerecht zu werden, dass der andere aus der Sicht dieses Aspekts irrelevant ist. Es ist gleichzeitig ein- und mehrspurig.

Ich sehe moderne Trennung von Bedenken über die Modularisierung Ihres Codes sprechen. Wenn ich jedoch das obige Zitat lese, verstehe ich dies so, dass Sie Ihren Geist jeweils auf eine bestimmte Aufgabe konzentrieren, ohne sich auf andere Aspekte zu konzentrieren. Dies bedeutet für mich nicht unbedingt, dass Code in modulare Blöcke unterteilt werden muss.

Das heißt, es befindet sich ein Code vor Ihnen, der in einer Datei die Konzepte Ansicht, Repository, Controller, Ereignisbehandlung, Factory usw. in einer Datei enthält.

Hier ein kurzes Beispiel für Code mit Datenzugriff und Ansicht (Ausgabe):

$sql = "SELECT * FROM product WHERE id = " . db_input($id);
$row = db_fetch_array(db_query($sql)); 
<option value="<?=$row['id']?>"<?= $row['ver'] == $row['ver'] ? '  selected="selected"' : '' ?>>Version <?=$row['ver']?></option>

Mit modernem OO konnte ich den Datenzugriff mithilfe des Repository-Musters in eine eigene Datei einfügen, der Ansichtscode kann in eine eigene Dateivorlage eingefügt werden, und ich kann diese miteinander verbinden, um über einen Controller (oder einen Aktions- oder Anforderungshandler) zu kommunizieren, und ich kann Fügen Sie eine Factory hinzu, um verschiedene Abhängigkeiten zu erstellen und zu verkabeln. Und ich kann eine Konfigurationsdatei haben, die diese Fabriken definiert. Sicherlich ist es ein Schritt weg von Single-File-All.

Meine Frage zur Trennung von Bedenken lautet wie folgt: Als ich Dijkstras Zitat las, kam mir die Idee, dass er vielleicht nicht unbedingt bedeutete, dass die Trennung von Bedenken "modulare Trennung von Code (in Dateien oder ihre eigenen Funktionen / Methoden / usw.)" ist. und dass er mehr darauf bedacht war, sich auf einen Aspekt des Programms zu konzentrieren, ohne sich auf andere wichtige, aber derzeit nicht zu berücksichtigende Aspekte zu konzentrieren, unabhängig davon, ob sie physisch im Code getrennt sind oder nicht.

Warum belasten wir uns dann mit physischen modularen Codetrennungs- und Entwurfsmustern? Wird es nicht ausreichen, sich nur auf einen Aspekt zu konzentrieren, unabhängig davon, wie Ihr Code aufgebaut ist?

Ich spreche nicht davon, den schrecklichsten Spaghetti-Code zu schreiben und dann nur einen Aspekt davon zu betrachten, das wäre wahrscheinlich eine Belastung. Aber am Ende gehe ich dahin, warum die physische Codetrennung durchführen, warum den Code in getrennte Dateien oder Blöcke (Methoden) aufteilen, wenn es nicht notwendig ist, sich mental auf einen Aspekt zu konzentrieren?

Sollte die Trennung von Bedenken eher eine mentale als eine physische Übung bleiben?
Mit anderen Worten, sollte es eine Trennung zwischen den mentalen (Fokus auf) und den physischen (Code auf Papier) Aspekten der Programmierung geben?

Dennis
quelle
5
Ich bin mir ziemlich sicher, dass er 1974 die modulare Programmierung als selbstverständlich ansah, und deshalb hat er sie in diesem Artikel nicht explizit erörtert. Parnas' Papier über , wie man modularisieren war im Jahr 1972, und bis zu diesem Zeitpunkt , ob zu modularisieren war schon nicht mehr eine Frage. Was Sie beschreiben, ist nicht einmal modulare Programmierung, sondern strukturierte Programmierung , für die Dijkstra selbst bereits 1968 in seinem klassischen Artikel "Go To Considered Harmful" stark plädierte.
Jörg W Mittag
Okay, vielleicht kann ich "Trennung von Bedenken" eher als mentale Fokusübung und Modularisierung als eine Möglichkeit verstehen, einen Aspekt des Codes auf Papier zusammenzufassen. Jetzt sehe ich jedoch die Trennung von Bedenken und die Modularisierung eher als getrennte Konzepte.
Dennis
@ JörgWMittag, können Sie zwischen strukturierter und modularer Programmierung unterscheiden? Einige Links auf Google deuten darauf hin, dass sie gleich sind.
Dennis
Strukturierte = IF, WHILE, FORstatt GOTO. Modular = Module mit einer genau definierten öffentlichen API, die streng von einer versteckten internen Implementierung und Darstellung getrennt ist. (ZB Modula, Mesa, Modula-2, Modula-3, später Pascal-Dialekte ( UNIT).)
Jörg W Mittag

Antworten:

2

Dijkstra macht eine explizite Aussage darüber, wie man denkt. Die Modularisierung von Programmen (und Prozessen) - und ihre Wünschbarkeit - ist möglicherweise ein Ergebnis dieses Denkens, aber der entscheidende Punkt, den er macht, ist die Bewertung eines Problems. Das Programm ist in der Regel die Lösung eines Problems, und indem er eine "Trennung von Bedenken" befürwortet, bietet er kluge Ratschläge an. Das beste Beispiel dafür ist vielleicht "Optimierung". Der Witz war: "Wenn Sie planen, ein Programm zu optimieren, sollte Ihre erste Strategie sein: Nicht." Mit anderen Worten, Sie möchten sich darauf konzentrieren, zuerst das Programm korrekt zu machen. Es schnell und ausgefallen zu machen, ist ein Anliegen, das getrennt werden sollte - aber auch nicht vollständig entfernt werden sollte.

MCL
quelle
14

Die Trennung von Anliegen ist eine abstrakte Denkweise, die darin besteht, Dinge, die nicht in Beziehung gesetzt werden müssen, getrennt zu betrachten.

Modularisierung (Trennung nicht verwandter Funktionsgruppen in Module), Kapselung (Ausblenden interner Details der Module) und Abstraktion (Trennung des Allgemeinen vom Spezifischen und der Idee von ihrer Implementierung) sind Mittel, um diese Denkweise in der Domäne zu implementieren des Software-Designs.

Christophe
quelle
9

Ich würde vorschlagen, dass, obwohl das Papier von historischem Interesse ist, das, was Dijkstra vor über 40 Jahren mit dem Begriff "Trennung von Bedenken" meinte, heute nicht besonders relevant ist. Heutzutage wird es häufig in Bezug auf die Modulisierung verwendet.

Es gibt eine Fülle von Beweisen dafür, dass die Modulation von großem Nutzen ist und dass diese Vorteile die "Belastungen", die sie uns auferlegt, bei weitem überwiegen. Was auch immer Dijkstra damals bedeutete, ändert nichts an der Tatsache, dass kleine Codestücke, die sich jeweils nur auf eine Sache konzentrieren, zu Code führen, der einfacher zu schreiben, zu lesen, zu verstehen, zu warten und zu testen ist.

David Arno
quelle
5
Ich denke, es sollte angemerkt werden, dass ein Großteil des modernen Denkens über die Trennung von Bedenken aus frühen Veröffentlichungen stammte, aus denen schließlich die aspektorientierte Programmierung von IBM hervorging. Ich denke, die ersten Arbeiten (Ende der 90er bis Anfang der 2000er Jahre) sind dort der größte Einfluss. Es ist eine Weile her und die Websites haben sich alle geändert. Ich bin mir nicht sicher, ob ich sie überhaupt wiederfinden kann.
Berin Loritsch
2
Der schwierige Teil ist zu definieren, was "eine Sache" bedeutet. Ohne dies ist die Idee für das praktische Schreiben von Code nutzlos, und wenn sie falsch verstanden wird, wirkt sich dies sofort nachteilig auf die Schwierigkeit aus, den Code zu schreiben, zu lesen, zu verstehen, zu warten und zu testen.
jpmc26
1
Es würde uns wirklich helfen, Ihre Position zu verstehen, wenn Sie (a) erklären würden, was Dijkstra Ihrer Meinung nach mit "Trennung von Bedenken" meinte, und (b) erklären, WARUM Sie denken, dass das, was er meinte, nicht mehr relevant ist.
John R. Strohm
2

Ich kann Ihnen ein persönliches Beispiel für die Trennung von Bedenken geben, die meiner Meinung nach mit den Konzepten von Dijkstra vergleichbar ist. Wenn ich ein bestimmtes Thema in Software analysiere, konstruiere ich drei Ansichten.

  1. Zuerst betrachte ich die Daten. Die Daten repräsentieren die logischen Prädikate des Problems. Klassen werden zu abstrakten Entitäten in der realen Welt konstruiert, wobei ihre Attribute die Parameter der Abstraktion sind. Zuordnungen zwischen Klassen repräsentieren funktionale Zuordnungen zwischen den Klasseninstanzen. Zu diesem Zeitpunkt ist kein Code in das Denken involviert und es gibt keine Vorstellung von einer Verarbeitung. Nur eine statische Ansicht der Logik, die mit dem Thema verbunden ist.
  2. Zweitens betrachte ich die Dynamik. Jede Klasse mit einem nicht trivialen Lebenszyklus wird als endliche Zustandsmaschine modelliert. Dies beinhaltet Überlegungen zur Sequenzierung der Ausführung und Synchronisation. Wieder kein Code, der nur herausfindet, wie die Dinge interagieren und ablaufen.
  3. Drittens betrachte ich die Verarbeitung. Hier die eigentliche algorithmische Arbeit, die bei Zustandsübergängen oder bei anderen synchronen Operationen ausgeführt werden muss.

Am Ende erhält man eine dreifach facettierte Ansicht des Themas, die dann als Code in den für den Code selbst und seine Pflege geeigneten Gruppierungen formuliert werden kann. Die drei Facetten sind nicht nur eine mentale Übung. Ich erstelle schriftliche Beschreibungen aller Facetten. Warum? Denn wenn das Thema groß genug ist, kann ich nicht einmal eine vollständige Facette im Kurzzeitgedächtnis halten. Wenn das Thema klein ist, funktioniert fast jeder Ansatz, da Sie alles im Kopf behalten können.

Die Motivation zur Trennung von Bedenken besteht darin, den Einschränkungen des Kurzzeitgedächtnisses des Menschen Rechnung zu tragen. Wir können einfach nicht alles auf einmal in unseren Köpfen tragen, obwohl Computerprogrammierer in der Regel fähiger sind als die meisten anderen Leute, was die Anzahl der Konzepte betrifft, die sie in ihrem Kurzzeitgedächtnis manipulieren können. Um effektiv zu sein, müssen Bedenken systematisch getrennt werdeneinen oder mehrere Aspekte eines Problems ausschließen, um sich auf einen anderen bestimmten Aspekt zu konzentrieren. Das Ausschließen eines Aspekts lässt ihn natürlich nicht aus der Betrachtung verschwinden. Es muss ein Mittel geben, um alle Problemaspekte zu kombinieren, um eine Lösung zu erreichen. Die Erfahrung zeigt, dass das Endergebnis des Trennens und Rekombinierens häufig eine verständlichere Lösung ergibt als ein einzelner großer Sprung, bei dem viele Aspekte durcheinander gebracht werden können. Dies ist insbesondere dann der Fall, wenn das Problem groß oder kompliziert ist.

Andy Mango
quelle
1

Die Trennung von Bedenken ist ein logisches Konzept, das sich in Ihr Code-Organisationsmodell ausbreitet, unabhängig davon, wie Sie es implementieren. Es ist wahr, dass eine Codedatei nur ein technisches Detail ist, eine Möglichkeit, Ihre Software verwaltbar zu halten. Eine einzelne Datei mit einem guten Editor, mit dem eine Erweiterung von Regionen reduziert werden kann, funktioniert möglicherweise auch für Sie (für eine Weile). Oder eine relationale Datenbank, in der Klassen und Methoden auf Eltern-Kind-Weise in separaten Tabellen gespeichert werden, kann als Speichermedium fungieren. Aber Textdateien sind in einer Welt, in der Quellcode sein muss, schwer zu schlagen

  • tragbar
  • Zugriff durch viele verschiedene externe Tools
  • Zugriff für mehrere Programmierer
  • versionierbar und vergleichbar
  • Skalieren Sie gut mit Betriebssystemen, die im Umgang mit Dateien sehr gut sind

Das Fazit ist, dass wir Menschen nicht sehr gut darin sind, über verschiedene Dinge gleichzeitig nachzudenken oder damit umzugehen. Wir brauchen also ein Modell, das es ermöglicht, über eine Sache gleichzeitig nachzudenken und daran zu arbeiten, ohne die Gefahr zu haben, einen anderen Teil zu ruinieren, den wir zu diesem Zeitpunkt nicht in Betracht ziehen. Wir bauen also, indem wir jeweils einen Stein verlegen, um sicherzustellen, dass die zuvor verlegten Steine ​​die später verlegten Steine ​​nicht beeinträchtigen. Und wenn wir später einen Stein wechseln wollen, dürfen die Dinge nicht zusammenbrechen. Das ist ein Modell, das für unsere einspurigen Köpfe funktioniert.

So wachsen jedoch keine Pilze oder Algen ... Wie ist das für eine demütigende Tatsache?

Martin Maat
quelle
-1

Ich glaube, die spezifische Antwort auf Dijkstras Zitat wurde jedoch angesprochen, da Sie sagen: "Mit modernem OO könnte ich den Datenzugriff in eine eigene Datei einfügen" und fragen: "Sollte die Trennung von Bedenken eher eine mentale als eine physische Übung bleiben?" Lassen Sie mich Ihre Aufmerksamkeit darauf lenken, wohin uns moderne OO-Prinzipien führen.

Bei der Entwicklung mit OO sollte man den SOLID-Prinzipien folgen. Hier ist ein netter Link für sie, aber die TLDR zur "Trennung von Bedenken" befindet sich hauptsächlich im S in SOLID: The Single Responsibility Principle oder SRP.

Dies ist definitiv eine körperliche Übung, keine geistige. In Ihrem speziellen Beispiel weist MVC (oder seine Geschwister MVVM und MVP) an , die Konzerte von Model, View und Controller / Presenter / ViewModel physisch in separate Dateien aufzuteilen. Ich habe einige MVVM-Implementierungen gesehen, bei denen diese in separaten Assemblys implementiert sind, um die Tendenz, Konzepte zu verwechseln, weiter einzuschränken.

Aber. Es geht über das einfache "Dies ist eine Ansicht und dies ist ein Modell" hinaus, wenn Sie Onkel Bobs Ansicht dazu folgen .

Man muss auch die Quelle der Anforderungen für ein bestimmtes OO-Element berücksichtigen . Wenn Sie beispielsweise mischen, was der Kunde mit dem, was das Betriebspersonal will, will, verletzen Sie auch die SRP. Oder, um es so auszudrücken wie Onkel Bob: Eine Klasse sollte nur einen Grund haben, sich zu ändern.

Ich empfehle Ihnen dringend, dies über die angegebenen Links weiter zu recherchieren oder im Internet nach "soliden Prinzipien" zu suchen.

Reginald Blue
quelle
Nein. SOLID-Prinzipien sind so weit von der Realität des tatsächlichen Schreibens von Code (= philosophisch) entfernt, dass sie nur dann auf eine entfernt nützliche Weise verstanden werden können, wenn Sie bereits wissen, wie man guten Code schreibt. An diesem Punkt sind sie bestenfalls überflüssig. Wenn Sie sie als Leitprinzipien verwenden, ohne bereits Erfahrung und Fähigkeiten zu haben, wird extrem schlechter Code erzeugt.
jpmc26