Ich bin etwas neu in der Programmierung (ich bin von Beruf Maschinenbauingenieur) und entwickle während meiner Ausfallzeit ein kleines Programm, das einen (Solidworks-) Teil auf der Grundlage von Eingaben verschiedener Mitarbeiter aus der gesamten Anlage generiert.
Basierend auf nur wenigen Eingaben (6 um genau zu sein) muss ich Hunderte von API-Aufrufen durchführen, die jeweils bis zu einem Dutzend Parameter aufnehmen können. Alles wird durch eine Reihe von Regeln generiert, die ich nach einem Interview mit allen Personen, die mit dem Teil befasst sind, gesammelt habe. Der Regel- und Parameterbereich meines Codes ist 250 Zeilen lang und wächst.
Was ist der beste Weg, um meinen Code lesbar und verwaltbar zu halten? Wie unterteile ich alle meine magischen Zahlen, alle Regeln, Algorithmen und prozeduralen Teile des Codes? Wie gehe ich mit einer sehr ausführlichen und detaillierten API um?
Mein Hauptziel ist es, jemandem meine Quelle zu geben und ihn verstehen zu lassen, was ich getan habe, ohne meinen Beitrag zu leisten.
quelle
Antworten:
Basierend auf Ihrer Beschreibung werden Sie wahrscheinlich die wunderbare Welt der Datenbanken erkunden wollen. 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. Sie werden viel mehr Glück haben und es auf lange Sicht viel einfacher finden, die Anwendung zu erweitern, wenn Sie kategorisieren können, wie sich die Daten auf die Teile beziehen, und eine Datenbankstruktur dafür definieren können.
Denken Sie daran, dass 'Datenbanken' nicht unbedingt MySQL oder MS-SQL bedeuten müssen. Wie Sie die Daten speichern, hängt stark davon ab, wie das Programm verwendet wird, wie Sie es schreiben usw. Es kann sich um eine SQL-Datenbank oder einfach um eine formatierte Textdatei handeln.
quelle
Sofern Sie nicht damit rechnen, dies auf mehrere Teile auszudehnen, würde ich nur ungern eine Datenbank hinzufügen. Wenn Sie über eine Datenbank verfügen, müssen Sie eine Menge lernen und mehr installieren, damit sie für andere Benutzer funktioniert. Durch das Hinzufügen einer eingebetteten Datenbank bleibt die endgültige ausführbare Datei portabel, aber jemand mit Ihrem Quellcode muss jetzt noch eine Sache erledigen.
Ich denke, eine Liste klar benannter Konstanten und regelimplementierender Funktionen wird viel helfen. Wenn Sie alle natürlichen Namen vergeben und sich auf gebildete Programmiertechniken konzentrieren , sollten Sie in der Lage sein, ein lesbares Programm zu erstellen.
Im Idealfall erhalten Sie folgenden Code:
Abhängig davon, wie lokal die Konstanten sind, wäre ich versucht, sie in den Funktionen zu deklarieren, in denen sie verwendet werden, wo dies möglich ist. Das Wenden ist ganz nützlich:
in
Das gibt Ihnen weitgehend selbstdokumentierenden Code und ermutigt jeden, der den Code ändert, dem, was er hinzufügt, ähnlich aussagekräftige Namen zu geben. Durch das Starten von local wird es auch einfacher, mit der Gesamtzahl der Konstanten umzugehen, die Sie akkumulieren. Es wird etwas ärgerlich, wenn Sie eine lange Liste von Konstanten durchblättern müssen, um sicherzustellen, dass der Wert dem gewünschten Wert entspricht.
Ein Tipp für Namen: Schreiben Sie das wichtigste Wort nach links. Es liest sich vielleicht nicht ganz so gut, erleichtert aber das Auffinden. Meistens schauen Sie auf einen Sumpf und fragen sich, wo der Bolzen ist, nicht auf einen Bolzen und fragen sich, wo er sich befindet. Nennen Sie ihn also SumpBoltThreadPitch, nicht BoltThreadPitchSump. Sortieren Sie dann die Liste der Konstanten. Um später alle Gewindesteigungen zu extrahieren, können Sie die Liste in einem Texteditor abrufen und entweder die Suchfunktion verwenden oder ein Tool wie grep verwenden, um nur die Zeilen zurückzugeben, die "ThreadPitch" enthalten.
quelle
.CreateLine(m_trunion_support_spacing / 2, -((m_flask_length / 2) + m_sand_ledge_width + m_wall_thickness), -m_flange_thickness, m_trunion_support_spacing / 2, -((m_flask_length / 2) + m_sand_ledge_width + m_wall_thickness), -m_flask_height + m_flange_thickness)
createGroove(length, depth)
. Sie müssen Funktionen implementieren, die beschreiben, was Sie erreichen möchten, wie Sie es einem Maschinenbauer beschreiben würden. Darum geht es beim Lesen und Schreiben.Ich denke, Ihre Frage reduziert sich auf: Wie strukturiere ich eine Berechnung? Beachten Sie, dass Sie "eine Reihe von Regeln" verwalten möchten, bei denen es sich um Code handelt, und "eine Reihe von magischen Zahlen", bei denen es sich um Daten handelt. (Sie können sie als "in Ihren Code eingebettete Daten" betrachten, aber es handelt sich trotzdem um Daten).
Darüber hinaus ist es das allgemeine Ziel aller Programmierparadigmen, Ihren Code für andere "verständlich" zu machen (siehe z. B. " Implementation Patterns " von Kent Beck oder " Clean Code " von Robert C. Martin für Autoren von Software, die dasselbe Ziel angeben wie Sie, für jedes Programm).
Alle Hinweise in diesen Büchern gelten für Ihre Frage. Lassen Sie mich einige Hinweise speziell für "magische Zahlen" und "Regelsätze" extrahieren:
Verwenden Sie benannte Konstanten und Aufzählungen, um magische Zahlen zu ersetzen
Beispiel für Konstanten :
sollte durch eine benannte Konstante ersetzt werden, damit keine späteren Änderungen einen Tippfehler verursachen und Ihren Code beschädigen können, z. B. durch Ändern der ersten,
0.625
aber nicht der zweiten.Beispiel für Aufzählungen :
Durch Aufzählungen können Sie zusammengehörige Daten zusammenstellen. Wenn Sie Java verwenden, denken Sie daran, dass Enums Objekte sind. Ihre Elemente können Daten enthalten, und Sie können Methoden definieren, die alle Elemente zurückgeben, oder einige Eigenschaften überprüfen. Hier wird eine Aufzählung verwendet, um eine andere Aufzählung zu erstellen:
Der Vorteil ist: Jetzt kann niemand ein EnginePart falsch definieren, das nicht aus Stahl oder Kohlenstoff besteht, und niemand kann ein EnginePart mit dem Namen "asdfasdf" einführen, wie es der Fall wäre, wenn es eine Zeichenfolge wäre, die auf Inhalt überprüft würde.
Das Strategy - Muster und das Factory - Methodenmuster beschreiben, wie "Regeln" gekapselt und an ein anderes Objekt übergeben werden, das sie verwendet (im Falle des Factory - Musters baut die Verwendung etwas auf; im Falle des Strategy - Musters das Nutzung ist was immer Sie wollen).
Beispiel für ein Factory-Methodenmuster :
Stellen Sie sich vor , Sie haben zwei Arten von Motoren: ein , wobei jeder Teil hat mit dem Kompressor verbunden ist, und eine , wo jeder Teil kann frei unabhängig von anderen Teilen verbunden werden. Aus Wikipedia übernommen
Und dann in einer anderen Klasse:
Der interessante Teil ist: Jetzt ist Ihr Fertigungslinienkonstruktor von der Art der zu bearbeitenden Engine getrennt. Vielleicht
addEngine
rufen die Methoden eine entfernte API auf ...Beispiel für ein Strategiemuster :
Das Strategiemuster beschreibt, wie Sie eine Funktion in ein Objekt einfügen, um dessen Verhalten zu ändern. Stellen Sie sich vor, Sie möchten ein Teil manchmal polieren, manchmal malen und standardmäßig die Qualität überprüfen. Dies ist ein Python-Beispiel, das von Stack Overflow übernommen wurde
Sie können dies erweitern, um eine Liste der Aktionen zu speichern, die Sie ausführen möchten, und diese dann nacheinander von der
execute
Methode aus aufrufen . Vielleicht könnte diese Verallgemeinerung besser als Builder-Muster beschrieben werden , aber hey, wir wollen nicht wählerisch werden, oder? :)quelle
Möglicherweise möchten Sie eine Regelengine verwenden. Mit einer Regel-Engine erhalten Sie eine DSL (Domain Specific Language), mit der die für ein bestimmtes Ergebnis erforderlichen Kriterien auf verständliche Weise modelliert werden können, wie in dieser Frage erläutert .
Abhängig von der Implementierung der Regelengine können die Regeln sogar geändert werden, ohne den Code neu zu kompilieren. Und weil die Regeln in ihrer eigenen, einfachen Sprache geschrieben sind, können sie auch von den Benutzern geändert werden.
Wenn Sie Glück haben, gibt es eine einsatzbereite Regel-Engine für die von Ihnen verwendete Programmiersprache.
Der Nachteil ist, dass Sie sich mit einer Regel-Engine vertraut machen müssen, die für Programmieranfänger schwierig sein kann.
quelle
Meine Lösung für dieses Problem ist ganz anders: Ebenen, Einstellungen und LOP.
Wickeln Sie zuerst die API in eine Ebene. Suchen Sie nach Sequenzen von API-Aufrufen, die zusammen verwendet werden, und kombinieren Sie sie zu Ihren eigenen API-Aufrufen. Schließlich sollten keine direkten Aufrufe an die zugrunde liegende API erfolgen, sondern nur Aufrufe an Ihre Wrapper. Die Wrapper-Aufrufe sollten wie eine Mini-Sprache aussehen.
Zweitens implementieren Sie einen "Einstellungsmanager". Auf diese Weise können Namen dynamisch mit Werten verknüpft werden. Etwas wie das. Eine weitere Mini-Sprache.
Implementieren Sie schließlich Ihre eigene Minisprache, in der Sie Designs ausdrücken können (dies ist sprachorientierte Programmierung). Diese Sprache sollte für die Ingenieure und Designer verständlich sein, die die Regeln und Einstellungen beitragen. Das erste Beispiel für ein solches Produkt ist Gnuplot, aber es gibt viele andere. Sie könnten Python verwenden, obwohl ich persönlich nicht würde.
Ich verstehe, dass dies ein komplexer Ansatz ist und möglicherweise zu viel für Ihr Problem bedeutet oder Fähigkeiten erfordert, die Sie noch nicht erworben haben. Es ist nur so, wie ich es machen würde.
quelle
Ich bin mir nicht sicher, ob ich die Frage richtig verstanden habe, aber es hört sich so an, als ob Sie die Dinge in einigen Strukturen gruppieren sollten. Angenommen, Sie verwenden C ++ und können Folgendes definieren:
Sie können diese zu Beginn des Programms instanziieren:
Dann sehen Ihre API-Aufrufe wie folgt aus (vorausgesetzt, Sie können die Signatur nicht ändern):
Wenn Sie die Signatur der API ändern können, können Sie die gesamte Struktur übergeben:
Sie können auch alle Parameter in einem größeren Wrapper gruppieren:
quelle
Ich bin überrascht, dass das noch niemand erwähnt hat ...
Du sagtest:
Lassen Sie mich das sagen, die meisten anderen Antworten sind auf dem richtigen Weg. Ich denke definitiv, dass Datenbanken Ihnen helfen könnten. Aber eine andere Sache, die Ihnen helfen wird, ist das Kommentieren, gute Variablennamen und die richtige Organisation / Trennung von Bedenken.
Alle anderen Antworten basieren stark auf technischen Aspekten, ignorieren jedoch die Grundlagen, die die meisten Programmierer lernen. Da Sie von Beruf ein Mech-Ingenieur sind, sind Sie an diese Art der Dokumentation vermutlich nicht gewöhnt.
Das Kommentieren und Auswählen guter, prägnanter Variablennamen trägt immens zur Lesbarkeit bei. Was ist leichter zu verstehen?
Oder:
Das ist ziemlich sprachunabhängig. Unabhängig davon, mit welcher Plattform, IDE, Sprache usw. Sie arbeiten, ist eine ordnungsgemäße Dokumentation der sauberste und einfachste Weg, um sicherzustellen, dass jemand Ihren Code verstehen kann.
Als nächstes geht es darum, diese magischen Zahlen und Unmengen von Bedenken in den Griff zu bekommen, aber ich denke, GrandmasterBs Kommentar hat das ziemlich gut gemeistert.
quelle