Forum: Mikrocontroller und Digitale Elektronik Mikrocontroller-Programmierung in C: Effizienz vs. "Usability"


von Oliver L. (olubritz)


Angehängte Dateien:

Lesenswert?

Hallo liebe Leute,
mein Name ist Olli und ich programmiere nun schon seid ein paar Jahren 
Mikrocontroller (zurzeit hauptsächlich XMEGA) in C. Nun versuche ich 
immer wieder meine eigene Programmierweise zu hinterfragen und könnte 
dabei eure Hilfe gebrauchen. Es geht um das Thema Effizienz vs. 
"Usability".

Was meine ich: Wenn ich zum Beispiel einen Beschleunigungssensor, wie 
den LSM303D, an meinen Controller anschließe, so schreibe ich meist 
einen "Treiber", also ein Software-Modul, welches die notwendigen 
Funktionen zur Verwendung des Sensors bereitstellt. Der Sensor wird per 
TWI/I2C angesteuert und bietet eine Reihe von Registern für 
Einstellungen oder die Messdaten. Nun kann eine der Funktionen des 
"Treibers" sein, dass zum Beispiel das 8bit-Register CTRL1 des Sensors 
ausgelesen wird. Ich habe im Anhang zwei Ansätze, die die beiden 
Begriffe Effizienz und "Usability" erklären sollen. Der erste Ansatz ist 
der effizienteste, da dort der Funktion nur der Registerinhalt vom 
Nutzer übergeben und dann an den Sensor übermittelt wird. Beim zweiten 
Ansatz werden an die Funktion verschiedene Parameter übergeben, die den 
Inhalt des Registers darstellen. Hier also die Datenrate, die Achsen, 
welche verwendet werden sollen, und ob ein "Block Update" erfolgen soll.

Das Problem: Der zweite Ansatz ist besser zu verwenden, da man sich 
nicht mit dem Inhalt der Register auseinandersetzen muss. Dafür ist er 
aber nicht sehr effizient, da zum einen mehrere Variablen für die 
Datenübergabe notwendig sind und zum anderen die Daten erst 
"zusammengepackt" werden müssen. Das Problem verstärkt sich dann, wenn 
zum Beispiel in einem Register die 8bit je andere Funktionen haben. Dann 
müsste man beim zweiten Ansatz 8 Bool-Variablen übergeben (oder eine 
struct mit 8 Bool-Variablen).

Die Fragen: Wie handhabt ihr das bei euren Programmen? Welche 
Erfahrungen  habt ihr gemacht?

Ich bin der Meinung, dass man speziell in der 
Mikrocontroller-Programmierung auf die Effizienz achten muss, da ja 
meist die Ressourcen knapp sind ;) (im Vergleich zur Programmierung auf 
z.B. einem Linux-Board oder PC). Trotzdem ist es schon sinnvoll, wenn 
man auch auf die Verwendbarkeit achtet, und wenn es nur die eigene ist, 
da man auch so Zeit sparen kann.

Ich hoffe ich konnte mein anliegen gut rüberbringen =)

Gruß Olli

von Phantomix X. (phantomix)


Lesenswert?

Wie wäre es mit einer verODERung beim Funktionsaufruf?

also bspw:
lsm303d_chg_ctrl1(LSM303D_AODR_200HZ | LSM303D_AXIS_SEL_XY);

das wird zur Compilezeit aufgelöst und verschwendet daher keine 
Ressourcen.

von Oliver S. (oliverso)


Lesenswert?

Du siehst da nur ein Teilproblem.

Die Frage, ob man da nur ein komplettes Byte rüberschiebt, oder das Byte 
zunächst aus Parametern passend zusammenbauen muss, hängt ja zu 
allererst mal von der Anwendung ab.

Musst du das Byte parametrieren, dann ist das halt so. Ob das nun in der 
Kommunikationsfunktion passiert, oder außerhalb da von, ist fast egal, 
machen musst du es trotzdem.

Oliver

von eagle user (Gast)


Lesenswert?

Oliver S. schrieb:
> Ob das nun in der Kommunikationsfunktion passiert,
> oder außerhalb da von, ist fast egal

Taktzyklen-mäßig fast, ja, deshalb kann die Funktion auch ruhig 
getrennte Parameter bekommen, es einfach schöner. Noch dazu bei der 
initialisierung über I2C...

von Purzel H. (hacky)


Lesenswert?

Ich hab einen Initialisierungsbefehl und dann Datenbefehle. Alles auf 
Lowlevel. Das hat vielleicht staerker Restriktionen, ist aber ok, da 
immer genau so angewendet, und transparenter.

von Cube_S (Gast)


Lesenswert?

Wenn's um Effizienz geht, wäre dann nicht einmal darüber nachzudenken ob 
die Übergabe der Pointer der richtige Wert ist. Das schränkt meiner 
Meinung nach auch die Usability ein.
1
int lsm303d_chg_ctrl1(uint8_t* register_data, bool write)
...
1
lsm_data[1] = register_data;
Was sagt eigentlich der Compiler dazu? Und wie sieht der Aufruf aus?

von PittyJ (Gast)


Lesenswert?

Usability steht bei mir im Vordergrund.
So, dass ich den Code leicht warten und portieren kann.

Meist muss man den Code erst 2 Jahre später wieder ändern. Und dann 
freust du dich, dass das einfach geht und dass du deinen eigenen Code 
noch verstehst.
Ich nehme sogar C++ mit Klassen und Konstruktoren, kapsel die Daten und 
baue Zugriffsfunktionen. Zu 99% geht auch alles auf den kleinen AVRs.
Und ein gekapselter Sensorzugriff portiert sich auch gut in ein neues 
Programm, welches zufällig den gleichen Sensor benutzt.

Nur wenn die Performance mal wirklich nicht reicht, dann müssen ein paar 
Hacks rein. Aber das ist sehr selten.

von Robin (Gast)


Lesenswert?

Wichtig für eine effiziente Programmierung und spätere Portierung ist 
mMn. dass es definierte schnittstellen gibt, also z.B. 
TWI_send_data(data, kanal) und diese auf jedem System zur verfügung 
stehen und eine definierte Aufgabe haben. Denn die braucht man immer 
wieder.

von Axel S. (a-za-z0-9)


Lesenswert?

Oliver Lubritz schrieb:
> Ich bin der Meinung, dass man speziell in der
> Mikrocontroller-Programmierung auf die Effizienz achten muss, da ja
> meist die Ressourcen knapp sind

Auch auf µC muß man nicht überall auf Effizienz achten. Lesbarkeit 
(und damit Hand in Hand gehend: Wartbarkeit) des Codes sollte immer 
oberste Prorität haben. Wenn man Lesbarkeit der Effizienz opfert, dann 
nur nachdem man die Notwendigkeit und(!) Wirksamkeit dieses Ansatzes 
nachgewiesen hat. Aber heutzutage sind Hochsprachen-Compiler doch viel 
besser als ihr Ruf.


XL

von Moby (Gast)


Lesenswert?

> Aber heutzutage sind Hochsprachen-Compiler doch viel
> besser als ihr Ruf.

Ein Ruf kommt nie von ungefähr ;-)

von Oliver L. (olubritz)


Lesenswert?

Danke erstmal für die Antworten.

@Cube_S:
Die Übergabe von Pointern ist sicher für die Verwendbarkeit an sich eher 
unpraktisch, aber hier sinnvoll denke ich, da die Funktion für das Lesen 
und Schreiben genutzt werden soll. Allgemein war das aber nur ein 
Beispiel. Deshalb auch leider der Fehler:
1
lsm_data[1] = register_data;
 Hätte ich drauf achten sollen auch wenn es nur ein Beispiel ist, müsste 
in diesem Fall natürlich heißen:
1
lsm_data[1] = *register_data;

@Phantomix:
An die VerODERung habe ich auch schon gedacht. Ein interessanter Ansatz.

@Axel:
Der Hinweis mit der Wartbarkeit ist gut. Ich hatte eigentlich mehr 
darauf geachtet, dass andere Menschen den Code wiederverwenden könnten, 
aber bezüglich Wartbarkeit hab ich eher gedacht ich bekomme das schon 
hin. Nur nach zwei Jahren ist es sicher schwer auch wenn man es selbst 
geschrieben hat.

