In diesem Fall kann man sich ein eigenes Assert-Makro schreiben, das immer übersetzt wird. Es sichert wichtige Systemparameter zur Diagnose des Fehlers und führt das System dann in den sicheren Abschaltzustand. Auch hybride Designs sind denkbar, wenn keine Gefährdung von einem unerwarteten Programmfehler ausgeht, aber trotzdem hohe Anforderungen an die Software-Integrität vorliegen. Solche Systeme sind etwa Erdbeobachtungs-Satelliten. Sind die Daten des künstlichen Erdtrabanten falsch, so ist dadurch niemand in Gefahr. Eine Weltraum-Mission kostet etliche Millionen Euro, die Erwartungshaltung an die Güte der Daten ist also sehr hoch, obwohl die Gefahr eines Bitkippers im RAM oder eines vorübergehenden CPU-Fehlers im Orbit besonders hoch ist. Die Software muss also robust gegen solche strahlungsbedingten Fehlerquellen sein. Typischerweise ist daher missionskritische Software gespickt mit Zusicherungen, die die verschiedenen Fehlertypen – je nach Beschaffenheit des Fehlers – unterschiedlich behandeln:
Die meisten Fehler lassen sich einer der folgenden drei Klassen zuordnen:
Die wenigsten eingebetteten Systeme werden, wie der Satellit, ein Team von Fachkräften haben, das Tag und Nacht die Daten der Firmware überwacht. Wenn Ihr System auch keine „Bodenstation“ hat, die darauf wartet, Daten der Firmware zu analysieren, so könnten Sie doch im Wartbarkeits-Design daran denken,
Für die Erkennung dieser Situationen, wie gesagt, bieten sich Zusicherungen an.
Datenkapselung und Maskierung von Fehlern
Nun steht sauberes Software-Design – Stichwörter „Datenkapselung“, „Kohäsion“, „Modularität“ – im Widerspruch zur Testbarkeit im eingangs definierten Sinn. Moderne Programmiersprachen unterstützen den Programmierer weitgehend im sauberen Design, etwa durch Objektorientiertheit. Objektorientiertes Design macht einen Software-Test von Natur aus schwerer, weil der Zugriff auf interne Daten im Regelfall verwehrt bleibt. Die Maskierung von Fehlern wird also begünstigt, und beim Modultest muss man sich mit Tricks behelfen [4].
Umso wichtiger ist es daher bei objektorientiertem Design, bei Software mit hohem Integritätsanspruch, innerhalb der OO-Klassen Zusicherungen für diese versteckten Größen anzubringen.
Bjarne Stroustrup, Erfinder von C++, meinte in einem Interview [2], dass man bei Klassen nur dann Attribute für die Außenwelt unsichtbar machen sollte, wenn man deren Gültigkeit durch Invarianten prüfen kann. Eine Invariante ist eine Formel, die angibt, ob das Objekt gültig ist. In diese Formel finden die Werte der (versteckten) Attribute des Objekts Eingang. Im Falle einer Klasse, die besetzte und freie Speicherpartitionen eines Dual-Port-RAM verwaltet, könnte dies zum Beispiel die Summe der besetzten und freien Partitionen sein. Die muss immer konstant sein. Ist dies nicht der Fall, dann stimmt etwas nicht.