Kategorie-Archiv: Software

Frequenzzähler/ Periodenmesser mit einem PIC32 – Teil 8

Mittlerweile habe ich das Projekt abgeschlossen. Das Gerät funktioniert wie erwartet und die Genauigkeit und Kurzzeitstabilität ist gut. Einzig den Quarzoszillator werde ich wohl noch mal austauschen, da er eine zu hohe Temperaturabhängigkeit aufweist. Wenn man ihn mit dem Finger erwärmt, kann man das Messgerät auch als Fieberthermometer verwenden. Sobald ich mal günstig einen 1ppm TCXO mit 25 MHz bekomme wird das besser.

Im letzten Schritt habe ich noch die Spannungsversorgung ergänzt. Als Basis verwende ich ein normales USB Netzteil für die 5 Volt, die ich für die Anzeige und ein Teil der Eingangssignalverarbeitung benötige. Daraus leite ich dann noch mit einem einfachen Linearregler die 3,3 Volt für den Microcontroller ab.

Platine und Bereichsumschalter habe ich dann in ein Gehäuse eingebaut. Da ich keine Befestigungsschrauben auf der Vorderseite haben wollte, habe ich den Taster von der Rückseite her angeklebt. Das wäre beinahe schief gegangen, da ein wenig von dem Kleber auch an die Tastenkappe gekommen ist und diese mit der Frontplatte verklebt hat. Zum Glück konnte ich das Missgeschick mit etwas Geduld und Silikonöl beheben.

Das fertige Gerät

 

Was würde ich nun anders machen?

Im Vorfeld habe ich mir zu wenige Gedanken über den Aufbau der Platine und die Verteilung der Port-Pins gemacht. Da ich zuerst das Anzeigemodul aufgebaut habe, habe ich die Port-Pins danach ausgewählt, dass ich möglichst zusammenhängende Bits für die Bus Signale habe. Dabei habe ich nicht darauf geachtet, dass nur ein Teil der Input-Pins 5 Volt tolerant sind – und genau diese dann als Output verwendet. Zum Glück gibt es das 4-fach AND Gatter 7408 in einer VHC Version als Pegelwandler – allerdings nur im SMD Gehäuse. Die kleinen Pins in einer fliegenden Verdrahtung frei Hand anzulöten ist nicht einfach. Ich muss mir mal einen Vorrat an Adapterplatinen zulegen.

Weiterhin würde ich nun keinen 7447 mehr als 7 Segment Decoder verwenden. Statt dessen würde ich drei zusätzliche Port-Pins spendieren und jedes Segment einzeln per Software steuern. Das würde aber auch dazu führen, dass ich statt der 28 Pin Variante des PIC32 ein 44 Pin Gehäuse verwenden müsste. Und die zusätzlichen Pins würden weitere Zusatzfunktionen erlauben.

Zuletzt würde ich statt der beiden 32 Bit Counter nun vier 16 Bit Counter verwenden, die per Software dann jeweils auf 32 Bit verlängert werden – durch eine Interrupt Routine beim Überlauf. Damit hätte ich dann eine Zwei-Kanal Lösung oder könnte auch das Impuls-Pausen-Verhältnis messen.

Vielleicht werde ich das Projekt später noch mal aufgreifen und verbessern. Im Augenblick bin ich mit dem aktuellen Stand zufrieden und beende das Projekt erst mal.

Programmier-Un-tugenden, die man vermeiden sollte

Gestern ist mir mal wieder unschöner Programm-Code über den Weg gelaufen. Das hat mich dazu animiert, mal die häufigsten Fehler aufzulisten, die ich immer mal wieder sehe und über die ich mich dauerhaft ärgern kann.

Dabei geht es mir noch nicht mal um irgendwelche abstrakten Programmiermodelle oder best practices im Architekturbereich. Es geht um kurze, alltäglich Codestücke, die man eigentlich nicht falsch machen kann. Und doch wird es gerne falsch gemacht. Es geht auch nicht um Syntaxfehler, die filtert der Compiler raus. Sondern einfach nur um schlechten Code, der irgendwie funktioniert.

1. Unklare Vorstellungen über boolsche Werte

Wenn ich solche Abschnitte sehe, stellen sich mir die Nackenhaare auf:

boolean isEnabled = myButton.getEnabled();