Danke auf jeden Fall erstmal für eure Erfahrungen. Ich habe in meinem 
Umfeld kaum Menschen mit denen ich mich in diesem Bereich austauschen 
kann, deswegen ist es sehr schön mal Erfahrungen von anderen als Input 
zu bekommen.

Olli

von Phantomix X. (phantomix)


Lesenswert?

Oliver Lubritz schrieb:
> Die Übergabe von Pointern ist sicher für die Verwendbarkeit an sich eher
> unpraktisch, aber hier sinnvoll denke ich, da die Funktion für das Lesen
> und Schreiben genutzt werden soll.

Vielleicht sind an der Stelle zwei getrennte Funktionen sinnvoller, da 
du innerhalb der Funktion eh zwei Codeblöcke hast.

Edith:
Das macht zwar vielleicht ein paar Bytes mehr im Flash aus, ist aber für 
die Laufzeit günstiger.

: Bearbeitet durch User
von Oliver L. (olubritz)


Lesenswert?

Phantomix Ximotnahp schrieb:
> Edith:
> Das macht zwar vielleicht ein paar Bytes mehr im Flash aus, ist aber für
> die Laufzeit günstiger.

Ja der eigentliche Hintergrund für die Schreibweise war, den Flash zu 
schonen. Geht hat auf Kosten der Verwendbarkeit und wie du sagst 
Laufzeit. Besonders unpraktisch, wenn man die Funktionen nur zum 
Schreiben nutzt, da man sich dann meist Variablen für die Übergabe an 
die Funktion sparen kann.
Es war mal eine Anmerkung an mich eines Menschen der C-Programmierung im 
Bereich Embedded-Linux macht. Ist sicher kein schlechter Ansatz, jedoch 
sollte man das, wie bei allem, wahrscheinlich nicht stur verfolgen, 
sondern je nach Situation anpassen.

Olli

von Peter D. (peda)


Lesenswert?

Oliver Lubritz schrieb:
> Der Sensor wird per
> TWI/I2C angesteuert und bietet eine Reihe von Registern für
> Einstellungen oder die Messdaten.

Ich mache das meistens so, daß ich einmal die nötigen Einstellungen 
eines Peripheriebausteins im h-File definiere und die Init-Funktion 
rasselt das einfach nur runter und schickt es raus.
Danach rufe ich nur noch die Read-Funktion auf, die mir den aktuellen 
Meßwert liefert. Bei nem ADC muß ich vielleicht noch den Meßeingang 
umschalten.
Daß ich zur Laufzeit an sämtlichen Parametern rumspielen muß, kommt 
eigentlich nie vor.

von c-hater (Gast)


Lesenswert?

Peter Dannegger schrieb:

> Daß ich zur Laufzeit an sämtlichen Parametern rumspielen muß, kommt
> eigentlich nie vor.

Richtig. Zur Laufzeit schraubt man wirklich nur relativ selten an 
irgendwelchen Konfigurationen herum. Aber es kommt, je nach Anwendung, 
eben doch vor und wenn es vorkommt, ist es relativ häufig auch noch 
performance-relevant.

Dazu kommt noch ein weiteres Problem: Es gibt eigentlich oft keine klare 
Abgrenzung zwischen "Konfiguration" und "Betrieb", weil das erst durch 
die Art der Benutzung der Hardware festgelegt wird. Einfaches, aber 
durchaus typisches Beispiel für das Dilemma: der generische IO-Pin.
Normalerweise legt man in der "Konfiguration" fest, ob das Ding als 
Eingang oder als Ausgang benutzt wird. Aber es gibt auch viele 
Anwendungen, da benutzt man exakt dieselbe Sache im Betrieb zum Wechsel 
zwischen einem aktiven Ausgang und dem HighZ-Status.

Allein dieses kleine Beispiel zeigt die grundsätztliche Schwäche jeder 
Abstraktion: sie abstrahiert (oft unter dem Gesichtspunkt einer 
typischen Art der Nutzung) und verdeckt damit vorhandene Möglichkeiten 
oder stellt sie zumindest nur suboptimal und damit im allgemeinen auch 
langsam zur Verfügung.

