KI und die Zukunft der Systemprogrammierung

C++
Kris van Rens wirft einen Blick auf die Zukunft der Systementwicklung und darauf, dass die Zufriedenheit der Entwickler ein wichtiger Aspekt der Softwareentwicklung ist

Künstliche Intelligenz im Allgemeinen und große Sprachmodelle (LLMs) im Besonderen verändern unbestreitbar die Art und Weise, wie wir arbeiten und Code schreiben. Insbesondere beim Lernen, Erklären, Refactoring, Dokumentieren und Überprüfen von Code erweisen sie sich als äußerst nützlich.

Für mich ist die Generierung von produktionsreifem Code mit einem LLM im Chat-Stil jedoch immer noch eine gemischte Sache. Die sorgfältig ausgearbeitete Eingabeaufforderung für eine komplexe, eingeschränkte Aufgabe übersteigt den resultierenden Code oft um Größenordnungen, so dass ich die Produktivitätsgewinne in Frage stelle. Manchmal ertappe ich mich dabei, wie ich die Eingabeaufforderung iterativ bekämpfe, um den richtigen Code für mich zu generieren, nur um dann festzustellen, dass sie zufällig vergessen hat, eine meiner früheren Anforderungen zu implementieren. Manchmal erzeugen die LLMs auch Code mit ungültigen Konstrukten: Sie halluzinieren Antworten, und das immer mit großer Sicherheit. Hinzu kommt, dass die LLMs so arbeiten, dass die Antworten jedes Mal, wenn Sie eine ähnliche Abfrage eingeben, völlig anders ausfallen können oder zumindest stark von der jeweiligen Eingabeaufforderung abhängen.

OpenAI-Mitbegründer Andrej Karpathy hat es gut ausgedrückt: „In gewisser Weise ist alles, was LLMs tun, Halluzinationen. Sie sind Traummaschinen.“ Dieses scheinbar ’schwarzmagische‘ Verhalten von LLMs ist mit meinem inneren technikgetriebenen Drang, einem deterministischen Prozess zu folgen, nicht ganz vereinbar. Vielleicht liegt es an meiner völligen Inkompetenz in Sachen Sofortengineering, aber aus meiner Sicht müssen wir trotz der Macht der generativen KI, die uns zur Verfügung steht, immer noch absolut verstehen, was wir tun, anstatt blind auf die Korrektheit des Codes zu vertrauen, der von diesen Traummaschinen erzeugt wurde. Das seltsame Gefühl und die Idiosynkrasie von LLMs werden in Zukunft wahrscheinlich nachlassen, aber ich möchte den Code, den ich produziere und für den ich verantwortlich bin, immer noch wirklich verstehen.

Wahrscheinlich wird die KI in der zukünftigen Softwareentwicklung eine Abstraktionsverschiebung ermöglichen, die es uns erlaubt, auf einer höheren Abstraktionsebene zu entwerfen, als wir es heute oft tun. Das wiederum könnte dazu führen, dass wir weniger Code von Hand schreiben müssen. Ich kann jedoch nicht erkennen, wie die Verwendung von generiertem Code in der Produktion ohne die Korrektheitsgarantien strenger Tests und formaler Verifizierung gut funktionieren soll – das ist heute nicht die Realität.

''An aspect of software engineering where LLMs can make an overall positive difference is interpreting compiler feedback.''

Positiver Unterschied

Ein weiterer Anwendungsbereich von LLMs ist die Inline-Code-Vervollständigung in einem Editor/IDE. Selbst das ist für mich kein durchschlagender Erfolg. Mehr als einmal war ich davon überwältigt, dass die LLM-basierte Code-Vervollständigung eine mehrzeilige Lösung für das vorschlägt, was sie glaubt, dass ich eingeben wollte. Anstatt die Code-Idee direkt aus meiner Vorstellung zu implementieren, muss ich dann einen Klecks generierten Vorschlagscode lesen und mich fragen, was er tut und warum. Diese Vervollständigungen sind nicht einfach und bringen mich oft auf die schiefe Bahn. Ich habe in letzter Zeit mit der Embedded-Entwicklung für Mikrocontroller-Einheiten experimentiert und festgestellt, dass die LLM-basierte Vervollständigung vor allem bei Code in diesem Kontext nur Vermutungen anstellt und manchmal sogar nicht existierende GPIO-Pin-Nummern (General Purpose IO) erfindet, während sie arbeitet. Mir gefällt die Kombination von LLMs zur Codevervollständigung mit einem KI-Modell, das die Bewegungen des Editors beim Refactoring vorhersagt. Refactors sind oft Stapel von ähnlichen kleinen Operationen, die die Modelle gut vorhersagen können.

Ein Aspekt der Softwareentwicklung, bei dem LLMs einen positiven Beitrag leisten können, ist die Interpretation von Compiler-Feedback. C++ zum Beispiel ist berüchtigt für seine schwer lesbaren und oft sehr langen Compilerfehler. Die Einführung von Konzepten in C++20 sollte hier eine drastische Verbesserung bewirken, aber ich habe es nicht erlebt. Vielleicht ist das noch nicht ganz ausgereift, aber bis dahin sind wir gezwungen, uns mit komplexen und oft langen Fehlermeldungen (manchmal sogar Hunderte von Zeilen lang) zu beschäftigen. Aufgrund ihrer Fähigkeit, Compiler-Meldungen zu interpretieren oder zusammenzufassen, in Kombination mit ihren lehrreichen und generativen Funktionen, sind LLMs mit einem großen Kontextfenster geeignet, solche Rückmeldungen zu verarbeiten, was sie zu einem großartigen Begleitwerkzeug für C++-Entwickler macht. Es gibt einen enormen Bestand an bereits existierendem C++-Code und Dokumentation, aus dem man lernen kann, was eine gute Grundlage für das Training eines LLM ist.

Weitere Nachteile von C++ sind die ständig wachsende Komplexität der Sprache und die Tendenz des Compilers, Sie eher zu bekämpfen als Ihnen zu helfen. Ein effektiver Einsatz von LLMs zur Bekämpfung dieser Probleme könnte die Sprache kurzfristig retten. Die Entwicklung der C++-Sprache ist langsam, aber das Potenzial der Werkzeuge ist enorm. Angesichts der schieren Menge an bestehendem C++-Code, der heute verwendet wird, wird die Sprache auf Dauer Bestand haben, und jedes Tool, das Entwicklern bei der Arbeit mit ihr hilft, ist willkommen.

''To me, writing code is a highly creative, educational and enjoyable activity.''

Glück der Entwickler

Die Verwendung von LLMs zur Codegenerierung nimmt mir auch einen Teil der Freude am Programmieren. Für mich ist das Schreiben von Code eine höchst kreative, lehrreiche und unterhaltsame Tätigkeit, bei der ich meine Fähigkeiten verfeinern kann. Wenn ich die Arbeit von einer magischen Box erledigen lasse, wird diese Erfahrung bis zu einem gewissen Grad zunichte gemacht – selbst das manuelle Schreiben der langweiligen Teile und der Tests hat einen gewissen Bildungswert.

Ger Cloudt, ein Kollege aus dem Bereich der Softwareentwicklung, behauptet in seinem Werk über Softwarequalität, dass die organisatorische Qualität, zu der auch die Zufriedenheit der Entwickler gehört, nur die halbe Wahrheit ist. Ihm zufolge ist die organisatorische Qualität der Schlüssel, da sie die Qualität von Design, Code und Produkt ermöglicht. Sicherlich sind ein sauberer Code und eine saubere Architektur wichtig, aber ohne die richtigen Tools, die richtige Einstellung, die richtige Kultur, die richtige Ausbildung usw. wird der Entwicklungsprozess irgendwann zum Stillstand kommen.

LLMs helfen zweifellos bei den Werkzeugen und der Ausbildung, aber es gehört mehr zum Programmieren, als nur Code wie ein Roboter zu produzieren. Ein Teil des Handwerks der Softwareentwicklung ist – wie bei jedem Handwerk – die Freude und der Stolz auf Ihre Arbeit und die Ergebnisse, die Sie produzieren. Halten Sie mich für verrückt, aber ich empfinde eine große Befriedigung, wenn ich mit meinen eigenen Händen schön aussehenden Code erstellen kann.

Überdenken Sie den Zustand von Rust

C++
Ende 2022 schrieb Kris van Rens über den Aufstieg der Programmiersprache Rust, und zwar weitgehend in demselben Anwendungsbereich, der von C und C++ dominiert wird. Hat sich die Landschaft der traditionellen Systemprogrammierung wirklich verändert oder war das alles nur viel Lärm um nichts?

Laut dem Tiobe-Index steht Python mit 23 Prozent einsam an der Spitze der „beliebtesten Programmiersprachen“. Es folgen C++ (10 Prozent), Java (ebenfalls 10 Prozent) und C (9 Prozent). Der Index versucht, Erkenntnisse darüber zu gewinnen, wonach Menschen in Suchmaschinen suchen, wobei man davon ausgeht, dass dies ein Maß für die Popularität ist. Als relativ junge Sprache liegt Rust mit etwas mehr als 1 Prozent auf Platz 14.

