Antrag für den Vortrag aus dem Konzept entwickelt
- Kurzfassung - Langfassung
This commit is contained in:
parent
fab7b88066
commit
5175f54a82
1 changed files with 48 additions and 53 deletions
|
|
@ -1,12 +1,26 @@
|
|||
Konzept für einen Vortrag
|
||||
=========================
|
||||
Antrag für einen Vortrag auf der FrOSCon 24
|
||||
===========================================
|
||||
:author: Ichthyostega
|
||||
:date: 15.5.2024
|
||||
:date: 23.5.2024
|
||||
|
||||
|
||||
Alt werden mit C++
|
||||
------------------
|
||||
|
||||
Kurzfassung
|
||||
~~~~~~~~~~~
|
||||
|
||||
Für eine langlebige Codebasis ist der Charakter und die weitere Entwicklung der einmal gewählten
|
||||
Programmiersprache bedeutsam. Dies wird verdeutlicht anhand von Beispielen und Erfahrungen im Projekt
|
||||
Lumiera mit der Sprache C++. Diese Sprache bietet Abstraktionsmittel, die sehr hilfreich sein können,
|
||||
in einer großen und komplexen Codebasis die Flexibilität und Änderbarkeit zu erhalten. Allerdings tritt
|
||||
die schrittweise Evolution dieser Sprachmittel in Wechselwirkung mit der Entwicklung der Codebasis und
|
||||
erzeugt Wartungsprobleme. Dies wird beleuchtet am Beispiel von Lambdas und Funktoren, der Einführung
|
||||
von RValue-Referenzen, sowie der Entwicklung von Generics und Concepts.
|
||||
|
||||
|
||||
Langfassung
|
||||
~~~~~~~~~~~
|
||||
|
||||
Software lebt solange sie änderbar ist.
|
||||
Für langlebige Software ist der Charakter der Programmiersprache bedeutsam. Der Charakter jeder Sprache,
|
||||
|
|
@ -16,11 +30,9 @@ bestehenden Codebasis, die sich ebenfalls weiterentwickelt.
|
|||
Exemplarisch sei dies am Beispiel der Erfahrungen im Projekt Lumiera mit der Sprache C++ nachgezeichnet.
|
||||
In diesem OpenSource-Projekt wird Software für professionellen Film/Videoschnitt entwickelt.
|
||||
|
||||
Entscheidung für eine Plattform ist im Kern eine Entscheidung für ein Ökosystem.
|
||||
Ein langlebiges Projekt muß auf Autonomie und Handlungsfähigkeit achten.
|
||||
Daher scheiden die meisten zunächst offensichtlichen und beliebten Plattformen aus.
|
||||
|
||||
Für Lumiera hat man sich damals für C++ in einem Unix-Umfeld entschieden.
|
||||
Entscheidung für eine Plattform ist im Kern eine Entscheidung für ein Ökosystem. Ein langlebiges Projekt
|
||||
muß auf Autonomie und Handlungsfähigkeit achten. Daher scheiden die meisten zunächst offensichtlichen und
|
||||
beliebten Plattformen aus. Für Lumiera hat man sich damals für C++ in einem Unix-Umfeld entschieden.
|
||||
Realistische andere Optionen wären noch gewesen: D, Java, plain-C, Haskell.
|
||||
Einmal getroffen, ist eine solche Entscheidung mehr oder weniger endgültig.
|
||||
Denn jede der großen Programmiersprachen steht auch für eine bestimmte
|
||||
|
|
@ -33,42 +45,25 @@ zu verstehen und zu beherrschen. Das wird ermöglicht durch den sachgemäßen An
|
|||
von Abstraktionen.
|
||||
|
||||
Durch einen Interface-Kontrakt wird die Implementierung zum Detail, und damit lokal
|
||||
änderbar. Sprachmittel: Vererbung. Tendentiell problematisch, aber gut verstanden
|
||||
und weitgehend stabil. Tendenz: zunehmende Betonung von Modularität in Kontrakten,
|
||||
realisiert als Mix-in
|
||||
|
||||
Schwachstelle von Kontrakten: man muß das Verhalten festlegen. Damit dringt man in
|
||||
die Implementierung ein und braucht entsprechende Ausdrucksmittel. Der vorherrschende
|
||||
Ansatz hierfür war in den letzten 20 Jahren die Trennung von Infrastruktur und Funktionalität.
|
||||
Ein Stück Funktionalität wird zu einem abstrakten Element, das in einen Kontrakt eingebunden
|
||||
werden kann.
|
||||
|
||||
Die Sprachmittel in C++ waren dafür wenig geeignet und problematisch: im Grunde haben wir
|
||||
bis heute nur Funktions-Pointer. Jedoch hat C++ durch seine Klassen und das Typsystem eine
|
||||
ausgeprägte Stärke im Bauen neuer Abstraktionen. Die Boost-Libraries haben daraus ein neues
|
||||
Sprachmittel geschaffen: Funktions-Objekte.
|
||||
|
||||
In der Praxis war der Weg dorthin mühsam und erforderte viele work-arounds. Das führt dazu,
|
||||
daß im bestehenden Code eine Menge von Hilfsmitteln entsteht, die aufeinander aufbauen und
|
||||
weithin im Einsatz sind. Und dann kam C++11 mit einem neuen Sprachmittel: den Lambda-Ausdrücken.
|
||||
Diese stehen gleichberechtigt neben den Funktionsobjekten.
|
||||
Unterschiede Funktions-Objekt vs Lambda.
|
||||
|
||||
Die Entkopplung von Infrastruktur und Funktionalität führt dazu, daß zunehmend auch die
|
||||
Operationen von den Daten entkoppelt werden müssen. Ein Funktions-Objekt, das gut per Kontrakt
|
||||
in eine Infrastruktur eingebunden ist, könnte viele weitere Anwendungen abdecken, wenn man es
|
||||
von den konkreten Argument-Daten abstrahieren könnte. So entsteht die Forderung nach Funktionen
|
||||
änderbar. Für einen Kontrakt muß aber auch das Verhalten festgelegt werden. Damit dringt
|
||||
die Abstraktion in die Implementierung ein, und erfordert entsprechende Ausdrucksmittel.
|
||||
Der vorherrschende Lösungsansatz hierfür war in den letzten 20 Jahren die Trennung von Infrastruktur
|
||||
und Funktionalität. Ein Stück Funktionalität wird zu einem abstrakten Element, das in einen
|
||||
anderweitig geregelten Kontrakt eingebunden werden kann. Einmal etabliert, könnte ein solches
|
||||
Schema oft an weiteren Stellen angewendet werden, sofern man auch noch von den konkreten
|
||||
Funktionsargumenten abstrahieren könnte. So entsteht die Forderung nach Funktionen
|
||||
auf generischen Argumenten.
|
||||
|
||||
Auch hierfür waren die vorhandenen Sprachmittel unzulänglich, und ziemlich clevere Tricks kamen
|
||||
flächendeckend zum Einsatz: vor allem die partielle Spezialisierung von Templates.
|
||||
Draus entsteht in einer größeren Code-Basis eine interne Binding-Schicht, die erhebliche
|
||||
Probleme bei der Wartung aufwirft.
|
||||
|
||||
Währenddessen entwickelte sich die Sprache weiter. Mithilfe der RValue-References wurde das
|
||||
transparente Durchreichen von Argumenten möglich. Die hierfür notwendigen semantischen Anpassungen
|
||||
sind subtil und tückisch. Eine schrittweise Umstellung einer großen Codebasis ist ein langlaufender
|
||||
Vorgang und eine organisatorische Herausforderung.
|
||||
In der Praxis war der Weg dorthin mühsam und erforderte viele Workarounds. Die Sprachmittel in C++
|
||||
waren dafür anfangs wenig geeignet und problematisch: im Grunde gab es nur die schon in C nutzbaren
|
||||
Funktions-Pointer. Jedoch hat C++ durch seine Klassen und das Typsystem eine ausgeprägte Stärke
|
||||
im Bauen neuer Abstraktionen. Die Boost-Libraries haben daraus ein neues Sprachmittel geschaffen:
|
||||
Funktions-Objekte. Mit C++11 wurden diese auch Teil der Sprachdefinition; zugleich jedoch wurden
|
||||
auch Lambda-Ausdrücke als neues Sprachmittel eingeführt. Beide Sprachmittel stehen nun gleichberechtigt
|
||||
nebeneinander und ermöglichen völlig neue Anwendungsmuster. Und die Sprache entwickelte sich weiter.
|
||||
Mithilfe der RValue-References wurde das transparente Durchreichen von Argumenten möglich. Die hierfür
|
||||
notwendigen semantischen Anpassungen sind subtil und tückisch. Eine schrittweise Umstellung einer großen
|
||||
Codebasis ist ein langlaufender Vorgang und eine organisatorische Herausforderung.
|
||||
|
||||
Oft muß man aber Argumente nicht nur durchreichen, sondern eine generische Funktion muß
|
||||
Eigenschaften ihrer Argumente verstehen und sich daran anpassen können. In den meisten älteren
|
||||
|
|
@ -89,29 +84,29 @@ Trotzdem war diese Entwicklung in der Praxis derart erfolgreich, daß das C++ -
|
|||
gefolgt ist, und die Aufgabe übernommen hat, die historisch gewachsene schwarze Magie in
|
||||
klar definierte und sauber verwendbare Sprachmittel inkrementell weiter zu entwickeln.
|
||||
|
||||
- Varidadics
|
||||
- Varidadische Ausdrücke
|
||||
- Concepts
|
||||
|
||||
Wenn man diese Aufgabe ernst nimmt, darf man sich nicht damit begnügen, einen pragmatischen Gebrauch
|
||||
Wenn man diese Aufgabe ernst nimmt, kann man sich nicht damit begnügen, einen pragmatischen Gebrauch
|
||||
zu codifizieren und syntaktisch nett zu verpacken. Vielmehr sind neue Sprachmittel gefordert, die
|
||||
sich zwar in den Stil der Sprache nahtlos einfügen, und auch das gleiche leisten wie die historisch
|
||||
gewachsene Lösung, aber dennoch auf einer neuen Basis stehen, klar definiert und leichter korrekt
|
||||
verwendbar sind. Das ist eine sehr anspruchsvolle Aufgabe; das Ergebnis ist erstaunlich, hat aber
|
||||
auch sehr lange gedauert und ist in einigen Teilaspekten immer noch unfertig.
|
||||
auch sehr viel Zeit in Anspruch genommen und ist in manchen Teilaspekten immer noch unfertig.
|
||||
|
||||
Das bedeutet: man muß lange Zeit mit einer Mischung aus magischen Lösungen und der neuen
|
||||
Standard-Lösung leben. Beide koexistieren, sind aber untereinander nicht kompatibel, obgleich
|
||||
sie beide den gleichen Zweck erfüllen. Das erzeugt eine schwierige Situation in einer großen
|
||||
Codebasis: zusammenhängende Systeme ziehen sich über weite Strecken durch den Code, und
|
||||
stützen sich jeweils auf eine Menge von Hilfsmitteln ab, die untereinander nicht austauschbar
|
||||
sind.
|
||||
Diese schrittweise Weiterentwicklung der Sprache führt dazu, daß im bestehenden Code eine Menge von Hilfsmitteln
|
||||
entsteht, die aufeinander aufbauen und weithin im Einsatz sind. Jedoch sind die Lösungen aus verschiedenen
|
||||
Entwicklungsstadien untereinander oft nicht kompatibel, da sich die gesamte Herangehensweise geändert hat.
|
||||
In einer größeren Code-Basis entstehen so komplexe interne Binding-Schichten, die erhebliche Probleme
|
||||
bei der Wartung aufwerfen können: zusammenhängende Systeme ziehen sich über weite Strecken durch den Code,
|
||||
und stützen sich jeweils auf Hilfsmittel ab, die untereinander nicht austauschbar sind.
|
||||
|
||||
Beispiele
|
||||
Beispiele hierfür sind:
|
||||
- Loki-Typlisten vs. Variadic Arguments
|
||||
- Type-Traits vs. Concepts
|
||||
|
||||
Da die jeweiligen Alternativen den gleichen Zweck auf unterschiedlichem Weg erreichen, kann eine
|
||||
Umstellung herausfordernd sein und läuft auf eine Überarbeitung etablierter Infrastrukturen
|
||||
Umstellung herausfordernd sein und läuft auf eine großflächige Überarbeitung etablierter Infrastrukturen
|
||||
hinaus. Daraus erwächst aber auch die Chance, in der Codebasis weithin etablierte Lösungen
|
||||
zu hinterfragen und weiterzuentwickeln.
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue