Wie kann ich meine Software zu vermeiden übermäßige Umschreiben und Interdependenzen planen

StackOverflow https://stackoverflow.com/questions/3472405

  •  28-09-2019
  •  | 
  •  

Frage

Ich schreibe eine Motorsteuerung, die ein paar Schnittstellen (Tasten, Bluetooth, haptische Knöpfe) hat, die eine Aufgabe, die ständig eine größere sein wächst als ich dachte. Ich habe versucht, nur um es zu gehen, indem sie mit Low-Level-Module beginnen (zB Schreibcode auf dem I2C-Bus zu reden), dann diejenigen über diesem (Code Gespräch mit einem bestimmten Gerät auf der I2C Bus ...), aber allzu oft ich auf meine unteren Module Griff zu tauchen wieder haben Macken ich zubringen nicht. Dies geschieht entweder eine lange Zeit oder ich wirklich Hack-ish-Code.

Mein Ziel ist eine 8-Bit-MCU, so von unten nach oben scheint, wie ich die Hardware besser ausnutzen kann. Wenn ich gehe top-down I am oder Test / debug keine Struktur zu bauen.

Ich habe versucht, einige allgemeine Diagramme und diejenigen, die für eine besondere Ebenen / Treiber zeichnen, aber ich bin mir nicht sicher, wie man sie so zu strukturieren, wo ich darüber sehr systematisch sein und zu vermeiden, dass die ungerade Signal fehlt, dass der Bedarf durch zu gehen 2-3 Schichten.

Ich denke, das ist der Grund für einen CS Grad? Ich bin ein Elektroingenieur: P

War es hilfreich?

Lösung

Es klingt wie Sie auf dem richtigen Weg sind. Manchmal wird kein Betrag der Planung gehen Sie zu vermeiden, dass einem späteren Zeitpunkt neu zu gestalten oder refactor Teile eines Systems bei. Probieren Sie einige der folgenden Tipps:

  • Halten Sie den Code in Modulen durch logische Funktionen getrennt sind.
  • kein doppelter Code, sondern entwirft wiederverwendbare Methoden für die gemeinsame Funktionalität.
  • Versuchen Sie, die Versuchung hinzuzufügen Hacks für Sonderfälle zu vermeiden. Schließlich wird diese wartbaren werden. Stattdessen anpassen und Refactoring kleine Abschnitte so schnell wie möglich. ein großes Re-Design am Ende zu tun versuchen wird schwieriger.
  • Versuchen Sie nicht zu über entwerfen das System von Anfang an, wie Sie nur Ihre Zeit verschwenden werden können, wenn Sie an der tatsächlichen Durchführung erhalten.
  • Halten Sie die unteren Ebenen so einfach wie möglich, dann erweiterte Funktionen auf bauen.
  • Ihre Funktionen dokumentieren und einen einig Unit-Tests schreiben, vor allem nach komplexen bedingten Anweisungen hinzufügen.
  • Versuchen
  • zu fangen Fehler so weit oben den Stapel wie möglich. Zum Beispiel tut Eingabevalidierung und Rückgabewerte zu überprüfen. Dadurch wird einfacher debuggen.

Andere Tipps

Wenn in mehrstufigen Code arbeiten, ist es verlockend, zu tauchen in eine niedrigere Stufe, wenn die API nicht lassen Sie tun genau das, was Sie wollen, es zu tun. Dies ist besonders schwierig, wenn mulitple Ebene zugleich writting.