Und dieses Problem ist keinesfalls nur auf den Bereich der µC 
beschränkt, das findet man auf allen Ebenen der Softwareentwicklung. Ich 
denke da nur an die "File"-Abstraktion der Unixoide. Klar, es ist 
wunderschön einfach, eine UART als File zu öffnen, um ein paar Bytes 
darüber zu verschicken. Aber wenn ich wirklich alle Möglichkeiten nutzen 
will, die die UART-Hardware bietet, wird es recht kompliziert (und 
laaangsaaam).

Oder, noch deutlich krasser: LPT unter Windows. Eine vollständige 
Nutzung aller Features der Hardware ist dort überhaupt nur mit eigener 
Treiberentwicklung möglich. Klarer Fall von Überabstraktion mit dem 
Focus "Druckerschnittstelle".

Abstraktion ist Fluch und Segen zugleich. In kleinen µC hat sie eher nix 
zu suchen.

von W.S. (Gast)


Lesenswert?

Oliver Lubritz schrieb:
> Nun kann eine der Funktionen des
> "Treibers" sein, dass zum Beispiel das 8bit-Register CTRL1 des Sensors
> ausgelesen wird.

Jaja, etwa so stellt sich auch diese unsägliche ST-Lib dar, wo um die 
Hardware herum nur ein Brei aus Software geschmiert wird, der sachlich 
gar keinen Nutzen bringt, sondern nur das Ganze verkompliziert.

Es geht besser, sehr viel besser. Aber dazu muß man sich zunächst die 
gewünschte Wirkfunktion der Peripherie klarmachen. Im Beispielfall 
deines Beschleunigungssensors wäre das ja vermutlich, daß dein 
eigentliches Anwendungsprogramm zum einen den derzeitigen Stand 
(Richtung&Größe) der vorhandenen Beschleunigung abfragen will - und daß 
es zum anderen entweder zeitzyklisch oder bei hinreichenden 
Veränderungen aktiviert werden muß.

Also sollte dein "Treiber" sich intern um alles kümmern, was für den 
Sensor nötig ist und seine Schnittstelle zum übergeordneten Programm 
sollte eigentlich nur folgendes bieten:
- den momentanen Stand ablesen können
- in das vorhandene Eventsystem bei entsprechenden Bedingungen eine 
Botschaft einspeisen.

Kurzum, der Treiber soll für den Rest der Firmware eben DAS liefern, was 
man eigentlich wissen möchte. Alle Interna wie Register etc. sind dem 
aufrufenden programm doch eigentlich schnurz.

Ähnlich sieht es z.B. mit einem virtuellen COM-Port per USB aus. Kein 
aufrufendes Programm interessiert sich dafür, WIE der Treiber das zu 
sendende Zeugs über den USB rüberkriegt, oder wie er empfangenen Daten 
zwischenspeichert, bis man sie sich asynchron und einzeln je nach Gusto 
abholt.

W.S.

von Oliver L. (olubritz)


Lesenswert?

Peter Dannegger schrieb:
> Ich mache das meistens so, daß ich einmal die nötigen Einstellungen
> eines Peripheriebausteins im h-File definiere und die Init-Funktion
> rasselt das einfach nur runter und schickt es raus.
> Danach rufe ich nur noch die Read-Funktion auf, die mir den aktuellen
> Meßwert liefert. Bei nem ADC muß ich vielleicht noch den Meßeingang
> umschalten.
> Daß ich zur Laufzeit an sämtlichen Parametern rumspielen muß, kommt
> eigentlich nie vor.

So habe ich das quasi jetzt auch gelöst. Es kann aber schon passieren, 
dass man Einstellungen ändern muss, zum Beispiel wenn man die Datenrate, 
mit der der Sensor misst auf "Power-Down" stellen will, ihn also quasi 
ausschaltet. Bei einigen meiner Projekte schalte ich die Sensorik per 
Hardware sogar ganz ab zwischendurch. Nur wenn ich Messen will schalte 
ich sie ein, mache eine Messung und schalte sie dann wieder aus. Man 
benötigt dann immer wieder eine Neukonfiguration (ok die packt man in 
eine Funktion und ruft sie einfach immer wieder auf).

