Hallo zusammen, Ich bin jet ein gutes Jahr in der Softwareentwicklung für Landmaschinen tätig. Hab bisher meine C-KnowHow deutlich verbessern können gegenüber dem Studium. Der nächste Schritt wäre nun zu wissen, wie man "gute" Software schreibt bzw baut. Wir schreiben nur die Applikation für die Maschinen, da die Bios Funktionen vom Hersteller im Form einer Lib kommen. Meiner Meinung ist die Applikation etwas veraltet und pseudo C++. So gibt es zum Beispiel zyklische Funktionen, bei denen Parameter neu geladen oder kontrolliert werden. Beispielsweise wenn ich einen Ringpuffer mit 10 Stellen initialisiere wird jede Sekunde überprüft, ob sich was an der Grösse geändert hat. Auf die Frage warum sowas gemacht wird heisst es nur, dass es schon immer so gemacht wird. Ausserdem gibt es für jedes Modul ein eigenes Objekt. Diese Objekt wird dann jeder Funktion als Übergabeparameter im Modul übergeben. Beispiel: Es gibt eine Hydraulik.c und .h und dort ist das Objekt Hydraulik_t definiert mit allen Variablen, die die Hydraulik betreffen. Somit kann man in jeder Funktion auf jede Variable zugreifen. Da ich nächstes Jahr ein neues Projekt bekomme wollte ich mal den kompletten Code anpassen. Daher habe ich die Frage ob ihr mir gute Bücher für den Bereich Embedded Software empfehlen könnt. Hab schon nach Design patterns geschaut aber die Bücher waren meistens nicht gut bewertet. Ich möchte mehr darüber erfahren wie man seine Software besser strukturiert, generell wie man sie aufbaut. Gruss Pit
Pit schrieb: > Ich bin jet ein gutes Jahr in der Softwareentwicklung für Landmaschinen > tätig. Hab bisher meine C-KnowHow deutlich verbessern können gegenüber > dem Studium. Der nächste Schritt wäre nun zu wissen, wie man "gute" > Software schreibt bzw baut. Definitiv jedenfalls nicht mit C. Entweder man hat ein vergleichsweise großzügig mit Resourcen ausgestattes Zielsystem, dann benutzt man eine OO-Programmiersprache, notfalls halt C++ (wenn man glaubt C zu können, was ich in 99,5% aller Fälle sowieso erstmal bezweifeln würde). Oder man hat das nicht, dann macht man das mit einer Sache, die im Prinzip dasselbe ist wie C, mit einem Macro-Assembler. C war immer Dreck, ist Dreck und wird immer Dreck bleiben. Nicht Fleisch, nicht Fisch, für nichts wirklich zu gebrauchen. Zu undeterminiert im Timing-Verhalten, zu ineffizient bei der Codegenerierung, um Asm ersetzen zu können, zu schwach typisiert und ohne OO-Konzepte, um richtige Hochsprachen ersetzen zu können. Braucht man nicht und will man nicht. (Sollte man aber nichtsdestotrotz beherrschen, zumindest um hinreichend kompetent lästern zu können, aber auch sonst ist es durchaus oft hilfreich...) Insofern war es also zumindest nicht völlig umsonst, daß du dir auch C-Kenntnisse angeeignet hast. Viel wichtiger dürfte aber die hoffentlich ganz allgemein gewonnene Routine bei der Analyse von Problemen und der Umsetzung mit den Mitteln irgendeiner gegebenen Programmiersprache sein. Wirklich Programmierer ist man nämlich erst, wenn einem die Programmiersprache im Prinzip egal ist, man den Kram also in jeder umsetzen kann, solange man nur eine Referenz der jeweiligen Sprachmittel hat. Dann entscheidet die konkret verwendete Sprache nämlich nur noch über zwei Sachen: 1) Wie lange die Implementierung dauert. 2) Wie effizient das Ergebnis zur Laufzeit ist. Und wenn man soweit ist, wird die Sache sofort sonneklar: Normaler Kram in einer OO-Sprache, zeitkritisches Zeug in Asm. Und wenn die Resourcen sehr knapp sind: alles in Asm. Fazit: No need for C.
Pit schrieb: > So gibt es zum Beispiel > zyklische Funktionen, bei denen Parameter neu geladen oder kontrolliert > werden. Beispielsweise wenn ich einen Ringpuffer mit 10 Stellen > initialisiere wird jede Sekunde überprüft, ob sich was an der Grösse > geändert hat. Auf die Frage warum sowas gemacht wird heisst es nur, dass > es schon immer so gemacht wird. Das klingt relativ unsinnig. Wenn keiner einen Grund dafür nennen kann, dann mach es in Deinem eigenen Projekt einfach nicht. Pit schrieb: > Ausserdem gibt es für jedes Modul ein eigenes Objekt. Diese Objekt wird > dann jeder Funktion als Übergabeparameter im Modul übergeben. Beispiel: > Es gibt eine Hydraulik.c und .h und dort ist das Objekt Hydraulik_t > definiert mit allen Variablen, die die Hydraulik betreffen. Somit kann > man in jeder Funktion auf jede Variable zugreifen. Das ist hingegen nicht verkehrt, sofern den Funktionen ein Zeiger auf das Objekt übergeben wird und nicht das Objekt selbst. Genau so macht es C++ mit dem this-Zeiger auch, nur dass die Syntax etwas kompakter ist:
1 | // C:
|
2 | hydraulik_mach_etwas(&meine_hydraulik, 42); |
3 | // C++:
|
4 | meine_hydraulik.mach_etwas(42); |
Auf Mikrocontrollern muss man ggf. halt abwägen, ob man wirklich mehrere Instanzen braucht oder nicht. Wenn ein Objekt garantiert nur einmal im System vorkommt, kann man es sich sparen. Allgemein halte ich es für das wichtigste, die Prinzipien "Starke Bindung, lose Kopplung" sowie "Information Hiding" so gut es geht umzusetzen. Sprich zusammengehörigen Code in einer Klasse bzw. einem Modul sauber kapseln und mit einer möglichst einfachen und kompakten Schnittstelle versehen. Außerdem die Module nach Schichten trennen (z.B. Mikrocontroller-Hardwareabhängig -> Hardwareabstraktion -> Ansteuerung einer (externen) Komponente -> Programmlogik). Aber auch aufpassen, dass man sich nicht "verkünstelt" und trivialen Code in 20 Schichten aufbläht. Da den richtigen Mittelweg zu finden, abgegrenzte Komponenten zu identifizieren, sinnvolle Schnittstellen zu definieren und daraus wiederverwendbare Module zu machen, ist dann hauptsächlich Erfahrungs- und imo auch Talentsache. Am Ende sind es immer Einzelfallentscheidungen, das kann einem kein Buch abnehmen. Aus meiner Sicht ist noch sehr hilfreich, sich viel mit fremden Code und vor allen dessen Schnittstellen zu beschäftigen. Bei guten Interfaces ist es leicht, sie richtig zu benutzen, und schwer, sie falsch zu benutzen. Da bekommt man mit der Zeit ein Gefühl für und kann sich gute Konstruktionen abschauen, aber auch aus "Anti-Patterns" lernen. Einen Buchtipp speziell für Embedded-Systeme habe leider nicht. Klassiker wie "Design Patterns" von der Gang of Four zielen eher auf dynamische Software, bei der zur Laufzeit mit Objekten hantiert wird, die die Struktur der Anwendung bestimmen. Das ist bei interaktiven PC-Anwendungen oft der Fall. Embedded-Systeme sind dagegen typischerweise statisch aufgebaut und maximal die Eingabedaten dynamischer Natur, aber nicht das Zusammenspiel der Systemkomponenten an sich. Man legt also bei einem Embedded-System z.B. weniger Wert darauf, dass man zur Laufzeit neue Hydraulikmodule einfügen kann, sondern eher, dass sich Änderungen auf möglichst wenig, zentralen Code beschränken und man Code in verschiedenen Projekten wiederverwenden kann. Außerdem basieren viele der klassischen Design-Patterns auf Polymorphie mit virtuellen Methoden, was in C so eh nicht geht (bzw. nur sehr umständlich mit Funktionszeigern) und auf Mikrocontrollern auch recht teuer (Laufzeit, vor allem aber RAM) ist. Falls Du das Buch nicht kennst, ist es aber trotzdem eine Lektüre wert, auch wenn man die Lösungen dann nicht 1:1 so umsetzt.
Pit schrieb: > Hab bisher meine C-KnowHow deutlich verbessern können gegenüber > dem Studium. Der nächste Schritt wäre nun zu wissen, wie man "gute" > Software schreibt bzw baut. Gute Software hängt zumeist NICHT von der verwendeten Programmiersprache ab. Mit Einschränkungen, die man kurz zusammenfassen kann: Die Programmiersprache sollte dem Vorhaben angemessen sein. Also wäre z.B. C++ auf nem gewöhnlichen µC eher unangemessen, weil das dort völlig übliche Kreieren und wieder Zerstören von Objekten auf dem Heap etwas ist, das man in den meisten Fällen in einer µC-Firmware garnicht braucht. Auch all die Funktionalität zum E/A über Standardkanäle paßt eher zu einem Kommandozeilen-Programm auf dem PC als zu einer Firmware im µC. Das Gegenteil, nen 32 Bitter komplett in Assembler programmieren zu wollen, wäre ebenso unangemessen. Also: schlichtweg auf dem Teppich bleiben, ist der erste Schritt zu gutem Code. Es läuft auf C hinaus, denn C gibt's und ist benutzbar, sowas wie Pascal wäre auch benutzbar, gibt's aber nicht. Die Auswahl ist halt nicht groß, gelle? Als dringlichstes rate ich zu sinnvoller Modularisierung. Also in sich geschlossene Programmteile für jeweilige Gruppen von Berechnungen und Treiber für die diversen Peripheriefunktionen, derart, daß sie ohne Wenn und Aber und ohne Blockierungen funktionieren, ohne daß man von außen sich um deren ganzen internen Krempel kümmern muß. Da wird von vielen Programmiereichen ziemlicher Mist betrieben, weil sie die verschiedenen Funktionsbereiche einer Firmware nicht auseinander kriegen. Als nächstes rate ich zu spezialisierten Konvertierungen, also Verzicht auf sowas wie sprintf und Konsorten. OK, ob dir meine Einlassungen bei solchen Vorgaben wie "hydraulik_t" wirklich helfen, ist fraglich. W.S.
Pit schrieb: > Ich bin jet ein gutes Jahr in der Softwareentwicklung für Landmaschinen > tätig. So, du sprichst ISOBUS, sehr lobenswert. :) > Hab bisher meine C-KnowHow deutlich verbessern können gegenüber > dem Studium. Der nächste Schritt wäre nun zu wissen, wie man "gute" > Software schreibt bzw baut. > Wir schreiben nur die Applikation für die Maschinen, da die Bios > Funktionen vom Hersteller im Form einer Lib kommen. Meiner Meinung ist > die Applikation etwas veraltet und pseudo C++. Google doch einfach mal nach populären C-Bibliotheken/Anwendungen und schau dir mal an, was die so gemacht haben. Gerade für GNU/Linux oder im BSD-Bereich gibt es so hervorragende Bibliotheken, die man sich mal anschauen kann, das hilft schon sehr. > So gibt es zum Beispiel > zyklische Funktionen, bei denen Parameter neu geladen oder kontrolliert > werden. Beispielsweise wenn ich einen Ringpuffer mit 10 Stellen > initialisiere wird jede Sekunde überprüft, ob sich was an der Grösse > geändert hat. Auf die Frage warum sowas gemacht wird heisst es nur, dass > es schon immer so gemacht wird. Was am Anfang kein schlechter Ratschlag ist, sich an den Code anzupassen, der vorhanden ist, anstelle neue Baustellen aufzureißen. > Ausserdem gibt es für jedes Modul ein eigenes Objekt. Diese Objekt wird > dann jeder Funktion als Übergabeparameter im Modul übergeben. Beispiel: > Es gibt eine Hydraulik.c und .h und dort ist das Objekt Hydraulik_t > definiert mit allen Variablen, die die Hydraulik betreffen. Somit kann > man in jeder Funktion auf jede Variable zugreifen. Hmm - und du möchtest eine kleine objektorientierte Architektur nur mit Strukturen. Jo, kann man machen. > Da ich nächstes Jahr ein neues Projekt bekomme wollte ich mal den > kompletten Code anpassen. Da haste dir was vorgenommen. > Daher habe ich die Frage ob ihr mir gute > Bücher für den Bereich Embedded Software empfehlen könnt. Hab schon nach > Design patterns geschaut aber die Bücher waren meistens nicht gut > bewertet. Kannst du nicht mal in 'ne Fach-/Universitätsbuchhandlung respektive Bibliothek gehen und dir dort mal Bücher zum Thema anschauen, bevor du welche kaufst? Ansonsten: der Klassiker ist E. Gamma "Entwurfsmuster", sehr zu empfehlen ist auch "Entwurfsmuster von Kopf bis Fuss" vom O'Reilly-Verlag. Letzteres ist für Einsteiger ziemlich gut. Das betrifft aber grundsätzlich objektorientierte Programmierung. So wie ich dich verstehe, nutzt du ANSI-C zur Programmierung. Gerade im ISOBUS-Bereich würde ich dir da "Test-Driven-Development for Embedded-C" von James Grenning empfehlen. Bevor du anfängst, Baustellen aufzureißen, solltest du da mal einen Blick drauf werfen. > Ich möchte mehr darüber erfahren wie man seine Software besser > strukturiert, generell wie man sie aufbaut. Schreibe SOLIDen Code: S - Single Responsibility O - Open/Close L - Liskov Substitution I - Interface Segregation D - Dependency Inversion Und wie man das mit C macht - siehe Grenning: http://www.renaissancesoftware.net/blog/
Fabian O. schrieb: > Das ist hingegen nicht verkehrt, sofern den Funktionen ein Zeiger auf > das Objekt übergeben wird und nicht das Objekt selbst. Ja es wird ein Zeiger auf das Objekt übergeben. Das an sich "stört" mich ja auch gar nicht. Ich habe halt nur ein Problem damit, dass man damit zugriff auf alle Variablen hat. Dann sind das ja quasi alles globale Variablen und darauf würde ich gern verzichten. Mir geht es ja auch nicht darum alles auf den Kopf zu stellen. Der bisherige Programmstil hat sich ja über Jahre bewährt und ich möchte mir einfach nur mal einen Überblick überschaffen, welche Methoden man einsetzen kann bzw was sich so an der Programmierung in den letzten Jahren geändert hat. Bücher ausleihen ist hier schwierig, da in der nähe keine Uni ist und die Bibliotheken hier haben auch sehr wenig technische Bücher. Nach Skripten habe ich natürlich auch schon gegoogelt aber da werden oftmals nur die Grundlagen vermittelt. Zum Beispiel die Sache mit dem Objekt und der Übergabe als Zeiger habe ich so in noch keinem Skript gesehen oder das man Enums als State eines Objekts benutzt.
c-hater schrieb: > Definitiv jedenfalls nicht mit C. Dummschwätzer. Zeigt nur deine Inkompetenz. Such dir einen anderen Job, der dich nicht so überfordert.
c-hater schrieb: > Fazit: No need for C. Seit einiger Zeit lese ich deine Kommentare. Und immer mehr verfestigt sich meine Meinung: Egal, was dein Dealer sagt und egal wie preiswert das Zeug ist, such dir was anderes. Es bekommt dir nicht. Ich habe auch viele Jahre nur in ASM programmiert, meist, weil es nichts besseres gab. Für C habe ich mehrere Anläufe gebraucht. Heute möchte ich diese Sprache nicht mehr missen. Es ist für mich der optimale Kompromiss zwischen maschinennah und übersichtlich.
Georg G. schrieb: > c-hater schrieb: >> Fazit: No need for C. > > Seit einiger Zeit lese ich deine Kommentare. Und immer mehr verfestigt > sich meine Meinung: Egal, was dein Dealer sagt und egal wie preiswert > das Zeug ist, such dir was anderes. Es bekommt dir nicht. > > Ich habe auch viele Jahre nur in ASM programmiert, meist, weil es nichts > besseres gab. Für C habe ich mehrere Anläufe gebraucht. Heute möchte ich > diese Sprache nicht mehr missen. Es ist für mich der optimale Kompromiss > zwischen maschinennah und übersichtlich. Die ganze Embedded-Welt programmiert in C. Was juckt dich ein kleiner c-hater Troll? Dem ist nicht zu helfen, den ignoriert man.
:
Bearbeitet durch User
Falk Schilling schrieb: > Gerade im > ISOBUS-Bereich würde ich dir da "Test-Driven-Development for Embedded-C" > von James Grenning empfehlen. Bevor du anfängst, Baustellen aufzureißen, > solltest du da mal einen Blick drauf werfen. Das Buch habe ich mir mal von einem Studenten in unserer Abteilung ausleihen lassen. Sieht auf den ersten Blick sehr interessant aus. Wie gesagt mir geht es nicht darum, alles auf den Kopf zu stellen. Ich wollte mir nur Methoden anschauen, um die Software besser in Hinsicht auf Lesbarkeit, Wartbarkeit und auch Einfachheit zu machen. Ich werde natürlich nicht alles über den Haufen werfen aber ich denke es gibt einige Punkte, die man optimieren kann. Einige habe ich schon optimiert und andere habe ich wieder auf die alte Art zurückgeschrieben. Kennt vielleicht einer "Making Embedded Systems" vom O'Reilly Verlag? Die Leseprobe find ich auch interessant und generell sind viele Bücher von O'Reilly wirklich gut.
Das Buch Testdriven Deleopment Buch habe ich auch, und ja es ist ganz gut. Vor allem wenn man eh neu mit einem Projekt anfängt, kann man da viele Tips von beherzigen. Bei bestehenden Sachen ist das erstmal ziemlich aufwändig und man sollte sich imho gleich mal davon verabschieden alles umstellen zu können. Ansonsten kann ich noch http://www.amazon.de/Automotive-Embedded-Systeme-Effizfientes-Implementierung/dp/3540243399 empfehlen. Nicht von dem Automotive im Titel abschrecken lassen. Aber das Buch ist meiner Meinung nach ziemlich gut und recht praxisorientiert
> Das an sich "stört" mich ja auch gar nicht. Ich habe halt nur ein > Problem damit, dass man damit zugriff auf alle Variablen hat. Wenn das tatsächlich ausgenutzt wird, könnte das allerdings wirklich ein Hinweis sein, dass die wesentlichen Konzepte der objektorientierung von den Ur-Entwicklern nicht verstanden wurden. Auch wenn es in C nicht anders geht, darf man auch dann den Zeiger nicht als eine Art Freibrief ansehen, dass man jetzt mit den Objekt-Daten anstellen kann, was immer man will. So gesehen gewinnst du durch den Einsatz eines C++ Compilers schon etwas. Einfach nur dadurch, dass du Dinge als protected oder private markieren kannst. Alleine das ist schon was wert. Es gibt Dinge, die man in C++ dem Compiler überantworten kann, die in C rein nur auf der Disziplin des Programmierers beruhen.
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.