Hier ein paar Vorschläge:

  • Behandeln Sie alle anderen Ebenen als die auf dem Sie arbeiten, als ob sie verschlossen sind. Erstellt von einem anderen Unternehmen, Entwickler, etc., um den Drang wider eine andere Ebene zu ändern, um ein Problem in der aktuellen Ebene zu lösen.
  • Erstellen Sie eine „Geschwister tier“ auf die, die Sie gerade arbeiten. Das ist schwer im abstrakten Sinne zu beschreiben, aber sagen sie mal Ihre untere Ebene ist eine Business-Schicht und die höhere Stufe ist eine Benutzeroberfläche, wieder eine einzigen UI-Ebene für eine andere Anwendung erstellen. Jetzt mit zwei Verbraucher von derselben API kann helfen, weisen darauf hin, was in jeder Schicht sein sollte.
  • Versuchen Sie, die Reihenfolge abwechselnd, in dem Sie auf Ebenen arbeiten. Zum Beispiel, in einigen Anwendungen finde ich es sinnvoller, zuerst die Benutzeroberfläche zu entwerfen, dann meinen Weg bis auf die Business-Schicht / Datenbank, die UI-Arbeit zu machen, wie entworfen. Andere Zeiten, ist es sinnvoller zu stat mit dem Datenmodell und die Arbeit an einem UI-up. Aber der Punkt ist, Sie „denken“, eine API anders in diesen beiden Szenarien. Und von beiden Winkel an mehreren gestaffelten Code angesehen haben, hilft.
  • Erfahrung zählt. Manchmal ist nur macht die Fehler, übermäßig gekoppelt Code der einzige Weg, um wirklich zu lernen, es zu vermeiden. Statt des Seins perfekt auf Ihre Anwendung planen, planen sie unvollkommen ist. Damit meine ich zuerst eine schnelle Entwicklung / Test / refactor Zyklus einrichten, dass so können Sie schnell auf Fehler anpassen, dass Sie bis sehen werde nicht, nachdem Sie sie gemacht haben. Dies ist auch ein Bereich, in den „Wegwerf-Prototyping“ in praktisch. Machen Sie einen einfachen groben Entwurf, daraus lernen und wirft es weg. Der Wurf entfernt Teil ist wichtig. Auch seine erstaunliche, wenn beginne ein von Grund auf neu zu bauen. Sie werden unvermeidlich macht es besser (und in meinem expirience, mehr organisiert) auf, was Sie von dem Prototyp gelernt.

Es ist wirklich eher eine Frage der Erfahrung als Ihr Studium. Wenn Sie immer noch lernen, Dinge darüber, wie die Hardware zu steuern, dann natürlich der Code ändern wird. Ich würde das nicht den Kopf zerbrechen über. Da jedoch, was Sie wirklich Prototyping tun, sollten Sie bereit sein, den Code Refactoring, wenn Sie es arbeiten, haben. Entfernen Sie Redundanzen, compartmentalize Daten und Funktionalität, und organisieren Sie Ihre Schnittstellen, so dass es Sinn macht.

Meine Erfahrung ist, dass Gerätetreiber-Code muss Top-down- und Bottom-up-Design / Implementierung, was ich von außen nach innen. Sie wissen, was der Benutzer tun zu wollen, geht und Sie können diese Schnittstellen schreiben, und Sie wissen, was die Low-Level-Treiber tun muss, und Sie schreiben, dass. Wenn sie nicht erfüllen, auch in der Mitte, überdenken Sie Ihr Modul-Layout.

Zur Verbesserung vorbehaltlich Ihr Design und Code von Menschen mit mehr Erfahrung zu überprüfen. Lassen Sie Ego aus ihm heraus und erhalten nur ihre Sicht auf das Problem. Vielleicht haben Sie auch ein Buch über objektorientierte Analyse und Design (Früher habe ich wie Peter Coad der Bücher. Ich weiß nicht, wer sich jetzt schreibt) gelesen. Ein gutes zeigen Beispiele dafür, wie ein Problem in Objekte mit klaren Rollen und Verantwortlichkeiten zu partitionieren.

Das andere Stück, wenn Sie die Treiber Prototyping beendet haben und wissen, wie die Hardware zu steuern, ist sicherzustellen, dass Sie detaillierte Anforderungen haben. Nichts dreht Code mehr als Anforderungen, während Sie schreiben zu entdecken. Sie könnten versuchen, auch UML zu lernen und die Gestaltung mit Diagrammen, bevor das Schreiben von Code. Dies gilt nicht für alle. Beachten Sie auch, dass Sie nicht in einer Sprache zu kodieren müssen, dass unterstützt die objektorientierte Konstrukte Verwendung OOD.

Wenn Ihr Problem ist, wie die richtigen Abstraktionen zu bauen, was der Fall zu sein scheint, glaube ich, dass die wichtigste Sache, die Sie (außer fragen für Design-Code-Reviews / Bücher lesen / Lesecode) zu lernen, tun können, ist ZU sTARK, bevor Sie beginnen das Schreiben von Code THINK .

Es geschieht in der Regel, dass Sie mit einer groben Idee beginnen, was Sie wollen und wie es getan werden soll und dann weitergehen zu Code schreiben. Später können Sie feststellen, dass Sie nicht über Dinge denken haben, und Sie haben mehrere klaffende Löcher jetzt, die, weil sie Zeit beim Schreiben des Codes investiert haben, sind schwer zu Patch, was zu jeder verschwendete Zeit oder Hacky-Code.

Denken schwer, wie ein Design zu schaffen, die sich leicht Änderungen umgehen können. Zum Beispiel kapseln die Daten, dass die Bedürfnisse Reise zwischen den Schichten, so dass, wenn Sie später entdecken Sie einen entscheidenden Parameter verpasst Sie leicht auf die Struktur hinzufügen können, ohne Code überall zu modifizieren.