@c-hater:
Eine interessante Anmerkung. Ich denke du hast Recht. Eine Abstraktion 
kann helfen aber auch hinderlich sein.

@W.S.:
Ja es ist richtig es geht besser. Eine entsprechende Abstraktion 
verbessert auch auf jeden Fall die Nutzbarkeit, das stimmt. Aber wie 
schon geschrieben wurde, kann eine zu starke Abstraktion auch ein Fluch 
sein. Der Sensor bietet eine Menge von Funktionen und 
Einstellungsmöglichkeiten, welche man vielleicht nutzen will. Wenn ich 
nun eine dieser Einstellungen im Betrieb ändern möchte kann ich dies 
nicht, wenn mir keine entsprechenden Funktionen bereitgestellt werden. 
Ich denke dort lässt sich ein Mittelweg finden, der mir noch fehlt. Auf 
jeden Fall danke für den Denkansatz.

Olli

von Peter D. (peda)


Lesenswert?

Oliver Lubritz schrieb:
> Nur wenn ich Messen will schalte
> ich sie ein, mache eine Messung und schalte sie dann wieder aus. Man
> benötigt dann immer wieder eine Neukonfiguration (ok die packt man in
> eine Funktion und ruft sie einfach immer wieder auf).

Dann könnte man dem Init einen Parameter übergeben (0 = off, 1 = init).

Man kann auch separate Funktionen für selten benötigte Sonderwünsche 
schreiben. Werden sie nicht aufgerufen, dann kann ja der Linker toten 
Code entfernen.

von Oliver L. (olubritz)


Lesenswert?

Peter Dannegger schrieb:
> Oliver Lubritz schrieb:
>> Nur wenn ich Messen will schalte
>> ich sie ein, mache eine Messung und schalte sie dann wieder aus. Man
>> benötigt dann immer wieder eine Neukonfiguration (ok die packt man in
>> eine Funktion und ruft sie einfach immer wieder auf).
>
> Dann könnte man dem Init einen Parameter übergeben (0 = off, 1 = init).
>
> Man kann auch separate Funktionen für selten benötigte Sonderwünsche
> schreiben. Werden sie nicht aufgerufen, dann kann ja der Linker toten
> Code entfernen.

Stimmt das wäre auch eine Möglichkeit. Danke =)

Olli

von Jan B. (berge)


Lesenswert?

Sehr gut lässt sich so etwas übrigens in C++ mit Templates erschlagen. 
Da wird viel zur Compilezeit bereits erledigt :)

LG Jan

von Markus (Gast)


Lesenswert?

Hallo,

Oliver Lubritz schrieb:
> Aber wie
> schon geschrieben wurde, kann eine zu starke Abstraktion auch ein Fluch
> sein. Der Sensor bietet eine Menge von Funktionen und
> Einstellungsmöglichkeiten, welche man vielleicht nutzen will. Wenn ich
> nun eine dieser Einstellungen im Betrieb ändern möchte kann ich dies
> nicht, wenn mir keine entsprechenden Funktionen bereitgestellt werden.
dann stellt man sie halt zur Verfügung.
Werden spezielle Funktionen einer konkreten 
Schnittstellenimplementierung  benötigt, kann man in die Schnittstelle 
ja etwas wie einen "getDelegate()" vorsehen, wie z.B. in der Klasse 
EntityManager des Java Persistence APIs. Der Pointer, den getDelegate() 
zurückliefert, muß dann halt gecastet werden.

Die eigendliche Domäne der Anwendung braucht mit derartigen 
Spezialitäten nichts zu tun zu haben, wenn die Zugriffe auf die unter 
der Schnittstelle liegenden Funktionen entsprechend weggekapselt werden. 
Es gibt ja genug Design Patterns, die solchen Mechanismen einen Namen 
geben, hier z.B. Decorator, Wrapper oder Proxy.

Grüße, Markus

von Oliver L. (olubritz)


Lesenswert?

Jan Berg schrieb:
> Sehr gut lässt sich so etwas übrigens in C++ mit Templates erschlagen.
> Da wird viel zur Compilezeit bereits erledigt :)
>
> LG Jan