In einer abschließenden Zusammenfassung schreibt der CEO von Tiobe, Paul Jansen, über Rust, dass „seine steile Lernkurve es leider nie zur Lingua Franca des gewöhnlichen Programmierers machen wird.“ Die steile Lernkurve einer Sprache als Hindernis auf dem Weg zu einem großen Erfolg zu nennen, erscheint mir etwas zweifelhaft, wenn man bedenkt, wie beliebt C++ in Kombination mit seiner Komplexität in großem Maßstab ist. Ich denke auch, dass die Überschätzung und Betonung der Lernkurve einer Sprache die Entwickler unterschätzt – viele Unternehmen, die Rust in der Produktion einsetzen, haben bereits gezeigt, dass es sehr leicht zu handhaben ist.

''When it comes to learning in general, I always tend to keep a positive attitude: people are much more capable than we might think.''

Einzigartiges Kunststück

In den letzten Jahren hat sich Rust als würdige Alternative im Bereich der produktionsgerechten Systemprogrammierung etabliert. Es demonstriert erfolgreich, wie eine Sprache gleichzeitig modern, performant und sicher sein kann. Sie wird kontinuierlich alle sechs Wochen veröffentlicht, so dass es immer etwas Neues gibt – zum Zeitpunkt der Erstellung dieses Artikels sind wir bei v1.85. Neue Funktionen kommen, wenn sie fertig sind, und die meisten Änderungen an der Sprache oder der Bibliothek erfolgen eher stückweise.

Da Rust immer ausgereifter wird, hat seine Beliebtheit und Akzeptanz im Laufe der Zeit allmählich zugenommen. Der Risikofaktor für die Einführung als Produktionssprache der Wahl hat nachgelassen, wie man aus den Berichten vieler Unternehmen schließen kann. Google hat Teile von Android in Rust umgeschrieben, um die Sicherheit zu verbessern, Microsoft schreibt zentrale Windows-Bibliotheken in Rust um und Amazon verwendet Rust schon seit langem in seiner AWS-Infrastruktur.

Eine weitere erwähnenswerte Besonderheit ist, dass Rust neben C Teil des Mainline-Linux-Kernels ist. Es muss gesagt werden, dass die Bemühungen, die Unterstützung für Rust auf alle Kernel-Subsysteme auszuweiten, nicht unumstritten sind, aber mit dem Segen von Linus Torvalds werden Fortschritte erzielt . Es wird sehr interessant sein zu sehen, wie sich dieses Experiment entwickeln wird.

''One of my main observations is that switching back from Rust to C++ makes me feel as if I’m being flung back into the dark ages of systems software development.''

Glückliche Entwickler

Ich habe in den letzten Jahren viel mit Rust und C++ gearbeitet. Eine meiner wichtigsten Beobachtungen ist, dass der Wechsel von Rust zu C++ mir das Gefühl gibt, in das dunkle Zeitalter der Systemsoftwareentwicklung zurückgeworfen zu werden. Das mag hart klingen, aber ehrlich gesagt fühlen sich die meisten Programmieraufgaben selbst bei der Verwendung der neuesten Version, C++23, mühsam und eingeschränkt an, verglichen mit dem, was in Rust möglich wäre. In den ersten Tagen habe ich manchmal die Möglichkeit vermisst, geschriebenen Code direkt mit dem ausgegebenen Maschinencode zu korrelieren, wie es in C++ möglich ist, aber das ist in 99 Prozent der Fälle absolut unnötig, und moderne Compiler sind bei der Optimierung ohnehin viel kompetenter als Menschen.

Was das Tooling-Ökosystem und die Integration angeht, ist Rust auf einer ganz anderen Ebene und viel mehr auf der Höhe der Zeit in der heutigen Web-Entwicklungswelt. Während ich mit der C++-Sprache und dem Compiler oft darum kämpfe, die Dinge richtig zu machen, scheinen mich die Strenge von Rust, das Typsystem, die vernünftigen Vorgaben und der Borrow Checker ganz natürlich zu den richtigen Designentscheidungen zu führen – contend vs. guide. Wenn mein Rust-Code erfolgreich gebaut wird und die Tests bestehen, kann ich das Projekt mit der Gewissheit verlassen, dass die Software während der Laufzeit nicht abstürzt und der Code nicht einfach von einem Kollegen gebrochen werden kann. Auch die Rust-Makrosysteme und das hochwertige Paket-Ökosystem mit Bibliotheken sowie Plugin-Tools für das Build-System machen einen großen Unterschied in der Produktivität.

Diese und andere Aspekte machen die Arbeit mit Rust äußerst angenehm. Sie machen Entwickler glücklich. Es gibt einen Grund, warum Rust in der Stack Overflow-Entwicklerumfrage nun schon neun Jahre in Folge die am meisten gewünschte Programmiersprache ist.

Dividenden

Rust ist sehr gut für den Produktionseinsatz geeignet, sogar in kritischen Systemen, die Sicherheitszertifizierungen erfordern (z.B. durch die Verwendung der Ferrocene Toolchain). Ich halte die Einführung von Rust für einen logischen Schritt, um die Vorteile der Speichersicherheit, der hohen Produktivität und der größeren Zufriedenheit der Entwickler schon heute zu nutzen, anstatt zu warten, bis die aktuellen Tools mit dem Rest der Welt Schritt halten. Hinzu kommt die Möglichkeit, durch das Erlernen einer neuen Programmiersprache ein besserer Entwickler in jeder anderen Programmiersprache zu werden.

Wenn es um das Lernen im Allgemeinen geht, neige ich immer dazu, eine positive Einstellung zu bewahren: Die Menschen sind viel fähiger, als wir vielleicht denken. Ja, die Lernkurve für Rust ist steiler als die der meisten anderen Sprachen, aber sie ist es wert und zahlt sich langfristig aus. Ich würde eine steile Lernkurve und vernünftige und strenge Sprachregeln und -garantien jederzeit einem Leben mit Software-Speichersicherheitsfehlern vorziehen.

Überdenken Sie den Stand von C++

C++
Ende 2022 schrieb Kris van Rens über den Stand von C++ zu dieser Zeit und seine Herausforderer. Eine Fortsetzung nach zwei weiteren Jahren.

Im Jahr 2022 zog Google aus Unzufriedenheit mit dem Entwicklungsprozess von C++ einen Großteil seiner Ressourcen aus der Arbeit an C++ und dem Clang-Compiler-Frontend ab. Als Alternative kündigte es das langfristige Projekt Carbon an, eine Nachfolgesprache, die eng mit C++ zusammenarbeiten kann. Dies und die darauf folgenden Ereignisse stellten einen Wendepunkt für C++ dar, da die Sprache wegen der angehäuften technischen Schulden und des relativ langsamen Entwicklungstempos ernsthaft kritisiert wurde. Von diesem Moment an, so schien es, hatte jeder eine (starke) Meinung und verkündete sie lautstark – die Menge an Kritik konnte vom C++-Komitee nicht länger ignoriert werden.

Ein weiterer Aspekt von C++, der unter Beschuss geraten ist, ist die fehlende Speichersicherheit. Speichersicherheit in einer Programmiersprache bezieht sich auf die Fähigkeit, Fehler im Zusammenhang mit unsachgemäßem Speicherzugriff, wie z.B. Pufferüberläufe, Use-after-free-Fehler oder baumelnde Zeiger, durch eingebaute Funktionen und Garantien in der Sprache selbst zu verhindern oder abzufangen. Dies kann zu allgemeiner Sprachsicherheit erweitert werden, bei der alle undefinierten Verhaltensweisen und nicht spezifizierte Semantiken aus der Sprache eliminiert werden. Sprachsicherheit ist ein Konzept, das auf einem Spektrum und nicht als binäre Eigenschaft definiert ist; einige Sprachen sind sicherer als andere. Beispiele für Sprachen, die als sicher gelten und dennoch ein relativ niedriges Niveau haben, sind Swift, Ada und Rust.

Nach der sprichwörtlichen Hitze des Sommers 2022 hat eine Reihe von Schlägen in Form von öffentlichen Empfehlungen zur Speichersicherheit sowohl C als auch C++ explizit ins schlechte Licht gerückt. Ende 2022 meldete sich zunächst die NSA mit einem White Paper zu Wort, in dem sie uns aufforderte, von C und C++ abzurücken. Dann begann die CISA (die US Cybersecurity Infrastructure Security Agency), sich für eine Roadmap zur Speichersicherheit einzusetzen. In den Jahren 2023 und 2024 verkündeten sogar das Weiße Haus und der US-Verbraucherbericht, dass wir die Speichersicherheit ernster denn je nehmen und zu speichersicheren Sprachen übergehen sollten. Es gab noch viele weitere Ereignisse, aber es genügt zu sagen, dass sie alle vom C++ Komitee nicht unbemerkt geblieben sind.

