Spare bis zu 70% auf unsere Weiterbildungsangebote. Aktionszeitraum vom 22.11. - 30.11.2024.
Programmiersprachen: Durchstarten mit D
(Bild: D Language Foundation/Montage: Golem.de)
Wenn ich an die Programmiersprache D denke, fallen mir drei Wörter ein: leicht, schnell, ausdrucksstark. Passt zu meinem Auto.
Dieser Text ist eine Übersetzung. Das Original des Programmierers Dylan Graham ist hier zu finden.
Ich fahre täglich einen Holden VZ Ute. Ich schätze ihn sehr, allerdings wurde er ab Fabrik mit einem sehr schlechten Viergang-Automatikgetriebe ausgestattet. Allein in den ersten 18 Monaten habe ich vier Getriebe kaputtgemacht. Ein neues Fahrzeug konnte ich mir nicht leisten, also musste ich kreativ werden.
Ich kaufte ein solides Sechsgang-Automatikgetriebe eines anderen Autos, wusste aber erst mal nicht, wie ich das mit meinem eigenen Auto zusammenbringen sollte. Damit es funktionierte, musste ich meine eigene Leiterplatte, mein eigenes Computersystem und meine eigene Firmware bauen. Damit sollten die Magnetspulen, die Hydraulik und die Kupplungen im Getriebe gesteuert, Benutzereingaben verarbeitet, Schaltvorgänge umgesetzt und eine Schnittstelle zu meinem Auto geschaffen werden, die vorgeben sollte, eine Viergang-Automatik zu sein.
Ich habe für all das eine Lösung gefunden und bin ziemlich stolz darauf: Ein Schaltvorgang kann in 250 Millisekunden umgesetzt werden, was für schnelles Fahren großartig ist. Der erste Gang ist recht stramm, wodurch das Auto gut beschleunigt und mitunter selbst stärkere Autos abhängt. Es gibt eine Schaltwippen-Gangschaltung, Diagnosedaten auf dem Bildschirm und die Möglichkeit, alles neu einzustellen, wann immer ich will.
Der Rechner besteht aus zwei Teilen: der Platine für die Benutzeroberfläche, die ein OLED-Display ansteuert und einen STM32F042 verwendet, und der Hauptplatine, die alles andere übernimmt und einen STM32F407 hat. Beide arbeiten über einen CAN-Bus (Controller Area Network) zusammen. Die gesamte Firmware dafür ist in D geschrieben.
Ich habe mich für D (wie -besseresC) entschieden, weil es diese großartige einheitliche Funktionsaufruf-Syntax (Uniform Function Call Syntax, UFCS) hat, Metaprogrammierung ermöglicht und eine einfache Schnittstelle zu C bietet; außerdem habe ich es wegen der Unit-Tests, der Portabilität, wegen shared und @safe ausgesucht. Darüber hinaus gibt es eine sehr hilfsbereite, offene Community für die Sprache. Es war eine Freude, in den Foren über D zu diskutieren.
Die Vorteile von D
Die Uniform Function Call Syntax
Die UFCS hat meinen Code deutlich übersichtlicher gemacht. Er folgt genau dem Datenfluss, ohne meinen Stack mit temporären Variablen, verschachtelten Funktionsaufrufen oder anderem Kram zu belasten.
Hier ist zum Beispiel Code, den ich in meinem kommenden ECU-Projekt (Engine Control Unit) verwende:
Diesen Code muss niemand rückwärts lesen, um ihn besser zu verstehen, es müssen keine Klammern gezählt oder Unmengen von Zwischenvariablen verwendet werden. Er ist einfach auf den Punkt.
Metaprogrammierung
Viele Programmierer schwören auf das Don't-Repeat-Yourself-Prinzip (DRY). Die Metaprogrammierung von D ist ein tolles Tool, um das zu erreichen. Ich verwende es in meiner CAN-Bus-Implementierung, etwa so:
Ich habe spezifische Alias-Typen wie HeartbeatPacket und BeepHornPacket, aber ich muss keinen Code wiederholen. Sie alle folgen der gleichen zugrundeliegenden Struktur. Wenn ich also CANPacket ändere, wird jeder Alias-Typ ebenfalls aktualisiert.
Schnittstellen zu C
Ich muss häufig mit dem HAL und dem RTOS meines Microcontrollers kommunizieren; mit der C-Schnittstelle von D ist das ganz einfach. Einfach extern(C) hinzugefügt und schon kann es losgehen.
Weitere Vorteile von D: Unit-Tests, shared, @safe
Unit-Tests
Die eingebauten Unit-Tests von D haben mich ein paarmal gerettet. Ich kann alle Unit-Tests unter Windows laufen lassen, um die logische Korrektheit zu garantieren und dann für den Microcontroller ein Build-Ziel zu bauen.
Portabilität
Außerdem unterstützt D eine überraschend große Anzahl von Zielsystemen - über GDC und LDC. Wäre D nicht so portabel, hätte ich mein Projekt in C++ schreiben müssen (uff). Ich verwende LDC und das Cross-Compiling kann durch einfaches Anpassen meiner Kommandozeilenargumente durchgeführt werden.
Shared
Shared ist ein D-Sprachkonstrukt zum Umgang mit Multithreading-Zugriff auf Code. Es ist nicht perfekt, aber für mich funktioniert es gut. Ich habe mehrere Threads in meinem Programmcode und sie müssen Daten synchronisieren.
Ich markiere bestimmte Variablen als shared, was bedeutet, dass ich beim Zugriff auf diese Daten besondere Sorgfalt walten lassen muss. Das funktioniert ganz gut mit Systemsperren und Mutex.
@safe dient dazu, fragwürdige Speicheraktivitäten zu unterbinden und ein optimales Speicherverhalten zu erzwingen. Ich hatte noch nicht viel mit @safe zu tun, weil ich nichts Schlimmes mit meinem Speicher anstelle. Es ist aber gut zu wissen, dass, wenn ich einen Fehler mache, der Compiler mir helfen kann, ihn zu beseitigen.
Wenig Reibungsverluste
Adam D. Ruppe bringt es auf den Punkt: Mit D gibt es wenig "mentale Reibungsverluste". Die Flexibilität und Ausdruckskraft der Sprache machen es einfach, die eigenen Gedanken in geschriebenen Code zu übersetzen und die Produktivität hoch zu halten. Ich muss mit D nicht viel herumkämpfen, es ist für mich die Sprache, in der ich am produktivsten bin.
D ist die perfekte Lösung für diese Art von Projekten - ich denke, es wird eine große Zukunft in der Embedded-Welt haben. Ich werde D weiterhin für meine Projekte verwenden und arbeite bereits an einem weiteren D-betriebenen Autoprojekt, das ich hoffentlich bald vorstellen kann.
veröffentlicht am 16. Juli 2021