(Bild: Erstellt mit KI (Midjourney) durch iX-Redaktion)
Wer in Visual Basic programmiert, wird gerne belächelt, immerhin sei Basic eine "schlechte" Programmiersprache. Warum ist das eigentlich so und was ist da dran?
Vor ein paar Tagen habe ich einen Entwickler kennengelernt, und natürlich (wie das unter Entwicklern eben so ist) kam relativ schnell die Frage auf, mit welcher Programmiersprache man denn jeweils unterwegs sei. Ich habe dann ein bisschen erzählt, was wir bei the native web [1] so machen, womit wir uns beschäftigen und womit wir arbeiten.
Und natürlich habe ich ihn dann gefragt, wie das denn bei ihm sei. Da kam dann ein leicht verschämtes:
"Naja, ich arbeite nur mit Visual Basic."
Diese Antwort war ihm sichtlich unangenehm, und ich habe ihn dann gefragt, warum das so sei. Er erzählte mir, dass er schon oft die Erfahrung gemacht hätte, dass andere Entwicklerinnen und Entwickler ihn nach dieser Antwort nicht mehr so ganz ernst nehmen, sondern ihn eher belächeln würden. So nach dem Motto:
"Ach guck mal, wie niedlich, da arbeitet jemand tatsächlich noch mit Visual Basic!"
Zugegeben: Visual Basic hat keinen besonders guten Ruf. Eher im Gegenteil: Die Sprache gilt als veraltet, als minderwertig, kurzum als "schlecht". Doch da stellt sich natürlich die Frage: Was ist da dran? Ist Visual Basic wirklich so eine katastrophal schlechte Sprache? Um das beantworten zu können, muss man die Frage etwas allgemeiner stellen, nämlich: Was zeichnet eine gute oder eine schlechte Programmiersprache überhaupt aus?
Bevor wir loslegen, möchte ich noch ein paar Hinweise geben. Zuallererst: Auf diese Frage gibt es nicht die eine wissenschaftlich fundierte und absolut objektive Antwort. Schon die Definition von "gut" und "schlecht" ist eine Frage der Interpretation. Ich werde mir daher zwar große Mühe geben, das Ganze objektiv anzugehen, nicht emotional zu argumentieren und meine Behauptungen an Fakten festzumachen. Dennoch ist das, was hier steht, meine persönliche Sicht der Dinge. Bevor Du also in den Kommentaren mit Kritik um Dich wirfst, wäre es nett, wenn Du das berücksichtigen könntest.
Zweitens: Es geht mir in diesem Blogpost nicht speziell um Visual Basic. Vielmehr versuche ich, zu erklären, woran ich festmache, ob ich eine Sprache als gut oder schlecht empfinde. Dabei liefere ich die Kriterien, die ich für wichtig halte, und erkläre, aus welchen Gründen ich sie für wichtig erachte. Es ist völlig in Ordnung, wenn Du sagst, dass diese Kriterien für Dich nicht greifen oder Du sie anders bewertest. Denn immer da, wo es um Qualität geht, spielt auch das eigene Wertesystem eine Rolle. Und das sieht bei Dir sicher anders aus als bei mir, allein schon deshalb, weil wir unterschiedliche Erfahrungen gemacht haben.
Drittens: Generell möchte ich darum bitten, in den Kommentaren nett zueinander zu sein und konstruktiv miteinander umzugehen. Auch wenn Dir die Sprache, die jemand anderes bevorzugt, nicht gefällt, macht das die entsprechende Person nicht zu einem schlechten Menschen. Es ist völlig in Ordnung, Technologien kritisch zu hinterfragen. Anderen Menschen sollten wir trotz Kritik respektvoll begegnen.
Damit kommen wir nun endlich zum eigentlichen Thema: Was macht eine Programmiersprache gut oder schlecht?
Eine häufig genannte Antwort lautet: Eine Sprache ist dann gut, wenn man mit ihr das jeweils gesteckte Ziel erreichen kann. Nach dem Motto: Wenn eine Sprache den Zweck erfüllt, dann kann sie nicht schlecht sein. Für mich persönlich ist das allerdings kein besonders überzeugendes Argument. Denn bloß, weil ein Werkzeug eine Aufgabe erfüllt, ist es noch lange kein gutes Werkzeug – es ist dann zunächst einmal nur ein für diese Aufgabe passendes oder geeignetes Werkzeug.
Ob es auch gut ist, steht auf einem anderen Blatt. Das merkt man spätestens dann, wenn es mehrere Werkzeuge für dieselbe Aufgabe gibt. Denn dann gibt es oft Unterschiede. Insofern gilt für mich, dass "gut" und "geeignet" zwei verschiedene Paar Schuhe sind. Umgekehrt ist eine Sprache nicht per se schlecht, nur weil sie für ein Problem ungeeignet ist. Sie ist dann einfach nur für dieses Problem ungeeignet. "Gut" oder "schlecht" sind für mich Begriffe, die sich auf eine qualitative Bewertung der Sprache an sich beziehen, unabhängig von ihrer Tauglichkeit für ein bestimmtes Problem.
Ein ähnlicher Punkt ist das Feature-Set einer konkreten Implementierung einer Sprache. Es hieß früher zum Beispiel oft, dass C# eine schlechte Sprache sei, weil sie nur unter Windows lauffähig war. Das ist falsch. Die Sprache an sich ist zunächst nur eine Syntax mit einer Semantik, wie man sich ausdrücken kann. Ob es dafür eine passende Laufzeitumgebung oder einen passenden Compiler für eine konkrete Plattform gibt, ist unabhängig von der Idee der Sprache. Heute ist es ja problemlos möglich, C# auch auf macOS oder Linux auszuführen. Insofern sind auch das keine Kriterien dafür, ob eine Sprache gut oder schlecht gestaltet wurde. Es sagt nur etwas über die Verfügbarkeit von Implementierungen aus.
Ein weiterer Punkt: Eine Sprache ist nicht dasselbe wie ihre Funktions- oder Klassenbibliothek. Auch das ist ein Implementierungsdetail. Es kann für ein und dieselbe Sprache unterschiedliche Umgebungen geben, die unterschiedlich viel an "Drumherum" zur Verfügung stellen. Das kennt man zum Beispiel aus .NET oder Java mit unterschiedlich umfangreichen Runtimes. Es geht mir also wirklich nur um das, was direkt zur Sprache an sich gehört.
Allein darüber könnte man nun lange diskutieren, ob diese Abgrenzung sinnvoll ist oder nicht. Für heute möchte ich sie so machen, weil es in meinen Augen die sinnvollste Definition ist, wenn man über das Design einer Sprache sprechen will.
Damit ist umrissen, was ich überhaupt bewerten will. Jetzt ist die Frage, was geeignete Kriterien sind. Das wichtigste Kriterium für mich ist die Ausdrucksstärke einer Sprache. Eine Programmiersprache ist ein Werkzeug, um das umzusetzen, was eine Entwicklerin oder ein Entwickler im Sinn hat. Das sollte möglichst zielgerichtet und ohne unnötige Umstände möglich sein. Das macht das Schreiben und Lesen von Code einfacher. Je weniger eine Sprache mich zwingt, Konzepte umzuformulieren, desto einfacher und direkter lassen sich Ideen ausdrücken. Sprachen, die für jedes gedankliche Konzept ein entsprechendes Konzept in der Sprache bieten, empfinde ich als gelungen.
Ein Beispiel: In der Mathematik ist 1 die Fakultät von 1, und die Fakultät von n ist n * fac(n - 1). Hier handelt es sich also um eine rekursive Definition. Eine Sprache ist dann ausdrucksstark, wenn sie Rekursion unterstützt, weil ich die Fakultät dann genau so ausdrücken kann, wie sie in meinem Kopf definiert ist. Das klingt trivial, aber Rekursion gab es tatsächlich nicht schon immer in Programmiersprachen. Sie musste erst einmal eingeführt werden, und das war mit Lisp im Jahr 1958 [3]. Das im Jahr zuvor entstandene Fortran kannte keine Rekursion. Und genau das meine ich mit Konzepten: Eine gute Sprache holt mich auf der konzeptionellen Ebene dort ab, wo ich stehe, und bürdet mir keine unnötige Denkarbeit auf.
Die Ausdrucksstärke ist aber nicht das einzige Kriterium. Das zweite wichtige Kriterium aus meiner Sicht ist Minimalismus: Für jedes Konzept sollte es nur genau einen einzigen Weg geben, um ans Ziel zu kommen. Ich will mich nicht zwischen mehreren gleichwertigen Wegen entscheiden müssen. Zu viele Alternativen führen nämlich zu Inkonsistenzen im Code und erhöhen die Komplexität. Ein Beispiel: JavaScript kennt zig Wege, eine Iteration auszudrücken – unter anderem sieben verschiedene Schleifentypen:
for als klassische Zählschleifefor ... in um über Objekte zu iterierenfor ... of eine Art for … eachfor await ... of als asynchrone Variante davonwhile als abweisende Schleifedo ... while als nicht abweisende SchleifeforEach als Schleifen-Funktion an ArraysIch bin mir sicher, dass ich die eine oder andere Variante vergessen habe, aber dass es überhaupt sieben verschiedene Schleifentypen in JavaScript gibt, die im Prinzip alle das Gleiche machen und sich lediglich in Details unterscheiden, das ist schon erschreckend. Vergleicht man das mit Go, dann kommt Go mit einer einzigen Schleife aus – nämlich der for-Schleife, die gegebenenfalls noch um das range-Schlüsselwort ergänzt wird. Das war's, und das führt zu viel weniger Diskussionen und Verwirrung.
Das dritte Kriterium ist Konsistenz: Konzeptionell gleiche Dinge sollten syntaktisch gleich formuliert werden. Das senkt die kognitive Belastung und fördert die Lesbarkeit. In Go (nachdem ich die Sprache gerade positiv erwähnt habe, nenne ich nun auch ein Manko) stolpere ich regelmäßig darüber, dass Parameter einer Funktion per Komma separiert werden, Felder eines Struct jedoch nicht. Das ist unlogisch, weil man in beiden Fällen eine Auflistung von Namen und Typen vornimmt, und warum dieses – aus konzeptioneller Sicht – gleiche Muster mit unterschiedlichen Syntaxvarianten ausgeführt wird, erschließt sich mir nicht.
Viertens ist mir eine gewisse Explizitheit wichtig. Sprachen sollten dazu führen, dass man sich präzise ausdrücken muss. Ich bin ein großer Fan von expliziten Konvertierungen und kein Freund von impliziten. Explizitheit sorgt für mehr Klarheit und weniger Fehler. Je gefährlicher eine Aktion ist, desto expliziter sollte sie sein. Und hier kann man Go wieder als Positivbeispiel nennen: Der unsichere (weil direkte) Zugriff auf den Speicher erfolgt hier über das unsafe-Paket, das heißt, man muss explizit hinschreiben, dass es sich um unsicheren Code handelt.
Nun gehen da natürlich manchmal die Meinungen auseinander, was gut und was schlecht ist. Und da fragt man sich dann vielleicht, wie sehr Sprachdesigner auf die Community hören sollten. Meine klare Antwort ist: Eigentlich gar nicht. Denn es äußern sich oft nur wenige aus der Community, die dann aber sehr lautstark auftreten. Wirklich gutes Sprachdesign ist unglaublich schwer, und bloß weil es einige laute Schreihälse gibt, heißt das noch lange nicht, dass ihre Forderungen sinnvoll oder durchdacht seien. Tatsächlich denken viele Entwicklerinnen und Entwickler an der Stelle zu kurz und übersehen langfristige Konsequenzen, die eine Sprache aufweichen, verwässern und inkonsistent machen können.
Außerdem gilt: Wenn man zu einem neuen Feature erst einmal "ja" gesagt hat, kann man es nicht wieder entfernen, ohne einen Breaking-Change zu haben. Deshalb sollte man sich sehr genau im Vorfeld überlegen, welche Features wirklich in eine Sprache aufgenommen werden sollten. Mit anderen Worten: Weniger Optionen fördern die Standardisierung von Code und damit seine Lesbarkeit. Letztlich geht es um die richtige Balance zwischen Ausdrucksstärke, Minimalismus, Explizitheit und Konsistenz. Vielleicht auch noch um Fehlervermeidung.
Und eine Sprache, die das alles vereint, würde ich persönlich als gelungen bezeichnen.
Wenn ich auf meine eigene Reise zurückblicke, sehe ich, wie sich die von mir genutzten Sprachen entwickelt haben. Meine erste große Sprache war Basic: Zunächst GW-Basic, später QuickBasic und schließlich Basic PDS, alles unter MS-DOS. Und Basic ist eigentlich das Gegenteil von dem, was ich beschrieben habe. Es ist nicht ausdrucksstark, nicht minimalistisch, nicht explizit. Es war bestenfalls halbwegs konsistent. Fehlervermeidend war es schon gar nicht, man denke nur an das unsägliche ON ERROR GOTO NEXT.
Danach habe ich zehn Jahre lang sehr intensiv mit C# gearbeitet. C# ist in fast allen Belangen besser als Basic: Es ist ausdrucksstärker, expliziter und weniger fehleranfällig. Nur minimalistisch ist es nicht, auch in C# gibt es zu viele Wege, dasselbe zu machen. Aber im Vergleich zu Basic war es trotzdem eine deutliche Verbesserung.
Dann kam JavaScript, mit dem ich wiederum zehn Jahre sehr viel gearbeitet habe. JavaScript kann tatsächlich minimalistisch genutzt werden, das macht es aber nicht zu einer minimalistischen Sprache. Tatsächlich gibt es auch in JavaScript sehr viele Schlüsselwörter und es ist weniger konsistent und gleichzeitig deutlich fehleranfälliger als C#. Unterm Strich sind die beiden Sprachen also durchaus unterschiedlich, aber ich würde sie letztlich als "gleichwertig" bezeichnen, nur eben als "anders".
Seit einigen Jahren arbeite ich nun hauptsächlich mit Go. Go ist eine viel kleinere Sprache als alle zuvor genannten: Es ist minimalistischer, konsistenter, weniger fehleranfällig und trotzdem ausdrucksstark. Ich fühle mich momentan mit Go sehr wohl, aber es wird wohl nicht die letzte Sprache sein, mit der ich mich jemals beschäftigen werde.
Wenn ich diese Reise von Basic über C# und JavaScript zu Go Revue passieren lasse, dann sehe ich, wie die von mir bevorzugten Sprachen immer mehr in die Richtung dessen gehen, was ich als gutes Sprachdesign empfinde. Das sagt allerdings absolut noch nichts über die Standardbibliothek, das Tooling oder ähnliches aus – es geht nur um die Sprache an sich.
Und: Was für mich funktioniert, muss nicht für jeden passen. Ich habe versucht, objektive Kriterien zu nennen, aber die Frage, ob eine Sprache gut oder schlecht ist, hängt immer vom eigenen Wertesystem ab. Selbst wenn Du die gleichen Kriterien anwendest wie ich, musst Du nicht zum gleichen Ergebnis kommen. Unterschiedliche Sprachen haben unterschiedliche Stärken und Schwächen.
Ich nehme aber an, dass niemand sagen würde, alle Sprachen seien gleich gut, denn sonst würden wir alle immer noch dieselbe Sprache nutzen, mit der wir irgendwann einmal angefangen haben. Die Tatsache, dass wir das nicht tun, zeigt, dass wir eine andere Sprache für gelungener hielten (oder dass wir uns in eine Nische weiterentwickelt haben, in der wir um eine bestimmte Sprache nicht herumkommen, unabhängig davon, ob wir sie gut oder schlecht finden).
Was für mich bleibt, sind vor allem zwei Dinge: Erstens kann ich auf Basis meines persönlichen Wertesystems argumentativ erläutern, warum ich bestimmte Sprachen gegenüber anderen bevorzuge, und warum ich zum Beispiel Go für gelungener halte als C#. Zweitens ist mir bewusst, dass diese qualitative Einschätzung von jeder Entwicklerin und jedem Entwickler anders getroffen werden kann, da der eigene Hintergrund jeweils ein anderer ist – und das macht eine objektive Darstellung so schwierig.
Hinzu kommt noch, dass man eine Sprache letztlich nur nach diesen Kriterien auswählt, sondern eben auch nach Tauglichkeit für das vorliegende Problem, nach Tooling, nach Funktions- und Klassenbibliothek, und, und, und.
Und deshalb macht man es sich zu leicht, wenn man jemanden belächelt, weil sie oder er mit Visual Basic programmiert: Ja, auch in meinen Augen ist Visual Basic keine besonders gelungene Sprache. Trotzdem kann es sein, dass sie für den eingangs erwähnten Entwickler genau das Richtige ist, aus einer Vielzahl von Gründen. Und statt darüber zu urteilen, sollten wir vielleicht eher neugierig und überrascht nachfragen: Warum? Denn vielleicht können wir dabei etwas lernen.
URL dieses Artikels:
https://www.heise.de/-10248069
Links in diesem Artikel:
[1] https://www.thenativeweb.io/
[2] https://www.heise.de/Datenschutzerklaerung-der-Heise-Medien-GmbH-Co-KG-4860.html
[3] https://www.youtube.com/watch?v=JxF5cv9LNIc
[4] mailto:rme@ix.de
Copyright © 2025 Heise Medien
(Bild: Erstellt mit KI (Midjourney) durch iX-Redaktion)
Je erfahrener ein Entwickler oder eine Architektin ist, desto besser die Ergebnisse – sollte man meinen. Doch tatsächlich ist häufig das Gegenteil der Fall.
Vielleicht kennen Sie die Situation: Sie öffnen ein Projekt, das jemand anderes entwickelt hat, und schon nach wenigen Minuten denken Sie sich:
"Das ist aber ganz schön kompliziert implementiert!"
Je mehr Code Sie lesen, desto stärker beschleicht Sie das Gefühl, dass vieles unnötig komplex ist. Häufig sind es Abstraktionsebenen, die Dinge verschleiern, die eigentlich pragmatisch und einfach hätten gelöst werden können. Solche Ansätze machen den Code schwer verständlich – und das gilt nicht nur für den Code, sondern auch für die Architektur eines Projekts. Vielleicht haben auch Sie schon einmal das Gefühl gehabt, dass weniger darauf geachtet wurde, guten Code zu schreiben, sondern dass jemand sich an einer übertriebenen Komplexität verkünstelt hat.
Genau darum geht es heute: Architektur sollte im Idealfall unsichtbar sein. Doch was bedeutet das genau? Und wie können Sie dieses Prinzip für sich nutzen?
Fangen wir mit der Frage an, was es bedeutet, dass eine gute Architektur unsichtbar ist. Ein Vergleich mit der Realität hilft, das zu verdeutlichen. Denken Sie an beeindruckende Bauwerke: vielleicht an eine moderne Villa, bei der jedes Detail passt und alle Entscheidungen nahtlos ineinanderfließen. Oder an ein historisches Bauwerk wie den Kölner Dom, das architektonisch ebenfalls fasziniert. Der entscheidende Punkt ist: Sie bewundern in beiden Fällen das Bauwerk als Ganzes. Sie wissen zwar, dass dahinter eine durchdachte Architektur steckt, diese drängt sich Ihnen aber nicht auf. Vielmehr wirkt alles wie ein schlüssiges Gesamtbild, bei dem man spürt, dass alle Details durchdacht sind. Das heißt, gute Architektur tritt in den Hintergrund und fordert nicht ständig Ihre Aufmerksamkeit.
Natürlich ließe sich alternativ auch ein Bauwerk schaffen, bei dem jede architektonische Entscheidung überdeutlich sichtbar wird. Das mag zwar schick aussehen, würde aber den Eindruck einer überambitionierten Studie vermitteln, die mehr Selbstzweck als Grundlage für ein großartiges Bauwerk ist. Und genau das meine ich, wenn ich sage: Gute Architektur ist unsichtbar. Sie schafft Strukturen, ohne sich in den Vordergrund zu drängen.
Dieses Prinzip gilt nicht nur für Bauwerke, sondern auch für Software. Auch hier ist Architektur kein Selbstzweck. Sie sollte ein solides Fundament liefern, auf dem eine gut strukturierte, wartbare und langfristig nutzbare Software entstehen kann. Wenn eine Architektur diese Ziele erfüllt, ohne sich selbst zu wichtig zu nehmen, ist sie gelungen. Wenn sie diese Ziele hingegen verfehlt oder unnötig in den Vordergrund rückt, ist sie schlecht.
Bis hierhin klingt das alles vielleicht recht einleuchtend. Doch wenn es so einfach wäre, würden wir nicht so häufig auf Projekte stoßen, bei denen wir uns denken:
"Was ist das denn? Was hat sich da bloß jemand gedacht?"
Über die Jahre fällt dann ein Muster auf: Menschen, die gerade erst mit der Programmierung beginnen, entwickeln oft einfache und pragmatische Lösungen – allein schon deshalb, weil sie es nicht anders können. Mit wachsendem Wissen neigen Entwicklerinnen und Entwickler jedoch dazu, Probleme immer stärker zu abstrahieren. Das wird uns in der Ausbildung schließlich so beigebracht: Der Versand einer Word-Datei wird abstrahiert zu "Dateiversand", dieser wiederum zur Nachricht eines Senders an einen Empfänger – und am Ende reden wir nur noch abstrakt über "Messaging". Dabei wollte man ursprünglich einfach nur eine Word-Datei per E-Mail versenden.
Das Problem dabei ist oft zu viel und vor allem zu frühe Abstraktion. Jede Abstraktion führt zu einer weiteren Indirektion, die den Code schwerer verständlich macht. Statt den eigentlichen Gedankengang der Entwicklerin oder des Entwicklers im Code nachvollziehen zu können, muss man diesen gedanklich zunächst auf eine andere Ebene übersetzen. Je mehr solche Ebenen es gibt, desto schwieriger wird es, den Code zu verstehen. Dabei wird Code jedoch nur einmal geschrieben, aber viele Male gelesen. Der Fokus sollte daher viel eher auf Lesbarkeit, Nachvollziehbarkeit und Verständlichkeit liegen, nicht auf möglichst vielen Abstraktionen. Das "You Ain’t Gonna Need It"-Prinzip (YAGNI) ist nicht ohne Grund ein Leitmotiv in der Softwareentwicklung: Keep it simple! Dieses Prinzip gilt für Code genauso wie für Architektur.
Ein zentraler Aspekt ist die klare Definition von Verantwortlichkeiten: Welche Funktion, Klasse oder welcher Service ist wofür zuständig? Die Prinzipien der niedrigen Kopplung und der hohen Kohäsion helfen hier: Einzelne Elemente sollten möglichst unabhängig voneinander existieren, während alles, was zu einer Aufgabe gehört, an einem Ort zusammengeführt wird. Wenn Sie also einen Fehler beheben müssen, sollte die Änderung an einer Stelle genügen, ohne andere Teile des Systems zu beeinflussen.
Ein Beispiel aus der Praxis verdeutlicht das: In einem Code-Review stieß ich auf eine unnötige Abstraktion in einer Go-Codebasis. Anstatt einen Pointer zu verwenden, um auszudrücken, dass ein Wert optional ist, hatte die Entwicklerin einen Maybe-Typ eingeführt – ein Konzept aus der funktionalen Programmierung. Dieser Typ war jedoch nur an einer einzigen Stelle im Code verwendet worden, was weder konsistent noch sinnvoll war. Ein einfacher Pointer hätte denselben Zweck erfüllt und wäre deutlich verständlicher und weniger fehleranfällig gewesen.
Das Problem unnötiger Abstraktion tritt nicht nur auf Code-, sondern auch auf Architekturebene auf. So wird manchmal ein Microservice eingeführt, nicht weil er notwendig ist, sondern um das Konzept eines Microservices umzusetzen. Das führt zu unnötiger Komplexität und verfehlt das eigentliche Ziel, die Struktur und Verständlichkeit der Software zu verbessern.
Warum verkünsteln sich erfahrene Entwicklerinnen und Entwickler so oft? Ein Grund ist der Wunsch nach Perfektion, ein anderer das Streben nach Anerkennung. Es ist wichtig, sich diesen Effekt bewusst zu machen und den eigenen Code und die eigene Architektur zu reflektieren. Code-Reviews und Pair-Programming können hier helfen, denn sie fördern pragmatische Ansätze und die Verständlichkeit für andere.
Architektur und Code sind Mittel zum Zweck, kein Selbstzweck. Sie sollten die fachlichen Anforderungen und die Bedürfnisse des Teams in den Mittelpunkt stellen. Lösungen sollten iterativ und pragmatisch entwickelt werden. Fragen Sie sich stets: Braucht das Team diese Abstraktion wirklich, oder verkompliziert sie die Dinge nur unnötig?
URL dieses Artikels:
https://www.heise.de/-10225156
Links in diesem Artikel:
[1] https://www.heise.de/Datenschutzerklaerung-der-Heise-Medien-GmbH-Co-KG-4860.html
[2] mailto:rme@ix.de
Copyright © 2025 Heise Medien
(Bild: Pincasso/Shutterstock)
C# 13.0 bietet neben partiellen Klassen und Methoden jetzt auch die lang erwartete Umsetzung für partielle Properties und Indexer.
Eine wichtige Neuerung in C# 13.0 sind partielle Properties und Indexer. Auf dieses Sprachfeature warten viele Entwicklerinnen und Entwickler bereits seit der Einführung der partiellen Methoden in C# 3.0. Das C#-Schlüsselwort partial gibt es sogar bereits seit C# 2.0 für Klassen.
Mit partiellen Klassen kann man den Programmcode einer einzigen Klasse auf mehrere Codedateien aufspalten – ohne dafür Vererbung zu nutzen. Das ist nicht nur sinnvoll für mehr Übersichtlichkeit bei umfangreichen Klassen, sondern wird vor allem verwendet, wenn ein Teil der Klasse automatisch generiert und der andere Teil der Klasse manuell geschrieben wird. Diese Vorgehensweise kommt in .NET zum Beispiel bei GUI-Bibliotheken wie ASP.NET Webforms und Blazor, beim Reverse Engineering von Datenbanken mit Entity Framework und Entity Framework Core sowie bei Source-Generatoren (z.B. für reguläre Ausdrücke und JSON-Serialisierung) zum Einsatz.
In C# 13.0 können Entwicklerinnen und Entwickler auch Property- und Indexer-Definition sowie deren Implementierung mit partial in zwei Dateien trennen. Dabei müssen beide Teile jeweils die gleiche Kombination von Getter und Setter mit den gleichen Sichtbarkeiten sowie dem gleichen Typ realisieren.
Ein konkretes Beispiel: Wenn in einem Teil der Klasse eine Property sowohl einen öffentlichen Getter als auch einen öffentlichen Setter besitzt, müssen diese auch im anderen Teil vorhanden und öffentlich sein. Aber während in einem Teil ein automatisches Property verwendet wird, kann im anderen Teil eine explizite Implementierung vorhanden sei.
Partielle Properties und partielle Indexer können genau wie partielle Klassen und partielle Methoden NICHT aus mehreren Projekten/Assemblies zusammengeführt werden. Alle Teile müssen in dem gleichen Projekt sein!
Die folgenden Listings zeigen ein Beispiel einer aufgeteilten Klasse mit partieller Methode und partiellem Property sowie einem partieller Indexer.
Der erste Codeausschnitt zeigt den ersten Teil der partiellen Klasse nur mit Definitionen von Property ID, Indexer und Print():
using System.Text.Json.Serialization;
namespace NET9_Console.CS13;
/// <summary>
/// Erster Teil der partiellen Klasse nur mit Definitionen
/// </summary>
public partial class PersonWithAutoID
{
// NEU: Partielles Property --> kein "Convert to Full Property"
public partial int ID { get; set; }
// NEU: Partieller Indexer
public partial string this[int index] { get; }
// "Normales Property"
public string Name { get; set; }
// Partielle Methode (gab es vorher schon)
public partial void Print();
}
Im zweiten Teil der partiellen Klasse werden Getter und Setter für ID und den Indexer sowie die Methode Print() implementiert:
/// <summary>
/// Implementierung der Getter und Setter für ID, der Getter für den Indexer sowie die Methode Print()
/// </summary>
public partial class PersonWithAutoID
{
int counter = 0;
// Implementierung des Partial Property
private int iD;
public partial int ID
{
get
{
if (iD == 0) iD = ++counter;
return iD;
}
set
{
if (ID > 0) throw new ApplicationException("ID ist bereits gesetzt");
iD = value;
}
}
// Implementierung des Partial Indexer
public partial string this[int index]
{
get
{
return index switch
{
0 => ID.ToString(),
1 => Name,
_ => throw new IndexOutOfRangeException()
};
}
}
// Implementierung der Partial Method
public partial void Print()
{
Console.WriteLine($"{this.ID}: {this.Name}");
}
}
Folgender Code implementiert den Nutzer der zusammengesetzten Klasse PersonWithAutoID:
/// <summary>
/// Client-Klasse für die Demo
/// </summary>
public class CS13_PartialPropertyAndIndexerDemoClient
{
public void Run()
{
CUI.Demo(nameof(CS13_PartialPropertyAndIndexerDemoClient));
CS13.PersonWithAutoID p = new() { Name = "Holger Schwichtenberg" };
p.Print(); // 1: Holger Schwichtenberg
CUI.H2("Versuch, die ID neu zu setzen, führt zum Fehler:");
try
{
p.ID = 42;
}
catch (Exception ex)
{
CUI.Error(ex); // System.ApplicationException: ID ist bereits gesetzt
}
CUI.Print($"Nutzung des Indexers: {p[0]}: {p[1]} ");
}
}
URL dieses Artikels:
https://www.heise.de/-10237499
Links in diesem Artikel:
[1] mailto:rme@ix.de
Copyright © 2025 Heise Medien
(Bild: Pincasso/Shutterstock)
Die Programmiersprache C# 13.0 ist zusammen mit Visual Studio 2022 Version 17.12 und .NET 9.0 am 12. November 2024 erschienen.
Das neue C# 13.0 unterstützt Microsoft offiziell erst ab .NET 9.0 ("C# 13.0 is supported only on .NET 9 and newer vesions.").
Man kann allerdings die meisten Sprachfeatures aus C# auch in älteren .NET-Versionen einschließlich .NET Framework, .NET Core und Xamarin nutzen. Dazu muss man die verwendete Compilerversion per Tag <LangVersion> in der Projektdatei (.csproj) auf "13.0" erhöhen.
<LangVersion>13.0</LangVersion>
Damit Sprachfeatures auch in Versionen vor .NET 9.0 funktionieren, dürfen sie keine Abhängigkeit von in .NET 9.0 eingeführten Basisbibliotheksklassen haben. Sofern man <LangVersion>latest</LangVersion> in der Projektdatei setzt, sind in älteren Versionen folgende neuen Sprachfeatures von C# 13.0 möglich:
ref struct, außer der Verwendung als Typargument\eZu beachten ist aber, dass es für den Einsatz der neuen Sprachfeatures in .NET-Versionen vor 9.0 keinen technischen Support von Microsoft gibt, man also bei Problemen nicht den Support-Vertrag nutzen kann, um Microsoft um Hilfe zu ersuchen. Dennoch ist der Einsatz höherer C#-Versionen in älteren .NET-Projekten in einigen Unternehmen gängige und problemlose Praxis.
In C# 13.0 sind folgende neue Sprachfeatures erschienen, die ich in den kommenden Wochen in dieser Blogserie besprechen werde:
\e für ANSI/VT100 Terminal Control Escape Sequences,params,Threading.Lock für lock-Anweisungen undref structs (auf Stack).Ein weiteres Sprachfeature ist in C# 13.0 in experimenteller Form enthalten: halbautomatische Properties mit dem neuen Schlüsselwort field. Dieses Schlüsselwort ist nur verfügbar, wenn man in einer Projektdatei entweder <EnablePreviewFeatures>True</EnablePreviewFeatures> oder <LangVersion>preview</LangVersion> setzt.
Folgende Sprachfeatures waren für C# 13.0 geplant und zum Teil schon als Prototyp verfügbar, wurden aber dann auf C# 14.0 vertagt [1], das im November 2025 erscheinen soll :
(int x, string y) = default statt (default, default)Array, Span<T> und ReadOnlySpan<T>extensioneinführen.Es gibt einige wenige Breaking Changes [2] im Verhalten des Compilers in C# 13.0 gegenüber C# 12.0. Dabei handelt es sich jedoch um Sonderfälle von geringer Bedeutung, beispielsweise das Verbot der Annotation [InlineArray] auf record struct).
URL dieses Artikels:
https://www.heise.de/-10217343
Links in diesem Artikel:
[1] https://github.com/dotnet/roslyn/blob/main/docs/Language%20Feature%20Status.md
[2] https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/breaking-changes/compiler%20breaking%20changes%20-%20dotnet%209
[3] mailto:rme@ix.de
Copyright © 2025 Heise Medien
(Bild: TippaPatt/Shutterstock)
.NET 9.0 ist eine Version mit Standard-Term-Support (STS) für 18 Monate. Für einige Bibliotheken ist der Support aber deutlich kürzer.
Während die vorherige, im November 2023 erschiene Version 8.0 noch 36 Monate Support erhalten hat und daher noch bis zum November 2026 mit Updates versorgt wird, bietet Microsoft Aktualisierungen und technische Hilfe für .NET 9.0 für die Dauer von 18 Monaten, also nur bis Mai 2026 an.
(Bild: Microsoft)
Für einige von Microsoft veröffentlichte .NET-NuGet-Pakete, die nicht Teil des .NET-SDKs sind, gilt eine andere Support-Richtlinie.
Das betrifft folgende Paketfamilien:
Für diese Pakete gilt:
Die Liste der betroffenen NuGet-Pakete findet man auf der Seite zu den Extensions [1].
(Bild: Microsoft [2])
URL dieses Artikels:
https://www.heise.de/-10215755
Links in diesem Artikel:
[1] https://dotnet.microsoft.com/en-us/platform/support/policy/extensions
[2] https://dotnet.microsoft.com/en-us/platform/support/policy/extensions
[3] mailto:rme@ix.de
Copyright © 2024 Heise Medien
In this release, the coding focus has been on moving to PHP 8.1+ and refactoring the integration of the SimplePie library (which was long due). At the same time, plenty of new features have been added. Enjoy! 🎄
Breaking changes 💥:
A few highlights ✨:
search:UserQueryA date:P1dCache-Control: max-age and ExpiresThis release has been made by @aledeg, @Alkarex, @Art4, @ColonelMoutarde, @Frenzie, @math-GH, @ramazansancar
and newcomers @DevGrohl, @UserRoot-Luca, @aarnej, @andrey-utkin, @bhj, @christophehenry, @davralin, @drego85, @ev-gor, @killerog, @kwarraich, @minna-xD, @mtalexan, @oshaposhnyk, @patHyatt
Full changelog:
search:UserQueryA date:P1d #6851Cache-Control: max-age and Expires #6812, FreshRSS/simplepie#26Authorization) #6820&state=96 (no UI button yet)phpgt/cssxpath library with improved CSS selectors #6618
:last-child, :first-of-type, :last-of-type, ^=, |=("a b") or (!c) #6818v mode #7009+ #7033
Referer #6822, FreshRSS/simplepie#27
Referer: https://example.net/ to the custom HTTP headers of the feed #6820windows.open noopener (to avoid flash of white page in dark mode) #7077, #7089aria-hidden bug, and use HTML5 hidden #6910<pre> and <code> #6770<template> instead of duplicated HTML code #6751, #7113<template> #6864? to show shortcut page and help #6981simplepie_after_init #7007Minz_Request::paramArray() #6800booleansInConditions #6793phpstan.dist.neon to allow custom configuration in phpstan.neon #6892ControlSignature #6896
(Bild: Pincasso/Shutterstock.com)
Auch für das aktuelle .NET-Release wird der Dotnet-Doktor-Blog die Neuerungen in einer Artikelserie detailliert beschreiben.
Mit diesem Beitrag beginne ich die neue Blogserie zu .NET 9.0. Wie im letzten Jahr zu .NET 8.0 [1] werde ich in zahlreichen kleineren Beiträgen die Neuerungen in .NET 9.0 vorstellen.
.NET 9.0 steht seit dem 12. November 2024 auf der Downloadseite [2] kostenfrei zur Verfügung. Für .NET 9.0 benötigen Entwicklerinnen und Entwickler die Entwicklungsumgebungen Visual Studio 2022 [3] mindestens in der Version 17.12.
Entwickelt wurde .NET 9.0 in den letzten 12 Monaten. Seitdem hat Microsoft sieben Preview-Versionen und zwei Release-Candidate-Versionen veröffentlicht, über ich für heise developer jeweils berichtete.
Wie schon bei .NET 6.0/C# 10.0 und .NET 7.0/C# 11.0 sowie .NET 8.0/C# 12.0 verwendet Microsoft an einigen Stellen eine Schreibweise ohne ".0" (.NET 9/C# 13) und an anderen mit ".0" (.NET 9.0/C# 13.0). Ich werde einheitlich die Schreibweise mit ".0" verwenden, wie es auf der Downloadseite [4] steht.
(Bild: Microsoft [5])
Meine Serie wird in den kommenden Wochen und Monaten über diese Aspekte von .NET 9.0 berichten:
Meine Beiträge erheben dabei nicht den Anspruch, die Dokumentation zu ersetzen oder zu überbieten. Leserinnen und Leser können meine Beiträge als Impulsgeber verstehen, sich zu entscheiden, ob eine Neuerung für ihre Anwendungsfälle Sinn ergibt und sie sich damit dann näher beschäftigen wollen.
Ich werde die Beiträge der Serie jeweils so weit im Voraus schreiben, dass eine wöchentliche Veröffentlichung gewährleistet ist. Aufgrund von redaktionellen Engpässen kann es dennoch vorkommen, dass einmal eine Woche kein Beitrag erscheint.
URL dieses Artikels:
https://www.heise.de/-10215673
Links in diesem Artikel:
[1] https://www.heise.de/blog/Neu-in-NET-8-0-1-Start-der-neuen-Blogserie-9574680.html
[2] https://dotnet.microsoft.com/en-us/download/dotnet/9.0
[3] https://visualstudio.microsoft.com/
[4] https://dotnet.microsoft.com/en-us/download/dotnet/9.0
[5] https://dotnet.microsoft.com/en-us/download/dotnet/9.0
[6] mailto:rme@ix.de
Copyright © 2024 Heise Medien
(Bild: incrediblephoto / Shutterstock.com)
Künstliche Intelligenz könnte zu einem enormen Produktivitätssprung in der Softwareentwicklung führen. Welche Auswirkungen kann das haben?
Nehmen wir einmal an, dass wir es schaffen, die Produktivität in der Softwareentwicklung um eine Größenordnung – also um den Faktor zehn – zu verbessern. Um es ganz konkret zu machen, ein Gedankenexperiment: Eine Projektleiterin wacht morgens auf und weiß, dass in ihrem Projekt statt 100 Menschen nur 10 Menschen notwendig sind. Sie weiß auch, welche Menschen das sind. Das ist absolut sicher, so wie der Himmel blau ist.
Was wird die Projektleiterin nun tun?
Die erste Option wäre, das Projekt mit zehn Personen fortzusetzen und den restlichen 90 Personen andere Aufgaben zu geben oder sie gar zu entlassen. Diese Option umzusetzen ist schwierig, weil die Projektleiterin sich und anderen damit eingesteht, dass zu viele Menschen an dem Projekt gearbeitet haben. Außerdem ist das Management eines 100-Personen-Projekts prestigeträchtiger als die Leitung eines Projekts mit zehn Personen. Das Vorgehen birgt auch ein Risiko, weil man die Personen nicht so einfach wiederbekommt, wenn man doch eine sinnvolle Aufgabe für sie findet.
Eine andere Option ist, die zehn Personen an dem ursprünglichen Projekt arbeiten zu lassen und den anderen eine andere Aufgabe zu geben. Dazu könnte man den Scope des Projekts vergrößern. Das ist gegebenenfalls relativ einfach möglich, denn der Wunsch nach mehr Features ist eher die Regel. Oder man sucht für die Menschen ein anderes Projekt. Am Ende steht bei beiden Optionen mehr Wert für die Organisation und damit mehr Prestige für alle Beteiligten.
Vielleicht könnte man das Projekt auch durch die zusätzlichen Personen beschleunigen. Das erscheint aber schwierig, da mehr Menschen ein Projekt sogar verlangsamen können, weil Einarbeitung und mehr Kommunikation notwendig sind. Fred Brooks hat genau darauf in seinem Buch "The Mythical Man Month" hingewiesen.
Aber ist ein solches Gedankenexperiment überhaupt realistisch? Auch hier hat Fred Brooks eine Antwort: In seinem Paper "No Silver Bullet" [1] stellt er die Behauptung auf, dass keine einzelne Maßnahme alleine die Produktivität in der Softwareentwicklung um eine Größenordnung verbessern kann. Das lässt aber Raum dafür, dass eine Kombination von Maßnahmen dieses Ziel erreichen kann. Und außerdem ist es – so wie dieser Blog-Post – auch eine Hypothese, die er nicht weiter belegt.
Ein Grund, warum das Szenario vielleicht doch realistisch ist: Wie schon erwähnt, bedeuten mehr Menschen in einem Projekt mehr Prestige und somit gibt es einen Drang dazu, Projekte möglichst mit vielen Menschen durchzuführen. Das Gesetz von Parkinson besagt nun, dass alle verfügbaren Menschen auch an dem Projekt mitarbeiten werden. Da Softwareentwicklung viel Kommunikation bedeutet, kann diese Vielzahl an Menschen zu erschwerter Kommunikation führen. Weil die Kommunikation sich auch in der Architektur niederschlägt, bricht dann auch die Architektur zusammen. Die Beziehung zwischen Kommunikation und Architektur geht auf Conway und sein Gesetz zurück. Er hat auch die These von aufgeblasenen Projekten mit schlechter Kommunikation und am Ende schlechter Architektur aufgestellt, die bereits Thema eines anderen Blog-Posts [2] war.
Dann kommt man aber mit einer sauberen Architektur, weniger Menschen und damit weniger Kommunikation und Kommunikationsproblemen vielleicht genauso schnell zum Ergebnis, sodass das Gedankenexperiment vielleicht doch nicht ganz unrealistisch ist.
Motivator für das Gedankenexperiment ist aber eine andere Entwicklung: Es kann sein, dass wir durch künstliche Intelligenz bei der Produktion von Code deutlich effizienter werden, wie ein anderer Blog-Post [3] diskutiert hat. Dann ist die Frage, was bei einer Verbesserung von Produktivität um einen Faktor 10 passiert, sehr relevant.
Das Gedankenexperiment legt den Verdacht nahe, dass selbst bei einem solchen Fortschritt eher mehr Software produziert wird und in der Konsequenz Software auch für Bereiche genutzt wird, für die es sich im Moment noch nicht lohnt.
Tatsächlich gibt es in der Ökonomie für dieses Phänomen: Rebound-Effekt [4]. Wenn beispielsweise Autos effizienter werden, werden sie für mehr Fahrten genutzt, sodass am Ende nicht etwa der Verbrauch sinkt, sondern gegebenenfalls sogar steigt. Vielleicht führt KI zu einem ähnlichen Effekt: Softwareentwicklung wird damit zwar effizienter, aber Software wird dann auch für andere Einsatzzwecke genutzt, sodass am Ende der investierte Aufwand derselbe bleibt. Tatsächlich unterstützt Software immer mehr Bereiche und KI könnte diesen Trend dann noch verstärken.
Im Extremfall können Menschen Software entwickeln, denen das technische Skillset eigentlich fehlt. Auch dieses Versprechen gab es schon mehrfach, mit Technologien wie COBOL, aber auch Low- oder No-Code. Aber selbst wenn KI hier erfolgreich ist: Andere Branchen zeigen, welche Effekte solche Disruptionen haben. Mit Desktop-Publishing können im Vergleich mit den Achtzigerjahren nun viel mehr Menschen Druckerzeugnisse erstellen, aber die Qualität ist eher schlechter geworden und Profis haben immer noch ihr Betätigungsfeld.
Das mag nun so wirken, als sei die Zukunft der Softwarebranche auch gegen KI abgesichert. Aber natürlich ist die Zukunft schwer vorhersagbar. Man hätte auch argumentieren können, dass die aktuelle Krise am IT-Markt nur ein Vorbote von dem ist, was KI anrichten wird. Die Zukunft ist offen.
Selbst eine Verzehnfachung der Produktivität in der Softwareentwicklung, wie sie KI vielleicht hervorbringt, bedeutet nicht unbedingt, dass weniger Menschen in dem Bereich arbeiten werden, sondern vielleicht eher, dass Software für noch mehr Einsatzzwecke genutzt wird.
URL dieses Artikels:
https://www.heise.de/-10189960
Links in diesem Artikel:
[1] https://software-architektur.tv/2024/02/02/folge201.html
[2] https://www.heise.de/blog/Beten-wir-Komplexitaet-an-4170914.html
[3] https://www.heise.de/blog/KI-in-der-Softwareentwicklung-Ueberschaetzt-9336902.html
[4] https://de.wikipedia.org/wiki/Rebound-Effekt_(%C3%96konomie)
[5] https://genai.bettercode.eu/?wt_mc=intern.academy.dpunkt.konf_dpunkt_bcc_genai.empfehlung-ho.link.link
[6] https://genai.bettercode.eu/?wt_mc=intern.academy.dpunkt.konf_dpunkt_bcc_genai.empfehlung-ho.link.link#programm
[7] mailto:rme@ix.de
Copyright © 2024 Heise Medien
(Bild: Erstellt mit KI (Midjourney) durch iX)
Architektur wirkt oft wie eine dunkle Magie, die nur in den elitären Kreisen der Wissenden diskutiert wird. Das ist nicht nur falsch, sondern auch gefährlich.
"Architektur ist überbewertet" wirkt auf den ersten Blick wie ein typischer Clickbait-Titel, aber ich will kurz erklären, was genau ich mit diesem Titel meine. Architektur hat ein Problem, über das meiner Meinung nach viel zu wenig gesprochen wird, das aber auf uns als Entwicklerinnen und Entwickler gravierende Auswirkungen hat.
Es geht um die ständige Idealisierung und die überhöhte Wahrnehmung von Architektur, von Architekten und all dem, was damit zusammenhängt und einhergeht, wie zum Beispiel einer ganzen Reihe von Prinzipien, Konzepten und nicht zuletzt auch von einigen Personen.
Das schreckt ab, denn auf dem Weg wird Architektur nicht mehr als das wahrgenommen, was sie eigentlich ist – nämlich als die Kunst, Software adäquat zu strukturieren –, sondern sie wird auf einmal als Selbstzweck wahrgenommen. Das jedoch ist nicht nur falsch, sondern auch gefährlich.
Architektur hat ein Problem: Sie wird idealisiert und überhöht. Wenn Sie nicht genau wissen, was ich damit meine, stellen Sie sich vor, wie über typische Prinzipien und Konzepte aus der Architektur gesprochen wird: Da geht es nicht um ein paar hilfreiche Leitplanken und nützliche Wegweiser, die Sie bei Ihren Bemühungen zu einer gut strukturierten Software unterstützen. Nein, da geht es zum Beispiel um Clean Code (und ja, mir ist bewusst, dass das Thema für viele nicht unter Architektur fällt, im Sinne einer besseren Strukturierung von Software gehört aber auch Clean Code dazu).
Allein durch die Namensgebung sprechen wir nicht mehr nur auf einer technischen Ebene, sondern es schwingt noch etwas ganz anderes mit, etwas Emotionalisiertes: Wenn Sie sich nicht an diese Regeln halten, dann schreiben Sie Code, der schmutzig, ungepflegt und minderwertig ist. Wollen Sie so etwas etwa wirklich? Wo die Frage nach gut strukturiertem Code explizit auf der emotionalen Ebene exkludiert, fällt eine rein sachliche Diskussion schwierig.
Ein weiteres Beispiel sind die SOLID-Prinzipien. Auch suggeriert allein der Name bereits ein stabiles Fundament, ein Fels in der Brandung. Und wehe, Sie setzen sie nicht ein: Dann stehen Sie da wie ein Grashalm, der beim leichtesten Windhauch umknickt. Wollen Sie das?
Bei diesen Beispielen kann man sich sehr gut den erhobenen Zeigefinger vorstellen: Passen Sie bloß auf, sonst enden Sie wie all die anderen vor Ihnen – als Versager.
Tatsächlich ist es jedoch nicht die Namensgebung allein: Das ist nur das, was als Erstes auffällt. Es geht noch weiter: Versuchen Sie einmal, Clean Code zu kritisieren. Sofort kommen zahlreiche Befürworterinnen und Befürworter, die Clean Code mit Leidenschaft verteidigen und als das Nonplusultra darstellen. So nach dem Motto:
"Wie können Sie es wagen, Clean Code zu hinterfragen, zu kritisieren oder gar infrage zu stellen? Was bildet Sie sich ein, wer Sie sind? Und übrigens: Sie haben damit auch Uncle Bob beleidigt, also entschuldigen Sie sich gefälligst!"
Vielleicht finden Sie das jetzt übertrieben, und natürlich verhält sich nicht jede Anhängerin und jeder Anhänger von Clean Code, SOLID & Co. derart. Das Problem ist jedoch: Es lässt sich nicht leugnen, dass um diese Themen ein gewisser Kult betrieben wird, inklusive eines ausgeprägten Personenkults. Ich behaupte nicht, dass das nur Uncle Bob alias Robert C. Martin betrifft, aber bei ihm ist es besonders auffällig. Und so etwas ist immer problematisch, denn dann wird nicht mehr sachlich über die Inhalte diskutiert. Stattdessen werden diese mit unsachlichen Emotionen und persönlichen Befindlichkeiten aufgeladen und untrennbar verknüpft.
Wenn sich das über Jahre und Jahrzehnte verfestigt, hat das natürlich Folgen. Architektur und lesbarer Code werden dann nicht mehr als etwas wahrgenommen, womit sich jede und jeder beschäftigen sollte, sondern als etwas für die Eliten. Genau so erlebe ich oft die Meinung von weniger erfahrenen Entwicklerinnen und Entwicklern: Sie sagen, sie hätten von Architektur keine Ahnung, aber eines Tages würden sie das gerne in ihrem Jobtitel stehen haben, "Distinguished Senior Solution Architect" oder etwas Ähnliches.
So entsteht eine mystische Aura um dieses Thema, als wäre es nur für sehr erfahrene Menschen zugänglich, die es geschafft haben, Teil dieses elitären Kreises zu werden. Was genau eine Architektin oder ein Architekt eigentlich macht, wird dabei oft nicht mehr klar. Es scheint nur eines sicher: Es handelt sich um eine intellektuell anspruchsvolle Aufgabe, der Normalsterbliche vermeintlich nicht gewachsen sind. Dementsprechend beschäftigt man sich nicht mit Architektur, überlässt es den Weisen, entwickelt sich nicht weiter und bleibt jahrelang in dem Traum gefangen, selbst irgendwann ein Teil dieses elitären Zirkels zu sein, ohne den Weg dorthin zu kennen.
Das eigentliche Problem ist, dass Architektur oft als Selbstzweck betrachtet wird: Sie wird um ihrer selbst willen betrieben und nicht als praktisches Werkzeug, das einer größeren Aufgabe dient. Nein, die Architektur selbst wird zur höheren Aufgabe erhoben. Das ist jedoch Unsinn. Clean Code kann durchaus kritisiert werden, und Robert C. Martin ist kein Heiliger. Die SOLID-Prinzipien sind, wenn wir ehrlich sind, fünf relativ beliebig ausgewählte Prinzipien, die in der Objektorientierung mehr oder weniger sinnvoll und manchmal nützlich sind.
Warum es ausgerechnet diese fünf Prinzipien geworden sind und nicht irgendwelche anderen, bleibt Spekulation. Vermutlich hat sich jemand ein schickes Akronym ausgedacht (eben "SOLID") und dazu Prinzipien zusammengesucht, die ansatzweise sinnvoll erschienen. Wenn man sich diese Prinzipien genauer anschaut, sind die meisten davon weder besonders elegant formuliert (im Sinne von anschaulich und greifbar), noch sind sie besonders hilfreich im Alltag. Ich kann mich zumindest nicht erinnern, wann ich das letzte Mal dachte:
"Wie praktisch, dass ich das Liskovsche Substitutionsprinzip kenne, ohne das wäre diese Struktur deutlich schlechter."
Dennoch wird vermittelt, dass die SOLID-Prinzipien die fünf wichtigsten Prinzipien der objektorientierten Programmierung seien. Das sind sie jedoch nicht, da die meisten viel zu spezifisch sind.
Das heißt, sie sind keine absolute Wahrheit, die nicht hinterfragt werden dürfte. Sie sind nur Mittel zum Zweck. Architektur (und dazu zähle ich Clean Code und diese Prinzipien wie oben schon erwähnt) hat letztlich nämlich nur ein einziges konkretes Ziel: Sie soll helfen, eine gute Struktur für Code zu schaffen, sodass dieser langfristig verständlich, überschaubar, wartbar und erweiterbar bleibt.
Wann hat Code diese Struktur? Eigentlich ist das ganz einfach: immer dann, wenn zwei Grundprinzipien erfüllt sind. Code ist gut strukturiert, wenn er zum einen eine geringe Kopplung und zum anderen eine hohe Kohäsion aufweist. In dem Video zu Kopplung und Kohäsion [2] erkläre ich die beiden Prinzipien im Detail.
Diese beiden Prinzipien – geringe Kopplung und hohe Kohäsion – sind der Leitstern, der uns überall im Code Orientierung gibt, egal ob bei Funktionen und Klassen im Kleinen oder im Großen bei den zahlreichen Microservices einer verteilten Anwendung. Diese Prinzipien machen eine gute Architektur aus. Darüber nachzudenken und daran zu arbeiten erfordert keinen Titel wie "Distinguished Senior Solution Architect". Auch Praktikantinnen und Praktikanten können sich damit beschäftigen. Vielleicht fehlt ihnen etwas Erfahrung, aber sie sind durchaus intellektuell in der Lage, darüber nachzudenken.
Die entscheidende Frage lautet: Wo sollte ich mich um was kümmern, wer ist wofür verantwortlich? Das ist letztlich alles.
Die Entscheidungen müssen ein höheres Ziel unterstützen: die Fachlichkeit. Denn genau darum geht es in der Softwareentwicklung. Wir entwickeln nicht deshalb Software, weil es Spaß macht (auch wenn es tatsächlich Spaß macht), sondern um ein tieferliegendes fachliches Problem zu lösen. Software ist kein Selbstzweck, sondern ein Werkzeug, um einen fachlichen Zweck zu erfüllen. Und Architektur muss sich daran messen lassen.
Es geht nicht darum, ob wir alle fünf SOLID-Prinzipien umgesetzt oder möglichst viele Design-Patterns verwendet haben. Was am Ende zählt, ist, dass die Architektur das fachliche Problem unterstützt und es uns erleichtert, die Software langfristig zu warten und weiterzuentwickeln. Apropos Design-Patterns: Auch diese halte ich für überbewertet [3].
Mit diesem Mindset trifft man jedoch oft auf Projekte, in denen die Architektur schon feststand, bevor die fachlichen Anforderungen bekannt waren. Das halte ich für eine schlechte Idee, genauso wie die Wahl von Technologien, bevor Architektur und Anforderungen klar sind. Was ich in Teams oft erlebe, sind Argumente wie:
"Wir sind aber nicht Netflix. Wir brauchen keine Microservices, kein CQRS, kein Event-Sourcing, keine komplexe Architektur."
Stattdessen setzt man auf eine einfache Drei-Schichten-Architektur mit einem Monolithen und Dependency Injection. Missverstehen Sie mich nicht: Es gibt Projekte, wo das angemessen ist. Viel zu oft werden solche Entscheidungen jedoch mit unpassenden Argumenten und aus den falschen Gründen getroffen. Bei Microservices etwa ist die Frage nicht:
"Sind Sie Netflix?"
Stattdessen geht es (eigentlich) um geringe Kopplung und hohe Kohäsion bei ausreichend komplexer Fachlichkeit. Diese Anforderungen kann auch ein Drei-Personen-Start-up haben. Das hängt nicht davon ab, ob man Netflix ist, sondern vom jeweiligen Business.
Die klassische Drei-Schichten-Architektur im Monolithen hat einige gravierende Nachteile: Fachlicher und technischer Code sind oft nicht sauber getrennt, was Anpassungen erschwert. Beim Testen merkt man das besonders: Es ist kaum möglich, die Geschäftslogik zu testen, weil immer die Datenbank mit dranhängt. Statt die Architektur zu hinterfragen, setzen viele dann auf Mocking. Doch Mocking ist eine der schlechtesten Ideen im Testen, weil es grüne Tests liefert, ohne sicherzustellen, dass die Mocks die Realität abbilden. Mit anderen Worten: Mocking wird zum Workaround für schlechte Architekturentscheidungen.
Tatsache ist: Es gibt deutlich bessere Ansätze. Gerade bei komplexer Geschäftslogik bietet sich etwa eine hexagonale Architektur an, die die Fachlichkeit in den Mittelpunkt rückt – ohne Abhängigkeiten zu externen Ressourcen. Doch auch hier heißt es oft:
"Wir sind doch nicht Netflix."
Solche Aussagen basieren oft auf Angst vor Veränderung. Das Problem sind nicht sachliche Argumente, sondern emotionale Bedenken:
"Das haben wir noch nie gemacht, also bleibt alles beim Alten."
Oft bekommen dann Berater den Auftrag, die beruhigende Botschaft zu verbreiten, ein Monolith reiche aus, denn man sei nicht Netflix. Das wird dann nach und nach zum gefährlichen Mantra.
Jahre später stellt man dann fest, dass die Technologie veraltet ist, aber ein Wechsel kaum möglich ist, weil alles miteinander verwoben ist. Technologiewechsel werden so zu Alles-oder-Nichts-Entscheidungen. Dabei treten viele Probleme auf: schlechte Testbarkeit, keine Skalierbarkeit, fehlende APIs für externe Systeme oder unklare Verantwortlichkeiten bei Master-Data-Management. All das hätte man vermeiden können, wenn man früher über eine fachlich sinnvolle Architektur nachgedacht hätte.
Der Sinn einer Architektur liegt darin, eine tragfähige Struktur für die Software zu schaffen, die geringe Kopplung und hohe Kohäsion gewährleistet. Wie man das erreicht, ist zweitrangig. Wichtig ist, dass die Fachlichkeit unterstützt wird. Unsachliche Diskussionen über Werkzeuge wie Clean Code, SOLID oder Design-Patterns helfen dabei nicht. Stattdessen sollten wir mehr darüber sprechen, warum wir Software entwickeln und wie die Fachlichkeit unsere Entscheidungen beeinflusst. Wer sich weiterhin hinter emotionalen und unsachlichen Argumenten versteckt, wird langfristig viel Schaden anrichten.
Fragen Sie sich daher immer, ob Ihre Architektur das fachliche Problem löst oder eher behindert. Und wenn Letzteres der Fall ist, denken Sie über Alternativen nach – losgelöst von dem, was in Lehrbüchern steht oder als Standard gilt. Architektur ist mehr als das. Jede Entwicklerin und jeder Entwickler kann dazu beitragen, denn Programmieren bedeutet, Strukturen zu schaffen.
URL dieses Artikels:
https://www.heise.de/-10191624
Links in diesem Artikel:
[1] https://www.heise.de/Datenschutzerklaerung-der-Heise-Medien-GmbH-Co-KG-4860.html
[2] https://www.youtube.com/watch?v=kWP432pXP-U
[3] https://www.youtube.com/watch?v=oC-9HZ0r3e4
[4] https://shop.heise.de/ix-developer-praxis-softwarearchitektur-2024/print?wt_mc=intern.shop.shop.ix-dev-softwarearchitektur24.dos.textlink.textlink
[5] mailto:rme@ix.de
Copyright © 2024 Heise Medien
Der 2024 Web Almanac ist seit wenigen Tagen verfügbar
(Bild: HTTP Archive, Apache 2.0)
98 Prozent aller Requests nutzen HTTPS, 25 Prozent der Websites setzen keinerlei Caching ein: Nach einer Pause in 2023 meldet sich der Web Almanac zurück.
Der Web Almanac 2024 [1] ist da! Das kostenlose Jahrbuch bietet tiefgehende Einblicke in die aktuellen Entwicklungen des World Wide Web. Das in diverse Sprachen übersetzte Nachschlagewerk identifiziert Trends, aber auch Herausforderungen und richtet sich an alle, die das moderne Web verstehen und mitgestalten möchten.
78 führende Webexperten aus der ganzen Welt haben ehrenamtlich 21 Kapitel verfasst, die unterschiedliche Aspekte des Web beleuchten: Dazu gehören Markup [2], Performance [3], E-Commerce [4] oder Cookies [5]. Alle Kapitel haben ein Peer-Review durchlaufen und die Rohdaten sind jeweils am Ende eines Artikels verlinkt. Die Analysen basieren auf den umfangreichen Daten des HTTP Archive [6].
Das Jahrbuch erschien vergangenes Jahr nicht, da sich der Projektleiter in Elternzeit befand und keine halbherzige Durchführung wollte. Verglichen zur Ausgabe von 2022 [7] hat sich das Rohdatenmaterial verdoppelt: Über 17 Millionen Websites wurden analysiert und über 83 TByte Daten verarbeitet. Das Jahrbuch wurde auf Basis der Daten des Juli-Crawls geschrieben.
Auch die diesjährige Ausgabe fördert wieder viele interessante, aber auch einige kuriose Erkenntnisse zutage:
h1-Element (bei 6 Prozent davon ist es leer, Quelle [11])divs (Quelle [14])Um die Veröffentlichung des Web Almanac 2024 zu feiern, laden die Autoren zu einem Online-Event ein, das am 10. Dezember 2024 um 19 Uhr stattfindet. Interessierte können sich unter folgendem Link zuschalten: The Web Almanac Live Stream (YouTube) [17].
URL dieses Artikels:
https://www.heise.de/-10186758
Links in diesem Artikel:
[1] https://almanac.httparchive.org/en/2024/
[2] https://almanac.httparchive.org/en/2024/markup
[3] https://almanac.httparchive.org/en/2024/performance
[4] https://almanac.httparchive.org/en/2024/ecommerce
[5] https://almanac.httparchive.org/en/2024/cookies
[6] https://httparchive.org/
[7] https://www.heise.de/blog/HTTP-Archive-legt-Web-Jahrbuch-2022-vor-mit-einigen-kuriosen-Erkenntnissen-7286733.html
[8] https://almanac.httparchive.org/en/2024/security#fig-1
[9] https://almanac.httparchive.org/en/2024/third-parties#prevalence
[10] https://almanac.httparchive.org/en/2024/third-parties#fig-6
[11] https://almanac.httparchive.org/en/2024/seo#header-elements
[12] https://almanac.httparchive.org/en/2024/cdn#fig-3
[13] https://almanac.httparchive.org/en/2024/cookies#fig-2
[14] https://almanac.httparchive.org/en/2024/markup#fig-13
[15] https://almanac.httparchive.org/en/2024/sustainability#fig-28
[16] https://almanac.httparchive.org/en/2024/sustainability#how-many-of-the-sites-listed-in-the-http-archive-run-on-green-hosting
[17] https://www.youtube.com/live/cdYR0ZmplIM
[18] mailto:rme@ix.de
Copyright © 2024 Heise Medien
(Bild: Sergey Nivens/Shutterstock.com)
Low-Code- und No-Code-Plattformen versprechen Fachabteilungen, geschäftsrelevante Software selbst entwickeln zu können. Doch ist das wahr?
Stellen Sie sich für einen kurzen Augenblick vor, Sie würden nicht in der Softwareentwicklung arbeiten, sondern wären vielleicht Domänenexpertin oder -experte für Versicherungs-Policen. Sie arbeiten bei einer Versicherung in der Fachabteilung. Programmierung und Softwareentwicklung sind so gar nicht Ihre Themen, aber Sie kennen sich dafür bestens mit all den inhaltlichen Aspekten wie Policen, Schäden, Haftung und Regress aus.
Nun benötigen Sie ein kleines Stück Software: Vielleicht ein einfaches Tool, um die Daten von Kundinnen und Kunden effizienter zu erfassen, oder einen Report, der Ihnen ermöglicht, Ihre Policen für das nächste Jahr besser zu optimieren. Was es konkret ist, spielt letztlich keine Rolle. Es geht um etwas Kleines und Einfaches, das Ihnen und Ihren Kolleginnen und Kollegen das Leben erleichtert und Ihr Business voranbringt.
Wie kommen Sie nun zu dieser Software? Klar, Sie könnten natürlich zur hausinternen IT-Abteilung gehen und nett fragen. Wenn Sie Glück haben, sagt Ihnen die freundliche Kollegin aus der IT, dass das kein Problem sei. Sie würde sich darum kümmern und Ihnen das nebenbei bauen. Natürlich stellt sich nachher heraus, dass sie leider nicht ganz so viel Zeit erübrigen kann wie gedacht, und sie wusste vielleicht auch nicht ganz so genau, was Sie eigentlich im Detail wollten.
Deshalb macht die Software am Ende nicht ganz das, was sie sollte. Aber hey, beschweren Sie sich nicht: Immerhin haben Sie überhaupt etwas bekommen! Es hätte nämlich auch schlimmer kommen können: Wären Sie statt an die freundliche und hilfsbereite Kollegin an ihren grummeligen Kollegen geraten, hätte er Ihnen wahrscheinlich sehr deutlich zu verstehen gegeben, dass für so einen Quatsch keine Zeit da sei, die IT ohnehin völlig überlastet sei und Sie ohne eine um 27 Ecken eingeholte Budgetfreigabe gar nicht erst wieder ankommen bräuchten.
Wie schön wäre es, wenn Sie die IT einfach gar nicht bräuchten, sondern sich das, was Sie benötigen, einfach selbst hätten zusammenbauen können – ganz ohne jegliche Programmierkenntnisse? Willkommen bei der Welt der Low-Code- und No-Code-Plattformen!
Das, was ich Ihnen gerade geschildert habe, beschreibt letztlich das Werbeversprechen von Low-Code- und No-Code-Umgebungen. Die Idee dahinter ist, dass viele Vorgänge in Fachanwendungen mehr oder weniger immer gleich ablaufen: Formulareingaben, Datenabrufe aus einem SharePoint, tabellarische oder grafische Visualisierungen – all das sind immer wiederkehrende Muster. Die Plattform stellt nun solche Aktivitäten als Bausteine zur Verfügung, und Sie können sich daraus Ihre eigene Anwendung zusammenbauen, ohne wissen zu müssen, wie die technischen Details funktionieren.
Ich selbst habe das vor einiger Zeit einmal ausprobiert, gemeinsam mit einem Freund, auf Basis der Microsoft Power Platform, genauer gesagt mit Power Automate. Es ging um einen simplen Anwendungsfall: Daten von einer HTTP-API abrufen und anzeigen. Nach drei bis vier Stunden hatten wir dann allerdings keine Lust mehr, weil wir immer wieder auf Probleme stießen. Entweder waren wir zu zweit zu unfähig (was ich bezweifle), oder unser Anwendungsfall lag geringfügig außerhalb der vorgesehenen Nutzungspfade. Schlussendlich zogen wir einen Kollegen hinzu – einen zertifizierten "Microsoft Power Platform Developer". Ein Entwickler also für eine Plattform, die Entwickler angeblich überflüssig machen soll – an Absurdität lässt sich das kaum überbieten!
Dieser Vorfall ist natürlich nicht repräsentativ für alle Low- und No-Code-Plattformen. Aber er zeigt ein grundlegendes Problem auf: Die Plattformen machen große Versprechungen, schüren hohe Erwartungen – und die Realität bleibt dahinter zurück: Fachabteilungen können nicht plötzlich auf magische Weise alles selbst lösen. Sie können nicht auf die IT-Abteilung und Entwickler verzichten. Und sie sparen am Ende oft weder Zeit noch Geld. Im ungünstigsten Fall passiert sogar genau das Gegenteil.
Woran liegt das? Programmieren bedeutet, eine Sprache zu beherrschen. Egal, ob Sie Französisch oder eine Programmiersprache lernen: Sie müssen Vokabeln und Grammatik lernen, lesen, schreiben, sprechen – und üben. Entwicklerinnen und Entwickler haben sich all dieses Wissen in jahrelanger, mühsamer Arbeit angeeignet. Und nun kommt eine Plattform daher, die behauptet:
"Das brauchen Sie alles nicht!"
Stattdessen bekommen Sie Bausteine, die Sie anordnen sollen. Aber diese Bausteine reichen oft nicht aus, um komplexe Anforderungen abzubilden. Die fachliche und technische Komplexität bleibt bestehen – sie wird nur unsichtbar. Und spätestens, wenn eine Anwendung nicht performant läuft, Race Conditions auftreten oder der Datenverkehr das Netzwerk lahmlegt, kommen Sie ohne grundlegende Programmierkenntnisse nicht weiter.
Hinzu kommt, dass viele Plattformen proprietär sind. Sobald Sie eine Anwendung auf Basis einer solchen Plattform entwickeln, schaffen Sie einen Vendor-Lock-in. Die IT wird sich hüten, solche Anwendungen zu supporten. Das erinnert nämlich zu sehr an Microsoft Access, das in vielen Unternehmen bis heute Probleme verursacht. Das Problem ist also nicht neu – nur die Technologien haben sich geändert.
Darüber hinaus wissen Fachabteilungen oft selbst nicht, wie ihre Prozesse im Detail aussehen oder was sie genau wollen. Deshalb gibt es Business-Analysten und Requirements Engineers, die diese Anforderungen gemeinsam mit den Fachabteilungen erarbeiten. Fachabteilungen haben das fachliche Know-how, aber sie sind meist nicht darauf vorbereitet, dieses Wissen zielführend und nachhaltig in digitale Prozesse umzusetzen.
Trotz aller Kritik haben Low-Code-Plattformen aber natürlich auch ihre Berechtigung. Sie können die Kommunikation zwischen Entwicklung und Fachabteilung erleichtern, indem die Fachabteilung beispielsweise eigenständig Prototypen erstellt. Für einfache Anforderungen – wie "Formular ausfüllen und Daten per E-Mail senden" – können sie zudem durchaus ausreichen. Bei komplexeren Aufgaben würde ich jedoch zur Vorsicht raten.
Was mich an dem ganzen Thema aber mit Abstand am meisten stört, ist das Narrativ von "Entwicklung gegen Fachabteilung". Es geht nicht um "wir gegen die", und dieses Narrativ war noch nie konstruktiv oder gar zielführend, sondern führt stets nur zu Zwist und Schuldzuweisungen. Am Ende des Tages sind wir doch eigentlich dann erfolgreich, wenn wir unsere unterschiedlichen Fähigkeiten und Kenntnisse konstruktiv zusammenbringen und gemeinsam und partnerschaftlich auf ein gemeinsames Ziel hinarbeiten: Es geht um Partnerschaft auf Augenhöhe. Und Low-Code-Plattformen sollten diese Partnerschaft unterstützen, nicht spalten – doch genau das ist es, was sie letztlich machen.
Langer Rede, kurzer Sinn: Gehen Sie kritisch mit solchen Plattformen um. Verstehen Sie deren Grenzen und setzen Sie auf eine solide Zusammenarbeit zwischen Entwicklung und Fachabteilung. Nur so profitieren letztlich alle Beteiligten – außer vielleicht der Hersteller der Plattform.
URL dieses Artikels:
https://www.heise.de/-10184237
Links in diesem Artikel:
[1] https://www.heise.de/Datenschutzerklaerung-der-Heise-Medien-GmbH-Co-KG-4860.html
[2] mailto:rme@ix.de
Copyright © 2024 Heise Medien
(Bild: fizkes/Shutterstock.com)
Im Sommer 2025 veranstaltet die the native web GmbH eine eintägige Konferenz zum Thema professionelle Web- und Cloud-Entwicklung.
Das Jahr 2024 ist noch nicht ganz vorüber, aber es neigt sich allmählich dem Ende entgegen. Für meine Kolleginnen und Kollegen der the native web GmbH [1] und mich bedeutet das, dass in diesem Jahr nur noch ein paar wenige Posts in diesem Blog und auch Videos auf YouTube vor uns liegen, bevor wir uns in den Weihnachtsurlaub verabschieden werden. Es bedeutet aber auch, dass wir bereits fleißig mit der Planung für das kommende Jahr beschäftigt sind.
Was Sie im nächsten Jahr genau erwartet, das verrate ich Ihnen heute noch nicht im Detail, aber ich möchte zumindest schon einmal ein paar Worte über das vergangene Jahr verlieren.
Rückblickend war 2024 für uns ein großartiges Jahr. In den vergangenen elf Monaten haben wir sage und schreibe 26 Blogposts geschrieben, 47 Videos veröffentlicht, fünf Livestreams veranstaltet und 36 Webinare im Rahmen unserer tech:lounge Masterclass durchgeführt. Und ganz gleich, was wir gemacht haben – eine Sache war immer gleich: Ihr Feedback!
Sie haben uns in so vielen Kommentaren, E-Mails, Telefonaten, persönlichen Gesprächen, auf Discord und sogar per Post (!) geschrieben und gesagt, wie ungemein wichtig unsere Videos und Artikel für Sie sind: für lebenslanges Lernen, für kontinuierliche Weiterbildung, für den Alltag. Sie haben uns mitgeteilt, dass wir Sie mit unserem Content unterstützt haben, sich weiterzuentwickeln, endlich den neuen Job zu bekommen, anderen weiterzuhelfen und vieles mehr.
Das macht uns unglaublich stolz und wir sind sehr dankbar für dieses Feedback, denn es zeigt uns, dass das, was wir machen, nicht einfach nur das nächste x-beliebige Content-Schnippsel im Internet ist, sondern dass wir wirklich etwas zum Guten bewirken können und einen positiven Einfluss auf Ihr Leben haben. Das ist alles andere als selbstverständlich. Und darüber bin ich sehr froh.
Lebenslanges Lernen ist gerade in der IT ein wichtiges Thema. Nur wer sich dauerhaft und kontinuierlich weiterbildet, wird auch nachhaltigen Erfolg in der Softwareentwicklung haben. Deshalb haben wir uns auch für das kommende Jahr einiges vorgenommen. Was das alles im Detail sein wird, möchte ich an dieser Stelle noch nicht verraten, aber zwei Neuigkeiten möchte ich doch schon mit Ihnen teilen.
Zum einen werden wir im Sommer 2025 zum ersten Mal seit der Pandemie wieder eine Vor-Ort-Veranstaltung durchführen: Wir werden eine kleine, schnuckelige, eintägige Konferenz rund um das Thema der professionellen Web- und Cloud-Entwicklung bei uns in Freiburg im Breisgau veranstalten. Vom Morgen bis in den späten Abend hinein wird es am 4. Juli 2025 um Themen wie Architektur, Algorithmen, Protokolle, Skalierbarkeit und Ausfallsicherheit gehen.
Da wir die Veranstaltung direkt neben unserem Büro abhalten, ist das auch die perfekte Gelegenheit, meine Kolleginnen und Kollegen (und natürlich auch mich) einmal persönlich kennenzulernen. Wie das bei Veranstaltungen in der Realität leider so ist, ist der Platz natürlich begrenzt, das heißt, die Teilnahme ist auf 150 Personen limitiert. Ein Ticket kostet 399 Euro (zuzüglich 19 % Umsatzsteuer), und Sie können es ab sofort auf unserer Website buchen [2], um bei der tech:lounge Live! vor Ort dabei sein zu können. Und natürlich würde ich mich sehr freuen, Sie dort begrüßen zu dürfen!
Das ist jedoch noch nicht alles. Pünktlich zum Jahresende haben wir noch ein ganz besonderes Spezialangebot für Sie: Wir haben uns überlegt, dass wir auch im kommenden Jahr wieder Webinare anbieten werden, und zwar 24 Stück. Normalerweise kostet ein einzelnes Webinar 179 Euro, und ein Dreierpaket kostet 399 Euro. Bei 24 Webinaren wären das also insgesamt über 4.200 Euro.
Weil wir aber wissen, dass viele von Ihnen regelmäßig bei unserer tech:lounge Masterclass zu Gast sind, bieten wir Ihnen bis zum 31. Dezember dieses Jahres an, die Teilnahme an allen 24 Webinaren, die im kommenden Jahr stattfinden werden, für lediglich 999 Euro zuzüglich 19 % Umsatzsteuer zu buchen. Das sind über 75% Rabatt, und damit möchten wir Ihnen für Ihre Treue und auch für das Vertrauen danken, das Sie in den vergangenen Monaten und Jahren in uns gesetzt haben. Auch hier wissen wir, dass das alles andere als selbstverständlich ist.
Wir nennen dieses Angebot tech:lounge 360°, denn – und das ist anders als bisher – alle 24 Webinare folgen einem durchgängigen roten Faden. Das bedeutet, wir werden ab März bis einschließlich Dezember gemeinsam eine komplette Anwendung entwickeln. Dabei sind nicht nur alle möglichen Themen enthalten, wie zum Beispiel Konzeption, Modellierung, Architektur, Entwicklung, APIs, Services, Deployment, Operations, Data-Management, UIs und vieles mehr, sondern wir fügen das alles auch noch zu einem einzigen, großen, durchgängigen praktischen Beispiel zusammen.
So können Sie innerhalb eines Jahres praxisnah verfolgen, wie nach und nach eine moderne und skalierbare Web- und Cloud-Anwendung entsteht. All das in über 80 Stunden Training, verteilt auf 24 Termine, für gerade einmal 999 Euro. Auch das Ticket hierfür können Sie ab sofort auf unserer Website buchen [3]. Es lohnt sich jedoch, schnell zu sein: Das vergünstigte Angebot gilt nur bis zum 31. Dezember 2024, danach gelten die regulären Konditionen und Preise. Auch hier würde ich mich natürlich sehr freuen, Sie begrüßen zu dürfen!
PS: Einen letzten Livestream für dieses Jahr wird es in ungefähr zwei Wochen übrigens auch noch geben, nämlich am 12. Dezember, wie immer ab 18 Uhr auf unserem YouTube-Kanal [4].
URL dieses Artikels:
https://www.heise.de/-10159636
Links in diesem Artikel:
[1] https://www.thenativeweb.io/
[2] https://techlounge.io/
[3] https://techlounge.io/
[4] https://www.youtube.com/@thenativeweb
[5] mailto:rme@ix.de
Copyright © 2024 Heise Medien
Vom gewöhnlichen LLM zur menschenähnlichen KI
(Bild: von DALL-E generiert)
Sind große Sprachmodelle tatsächlich kurz vor dem Erreichen eines menschlichen Niveaus, wie in einigen Publikationen und YouTube-Kanälen behauptet?
In derzeitigen Diskussionen über generative Künstliche Intelligenz werden häufig Begriffe wie Künstliche Superintelligenz (ASI – Artificial Super Intelligence) und Allgemeine Künstliche Intelligenz (AGI – Artificial General Intelligence) verwendet. Sie erwecken den Eindruck, dass wir mit den heutigen großen Sprachmodellen (LLMs) kurz vor der Erreichung von ASI oder AGI stehen. Laut IBM ist "künstliche Superintelligenz (ASI) ein hypothetisches, softwarebasiertes künstliches Intelligenzsystem (KI) mit einem intellektuellen Umfang jenseits menschlicher Intelligenz. Auf der grundlegendsten Ebene verfügt diese superintelligente KI über hochmoderne kognitive Funktionen und hochentwickelte Denkfähigkeiten, die fortschrittlicher sind als die eines jeden Menschen."
Ich vertrete jedoch eine andere Perspektive. Obwohl LLMs bedeutende Fortschritte in der Verarbeitung und Generierung natürlicher Sprache gemacht haben, sind sie im Wesentlichen ausgeklügelte statistische Modelle, die im Mustererkennen glänzen. Sie sind durch die begrenzte Menge an qualitativ hochwertigen verfügbaren Trainingsdaten eingeschränkt. Wenn wir die leicht zugänglichen Daten erschöpfen, wird es für Unternehmen wie OpenAI oder Anthropic zunehmend schwieriger, wie in der Vergangenheit erhebliche Fortschritte in Geschwindigkeit und Wissen ihrer Modelle zu erzielen.
Wie würde also eine wirklich menschenähnliche KI aussehen? Eine authentisch intelligente Maschine würde mehrere Schlüsselmerkmale aufweisen:
Proaktivität
Anstatt sich ausschließlich auf große Mengen an vorhandenen Daten zu verlassen, sollte eine KI die Fähigkeit haben, proaktiv neues Wissen und Erfahrungen durch selbstlernende Mechanismen zu suchen. Dies beinhaltet das Initiieren von Interaktionen mit anderen Maschinen und Menschen, um Informationen in Echtzeit zu erwerben. Eine wirklich intelligente Maschine würde nicht passiv statische Daten verarbeiten, sondern aktiv mit ihrer Umgebung interagieren, um ihr Verständnis zu erweitern.
Autonomes Verhalten
Autonomie ist essenziell, damit eine KI wirklich ihre Umgebung erkunden und mit ihr interagieren kann. Eine intelligente Maschine sollte in der Lage sein, unabhängige Entscheidungen über ihre Handlungen und zukünftigen Richtungen zu treffen, ohne ständige menschliche Führung. Diese Autonomie ermöglicht es der KI, sich in komplexen, dynamischen Umgebungen zurechtzufinden und sich an neue Situationen und Herausforderungen anzupassen, wenn diese auftreten.
Emotionale Intelligenz
Während Emotionen bei Menschen komplex und nicht vollständig verstanden sind, könnte die Einbeziehung von Elementen, die Emotionen wie Neugier und Zufriedenheit analog sind, die Fähigkeit einer KI verbessern, zu erkunden und zu lernen. Neugier treibt die Suche nach neuem Wissen an und veranlasst die KI, neuartige oder "interessante" Themen zu untersuchen.
Sensoren und Aktoren
Die physische Interaktion mit der Umwelt ist entscheidend, damit eine KI erfahrungsbasiertes Wissen erlangen kann. Ausgestattet mit Sensoren und Aktoren kann eine KI ihre Umgebung wahrnehmen und Aktionen ausführen, die die Welt beeinflussen. Diese Verkörperung ermöglicht es der KI, aus direkter Erfahrung zu lernen und Informationen zu erwerben, die in bereits vorliegenden Datensätzen nicht vorhanden sind.
Denken, Meta-Denken und Reflexion
Fortgeschrittene kognitive Prozesse wie Denken und Selbstreflexion sind unerlässlich, damit eine KI aus ihren Erfahrungen, einschließlich Misserfolgen, lernen kann. Durch die Analyse vergangener Handlungen und Ergebnisse kann die KI ihr Verhalten anpassen, um die zukünftige Leistung zu verbessern.
Während aktuelle KI-Technologien beeindruckende Fortschritte gemacht haben, erfordert die Erreichung echter AGI oder ASI die Überwindung signifikanter Hürden:
Die Reise hin zu menschenähnlicher KI besteht nicht nur darin, Modelle zu skalieren oder Daten zu erhöhen, sondern erfordert ein grundlegendes Umdenken, wie KI-Systeme lernen, interagieren und denken. Indem wir uns auf Proaktivität, Autonomie, emotionale Intelligenz, physische Verkörperung und fortgeschrittene kognitive Prozesse konzentrieren, können wir der Entwicklung von KI näher kommen, die nicht nur menschliche Fähigkeiten nachahmt, sondern auch auf wirklich intelligente und autonome Weise mit der Welt interagiert.
Nur indem wir diese facettenreichen Herausforderungen angehen, können wir hoffen, das volle Potenzial der Künstlichen Intelligenz zu realisieren und den Weg für Maschinen zu ebnen, die wirklich denken, lernen und vielleicht eines Tages ein Bewusstsein ähnlich dem unseren besitzen.
URL dieses Artikels:
https://www.heise.de/-10039060
Links in diesem Artikel:
[1] mailto:map@ix.de
Copyright © 2024 Heise Medien
(Bild: Natalia Hanin / Shutterstock.com)
Das OpenJDK entwickelt sich rasant weiter. Die Anzahl der JEPs pro halbjährlichen Release steigt. Java gehört auch mit 30 Jahren noch nicht zum alten Eisen.
Für das OpenJDK 24 [1] sind aktuell (Stand: 20.11.2024) schon 24! (in Worten: vierundzwanzig) JEPs eingeplant. Das passt nicht nur zur nächsten Release-Nummer. Das ist auch ein neuer Rekord, seit die Entwicklung 2018 auf die halbjährlichen Release-Zyklen umgestellt wurde. Und die Zahl kann sogar noch weiter wachsen. Denn erst am 5. Dezember startet die Rampdown Phase One mit dem Feature Freeze für die nächste Version. Und weil es diesmal so viele JEPs (JDK Enhancement Proposals) sind, werden wir hier schon mal einen ersten Blick auf die aus Developer-Sicht interessantesten Punkte werfen, die aktuell eingeplant sind. Weitere Details können über die jeweiligen JEPs nachvollzogen werden.
In einem späteren Post schauen wir uns dann die restlichen Features an. Vielleicht kommen ja sogar noch welche hinzu. Wir dürfen also gespannt sein, was in den nächsten zwei Wochen passieren wird.
JEP 485 – Stream Gatherers
Nach zwei Previews erfolgt nun die Finalisierung. Die in Java 8 eingeführte Stream API unterstützt jetzt das Hinzufügen eigener Intermediate Operationen. Dadurch können Daten in Streams nun auf bessere, optimierte Art und Weise transformiert werden als mit den wenigen fest eingebauten Intermediate Operationen bisher. Somit können Stream Pipelines ab sofort flexibler und ausdrucksstärker implementiert werden. Das OpenJDK liefert auch gleich einige neue Operationen mit: fold, mapConcurrent, scan, windowFixed und windowSliding. In Zukunft können relativ einfach weitere folgen.
JEP 484 – Class-File API
Hier erfolgt nun ebenfalls nach zwei Previews die Finalisierung des neuen Standards zum Parsen, Generieren und Transformieren von Java-Bytecode (Class Files) basierend auf der Spezifikation der Java Virtual Machine. In Zukunft können alle JDK-Komponenten auf diese Standard-API migriert werden. Schlussendlich können die JDK-Entwickler dann die interne Kopie und damit die Abhängigkeit zur Drittanbieter-Bibliothek ASM entfernen.
JEP 488 – Primitive Types in Patterns, instanceof, and switch (Second Preview)
Es geht in diesem zweiten Preview um die Erweiterung des Pattern Matching, sodass primitive Datentypen wie int, byte und double in allen Pattern-Kontexten verwendet werden dürfen, also beim instanceof und im switch. Entwickler haben dadurch weniger Limitierungen und Sonderfälle und können primitive und Referenzdatentypen auch im Kontext von Type Patterns oder als Komponenten in Record Patterns austauschbar verwenden. Seit der ersten Preview gibt es keine Änderungen, die JDK-Entwickler wollen aber weiteres Feedback sammeln.
JEP 499 - Structured Concurrency (Fourth Preview)
Bei der Bearbeitung von mehreren parallelen Teilaufgaben erlaubt Structured Concurrency die Implementierung auf eine besonders les- und wartbare Art und Weise. Alternativ konnten Entwickler für diesen Zweck bisher die Parallel Streams, den ExecutorService oder reaktive Programmierung einsetzen. Alles sehr mächtige Ansätze, die aber gerade einfache Umsetzungen unnötig kompliziert und fehleranfällig machen. Structured Conncurrency behandelt Gruppen von zusammengehörigen Aufgaben als eine Arbeitseinheit, wodurch die Fehlerbehandlung sowie das Abbrechen der Aufgaben vereinfacht und die Zuverlässigkeit sowie die Beobachtbarkeit erhöht werden. Änderungen zur letzten Preview gibt es keine. Die Macher des OpenJDK wünschen sich vielmehr weitere Rückmeldungen aus der "realen" Welt.
JEP 487 – Scoped Values (Fourth Preview)
Einführung eines Gültigkeitsbereichs, sodass unveränderliche Daten sowohl in den Aufrufen innerhalb eines Threads als auch in Child-Threads geteilt und verwendet werden können. Scoped Values lassen sich einfacher nachvollziehen, verfolgen aber ähnliche Ziele wie ThreadLocal-Variablen. Sie haben auch einen geringeren Platz- und Zeitbedarf, insbesondere wenn sie zusammen mit virtuellen Threads (JEP 444 [2]) und Structured Concurrency (JEP 480 [3]) verwendet werden. Eine Änderung gibt es diesmal: Die Methoden callWhere() und runWhere() wurden aus der Klasse ScopedValue entfernt. Ihre Funktionalität kann aber noch über ein Objekt der Klasse Carrier aufgerufen werden, welches die Methode where() von ScopedValue zurückliefert. Dadurch wird die API vollständig fluent. Die Funktion call() liefert übrigens ein Ergebnis, während die Prozedur run() nichts zurückgibt.
JEP 489 – Vector API (Ninth Incubator)
Die Vector API ist der Dinosaurier unter den JEPs und nun schon das neunte Mal als Inkubator dabei. Seit Java 16 taucht sie regelmäßig in den Releases auf. Es geht dabei um die Unterstützung der modernen Möglichkeiten von SIMD-Rechnerarchitekturen mit Vektorprozessoren. Single Instruction Multiple Data (SIMD) lässt viele Prozessoren gleichzeitig unterschiedliche Daten verarbeiten. Durch die Parallelisierung auf Hardwareebene verringert sich beim SIMD-Prinzip der Aufwand für rechenintensive Schleifen. Der Grund für die lange Inkubationsphase hängt mit der Abstimmung mit dem Projekt Valhalla zusammen. Man wartet auf die Reformen am Typsystem (JEP 401: Value Classes and Objects [4]). Die Entwickler des JDK wollen vor der Finalisierung der Vector API die derzeitigen wertbasierten Klassen (Referenztypen) in Value Classes (ohne Objektidentität) umwandeln. Das kann noch etwas dauern, denn für das OpenJDK 24 sind die Value Types bisher noch nicht auf dem Plan. Aber immerhin hat Brian Goetz (Java Language Architekt bei Oracle) im Sommer 2024 angekündigt, dass sie beim Projekt Valhalla nach 10 Jahren den Durchbruch in der Implementierung geschafft haben. Hier könnte also mit dem OpenJDK 25 vielleicht schon die erste Preview auftauchen.
JEP 486 – Permanently Disable the Security Manager
Der Security Manager wurde häufig zur Absicherung von clientseitigem Java-Code (Rich-Clients, Applets), aber nur selten für die Server-Seite verwendet. Zudem ist seine Wartung teuer. Mit Java 17 (2021) wurde er als Deprecated for Removal markiert. Nun wird er intern ausgebaut. Er kann jetzt nicht mehr aktiviert werden und andere Klassen der Java-Plattform verweisen nicht mehr darauf. Diese Änderung wird aber vermutlich keine Auswirkungen auf die große Mehrheit der Anwendungen, Bibliotheken und Tools haben. In einer der zukünftigen Java-Versionen wird die Security Manager API endgültig entfernt.
JEP 492 – Flexible Constructor Bodies (Third Preview)
In Konstruktoren dürfen Anweisungen nun bereits vor einem expliziten Konstruktoraufruf (super() oder this()) erscheinen. Diese Anweisungen dürfen zwar nicht auf die zu konstruierende Instanz verweisen, können jedoch Parameter validieren bzw. transformieren oder auf Felder der Oberklasse zugreifen. Die Initialisierung von Feldern vor dem Aufruf eines anderen Konstruktors macht die Klasse zuverlässiger, wenn beispielsweise Methoden überschrieben werden.
JEP 494 – Module Import Declarations (Second Preview)
Dadurch lassen sich jetzt in Java alle exportierten Packages eines Moduls auf einmal importieren. Das vereinfacht die Wiederverwendung modularer Bibliotheken. Es ist übrigens nicht erforderlich, dass der importierende Code selbst in einem Modul enthalten ist. Bei dieser zweiten Preview gibt es zwei Erweiterungen. Einerseits wurden Beschränkungen bei den transitiven Abhängigkeiten vom Modul java.se (eine Art Aggregator-Modul ohne eigene Packages/Klassen) zu java.base aufgehoben. Dadurch kann man nun mit dem Import dieses einen Moduls die gesamte API von Java SE importieren. Außerdem ist es jetzt möglich, dass sogenannte Type-Import-on-Demand-Deklarationen (z. B. import java.util.*) vorherige Modul-Import-Deklarationen überdecken. Wenn beispielsweise die Module java.base und java.sql importiert werden, gäbe es eine Unklarheit beim Verwenden der Klasse Date. Die gibt es als java.util.Date und als java.sql.Date. Durch die on-demand-Deklaration import java.util.* wird in dem Fall java.util.Date verwendet.
JEP 495 – Simple Source Files and Instance Main Methods (Fourth Preview)
Das Ziel ist, Anfängern den Einstieg in Java zu erleichtern und erfahrenen Entwicklerinnen und Entwicklern die Möglichkeit zu geben, kleine Anwendungen einfach bauen und ausführen zu können. Anfänger wie auch Fortgeschrittene müssen sich somit nicht mit den für große Programme konzipierten Sprachfunktionen auseinandersetzen. In dieser vierten Preview soll weiter Feedback gesammelt werden. Unter Beibehaltung der bestehenden Java-Toolchain und nicht mit der Absicht, einen separaten Dialekt für Java einzuführen, lassen sich in simplen Java Source Files, die nur eine vereinfachte main-Methode (ohne Klassen-Deklaration) enthalten, einfache, skriptartige Programme erstellen. Dazu kommt die leichtere Verwendung von Standardein- und -ausgabe durch die neuen statischen Methoden print(), println() und readln() der Klasse java.io.IO. Diese wird zum Teil automatisch importiert, womit die Funktionen einsatzbereit sind.
URL dieses Artikels:
https://www.heise.de/-10051629
Links in diesem Artikel:
[1] https://openjdk.org/projects/jdk/24/
[2] https://openjdk.org/jeps/444
[3] https://openjdk.org/jeps/480
[4] https://openjdk.org/jeps/401
[5] mailto:rme@ix.de
Copyright © 2024 Heise Medien
(Bild: jakkaje879/Shutterstock.com)
Die Bücher des Bloggers Dotnet-Doktor sind passend zum Release avon.NET 9.0 auf dem aktuellen Stand.
Pünktlich zum Release von .NET 9.0 [1] ist es mir auch dieses Jahr wieder gelungen, dass meine .NET-Bücher auf dem RTM-Stand (Release to Manufacturing) verfügbar sind:
Die Bücher gibt es in gedruckter Form (Print-on-Demand), im PDF-Format und als Kindle-E-Book.
(Bild: IT-Visions.de [6])
URL dieses Artikels:
https://www.heise.de/-10032056
Links in diesem Artikel:
[1] https://www.heise.de/news/Microsoft-NET-9-0-bringt-Breaking-Changes-und-neue-KI-Bibliothek-10031831.html
[2] https://it-visions.de/buch/N9U
[3] https://it-visions.de/buch/CSC13
[4] https://it-visions.de/buch/EFC13
[5] https://it-visions.de/buch/BLA90
[6] http://www.it-visions.de/NET9buecher
[7] https://net.bettercode.eu/?wt_mc=intern.academy.dpunkt.konf_dpunkt_bcc_net.empfehlung-ho.link.link
[8] https://net.bettercode.eu/index.php?wt_mc=intern.academy.dpunkt.konf_dpunkt_bcc_net.empfehlung-ho.link.link#programm
[9] https://net.bettercode.eu/tickets.php?wt_mc=intern.academy.dpunkt.konf_dpunkt_bcc_net.empfehlung-ho.link.link
[10] mailto:mdo@ix.de
Copyright © 2024 Heise Medien
(Bild: erstellt mit KI (Dall-E) von iX-Redaktion)
Ein neuronales Netz von Grund auf selbst zu entwickeln, trägt enorm zum Verständnis von KI bei. Das richtige Buch hilft, diesen Wunsch zielführend umzusetzen.
Manchen mag es heute so gehen wie mir vor acht Jahren: Ich wollte unbedingt mein eigenes neuronales Netz bauen, hatte jedoch von Künstlicher Intelligenz ungefähr so viel Ahnung wie eine Kuh vom Fahrradfahren. Zum Glück gibt es Bücher, mit denen man sich weiterbilden kann. Das große Problem besteht in der Regel allerdings darin, ein Buch zu finden, das auch wirklich weiterhilft: Es soll praktisch sein, aber auch die grundlegende Theorie vermitteln. Es darf nicht zu akademisch sein, sondern sollte alltagstauglich bleiben. Es soll dies, es sollte das, es sollte jenes.
Damals stieß ich dann durch Zufall auf ein außergewöhnlich gutes Buch, das mir sehr geholfen hat, ein fundiertes Verständnis und eine gute Vorstellung von neuronalen Netzen zu bekommen. Und ich habe im Anschluss tatsächlich mein erstes neuronales Netz gebaut. Dieser Blogpost eignet sich vor allem für diejenigen, die den gleichen Wunsch haben wie ich damals.
Was eine Künstliche Intelligenz ist, davon hatte ich schon seit meiner Kindheit eine recht genaue Vorstellung: Für mich war das immer ein Computer, der mithilfe seiner Schaltkreise "denken" kann. Einer, der in der Lage ist, Menschen und seine Umwelt zu verstehen, zu lernen, logische Schlüsse zu ziehen, und so weiter. Geprägt wurde diese Vorstellung bei mir ganz klar durch den berühmten Roman von Arthur C. Clarke und den gleichnamigen Film von Stanley Kubrick: "2001: Odyssee im Weltraum [1]".
Der darin vorkommende Computer HAL 9000 ist für mich der Inbegriff von Künstlicher Intelligenz, und ich habe als Kind davon geträumt, eines Tages mit einem solchen Computer interagieren zu können. Oder noch besser, eines Tages selbst einen solchen Computer zu entwickeln. Insofern sind Arthur C. Clarke und Stanley Kubrick in gewissem Sinne mitschuldig daran, dass ich den Weg in die Informatik eingeschlagen habe. Tatsächlich hat HAL bis heute nichts von seiner Faszination auf mich verloren, im Gegenteil. Allerdings bin ich mir nicht mehr so sicher wie damals, ob ich ihn in der Realität wirklich haben wollen würde …
Der Punkt ist: So wie es mir damals ging, geht es Ihnen vielleicht heute auch. Soll heißen: Vielleicht tragen auch Sie schon seit einer Weile den Wunsch mit sich herum, eine eigene Künstliche Intelligenz zu entwickeln. Es muss ja vielleicht nicht gleich ein Supercomputer à la HAL 9000 sein, aber so ein kleines, schnuckeliges neuronales Netz wäre vielleicht doch ganz cool. Die gute Nachricht ist: Das ist gar nicht so schwer, wie Sie vielleicht denken.
Die zweite gute Nachricht ist: Neuronale Netze sind die Grundlage von so vielem heutzutage, dass es ungemein praktisch ist, zu verstehen, wie sie funktionieren. Also nicht nur, sie anwenden zu können, sondern wirklich zu begreifen, was ein neuronales Netz ist, warum es auf eine gewisse Art aufgebaut wird, wie und warum es funktioniert, und so weiter. Ich bin der festen Überzeugung, dass es, trotz all der KI-Frameworks wie TensorFlow, Keras, PyTorch & Co., die das Anwenden von Künstlicher Intelligenz sehr einfach machen, eine sehr gute Idee ist, auch zu verstehen, wie das Ganze überhaupt funktioniert.
Nun ist das Problem, dass es kaum gute Literatur oder andere Quellen gibt. Entweder sind die Materialien, die man findet, viel zu akademisch und mathematisch oder sie streifen die Grundlagen und die zugrunde liegende Theorie nur kurz und konzentrieren sich auf die Anwendung. Ersteres sind zum Beispiel die von Stanford verfügbaren Online-Kurse, und Letzteres sind die ganzen Bücher mit Titeln wie "Keras: Machine-Learning in der Praxis" oder "Einführung in die KI mit TensorFlow".
(Bild: O'Reilly)
Genau an diesem Punkt stieß ich vor vielen Jahren auf ein fantastisches Buch: Es hieß "Make Your Own Neural Network" und stammte aus der Feder von Tariq Rashid. Das Wort "Buch" ist hier fast schon zu hoch gegriffen: Es war eher eine umfangreiche Broschüre, da der Autor es damals selbst verlegt hatte, ohne einen professionellen Verlag dahinter. Dem Inhalt hat das jedoch keinen Abbruch getan, im Gegenteil: Ich war sehr beeindruckt, wie anschaulich und greifbar er erklärt hat, wie man ein eigenes neuronales Netz entwickelt, und zwar wirklich von Grund auf, also ohne die genannten Frameworks, aber eben auch ohne dafür Mathematik studiert haben zu müssen.
Im vergangenen Juni stellte ich nun fest, dass O’Reilly das Ganze als Buch herausgebracht hat. Da der Vertrieb von O’Reilly im deutschsprachigen Raum vom dpunkt.verlag übernommen wird, und mein Unternehmen (the native web [3]) mit diesem wiederum eine Kooperation hat, habe ich die Neuausgabe als Rezensionsexemplar kostenlos zur Verfügung gestellt bekommen. Das heißt jedoch nicht, dass ich das Buch schönreden muss: Ich teile hier ganz unabhängig meine Meinung und sage, was mir an dem Buch gefällt und was nicht. Ich werde nicht dafür bezahlt, und es gibt keine Vereinbarung, dass ich das Buch in den Himmel loben müsste. Ich sage das nur deshalb so explizit dazu, um offen, ehrlich und transparent zu sein, denn das ist uns sehr wichtig.
Die Frage lautet also nun: Wie fangen Sie an, wenn Sie ein eigenes neuronales Netz bauen möchten? Eigentlich ist das ganz klar: Zuerst einmal müssen Sie einige grundlegende Konzepte kennenlernen. Sie müssen wissen, welche Arten von neuronalen Netzen es gibt: Es gibt Netze, die versuchen, einen konkreten Wert vorherzusagen, und solche, die versuchen, einen gegebenen Wert zu kategorisieren, oder genauer gesagt, zu klassifizieren. Natürlich gibt es noch weitere Arten, aber das sind die beiden grundlegenden Typen.
Dann stellt sich die Frage: Was ist überhaupt ein Neuron? Wie ist es intern aufgebaut und wie funktioniert es? Was ist eine Aktivierungsfunktion? Wie formt man aus einzelnen Neuronen eine Schicht und daraus wiederum ein Netz? Wie lernt ein solches Netz überhaupt, was es tun soll? Und so weiter.
Es gibt also viele Fragen, die noch gar nicht darauf abzielen, wie man ein neuronales Netz schlussendlich baut, sondern erst einmal darauf, zu verstehen, was überhaupt die Bauteile eines solchen Netzes sind. Das Schöne ist: Um das zu erklären, braucht man nicht viel. Im Prinzip reichen ein Blatt und ein Stift aus, um das Ganze aufzumalen, und die Mathematik, die man benötigt, hat man (und das meine ich ernst) weitestgehend bereits in der Grundschule gelernt.
Viel mehr als Addition, Multiplikation und ein bisschen lineare Gleichungen ist es in weiten Teilen nämlich nicht. Wenn man es effizient machen möchte, braucht man vielleicht noch die Matrizenmultiplikation, aber auch das ist am Ende nur eine Kombination von Addition und Multiplikation. Und das Einzige, wofür man tatsächlich etwas mehr Mathematik benötigt, ist das eigentliche Lernen oder Trainieren der Netze mit dem sogenannten Backpropagation-Algorithmus, für den man dann Ableitungen braucht.
Aber auch das ist kein Universitätswissen, sondern Schulstoff der gymnasialen Oberstufe. Mit anderen Worten: Jede Schülerin und jeder Schüler der 11. Klasse bringt das Wissen und das mathematische Handwerkszeug mit, das man für neuronale Netze im Wesentlichen braucht.
Vielleicht mag das jetzt nach viel klingen. Tatsächlich ist es aber gar nicht so umfangreich, denn Tariq Rashid beschreibt das alles im ersten Kapitel des Buches auf gerade einmal 90 Seiten. Auch das klingt vielleicht viel, aber zum einen sind dort viele Beispiele und Abbildungen enthalten (die übrigens in Farbe gedruckt sind, was ich schön finde), und zum anderen nimmt er sich wirklich viel Zeit für die Erklärungen, sodass man gut folgen kann.
Um es anders zu formulieren: Nach 90 anschaulichen, gut verständlichen und kurzweiligen Seiten haben Sie die komplette Basis verstanden, wie neuronale Netze arbeiten – von einfachen Netzen bis hin zu den Transformern in modernen Sprachmodellen, denn auch diese basieren letztlich auf neuronalen Netzen, wenn auch sehr komplexen. Aber 90 Seiten, das war’s.
Das heißt, wenn Sie all das kennengelernt haben, dann haben Sie ein intuitives Grundverständnis dafür, was ein neuronales Netz ist und wie und warum es funktioniert. Vielleicht wird das Ganze ein wenig ernüchternd wirken, denn es ist keine dunkle Magie oder etwas Mystisches: Es sind nur ein paar mathematische Formeln. Im Prinzip so etwas wie
f(x) = x^2
in komplexerer Form. Allein das ist aus meiner Sicht schon eine durchaus wichtige Erkenntnis, denn genauso wenig, wie diese einfache Funktion ein Bewusstsein hat oder die Weltherrschaft anstrebt, macht das irgendeine andere mathematische Formel, selbst wenn sie komplexer ist und mit mehr Variablen arbeitet. Verstehen Sie mich dabei bitte nicht falsch: Damit will ich mitnichten sagen, dass von Künstlicher Intelligenz keine Gefahr ausgehen könnte, aber das typische Schreckensszenario à la
"Wir werden alle sterben, weil die KI sich selbstständig macht."
ist Blödsinn. Die KI an sich, oder das neuronale Netz an sich, ist letztlich einfach nur eine komplexe Formel, nicht mehr und nicht weniger.
Nun muss man das Ganze natürlich auch umsetzen können. Genau das passiert im zweiten Kapitel des Buches, auf insgesamt rund 70 Seiten: Dort erklärt Tariq Rashid zuerst im Schnelldurchlauf die Programmiersprache Python. Ob Sie das Ganze letztlich in Python oder in einer anderen Sprache nachbauen, ist für das Verständnis nebensächlich – mit Python wird es Ihnen jedoch leichter gemacht, wenn Sie später doch mit Frameworks arbeiten möchten, da die meisten davon für Python verfügbar sind.
Python als Sprache selbst hat keinerlei besondere Eigenschaften, die sie besonders gut für Künstliche Intelligenz geeignet machen. Es liegt viel eher am Ökosystem drumherum. Für den Anfang ist das jedoch relativ egal, ich selbst habe das Ganze damals mit JavaScript auf der Basis von Node.js umgesetzt.
Nach dieser kurzen Einführung ist das zweite Kapitel dann im weiteren Verlauf ziemlich geradlinig: Sie müssen einfach das, was Sie in Kapitel 1 gelernt haben, in Programmcode umsetzen. Das ist vor allem eine Fleißaufgabe und hat wenig mit Verständnis zu tun, denn die notwendige gedankliche Vorarbeit haben Sie in Kapitel 1 schon lange geleistet. Natürlich stellt sich die spannende Frage: Wie gut ist denn ein neuronales Netz, das man selbst baut?
Um das beurteilen zu können, braucht man ein konkretes Beispiel. Der Autor verwendet dafür den MNIST-Datensatz, eine Sammlung von handgeschriebenen Ziffern, die als Einzelbilder vorliegen. Damit trainiert er dieses erste Netz. Ziel ist es, mit möglichst hoher Erkennungsrate vorherzusagen, welche Ziffer auf einem gegebenen Bild zu sehen ist. Er erreicht mit diesem ersten Netz ohne weitere Optimierung eine Erfolgsrate von rund 97 %.
Das finde ich schon ziemlich beeindruckend. Natürlich mussten die Daten dafür vorbereitet werden, aber auch das erklärt Rashid ausführlich und anschaulich, sodass man versteht, dass es normal ist, dass Daten für eine KI immer in der einen oder anderen Form aufbereitet werden müssen.
Die übrigen 40 Seiten des Buches sind relativ schnell abgehakt: Im dritten Kapitel geht es noch um die Frage, wie man das Training verbessern könnte, das ist aber wirklich nur ein Ausblick. Das vierte und letzte Kapitel gibt dann eine Einführung, wie man das Ganze mit PyTorch umsetzen könnte, einfach weil Sie in der Praxis vermutlich eher mit einem solchen Framework arbeiten werden, als alles von Hand zu programmieren. Trotzdem – und das war mein Punkt am Anfang dieses Blogposts – ist es hilfreich zu wissen, wie das Ganze unter der Haube zusammenhängt und funktioniert. Im Anhang gibt es dann noch eine kurze Einführung in die Analysis, weil vielleicht doch nicht jede Entwicklerin und jeder Entwickler eine Ableitung "mal eben so" berechnen kann.
Und das ist dann das gesamte Buch mit seinen rund 250 Seiten. Das Erstaunliche dabei ist, dass eigentlich nur die ersten 160 Seiten wirklich wichtig für den Einstieg und das Verständnis sind. Der Rest ist eher eine nette Beigabe. Wenn Sie sich vertieft mit der Anwendung beschäftigen möchten, würde ich Ihnen ohnehin ein anderes Buch nahelegen, nämlich "Deep Learning illustriert [4]" von Jon Krohn, Grant Beyleveld und Aglaé Bassens, das ich vor rund einem Jahr vorgestellt und besprochen habe.
So oder so: Ich wünsche Ihnen viel Spaß und Erfolg bei Ihrem ersten eigenen neuronalen Netz!
Tariq Rashid
Neuronale Netze selbst programmieren: Ein verständlicher Einstieg mit Python [5]
O'Reilly, 2. Auflage 2024
448 Seiten
ISBN (Print): 978-3-96009-245-2
[Anmerkung d. Red.: Der dpunkt.verlag als Herausgeber des Buches ist wie heise online Teil der heise group]
URL dieses Artikels:
https://www.heise.de/-10002704
Links in diesem Artikel:
[1] https://de.wikipedia.org/wiki/2001:_Odyssee_im_Weltraum
[2] https://www.heise.de/Datenschutzerklaerung-der-Heise-Medien-GmbH-Co-KG-4860.html
[3] https://www.thenativeweb.io/
[4] https://www.youtube.com/watch?v=rE2xwBBZflA
[5] https://dpunkt.de/produkt/neuronale-netze-selbst-programmieren-2/
[6] mailto:rme@ix.de
Copyright © 2024 Heise Medien
(Bild: erstellt mit KI (Dall-E) durch iX)
Version 2.0 bricht mit vielen ehemaligen Idealen des Deno-Projektes. Doch ist das gar nicht so schlimm, da Deno dadurch erst massentauglich wird.
Seit über vier Jahren veröffentlichen wir annähernd jede Woche ein neues Video auf dem YouTube-Kanal meines Unternehmens [1], und im Laufe der Zeit habe ich dabei auch die eine oder andere Einschätzung zu der einen oder anderen Technologie abgegeben. Dabei gehe ich nicht leichtfertig vor, sondern mache mir im Vorfeld intensiv Gedanken, welche Technologien in der Zukunft funktionieren könnten und welche eher nicht, worauf der Markt anspringen wird und worauf eher nicht, und so weiter. Ohne mich selbst loben zu wollen, würde ich sagen, dass ich ein passables Händchen dafür habe, zukünftige Trends und Entwicklungen frühzeitig zu erkennen und entsprechend vorherzusagen. Trotzdem liege auch ich natürlich gelegentlich daneben.
Das kann zum einen passieren, wenn mir aller Sorgfalt zum Trotz doch eine Fehleinschätzung unterläuft, weil ich zum Beispiel einen wesentlichen Aspekt nicht gesehen habe. Das kann aber auch passieren, weil sich manche Technologien im Laufe der Zeit dermaßen stark verändern, dass ich sie nach einer Weile eigentlich neu bewerten und meine bisherige Meinung gegebenenfalls revidieren muss. Und genau das ist heute der Fall: Heute müssen wir nämlich einmal über die neu erschienene Version 2 von Deno [2] sprechen.
Wer unsere Videos schon länger verfolgt, weiß, dass die ersten Videos zu Deno fast auf den Tag genau vier Jahre zurückliegen. Ausgangspunkt war damals der Vortrag von Ryan Dahl auf der JSConf EU 2018 mit dem Titel "Ten Things I Regret About Node.js [3]". Dazu habe ich damals eine erste Einschätzung [4] abgegeben: Im Unterschied zu vielen anderen konnte ich seiner Argumentation nicht viel abgewinnen. Daran hat sich bis heute nichts geändert: Ich fand seinen Vortrag, um ehrlich zu sein, inhaltlich schwach und die genannten Argumente dürftig.
Die damalige Ankündigung von Deno wirkte auf mich maßlos überzogen. Ja, es gab ein oder zwei interessante Aspekte, wie das konsequente Nutzen der V8-Sandbox, aber es gab genug Punkte, die bereits damals überholt, irrelevant oder einfach nicht durchdacht waren. Oft habe ich danach kritisiert, wie sich Ryan Dahl verhalten hat: Wäre es ihm wirklich darum gegangen, die Welt für JavaScript-Entwicklerinnen und -Entwickler zu verbessern, hätte er sich (aus meiner Sicht) eher wieder bei Node.js engagieren sollen, statt das JavaScript-Ökosystem nun auch auf dem Server zu fragmentieren.
Außerdem wirkte die ganze vorgeschobene Reue auf mich wie ein Vorwand, um im Hintergrund ein Unternehmen aufzubauen – was natürlich völlig legitim ist, aber für meinen Geschmack nicht transparent genug kommuniziert wurde. Insgesamt war mir der Vortrag zu pathetisch, zu viel Drama, zu viel Show und zu wenige echte Argumente. Kurz gesagt: Ich hielt Deno damals vor allem für heiße Luft.
Tja, und was soll ich sagen? Seit der Ankündigung vor immerhin sechs Jahren ist Deno eher gefloppt. Ja, es hatte sicherlich einen gewissen Einfluss auf die Weiterentwicklung von Node.js, aber dieser dürfte doch überschaubar gewesen sein. Im Gegenzug hat Deno jedoch die Fragmentierung von JavaScript auf dem Server [6] eingeleitet, was inzwischen mit Bun noch schlimmer wurde. Apropos Bun: Auch davon hört man abseits einer sehr kleinen und überschaubaren Community nichts, und auch hier wird mir zu viel Show gemacht und zu wenig geliefert. Bis hierhin bleibt Deno für mich also vor allem viel Show, viel Gerede, wenig Substanz und vor allem eines – unnötig.
Das Interessante dabei ist, dass vieles von dem, was Ryan Dahl damals groß angekündigt hat, sich letztlich als nicht sonderlich schlaue Idee erwiesen hat, wie beispielsweise seine große Kritik an der vermeintlich ach so "bösen" package.json-Datei, in der in Node.js die Abhängigkeiten verwaltet werden. Was wurde nicht alles gesagt, was an npm schlecht sei, warum das alles ein grundlegender Designfehler sei, und so weiter. Das alles müsse man nun besser machen (und "besser" hieß vor allem anders). Turns out: npm ist sicherlich nicht perfekt, aber um Welten besser, als Ryan Dahl es damals dargestellt hat. All die Ansätze, die Deno seitdem versucht hat, um Abhängigkeiten anders zu verwalten, haben am Ende nur eines bewirkt: Inkompatibilität und – ironischerweise – neue Probleme.
Weil irgendwann dann auch das Team hinter Deno gemerkt hat, dass es keine gute Idee ist, das bestehende JavaScript-Ökosystem komplett zu ignorieren und auszuschließen, hat man bei Deno dann eine Kehrtwende vollzogen und eine provisorische Unterstützung für npm integriert. Und plötzlich war Deno nicht mehr eine völlige Insellösung, sondern man konnte immerhin ein bisschen damit arbeiten. Trotzdem funktionierte vieles nicht. Deshalb wurde die Kompatibilität zu npm und übrigens auch zu Node.js nach und nach weiter ausgebaut, denn man merkte, dass der Umstieg unattraktiv ist, wenn praktisch alle Basis-APIs fehlen, sie anders heißen oder anders funktionieren.
Deno hat sich also nach und nach von vielen seiner vermeintlichen Ideale abgewendet und versucht nun, 90 Prozent all dessen zu unterstützen, was angeblich so schlecht und fehlerhaft gewesen sei. Das gipfelte Anfang Oktober in der Veröffentlichung von Deno 2.0 [7].
Das war für mich Grund genug, meine Meinung noch einmal auf den Prüfstand zu stellen. Und ich muss sagen, ich muss einiges revidieren: Deno 2 ist die erste Version von Deno, die wirklich interessant ist, weil es endlich mehr als nur eine akademische Fingerübung darstellt, und eine Menge interessanter Punkte bietet, die es als möglichen Ersatz für Node.js positionieren könnten. Der Zeitpunkt dafür ist sogar günstig, denn bei Node.js häufen sich die Probleme: Es entwickelt sich zwar weiter, aber es gibt zu viele angefangene Baustellen und es wird immer chaotischer. Deshalb war der Titel eines unserer Videos vor rund sechs Monaten auch schon: "Node 22, lass uns Freunde bleiben [8]". Auf gut Deutsch: Ich habe keine Lust mehr auf eine Beziehung mit dir, ich mache Schluss!
Und da kommt nun eben Deno 2 ins Spiel. Das Besondere an Deno 2 ist, dass das Team dahinter sich große Mühe gegeben hat, die mangelnde Kompatibilität zu Node.js und npm zu überwinden. Ab Deno 2 ist es nun möglich, Deno als echtes Drop-in-Replacement zu nutzen. Das Versprechen lautet: Alles, was in Node.js läuft, läuft auch in Deno. Das gilt für kleine und große Anwendungen und bezieht viele Frameworks wie Next.js, Astro, Remix, Angular, SvelteKit und mehr ein – alles läuft out of the box. Aber Deno ist nicht einfach eine 1:1-Kopie von Node.js geworden, sondern ist in gewissem Sinne inzwischen "das bessere Node".
Denn Deno bringt (nicht erst seit Version 2) eine Reihe von Features mit, von denen Node.js nur träumen kann: native TypeScript-Unterstützung (die gibt es in Node.js inzwischen, allerdings ist sie noch sehr rudimentär), ein eingebauter Formatter, ein integrierter Linter, ein Type-Checker, ein Test-Framework, ein Compiler, ein sinnvolles Sicherheitskonzept, bei dem nicht jeglicher Code aus dem Internet ungefragt mit Full-Trust läuft, und so weiter. All das fehlt Node.js seit nunmehr 15 Jahren. Und dabei ist das Ganze in Deno auch noch sehr schnell und durchdacht umgesetzt.
Ein Beispiel: In Deno muss TypeScript-Code nicht von Hand kompiliert werden, das erledigt Deno automatisch, sobald die Anwendung gestartet wird. Aus Performance-Gründen wird dabei allerdings auf die Typprüfung von TypeScript verzichtet, es sei denn, sie wird explizit mit dem Parameter --check angefordert. Bei der Ausführung von Tests hingegen ist die Typprüfung standardmäßig aktiv. Das ergibt Sinn: Während der Entwicklung, wenn es nicht auf das letzte Quäntchen Performance ankommt, hat man die gewünschte Typsicherheit, bei der Ausführung dafür eine möglichst gute Performance. Und das Schöne ist, dass das Test-Framework in Deno bereits enthalten ist, es muss also nichts zusätzlich installiert werden.
Node.js bietet ein paar Aspekte davon inzwischen zwar ebenfalls, aber es hat sehr lange gedauert, und es kommt weder vom Umfang noch von der Integration an Deno heran. Und Deno endet hier nicht: Das Test-Framework geht beispielsweise deutlich weiter als das von Node, denn Deno kann direkt auch die Code-Coverage berechnen, Benchmarks ausführen und mehr.
All diese Funktionen, um Tests auszuführen, Code-Coverage zu ermitteln und Benchmarks durchzuführen, sind im Deno-Binary von Haus aus enthalten. Man braucht also nur ein einziges Tool, um all diese Dinge nutzen zu können. Darüber hinaus ist zum Beispiel aber auch noch ein Formatter integriert, der nicht nur JavaScript und TypeScript, sondern auch HTML, CSS und YAML formatiert. Ein umfangreicher Linter ist ebenfalls enthalten, eine integrierte Lösung zum Ausführen von Tasks, ein Dokumentationsgenerator und ein Compiler, um echte Binaries zu erzeugen. Letzteres ist bei Node.js zwar in der Theorie auch möglich [9], jedoch dermaßen umständlich gelöst, dass es absolut keinen Spaß macht, das Feature zu nutzen.
Deno enthält außerdem einen Webserver, Unterstützung für Jupyter-Notebooks und vieles mehr – und all das in einer einheitlichen und aufeinander abgestimmten Form, während man bei Node alles mühsam zusammensuchen und von Hand konfigurieren muss. Und das ist am Ende das, wodurch Deno 2 besonders auffällt: Einfachheit und "it just works".
Hat man beispielsweise eine Anwendung, die npm-Module verwendet, muss man bei Deno kein "npm install" mehr ausführen. Deno lädt die benötigten Module beim ersten Start der Anwendung automatisch herunter und cacht sie lokal. Das funktioniert so gut und transparent im Hintergrund, dass man beim Entwickeln nach einer halben Stunde vergessen hat, dass man jemals "npm install" ausführen und sich mit einem node_modules-Verzeichnis oder einer Lock-Datei herumschlagen musste. Und das alles geht dabei auch noch unglaublich schnell – jeder Package-Manager, den ich bisher unter Node.js gesehen habe, kann da im Vergleich einpacken. Das ist wirklich gut gelöst, und das ist der Eindruck, den Deno 2 hinterlässt: Es wirkt wie Node.js, aber neu durchdacht.
Vielleicht war Deno 1 in den vergangenen sechs Jahren so gesehen einfach nur ein Proof of Concept: Ein nicht schöner, aber notwendiger Prototyp, um herauszufinden, wohin die Reise eigentlich gehen soll, und Deno 2 ist nun die echte erste Version.
Und da muss ich ganz ehrlich meinen Respekt aussprechen, denn Deno 2 ist eine sehr gelungene zweite Version. Auf einmal macht es wieder Spaß, mit TypeScript zu entwickeln, weil man nicht hundert verschiedene Dinge installieren und konfigurieren muss, sondern einfach nur einen Editor öffnet, ein paar Zeilen schreibt und ausführt. Und formatiert. Und testet. Und so weiter. Und all das, ohne auch nur ansatzweise irgendetwas dafür installieren zu müssen.
Im Vergleich dazu, wie sich Node.js aktuell anfühlt, ist das ein großer Schritt nach vorn. Es fühlt sich endlich wieder modern und zeitgemäß an. Und insofern muss ich sagen: Sobald die passende Laufzeitumgebung da ist, macht TypeScript auf einmal wieder eine Menge Spaß. Danke, Deno 2!
URL dieses Artikels:
https://www.heise.de/-9987604
Links in diesem Artikel:
[1] https://www.youtube.com/@thenativeweb
[2] https://deno.com/blog/v2.0
[3] https://www.youtube.com/watch?v=M3BM9TB-8yA
[4] https://www.youtube.com/watch?v=7oeR1GcVK3Y
[5] https://www.heise.de/Datenschutzerklaerung-der-Heise-Medien-GmbH-Co-KG-4860.html
[6] https://www.youtube.com/watch?v=WLklm8JQbjo
[7] https://www.heise.de/news/JavaScript-Runtime-Deno-2-0-nimmt-es-mit-Node-js-auf-9976092.html
[8] https://www.youtube.com/watch?v=GH8gSl-z9Wg
[9] https://www.youtube.com/watch?v=6ThplMUASJA
[10] mailto:rme@ix.de
Copyright © 2024 Heise Medien
(Bild: erstellt mit KI (Dall-E) von iX-Redaktion)
Viele Softwareprojekte sprengen sowohl den zeitlichen als auch den finanziellen Rahmen und liefern dann nachher trotzdem nicht das gewünschte Ergebnis. Warum?
Wussten Sie, dass ungefähr 75 Prozent aller Softwareprojekte scheitern? Entweder dauern sie länger als ursprünglich geplant oder sie kosten mehr als erwartet (oder beides) und liefern trotzdem nicht das gewünschte Ergebnis. Das bedeutet, sie verfehlen das eigentliche Ziel. Da stellt sich natürlich die Frage: Woran liegt das eigentlich und was kann man als Team beziehungsweise als Unternehmen machen, um das bei eigenen Projekten zu vermeiden?
Bevor ich im Folgenden tiefer in das Thema einsteige, vorweg noch ein kleiner Hinweis: Die 75 Prozent sind natürlich nicht in Stein gemeißelt. Je nachdem, welche Studie man zurate zieht, sind es mal mehr, mal weniger Prozent. Aber selbst wenn es "nur" 50 Prozent wären, hieße das immer noch, dass jedes zweite Softwareprojekt Probleme hat. Und wenn man sich dann einmal überlegt, wie viel in unserer heutigen modernen Welt von Software abhängt, dann ist das so oder so schon ganz schön viel. Insofern: Nehmen Sie die 75 Prozent bitte nicht wortwörtlich, sondern als Tendenz und als ungefähre Größenordnung.
Warum also scheitern so viele Softwareprojekte und sprengen häufig zeitliche und finanzielle Rahmen? Das ist eine durchaus spannende Frage, denn an der eigentlichen Planung kann es kaum liegen: Teams und Unternehmen verbringen häufig sehr viel Zeit damit, sich Gedanken über die richtige Technologie zu machen. Da wird dann gerne wochen- oder gar monatelang diskutiert, ob nun zum Beispiel .NET oder Go vorzuziehen sei, ob React oder Web-Components die bessere Wahl sei, ob man eine SQL- oder eine NoSQL-Datenbank nehmen sollte, ob man MQTT brauchen wird oder nicht, und so weiter. Mit anderen Worten: Es wird viel Zeit mit der Evaluation und Auswahl von Technologien verbracht und daran sind üblicherweise viele kluge Köpfe beteiligt. Daher ist es eher unwahrscheinlich, dass dies das Problem ist.
Allerdings liegt es häufig auch nicht an der gewählten Architektur. Denn auch hier wird in der Regel sehr ausführlich und sorgfältig diskutiert: Es werden die Vor- und Nachteile von Monolithen, Microservices und Co. verglichen, es wird über REST, GraphQL und gRPC debattiert und architektonische Entscheidungen werden selten leichtfertig getroffen, sondern erst nach sorgfältiger Abwägung vieler Argumente. Auch die Architektur ist also häufig nicht das eigentliche Problem.
Am ehesten gerät als Nächstes dann der verwendete Entwicklungsprozess in Verdacht. Doch hier gibt es gar nicht dermaßen viele Unterschiede, wie man häufig zunächst meinen würde, denn viele Teams nutzen einfach Scrum, allein schon deshalb, weil sie Teil eines größeren Unternehmens sind und Scrum dort fest gesetzt ist. Bei Scrum im Speziellen und Agilität im Allgemeinen kann man zwar einiges falsch machen [2], aber andererseits gibt es auch immer wieder Teams, die erfolgreich agil arbeiten und bei denen man den Eindruck hat, dass Agilität verstanden wurde. Trotzdem bleibt die Softwareentwicklung am Ende oft eher mittelprächtig. Selbst wenn der Prozess nicht optimal ist, scheint er dennoch nicht das Hauptproblem zu sein.
Bleibt die Entwicklung an sich: Hier arbeiten in der Regel allerdings auch viele erfahrene und kompetente Menschen, die sich mit der gewählten Technologie gut auskennen. Wer sich beispielsweise für .NET, Web-Components und den SQL Server entscheidet, stellt in der Regel auch sein Team entsprechend so auf, dass es aus Menschen besteht, die mit diesen Technologien möglichst vertraut sind. Doch auch das garantiert erfahrungsgemäß nicht, dass die Softwareentwicklung später tatsächlich im Zeit-, Budget- und Funktionsrahmen bleibt. Wenn es also auch nicht an der Entwicklung selbst liegt – was bleibt dann noch?
Hier kommt ein Thema ins Spiel, das unglaublich gerne übersehen wird: Das Problem in der Softwareentwicklung sind in der Regel nämlich nicht die technischen Faktoren. Damit will ich nicht sagen, dass es keine technischen Schwierigkeiten gäbe, wie eine weniger geeignete Architektur oder unzureichendes technologisches Wissen. Tatsächlich ist das aber selten das Hauptproblem. Viel häufiger ist es so, dass vor lauter Technologie etwas anderes vernachlässigt wird – nämlich die Fachlichkeit. Ich kann gar nicht sagen, wie viele Teams ich schon kennengelernt habe, die technologisch topfit waren, die aber leider absolut keine Ahnung davon hatten, worum es in ihrem Projekt inhaltlich eigentlich ging.
Das merkt man immer, wenn man wie ich als externer Berater zu einem solchen Team stößt und die erstbeste Verständnisfrage stellt, wenn dann alle große Augen machen, niemand antworten kann (weil niemand die Antwort weiß) und man dann gesagt bekommt, dass diese Frage noch nie jemand gestellt hätte. Und es handelt sich dabei nicht um exotische Fragestellungen, sondern oft um elementare Grundlagen. Zum Beispiel bei einem Team, das Software für die Personalabteilung entwickelt, die Frage:
"Wie sieht der Prozess für eine Einstellung aus?"
Wenn schon diese Frage niemand beantworten kann, wie soll ein Team dann eine Software entwickeln, die dieses Thema adäquat und zielgerichtet digital abbildet? Um es kurz zu machen: Das kann nicht funktionieren!
Mit anderen Worten: Softwareentwicklung ist kein Selbstzweck. Wir als IT-Branche entwickeln Software nicht deshalb, weil es so toll ist, Software zu entwickeln, sondern weil wir ein tieferliegendes fachliches Problem lösen wollen. Damit eine Software ein Problem adäquat und zielgerichtet lösen kann, muss man jedoch als Entwicklerin oder Entwickler das zugrunde liegende fachliche Problem überhaupt erst einmal verstehen. Das heißt, man muss wissen, worum es geht, welche Prozesse es gibt, was die Rahmenbedingungen sind, wie der Kontext aussieht, um welche Daten es geht und was das alles im Detail für die Menschen bedeutet.
Das sind Fragen, die häufig nicht gestellt werden. Es wird einfach davon ausgegangen, dass das nicht so wichtig sei, dass sich das schon im Laufe der Zeit von selbst ergeben würde, dass es genüge, wenn der Product Owner Bescheid wisse und so weiter. Doch immer wieder stellt sich heraus, dass das nicht funktioniert.
Das führt dann dazu, dass in einem Team weder eine gemeinsame Sprache noch ein gemeinsames Verständnis der fachlichen Thematik existiert. Es wird zwar viel geredet, aber oft aneinander vorbei, weil niemand das Gegenüber wirklich versteht. Und anstatt nachzufragen, werden implizite Annahmen getroffen, und man lebt zu lange in dem Glauben, man wüsste, worum es eigentlich ginge. Wenn zwei Leute am selben Thema arbeiten und keine gemeinsame Sprache und kein gemeinsames Verständnis haben, wird es jedoch schwierig. Es werden unterschiedliche Begriffe für dasselbe Konzept genutzt, ohne zu wissen, ob wirklich alle das Gleiche meinen. Oder es wird ein Begriff verwendet, der von allen unterschiedlich interpretiert wird, was aber niemandem auffällt. Man bewegt sich in einer schwammigen, unklaren sprachlichen Blase und nimmt das als völlig normal hin.
Und dann wundert man sich, dass nach zwei Jahren nicht das herauskommt, was jemand anderes sich zwei Jahre zuvor vorgestellt hat. Ganz ehrlich: Es ist naiv anzunehmen, dass das jemals hätte funktionieren können. Ist es erst einmal so weit gekommen, muss nachgebessert werden. Das kostet Zeit und Geld. Und damit dauert es auf einmal länger und kostet mehr als geplant. Da man nach zwei Jahren aber nicht einfach alles über den Haufen werfen möchte, arbeitet man eher an den Symptomen als an den Ursachen.
Das heißt, wenn mit falschen Grundkonzepten gestartet wurde, bleiben diese nun erhalten, weil man sie nicht mehr überarbeiten kann, da der Aufwand dafür zu hoch wäre. So entsteht Software, die von vornherein nicht passend ist, und man startet von Anfang an mit einer Lösung, bei der alle insgeheim wissen, dass man es eigentlich viel besser hätte machen können. Nur spricht das niemand laut aus. Stattdessen kommt dann irgendjemand daher und sagt:
"Ich hab's Euch ja prophezeit: Wir hätten damals doch auf Go statt .NET setzen sollen, aber das wollte ja keiner hören!"
Und alle stehen da, nicken betroffen und denken:
"Ja, stimmt, wenn wir heute noch mal neu anfangen könnten, dann wäre alles besser!"
Aber der Punkt ist: Es wäre nur kurzfristig besser, weil man wieder ohne Altlasten auf der "grünen Wiese" starten würde, aber langfristig würde man wieder dieselbe, nicht passende Software entwickeln, weil man erneut nicht verstanden hat, was das zugrunde liegende fachliche Problem ist. Man tauscht quasi die Technologie, aber die Technologie war nie das Problem. Ich glaube, es war Albert Einstein, der (sinngemäß) einmal gesagt hat:
"Immer wieder dasselbe zu tun und ein anderes Ergebnis zu erwarten, ist die Definition von Dummheit."
Wenn wir das doch aber wissen – warum versuchen wir als Branche dann immer und immer wieder, Software ohne fachliches Verständnis zu entwickeln?
Wenn wir also bessere Software entwickeln wollen, wenn wir Software in kürzerer Zeit fertigstellen wollen, dann müssen wir weniger über Technologie und viel mehr über Fachlichkeit sprechen. Wir müssen sicherstellen, dass alle am Projekt Beteiligten von Anfang an ein gemeinsames Verständnis der Thematik haben. Damit sage ich nicht, dass wir nicht mehr über Technologien sprechen sollten. Damit sage ich auch nicht, dass jede Entwicklerin und jeder Entwickler zum absoluten Fachexperten werden muss. Aber es hilft, wenn zumindest ein solides Grundwissen vorhanden ist, weil man ein Feature viel passgenauer umsetzen kann, wenn man versteht, was es macht, wer es verwendet, welchem Zweck es dient und so weiter. Die Frage ist also: Wie schafft man es, eine solche gemeinsame fachliche Sprache und ein gemeinsames Verständnis im Team zu etablieren?
Tatsächlich ist das gar nicht so schwierig, wie man vielleicht glaubt, es ist eher nur zeitaufwendig. Das Fundament von allem ist eine gute Kommunikation, in der man sich über die Fachlichkeit austauscht: Es wird erklärt, es werden Verständnisfragen gestellt, Dinge werden hinterfragt. Und zwar übergreifend über alle im Team beteiligten Disziplinen hinweg. Also echte interdisziplinäre Zusammenarbeit und kein disziplinäres Schubladendenken.
Und es gibt so viele Hilfsmittel dafür: Das fängt beim aktiven und aufmerksamen Zuhören an, geht über kritisches Mitdenken und Nachfragen, dazu gehören Empathie, echte Neugier und ehrliches Interesse. Es gibt Werkzeuge wie Domain-driven Design, Design Thinking, das Arbeiten mit Events, das Beschäftigen mit Semantik, mit natürlicher Sprache und vieles mehr. Was all diese Punkte jedoch gemeinsam haben, ist, dass sie keine technischen Hilfsmittel sind.
Das heißt, die eine essenzielle Voraussetzung ist, dass man aus der bequemen technologischen Komfortzone herauskommt, in der man es sich seit Jahren gemütlich gemacht hat, und dass man den Sprung ins kalte Wasser wagt, sich die Blöße gibt, einzugestehen, dass man von der Fachlichkeit keine Ahnung hat – aber ehrlich interessiert ist und neugierig auf das, was da in einer neuen Welt vor einem liegt. Diesen Schritt zu machen, ist ungemein wichtig, aber er fällt vielen unglaublich schwer.
Und das liegt nicht daran, dass Entwicklerinnen und Entwickler nicht wollen würden. Sondern es liegt daran, dass das in vielen Aspekten mit dem bricht, was man in der Ausbildung gelernt hat. Plötzlich sind nicht mehr Daten und Objekte die wesentlichen Konstrukte, um einen Sachverhalt zu strukturieren. Plötzlich sind es Geschäftsprozesse und Abläufe. Es ist der Wandel von einer rein statischen, datengetriebenen Welt hin zu einer dynamischen, prozessgetriebenen Welt. Denn wir schreiben Software nicht, um Daten zu verwalten. Wir schreiben Software, um Prozesse abzubilden. Dass dafür Daten benötigt werden, versteht sich von selbst. Aber Daten spielen in dieser Welt nicht die erste Geige, genauso wenig wie die Technologie die erste Geige spielen sollte, sondern eben die Fachlichkeit. Es geht nicht um Daten, sondern um Prozesse. Das, was Software lebendig macht, sind nicht die Daten, sondern die Funktionen. Und das ist die entscheidende Änderung in der Perspektive.
Betrachten Sie die Welt als eine Ansammlung von Daten, die verwaltet werden müssen, dann wird Ihre Software letztlich immer nur Excel mit einer mehr oder weniger anderen Bedienoberfläche sein, die die Anwenderinnen und Anwender nicht wirklich in ihren Aufgaben und Intentionen unterstützt. Um das nämlich zu erreichen, müssen Sie die Intentionen verstehen, Sie müssen die Abläufe und die Prozesse verstehen. Denn nur dann können Sie die Prozesse adäquat in Ihrer Software abbilden und Menschen das Leben vereinfachen. Und darum geht es letztlich bei der Softwareentwicklung: Das Leben von Menschen in irgendeiner Form angenehmer, sicherer, komfortabler – im weitesten Sinne irgendwie "besser" zu machen. Und Technologie ist dafür ein notwendiges Werkzeug, ein Mittel zum Zweck. Aber Technologie ist kein Selbstzweck.
Wenn Sie mehr über diese Sichtweise auf die Welt der Softwareentwicklung erfahren möchten, habe ich abschließend noch zwei Tipps für Sie: Erstens, schauen Sie sich das Video "CRUD? Bloß nicht! [3]" an. Und zweitens: Raffen Sie sich auf, die rein technologische Komfortzone zu verlassen und stürzen Sie sich in die zuvor genannten Themen, um der Fachlichkeit einen höheren Stellenwert zu geben. Holen Sie sich im Zweifelsfall Unterstützung von außen, um das Vorgehen zu beschleunigen, aber egal ob mit oder ohne: Das Wichtigste ist, dass Sie den ersten Schritt in dieser Richtung machen. Viel Erfolg!
URL dieses Artikels:
https://www.heise.de/-9979648
Links in diesem Artikel:
[1] https://www.heise.de/Datenschutzerklaerung-der-Heise-Medien-GmbH-Co-KG-4860.html
[2] https://www.youtube.com/watch?v=iQK620MY_48
[3] https://www.youtube.com/watch?v=MoWynuslbBY
[4] mailto:rme@ix.de
Copyright © 2024 Heise Medien
(Bild: erstellt mit KI (Dall-E) von iX-Redaktion)
Die umfangreiche Serie mit Blogbeiträgen zu .NET 8.0 und den Neuerungen in C# 12 geht zwei Monate vor dem Release von .NET 9.0 zu Ende.
In den letzten 40 Wochen habe ich Ihnen jede Woche ein neues Feature aus .NET 8.0 vorgestellt. Es gab kleinere und größere Neuigkeiten in der Programmiersprache C#, der .NET-Basisklassenbibliothek und dem .NET Software Development Kit (SDK).
Auch wenn ich nicht alle neuen Features vorgestellt habe, möchte ich diese Serie nun enden lassen und mich in den kommenden Wochen darauf konzentrieren, meine Fachbücher zu C# [1], Blazor [2] und Entity Framework Core [3] auf den Stand von .NET 9.0 zu bringen.
.NET 9.0 ist seit dieser Woche im Stadium "Release Candidate 2" [4] und mit einer "Go-Live"-Lizenz ausgestattet. Die fertige Version soll am 12. November 2024 erscheinen. Die oben genannten Bücher will ich bis dahin auf dem aktuellen Stand haben, sodass diese wie in den Vorjahren pünktlich zum Erscheinungstermin verfügbar sind.
Aktuell gibt es von mir das Buch .NET 9.0 Update [8], das auf dem Stand des Release Candidate 2 ist und auf 170 Seiten die Neuerungen gegenüber .NET 8.0 beschreibt.
.NET 8.0 hat noch Long-Term Support bis zum November 2026. Es besteht also kein Zwang, auf .NET 9.0 zu wechseln. Das kommende .NET-Release wird mit Standard-Term Support von Microsoft von November 2024 bis Mai 2026 mit Updates versorgt werden. Zwischenzeitlich ist für November 2025 dann .NET 10.0 geplant.
Ab Dezember plane ich eine neue Blogserie mit den Neuerungen aus .NET 9.0.
URL dieses Artikels:
https://www.heise.de/-9977510
Links in diesem Artikel:
[1] https://it-visions.de/Csharpbuch
[2] https://it-visions.de/Blazorbuch
[3] https://it-visions.de/EFCorebuch
[4] https://www.heise.de/news/Jetzt-schon-einsetzen-NET-9-0-Release-Candidate-2-mit-Go-Live-Lizenz-9974342.html
[5] https://net.bettercode.eu/?wt_mc=intern.academy.dpunkt.konf_dpunkt_bcc_net.empfehlung-ho.link.link
[6] https://net.bettercode.eu/index.php?wt_mc=intern.academy.dpunkt.konf_dpunkt_bcc_net.empfehlung-ho.link.link#programm
[7] https://net.bettercode.eu/tickets.php?wt_mc=intern.academy.dpunkt.konf_dpunkt_bcc_net.empfehlung-ho.link.link
[8] https://www.it-visions.de/buch/n9U
[9] mailto:rme@ix.de
Copyright © 2024 Heise Medien
(Bild: erstellt mit KI (Dall-E) von iX)
Das WebAssembly System Interface (WASI) wird durch Microsoft nun mit einem eigenen SDK unterstützt – aber weiterhin im Status "experimentell".
Das WebAssembly System Interface (WASI) ist ein Standard, um WebAssembly-Bytecode-basierte Anwendungen plattformneutral außerhalb des Webbrowsers zu betreiben. WASI wurde am 27. März 2019 erstmals öffentlich bekanntgegeben [1] und wird in einer Untergruppe der WebAssembly-Gruppe beim W3C [2] (World Wide Web Consortium) standardisiert.
Schon seit dem 25. März 2022 bot Microsoft eine experimentelle Implementierung für WASI-basierte Anwendungen mit .NET 7.0 – zunächst aber nur in einem GitHub-Repository eines Microsoft-Mitarbeiters [3].
Seit .NET 8.0 ist das Projekt als experimenteller Workload für das .NET SDK verfügbar.
Den Workload installiert man folgendermaßen:
dotnet workload install wasi-experimental
Eine neue WASI-basierte Konsolenanwendung legt man danach an mit
dotnet net wasiconsole
oder in Visual Studio:
(Bild: Screenshot (Holger Schwichtenberg))
Folgender Code zeigt eine Konsolenanwendung, die einige Systeminformationen ausgibt:
// WASI-Demo (C) Dr. Holger Schwichtenberg, 2022
Console.WriteLine(System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription + "' sagt 'Hallo' via WebAssembly/WASI!");
Console.WriteLine("OS Description: " + System.Runtime.InteropServices.RuntimeInformation.OSDescription);
Console.WriteLine("OS Architecture: " + System.Runtime.InteropServices.RuntimeInformation.OSArchitecture);
Console.WriteLine("OS Version: " + System.Environment.OSVersion);
Console.WriteLine("Machine Name: " + System.Environment.MachineName);
Console.WriteLine("Current User: " + System.Environment.UserDomainName + "\\" + System.Environment.UserName);
Console.WriteLine("Process Path: " + System.Environment.ProcessPath);
Console.WriteLine("Current Directory: " + System.Environment.CurrentDirectory);
Console.WriteLine("Process ID: " + System.Environment.ProcessId);
Console.WriteLine("64 Bit: " + System.Environment.Is64BitProcess);
Console.WriteLine("Working Set: " + System.Environment.WorkingSet);
foreach (var d in System.Environment.GetLogicalDrives())
{
Console.WriteLine("Drive: " + d);
}
Das WASI-Projekt im folgenden Code basiert auf einer normalen .NET-8.0-Konsolenanwendung mit dem RuntimeIdentifier wasi-wasm:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifier>wasi-wasm</RuntimeIdentifier>
<OutputType>Exe</OutputType>
<PublishTrimmed>true</PublishTrimmed>
</PropertyGroup>
</Project>
Beim Übersetzen (siehe nächste Abbildung) entsteht nicht nur eine DLL, sondern auch eine WebAssembly-Bytecode-Datei (.wasm), die ca. 11 MB groß ist.
Diese .wasm-Datei enthält die komplette WASI-Anwendung inklusive .NET-Laufzeitumgebung; die DLL ist zur Laufzeit ebenso wenig wie die Installation der .NET Runtime zur Ausführung notwendig. Allerdings kann man eine .wasm-Datei bisher in keinem der üblichen Betriebssysteme direkt starten; man benötigt eine WASI-Laufzeitumgebung wie Wasmtime von der Bytecode Alliance [4] oder Wasmer [5].
Die nächsten Abbildungen zeigen die Ausführung mit Wasmtime, das für Windows in einer rund 10 MB großen .exe-Datei geliefert wird. Man sieht, dass die Anwendung in einer Sandbox läuft und derzeit auch noch vom Betriebssystem und Benutzer "Browser" spricht, auch wenn gar kein Browser im Spiel ist. Die Prozess-ID ist immer 42. Das WASI SDK von Microsoft erlaubt auch die Verwendung von ASP.NET Core, das heißt, man kann eine Webserver-Anwendung auf Basis von WebAssembly-Bytecode schreiben.
(Bild: Screenshot (Holger Schwichtenberg))
(Bild: Screenshot (Holger Schwichtenberg))
URL dieses Artikels:
https://www.heise.de/-9962217
Links in diesem Artikel:
[1] https://hacks.mozilla.org/2019/03/standardizing-wasi-a-webassembly-system-interface/
[2] https://github.com/WebAssembly/WASI/blob/main/Charter.md
[3] https://github.com/SteveSandersonMS/dotnet-wasi-sdk
[4] https://github.com/bytecodealliance/wasmtime
[5] https://wasmer.io
[6] https://net.bettercode.eu/?wt_mc=intern.academy.dpunkt.konf_dpunkt_bcc_net.empfehlung-ho.link.link
[7] https://net.bettercode.eu/index.php?wt_mc=intern.academy.dpunkt.konf_dpunkt_bcc_net.empfehlung-ho.link.link#programm
[8] https://net.bettercode.eu/tickets.php?wt_mc=intern.academy.dpunkt.konf_dpunkt_bcc_net.empfehlung-ho.link.link
[9] mailto:rme@ix.de
Copyright © 2024 Heise Medien