''C is quite a simple language; it’s easy to learn and get started with. However, it’s very hard to become advanced and proficient at it at scale.''

Zugegeben, einige der Bemühungen der Mitglieder des C++-Ausschusses, die öffentlichen Angriffe zu entkräften, wirkten ein wenig verächtlich. Oft wurde die Speichersicherheit als „nur eines der vielen potenziellen Softwareprobleme“ heruntergespielt. Das klingt für mich sehr nach einem logischen Trugschluss. Sicher, viele Dinge können schief gehen, und eine sichere Sprache ist kein Allheilmittel. Allerdings haben sich die Anforderungen an die Softwareentwicklung in den letzten vierzig Jahren drastisch verändert, und heute ist die Speichersicherheit ein gelöstes Problem für viele andere Sprachen, die im gleichen Anwendungsbereich eingesetzt werden können. Offiziell hat die ISO-Arbeitsgruppe 21 (WG21) die Studiengruppe 23 (SG23) für „Safety and Security“ eingesetzt, deren Aufgabe es ist, die besten Wege zu finden, um C++ zu einer sichereren Sprache zu machen und gleichzeitig andere Einschränkungen wie die Abwärtskompatibilität einzuhalten – gar nicht so einfach.

Unbestreitbare Kluft

Ich habe in den letzten Jahrzehnten mit verschiedenen Programmiersprachen gleichzeitig in der Produktion gearbeitet. Was mir bei all meinen Erfahrungen mit C und C++ besonders auffällt, ist die schiere kognitive Belastung, die sie für Entwickler darstellen.

C ist eine recht einfache Sprache, die leicht zu erlernen ist und mit der man leicht anfangen kann. Es ist jedoch sehr schwer, sie in großem Umfang zu beherrschen und weiterzuentwickeln. Da es sich um eine einfache Sprache handelt, sind Sie gezwungen, viele wichtige fehleranfällige technische Aufgaben wie die Speicherverwaltung und die richtige Fehlerbehandlung manuell zu erledigen – wichtige Aspekte einer zuverlässigen, fehlerfreien Software. Es gibt zwar viele Kontrollmöglichkeiten auf niedriger Ebene, aber die Zeremonie und der kognitive Aufwand, um die Dinge richtig zu machen, sind einfach umwerfend.

Das Gleiche gilt weitgehend für C++. Es macht die Dinge besser, indem es Sie beim Schreiben von korrektem Code unterstützt, zum Beispiel mit der Standardbibliothek, die intelligente Zeiger für die Speicherverwaltung enthält. Allerdings macht es die enorme Komplexität der Sprache auch schwer, sie in großem Umfang korrekt zu verwenden.

Hinzu kommt, dass all diese Aspekte der Codierung in C und C++ keine Garantie dafür bieten, dass die Dinge nach der Kompilierung zuverlässig sind. Dies zwingt Entwickler dazu, sich mit bewährten Verfahren zu befassen, Compiler-Sanitizer und statische Analysatoren zu verwenden und umfangreiche Tests durchzuführen, nur um sicherzugehen, dass alles in Ordnung ist. Natürlich sollten die meisten dieser Aktivitäten Teil einer gesunden Denkweise von Softwareentwicklern sein, aber es ist schmerzlich zu erkennen, dass C und C++ die Anforderung, diese Arbeit zu erledigen, auf den Entwickler abwälzen, anstatt sie direkt in der Sprache zu berücksichtigen. Die Entwicklung einer Sprache ist, wie jede technische Herausforderung, eine endlose Abfolge von Kompromissen, aber es gibt eine unbestreitbare Lücke zwischen den Fähigkeiten der ‚alten Sprachen‘ und den aktuellen Bedürfnissen der Softwareentwicklung. Andere, neuere Sprachen zeigen, dass es möglich ist, diese Anforderungen zu erfüllen und gleichzeitig das Leistungspotenzial zu erhalten.

''New features improve the language but also inherently increase the already quite substantial complexity, while all the old footguns and dangers like undefined behavior are still there.''

Jahre entfernt

Die meisten Programmiersprachen werden im Laufe der Zeit ständig verbessert. In der Welt von C wird sich jedoch wahrscheinlich wenig bis gar nichts ändern. Für viele Projekte ist C daher heute nicht mehr die richtige Sprache, wenn Sie überhaupt noch Sicherheit wünschen. Es gibt Alternativen, die für den Zweck besser geeignet sind – wenn dies angesichts Ihrer Projektbeschränkungen und -präferenzen möglich ist.

Bei C++ sieht die Sache anders aus. Die WG21 bereitet sich derzeit auf die Veröffentlichung von C++26 vor, das enorme neue Funktionen mit sich bringen wird, darunter (höchstwahrscheinlich) Verträge, Executors und sogar statische Reflexion. Diese Funktionen werden mit Sicherheit die Spielregeln verändern, aber vor allem das Anwendungspotenzial der Sprache oder, im Falle von Verträgen, die Sicherheit und Korrektheit verbessern, allerdings auf Kosten der manuellen Arbeit des Entwicklers.

Neue Funktionen verbessern die Sprache, erhöhen aber auch die ohnehin schon beträchtliche Komplexität, während all die alten Fußangeln und Gefahren wie undefiniertes Verhalten immer noch vorhanden sind. Wenn Sie als Trainer Anfängern C++ beibringen, bleibt es zum Teil eine Übung, sie von den Fallstricken fernzuhalten – nicht wirklich eine natürliche, bequeme Art zu lehren oder zu lernen.

Das ‚Paralleluniversum‘ der Circle C++-Sprache zeigt, wie die scheinbar schwerfällige Syntax und Sprachdefinition von C++ immer noch in der Lage ist, viele andere großartige Funktionen wie echte Enumeratoren, Pattern Matching, statische Reflexion und sogar einen Borrow Checker zu integrieren. Leider ist diese bemerkenswerte Ein-Mann-Show von Sean Baxter kein standardisiertes C++ (und umgekehrt). Die Chancen sind gering, dass eine dieser hervorragenden Funktionen in absehbarer Zeit in das offizielle C++ aufgenommen wird.

Baxter hat auch einen „Safe C++“-Vorschlag, den er der Safety and Security Study Group im November letzten Jahres vorgelegt hat. Darin schlägt er vor, C++ um eine „rigoros sichere Teilmenge“ der Sprache zu erweitern, die die gleichen Sicherheitsgarantien bietet wie der Rust-Borrow-Checker. Ich begrüße diese Bemühungen, aber es bleibt abzuwarten, ob und in welcher Form dieser Vorschlag seinen Weg durch den oft träge erscheinenden Entwicklungsprozess der Sprache C++ finden wird. Die Arbeiten an C++26 haben sich weitgehend angenähert und C++29 ist noch ein paar Jahre entfernt. Hinzu kommt die Implementierungs-/Industrialisierungszeit dieser Spezifikationsversionen, bevor sie wirklich auf unseren virtuellen Werkbänken landen, und es könnte durchaus noch ein Jahrzehnt dauern – wenn wir Glück haben.

Grünere Weiden

Aber es ist noch nicht alles verloren. Das C++-Komitee leistet großartige Arbeit bei der Weiterentwicklung der Sprache, und der aktuelle Stand der Sprache und des Ökosystems ist besser denn je. Es ist nur so, dass die Kluft zwischen dem, was C++ heute bieten kann, und dem, was bei der Sicherheit der Systemprogrammierung und den integrierten Werkzeugen möglich ist, enorm ist.

Wenn ich ein paar Jahre in die Zukunft blicke, sehe ich nicht, dass diese Lücke geschlossen wird. Inzwischen stehen Sprachen wie Rust und Swift nicht mehr still. Es gibt in der Welt eine große Dynamik und ein früheres Engagement für C++, so dass die Industrie daran festhält, aber wie lange kann sie die Technologielücke aufrechterhalten, bevor Branchen oder Anwendungsbereiche zu grüneren Weiden wechseln?

C++ und Rust

Trotz einer Vielzahl aufstrebender Alternativen ist C++ immer noch eine Macht, mit der man rechnen muss, vor allem in der von Altlasten geplagten High-Tech-Branche. In einer Reihe von Artikeln stellt der Trainer des High Tech Institute, Kris van Rens, die Sprache in eine moderne Perspektive. In unserem neuen 4-tägigen Trainingskurs führt Kris van Rens die Teilnehmer in die Grundlagen der Sprache und die wichtigsten Best Practices ein.

Alle paar Jahre werden C und C++ für tot erklärt. Kürzlich hat Mark Russinovich, CTO von Microsoft Azure, öffentlich erklärt, dass sie zugunsten von Rust veraltet sein sollten. Das ist zwar eine persönliche Äußerung, aber für jemanden von Microsoft, der über eine enorme C++-Codebasis und viele aktive Mitglieder im C++-Komitee verfügt, ist das eine interessante Meinung.