Versuchen Sie, „das Design in Ihrem Kopf laufen“, mehrmals, bis Sie reasoanly sicher sind, dass Sie am wichtigsten Details in Betracht gezogen haben, und man kann sagen (dies ist der wichtigste Teil, weil man sonst immer vermissen Dinge oder Anforderungen ändern wird), dass, wenn Sie etwas verpasst Sie die Module mit relativer Leichtigkeit optimieren können.

UML können Sie die Art und Weise helfen strukturieren über das Design zu denken. Es ist sicherlich kein Allheilmittel, aber es zeigt die verschiedene Kriterien zu berücksichtigen, wenn ein Software-Design zu schaffen.

Es ist ein bisschen wie der klassische Schach Lehrer Rat: " sitzt auf Ihren Händen ": -)

Treiber sind zugänglich für eine Schicht Ansatz.

Ihre Fahrer konnte mehrere "Klassen" haben:

  • Eingabe nur
  • Ausgabe nur
  • beide I und O.

Sie sollten eine standardisierte Schnittstelle, z.B .:

GetKnobLevel()
GetNextKeyboardButton

Oder ein anderer Ansatz ist wie etwas zu haben,

syscall(DRIVERNUMBER, command)

Parameter / Ergebnisse in bestimmten Register setzen.

Es ist ein einfacher, brauchbarer Ansatz. Eine komplexere Variante könnte seinen Kreis Warteschlangen zwischen Ihrer Hardware Kommunikation Code und Software in Verbindung steht Code zu haben, anstelle von Registern.

Hier ist das mentale Modell verwende ich:

---
Application
---
OS
---
Driver communicators
---
drivers
---
hardware

Es gibt eine eng definierte, nicht-Varianz-Schnittstelle zwischen jeder Schicht (Ich halte einen Schichtkuchen mit dicken bereift zwischen den Schichten vorzustellen, ...). Das Betriebssystem kann nicht für Sie existieren, natürlich.

Wenn Ihre MCU-Software und Hardware-Interrupts wie der x86-CPU unterstützt, können Sie diese verwenden, um die Treiber von dem Treiber Kommunikatoren zu isolieren.

Dies ist ein bisschen einer „overengineery“ Lösung, um ehrlich zu sein. Aber in einer Situation, wo Ihre Komplexität signifikant ist immer, es ist einfacher, engen Engineering zu haben, als lose Technik zu haben.

Wenn Sie zwischen den Schichten miteinander kommunizieren, können Sie eine globale Variable für jede Kommunikation „Kanal“ verwenden können, und greifen Sie in einer disziplinierten Art und Weise, nur mit Funktionen für den Zugriff es.

Normalerweise werden Sie Papierentwürfe auf einer bestimmten Ebene zu tun, einige Sondierungsarbeiten und Neugestaltung, bevor Sie wirklich Ihr Projekt Code festgelegt. Flussdiagramme und Bus-Übergangsdiagramme arbeiten hier gut.

Dies ist der Ansatz, den ich in meinem Embedded-Systeme Arbeit begünstigt haben und es funktioniert gut für mich.

Auch - dieses Problem Raum nicht gut von den traditionellen Informatik Lehrplänen untersucht. Es ist viel weniger nachsichtig als die Web oder moderne Betriebssysteme.

Meiner Meinung nach sind die wichtigsten Aspekte des gut architectured Code sind geringe Kopplung und Trennung von Nebenwirkungen von dem Zustand .

Auch - Code ist ein Handwerk. Denken Sie nicht die perfekte Lösung von Anfang an machen. Seien Sie bereit, Ihren Code zu ändern, wie Sie neue Dinge zu lernen. In der Tat - Stellen Sie sicher, dass Sie umarmen ändern Selbst als Teil Ihrer Arbeit

.

Nicht glatt sein, sondern ein Zitat von The Mythical Man-Month in den Sinn kommt: "Planen einer wegzuwerfen, du wirst sowieso"

Die logische Folge davon ist „damit es funktioniert. Es richtig machen. Machen Sie es schnell.“

Ich nehme an, das macht mir einen Verfechter einige Designs up-front zu tun, aber nicht durch sie gelähmt zu werden. Es muss nicht das erste Mal durch perfekt sein. Planen Refactoring. Hoffentlich haben Sie die Dinge in einer solchen Art und Weise geschrieben, dass Sie nicht wirklich viel Code wegzuwerfen, aber die Dinge in eine angenehmere Art und Weise neu anordnen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top