Ich verwende jedoch C ;)

von MaWin (Gast)


Lesenswert?

Oliver Lubritz schrieb:
> Es geht um das Thema Effizienz vs. "Usability".

Effizienz ist einfach: Wenn sich am späteren Programm nichts mehr 
weglassen lässt, ohne die Funktion (inkl. Fehlerbehandlung) zu 
kastrieren, dann ist es Code-effizient, und wenn es im verfügbaren uC 
schnell genug läuft, erfüllt es auch die Anforderungen an speed und 
space.

Effizienz ist also ein hartes Kriterium.

Oliver Lubritz schrieb:
> Wie handhabt ihr das bei euren Programmen? Welche
> Erfahrungen  habt ihr gemacht?

Daß das, was als angeblich vorausdenkend und erweiterungsfähig bei der 
Entwicklung angepriesen wurde, immer zu kurz gedacht war und die 
Handhabbarkeit des Codes massiv verschlechterte, weil man aus cpde nicht 
mehr ersehen konnte, was benötigt und was überflüssig war (mit dem 
Effekt daß überflüssiger Code auch oft nie getestet und daher falsch 
war), und man oft über die Funktion des Codes vollkommen im unklaren war 
weil man dem generischen code nicht mehr ansehen konnte, wozu er 
nützlich ist, was er als machen SOLL (Ausnahmen sind da echt generischer 
Code, beispielsweise ein Datenbankzugriff ohne sich um konkrete 
Daten/Tabellenstrukturen zu kümmern).

Usability ist also bullshit, weil als weiches Kriterium stets 
Auslegungssache ist und 90% der Coder legen es zu ihren Faulheitsgunsten 
aus, statt klar zu sagen "ja, ich wusste auch nicht wie ich das Problem 
lösen sollte, da habe ich mal 200 Zeilen Code geschrieben der das 
Problem bloss weiterreicht".

von Bronco (Gast)


Lesenswert?

Oliver Lubritz schrieb:
> Ich bin der Meinung, dass man speziell in der
> Mikrocontroller-Programmierung auf die Effizienz achten muss, da ja
> meist die Ressourcen knapp sind ;)

Ist Dein System (Microcontroller) ausreichend, um Deine Anforderungen 
(was Du erreichen willst) bei der von Dir gewählten Implementierung (wie 
Du es programmiert hast) zu erfüllen?

Wenn ja, kannst Du so ineffizient sein, wie Du willst, aber es spielt 
überhaupt keine Rolle, denn Dein System ist ausreichend stark.

Wenn nein, kannst Du entweder
- ein leistungsstärkeres System nehmen
- deine Anforderungen reduzieren
- versuchen, durch Optimierung Dein Ziel zu erreichen

Die Frage ist nun, ob die Optimierung sinnvoll (wirtschaftlich) ist, 
denn es kostet Dich Arbeit:
1. Das Optimieren selbst
2. Später, wenn Du Deinen hochoptimierten Code noch mal anfassen mußt, 
und falls Dich dies mehr Aufwand kostet, als bei einem weniger 
effizienten, aber besser verständlichen Code

Ggf. ist es billiger, einen größeren µC zu kaufen.

von Fachmann (Gast)


Lesenswert?

Effizienz ist sehr wichtig besondrs bei Mikrocontroller Programierung, 
weil  die Ressourcen knapp sind. Das hängt auch von dem Compiler ab, 
wenn er gut ist, dann kann er optimierten asm Code erzeugen, und wenn 
nicht, dann helfen dir deine Optimierungversuche auch nicht.

von Oliver L. (olubritz)


Lesenswert?

@MaWin: Danke. Schöner Denkanstoß. Du hast Recht, wenn man mehr 
Funktionen einbringt als man benötigt dann passiert es oft, dass der 
nicht benötigte Code nicht richtig getestet ist. Das kann dann echt in 
die Hose gehen später.

@Bronco: Speziell deine Anmerkung zur Wirtschaftlichkeit ist wichtig. 
Das habe ich mir zwar auch schon gedacht, aber irgendwie noch nicht 
richtig berücksichtigt.