Unabhängig davon sind C und C++ immer noch sehr lebendig – beide sind die Lingua Franca vieler industrieller Softwareentwicklungsumgebungen. Und doch ist Rust derzeit der „Place to be“ im Land der Systemprogrammierung. Was ist es, das diese Sprache so attraktiv macht? Betrachten wir sie einmal aus der Perspektive von C++.

Bemerkenswerte Unterschiede

Zunächst einmal bietet Rust einen klaren und objektiven Vorteil gegenüber C++: garantierte Speichersicherheit für das kompilierte Ergebnis. Im Wesentlichen tauscht Rust die Kompilierungszeit (und die Komplexität des Compilers) gegen eine sicherere Laufzeit ein. Der Compiler wird versuchen, sich selbst davon zu überzeugen, dass der Code, den Sie ihm übergeben, speichersicherfähig ist. Dazu verwendet er sein Typsystem und manchmal auch die Hilfe des Entwicklers, um Dinge wie die Abhängigkeit von Variablen oder die Lebensdauer von Referenzen anzuzeigen.

Mehrere unabhängige Sicherheitsstudien zu großen C- und C++-Codebasen haben gezeigt, dass übereinstimmend satte 70 Prozent aller Bugs und Sicherheitsprobleme mit der Speichersicherheit zusammenhängen. In Anbetracht dessen scheint der Tausch von Kompilierzeit gegen eine speichersichere Laufzeit eine logische Schlussfolgerung zu sein. Wenn Sie qualitativ hochwertiges C++ mit den richtigen Tools, Tests, Best Practices und Compiler-Sanitizern schreiben, können Sie dieses Ziel auch erreichen, aber es gibt keine festen Garantien von Anfang an. Die ‚Leitplanken‘, die Rust implementiert, um Sie davor zu schützen, sich selbst in den Fuß zu schießen, mögen manchmal komplex oder sogar ärgerlich sein, aber denken Sie an die beträchtlichen Vorteile, die eine Garantie für die Speichersicherheit zur Laufzeit bei der Programmierung von nebenläufiger Software bietet.

''As software engineers, we should use the right tool for the job.''

Ein weiterer bemerkenswerter Unterschied zu C++ ist die Art und Weise, wie Rust die Behandlung von Fehlern und Funktionsergebniswerten integriert. Im Gegensatz zu C++ gibt es keine Ausnahmen. Rust bietet Mechanismen zur Behandlung von Fehlern über den normalen Kontrollfluss. Die Ergebniswerte müssen verarbeitet werden, so dass der Entwickler gezwungen ist, eine Fehlerbehandlung zu implementieren und fehlerhaften Code zu verhindern, so dass Fehler oder Ausnahmen nur selten unter dem Radar verschwinden. Wenn während der Laufzeit wirklich etwas schief läuft – z.B. wenn der Speicher erschöpft ist – erzeugt Rust eine so genannte Panik, einen fatalen Fehler, der den betreffenden Thread anhält (der anständig behandelt werden kann).

Der Rust-Compiler, der auf dem LLVM-Compiler-Backend aufbaut, ist offensichtlich sehr pedantisch, um die Speichersicherheit und die Korrektheit des Codes aufrechtzuerhalten, aber gleichzeitig auch sehr hilfreich. Betrachten Sie ihn als ein Paar Programmierer, das Ihnen über die Schulter schaut und lesbare Fehlermeldungen liefert und sogar mögliche Lösungen vorschlägt. Abgesehen vom Compiler dreht sich der größte Teil des Rust-Tooling-Ökosystems um Cargo, das ein Build-System, einen Paket- und Abhängigkeitsmanager und vieles mehr in einem ist. Trotz der Fülle an Paketmanagern, Build-Systemen und anderen Tools, die für C++ zur Verfügung stehen, kann das Einrichten eines ernsthaften C++-Projekts immer noch eine Qual sein.

Da Rust relativ jung ist, hatte es den Luxus, über 40 Jahre Sprachentwicklung in seine Syntax und Struktur einfließen zu lassen. Ein Großteil der Inspiration wurde sowohl von imperativen Sprachen wie C++ als auch von funktionalen Sprachen wie Haskell und Scheme übernommen. Das verleiht ihr den subjektiven Vorteil eines sehr ‚modernen‘ Gefühls. Außerdem sind viele Dinge in Rust Ausdrücke, die mehr Flexibilität in der Code-Notation bieten.

In meinem vorherigen Beitrag habe ich argumentiert, dass die Benutzerbasis einer Programmiersprache von größter Bedeutung ist. Mit Hilfe der Rust Foundation baut Rust diese Benutzerbasis allmählich auf, wie sich aus vielen Indikatoren wie dem Tiobe-Index und der Stack Overflow-Umfrage sowie der Aufnahme von Rust in den Linux-Kernel v6.1 ableiten lässt – keine geringe Leistung. Da immer mehr Sicherheitsberichte von positiven Effekten sprechen, die eng mit der Verwendung von speichersicheren Sprachen wie Rust zusammenhängen, wird die Benutzerbasis weiter wachsen. Jeder Hinweis (kein Wortspiel beabsichtigt) scheint auf eine glänzende Zukunft für Rust hinzuweisen.

Nicht nur Sonnenschein und Rosen

Sollten wir dann C und C++ zugunsten von Rust einfach verwerfen? Meiner Meinung nach stellt dies eine falsche Dichotomie dar. Warum sollten wir uns zwischen dem einen oder dem anderen entscheiden müssen? Als Software-Ingenieure sollten wir das richtige Werkzeug für die jeweilige Aufgabe verwenden.

Die Umstellung auf Rust ist auch nicht nur ein Zuckerschlecken. Wenn Sie einen großen Bestand an bestehendem C++-Code haben, ist Rust nicht direkt eine Hilfe, es sei denn, Sie sind bereit, für die Interaktion auf C-APIs zurückzugreifen. Es gibt Tools für die Interoperabilität auf C++-Ebene, aber diese stecken noch in den Kinderschuhen. Natürlich könnten Sie Ihren Code auch neu schreiben – aber das wird nicht einfach sein, vor allem nicht, wenn Sie sich stark auf erweiterte Vorlagen stützen. Und wenn Sie sich auf absolute Maximalanforderungen an die Leistung verlassen, ist Safe Rust dem vielleicht (noch?) nicht gewachsen. Außerdem schreiben Standards in strengeren Umgebungen wie der Automobil- oder Luftfahrtindustrie oft die Verwendung einer formal spezifizierten Programmiersprache vor, was Rust derzeit nicht ist.

Der beste Rat ist, sich nicht auf eine einzige Programmiersprache festzulegen. Das Erlernen mehrerer Sprachen ist im Allgemeinen sehr vorteilhaft und wird Ihre Kompetenz, Ihren Stil und Ihre Kenntnisse in jeder Sprache, die Sie beherrschen, verbessern. Werfen Sie also einen Blick auf C++, Rust und andere Alternativen, um Ihren Blickwinkel zu erweitern – oder einfach nur, um Spaß zu haben.

Anspruchsvolles C++

Trotz einer Vielzahl aufstrebender Alternativen ist C++ immer noch eine Macht, mit der man rechnen muss, vor allem in der von Altlasten geplagten High-Tech-Branche. In einer Reihe von Artikeln stellt der Trainer des High Tech Institute, Kris van Rens, die Sprache in eine moderne Perspektive. In unserem neuen 4-tägigen Trainingskurs führt Kris van Rens die Teilnehmer in die Grundlagen der Sprache und die wichtigsten Best Practices ein.

„Es gibt nur zwei Arten von Programmiersprachen: die, über die man sich beschwert, und die, die niemand benutzt. Dies ist ein berühmtes Zitat, das Bjarne Stroustrup, dem Erfinder von C++, zugeschrieben wird. Darin sind ein paar Wahrheiten versteckt.

Erstens und am offensichtlichsten: Keine einzige Programmiersprache ist perfekt, um jedes Problem in jedem Bereich zu lösen. Vor allem, wenn eine Sprache als „Allzwecksprache“ angepriesen wird, wie C++, kann sie fast überall eingesetzt werden, aber wahrscheinlich gibt es eine Diskrepanz zwischen dem verwendeten Werkzeug und dem benötigten Werkzeug. Es ist zum Beispiel durchaus möglich, eine komplette Webanwendung in C++ zu schreiben, aber ist es auch das richtige Werkzeug für diese Aufgabe? Persönlich würde ich das nicht sagen.

Wenn sich eine Sprache weiterentwickelt und altert, ist es sehr wichtig, dass es einen klaren Prozess für den Umgang mit (fehlerhaften?) Änderungen gibt. Ein konservativer und sicherer Ansatz besteht darin, die Abwärtskompatibilität ab der ersten stabilen Version aufrechtzuerhalten. Dies ist der Ansatz, den C++ seit Jahrzehnten verfolgt und an den es sich gehalten hat – was leider auch die Übernahme einiger Sprachverbesserungen verhindert.