if (isEnabled == true) { ...

Die Variable isEnabled enthält einen boolschen Wert, die IF-Entscheidung erwartet einen. Warum dann noch diesen zusätzlichen Vergleich dazu packen. Damit sich der Compiler auch wirklich sicher ist, dass der Wert true ist? Und dann könnte man konsequenterweise doch auch „if ((isEnabled == true) != false)“ schreiben.

Mir signalisiert so eine Vorgehensweise, dass der Entwickler nur eine vage Vorstellung von boolschen Werten und ihrer Verwendung besitzt.

2. Überflüssige Kontrollstrukturen

Dieses Beispiel geht in die gleiche Richtung wie Beispiel 1.

boolean isEnabled = myButton.getEnabled();

if (isEnabled) {

  otherButton.setEnabled(true);

} else {

  otherButton.setEnabled(false);

}

Hier wird ohne nachvollziehbaren Grund eine komplette Kontrollstruktur aufgebaut. Dabei kann ich mich gar nicht über die verschenken Nanosekunden ärgern. Aber jeder andere Entwickler erwartet hier, dass etwas passiert, was schwergewichtiger ist als eine einfache Zuweisung: „otherButton.setEnabled(isEnabled)“.

Leider kommt dieser Fehler in der Praxis immer wieder vor. Auch hier liegt vermutlich oft einfach ein Defizit im Bereich „mal darüber nachdenken, was ich gerade mache“ vor.

3. Verdrehte Ausdrücke

Eines meiner Lieblingsaufreger, besonders gern von alten C Programmierern gemacht:

if ( 7 == anzahlWochentage) ...

Das liest sich einfach schlecht – Obi-Wan Kenobi Grammatik. Wenn man den Ausdruck umgangssprachlich formulieren würde, würde man sagen „Wenn die Anzahl der Wochentage gleich 7 ist“ und keinenfalls „Wenn 7 die Anzahl der Wochentage ist“. Auch wenn der Inhalt der gleiche ist, stolpert man über die falsche Reihenfolge, der Gedankenfluss wird gestört, die Aufmerksamkeit ist beeinträchtigt.

Die Herkunft dieses Anti-Patterns ist klar. Uralte C Compiler (älter als 30 Jahre), haben die Anwender leichtfüßig in Fehler der Art „if (anzahlWochentage = 7)…“ laufen lassen. Durch das vergessene zweite Gleichheitszeichen wird aus dem Vergleich eine Zuweisung. In der umgedrehten Schreibweise führt das zu einem Compilerfehler, da ein konstanter Wert nicht als Left-Value verwendet werden kann. Aber auch vor 30 Jahren gab es schon „lint“ für solche Probleme. Alle modernen Compiler werfen hier deutliche Warnings aus, so dass man diesen Fehler eigentlich nicht mehr machen kann.

Ein Entwickler, der sich dieser Schreibweise bemächtigt, löst bei mir schnell den Verdacht aus, dass er sich nicht um seine Warnings kümmert. Oder, dass er so viele Warnings hat, dass er sie gar nicht mehr kontrollieren kann. Beides ist schlecht, der Programmierer bewegt sich Haarscharf an der Grenze zum Chaos.

4. Magic Numbers

Die Verwendung von symbolischen Konstanten statt Zahlen im Quellcode ist mittlerweile fast überall Standard. In vielen Firmen gibt es Style Guides, die die Verwendung von Magic Numbers ausdrücklich verbieten.

Der Nutzen von Konstanten liegt auf der Hand. Wenn ich fünf Produktgruppen habe und im Programmcode alle Schleifen mit der Ziffer 5 laufen lasse, habe ich bei einer Erweiterung auf 6 Gruppen massiven Aufwand. Man kann ja nicht einfach per Suchen und Ersetzen alle 5 gegen eine 6 austauschen. Statt dessen muss man sich jede Verwendung genau darauf hin ansehen, ob die Zahl der Gruppen gemeint ist. Zudem gibt es weitere Verwendungen, der Index der letzten Gruppe beträgt 4 und nicht 5. Darauf muss man also auch achten.

Übel wird es, wenn ein Programmierer zwar den Wortlaut der Regel befolgt aber den Sinn nicht verstanden hat (oder nicht verstehen will). Dann kommen solche Konstruktionen vor:

const FIVE = 5;

...

for (var group = 0; group < FIVE; group++) ...

Der Wortlaut der Regel wurde befolgt, im Programmcode selber gibt es keine Magic Numbers. Aber das Ziel wurde verfehlt. Ich sehe der FIVE in der for Schleife nicht an, was für einen Zweck sie hat. Besonders übel wird es, wenn sich die Zahl der Gruppen auf 6 erhöht:

const FIVE = 6;

So eine Vorgehensweise kann man nur begrenzt mit Unfähigkeit begründen. Das grenzt schon an Sabotage.

5. Unsinnige Kommentare

Vernünftige Kommentare zu erstellen, ist nicht unbedingt einfach. In manchen Betrieben gibt es eine Festlegung, was kommentiert werden muss. Bei uns ist es z.B. so, dass alle public Methoden mit einem JavaDoc Header versehen werden müssen. Kommentare innerhalb einer Funktion sind aber kaum über einen Style Guide definierbar. Wenn man dann einfach einen bestimmten Prozentsatz von Kommentarzeilen fordert, entstehen solche Konstruktionen:

customers++;  // customer wird eins hochgezählt

Ein unglaublich blöder Kommentar, der genau das wiederholt, was der Programmcode ganz offensichtlich ausführt. Solche Kommentare sind nicht nur nutzlos. Sie sind sogar schädlich. Spätestens dann, wenn sich der Programmcode mal ändert und der nutzlose Kommentar nicht angepasst wird. Dann habe ich einen Widerspruch im Quellcode der schwere Irrtümer auslösen kann.

Kommentare sollten im Normalfall NICHT beschreiben, was passiert. Das wird durch den Programmcode am Besten beschrieben. Und wenn der schwer verständlich ist, dann sollte man sich lieber Gedanken über eine bessere Schreibweise statt über einen Kommentar machen.

Kommentare sollten beschreiben WARUM etwas passiert. Denn dieser Teil ist nicht aus dem Code abzuleiten. Vielleicht aus dem Kontext. Oder aus dem Pflichtenheft (liegt das fünf Jahre später noch in einer aktualisierten Form vor?).

Haftung der Hersteller für Sicherheitslücken

Wenn eine größere Sicherheitslücke in einer Software auftritt, wird schnell der Ruf laut, dass doch der Hersteller dafür haften müsste. Aber ist das auch gerechtfertigt?

Ich möchte das Problem einmal in die Welt der realen Dinge transportieren. Wenn ein Auto gestohlen wird, kommt dann auch der Ruf nach der Herstellerhaftung? Nein. Selbst eine Wegfahrsperre ist nur ein Schutz vor „Gelegenheitsdieben“. Für ein Profi stellt sie kein Hindernis dar. Das Auto kommt auch komplett ohne Schutz gegen „denial of service“ Attacken. Ein Angreifer kann jedes Auto in wenigen Sekunden in einen nicht mehr fahrbereiten Zustand versetzen. Der Eigentümer kann sich nicht dagegen schützen.

Wenn ein Einbrecher in eine Wohnung einbricht, wird dann der Bauträger verklagt? Auch nicht. Selbst dann nicht, wenn er Schlösser einbaut, die ein Profi in wenigen Sekunden knacken kann.

Wer sich darauf verlassen möchte, dass seine Haustür sicher ist, sollte sich dieses Video nicht ansehen (und auch nicht auf YouTube nach „lock picking contest“ suchen).

Wenn Sie ein Fahrrad kaufen, erhalten Sie es im Allgemeinen sogar komplett ohne Schutz gegen Diebstahl oder Vandalismus. Verklagen Sie den Fahrradhändler, wenn es gestohlen wird? Oder die Reifen zerstochen werden? Auch nicht.

Noch ein Beispiel: ein Safe. Er hat keine Funktion außer eben sicher zu sein. Sie können aber trotzdem keinen Safe kaufen, der absolute Sicherheit garantiert. Sie können nur 30 Minuten, 60 Minuten oder 120 Minuten Schutz kaufen (gegen viel mehr Geld auch länger, aber nicht beliebig lang). Wenn Sie einem Einbrecher ausreichend viel Zeit lassen, wird er jeden Safe knacken.

In der realen Welt haben wir in Kauf genommen, dass es keine absolute Sicherheit gibt. Und wir müssen uns daran gewöhnen, dass das im Bereich der Software ebenfalls nicht möglich ist. Natürlich sollte ein Hersteller bestrebt sein, sein Produkt so sicher wie möglich zu machen. Aber egal wie viel Aufwand man treibt, wenn es etwas wertvolles gibt, wird es immer Kriminelle geben, die sich dieses mit viel Energie und manchmal auch mit Finesse aneignen wollen. Die Situation wird nicht besser, wenn man per Gesetz eine Eigenschaft einfordert, die prinzipiell nicht zu erfüllen ist.