Olli

von Arc N. (arc)


Lesenswert?

W.S. schrieb:
> Oliver Lubritz schrieb:
>> Nun kann eine der Funktionen des
>> "Treibers" sein, dass zum Beispiel das 8bit-Register CTRL1 des Sensors
>> ausgelesen wird.
>
> Jaja, etwa so stellt sich auch diese unsägliche ST-Lib dar, wo um die
> Hardware herum nur ein Brei aus Software geschmiert wird, der sachlich
> gar keinen Nutzen bringt, sondern nur das Ganze verkompliziert.

Ja und nein. Habe zwar mit der ST-Lib noch nicht gearbeitet, allerdings 
haben solche Software-Layer auch einen entscheidenden Vorteil: Sie 
berücksichtigen die diversen Fehler (sollten dies so weit möglich), die 
heutige Controller so mit sich rumschleppen. Das für jeden Controller 
bzw. Variante selbst zu berücksichtigen ist mMn nicht nur 
fehleranfällig, sondern ebenso verschwendete Zeit, die besser für andere 
Sachen genutzt werden kann.
Probleme an der Sache:
- Niemand garantiert wirklich, dass die APIs dieser Libs über einen 
längeren Zeitraum gleich bleiben oder die nächste Controllergeneration 
unterstützen
- Es kommt ein weiteres Abstraktionslayer hinzu, wenn diese 
Lib-Funktionen durch eigene Treiber gekapselt werden

von Quack+ (Gast)


Lesenswert?

Oliver Lubritz schrieb:
> Du hast Recht, wenn man mehr
> Funktionen einbringt als man benötigt dann passiert es oft, dass der
> nicht benötigte Code nicht richtig getestet ist. Das kann dann echt in
> die Hose gehen später.

Wenn man keine Test schreibt. Was zu MaWins Zeit wohl noch nicht ueblich 
war - da hielt man Ausprobieren noch fuer Testen.

Es fast ist immer sinnvoll, aktuell benoetigte Funktionalitaet nicht im 
Minimum genau auf den Anwendungszweck zugeschnnitten zu implementieren. 
Stattdessen wird die Anforderung abstrahiert, die Loesung generalisiert 
und so entwickelt und getestet. So vermeidet man komplexe, schlecht 
wart- und erweiterbare Spezialloesungen.

So spezifisch wie ein Stueck Code ist, so spezifisch sind dann auch die 
Tests - eng beschraenkt auf den einen Pfad, der bei der Entwicklung 
sichtbar war. Test sollen aber grossraeumig sein, damit sie auch Fehler 
finden, mit denen keiner gerechnet hat. Und an um so mehr Stellen ein 
Stueck Code verwendet wird, um so eher faellt ein Fehler zeitig auf. Mit 
spezifischen Code ist das nicht moeglich - da wird dann einfach noch 
eine Spezialloesung implementiert, die auch wieder genauso lausig 
getestet wird.

Noch schlimmer ist, wenn Jemand nachtraeglich an diesem beschraenkten 
Stueck Code rumfummeln muss, der gerade ein ganz anderes Problem loesen 
muss, weil Funktionalitaet fehlt, die gleich von Anfang leicht 
zusaetzlich haette implementiert werden koennen. Welcher Code ist wohl 
besser: Der von dem Entwickler, der gerade 100% im Thema ist, oder von 
jenem, der nebenbei etwas hinzufuegen muss?

Synergieeffekte treten nicht auf! Natuerlich kostet das am Anfang was, 
es wird Code geschrieben, der nicht unmittelbar gebraucht wird. Aber es 
ist eben so, wie immer im Leben: Gewinn macht nur, wer zeitig 
investiert.

Natuerlich gibt es Gegenbeispiele... endlose Frameworkhackerein, die nie 
an ein Ziel kommt. Damit wird gerne unterstrichen, wie gefaehrlich 
Generalisierung und Abstraktion sei - belastbare Zahlen gibt es dafuer 
aber nicht. Das ist nur eine Ausrede, um den Hackerkeller nicht 
verlassen zu muessen.

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
Noch kein Account? Hier anmelden.