Eine weitere versteckte Wahrheit aus dem Eingangszitat: Die Benutzerbasis ist extrem wichtig. Sie könnten die schönste, sicherste und angenehmste Programmiersprache aller Zeiten entwickeln. Aber was nützt Ihnen das, wenn sie nur von wenigen Menschen benutzt wird?

Gute Anwärter

Ein gutes Modell für die Bedeutung von Programmiersprachen ist ein mechanisches Schwungrad. Je größer die Benutzerbasis, desto größer das Schwungrad und die Rotationsgeschwindigkeit. Die Größe der Benutzerbasis wird durch die Anzahl der aktiven Entwickler, die vorhandenen Codebasen, die Abhängigkeiten zwischen den einzelnen Codebasen und andere Faktoren wie die Unterstützung der Integration durch Dritte bestimmt. Zumindest für C++ hat dieses Schwungrad noch eine enorme Dynamik. Dennoch gibt es Kräfte, die diese Dynamik langsam aufzehren. Andere Sprachen im Bereich der Systemprogrammierung gewinnen Teile der C++-Benutzerbasis für sich.

Zuvor habe ich über die Ankündigung der Programmiersprache Carbon geschrieben, einem C++-Nachfolger, der von Google ins Leben gerufen wurde, aber es gibt noch viele weitere Alternativen. Einige von ihnen, wie Zig, Odin und Go, sind eher auf C als auf C++ ausgerichtet – diese werde ich hier nicht behandeln. Um pragmatisch zu sein, werde ich Sprachen, die zu klein oder experimentell sind, wie Nim, Val, Vale, Cpp2 und Jakt, auslassen. Damit bleibt nur eine Handvoll „ernsthafter“ Alternativen übrig, darunter Rust, Swift, D und Circle.

''A good model for programming language significance is a mechanical flywheel.''

Was macht eine Sprache zu einem guten Anwärter für eine große C++-Benutzerbasis? Wir können damit beginnen, die Eigenschaften zu betrachten, bei denen C++ im Allgemeinen versagt. Verfügt die Alternative beispielsweise über eine durchgängig ‚moderne Syntax‘? Verfügt sie über eine eingebaute garantierte Sicherheit, z.B. für Speicher oder mathematische Operationen? Verfügt sie über ein Tooling/Packaging-Ökosystem? Die Interoperabilität von C++ ist ein weiterer sehr wichtiger Aspekt. Eine Schnittstelle für Fremdfunktionen (FFI) im Stil von C ist zwar schön, aber es ist eine Verschlechterung, wenn wir unsere C++-Schnittstellen an diese Schnittstelle anpassen müssen.

Eine dieser Eigenschaften zu haben, reicht jedoch nicht aus. Eine moderne und saubere Syntax ist sehr schön, aber sie allein reicht nicht aus. Ein großartiges Tooling-Ökosystem ist fantastisch, aber auch hier reicht es allein nicht aus. Wenn Sie eine Chance haben wollen, mit C++ erfolgreich zu sein, brauchen Sie meiner Meinung nach mindestens die folgenden drei Zutaten: eine 10-fache Verbesserung irgendeines Aspekts der Sprache, garantierte Speichersicherheit und gute Interoperabilität mit bestehendem C++-Code.

Ankreuzen der Kästchen

Wenn man sich unsere ernsthaften Alternativen ansieht, fehlt einer Sprache wie D die 10-fache Verbesserung. Deshalb denke ich, dass sie sich nie wirklich durchgesetzt hat, obwohl sie schon 20 Jahre alt ist. Das Ein-Mann-Projekt Circle ist sehr beeindruckend, vor allem wegen seiner Möglichkeiten, mit der Sprache zu experimentieren. Und vor allem ist es, abgesehen von der Entnahme von Feature-Flags, um Sprachverbesserungen zu ermöglichen, vollständig kompatibel mit C++. Leider ist Circle nicht offen geregelt und es fehlt ihm an garantierter Speichersicherheit. Swift verfügt über hervorragende Werkzeuge, ist aber zu sehr auf die Apple-Plattform ausgerichtet und bietet nur eine teilweise bzw. in Arbeit befindliche Interoperabilität mit C++.

Rust erfüllt die meisten Kriterien. Es hat sogar schon eine recht anständige Benutzerbasis. Obwohl es auch an echter, ausgereifter C++-Interoperabilität mangelt, ist es heute der vielversprechendste Anwärter. Mehr zu Rust in meinem nächsten Beitrag.

Der Zustand von C++

Trotz einer Vielzahl aufstrebender Alternativen ist C++ immer noch eine Macht, mit der man rechnen muss, vor allem in der von Altlasten geplagten High-Tech-Branche. In einer Reihe von Artikeln stellt der Trainer des High Tech Institute, Kris van Rens, die Sprache in eine moderne Perspektive. In unserem neuen 4-tägigen Trainingskurs führt Kris van Rens die Teilnehmer in die Grundlagen der Sprache und die wichtigsten Best Practices ein.

Im vergangenen Juli wurde die Programmiersprache Carbon auf der CppNorth C++ Konferenz in Toronto, Kanada, offiziell angekündigt. Carbon wird als „experimenteller Nachfolger von C++“ vorgestellt und wurde als Open-Source-Projekt gestartet, und zwar von Google. Moment mal… Google will einen C++-Nachfolger entwickeln? Bis vor kurzem war das Unternehmen stark an der Entwicklung der Sprache C++ und der Entwicklung des Clang C++ Front-Ends für den LLVM-Compiler beteiligt. Angesichts der Tatsache, dass bei Google Zehntausende von Ingenieuren an Milliarden von Codezeilen arbeiten, erscheint es ziemlich gewagt, den Weg einer völlig neuen Sprache einzuschlagen.

Warum sollte sich ein so großes Unternehmen wie Google an ein solch gewagtes Projekt wagen? Nun, es ist ein Symptom für den Zustand und die Entwicklung von C++. Für diejenigen, die die Entwicklung der Sprache in den letzten Jahren nicht mitverfolgt haben: Es hat einige wichtige Diskussionen gegeben. Natürlich geht es bei den Treffen des C++-Komitees darum, Diskussionen zu führen, aber ein Thema ist immer wieder aufgetaucht, ohne dass eine Einigung erzielt werden konnte: die Frage, ob es sich lohnt, das Sprachdesign auf Kosten der Abwärtskompatibilität zu verbessern oder nicht.

Schlankere Verwaltung

C++ gibt es nun schon seit etwa vierzig Jahren und wird weltweit zur Erstellung leistungsfähiger Software verwendet. Nach einer Periode relativer Ruhe nach der ersten ISO-Standardisierung im Jahr 1998 ist es dem Komitee gelungen, seit 2011 kontinuierlich alle drei Jahre große Verbesserungen einzuführen. Infolgedessen hat sich die Sprache im Vergleich zu dem, womit wir in den Neunzigern und Nullerjahren gearbeitet haben, stark verändert. Allein die Hinzufügung von Funktionen wie Konzepten, Bereichen und Modulen in C++20 hat es in sich.

Gleichzeitig ist jedoch bekannt, dass die Weiterentwicklung der Sprache C++ eine große Herausforderung darstellt. Die Last, jahrzehntelange technische Schulden zu tragen und gleichzeitig die Abwärtskompatibilität aufrechtzuerhalten, ist beträchtlich – zu viel für manche, wie es scheint. Der Versuch, eine wichtige Sprachfunktion hinzuzufügen, kann bis zu zehn Jahre Lobbyarbeit, Diskussionen, Überprüfungen, Tests, weitere Überprüfungen und sorgfältige Formulierung kosten. Natürlich ist die Einführung erheblicher Änderungen in einem Projekt mit so vielen Beteiligten keine Kleinigkeit, aber zehn Jahre sind in der heutigen technischen Welt buchstäblich ein ganzes Leben. Eine weitere Herausforderung besteht darin, dass das ISO-Komitee überwiegend westlich geprägt ist und die großen asiatischen C++-Anwender wie Indien oder China stark unterrepräsentiert sind. Diese Nachteile sehen nicht gut aus, vor allem nicht im Hinblick auf schnell wachsende, moderne, offen regierte (und relativ junge) Sprachen wie Rust oder Swift.

Sigasi Erweiterung für Visual Studio Code

Sigasi kündigt die Veröffentlichung deri VS Code Extension mit umfassender Unterstützung für SystemVerilog, Verilog und VHDL an. Unsere Erweiterung bietet Funktionen und Sprachunterstützung wie Code-Navigation, Projektverwaltung, Linting, Code-Formatierung, Tooltips, Outline, Autovervollständigung, Hover und vieles mehr!

''Still, I think right now is a very important time for C++ to consider its position in the systems programming universe; it can’t ignore the signals any longer.''

Ist die technische Verschuldung der Sprache C++ wirklich so gigantisch, dass es nahezu unmöglich ist, neue, wichtige Funktionen hinzuzufügen? Die Ein-Mann-Armee Sean Baxter vom Circle C++ Compiler hat bewiesen, dass dem nicht so ist. Allein in den letzten Monaten hat er im Alleingang bewiesen, dass es möglich ist, beträchtliche Funktionen wie einen echten Summentyp und Tupel auf Sprachebene hinzuzufügen. Zugegeben, eine Implementierung in einem einzigen Compiler eines C++-Dialekts ohne einen gründlich überprüften Vorschlag ist noch lange kein offizielles C++-Sprachmerkmal, aber es zeigt zumindest, wie viel Spielraum und Möglichkeiten es in der Syntax und der Sprache insgesamt gibt – wenn wir uns wirklich darauf einlassen. Es zeigt auch, dass die Last der technischen Schulden allein nicht der begrenzende Faktor bei der Entwicklung der Sprache ist.

Das Governance-Modell für die C++-Sprache wird sich wahrscheinlich nicht so bald ändern, da es so eng mit dem ISO-Prozess und den Interessengruppen des Komitees verbunden ist. Dennoch denke ich, dass jetzt ein sehr wichtiger Zeitpunkt für die Sprache ist, um ihre Position im Universum der Systemprogrammierung zu überdenken; sie kann die Signale nicht länger ignorieren. Vielleicht hilft eine schlankere Governance-Struktur oder die Möglichkeit, Änderungen vorzunehmen, um die technischen Schulden in einer zukünftigen Version abzubauen – wer weiß. Leider werden solche grundlegenden Änderungen des Prozesses höchstwahrscheinlich ebenfalls Jahre dauern.

Abwarten und Tee trinken

Werden die Nachteile dazu führen, dass C++ in absehbarer Zeit abgeschafft wird? Nein, definitiv nicht. Die schiere Eigendynamik des bestehenden Codes und der Benutzerbasis ist überwältigend. Ein ‚einfacher‘ Wechsel zu einer anderen Sprache ist nicht für jeden eine Option, nicht einmal für Google. Damit das klappt, ist echte Interoperabilität mit C++ (nicht nur C) erforderlich, und da hapert es bei Alternativen wie Rust und Swift noch. Nicht umsonst wirbt Google mit der C++-Interoperabilität als Hauptmerkmal von Carbon, das die schrittweise Übernahme der Sprache aus einer großen bestehenden C++-Codebasis ermöglicht.

Im Moment ist Carbon jedoch nicht viel mehr als eine grobe Spezifikation und eine Ankündigung. Wir müssen abwarten und sehen, ob es die Erwartungen erfüllen kann. In der Zwischenzeit wird sich auch C++ weiterentwickeln, hoffentlich positiv inspiriert durch die Möglichkeiten von Circle und anderen Sprachen in diesem Bereich.

 

Systemarchitektur für Politiker

Systemarchitekt

Da drüben, unter dem Sonnenschirm, Mütze, Sonnenbrille, Bier, das muss unser Premierminister sein.
Wenn ich noch ein Bier arrangiere, kann ich mich dann zu Ihnen setzen?

Bier ist willkommen und wenn Sie nicht über Politik reden, können Sie sich uns anschließen.
Systemarchitekt in der Politik
Illustration Rutte mit Luud Engels

Abgemacht! Ich bin ein politischer Analphabet. Ich gebe hier eine Schulung und kann nur ein wenig über High-Tech-Systemarchitektur sprechen.

Das klingt interessant! Ich habe schon an einigen Handelsmissionen teilgenommen und weiß, dass die Niederlande dort eine führende Rolle spielen.

Das ist wahr! Ich hatte die Gelegenheit, für Unternehmen zu arbeiten, die vorhersagen konnten, welches High-Tech-Produkt sie in drei Jahren auf den Markt bringen mussten, und die geniale Forscher und äußerst fähige Ingenieure einsetzten, um dieses Ziel zu erreichen.

Gerade weil für die Entwicklung, Herstellung und Wartung eines solchen Hightech-Produkts eine beträchtliche Anzahl unterschiedlicher Fachgebiete erforderlich ist, ergibt sich aus dieser Vielzahl von Disziplinen ein Wirrwarr von widersprüchlichen Anforderungen. Aber die erfolgreichen Unternehmen zeichnen sich dadurch aus, dass sie sich trotz dieses Wirrwarrs auf eine Vorgehensweise einigen und so rechtzeitig die richtigen Entscheidungen treffen können.

Das muss in der Tat ungeheuer komplex sein. Aber zum Glück wissen diese klugen Köpfe und geschickten Hände, welche Berechnungen und Modelle sie anwenden müssen. Bei meiner Arbeit wenden wir auch Modelle an, aber sie sind eher Futter für Diskussionen als dass sie zu einem Konsens und richtigen Entscheidungen führen. Bei uns ist es mehr menschliche Arbeit.

Da gibt es vielleicht mehr Gemeinsamkeiten, als Sie denken. Alle Experten in der High-Tech-Branche sind Herren und Meister auf ihrem Gebiet und nutzen die Bühne oft, um genau das zu zeigen: Beta-Überlegenheit.

Auf der einen Seite brauchen Sie dringend das Fachwissen, die Modelle und Berechnungen, damit diese Fachleute in ihren Bereichen innovativ bleiben und immer tiefere Tunnel graben. Und auf der anderen Seite wird jede neue Erkenntnis in einer bestimmten Disziplin als Waffe eingesetzt, um Experten aus anderen Tunneln das Hirn auszuschlagen.

Es entstehen Inseln, manchmal sogar Lager, und die Plage ist, dass sie alle einen gültigen Punkt haben.

Okay, okay, es ist also auch menschliche Arbeit. Aber Sie haben gerade gesagt, dass sie sich einigen. Und wie machen sie das?

Es geht um Systemarchitektur. Sie treffen Arbeitsvereinbarungen – man kann es auch als Ansatz bezeichnen -, in denen sich die verschiedenen Disziplinen gegenseitig darüber aufklären, wo sich der Widerspruch im Wesentlichen manifestiert und für welche Parameter eine ausgewogene Lösung gefunden werden muss. Es geht also nicht darum, zu verhandeln oder zu versuchen, einen Konsens zu erreichen, sondern gemeinsam gewichtete Entscheidungen zu treffen. Sobald sie alle einen Überblick haben und sich über das gesamte System einig sind, ordnen diese klugen Köpfe ihre eigene Tunnelweisheit dem, sagen wir, höheren Wohl unter.

Schön, dass das in der High-Tech-Branche so ist, aber wie anders ist es bei uns. Zweifellos haben Sie schon Debatten gesehen, in denen die Leute zu sehr damit beschäftigt sind, ihre eigene Parteiwahrheit zu verkünden und nicht bereit sind, dem anderen zuzuhören, geschweige denn ihn zu verstehen. Diese Art von Systemarchitektur funktioniert bei uns nicht.

Ich spiele jetzt mal des Teufels Advokat: Diese Debatten haben nicht das gemeinsame Ziel, das in erfolgreichen Unternehmen vorherrscht. In den Debatten fällt das Systemziel durch seine Abwesenheit auf.

Nein, das kann nicht der Grund sein. Wir haben uns zum Beispiel ein sehr klares Ziel für die Stickstoffreduzierung gesetzt: die Hälfte weniger bis 2030. Wie konkret soll das Ziel denn sein?

Hier berühren Sie einen grundlegenden Fehler. Sie sehen, dass Reduktion kein Systemziel ist. Genau hier unterscheiden sich konstruktive Unternehmen von der Politik. Lassen Sie mich das erklären.

Das Systemziel umfasst Begriffe wie Lebensmittelmenge, Lebensmittelqualität, nachhaltiger Betrieb und Erhaltung der Umwelt. Allerdings wurde noch nie ein System mit dem Ziel der Stickstoffreduzierung entwickelt, und genau deshalb protestieren viele, sobald Sie dies als Ziel festlegen. Verstehen Sie mich nicht falsch, ich bin kein Klimaverweigerer. Ich betrachte die übermäßige Stickstoffablagerung als negativen Effekt, der behoben werden muss.

Ich bin mir ziemlich sicher, dass die Landwirte, Bürger und Unternehmen in den Niederlanden das Systemziel einer nachhaltigen Nahrungsmittelproduktion unterstützen. Hätten Sie sie aufgefordert, weiter auf dieses Systemziel zuzusteuern, während der Stickstoffüberschuss repariert werden muss, hätten Sie kooperative Denker statt Gegendenker bekommen. Das Systemziel beinhaltet immer einen erwünschten Effekt, und die meisten Menschen wollen sich daher daran beteiligen.

Ich verstehe, was Sie meinen. Die Niederlande können also von Systemarchitekten regiert werden?

Govern nicht, aber selbst Politiker würden von Praktiken und Methoden wie denen der Systemarchitektur profitieren:

''Proclaiming system goals results in solution supporters.''

''Proclaiming solutions results in aimless opponents.''

 

Wir haben es also vermasselt?

Bei diesem Ansatz sicherlich ja! Allerdings ist auch in der High-Tech-Branche einiges schief gelaufen, und es wird auch weiterhin Fehler geben, aber jeder Fehler ist eine Chance zur Verbesserung. Was meinen Sie, wie die Systemarchitektur sonst noch entstanden ist?

Übrigens, Sie würden nicht über Politik sprechen!

Das habe ich nicht, wir haben nur über die Entscheidungsfindung gesprochen.

Trend 4: Das W-Modell

Trainer für Systemanforderungstechnik
Der Trainer des High Tech Institute, Cees Michielsen, beleuchtet eine Handvoll Trends im Bereich System Requirements Engineering. Für das High Tech Institute bietet er mehrmals im Jahr die 2-tägige Schulung‚System Requirements Engineering‚ an.

 

In der High-Tech-Branche wird oft auf das V-Modell verwiesen, wenn es um den Prozess von der ersten Idee bis zur Produktimplementierung geht, wenn es um die Entwicklung von Systemanforderungen geht. Dieses Modell beginnt mit einer funktionalen Gliederung, dem linken Schenkel des V. In der Praxis können Sie jedoch nicht alle Anforderungen in die traditionelle funktionale Gliederung aufnehmen. Typische Beispiele sind die physikalischen Eigenschaften von Produkten – Masse, Volumen, diese Art von Informationen.

Es wäre klug, das V-Modell zu dem zu erweitern, was ich das W-Modell nenne. Dieses Modell beginnt mit zwei parallelen Trajektorien im linken Bein: dem funktionalen und dem physischen Fluss. Beide berücksichtigen separate Systemaspekte: Der funktionale Fluss sorgt in erster Linie dafür, dass die erforderliche Funktionalität implementiert wird, während der physische Fluss dafür sorgt, dass die physischen Aspekte bis hinunter zu den relevanten Systemelementen budgetiert werden.

Die beiden linken Beine treffen sich auf der so genannten ‚Bausteinebene‘, wo die Elemente eines funktionalen Systems, z.B. das Bremssystem eines Autos, entsprechend ihren Anforderungen spezifiziert und entworfen werden. Diese Elemente haben sowohl funktionale als auch physische Eigenschaften. Im Beispiel des Bremssystems ist einer der Bausteine das Bremspedal, das durch funktionale Anforderungen spezifiziert wird, die deutlich machen, was das Pedal tun soll, und durch physische Anforderungen, die die Einschränkungen in Bezug auf die Masse des Pedals, den zulässigen Gestaltungsspielraum, das Material und mehr festlegen.

Bausteine werden auf der Ebene definiert, auf der eine bestimmte Funktionalität spezifiziert, entworfen und implementiert wird. Das bedeutet nicht, dass es sich immer um einzelne Teile handelt. Sie können recht komplex sein, wie der Motor eines Elektroautos. Wichtig ist jedoch, dass sie immer zwei ‚Eltern‘ haben: ein funktionales Elternteil (um sicherzustellen, dass sich das Bremssystem auf die Funktionalität des Bremspedals verlassen kann) und ein physisches Elternteil (um sicherzustellen, dass das Pedal an die vorgesehene Stelle passt und die Volumenbeschränkungen in der Fahrerkabine sowie andere Schnittstellen erfüllt).

Die Verwendung von Bausteinen verhindert, dass die Modelle zu detailliert werden. Gleichzeitig ermöglicht sie ein praktisches Produktmanagement, insbesondere für komplexe Systeme, sowohl im Produktdesign als auch im Fertigungsbereich. Für einen durchschnittlichen Pkw werden etwa 400 Bausteine definiert; die neuesten ASML-Maschinen haben etwa 2.000.

Nach der Freigabe wird das Bausteindesign virtuell in die funktionale und physische Struktur integriert, und zwar bis hin zur Systemebene. Damit soll nachgewiesen werden, dass der Entwurf die Anforderungen auf jeder Ebene erfüllt, sowohl auf der funktionalen als auch auf der physischen. Dies sind die beiden aufsteigenden Beine, die den mittleren Teil des W-Modells bilden.

Dieser Ansatz hat mehrere Vorteile. Er bringt klare Verantwortlichkeiten auf Systemebene sowohl für funktionale als auch für physische Anforderungen während des gesamten Lebenszyklus des Systems. Er ermöglicht eine eindeutige Budgetierung von physischen Aspekten wie Masse und Volumen im nachgelagerten Bereich. Es erleichtert die frühzeitige Erkennung möglicher Integrationsprobleme („es passt nicht, Produkt nicht ausgewogen, zu schwer, Schnittstellen nicht eingehalten“) – während der Designphase, vor der regulären Produktintegration. Es macht die Verantwortlichkeiten für das ‚Funktionieren‘ der Elemente deutlich – das Team, das das Bremssystem entwirft, muss nachweisen, dass es gemäß den Anforderungen funktioniert; es gibt keine Ausreden, zu warten, bis das gesamte Produkt integriert ist.

Es ist gut zu wissen, dass ein durchschnittliches funktionales Teilsystem, wie ein Bremssystem oder ein Füllstandssensor, nicht in einer Fertigungsstückliste auftaucht. Sie bestellen kein Bremssystem, sondern seine Bausteine. Das bedeutet, dass es in der Fertigungs- oder Logistikumgebung schwierig (wenn nicht gar unmöglich) ist, zu sagen, welche Funktion eine Komponente in der Fabrikhalle oder sogar im Endprodukt erfüllt. Wenn Sie jedoch der Logik des W-Modells folgen würden, wäre es ein Kinderspiel, da die Implementierung des Bausteins auch auf seine funktionale(n) Mutterkomponente(n) zurückgeht.

 

 

Trend 3: Rückverfolgbarkeit

Trainer für Systemanforderungstechnik
Der Trainer des High Tech Institute, Cees Michielsen, beleuchtet eine Handvoll Trends im Bereich System Requirements Engineering. Für das High Tech Institute bietet er mehrmals im Jahr die 2-tägige Schulung‚System Requirements Engineering‚ an.

 

Der Grundgedanke von nachvollziehbaren Anforderungen ist wirklich cool: Sie können eine Anforderung sowohl von oben nach unten von ihrer Erstellung bis zu ihrer Implementierung als auch von unten nach oben von ihrer Implementierung bis zu ihrem Ursprung verfolgen. In den meisten Lehrbüchern finden Sie gut aussehende Diagramme und Tabellen, die zeigen, wie Anforderungen mit anderen Anforderungen und Testfällen verknüpft sind. Leider haben diese Diagramme und Tabellen wenig mit der täglichen Praxis zu tun.
Systemanforderungen folgen den Prinzipien der Systemtechnik. Nehmen wir das Beispiel einer Wasserstraßenschleuse. Auf der Systemebene wird es eine Anforderung geben, die besagt, dass die Schleuse es Booten ermöglichen soll, den Kanal flussaufwärts und flussabwärts zu durchfahren. Wie können wir diese Anforderung erfüllen, wenn wir noch nicht wissen, wie wir das Problem lösen sollen, oder in der Anforderungssprache: wie wir diese Anforderung erfüllen können?
In der Praxis sehen wir eine große Vielfalt an Lösungen, vom großartigen schottischen Falkirk Wheel (einem echten Schiffshebewerk) bis zu den niederländischen Schleusen in Eefde. Zwei völlig unterschiedliche Lösungen für dasselbe Problem. Was ist also mit der Rückverfolgbarkeit unserer Systemanforderung zu tun?
Im Falle von Eefde besteht eine Schleuse aus zwei Toren und einer Kammer. Jede Komponente hat ihre eigenen Fähigkeiten, aber keine der Komponenten kann die Systemanforderung allein erfüllen. Deshalb brauchen wir die Designentscheidungen als Ankerpunkt im Anforderungsfluss (top-down, Anforderung zu Designentscheidung zu Anforderung) und in der Rückverfolgung (bottom-up). Durch das Design verstehen wir, dass der Wasserstand in der Kammer dem Wasserstand am geöffneten Tor entspricht, wenn wir eines der Tore öffnen. Anschließend können die Boote durch das geöffnete Tor in die Kammer fahren. Eine der so genannten abgeleiteten Anforderungen an das Tor-Teilsystem ist daher, dass es geöffnet und geschlossen werden kann.

[Courseinstructor heading=“‚Warum haben wir diese Anforderung und warum hat sie diesen Wert?'“

Die Fragen, die wir beantworten müssen und für die wir die Bottom-up-Spuren benötigen, sind: Warum haben wir diese Anforderung und warum hat sie diesen Wert? Die Antworten können nur durch Rückverfolgungen von den Anforderungen auf der Subsystemebene zu den Designentscheidungen eine Ebene höher gefunden werden, in unserem Fall die Systemebene der Wasserstraßenschleuse.
Systemingenieure müssen sich auch mit Ressourcenbudgets wie Masse, Volumen, Energie, Betriebsraum und Materialkosten befassen. All diese gehen als Einzelanforderungen in die Anforderungsspezifikation auf der Systemebene ein, werden aber nie an die Subsysteme weitergegeben, ohne dass sie im Zusammenhang analysiert werden, ein Design erstellt wird, das alle Vor- und Nachteile berücksichtigt, und schließlich entschieden wird, welche Lösung diese Systemanforderungen am besten erfüllt.
In der Realität gibt es viele Abhängigkeiten zwischen, in diesem Fall, den Anforderungen an die Ressourceneigenschaften. Vor allem in der Automobilindustrie sind Masse und Materialkosten zwei Fahrzeugeigenschaften, die stark miteinander verwoben sind. Auf der Systemebene wird das Gesamtbudget für die Masse festgelegt: Das Fahrzeug soll weniger als 1.500 kg wiegen, und das gilt auch für das Budget für die Materialkosten: Die Gesamtkosten für Materialien sollen 7.000 Euro nicht überschreiten. Dann wird für den Fall, dass schwierige Entscheidungen getroffen werden müssen, eine Priorität festgelegt, z.B. ist weniger Gewicht wichtiger als Materialkosten.
Der Entwurf versucht, dafür eine Lösung zu finden und weist Budgets für Masse und Materialkosten zu, wobei diese Anforderungen ausbalanciert werden und gleichzeitig bestimmte Fähigkeiten der Teilsysteme vorausgesetzt werden, die zu diesen Budgets beitragen. Wenn schließlich eine Entscheidung für eine Lösung getroffen wird, werden Teile des Massen- und Materialkostenbudgets den Subsystemen zugewiesen.
Wenn Sie für eines dieser Subsysteme verantwortlich sind und ein Massenbudget von 100 kg erhalten, wo würden Sie nach Antworten auf die Fragen suchen: Warum habe ich ein Massenbudget und warum sind es 100 kg?

Trend 2: Gute Qualitätsanforderungen

Trainer für Systemanforderungstechnik
Der Trainer des High Tech Institute, Cees Michielsen, beleuchtet eine Handvoll Trends im Bereich System Requirements Engineering. Für das High Tech Institute bietet er mehrmals im Jahr die 2-tägige Schulung‚System Requirements Engineering‚ an.

 

Können wir objektiv sagen, dass eine Anforderung von guter Qualität ist? Was wäre der Maßstab für gut? Gibt es so etwas wie ‚gut genug‘? Die meisten Antworten auf diese Fragen finden sich in der Arbeit von Philip Crosby, William Edwards Deming und Joseph Juran. Diese drei Qualitätsgurus sind nicht mehr unter uns, aber ihre Ideen sind nach wie vor eine große Inspirationsquelle.

Da Anforderungen das Ergebnis eines Requirements-Engineering-Prozesses sind, erscheint es logisch zu prüfen, ob eine Anforderung die Ziele des Prozesses erfüllt. Erstens wurden die Bedürfnisse der Stakeholder ermittelt, und zweitens ist eine korrekte und vollständige Übertragung der Stakeholder-Bedürfnisse bis zur Dekompositionsebene gewährleistet, auf der die Anforderungen in Hardware- oder Softwarekomponenten umgesetzt werden können. Ich werde mich hier auf das zweite Ziel konzentrieren.

Es wird zwischen intrinsischer und extrinsischer Anforderungsqualität unterschieden. Intrinsisch bedeutet, dass die Qualität der Anforderung durch die Art und Weise bestimmt wird, wie sie dokumentiert oder dem Leser präsentiert wird – die Syntax der Anforderung. Diese kann entweder rein textlich sein oder mit Bildern, Tabellen und mehr verschönert werden. Die Prüfung kann theoretisch auch von Personen oder Anwendungen durchgeführt werden, die sich nicht mit dem Thema auskennen. Sie müssen nicht verstehen, worum es in der Anforderung geht, sondern nur sehen, ob sie gegen die Regeln für das Schreiben von Anforderungen verstößt. Deming spricht von „Stolz auf die eigene Leistung“ und „gut formulierten Anforderungen“. Im Laufe der letzten 10-15 Jahre sind die Software-Tools zur Unterstützung dieser Qualitätsprüfungen immer weiter entwickelt worden. In Tools wie QVScribe sind Checklisten wie die Writing Requirements Guideline des International Council on Systems Engineering (Incose) vollständig eingebettet und intrinsische Qualitätsprüfungen sind vollständig automatisiert (einschließlich verschiedener Anforderungsvorlagen wie EARS und IREB).

Beachten Sie, dass die intrinsische Qualität nur ein Drittel der Gesamtqualität der Anforderungen abdeckt. Aber die Prüfungen der intrinsischen Qualität haben einen Wert. Wenn sie durchgeführt werden und Korrekturen vorgenommen werden, bevor die Anforderungen von Fachexperten und relevanten Stakeholdern überprüft werden, können diese Tools Zeit sparen und tatsächlich dazu beitragen, die Qualität der Anforderungen zu verbessern.

Aber Tools helfen Ihnen nicht dabei, herauszufinden, ob Ihre Anforderungen für die vorgesehene Zielgruppe sinnvoll sind. An dieser Stelle kommt die extrinsische Qualität von Anforderungen ins Spiel. Sie gilt in zwei Richtungen: zurück zu den Interessenvertretern, die eine bestimmte Funktion des zu entwickelnden Produkts oder eine Produkteigenschaft oder ein Verhalten gefordert haben (die Ausgangszielgruppe), und vorwärts zu den Empfängern der Anforderung (die Zielgruppe).

Betrachten wir die folgende Anforderung: „Die Reaktionszeit des Systems muss weniger als oder gleich 0,5 ms betragen.“ Diese Anforderung wird höchstwahrscheinlich die automatischen Qualitätsprüfungen mit Bravour bestehen. In der Praxis wird sie oft wie folgt formuliert: „Reaktionsfähigkeit des Systems: ≤ 0,5 ms.“ Würden Sie sagen, dass diese Anforderungen von gleicher Qualität sind? Aus syntaktischer Sicht wird die erste Anforderung eine höhere Punktzahl erhalten, da sie eine Anweisung enthält. Aber erst wenn wir die betreffenden Interessengruppen fragen, wissen wir, ob die beabsichtigte Bedeutung korrekt übersetzt wurde.

[Courseinstructor heading=“‚equirements engineers need to have checked and judged their requirements.'“

Qualität ist Konformität mit den Anforderungen, sagt Crosby. Haben wir als Anforderungsingenieure oder Unternehmensanalysten die Bedürfnisse der Interessengruppen korrekt in eine Systemanforderung umgesetzt? Diese Frage kann nur von den Interessengruppen beantwortet werden, die den ursprünglichen Bedarf geäußert haben. Anforderungsingenieure müssen also ihre Anforderungen prüfen und beurteilen lassen – eine Tätigkeit, die als schwierig empfunden wird.

Angenommen, der Kunde sagt, dass der Ingenieur die Anfrage nicht verstanden hat? Oder dass er das Thema völlig verfehlt hat? Ein solches Feedback ist nicht immer angenehm und das veranlasst einen Anforderungsingenieur, diese Konfrontationen zu vermeiden. Er wählt oft den sicheren Weg, indem er jemanden aus dem Projekt kontaktiert, der den Kunden oder Stakeholder vertritt.

Das ist keine kluge Einstellung. Wir wollen sichergehen, dass wir die Bedürfnisse des Stakeholders verstanden und sie korrekt und vollständig in Anforderungen umgesetzt haben. Deshalb gibt es keinen anderen Weg, als diese schwierigen Fragen direkt zu stellen.

Qualität ist Eignung für den Zweck, sagt Juran. Die Anforderungen müssen ausreichend Informationen und Details enthalten, damit die Designer Lösungen entwickeln können. Von den Anforderungen wird erwartet, dass sie quantifiziert werden, damit Tester ihre erfolgreiche Umsetzung überprüfen und validieren können. Kurz gesagt, sie müssen klar, eindeutig und aussagekräftig sein und genügend Details für diejenigen enthalten, die die Anforderungen als Input für ihre Arbeit erhalten.

Ich habe schon Fälle erlebt, in denen es keine Anforderungsdokumentation zwischen einem OEM und einem seiner Zulieferer gab. Es gab nur eine mündliche Vereinbarung. Obwohl diese Situation in manchen Kulturen als inakzeptabel gilt, wurden die Ziele des Requirements Engineering Prozesses erreicht. Der Lieferant liefert das Bauteil nun schon seit über zwölf Jahren in gleichbleibender Qualität zur Zufriedenheit des Kunden.

Was würden Sie in solchen Situationen tun? Wie sehen Sie die Qualität der Anforderungen in Ihrem Unternehmen? Wie würden Sie mit Anforderungen von Interessengruppen wie „Ich möchte, dass die nächste Version des Autos energieeffizienter ist“ umgehen? Ich würde mich freuen, von Ihnen zu hören, zu lernen und es weiterzugeben.