FreshRSS

🔒
❌ Über FreshRSS
Es gibt neue verfügbare Artikel. Klicken Sie, um die Seite zu aktualisieren.
Vor vorgesternIhre RSS-Feeds

Spielerisch Assembler lernen

Von Golo Roden

(Bild: Semisatch/Shutterstock.com)

Das Buch "Einführung in die moderne Assembler-Programmierung" von Scot W. Stevenson bietet eine solide Einführung in Assembler auf Basis der RISC-V-Architektur.

Endlich ist es so weit – heute stelle ich Ihnen ein Buch vor, auf das ich seit Monaten sehnsüchtig und gespannt gewartet habe. Das Thema des Buches ist für das Jahr 2024 allerdings ein wenig ungewöhnlich, denn es handelt sich um eine Einführung in die moderne Assembler-Programmierung. Vielleicht fragen Sie sich nun, warum Sie sich ausgerechnet mit Assembler beschäftigen sollten, doch dazu gleich mehr. Vor allem geht es mir in diesem Blogpost aber um die Frage, ob sich die Lektüre des Buches meiner Meinung nach lohnt. Legen wir los!

Das Buch heißt "Einführung in die moderne Assembler-Programmierung [1]" und trägt den Untertitel "RISC-V spielerisch und fundiert lernen". Geschrieben wurde es von Scot W. Stevenson und ist im Juli 2024 im dpunkt-Verlag [Anm. d. Red.: Ein Verlag der heise group] erschienen. Der Verlag war so freundlich, mir ein Rezensionsexemplar kostenlos zur Verfügung zu stellen. Es ist uns aber wichtig zu betonen, dass meine Meinung in diesem Blogpost nicht mit dem Verlag abgestimmt ist. Es handelt sich um meine persönliche und ehrliche Einschätzung, und ich erhalte keine Gegenleistung für die Rezension. Das ist uns wichtig offenzulegen, weil eine Rezensionen vertrauenswürdig sein sollte, und das nur dann gewährleistet ist, wenn ich frei sagen kann, was mir gefällt und was nicht. Das nur kurz vorab.

Warum ausgerechnet Assembler?

Bevor wir nun ins Buch einsteigen, vielleicht erst noch kurz die Frage: Warum sollte man sich im Jahr 2024 ausgerechnet mit Assembler-Programmierung beschäftigen? Gibt es da nichts Wichtigeres? Genau diese Frage stellt auch der Autor im Vorwort:

"Ein modernes Buch über Assembler-Programmierung, was soll das denn?"

Der Autor ist sich also bewusst, dass das Thema durchaus erklärungsbedürftig ist. Er schreibt, dass es zum einen diejenigen gebe, die im Studium dazu gezwungen würden, sich mit Assembler zu beschäftigen. Zum anderen gebe es aber auch diejenigen, die der Meinung seien, dass das Verständnis von Assembler zu einem besseren Verständnis für Computer an sich führen würde. Beides sind durchaus legitime Gründe, das Buch zu lesen, aber: Das Buch ist vor allem für eine dritte Zielgruppe geschrieben – nämlich für diejenigen, die Spaß daran haben, in die Interna abzutauchen und aus Neugier und Wissensdurst verstehen möchten, wie die Dinge unter der Haube funktionieren. Ich finde, das ist eine schöne und ehrliche Beschreibung, von der ich mich durchaus angesprochen fühle.

Nicht alles, was man lernt, muss meiner Meinung nach immer einen direkten Nutzen haben. Es macht zumindest mir auch sehr viel Spaß, mich mit gewissen Dingen um ihrer selbst willen zu beschäftigen, und Nullen und Einsen gehören für mich definitiv dazu. Insofern fördert das Buch vielleicht nicht direkt Ihre Karriere, aber es könnte Ihren intellektuellen Spieltrieb ansprechen und vielleicht sogar Ihren Horizont erweitern. Unabhängig davon glaube ich aber auch, dass ein gewisses Verständnis von Assembler dazu führt, die Maschine, mit der wir alle uns täglich beschäftigen, besser zu verstehen.

Mein Bezug zu Assembler

Ich selbst habe vor vielen Jahren einmal versucht, x86-Assembler zu lernen. Über ein paar Grundlagen verfüge ich daher, aber wirklich tief bin ich nie eingestiegen. Allerdings habe ich großen Respekt davor, wenn jemand Assembler wirklich beherrscht. Im März hatte ich in einem unserer Livestreams eine Entwicklerin zu Gast, die mit mir gemeinsam den Assembler-Quellcode des Computerspiels "Prince of Persia" analysiert hat [3]. Genauer gesagt, hat sie den Code analysiert und ich habe interessiert Fragen dazu gestellt. Das fand ich sehr spannend, und genau daran knüpft dieses Buch inhaltlich perfekt an. Mit anderen Worten: Falls Sie den Livestream gesehen haben und er Ihnen gefallen hat, dürfte auch das Buch Ihr Interesse wecken und Ihren Geschmack treffen.

Nun aber endlich zum Buch: Es hat etwas mehr als 250 Seiten (es ist also eher kompakt) und ist in 25 Kapitel gegliedert, die sich über fünf Teile erstrecken. Der erste Teil behandelt zunächst eine Reihe von Grundbegriffen und grundlegenden Konzepten: Wie funktionieren negative Zahlen im Binärsystem? Was ist ein Register? Was ist der Unterschied zwischen der CPU und der ALU? Was ist CISC, was ist RISC, was ist ein Opcode, was ein Mnemonic?

Die Maschine als Grundlage

Auf den ersten rund 70 Seiten geht es also darum, eine gemeinsame Sprache und ein grundlegendes Verständnis für die Ebene zu schaffen, auf der man mit Assembler arbeitet, mit der man aber im Alltag nicht so oft in Berührung kommt. Vieles kannte ich von vor zig Jahren, trotzdem fand ich es spannend, es noch einmal zu lesen, weil es ein guter Überblick war. Schön herausgearbeitet wird, dass Assembler zwar prinzipiell überall ähnlich ist, die konkrete Umsetzung aber stark von der Prozessorarchitektur und dem zugehörigen Befehlssatz abhängt. Das Buch behandelt den offenen RISC-V-Standard, zeigt aber anhand von Beispielen auch, wie Dinge auf anderen Architekturen gelöst werden. Das vermittelt gut, dass man mit Assembler auf zwei Ebenen arbeitet, nämlich einer abstrakt-konzeptionellen Ebene sowie einer technisch-konkreten Ebene, die sich von Prozessor zu Prozessor unterscheidet.

Der zweite Teil startet anschließend mit einem Überblick über die einzelnen Module von RISC-V. Dabei geht es um die zur Verfügung stehenden Register, die Wortgröße, die Adressierungsarten und dann vor allem um den tatsächlichen Befehlssatz. Hier werden relativ zügig die diversen Befehle vorgestellt und erklärt, beginnend bei einfachen Aufgaben wie dem Laden und Speichern von Daten, über das Rechnen bis hin zu Vergleichen, Bedingungen und Schleifen. Auch Pseudo-Befehle und Spezialfälle werden angesprochen, sowie der interne Aufbau der Befehle. Dieser Teil geht also tief in die Materie hinein, und das ist zugleich eine Stärke und eine Schwäche des Buches: Einerseits erhält man nämlich einen kompletten Überblick über die RISC-V-Befehle, andererseits ist dieser Abschnitt eher eine Referenz als ein Lehrbuch. Man liest es, übt es aber nicht, was dazu führt, dass man später im Buch zurückblättern und ständig hin- und herspringen muss.

Clean Code mit Assembler

In Teil drei geht es dann um die Vertiefung des bis dahin Gelernten, indem man die Grundbausteine zu größeren Einheiten zusammenfügt. Natürlich könnte man dies auch auf naive Weise tun, aber es empfiehlt sich, hier von erfahreneren Entwicklerinnen und Entwicklern zu lernen. Dabei geht es um Themen wie:

  • Wie schreibe ich effizienten Code?
  • Wie strukturiere ich Vergleiche und Verzweigungen?
  • Wie schreibe ich Schleifen?
  • Wie implementiere ich Multiplikation und Division?
  • Wie integriere ich Systemaufrufe in Assembler und wie interagiere ich mit der Standard-C-Bibliothek?

Ein wenig schwierig fand ich in diesem Teil die gewählte Reihenfolge der Kapitel, die etwas willkürlich wirkt. Im Großen und Ganzen passt es aber trotzdem, denn es handelt sich letztlich ohnehin um ein Sammelsurium diverser Best Practices, die keine natürliche Reihenfolge aufweisen.

Ab in die Praxis!

Damit sind dann auch schon 85 bis 90 Prozent des Buches gelesen, aber es gibt noch zwei weitere Teile: In Teil vier geht es um konkrete Projekte. Dieser Teil umfasst allerdings nur 25 Seiten für sage und schreibe zwei Projekte. Tatsächlich ist das für mich die größte Schwäche des Buches: Die Praxis kommt viel zu kurz. Für ein Buch mit dem Untertitel "RISC-V spielerisch und fundiert lernen" fehlt mir der spielerische Aspekt. Die ersten 225 Seiten erklären praktisch die Grammatik und Vokabeln einer neuen Fremdsprache, aber man kommt erst am Ende dazu, einen einfachen Satz zu sagen. Das finde ich schade, da hätte ich mir einen praxisorientierteren Aufbau gewünscht. Denn das Buch hat viel Potenzial, und ich finde, Assembler ist ein spannendes Thema, aber ich möchte es eben nicht nur theoretisch erlernen, sondern auch praktisch anwenden können.

Und damit wir uns hier nicht falsch verstehen: Das Buch ist nicht schlecht, aber als Lehrbuch eben nur bedingt geeignet. Es ist eher eine Referenz zum Nachschlagen, mit einem ausführlichen Teil über sauberes Programmieren in Assembler. Ich hatte nur eben aufgrund des Titels eher etwas anderes erwartet.

Teil fünf schließlich umfasst gerade einmal die letzten zehn Seiten. Es geht um typische Fehler, guten Stil und weiterführende Links. Insofern ist es kein echter fünfter Teil, sondern eher ein Anhang.

Lohnt sich die Lektüre?

Was bleibt? Wer sich für Assembler interessiert, wissen will, wie ein Computer und insbesondere der Prozessor intern funktioniert, und wer sich nicht scheut, sich mit einem eher low-leveligen Thema auseinanderzusetzen, und außerdem viel eigenen Spieltrieb mitbringt, kann durchaus großen Spaß an dem Buch haben. Wer aus den genannten Gründen etwas mehr über Assembler lernen, aber lieber stärker an die Hand genommen werden möchte, findet in dem Buch vielleicht nicht ganz das Richtige. Nichtsdestotrotz ist es ein gutes Buch.


URL dieses Artikels:
https://www.heise.de/-9817184

Links in diesem Artikel:
[1] https://dpunkt.de/produkt/einfuehrung-in-die-moderne-assembler-programmierung/
[2] https://www.heise.de/Datenschutzerklaerung-der-Heise-Medien-GmbH-Co-KG-4860.html
[3] https://www.youtube.com/watch?v=hr5xQpznD0Y
[4] mailto:mai@heise.de

Copyright © 2024 Heise Medien

Adblock test (Why?)

  • 05. August 2024 um 09:24

Neu in .NET 8.0 [32]: Weitere Neuerungen in System.Text.Json 8.0

Von Dr. Holger Schwichtenberg
Neural,Network,3d,Illustration.,Big,Data,And,Cybersecurity.,Data,Stream.

(Bild: rawf8/Shutterstock.com)

Die JSON-Bibliothek kann nun auch nicht öffentliche Mitglieder serialisieren und deserialisieren.

In System.Text.Json 8.0 kann man nun ein JsonNode-Objekt auch aus einem Stream erstellen:

JsonNode node = await JsonNode.ParseAsync(stream)

Zudem hat die Klasse JsonNode neue Methoden wie DeepClone() und DeepEquals() erhalten:

JsonNode person = JsonNode.Parse
  ("{\"Experte\":{\"Name\":\"Dr. Holger Schwichtenberg\"}}");
JsonNode personClone = person.DeepClone();
bool same = JsonNode.DeepEquals(person, personClone); // true
Console.WriteLine(same);

Außerdem wird bei JsonArray nun die Schnittstelle IEnumerable angeboten, das Aufzählung mit foreach und Language Integrated Query (LINQ) ermöglicht:

JsonArray jsonArray = new JsonArray(40, 42, 43, 42);
IEnumerable<int> values = 
  jsonArray.GetValues<int>().Where(i => i == 42);
foreach (var v in values)
{
 Console.WriteLine(v);
}

Im Namensraum System.Net.Http.Json gibt es nun eine Erweiterungsmethode GetFromJsonAsAsyncEnumerable<T>(URL), die eine Menge als IAsyncEnumerable<T> zur Iteration mit await foreach liefert.

In System.Text.Json 8.0 gibt es eine neue Annotation [JsonConverter], um einen eigenen Konverter zu registrieren. Ein Konverter ist eine Klasse, die von JsonConverter<T> erbt:

[JsonConverter(typeof(JsonStringEnumConverter<MyEnum>))]
public enum MyEnum { Value1, Value2, Value3 }

Weitere Informationen zu Konvertern finden sich auf der Learn-Plattform bei Microsoft [38].


URL dieses Artikels:
https://www.heise.de/-9821053

Links in diesem Artikel:
[1] https://www.heise.de/blog/Neu-in-NET-8-0-1-Start-der-neuen-Blogserie-9574680.html
[2] https://www.heise.de/blog/Neu-in-NET-8-0-2-Neue-Anwendungsarten-9581213.html
[3] https://www.heise.de/blog/Neu-in-NET-8-0-3-Primaerkonstruktoren-in-C-12-0-9581346.html
[4] https://www.heise.de/blog/Neu-in-NET-8-0-4-Collection-Expressions-in-C-12-0-9581392.html
[5] https://www.heise.de/blog/Neu-in-NET-8-0-5-Typaliasse-in-C-12-0-9594693.html
[6] https://www.heise.de/blog/Neu-in-NET-8-0-6-ref-readonly-in-C-12-0-9602188.html
[7] https://www.heise.de/blog/Neu-in-NET-8-0-7-Optionale-Parameter-in-Lambda-Ausdruecken-in-C-12-0-9609780.html
[8] https://www.heise.de/blog/Neu-in-NET-8-0-8-Verbesserungen-fuer-nameof-in-C-12-0-9616685.html
[9] https://www.heise.de/blog/Neu-in-NET-8-0-9-Neue-und-erweiterte-Datenannotationen-9623061.html
[10] https://www.heise.de/blog/Neu-in-NET-8-0-10-Plattformneutrale-Abfrage-der-Privilegien-9630577.html
[11] https://www.heise.de/blog/Neu-in-NET-8-0-11-Neue-Zufallsfunktionen-9637003.html
[12] https://www.heise.de/blog/Neu-in-NET-8-0-12-Eingefrorene-Objektmengen-9643310.html
[13] https://www.heise.de/blog/Neu-in-NET-8-0-12-Leistung-von-FrozenSet-9649523.html
[14] https://www.heise.de/blog/Neu-in-NET-8-0-14-Neue-Waechtermethoden-fuer-Parameter-9656153.html
[15] https://www.heise.de/blog/Neu-in-NET-8-0-15-Geschluesselte-Dienste-bei-der-Dependency-Injection-9662004.html
[16] https://www.heise.de/blog/Neu-in-NET-8-0-16-Neue-Methoden-fuer-IP-Adressen-9670497.html
[17] https://www.heise.de/blog/Neu-in-NET-8-0-17-Zeitabstraktion-fuer-Tests-mit-Zeitangaben-9675891.html
[18] https://www.heise.de/blog/Neu-in-NET-8-0-18-Ein-Zeitraffer-mit-eigenem-FakeTimeProvider-9683197.html
[19] https://www.heise.de/blog/Neu-in-NET-8-0-19-Razor-HTML-Rendering-in-beliebigen-NET-Anwendungen-9691146.html
[20] https://www.heise.de/blog/Neu-in-NET-8-0-20-Neue-Code-Analyzer-fuer-NET-Basisklassen-9706875.html
[21] https://www.heise.de/blog/Neu-in-NET-8-0-20-Neue-Code-Analyzer-fuer-ASP-NET-Core-9710151.html
[22] https://www.heise.de/blog/Neu-in-NET-8-0-22-Neues-Steuerelement-OpenFolderDialog-fuer-WPF-9722901.html
[23] https://www.heise.de/blog/Neu-in-NET-8-0-23-Verbesserungen-fuer-ZipFile-zur-Arbeit-mit-Dateiarchiven-9722920.html
[24] https://www.heise.de/blog/Neu-in-NET-8-0-24-HTTPS-Proxies-bei-HttpClient-9722968.html
[25] https://www.heise.de/blog/Neu-in-NET-8-0-25-Resilienz-im-HTTP-Client-9763586.html
[26] https://www.heise.de/blog/Neu-in-NET-8-0-26-Anpassung-der-Resilienz-im-HTTP-Client-9773126.html
[27] https://www.heise.de/blog/Neu-in-NET-8-0-27-Konfigurierbare-Namenskonventionen-in-System-Text-Json-8-0-9784360.html
[28] https://www.heise.de/blog/Neu-in-NET-8-0-28-Erweiterung-fuer-die-Deserialisierung-von-JSON-Objekten-9790704.html
[29] https://www.heise.de/blog/Neu-in-NET-8-0-29-Verbesserungen-fuer-den-JSON-Source-Generator-9798297.html
[30] https://www.heise.de/blog/Neu-in-NET-8-0-30-Neue-Datentypen-in-System-Text-Json-8-0-9808793.html
[31] https://www.heise.de/blog/Neu-in-NET-8-0-31-Erweiterte-Serialisierung-in-System-Text-Json-8-0-9814260.html
[32] https://www.heise.de/blog/Neu-in-NET-8-0-32-Weitere-Neuerungen-in-System-Text-Json-8-0-9821053.html
[33] https://www.heise.de/blog/Neu-in-NET-8-0-33-Erweiterung-des-AOT-Compilers-9829857.html
[34] https://www.heise.de/blog/Neu-in-NET-8-0-34-Verbesserte-Ausgaben-beim-Kompilieren-9837144.html
[35] https://net.bettercode.eu/
[36] https://net.bettercode.eu/index.php#programm
[37] https://net.bettercode.eu/tickets.php
[38] https://learn.microsoft.com/de-de/dotnet/standard/serialization/system-text-json/converters-how-to
[39] mailto:rme@ix.de

Copyright © 2024 Heise Medien

Adblock test (Why?)

  • 02. August 2024 um 10:03

Neu in .NET 8.0 [31]: Erweiterte Serialisierung in System.Text.Json 8.0

Von Dr. Holger Schwichtenberg
Neural,Network,3d,Illustration.,Big,Data,And,Cybersecurity.,Data,Stream.

(Bild: Yurchanka Siarhei / Shutterstock.com)

Die JSON-Bibliothek kann nun auch nicht öffentliche Mitglieder serialisieren und deserialisieren.

In System.Text.Json ermöglichen es die Annotationen [JsonInclude] und [JsonConstructor] seit Version 8.0, die Serialisierung nicht öffentlicher Klassenmitglieder zu erzwingen.

Für jedes nicht öffentliche Mitglied, das mit [JsonInclude] annotiert ist, muss im Konstruktor, der mit [JsonConstructor] annotiert ist, ein Parameter vorhanden sein, um den Wert während der Deserialisierung setzen zu können. Ein aussagekräftiges Beispiel dazu zeigt folgendes Listing:

public class Person
{
 [JsonConstructor] 
 // ohne Annotation: 'Deserialization of types without a 
 // parameterless constructor, a singular parameterized 
 // constructor, or a parameterized constructor annotated with 
 // 'JsonConstructorAttribute' is not supported. 
 internal Person(int id, string name, string website)
 {
  ID = id;
  Name = name;
  Website = website;
 }
 
 [JsonInclude] 
 // ohne Annotation: 'Each parameter in the deserialization 
 // constructor on type 'FCL_JSON+Person' must bind to an
 // object property or field on deserialization. Each parameter
 // name must match with a property or field on the object. 
 // Fields are only considered when
 // 'JsonSerializerOptions.IncludeFields' is enabled. 
 // The match can be case-insensitive.'
 
 internal int ID { get; }
 
 public string Name { get; set; }
 
 [JsonInclude] 
 // ohne Annotation: 'Each parameter in the deserialization
 // constructor on type 'FCL_JSON+Person' must bind to an object
 // property or field on deserialization. Each parameter name must
 // match with a property or field on the object. Fields are only
 // considered when 'JsonSerializerOptions.IncludeFields' is 
 // enabled. The match can be case-insensitive.'
 private string Website { get; set; }
 
 public override string ToString()
 {
  return $"{this.ID}: {this.Name} ({this.Website})";
 }
}
…
// Serialisierung
var p1 = new PersonWithoutParameterlessConstructor
  (42, Dr. Holger Schwichtenberg", "www.dotnet-doktor.de");
string json4 = JsonSerializer.Serialize(p1); 
Console.WriteLine(json4);
//{ "Name":"Dr. Holger Schwichtenberg","ID":42,"Website":"www.dotnet-doktor.de"}
 
// Deserialisierung
var p2 = 
  JsonSerializer.Deserialize<PersonWithoutParameterlessConstructor>(json4);
Console.WriteLine(p2);
//42: Dr.Holger Schwichtenberg (www.dotnet-doktor.de)


URL dieses Artikels:
https://www.heise.de/-9814260

Links in diesem Artikel:
[1] https://www.heise.de/blog/Neu-in-NET-8-0-1-Start-der-neuen-Blogserie-9574680.html
[2] https://www.heise.de/blog/Neu-in-NET-8-0-2-Neue-Anwendungsarten-9581213.html
[3] https://www.heise.de/blog/Neu-in-NET-8-0-3-Primaerkonstruktoren-in-C-12-0-9581346.html
[4] https://www.heise.de/blog/Neu-in-NET-8-0-4-Collection-Expressions-in-C-12-0-9581392.html
[5] https://www.heise.de/blog/Neu-in-NET-8-0-5-Typaliasse-in-C-12-0-9594693.html
[6] https://www.heise.de/blog/Neu-in-NET-8-0-6-ref-readonly-in-C-12-0-9602188.html
[7] https://www.heise.de/blog/Neu-in-NET-8-0-7-Optionale-Parameter-in-Lambda-Ausdruecken-in-C-12-0-9609780.html
[8] https://www.heise.de/blog/Neu-in-NET-8-0-8-Verbesserungen-fuer-nameof-in-C-12-0-9616685.html
[9] https://www.heise.de/blog/Neu-in-NET-8-0-9-Neue-und-erweiterte-Datenannotationen-9623061.html
[10] https://www.heise.de/blog/Neu-in-NET-8-0-10-Plattformneutrale-Abfrage-der-Privilegien-9630577.html
[11] https://www.heise.de/blog/Neu-in-NET-8-0-11-Neue-Zufallsfunktionen-9637003.html
[12] https://www.heise.de/blog/Neu-in-NET-8-0-12-Eingefrorene-Objektmengen-9643310.html
[13] https://www.heise.de/blog/Neu-in-NET-8-0-12-Leistung-von-FrozenSet-9649523.html
[14] https://www.heise.de/blog/Neu-in-NET-8-0-14-Neue-Waechtermethoden-fuer-Parameter-9656153.html
[15] https://www.heise.de/blog/Neu-in-NET-8-0-15-Geschluesselte-Dienste-bei-der-Dependency-Injection-9662004.html
[16] https://www.heise.de/blog/Neu-in-NET-8-0-16-Neue-Methoden-fuer-IP-Adressen-9670497.html
[17] https://www.heise.de/blog/Neu-in-NET-8-0-17-Zeitabstraktion-fuer-Tests-mit-Zeitangaben-9675891.html
[18] https://www.heise.de/blog/Neu-in-NET-8-0-18-Ein-Zeitraffer-mit-eigenem-FakeTimeProvider-9683197.html
[19] https://www.heise.de/blog/Neu-in-NET-8-0-19-Razor-HTML-Rendering-in-beliebigen-NET-Anwendungen-9691146.html
[20] https://www.heise.de/blog/Neu-in-NET-8-0-20-Neue-Code-Analyzer-fuer-NET-Basisklassen-9706875.html
[21] https://www.heise.de/blog/Neu-in-NET-8-0-20-Neue-Code-Analyzer-fuer-ASP-NET-Core-9710151.html
[22] https://www.heise.de/blog/Neu-in-NET-8-0-22-Neues-Steuerelement-OpenFolderDialog-fuer-WPF-9722901.html
[23] https://www.heise.de/blog/Neu-in-NET-8-0-23-Verbesserungen-fuer-ZipFile-zur-Arbeit-mit-Dateiarchiven-9722920.html
[24] https://www.heise.de/blog/Neu-in-NET-8-0-24-HTTPS-Proxies-bei-HttpClient-9722968.html
[25] https://www.heise.de/blog/Neu-in-NET-8-0-25-Resilienz-im-HTTP-Client-9763586.html
[26] https://www.heise.de/blog/Neu-in-NET-8-0-26-Anpassung-der-Resilienz-im-HTTP-Client-9773126.html
[27] https://www.heise.de/blog/Neu-in-NET-8-0-27-Konfigurierbare-Namenskonventionen-in-System-Text-Json-8-0-9784360.html
[28] https://www.heise.de/blog/Neu-in-NET-8-0-28-Erweiterung-fuer-die-Deserialisierung-von-JSON-Objekten-9790704.html
[29] https://www.heise.de/blog/Neu-in-NET-8-0-29-Verbesserungen-fuer-den-JSON-Source-Generator-9798297.html
[30] https://www.heise.de/blog/Neu-in-NET-8-0-30-Neue-Datentypen-in-System-Text-Json-8-0-9808793.html
[31] https://www.heise.de/blog/Neu-in-NET-8-0-31-Erweiterte-Serialisierung-in-System-Text-Json-8-0-9814260.html
[32] mailto:rme@ix.de

Copyright © 2024 Heise Medien

Adblock test (Why?)

  • 26. Juli 2024 um 15:35

Agilität führt zu 268 Prozent mehr Fehlschlägen – kann das sein?

Von Eberhard Wolff

(Bild: LanKS/Shutterstock.com)

Agilität ist angetreten, produktiver Software zu entwickeln. Eine Studie zeigt aber mehr Fehlschläge. Das sagt mehr über unsere Branche aus als über Agilität.

Eine Studie [1] will zeigen, dass agile Softwareentwicklung angeblich eine 268 Prozent höhere Chance für Fehlschläge mit sich bringt. So ein massiver Nachteil muss eigentlich dazu führen, dass alle sofort aufhören, überhaupt irgendwelche Projekte agil durchzuführen.

Wie kommen die Zahlen zustande? Die Studie stellt zunächst fest, dass folgende Faktoren den Erfolg von Softwareentwicklungsprojekten verbessern:

  • Requirements sind vor dem Start des Projekts klar (97 Prozent mehr erfolgreiche Projekte).
  • Möglichkeit Probleme können schnell diskutiert und adressiert werden (87 Prozent).
  • Projekt-Requirements basieren auf realen Problemen (54 Prozent).
  • Das Projekt hat eine vollständige Spezifikation oder ein vollständiges Requirements-Dokument, bevor die Implementierung startet (50 Prozent).
  • Es gab keine signifikanten Änderungen der Requirements später im Entwicklungsprozess (7 Prozent).

Keinen erheblichen Einfluss hatte hingegen, ob Menschen an einem oder mehreren Projekten gleichzeitig arbeiten.

Die Studie definiert agile Entwicklung als Projekte, bei denen Folgendes gilt:

  • Die Entwicklung startet, bevor die Requirements klar sind,
  • es gibt keine vollständige Spezifikation und
  • es gibt signifikante Änderungen spät im Projekt.

Zusammen führt das zu 268 Prozent mehr Fehlschlägen und 65 Prozent gescheiterten Projekten. Das Zahlenmaterial ist auch mit passenden statistischen Werten ausgestattet und wirkt daher überzeugend.

Was ist "Erfolg"?

Das erste Problem der Studie ist die fehlende Definition von "Fehlschlag". Ein mögliches Kriterium wäre, dass die Projekte nicht im Budget geliefert wurden. Das ist aber ein eigentümliches Ziel für ein Individualsoftwareprojekt. Wenn man Software möglichst billig haben will, sollte man sie nicht selbst entwickeln, sondern Standardsoftware kaufen. Das ist sinnvoll für Bereiche, in denen man die Flexibilität einer eigenen Implementierung nicht benötigt. Mir wäre beispielsweise nicht klar, warum man eine Finanzbuchhaltung selbst implementieren würde.

Vielleicht sind mit höheren Kosten ein höherer Wert verbunden, weil mehr Features umgesetzt und so vielleicht sogar mehr Umsatz und Gewinn erzielt werden? Ist das Projekt dann ein Fehlschlag?

Eine weitere Möglichkeit, "Fehlschlag" zu definieren wäre, wenn der Auftraggeber am Ende des Projekts vom Ergebnis enttäuscht ist. Das ist vielleicht sinnvoll, aber kein rationales Kriterium. Kunden können aus den unterschiedlichsten Gründen enttäuscht werden. Unterschiedliche Stakeholder können unterschiedlich zufrieden mit dem Ergebnis sein.

Die Definition von "Fehlschlag" ist keine Frage ohne praktische Auswirkungen. Ich habe selbst in Projekten mitgearbeitet, die offiziell ein Erfolg waren, aber subjektiv erhebliche Probleme hatten oder vorab definierte Projektziele nicht erreicht haben. Es geht schlimmer: Einige Projekte haben gar keine echten Projektziele – wie soll man dann über einen Fehlschlag oder Erfolg entscheiden?

Eigentlich könnte man jetzt schon damit aufhören, die Studie genauer zu betrachten. Aber die Studie hat noch viele weitere Probleme.

Krasse Überraschungen!

Die Studie behauptet, dass es hilfreich ist, wenn Requirements vor dem Start des Projekts bekannt sind, die Spezifikation vollständig ist und signifikante Änderungen spät im Projekt unterbleiben. Ich muss gestehen: Mein Erstaunen darüber wie auch über die anderen Ergebnisse der Studie hält sich in engen Grenzen. Mehr Informationen am Anfang und weniger Änderungen im Verlauf des Projekts machen Projekten das Leben sicher einfacher. Man könnte so ein Projekt als langweilig bezeichnen. Aus der Sicht der Umsetzer ist das super, weil das Projekt eben mit höherer Wahrscheinlichkeit erfolgreich ist. Aus Sicht der Auftraggeber erscheint es aber unwahrscheinlich, dass ein solches Projekt einen hohen Wert hat. Wenn man etwa einen neuen Markt schneller als der Wettbewerb mit einem neuen digitalen Produkt besetzen will, sind vermutlich die Requirements nicht klar, die Spezifikation unvollständig und es werden sich auch spät im Projekt Änderungen ergeben, weil schlicht nicht klar ist, was die Kunden genau wollen und wie der Markt aussieht. Niemand kann das wissen. Die Kunden greifen erst zu, wenn ihnen das Projekt gefällt.

Genau in dem Fall kann Agilität ihre Stärken ausspielen. Ich glaube sofort, dass solche Projekte öfter von der ursprünglichen Planung abweichen und das kann man einen Fehlschlag nennen. Aber was ist die Konsequenz? Solche Projekte einfach nicht angehen und eine solche Markt-Chance nicht ergreifen? Maßnahmen ergreifen, um doch Stabilität vorzutäuschen, die dann aber das Projekt behindern?

Anders gesagt: Gerade die Projekte, die laut der Studie öfter fehlschlagen, sind vielleicht die Projekte, die einen besonders hohen Wert generieren.

Was ist Agilität?

Angeblich orientiert sich die Definition von Agilität aus der Studie am agilen Manifest. [2] Also sollte das agile Manifest irgendwo etwas enthalten im Sinne von: "Wenn am Anfang des Projekts Anforderungen klar sind, und eine vollständige Spezifikation vorliegt, lösche dieses Dokument und sorge dafür, dass sich niemand an die Anforderungen und die Spezifikation erinnert – sonst genügt das Projekt nicht diesem Manifest." Und ebenso müsste da irgendwo "Wenn sich im Projekt später keine signifikanten Änderungen ergeben, dann erfinde welche – sonst genügt das Projekt nicht diesem Manifest" stehen. Ich habe nachgeschaut: Das steht nicht im agilen Manifest und es gibt auch keinen Absatz, der sich so interpretieren ließe. Im Gegenteil: Das agile Manifest wägt Optionen wie das Befolgen eines Plans und das Reagieren auf Änderungen ab – und legt den Fokus auf eins, in dem Beispiel das Reagieren auf Änderungen, ohne dass die andere Option als unwichtig bewertet wird – nur eben als weniger wichtig. Auf eine Änderung zu reagieren erscheint tatsächlich sinnvoller, als an dem festen Plan festzuhalten, der die Änderung noch gar nicht betrachtet haben kann.

Noch mehr Probleme

Die Studie basiert übrigens auf einer Umfrage unter 600 Software Engineers. Umfragen können immer nur das subjektive Bild der befragten Person abbilden – in diesem Fall also die der Software Engineers. Da eine Softwareentwicklung eine wirtschaftliche Investition ist, wäre es sinnvoll andere Gruppen, insbesondere unterschiedliche Stakeholder ebenfalls zu befragen. Schließlich geben sie die Projekte in Auftrag. Wer könnte also besser bewerten, ob das Projekt wirklich ein Fehlschlag ist.

Und die Studie lässt noch eine Frage unbeantwortet: Wie viele Projekte haben denn klare Requirements? 10 Prozent? 25 Prozent? 90 Prozent? Man kann aus der Studie nur entnehmen, dass es eine genügend große Anzahl sein muss, um statistisch signifikante Aussagen zu treffen. Wenn sehr viele Projekte unklare Requirements haben, wäre das ein Hinweis auf ein wichtiges Problem. Ob und wie man es lösen kann, ist dann die nächste Frage – und die ist nicht so einfach zu beantworten. Requirements kann man sich ja nicht einfach wünschen, sondern gegebenenfalls sind sie wie erwähnt prinzipienbedingt unklar.

Und nun?

Eigentlich ist die Studie keinen Blogpost wert. Sie ist ein durchsichtiges Manöver, um agile Softwareentwicklung zu diskreditieren und einen anderen Ansatz zu promoten. Aber die Studie hat dennoch Einfluss – mir sind in zwei unterschiedlichen Kontexten Hinweise auf die Studie untergekommen. Das ist nachvollziehbar: 268 Prozent ist eine krasse Zahl und das Ergebnis ist überraschend, weil Agilität ja eigentlich mehr Erfolg erreichen sollte. Da muss man einfach hineinschauen! Wenn man das wirklich tut, wird schnell klar, was für ein Unsinn da steht. Ein YouTube-Video [3] hat die Zahl genutzt, um andere Aspekte von Agilität zu kritisieren, also nicht die Probleme mit Requirements, die die Studie erläutert. Unabhängig davon, ob die Kritik berechtigt ist: Das Video nutzt die absurde Zahl aus der Studie, um Aufmerksamkeit zu generieren.

Wenn wir in unserer Branche so vorgehen, dürfen wir uns nicht wundern, wenn wir nicht lernen, was wirklich hilft und so kein Fortschritt erzielt wird. Dabei wird die kritische Arbeit mit Quellen schon in der Schule gelehrt.

Ob Agilität nun "gut" oder "schlecht" ist, können wir mit der Studie nicht beantworten. Aber: Dass wir Software in Iterationen erstellen müssen, hat sich in der Praxis historisch sehr früh gezeigt – im Prinzip als Menschen angefangen haben, Software in Teams zu entwickeln. Und zwar auch, wenn man anders als in agilen Projekten relativ stabile Anforderungen hat. Das wird klar, wenn man Pionieren und Pionierinnen wie Prof. Christiane Floyd zuhört [4]. Zu dem Thema habe ich auch einen Vortrag [5] gehalten. Dass es Projekte gibt, die gut daran tun, beispielsweise auf Änderungen zu reagieren, statt einem Plan zu folgen, sollte auch klar sein. Das wirkliche Problem ist vielleicht, dass Agilität als Begriff mittlerweile verbrannt ist, weil in der Realität "agile" Prozesse eingeführt werden, die nicht den ursprünglichen Ideen entsprechen und auch nicht sonderlich hilfreich sind.

tl;dr

Unsere Branche ist anfällig für tendenziöse Studien. Das ist schade. Krasse Behauptungen erzeugen Aufmerksamkeit.


URL dieses Artikels:
https://www.heise.de/-9810522

Links in diesem Artikel:
[1] https://www.engprax.com/post/268-higher-failure-rates-for-agile-software-projects-study-finds
[2] https://agilemanifesto.org/iso/de/manifesto.html
[3] https://www.youtube.com/watch?v=gSVBWvoNJ-s
[4] https://software-architektur.tv/2021/07/09/folge66.html
[5] https://software-architektur.tv/2024/04/02/folge211.html
[6] mailto:rme@ix.de

Copyright © 2024 Heise Medien

Adblock test (Why?)

  • 26. Juli 2024 um 11:02

Neu in .NET 8.0 [30]: Neue Datentypen in System.Text.Json 8.0

Von Dr. Holger Schwichtenberg
Ein Abakus auf einem Blatt mit Zahlen

(Bild: Alexander Lukatskiy/Shutterstock.com)

System.Text.Json beherrscht nun Half, Int128, UInt128, Memory und ReadOnlyMemory.

System.Text.Json kann seit Version 8.0 neuere Zahlentypen wie Half, Int128 und UInt128 sowie die Speichertypen Memory<T> und ReadOnlyMemory<T> serialisieren.

Bei Letzteren entstehen, wenn es sich um Memory<Byte> und ReadOnlyMemory<Byte> handelt, Base64-kodierte Zeichenketten. Andere Datentypen werden als JSON-Arrays serialisiert.

Beispiel 1:

JsonSerializer.Serialize<ReadOnlyMemory<byte>>
  (new byte[] { 42, 43, 44 });

wird zu "Kiss"

Beispiel 2:

JsonSerializer.Serialize<Memory<Int128>>
  (new Int128[] { 42, 43, 44 });

wird zu [42,43,44]

Beispiel 3:

JsonSerializer.Serialize<Memory<string>>
  (new string[] { "42", "43", "44" });

wird zu ["42","43","44"]


URL dieses Artikels:
https://www.heise.de/-9808793

Links in diesem Artikel:
[1] https://www.heise.de/blog/Neu-in-NET-8-0-1-Start-der-neuen-Blogserie-9574680.html
[2] https://www.heise.de/blog/Neu-in-NET-8-0-2-Neue-Anwendungsarten-9581213.html
[3] https://www.heise.de/blog/Neu-in-NET-8-0-3-Primaerkonstruktoren-in-C-12-0-9581346.html
[4] https://www.heise.de/blog/Neu-in-NET-8-0-4-Collection-Expressions-in-C-12-0-9581392.html
[5] https://www.heise.de/blog/Neu-in-NET-8-0-5-Typaliasse-in-C-12-0-9594693.html
[6] https://www.heise.de/blog/Neu-in-NET-8-0-6-ref-readonly-in-C-12-0-9602188.html
[7] https://www.heise.de/blog/Neu-in-NET-8-0-7-Optionale-Parameter-in-Lambda-Ausdruecken-in-C-12-0-9609780.html
[8] https://www.heise.de/blog/Neu-in-NET-8-0-8-Verbesserungen-fuer-nameof-in-C-12-0-9616685.html
[9] https://www.heise.de/blog/Neu-in-NET-8-0-9-Neue-und-erweiterte-Datenannotationen-9623061.html
[10] https://www.heise.de/blog/Neu-in-NET-8-0-10-Plattformneutrale-Abfrage-der-Privilegien-9630577.html
[11] https://www.heise.de/blog/Neu-in-NET-8-0-11-Neue-Zufallsfunktionen-9637003.html
[12] https://www.heise.de/blog/Neu-in-NET-8-0-12-Eingefrorene-Objektmengen-9643310.html
[13] https://www.heise.de/blog/Neu-in-NET-8-0-12-Leistung-von-FrozenSet-9649523.html
[14] https://www.heise.de/blog/Neu-in-NET-8-0-14-Neue-Waechtermethoden-fuer-Parameter-9656153.html
[15] https://www.heise.de/blog/Neu-in-NET-8-0-15-Geschluesselte-Dienste-bei-der-Dependency-Injection-9662004.html
[16] https://www.heise.de/blog/Neu-in-NET-8-0-16-Neue-Methoden-fuer-IP-Adressen-9670497.html
[17] https://www.heise.de/blog/Neu-in-NET-8-0-17-Zeitabstraktion-fuer-Tests-mit-Zeitangaben-9675891.html
[18] https://www.heise.de/blog/Neu-in-NET-8-0-18-Ein-Zeitraffer-mit-eigenem-FakeTimeProvider-9683197.html
[19] https://www.heise.de/blog/Neu-in-NET-8-0-19-Razor-HTML-Rendering-in-beliebigen-NET-Anwendungen-9691146.html
[20] https://www.heise.de/blog/Neu-in-NET-8-0-20-Neue-Code-Analyzer-fuer-NET-Basisklassen-9706875.html
[21] https://www.heise.de/blog/Neu-in-NET-8-0-20-Neue-Code-Analyzer-fuer-ASP-NET-Core-9710151.html
[22] https://www.heise.de/blog/Neu-in-NET-8-0-22-Neues-Steuerelement-OpenFolderDialog-fuer-WPF-9722901.html
[23] https://www.heise.de/blog/Neu-in-NET-8-0-23-Verbesserungen-fuer-ZipFile-zur-Arbeit-mit-Dateiarchiven-9722920.html
[24] https://www.heise.de/blog/Neu-in-NET-8-0-24-HTTPS-Proxies-bei-HttpClient-9722968.html
[25] https://www.heise.de/blog/Neu-in-NET-8-0-25-Resilienz-im-HTTP-Client-9763586.html
[26] https://www.heise.de/blog/Neu-in-NET-8-0-26-Anpassung-der-Resilienz-im-HTTP-Client-9773126.html
[27] https://www.heise.de/blog/Neu-in-NET-8-0-27-Konfigurierbare-Namenskonventionen-in-System-Text-Json-8-0-9784360.html
[28] https://www.heise.de/blog/Neu-in-NET-8-0-28-Erweiterung-fuer-die-Deserialisierung-von-JSON-Objekten-9790704.html
[29] https://www.heise.de/blog/Neu-in-NET-8-0-29-Verbesserungen-fuer-den-JSON-Source-Generator-9798297.html
[30] https://www.heise.de/blog/Neu-in-NET-8-0-30-Neue-Datentypen-in-System-Text-Json-8-0-9808793.html
[31] https://www.heise.de/blog/Neu-in-NET-8-0-31-Erweiterte-Serialisierung-in-System-Text-Json-8-0-9814260.html
[32] mailto:rme@ix.de

Copyright © 2024 Heise Medien

Adblock test (Why?)

  • 22. Juli 2024 um 08:41

Risiko Microservices? Vor- und Nachteile einer verteilten Architektur

Von Golo Roden
Lupe, unter der sich ein Warndreieck befindet.

(Bild: Dilok Klaisataporn/Shutterstock.com)

Microservices sind die perfekte Lösung für gewisse Probleme. Doch unpassend eingesetzt, können sie das ganze Projekt ruinieren. Worauf gilt es zu achten?

Vor ungefähr einer Woche habe ich einen Blogpost geschrieben, zu dem ich viel Feedback erhalten habe: "12 Regeln für die perfekte (Micro-)Service-Architektur [1]". Darin habe ich zwölf Regeln vorgestellt, die sich für uns bei der the native web GmbH [2] in den vergangenen Jahren für die Konzeption, den Entwurf und die Entwicklung von Microservices bewährt haben. Sehr deutlich habe ich außerdem gesagt: "Your mileage may vary", also auf gut Deutsch: Die Tatsache, dass sich diese Regeln für uns bewährt haben, bedeutet noch lange nicht, dass sie auf Sie, Ihr Team und Ihre Anforderungen 1:1 übertragbar seien.

Des Weiteren habe ich auch nicht behauptet, dass Microservices der einzig wahre Architekturansatz seien. Aber ich gehe in einem Blogpost über die Architektur von Microservices natürlich davon aus, dass der Text primär von Menschen gelesen wird, die mit der Konzeption, dem Entwurf und der Entwicklung von Microservices zu tun haben – oder die sich zumindest zukünftig dafür interessieren werden.

Achtung, Achtung! Bitte halten Sie sich von Microservices fern!

Daher war ich überrascht, dass rund die Hälfte der Kommentare – sei es hier auf heise Developer, auf YouTube, per E-Mail oder im persönlichen Gespräch – den Einsatz von Microservices an sich infrage gestellt hat, sinngemäß: Ja, das könne man schon alles so machen, aber als Allererstes solle man doch gründlich hinterfragen, ob Microservices an sich eine gute Idee seien oder nicht. Überrascht war ich deshalb, weil ich es zum einen für selbstverständlich halte, dass man ein Architekturprinzip im Vorfeld auf Eignung prüft, und ebendiese Frage zum anderen gar nicht das Thema des Blogposts war.

Anscheinend besteht eine Notwendigkeit, vor dem Einsatz von Microservices zu warnen, denn damit habe man "schon schlechte Erfahrungen gemacht". Dass das gleiche auch für andere Architekturansätze wie Monolithen, Client-Server oder Peer-to-Peer gilt, fällt dabei gerne unter den Tisch. Interessant finde ich, dass ich diese Reaktion sehr häufig auf die Erwähnung von Microservices erlebe. Ich mag auch gar nicht abstreiten, dass nicht die eine oder der andere tatsächlich schon schlechte Erfahrungen mit Microservices gemacht hat – mich wundert nur, dass stets nur bei Microservices so vehement darauf hingewiesen wird.

Deshalb habe ich mir überlegt, dass es vielleicht sinnvoll sein könnte, einmal die Frage zu stellen, wann Microservices eine gute und wann sie eine schlechte Idee sind. Mit anderen Worten: Über welche Aspekte lohnt es sich nachzudenken, bevor man auf Microservices setzt, damit ein Projekt nachher nicht tatsächlich in einem Fiasko endet?

Und übrigens, bevor nun jemand argumentiert, dass selbst Amazon inzwischen auf Microservices verzichten würde [4]: Zu diesem Gerücht habe ich mich vor geraumer Zeit bereits geäußert. Also falls Sie dieses Argument hätten anbringen wollen, dann schauen Sie sich bitte vorab das Video "Microservices sind doof – sagt Amazon?! [5]" an.

Argument #1: Komplexität der Architektur

Kommen wir nun zum ersten häufig genannten Argument gegen Microservices, nämlich der deutlich höheren Komplexität der Architektur. Per Definition sind Microservices eine verteilte Architektur, es handelt sich also bei einer Service-basierten Anwendung um ein verteiltes System. Der US-amerikanische Informatiker Andrew S. Tanenbaum [6] hat ein solches System wie folgt definiert [7]:

"Ein verteiltes System ist ein Zusammenschluss unabhängiger Computer, die sich für den Benutzer als ein einziges System präsentieren."

Tatsächlich gibt es von dieser Definition auch noch eine humoristische Abwandlung, und zwar:

"Ein verteiltes System ist ein System, das nicht das macht, was es soll, weil ein Computer ausgefallen ist, von dem Sie weder wussten, dass er existiert noch, dass er für irgendetwas wichtig ist."

Doch Spaß beiseite: Es liegt auf der Hand, dass verteilte Systeme in technischer Hinsicht komplexer sind als nicht-verteilte Systeme. Das hängt vor allem mit Problemen rund um die Kommunikation zwischen den einzelnen beteiligten Parteien zusammen, also mit Themen wie Konsistenz, Synchronisation, Verfügbarkeit und so weiter.

In diesen Zusammenhang fällt dann auch das sogenannte CAP-Theorem [8], das (vereinfacht ausgedrückt) besagt: Wenn in einem verteilten System ein Netzwerkausfall stattfindet und dadurch eine Partitionierung entsteht (das entspricht dem "P"), dann kann man sich aussuchen, ob man entweder die Konsistenz (also das "C") oder die Verfügbarkeit (also das "A", das hier für "Availability" steht) bewahren möchte. Beides zusammen ist nicht möglich.

Das bedeutet, dass man sich bei verteilten Systemen deutlich mehr Gedanken machen muss, wie man mit Konsistenz und Verfügbarkeit umgeht, was wiederum einiges an Wissen und Erfahrung erfordert. Vor allem benötigt man für ein verteiltes System jedoch eines, nämlich einen guten Grund, warum man ein System überhaupt als verteiltes System entwerfen möchte. Man sollte es nicht deshalb machen, weil es "interessant wirkt" oder "cool klingt".

Der vermutlich primäre Grund, ein System als verteiltes System gestalten zu wollen, ist (und das steckt sogar schon in der Definition von Andrew S. Tanenbaum), dass man eine hohe Unabhängigkeit zwischen den einzelnen Teilen anstrebt, und zwar in technischer, organisatorischer und vor allem auch in fachlicher Hinsicht. Darüber hinaus wird gerne noch genannt, dass man eine Technologie nicht systemrelevant werden lassen möchte, dass man mit Microservices eine höhere Flexibilität und eine bessere Anpassbarkeit bekäme, dass man ein verteiltes System gezielter skalieren könne und so weiter – aber die Unabhängigkeit, ist die eigentlich treibende Kraft hinter verteilten Systemen. Und wenn der Bedarf daran nicht gegeben ist, dann eignet sich ein stärker zentralisierter Ansatz höchstwahrscheinlich deutlich mehr.

Daher muss man sich die Frage stellen: Benötigt man technische, organisatorische und vor allem fachliche Unabhängigkeit?

Argument #2: Deployment und Infrastruktur

Kommen wir zum zweiten häufig genannten Argument gegen Microservices, nämlich dem Deployment und der Infrastruktur. Klar ist, dass Microservices komplexere Deployments nach sich ziehen, und zwar nicht zuletzt deshalb, weil schlichtweg mehr zu deployen ist. Natürlich ist das XCOPY-Deployment [9] eines einfachen Monolithen, der auf einem einzigen Server mit einer einzigen Instanz läuft, bedeutend einfacher.

Allerdings funktioniert das Deployment von Microservices eigentlich immer sehr ähnlich, und zwar vollkommen unabhängig davon, um welche Anwendung es sich dabei handelt. Das bedeutet, dass man das Know-how dafür problemlos "fertig von der Stange" einkaufen kann. Weder muss man hierbei viel experimentieren noch muss man viel herausfinden – es braucht lediglich jemanden, die oder der das schon einmal gemacht hat und die oder der sich mit den entsprechenden Technologien auskennt. Also, allen voran: Container, Docker und Kubernetes.

Mich persönlich überzeugt dieses Argument nicht so richtig, denn ja, die Komplexität ist zwar höher, aber nicht nennenswert höher – und dafür bekomme ich im Umkehrschluss eine viel niedrigere Komplexität in der Fachlichkeit der einzelnen Services. Das heißt, jeder einzelne Service wird einfacher zu entwickeln, weil er deutlich kleiner und überschaubarer ist. Und da gerade das der Punkt ist, den ich nicht von der Stange kaufen kann, ist die Ersparnis hier viel mehr wert als das, was ich beim Deployment potenziell an zusätzlichen Kosten habe. Denn ja, einerseits wird eine einfache, standardisierte und immer gleiche Aufgabe etwas komplexer, doch dafür erhält man eine viel niedrigere Komplexität bei den Dingen, die ohnehin schwierig, anspruchsvoll, zeitaufwendig und individuell sind. Und das klingt für mich persönlich eigentlich nach einem ziemlich guten Handel.

Diese Gegen-Argumentation basiert natürlich auf der Annahme, dass man mit Containerisierung, Docker, Kubernetes & Co. halbwegs vertraut ist. Wer heute immer noch von Hand mit Shell-Skripten auf Bare-Metal unterwegs ist, der wird Schwierigkeiten mit dem effizienten Deployment von Microservices haben. Allerdings zeigt die Erfahrung, dass das auch für alle anderen Arten von Deployments gilt. Falls Containerisierung & Co. für Sie und Ihr Team tatsächlich noch Neuland sein sollten, dann ist das etwas, was Sie schleunigst ändern sollten – zumindest, wenn Sie im Bereich Web und Cloud tätig sind. Als Einstieg kann ich Ihnen unseren kostenlosen Docker Deep-Dive [10] empfehlen, zu dem es auch noch einige Fortsetzungen und einen gesonderten Deep-Dive zu Kubernetes [11] gibt.

Argument #3: Konsistenz und Transaktionen

Kommen wir zum dritten häufig genannten Argument gegen Microservices, nämlich zu den Herausforderungen im Bereich Konsistenz und Transaktionsmanagement. Ich hatte bereits kurz das CAP-Theorem angesprochen, und in verteilten Systemen steht hier das "A" (Verfügbarkeit) häufig weit über dem "C" (Konsistenz). Das ist deshalb so, weil die kontinuierliche und dauerhafte Lauffähigkeit des Gesamtsystems deutlich wichtiger ist, als die punktuell garantierte strenge Konsistenz.

Und das heißt übrigens nicht, dass verteilte Systeme nicht konsistent seien. Es heißt nur, dass sie nicht Strong-Consistent sind, sondern Eventual-Consistent. Mit anderen Worten: Es dauert manchmal einen kleinen Augenblick, bis die Konsistenz über mehrere Services hinweg tatsächlich hergestellt ist.

Dieser Punkt sorgt häufig für Aufregung, weil es dann rasch heißt, es ginge nicht ohne Strong-Consistency und so weiter. Und das stimmt auch – zumindest in einigen, ganz wenigen, gut begründeten Ausnahmefällen. In den meisten typischen Business-Anwendungen ist Eventual-Consistency hingegen vollkommen ausreichend. Und anders, als viele Entwicklerinnen und Entwickler häufig glauben, handelt es sich dabei nicht um ein technisches Problem oder eine technische Herausforderung. Stattdessen ist es eine Frage des Risikos und der Wahrscheinlichkeit, um die sich das Business kümmern muss.

Ein Beispiel: Falls es an einer Hochschule wegen Eventual-Consistency dazu kommen kann, dass der letzte Platz in einem Seminar doppelt vergeben wird, muss man sich die Frage stellen, wie schlimm das ist. Und diese Frage ist, wie zuvor erwähnt, nicht technischer, sondern ausschließlich fachlicher Natur. Um sie adäquat beantworten zu können, muss man zunächst wissen, wie häufig der Fall eintreten kann und was dann die Konsequenzen sind. Auf andere Art formuliert: Wie hoch ist das Risiko im Verhältnis zur Wahrscheinlichkeit und was geht im schlimmsten Fall schief? Wenn die Antwort darauf ist, dass einmal in fünf Jahren eine Person mehr im Seminar sitzen könnte, dann ist das – ehrlich gesagt – völlig in Ordnung.

Selbstverständlich möchte ich damit nicht sagen, dass es nicht Bereiche oder Themen gäbe, wo Strong-Consistency zwingend erforderlich ist. Ich sage nur, dass es in vielen typischen Web- und Cloud-Anwendungen völlig in Ordnung ist, wenn es "nur" Eventual-Consistent ist. Und das wiederum kann ich aus jahrelanger Erfahrung in der Konzeption, im Entwurf und in der Entwicklung von Microservices bestätigen: Strong-Consistency wird in 95 % der Fälle massiv überschätzt. Die Wahrheit ist, dass in nahezu allen Fällen Eventual-Consistency gänzlich ausreichend und gut genug ist. Insofern kommt es bei diesem Argument letztlich darauf an, ob man einen dieser wenigen begründeten Ausnahmefälle hat oder nicht. Pauschal betrachtet, sind Konsistenz und Transaktionalität kein Argument gegen Microservices.

Argument #4: Entwicklungs- und Betriebskosten

Kommen wir zum fünften Argument gegen Microservices, nämlich den angeblich höheren Entwicklungs- und Betriebskosten. Häufig wird behauptet, Microservices seien ein Problem, weil ein einzelnes Team mit den zahlreichen Services zu viele Kontextwechsel hätte. Und wissen Sie was? Da bin ich ganz bei Ihnen! Es hat allerdings auch niemand gefordert, dass Sie Microservices mit einem einzigen Team umsetzen sollen.

Im Gegenteil! Eigentlich ist das Konzept der Microservices, bei dem es, wie anfangs erwähnt, um Unabhängigkeit geht, nämlich prädestiniert dafür, dass man mit unterschiedlichen Teams parallel an den verschiedenen Services arbeiten kann. Das heißt natürlich nicht, dass sich Microservices nur dann umsetzen lassen, wenn pro Service ein dediziertes Team bereitsteht. Aber es gibt ja noch etwas zwischen den Extremen. Meiner Meinung nach ist es überhaupt kein Problem, wenn ein Team eine Handvoll Services betreut (je nachdem, wie komplex und umfangreich die Services sind).

Wenn Sie aber an dem Punkt sind, wo ein einzelnes Team 20 oder gar 50 Services betreuen müsste, dann sind entweder die Services falsch geschnitten, Ihr Team ist falsch aufgestellt oder Sie haben schlicht und ergreifend zu wenige Teams. Daher sind Microservices primär dann sinnvoll, wenn es um das fachliche Zerlegen geht, wenn es um Unabhängigkeit geht, und wenn diese Unabhängigkeit sich auch in den Organisationsstrukturen widerspiegelt. Ansonsten wird es vermutlich eher schwierig werden. Wenn man aber mehrere Teams hat, dann sind Microservices ein sehr praktischer Ansatz, weil sie es dann nämlich erlauben, den Fokus auf nur einen Teil der Domäne legen zu müssen, und weil sie klare und explizite Schnittstellen erzwingen.

Und was die Betriebskosten angeht: Hier wird oft mit Monitoring, Logging, Alerting und so weiter argumentiert. Aber mal ganz ehrlich: Das brauchen Sie doch für einen Monolithen genauso? Und wo ist jetzt der große Unterschied, ob man nun 2 oder 20 oder 200 Container überwachen muss? Tatsächlich verstehe ich hier den Punkt nicht, denn der Aufwand steigt nicht linear mit der Anzahl der Container, sondern den größten Aufwand hat man damit, das ganze Monitoring & Co. an sich überhaupt einmal einzurichten und aufzusetzen. Wenn das jedoch einmal erledigt ist, stellt der Rest eher das i-Tüpfelchen dar, was den Aufwand angeht.

Argument #5: Koordination und Kommunikation

Und damit kommen wir zum fünften häufig genannten Argument gegen Microservices, nämlich den organisatorischen Herausforderungen. Hier wird in der Regel die zusätzlich notwendige Koordination und Kommunikation zwischen den Teams beklagt. Dabei geht es um Fragen wie:

  • Wer macht was?
  • Wer definiert welche API?
  • Wer richtet sich nach wem?

Um diese Fragen zu klären, gibt es zahlreiche etablierte API-Patterns [12]. Tatsächlich finde ich von allen genannten Argumenten dieses das mit Abstand schwächste, denn Microservices schneidet man ja nicht irgendwie, sondern entlang fachlicher Grenzen. Und dieses Schneiden entlang fachlicher Grenzen muss ohnehin gemacht werden, auch wenn man einen Monolithen baut, denn auch bei Modulen und Komponenten muss überlegt werden, wie und wo geschnitten wird.

Würde man das einfach nicht machen, bekäme man sehr schnell den berühmt-berüchtigten "Big Ball of Mud". Das heißt, wenn dieses Schneiden ohnehin erforderlich ist und wenn man sich dazu ohnehin Gedanken machen muss über Zuständig- und Verantwortlichkeiten, dann ist auch der Aufwand in jedem Fall der gleiche. Daran ändert sich nichts, ob diese Diskussionen nun innerhalb eines einzelnen Teams oder über mehrere Teams hinweg verteilt stattfinden. Der große Vorteil von Microservices ist dann, dass sie die Teams dazu zwingen, diese Diskussionen ordentlich und sorgfältig zu führen, ganz einfach deshalb, weil eine fachliche Grenze zugleich auch eine echte technische Grenze darstellt, die sich nicht ignorieren lässt.

Fazit

Es ergeben sich also folgende fünf Aspekte:

  1. Man sollte hinterfragen, ob man die Notwendigkeit zum fachlichen Zerlegen hat.
  2. Was Deployment und Infrastruktur angeht, sprechen diese eher für Services, weil das den teuersten Teil des Ganzen (nämlich die fachliche Entwicklung) vereinfacht.
  3. Man muss die Konsistenz hinterfragen, aber das ist kein technisches, sondern ein fachliches Problem.
  4. Die Entwicklung von Microservices funktioniert besonders dann gut, wenn man auch organisatorisch verteilt aufgestellt ist, sprich, in mehreren Teams entwickelt.
  5. Koordination und Kommunikation sind in jedem Fall erforderlich, das macht daher schlussendlich keinen nennenswerten Unterschied.

Services und insbesondere Microservices lohnen sich als Architekturansatz dann, wenn man fachlich gesehen sehr komplexe Anwendungen baut und/oder wenn man mehrere Teams hat, die an einem großen Projekt zusammenarbeiten müssen, man sich dabei jedoch eine gewisse Unabhängigkeit bewahren möchte. Und wenn das gegeben ist, dann sind Microservices höchstwahrscheinlich eine gute Idee, andernfalls wahrscheinlich eher nicht oder nur bedingt.

Und jetzt mal ganz ehrlich: Ist diese Erkenntnis wirklich eine Überraschung? Ich glaube nicht … stattdessen gilt wieder einmal, dass man das richtige Werkzeug für das vorliegende Problem auswählen sollte, und man deshalb einen gewissen Überblick über die zur Verfügung stehenden Werkzeuge haben sollte. Wer hingegen nur einen Hammer kennt, für die oder den wird jedes Problem wie ein Nagel aussehen.


URL dieses Artikels:
https://www.heise.de/-9800271

Links in diesem Artikel:
[1] https://www.heise.de/blog/Zwoelf-Regeln-fuer-die-perfekte-Micro-Services-Architektur-9792599.html
[2] https://www.thenativeweb.io/
[3] https://www.heise.de/Datenschutzerklaerung-der-Heise-Medien-GmbH-Co-KG-4860.html
[4] https://www.primevideotech.com/video-streaming/scaling-up-the-prime-video-audio-video-monitoring-service-and-reducing-costs-by-90
[5] https://www.youtube.com/watch?v=IDTCPI3phss
[6] https://de.wikipedia.org/wiki/Andrew_S._Tanenbaum
[7] https://de.wikipedia.org/wiki/Verteiltes_System
[8] https://www.youtube.com/watch?v=aApAZMfp4Nw
[9] https://www.youtube.com/watch?v=AFRsix3jHXU
[10] https://www.youtube.com/watch?v=DESdVoKhIxY
[11] https://www.youtube.com/watch?v=1SaPfm96lY4
[12] https://www.youtube.com/watch?v=n47RSfeFIy8
[13] mailto:who@heise.de

Copyright © 2024 Heise Medien

Adblock test (Why?)

  • 17. Juli 2024 um 11:37

Neu in .NET 8.0 [29]: Verbesserungen für den JSON-Source-Generator

Von Dr. Holger Schwichtenberg
Druckplatten mit Buchstaben

(Bild: RossEdwardCairney/Shutterstock.com)

Der Source Generator ist in .NET 8.0 wichtiger, damit die JSON-Serialisierung und -Deserialisierung auch AOT-Anwendungen funktioniert.​

System.Text.Json nimmt im Standard das Mapping von JSON auf .NET-Objekte per Laufzeitcodegenerierung vor. Schon seit der Version 6.0 gibt es in System.Text.Json auch einen Source-Generator. Dieser erzeugt den Mapping-Code bereits zur Entwicklungszeit, sodass keine Laufzeitcodegenerierung notwendig ist. Der JSON-Source-Generator war (und ist) ein wichtiges Instrument für die Leistungsoptimierung.

Mit Ausdehnung des Native-AOT-Compilers auf ASP.NET Core Web APIs ist er aber nochmals wichtiger geworden, denn bei Native AOT ist keine Laufzeitkompilierung möglich.

Der JSON-Source-Generator bietet in System.Text.Json Version 8.0 folgende neuen Möglichkeiten:

  • Der Source Generator für JSON (Text.Json.SourceGeneration.JsonSourceGenerator) unterstützt nun auch die in C# 9.0 eingeführten Init-Only-Properties und die in C# 11.0 eingeführten Required Properties.
  • Entwickler können per Projekteinstellung dafür sorgen, dass System.Text.Json gar keine Laufzeitcodegenerierung mehr ausführt: <JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault>
  • Entwickler können im Programmcode mit einem statischen Mitglied abfragen, ob eine Laufzeitcodegenerierung möglich ist: IsReflectionEnabledByDefault
  • Zu den Neuerungen in System.Text.Json 8.0 gehört auch, dass die Annotation [JsonSourceGenerationOptions] nun alle Optionen bietet, die auch die Klasse JsonSerializerOptions beim imperativen Programmieren mit der Klasse Text.Json. JsonSerializer erlaubt.

Wenn die Laufzeitcodegenerierung im JSON-Serializer abgeschaltet ist, man aber dennoch eine Serialisierung ohne Source Generator versucht (etwa JsonSerializer.Serialize(new { value = 42 });), kassiert man folgende Fehlermeldung: "Reflection-based serialization has been disabled for this application. Either use the source generator APIs or explicitly configure the 'JsonSerializerOptions.TypeInfoResolver' property."

Wenn die Laufzeitcodegenerierung im JSON-Serializer abgeschaltet ist, muss man eine von JsonSerializerContext abgeleitete Klasse erschaffen, die per Annotation [JsonSerializable] die Verweise auf die zu (de)serialisierenden .NET-Klassen erhält. Optional kann man die Einstellung per [JsonSourceGenerationOptions] vornehmen.

Die im folgenden Code verwendeten Klassen Consultant und Person waren bereits im Beispielcode zum vorherigen Teil der Serie [35]:

[JsonSerializable(typeof(Address))]
[JsonSerializable(typeof(Person))] 
[JsonSerializable(typeof(Consultant))]
[JsonSourceGenerationOptions(PreferredObjectCreationHandling 
 =JsonObjectCreationHandling.Populate)]
 
internal partial class PersonJsonContext : JsonSerializerContext
{
}

Diese Klasse muss man dann in den Serialisierungsoptionen festlegen:

var options = new JsonSerializerOptions
{
 TypeInfoResolver = PersonJsonContext.Default
};

Das folgende Listing zeigt, dass in System.Text.Json nun ein erforderliches Mitglied, das beim Deserialisieren nicht befüllt wird, auch bei JSON-Source-Generator zum Laufzeitfehler führt.

try
{
 var jsonString = """
 {"FULL-NAME":"Holger Schwichtenberg","PERSONAL-WEBSITE":"www.dotnet-doktor.de"}
 """;
 Console.WriteLine("JSON: " + jsonString);
 var obj = JsonSerializer.Deserialize<Consultant>(jsonString, options);
 if (obj != null) CUI.Success(obj.ToString());
}
catch (Exception ex)
{
 CUI.PrintError(ex.Message); // JSON deserialization for type 'NET8Konsole.Consultant' was missing required properties, including the following: ID !!! Vor .NET 8.0 wäre hier in Verbindung mit Source Generator KEIN Laufzeitfehler aufgetreten. ID war = 0
}


URL dieses Artikels:
https://www.heise.de/-9798297

Links in diesem Artikel:
[1] https://www.heise.de/blog/Neu-in-NET-8-0-1-Start-der-neuen-Blogserie-9574680.html
[2] https://www.heise.de/blog/Neu-in-NET-8-0-2-Neue-Anwendungsarten-9581213.html
[3] https://www.heise.de/blog/Neu-in-NET-8-0-3-Primaerkonstruktoren-in-C-12-0-9581346.html
[4] https://www.heise.de/blog/Neu-in-NET-8-0-4-Collection-Expressions-in-C-12-0-9581392.html
[5] https://www.heise.de/blog/Neu-in-NET-8-0-5-Typaliasse-in-C-12-0-9594693.html
[6] https://www.heise.de/blog/Neu-in-NET-8-0-6-ref-readonly-in-C-12-0-9602188.html
[7] https://www.heise.de/blog/Neu-in-NET-8-0-7-Optionale-Parameter-in-Lambda-Ausdruecken-in-C-12-0-9609780.html
[8] https://www.heise.de/blog/Neu-in-NET-8-0-8-Verbesserungen-fuer-nameof-in-C-12-0-9616685.html
[9] https://www.heise.de/blog/Neu-in-NET-8-0-9-Neue-und-erweiterte-Datenannotationen-9623061.html
[10] https://www.heise.de/blog/Neu-in-NET-8-0-10-Plattformneutrale-Abfrage-der-Privilegien-9630577.html
[11] https://www.heise.de/blog/Neu-in-NET-8-0-11-Neue-Zufallsfunktionen-9637003.html
[12] https://www.heise.de/blog/Neu-in-NET-8-0-12-Eingefrorene-Objektmengen-9643310.html
[13] https://www.heise.de/blog/Neu-in-NET-8-0-12-Leistung-von-FrozenSet-9649523.html
[14] https://www.heise.de/blog/Neu-in-NET-8-0-14-Neue-Waechtermethoden-fuer-Parameter-9656153.html
[15] https://www.heise.de/blog/Neu-in-NET-8-0-15-Geschluesselte-Dienste-bei-der-Dependency-Injection-9662004.html
[16] https://www.heise.de/blog/Neu-in-NET-8-0-16-Neue-Methoden-fuer-IP-Adressen-9670497.html
[17] https://www.heise.de/blog/Neu-in-NET-8-0-17-Zeitabstraktion-fuer-Tests-mit-Zeitangaben-9675891.html
[18] https://www.heise.de/blog/Neu-in-NET-8-0-18-Ein-Zeitraffer-mit-eigenem-FakeTimeProvider-9683197.html
[19] https://www.heise.de/blog/Neu-in-NET-8-0-19-Razor-HTML-Rendering-in-beliebigen-NET-Anwendungen-9691146.html
[20] https://www.heise.de/blog/Neu-in-NET-8-0-20-Neue-Code-Analyzer-fuer-NET-Basisklassen-9706875.html
[21] https://www.heise.de/blog/Neu-in-NET-8-0-20-Neue-Code-Analyzer-fuer-ASP-NET-Core-9710151.html
[22] https://www.heise.de/blog/Neu-in-NET-8-0-22-Neues-Steuerelement-OpenFolderDialog-fuer-WPF-9722901.html
[23] https://www.heise.de/blog/Neu-in-NET-8-0-23-Verbesserungen-fuer-ZipFile-zur-Arbeit-mit-Dateiarchiven-9722920.html
[24] https://www.heise.de/blog/Neu-in-NET-8-0-24-HTTPS-Proxies-bei-HttpClient-9722968.html
[25] https://www.heise.de/blog/Neu-in-NET-8-0-25-Resilienz-im-HTTP-Client-9763586.html
[26] https://www.heise.de/blog/Neu-in-NET-8-0-26-Anpassung-der-Resilienz-im-HTTP-Client-9773126.html
[27] https://www.heise.de/blog/Neu-in-NET-8-0-27-Konfigurierbare-Namenskonventionen-in-System-Text-Json-8-0-9784360.html
[28] https://www.heise.de/blog/Neu-in-NET-8-0-28-Erweiterung-fuer-die-Deserialisierung-von-JSON-Objekten-9790704.html
[29] https://www.heise.de/blog/Neu-in-NET-8-0-29-Verbesserungen-fuer-den-JSON-Source-Generator-9798297.html
[30] https://www.heise.de/blog/Neu-in-NET-8-0-30-Neue-Datentypen-in-System-Text-Json-8-0-9808793.html
[31] https://www.heise.de/blog/Neu-in-NET-8-0-31-Erweiterte-Serialisierung-in-System-Text-Json-8-0-9814260.html
[32] https://net.bettercode.eu/
[33] https://net.bettercode.eu/index.php#programm
[34] https://net.bettercode.eu/tickets.php
[35] https://www.heise.de/blog/Neu-in-NET-8-0-28-Erweiterung-fuer-die-Deserialisierung-von-JSON-Objekten-9790704.html
[36] mailto:rme@ix.de

Copyright © 2024 Heise Medien

Adblock test (Why?)

  • 12. Juli 2024 um 09:19

Zwölf Regeln für die perfekte (Micro-)Services-Architektur

Von Golo Roden
Puzzleteile, die teilweise zusammen und teilweise lose sind

(Bild: Shutterstock.com/Kenishirotie)

Services versprechen eine einfache, zielgerichtetete und fachlich adäquate Softwareentwicklung. Doch worauf sollte man bei ihrem Bau achten?

Häufig wird Entwicklerinnen und Entwicklern empfohlen, auf Services als Architektur zu setzen. Doch ist es gar nicht so einfach, Services derart zu bauen, dass sie nachher gleichermaßen schlank und skalierbar sind. Kommen dann Zweifel am eigenen Vorgehen hinzu, wird die Beschäftigung mit Services schnell zum Bremsklotz. Vor vielen Jahren gab es von Heroku für Cloud-Native-Anwendungen die Empfehlung der 12-Factor-Apps [1]: zwölf Regeln, die sich – laut Heroku – als tragfähige Basis erwiesen haben. Doch teilweise sind diese Regeln in die Jahre gekommen, außerdem wurden sie nie explizit für Services gemacht.

Was liegt also näher, als das Ganze aufzugreifen, mit der eigenen Erfahrung der vergangenen Jahre im Bereich der Konzeption und Entwicklung von Web- und Cloud-Services zu kombinieren, und zwölf aktualisierte Regeln aufzustellen? Genau das versuche ich in diesem Blogpost.

Eines sage ich jedoch direkt vorneweg: Die Auswahl der Regeln ist natürlich (wie auch damals bei Heroku) subjektiv und gefärbt. Das, was für uns bei der the native web GmbH [2] gut funktioniert, muss nicht für alle gut funktionieren. Wie es im Englischen so schön heißt: Your mileage may vary (YMMV) [3].

Regel #1: Fachlichkeit im Vordergrund

Die erste Regel wird vermutlich häufig belächelt, dennoch halte ich sie für die wichtigste schlechthin. Und auch, wenn viele sagen werden "das ist doch logisch, das braucht man doch nicht extra zu erwähnen", zeigt mir die Praxis, dass sie in 99 von 100 Fällen ignoriert wird. Die erste Regel lautet nämlich: Vor dem Entwickeln muss klar sein, was das fachliche Problem ist, das der Anwendung zugrunde liegt. Wer das nicht beantworten kann, wird nicht in der Lage sein, eine zielgerichtete und fachlich adäquate Lösung zu entwickeln, und zwar völlig unabhängig von der eingesetzten Technologie.

Daher: Man sollte als allererstes ein robustes, fundiertes und detailliertes fachliches Verständnis der entsprechenden Domäne aufbauen. Es ist dabei völlig zweitrangig, ob man dafür Domain-Driven Design (DDD) oder sonst irgendeine Methodik verwendet, aber man muss gedanklich von CRUD (Create, Read, Update, Delete) wegkommen, ansonsten baut man bestenfalls "Forms over Data", trifft aber nicht den eigentlichen Kern der Sache. CRUD ist ein Anti-Pattern [5], das es zu vermeiden gilt.

Regel #2: Services, Instanzen und Prozesse

Die zweite Regel besagt, dass ein Service stets genau einem Betriebssystemprozess entspricht. Mit anderen Worten: Ein einzelner Service besteht nicht aus zig unterschiedlichen Programmen, sondern ein Service besteht aus einer Codebase für einen Prozess in einem Git-Repository. Wenn von diesem Service mehrere Instanzen gestartet werden sollen, dann laufen natürlich mehrere Prozesse, aber pro Instanz gibt es jeweils nur genau einen Betriebssystemprozess.

Das heißt auch, dass man nicht mehrere Services in einem gemeinsamen Git-Repository unterbringt, sondern dass jeder Service über ein eigenes Repository verfügt. Der Grund dafür ist einfach: Nur auf dem Weg ist sichergestellt, dass jeder Service unabhängig gepflegt, versioniert, dokumentiert, deployed, … werden kann. Außerdem ermöglicht das Zuordnen von Services zu Repositories ein feingranulares Verwalten der Berechtigungen auf den Code der jeweiligen Services.

Regel #3: Ein Build-Skript für alle Systeme

Die dritte Regel fordert, dass es für das Bauen eines Services ein Skript gibt, das überall lauffähig ist. Die Technologie ist dabei völlig zweitrangig, theoretisch genügt ein einfaches Makefile. Der springende Punkt ist: Um vom Quellcode zum ausführbaren Binary zu kommen, darf nicht mehr Aufwand erforderlich sein, als einen einzigen Befehl auszuführen. Dieser Befehl kompiliert und linkt dabei nicht nur, sondern führt auch die Tests aus, die Codeanalyse und alles Weitere, was um den Build herum noch existiert.

Wichtig ist, dass dieses Skript in identischer Form auf jedem Rechner im Team lauffähig ist, das heißt, jede Entwicklerin und jeder Entwickler im Team kann eigenständig lokal bauen, und das identische Skript wird auch im Build-Schritt der CI/CD-Pipeline verwendet. Das Skript muss (abgesehen vom Einrichten gegebenenfalls erforderlicher Berechtigungen) erfolgreich ausführbar sein, nachdem man das Repository geklont und die Abhängigkeiten installiert hat. Alles, was darüber hinausgeht, ist unnötiger manueller Aufwand.

Regel #4: Stabiler main-Branch für Releases

Was in den Build mit hineinspielt, ist die vierte Regel, die sich mit einer passenden Branching-Strategie beschäftigt: Konkret sieht diese Strategie so aus, dass es einen main-Branch gibt, der per definitionem als stabil angesehen wird. Jegliche Entwicklung, sei es das Hinzufügen neuer Features, das Beheben von Bugs oder sonst etwas, passiert in gesonderten Branches, die von main abzweigen und nachher wieder nach main gemerged werden (das entspricht dem klassischen Ansatz von Feature-Branches).

Der einzige Weg, einen solchen Merge nach main durchzuführen, ist per Pull Request, bei dem auch wieder sämtliche Tests, Codeanalyse & Co. laufen. Außerdem muss jeder Pull Request, bevor er nach main gemerged werden kann, gründlich gereviewed werden. Außer dem stabilen Produktions-Branch main gibt es ansonsten also ausschließlich kurzlebige Branches, die sich um main herum ranken. Und jedes Mal, wenn ein Branch nach main gemerged wird, wird dieser gesquashed, und auf der neuen Basis von main ein neues Release des Services mithilfe von Semantic Versioning [6] gebaut.

Regel #5: Versionierte Container

Die fünfte Regel besagt, dass jeder durch einen Pull Request erzeugte Commit auf main nicht nur eine neue Version erzeugt, sondern auch ein neues Docker-Image, das ebenfalls versioniert ist. Auf dem Weg lässt sich jeder x-beliebige Stand des Services jederzeit im Nachhinein anhand seiner Versionsnummer entweder als Binary oder als komplettes Docker-Image herunterladen und ausführen.

Wichtig dabei ist, dass der Service zügig startet, weshalb auch im Docker-Image nicht mehr gebaut werden darf. Stattdessen muss das alles bereits vorher erfolgt sein. Hier bieten sich Multi-Stage-Builds [7] an, um das finale Produktiv-Image möglichst sauber und klein zu halten. Da Container damit rechnen müssen, jederzeit abgeschossen zu werden, darf es keine speziellen Anforderungen an einen Graceful-Shutdown des Dienstes geben.

Regel #6: Eine HTTP-basierte CQRS-API

Nachdem sich die vorangegangenen Punkte im Wesentlichen auf die Infrastruktur für Services bezogen haben, kommen wir nun zum Inhaltlichen. Jeder Service verfügt über eine API, über die er von außen angesprochen werden kann. Standardmäßig handelt es sich dabei um eine ganz klassische HTTP-API, also kein GRPC, kein GraphQL, ja noch nicht einmal HTTPS. Der Grund dafür ist einfach: Solange man auf einfaches, unverschlüsseltes HTTP setzt, lässt sich die API einfach testen und debuggen. Außerdem ist HTTP kompatibel zu praktisch jeder Technologie und Plattform, man braucht keinen speziellen Client (theoretisch genügt sogar curl), und man spart sich jeglichen Aufwand mit Zertifikaten und Co.

Diese HTTP-API besteht dabei aus drei Teilen:

  • Zum einen gibt es die fachlichen Commands. Das sind POST-Routen, die irgendeine fachliche Veränderung im Service bewirken.
  • Zweitens gibt es die fachlichen Queries. Das sind GET-Routen, die Daten aus dem Service abfragen und zurückgeben.
  • Drittens gibt es noch ein paar technische Routen, allen voran eine Ping- und eine Health-Route, um zu ermitteln, ob der Service überhaupt läuft und, wenn ja, wie sein Zustand ist.

Wem Commands und Queries als Begriffe nicht viel sagen, schaut sich das Design-Pattern CQRS [8] an. Dort schließt sich auch der Kreis zu der ersten Regel, die fordert, die Fachlichkeit und nicht CRUD in den Vordergrund zu rücken.

Regel #7: Alternative Protokolle

Fraglos ist reines HTTP kein besonders zeitgemäßes Protokoll mehr, hier ist eher HTTPS gefragt. Für die interne Service-zu-Service-Kommunikation möchte man darüber hinaus vielleicht auch eine gRPC-Schnittstelle haben. Grundsätzlich spricht nichts dagegen, solche Schnittstellen zusätzlich zur HTTP-Schnittstelle einzubauen. Aber man sollte eben nicht mit gRPC, GraphQL & Co. starten, denn klassisches HTTP ist weitaus einfacher in der Handhabung.

Was HTTPS angeht, ist es übrigens eine Überlegung wert, es nicht direkt im Service umzusetzen, sondern den davor liegenden Reverse-Proxy die TLS-Terminierung übernehmen zu lassen: Dieser kann die TLS-Terminierung dann nämlich direkt für alle Services übernehmen, wodurch man dieses Thema an einem zentralen Punkt gebündelt hat.

Regel #8: Statuslos und mit Loadbalancer

Apropos Reverse Proxy: Er kann nicht nur die TLS-Terminierung übernehmen, sondern auch das Loadbalancing über mehrere Instanzen eines Services hinweg. Damit das reibungslos funktioniert, müssen Services stets zustandslos sein. Jede eingehende Anfrage wird also verarbeitet, eine Antwort wird zurückgegeben, und danach wird alles, was im Rahmen dieser Anfrage geschehen ist, von der jeweiligen Service-Instanz wieder vergessen.

Wenn Informationen tatsächlich langlebiger sein sollen, müssen sie in einer Datenbank oder einem anderen Speicher persistiert werden. Nur auf diese Art ist sichergestellt, dass es egal ist, welche Instanz des Services eine eingehende Anfrage vom Loadbalancer zugewiesen bekommt.

Regel #9: Kommunikation über das Netzwerk

Die neunte Regel besagt, dass das Anbinden einer externen Ressource wie einer Datenbank oder einer Message-Queue über deren API erfolgen muss. Mit anderen Worten: Ein anderer Dienst wird stets über seine Netzwerkschnittstelle angesprochen und man verlässt sich nie darauf, dass er lokal auf anderem Wege erreichbar wäre. Außerdem erfolgt jeder Zugriff über die offizielle Schnittstelle und man greift niemals direkt auf Dateien oder andere Interna zu.

Ein anderer Service ist als Blackbox anzusehen und als solche sollte man die einzelnen Services dann auch behandeln. Das ist übrigens auch ein Grund dafür, warum ich geschrieben habe, dass jeder Service seine Funktionalität über eine API zur Verfügung stellen muss: Denn gemäß dieser Regel ist das der einzige Weg, auf dem ein Service von außen angesprochen werden darf.

Regel #10: Konfiguration per Umgebungsvariablen

Die zehnte Regel fordert, dass ein Service über Umgebungsvariablen konfiguriert wird. Theoretisch kann man auch mit Flags auf der Kommandozeile arbeiten, aber diese sollten (wenn überhaupt) nur optional unterstützt werden. Den Standardweg schlechthin bilden Umgebungsvariablen. Auch hier ist der Grund wieder sehr einfach: Umgebungsvariablen sind der einzige Mechanismus, der unabhängig von der konkreten zugrunde liegenden Plattform oder dem Betriebssystem funktioniert, und bei dem es keine syntaktischen Unterschiede zwischen den verschiedenen Ansätzen gibt.

Das ist bei Flags nicht gegeben und bei Konfigurationsdateien erst recht nicht: Hier hat man es rasch mit verschiedenen Encodings, Dateiformaten, Line-Endings, … zu tun. Außerdem lassen sich Umgebungsvariablen sowohl global als auch gezielt nur für einen einzelnen Prozess definieren (was für mehrere Instanzen auf einer Maschine ausgesprochen praktisch sein kann). Hinzu kommt, dass sie gut von Docker und Kubernetes unterstützt werden und man mit ihnen im Vergleich insgesamt sehr viel weniger Stolperfallen hat. Anders als Konfigurationsdateien kann man Umgebungsvariablen außerdem nicht aus Versehen in Git einchecken.

Regel #11: Log-Ausgabe auf die Konsole

Die elfte Regel besagt, dass jeder Service Log-Ausgaben erzeugen sollte, damit nachvollziehbar ist, was wann vorgefallen ist. Log-Ausgaben sollten aber nicht in eine Datei geschrieben werden. Denn diese landet im Zweifelsfall innerhalb eines Docker-Containers, wo sie beim Beenden des Containers mit ihm gelöscht wird. Weitaus besser ist es, Log-Ausgaben auf die Konsole zu schreiben, da man sie dann entsprechend abfangen, umleiten und an beliebiger Stelle verarbeiten kann.

Abgesehen von der viel flexibleren und besseren Verarbeitbarkeit macht das auch den Code des Services einfacher und es funktioniert zudem auch lokal, ohne Abhängigkeit von Dateipfaden, Log-Servern oder ähnlichem. Wer hier das Nonplusultra haben möchte, kann innerhalb des Services ermitteln, ob er interaktiv aus einer Shell heraus oder per Skript gestartet wurde, und die Ausgabe dementsprechend entweder menschenlesbar oder als JSON erzeugen. Tatsächlich haben wir das bei the native web früher häufig gemacht, inzwischen begnügen wir uns aber mit JSON. Denn auch JSON ist für Menschen immer noch gut lesbar, aber es vereinfacht erneut den Code, wenn man auf diese Unterscheidung verzichten kann.

Regel #12: Token-basierte Security

Die zwölfte Regel tangiert den Bereich der Sicherheit, auch wenn es hierzu sicherlich viel mehr zu sagen gäbe. Doch es gibt zwei Grundregeln:

  1. Jegliche Authentifizierung und Autorisierung erfolgt auf der Basis von Tokens.
  2. Ein Service erhält niemals höhere Rechte in der Ausführung, als er für den normalen Betriebsablauf benötigt. Wenn höhere Rechte erforderlich sind, um beispielsweise initial die Datenbank einzurichten, gibt es dafür ein Hilfsprogramm, das mit erhöhten Berechtigungen einmalig ausgeführt wird.

Auf dem Weg erhält man die erhöhten Rechte bei Bedarf, kommt aber im normalen Alltag mit einfachen Berechtigungen aus.

Das Patentrezept?

Wer diese zwölf Regeln zusammennimmt, hat eine gute Vorstellung davon, wie wir bei the native web an Services herangehen. Bei meiner Beschreibung habe ich einiges gestreift, vom Repository über die Infrastruktur und CI/CD bis hin zur eigentlichen Codebasis. Wir haben mit diesem Ansatz in den vergangenen Jahren sehr, sehr gute Erfahrungen gemacht. Aber, wie eingangs schon erwähnt, muss das nicht gleichermaßen für alle gelten. Vielleicht haben andere Teams andere Arten von Services, haben ein anderes Wertesystem, oder …

Eine letzte Kleinigkeit möchte ich aber noch erwähnen, die uns schon oft geholfen hat. Wie erwähnt, sehen wir den main-Branch als stabilen und versionierten Stand an. Dementsprechend leicht lässt sich ein solcher Stand deployen, aber wir machen das nicht automatisch: Wir sind überzeugt, dass bei Produktiv-Deployments letztlich ein Mensch die Kontrolle darüber haben sollte, für welche Kunden welche konkrete Version aus welchem Grund ausgeliefert wird.

Aber: Aufgrund der beschriebenen Struktur können wir natürlich auch für jeden Pull Request ein Docker-Image bauen, das anhand der Pull-Request-ID benannt wird. Kombiniert man das mit einem automatischen Deployment auf eine ebenfalls nach der Pull-Request-ID benannten Subdomain, erhält man für jeden Feature-Branch automatisch stets aktuelle Preview-Deployments. Es gibt somit nicht eine Test-Umgebung, sondern für jeden Pull Request wird dynamisch eine eigene aufgebaut – und nach dem Schließen des Pull Request wieder verworfen. Auf dem Weg lässt sich häufig zu einer viel besseren Einschätzung kommen, ob ein Branch schon gemerged werden kann oder nicht.

Damit ein solches Deployment funktioniert, benötigt man natürlich eine entsprechende Infrastruktur, die vollkommen automatisch Subdomains und Zertifikate einrichten kann, die Datenbanken bereitstellen kann, und so weiter. Die für uns beste Infrastruktur dafür ist Kubernetes, was sich vielleicht auch in einigen unserer Design-Entscheidungen widerspiegelt.


URL dieses Artikels:
https://www.heise.de/-9792599

Links in diesem Artikel:
[1] https://www.youtube.com/watch?v=91yfdjVMSuo
[2] https://www.thenativeweb.io/
[3] https://dictionary.cambridge.org/de/worterbuch/englisch/ymmv
[4] https://www.heise.de/Datenschutzerklaerung-der-Heise-Medien-GmbH-Co-KG-4860.html
[5] https://www.youtube.com/watch?v=MoWynuslbBY
[6] https://www.youtube.com/watch?v=nOVZxZX5dx8
[7] https://www.youtube.com/watch?v=3YP0eUHdLc8
[8] https://www.youtube.com/watch?v=nDSwyowKYP8
[9] mailto:rme@ix.de

Copyright © 2024 Heise Medien

Adblock test (Why?)

  • 10. Juli 2024 um 11:35

Neu in .NET 8.0 [28]: Erweiterung für die Deserialisierung von JSON-Objekten

Von Dr. Holger Schwichtenberg
Karteikasten auf dem Schreibtisch

(Bild: rawf8/Shutterstock.com)

System.Text.Json 8.0 bietet eine neue Einstellung zur Handhabung zusätzlicher Informationen bei der Deserialisierung von JSON in Objekten.

Bei der neu eingeführten Funktion UnmappedMemberHandling geht es darum, wie sich System.Text.Json verhält, wenn beim Deserialisieren mehr Eigenschaften vorhanden sind als Properties im Objekt.

Im folgenden Beispielcode gibt es in dieser JSON-Zeichenkette eine Eigenschaft "CITY", aber es existiert kein korrespondierendes Property City in der Klasse Consultant und deren Basisklasse Person.

Die Klassen Consultant und Person wurden im vorherigen Teil [1] schon verwendet und hier nicht noch mal wiedergegeben. Die Einstellung der Namenskonvention wurde ebenfalls besprochen.

try
{
 var jsonString = """
 {
 "ID":42,
 "FULL-NAME":"Holger Schwichtenberg",
 "PERSONAL-WEBSITE":"www.dotnet-doktor.de",
 "CITY":"Essen"
 }
 """;
 Console.WriteLine("JSON: " + jsonString);
 var obj = JsonSerializer.Deserialize<Consultant>(jsonString, options);
 if (obj != null) CUI.Success(obj.ToString());
}
catch (Exception ex)
{
 CUI.PrintError(ex.Message); 
}

Bisher hätte System.Text.Json zusätzlichen Informationen einfach ignoriert. Das ist auch im Standard weiterhin so. Via Annotation [JsonUnmappedMemberHandling] auf der zu deserialisierenden Klasse oder Eigenschaft UnmappedMemberHandling im Objekt JsonSerializerOptions können Entwicklerinnen und Entwickler dies nun ändern: Erlaubte Werte sind Skip (Ignorieren wie bisher) und Disallow.

Die folgende Einstellung von Disallow löst also beim obigen Deserialize() einen Laufzeitfehler aus: "The JSON property 'CITY' could not be mapped to any .NET member contained in type 'FCL_JSON.Consultant'."

var options = new JsonSerializerOptions
{
 // NEU: Enumeration JsonNamingPolicy mit Namenskonventionen 
 // KebabCaseLower, KebabCaseUpper, SnakeCaseLower 
 // und SnakeCaseUppter als Alternative zum 
 // bisher fest gesetzten CamelCase
 PropertyNamingPolicy = JsonNamingPolicy.KebabCaseUpper, 
 // Standard wäre CamelCase
 
 // NEU: Einstellungen zur Handhabung zusätzlicher Daten
 // bei der Deserialisierung von JSON in Objekten 
 // via Annotation [JsonUnmappedMemberHandling] 
 // oder Eigenschaft UnmappedMemberHandling 
 // im Objekt JsonSerializerOptions.
 UnmappedMemberHandling = JsonUnmappedMemberHandling.Disallow, 
 // Default wäre Skip
};


URL dieses Artikels:
https://www.heise.de/-9790704

Links in diesem Artikel:
[1] https://www.heise.de/blog/Neu-in-NET-8-0-27-Konfigurierbare-Namenskonventionen-in-System-Text-Json-8-0-9784360.html
[2] https://www.heise.de/blog/Neu-in-NET-8-0-1-Start-der-neuen-Blogserie-9574680.html
[3] https://www.heise.de/blog/Neu-in-NET-8-0-2-Neue-Anwendungsarten-9581213.html
[4] https://www.heise.de/blog/Neu-in-NET-8-0-3-Primaerkonstruktoren-in-C-12-0-9581346.html
[5] https://www.heise.de/blog/Neu-in-NET-8-0-4-Collection-Expressions-in-C-12-0-9581392.html
[6] https://www.heise.de/blog/Neu-in-NET-8-0-5-Typaliasse-in-C-12-0-9594693.html
[7] https://www.heise.de/blog/Neu-in-NET-8-0-6-ref-readonly-in-C-12-0-9602188.html
[8] https://www.heise.de/blog/Neu-in-NET-8-0-7-Optionale-Parameter-in-Lambda-Ausdruecken-in-C-12-0-9609780.html
[9] https://www.heise.de/blog/Neu-in-NET-8-0-8-Verbesserungen-fuer-nameof-in-C-12-0-9616685.html
[10] https://www.heise.de/blog/Neu-in-NET-8-0-9-Neue-und-erweiterte-Datenannotationen-9623061.html
[11] https://www.heise.de/blog/Neu-in-NET-8-0-10-Plattformneutrale-Abfrage-der-Privilegien-9630577.html
[12] https://www.heise.de/blog/Neu-in-NET-8-0-11-Neue-Zufallsfunktionen-9637003.html
[13] https://www.heise.de/blog/Neu-in-NET-8-0-12-Eingefrorene-Objektmengen-9643310.html
[14] https://www.heise.de/blog/Neu-in-NET-8-0-12-Leistung-von-FrozenSet-9649523.html
[15] https://www.heise.de/blog/Neu-in-NET-8-0-14-Neue-Waechtermethoden-fuer-Parameter-9656153.html
[16] https://www.heise.de/blog/Neu-in-NET-8-0-15-Geschluesselte-Dienste-bei-der-Dependency-Injection-9662004.html
[17] https://www.heise.de/blog/Neu-in-NET-8-0-16-Neue-Methoden-fuer-IP-Adressen-9670497.html
[18] https://www.heise.de/blog/Neu-in-NET-8-0-17-Zeitabstraktion-fuer-Tests-mit-Zeitangaben-9675891.html
[19] https://www.heise.de/blog/Neu-in-NET-8-0-18-Ein-Zeitraffer-mit-eigenem-FakeTimeProvider-9683197.html
[20] https://www.heise.de/blog/Neu-in-NET-8-0-19-Razor-HTML-Rendering-in-beliebigen-NET-Anwendungen-9691146.html
[21] https://www.heise.de/blog/Neu-in-NET-8-0-20-Neue-Code-Analyzer-fuer-NET-Basisklassen-9706875.html
[22] https://www.heise.de/blog/Neu-in-NET-8-0-20-Neue-Code-Analyzer-fuer-ASP-NET-Core-9710151.html
[23] https://www.heise.de/blog/Neu-in-NET-8-0-22-Neues-Steuerelement-OpenFolderDialog-fuer-WPF-9722901.html
[24] https://www.heise.de/blog/Neu-in-NET-8-0-23-Verbesserungen-fuer-ZipFile-zur-Arbeit-mit-Dateiarchiven-9722920.html
[25] https://www.heise.de/blog/Neu-in-NET-8-0-24-HTTPS-Proxies-bei-HttpClient-9722968.html
[26] https://www.heise.de/blog/Neu-in-NET-8-0-25-Resilienz-im-HTTP-Client-9763586.html
[27] https://www.heise.de/blog/Neu-in-NET-8-0-26-Anpassung-der-Resilienz-im-HTTP-Client-9773126.html
[28] https://www.heise.de/blog/Neu-in-NET-8-0-27-Konfigurierbare-Namenskonventionen-in-System-Text-Json-8-0-9784360.html
[29] https://www.heise.de/blog/Neu-in-NET-8-0-28-Erweiterung-fuer-die-Deserialisierung-von-JSON-Objekten-9790704.html
[30] https://www.heise.de/blog/Neu-in-NET-8-0-29-Verbesserungen-fuer-den-JSON-Source-Generator-9798297.html
[31] https://www.heise.de/blog/Neu-in-NET-8-0-30-Neue-Datentypen-in-System-Text-Json-8-0-9808793.html
[32] https://net.bettercode.eu/
[33] https://net.bettercode.eu/index.php#programm
[34] https://net.bettercode.eu/tickets.php
[35] mailto:rme@ix.de

Copyright © 2024 Heise Medien

Adblock test (Why?)

  • 05. Juli 2024 um 16:32

Bit-Rauschen, der Prozessor-Podcast: Das bringt Wi-Fi 7 wirklich

Was genau ist am WLAN-Standard Wi-Fi 7 besser als bisher – und wer kann die Vorteile praktisch nutzen? Darum kreist Folge 2024/14 des Podcasts Bit-Rauschen.

Der Standard Wi-Fi 7 für drahtlose Netzwerke umfasst zahlreiche Neuerungen, die WLAN schneller und stabiler machen sollen. Die Spitzengeschwindigkeit steigt im Vergleich zu Wi-Fi 6 und Wi-Fi 6E. Doch die lässt sich häufig nur kurzzeitig nutzen, sowie nur dann, wenn die Entfernung zwischen WLAN-Router oder Repeater und Endgerät nicht zu groß ist.

In der Praxis wichtiger sind mehrere andere neue Funktionen. Denn die tragen dazu bei, dass sich im Durchschnitt höhere Datentransferraten ergeben.

Der c’t-Redakteur Ernst Ahlers [7] erklärt im Gespräch mit seinem Kollegen Christof Windeck [8], was Wi-Fi 7 bringt, und in welchen Einsatzbereichen sich diese Vorteile besonders bemerkbar machen: Folge 2024/14 von "Bit-Rauschen: Der Prozessor-Podcast von c’t".

Podcast Bit-Rauschen, Folge 2024/14 :


Wir freuen uns über Anregungen, Lob und Kritik zum Bit-Rauschen. Rückmeldungen gerne per E-Mail an bit-rauschen@ct.de [10].

Alle Folgen unseres Podcasts sowie die c’t-Kolumne Bit-Rauschen finden Sie unter www.ct.de/Bit-Rauschen [11]


URL dieses Artikels:
https://www.heise.de/-9747881

Links in diesem Artikel:
[1] https://ct.de/bit-rauschen
[2] https://Bit-Rauschen.podigee.io/feed/mp3
[3] https://podcasts.apple.com/de/podcast/bit-rauschen-der-prozessor-podcast-von-ct/id1549821753
[4] https://open.spotify.com/show/6JD6gwqgVR27GYZACrWOT1
[5] https://podcasts.google.com/feed/aHR0cHM6Ly9iaXQtcmF1c2NoZW4ucG9kaWdlZS5pby9mZWVkL21wMw
[6] https://www.deezer.com/de/show/2195452
[7] https://www.heise.de/autor/Ernst-Ahlers-4507618
[8] https://www.heise.de/autor/Christof-Windeck-3687176
[9] https://www.heise.de/Datenschutzerklaerung-der-Heise-Medien-GmbH-Co-KG-4860.html
[10] mailto:bit-rauschen@ct.de
[11] https://www.heise.de/meinung/Bit-Rauschen-Der-Prozessor-Podcast-von-c-t-4914290.html
[12] https://www.heise.de/ct/
[13] mailto:ciw@ct.de

Copyright © 2024 Heise Medien

Adblock test (Why?)

  • 03. Juli 2024 um 06:10

Enterprise Switches und Wi-Fi 7 Access-Points: Lancom bringt neue Topmodelle

Von Benjamin Pfister
Wi-Fi-Symbol mit einer sieben daneben

(Bild: iX)

Lancom bringt zwei neue WiFi 7 Access-Points und diverse Switches – vom Core bis zur Access-Ebene. Auch einen Switch für Industrieumgebungen gibt es nun.

Lancom veröffentlicht neue Switches und APs: Neben dem neuen Access Point LX-7500 als Topmodell mit 4x4 Triband Antennen in den Frequenzbändern 2, 4, 5 und 6 GHz liefert der Hersteller noch den LX-7300 mit 2x2 Triband Antennen. Zudem verfügen sie über ein Scan Radio zum permanenten Umgebungsscan. Nach Angaben von Lancom ist dieses jedoch zunächst ausschließlich zum Scan der WLAN-Kanäle nutzbar und nicht für eine gesamte Spektrumsanalyse. Es soll in Kombination mit der Lancom Management Cloud (LMC) nicht nur das Funkfeld sichtbar machen, sondern es auch bewerten und Handlungsempfehlungen zur WLAN-Optimierung für den Administrator geben. Dies soll später auch automatisiert möglich sein.

Beide sollen für die effiziente Frequenznutzung auf das bekannte Multi-User Multiple In-Multiple Out (MU-MIMO) Verfahren setzen und QAM-4096 als Modulation verwenden. Die Kanalbreite beträgt bis zu 320 MHz. Als echte Neuerung gilt Multi-Link Operation, wodurch es je nach eingesetzter Variante möglich ist, parallele Verbindungen auf unterschiedliche Kanäle oder sogar unterschiedliche Frequenzbänder aufzuteilen. Zunächst unterstützt Link Enhanced Multi-Link Single Radio (MLSR). So können alle Multi-Link-fähigen Geräte und Antennen dynamisch auf einen einzigen Link umschalten – sollte das Band dann gestört sein, schaltet es dynamisch auf das zweite Band um. Hinzu kommt Simultaneous Transmit and Receive (STR): Damit können Geräte Daten gleichzeitig über mehrere Verbindungen senden und empfangen, um den Durchsatz zu erhöhen, die Latenz zu reduzieren und die Zuverlässigkeit zu verbessern. Darüber hinaus prüft der Hersteller die Integration weiterer MLO-Varianten, was aber von den Zertifizierungsbedingungen der Wi-Fi Alliance abhängt.

Es steigt aber nicht nur der maximal mögliche drahtlose Durchsatz: Um dies auch ins verkabelte Netz zu transportieren, bieten beide APs zwei Uplink-Ports mit 10G und 2,5G. Damit können die Access-Points auf Basis des Link-Aggregations-Protokolls LACP ein Aktiv/Aktiv-Paar bilden oder auf Basis von Spanning-Tree eine Aktiv/Passiv-Verbindung zu den Switchen formen. Der große Bruder LX-7500 bietet zudem Dual-PoE, wodurch selbst beim Ausfall eines Switches, beispielsweise bei Updates, das WLAN weiter bestehen kann. Aber auch falls die Switching-Infrastruktur noch nicht genügend Leistung über einen Port liefern kann, kann der Access-Point die Leistung beider Ports kombinieren.

Ein In-Service Software-Update für den eigentlichen Access-Point hat der Hersteller in Planung. Auch Secure Boot unterstützen die neuen Modelle. Die APs liefern aber auch BLE 5.1 und lassen sich über USB-Schnittstellen durch weitere IoT-Sensoren ergänzen. Die Access-Points basieren, wie die angekündigten Modelle von Mitbewerbern, auf einem Qualcomm-Chipsatz.

Ferner hat Lancom an Details geschraubt: Unter anderem wurde das Antennendesign für die Deckenmontage verbessert. Aber auch an der physischen Sicherheit wurde gearbeitet: So gibt es eine integrierte Verriegelung gegen unbefugtes Entfernen – zumindest gegen Unbedarfte, die nicht auf den Seiten des Herstellers nachlesen. Ein Neigungs- und Bewegungssensor kann bei falschen Montagewinkeln oder Entwenden warnen.

Zudem verfügt das Gerät über einen integrierten Energieverbrauchsmesser, um die Werte an zentrale Managementsysteme senden zu können. Dem Thema Energiebedarf widmet sich Lancom intensiv. So gibt es auch ein Feature namens Active Power Control, das ein intelligentes Power-Monitoring und -Management bieten soll. Beispielsweise soll perspektivisch die Uplink-Geschwindigkeit in Zeiten geringer Last reduziert werden, um Energie zu sparen. Das bedeutet gemäß Rückfrage beim Hersteller allerdings einen kurzen Link-Down von drei bis fünf Sekunden.

Die Wi-Fi 7 Access-Points [1] sollen ab September 2024 lieferbar sein und zu Listenpreisen von 899 Euro (LX-7300 [2]) und 1190 Euro (LX-7500 [3]) zu haben sein. Die Straßenpreise dürften darunter liegen.

Core-Switches

Mit höheren Wireless-Datenraten bedarf es jedoch auch eines Redesigns in der Switching-Infrastruktur. Lancom bringt daher nun neue Switchmodelle, um alle Rollen in Campus-Netzen abdecken zu können – vom Core bis zum Access. Die zugrunde liegenden Hardware-Chips stammen von Broadcom. Im Core und der Distributionsebene positionieren sich das neue Topmodell LANCOM CS-8132F mit 32x 100G QSFP28-Slots und der LANCOM YS-7154CF mit 48x 25G SFP28-Slots und 6x 100G QSFP28. Sie unterstützen auch Virtual Port Channels (VPC bzw. MC-LAG), um in redundanten Netzen auch bei Updates die Verfügbarkeit des Netzwerks gewährleisten zu können. Im Routing unterstützen sie nach Angaben des Herstellers OSPFv2 für IPv4 und OSPFv3 für IPv6, sowie BGP4. Als First-Hop-Redundancy-Protokoll bieten sie VRRP. Netzteile und Lüfter sind redundant und Hot-swappable ausgelegt – und selbst aus Rechenzentrumsswitchen bekannte Funktionen, wie die Auswahl des Luftflusses (vorn nach hinten oder hinten nach vorn), sind mit an Bord.

Auch eine separate CPU und eine 64 GByte große SSD für Zusatzanwendungen stehen bereit – jedoch fehlen diese Funktionen zum Auslieferungsstart noch. Dafür gibt es ein In-Service Software Upgrade (ISSU), um auch bei Updates die Uptime in kritischen Umgebungen gewährleisten zu können.

Die inzwischen bei Mitbewerbern häufig gebotene MACSec-Verschlüsselung bieten sie jedoch nicht. Dazu gab der Hersteller an, dass der Mutterkonzern Rohde & Schwarz mit seinen SITline-Netzwerkverschlüsselern eine Alternative bietet, um auch diesen Anwendungsfall bis zu Link-Geschwindigkeiten von 100G abzudecken. Die Switches sollen zu Listenpreisen von 34.990 Euro (CS-8132F [4]) und 29.990 Euro (YS-7154CF [5]) ab Oktober 2024 lieferbar sein.

Access-Switches

Auf Access-Ebene geht der Trend zum Multi-Gigabit Port und im Uplink zu 25G oder höher. So bietet der neue XS-4530YUP [6] beispielsweise 12x 2,5 Gbit/s und PoE gemäß 802.3bt (Typ 4), sowie 12x 10 Gbit/s bei gleichem PoE-Standard. Für Uplink oder Stacking stehen 4x SFP28-Ports (10G oder 25G) und 2x QSFP28 (40G oder 100G) zur Verfügung. Selbst auf Access-Ebene unterstützen die Switches bereits Virtual Port Channel sowie redundante Netzteile und Lüfter. Selbst diese Switches unterstützen ISSU.

Industrie-Switch

Der neue Lancom IGS-3510XUP [7] ist ein Industrie-Switch mit erhöhtem Temperaturbereich von -40 bis +60 °C. Er besitzt ein robustes, passiv gekühltes Metallgehäuse. Im Industriebereich noch unüblich ist die Uplink-Geschwindkeit von 2x 10 Gbit/s. Für den Downlink stehen 4x 1 Gbit/s PoE+ mit bis zu 30W PoE (802.3at) und 4x 2,5 Gbit/s PoE bis zu 90W (802.3bt Type 4) bereit. Insgesamt steht eine PoE-Leistung von bis zu 360W zur Verfügung. Lancom möchte auch noch Industrieprotokolle, wie das Ring-Protokoll ERPS (ITU-T G.8032) nachreichen. Der Switch lässt sich auch zentral über die Cloud verwalten.


URL dieses Artikels:
https://www.heise.de/-9787003

Links in diesem Artikel:
[1] https://www.heise.de/hintergrund/Kurz-erklaert-Schnelleres-WLAN-mit-Wi-Fi-7-7488584.html
[2] https://www.lancom-systems.de/produkte/wireless-lan/indoor-access-points/lancom-lx-7300
[3] https://www.lancom-systems.de/produkte/wireless-lan/indoor-access-points/lancom-lx-7500
[4] https://www.lancom-systems.de/produkte/switches/core-switches/lancom-cs-8132f
[5] https://www.lancom-systems.de/produkte/switches/aggregation-switches/lancom-ys-7154cf
[6] https://www.lancom-systems.de/produkte/switches/fully-managed-access-switches/lancom-xs-4530yup
[7] https://www.lancom-systems.de/produkte/switches/fully-managed-access-switches/lancom-igs-3510xup
[8] https://www.heise.de/ix/
[9] mailto:fo@heise.de

Copyright © 2024 Heise Medien

Adblock test (Why?)

  • 02. Juli 2024 um 16:33

Kanada: Indigene kaufen Netzbetreiber für elffache Fläche Deutschlands

Hozhaus; Arbeiter steht auf hoher Leiter und spannt ein Kabel zum Dach des Gebäudes, im Hintergrund Berge

FTTH (Fibre to the Holzhaus); die Aufnahme der Verlegearbeiten Northwestels im dünn besiedelten Yukon ist vom August 2022. Beleuchtet wurde das Kabel erst im Mai 2024.

(Bild: Daniel AJ Sokolov)

Bell Canada verkauft sein Festnetz im Norden des Landes an Ureinwohner. Northwestel wird der weltweit größte Netzbetreiber im Eigentum Indigener.​

Der Telecomkonzern Bell Canada verkauft seine Tochter Northwestel um ungefähr eine Milliarde kanadische Dollar (rund 680 Millionen Euro) an ein Konsortium aus Ureinwohnervölkern. Es handelt sich also um eine Art Verstaatlichung durch dutzende Völker. Das Unternehmen versorgt die drei Territorien Kanadas sowie den Norden der Pazifikprovinz Britisch-Kolumbien und einen Teil des Nordens Albertas mit ortsgebundenem Internetzugang, Festnetztelefonie und teilweise Kabelfernsehen, außerdem vertreibt es Satellitenanbindungen über Oneweb. Laut den neuen Eigentümern wird Northwestel (NWTel) damit zum weltweit größten Netzbetreiber im Eigentum Indigener - das stimmt zumindest bezogen auf die zu versorgende Fläche.

Denn das Versorgungsgebiet ist riesig: Rund vier Millionen Quadratkilometer sind mehr als die elffache Fläche Deutschlands. Dafür ist das Gebiet sehr dünn besiedelt. In den drei Territorien Kanadas (Nunavut im Osten, Nordwest-Territorien im Zentrum und Yukon im Westen) leben insgesamt nur rund 125.000 Menschen. Hinzu kommen weniger als zehntausend Einwohner im Norden Britisch-Kolumbiens und Albertas. Die Betriebsbedingungen sind extrem, mit sehr kalten, langen Wintern, Waldbränden im Sommer, Permafrostboden, enormen Entfernungen und generell bescheiden ausgebauter Infrastruktur. Fast die Hälfte der knapp hundert angeschlossenen Siedlungen ist nicht durchgehend auf dem Landweg erreichbar. Entsprechend hoch sind die Kosten für Netzerrichtung und -betrieb.

NWTel betreibt die jeweils einzige Glasfaser-Verbindung, die die zentral gelegenen Nordwest-Territorien und das westlich gelegenen Yukon-Territorium mit der Außenwelt verbinden. Das Nunavut-Territorium im Osten hat bislang keinen Anschluss an Glasfaser und ist auf Satelliten angewiesen. Auch in den beiden anderen Territorien gibt es Siedlungen, die die Glasfaser nicht erreicht. Bis zum Markteintritt des Satellitendienstes Starlink Ende 2022 hatte NWTel im Großteil seines Gebietes kaum nennenswerte Konkurrenz. Im östlich gelegenen Territorium Nunavut sowie in Teilen der Nordwest-Territorien gibt es mit SSi Canada zwar einen drahtlosen Mitbewerber, der aber ebenfalls auf den Northwestel-Backbone angewiesen ist und seit jeher über Apothekerpreise für dessen Nutzung klagt.

Für die Ureinwohner ist der Kauf sowohl eine wirtschaftliche als auch eine strategische Entscheidung: "Als indigene Völker waren wir schon lange der Auffassung, dass wir die Besten sind, um notwendige Entscheidungen zu treffen, die Dienstleistungen in unseren Siedlungen betreffen", sagte Tiffany Eckert-Maret, eine für die beteiligten Völker des Yukon tätige Managerin, "Der Kauf Northwestels wird uns die Autonomie geben, in Zukunft diese Investitionen und Entscheidungen zu treffen, um unsere Telecom-Berdürfnisse zu erfüllen." Trotz alledem erwarten die Ureinwohnerregierungen laufende Gewinne: "Der Kauf (NWTels wird Indigenen) Zugang zu langfristig stabilem Cashflow gewähren, den sie in wichtige Infrastruktur wie Wohnraum, Sozialleistungen, Gesundheitsversorgung und Bildungsprogramme" reinvestieren können, steht in der Pressemitteilung [1] zu lesen.

Offene Fragen

Nur teilweise ist geklärt, wie sich das neue Eigentümerkonsortium zusammensetzen wird. Die neu gegründete Holding heißt Sixty North Unity – ein Bezug auf den sechzigsten Breitengrad, der die Grenze zwischen Kanadas Territorien und Provinzen bildet. Bislang sind drei Eigentümergruppen Sixty North Unitys bekannt: Aus dem Yukon sind 13 der 14 Ureinwohnervölker mit dabei, in den Nordwest-Territorien der Großteil der First Nations (im US-Englisch Indians genannt), offenbar aber keine Inuit (US-Englisch: Eskimos) oder Métis. In Nunavut ist eine Organisation Teilhaber, die den Inuit-Regierungen in Kitikmeot, einer von drei Regionen des Territoriums, repräsentiert. Eingeladen sind auch die übrigen Ureinwohner im Norden Kanadas, teilweise sollen bereits Gespräche stattfinden.

Auch sonst lässt die Ankündigung des Verkaufs viele Fragen offen. Auch auf Nachfrage heise onlines bei allen Beteiligten war beispielsweise nicht zu erfahren, welche Teile der Infrastruktur bei dem Verkauf an die Ureinwohner gehen, und was bei Bell bleibt und fortan an Northwestel vermietet wird. Bells nördliches Mobilfunknetz und -frequenzrechte bleiben sicher bei Bell; aber wer den Glasfaser-Backbone und Satellitenbodenstationen erhält, ist unbekannt. Gleiches gilt für den Verbleib der Markenrechte sowie des Eigentumanteils am noch immer in Bau befindlichen Canada North Fibre Loop, der ersten Glasfaser in Permafrost [2].

Keine Auskunft gibt es außerdem zu etwaigen Übernahmen von Schulden oder andere Verbindlichkeiten, beispielsweise Pensionsansprüchen. Die wettbewerbsrechtliche Genehmigung stehen noch aus; doch da Northwestel schon jetzt keine nennenswerten Konkurrenz hat, dürfte die Wettbewerbsbehörde keine Steine in den Weg legen. Das Closing ist für das vierte Quartal geplant. Das gegenwärtige Northwestel-Management soll auch danach im Amt bleiben.

Keine Wachstumsphantasie

NWTel ist kein Mobilfunkanbieter; das Geschäft mit Kabelfernsehen schrumpft, und – wie aus Preisregulierungsverfahren hervorgeht – ist die Festnetztelefonie seit langem defizitär. In den Dörfern läuft Internet entweder über Satelliten, die NWTel nicht selbst betreibt sondern nur vermarktet, oder über alte DSL-Einrichtungen, die auch Verluste schreiben. Manche Siedlungen haben inzwischen auch Glasfaser.

Für die Dörfer des Yukon hat NWTel dutzende Millionen Dollar Subventionen erhalten, mit denen es Glasfaser zu den einzelnen Häusern gebracht hat. Die letzten Meilen dieses Glasfasernetzes im Yukon hat NWTel bereits vor zwei Jahren an die 13 Ureinwohnervölker verkauft und umgehend exklusiv zurückgemietet. Dieses Tafelsilber ist also schon verkauft. Jedenfalls dürfte die Glasfaser günstiger zu betreiben sein als DSL, zumindest gemessen pro übertragenem Gigabyte; aufgrund der Ringstruktur der Kupferkabel kann NWTel die DSLAMs aber nicht abschalten, solange auch nur ein Kunde am jeweiligen Ring noch DSL nutzt. Der Umstieg wird Jahre dauern.

Gewachsen ist das Unternehmen zuletzt nur bei Internetanschlüssen, weil die Bevölkerung der Region stark zugenommen hat. Den Yukon ausgenommen ist das Bevölkerungswachstum im Servicegebiet allerdings jüngst zum Erliegen gekommen. Kein Wunder; zwar gibt es zahlreiche unbesetzte und gut bezahlte Arbeitsplätze, doch herrscht im Norden Kanadas großer Mangel an Wohnraum, der vom Mangel an Gewerbeimmobilien noch übertroffen wird. Und seit eineinhalb Jahren wildert Starlink im NWTel-Revier. Starlink hat nicht nur seltener Totalausfälle aufgrund von Kabelbrüchen, auch die monatliche Gebühr lag bis vor kurzem unter der günstigsten Internet-Flatrate NWTels (die nur über Kabel und Glasfaser verfügbar ist, nicht über DSL, wo zusätzliche Datenmengen ordentlich ins Geld gehen).

Erst vor einigen Tagen hat NWTel eine Flatratetarif eingeführt (50/10 Mbit/s über Kabel, 50/50 Mbit/s über Glasfaser), dessen monatlicher Tarif leicht unter dem Starlink-Preis liegt. Ob das reicht, den Verlust an Marktanteilen zu bremsen, bleibt abzuwarten.

Rechnet sich das?

Laut heise online vorliegenden Angaben aus Bankenkreisen macht NWTel etwa 275 Millionen Dollar Jahresumsatz, davon zirka 75 Millionen mit anderen Bell-Gesellschaften. Der Gewinn vor Steuern, Zinsen und Abschreibungen (EBITDA) liegt demnach bei ungefähr 135 Millionen Dollar, was eine EBITDA-Marge von erstaunlichen 49 Prozent ergibt. Selbst im hochpreisigen Telecom-Markt Kanada ist das für einen Festnetzbetreiber richtig stark.

Von den 31.000 Internetkunden NWTels beziehen etwa 8.500 auch Kabelfernsehen. Das (großteils bereits 2022 verkaufte) Glasfasernetz verläuft zu oder nahe bei 17.000 Gebäuden, 11.000 Haushalte nutzen noch aktiven Kupferdraht. Auch diese Daten sind nicht offiziell, kursieren aber unter Bankiers.

Unklar ist, wie so wenige Kunden den Kaufpreis von rund einer Milliarde Dollar finanzieren sollen. Der Zinsfuß dürfte bei acht bis zehn Prozent liegen. Selbst bei nur sechs Prozent Zinsen macht alleine die Zinslast 60 Millionen Dollar jährlich aus. Umgelegt auf 31.000 Internetkunden wären das 161 Dollar Zinsen pro Anschluss und Monat, die Tilgung der Schulden nicht eingerechnet.

Kosten steigen

Große Satellitenschüssel mit Aufschrift Northwestel in einer Wiese

NWTel-Schüssel in Bob Quinn Lake, Britisch-Kolumbien, Kanada. Der Weiler ist benannt nach Robert Quinn, einem Netzelektriker der Yukon Telegraph Line, einem Vorgänger Northwestels.

(Bild: Daniel AJ Sokolov)

Gleichzeitig steigen die Kosten, denn NWTel muss Arbeitsplätze vor Ort schaffen, um bislang von Bells Konzernzentrale mitbetreute Aufgaben erledigen zu können, beispielsweise Rechts- und Finanzabteilung. Zudem haben die neuen Eigentümer vor, Ureinwohner durch Kurse und Mentorships zu Fachkräften heranzubilden, die dann bei NWTel beschäftigt werden können. Auch das kostet. Und der Einkauf, von Kugelschreibern über Netzausrüstung bis zu Softwarelizenzen, wird teurer werden, sobald die von Bell ausgehandelten Mengenrabatte wegfallen.

Nicht zuletzt versprechen die neuen Eigentümer zusätzliche Investitionen. Dazu gehören Gigabit-Anschlüsse für Haushalte (eventuell auch für Kabel-Internet), zusätzliche Infrastruktur für erdnahe Satellitennetze, sowie ein Unterseekabel im Großen Sklavensee, um Yellowknife, der Hauptstadt der Nordwestterritorien, eine zweite Glasfaseranbindung zu verschaffen. Der See ist ungefähr so groß wie Albanien, oder fast so groß wie das deutsche Bundesland Brandenburg. Durch ein Unterseekabel (zusätzlich zur bestehenden Anbindung über Land) werden die häufigen Telecom-Ausfälle aufgrund beschädigter Glasfasern, so die Hoffnung, der Vergangenheit angehören.

Trotz alledem erwarten die Ureinwohnerregierungen "langfristig stabilen Cashflow". Eine Wette mit ungewissem Ausgang. Bell jedenfalls darf sich über eine Milliarde Dollar freuen, die es zur Schuldentilgung nutzen wird. Es muss sich nicht länger mit den besonders schwierigen Bedingungen des kanadischen Nordens herumschlagen und kann Gewinn verbuchen. Der Verkaufspreis soll geschätzt beim zweieinhalbfachen Buchwert liegen.

Geschichte

Northwestel besteht im Yukon und den Nordwestterritorien seit 1979 und war damals eine Tochterfirma der staatlichen Canadian National Railways, die so hoch im Norden aber gar keine Schienen hatte. 1988 übernahm Bell Canada den Netzbetreiber und verschmolz ihn 1992 mit dem Bell-Betrieb im heutigen Nunavut. Mangels Konkurrenz ist NWTel der einzige Internetprovider Kanadas, dessen Endkundenpreise reguliert sind. Die schrittweise Einführung von Internet-Flatrates für Kabel- und Glasfaserkunden erfolgte ab Ende 2020, im inoffiziellen Austausch gegen Millionensubventionen für den Ausbau von Fibre to the Home (FTTH). Der günstigste Flatrate-Tarif im Yukon kostet heute 130 Dollar pro Monat netto, umgerechnet 89 Euro zuzüglich Steuer; Businesskunden zahlen mindestens 300 Dollar monatlich (205 Euro).

Die Geschichte der Telekommunikation beginnt im Norden Kanadas 1865. An regionaler Telecom-Geschichte Interessierten sei das Büchlein "In Direct Touch with the Wide World, Telecommunications in the North 1865-1992" von Dianne Green empfohlen, das Northwestel 1992 aufgelegt hat (ISBN-10: 096961280X).


URL dieses Artikels:
https://www.heise.de/-9781701

Links in diesem Artikel:
[1] https://www.nwtel.ca/sixty-north-unity-northwestel-and-bell-canada-announce-transformative-partnership-advance-economic
[2] https://www.heise.de/news/Kanada-Erste-Glasfaser-im-Permafrost-hilft-deutschen-Satelliten-4258742.html
[3] mailto:ds@heise.de

Copyright © 2024 Heise Medien

Adblock test (Why?)

  • 28. Juni 2024 um 06:07

Neu in .NET 8.0 [27]: Konfigurierbare Namenskonventionen in System.Text.Json 8.0

Von Dr. Holger Schwichtenberg

(Bild: Shutterstock.com/calimedia)

In der JSON-Bibliothek können Entwicklerinnen und Entwickler nun neben CamelCasing auch andere Namenskonventionen wählen.

Der JSON-Serializer System.Text.Json (NuGet-Paket [1]) erhielt in Version 8.0 einige Erweiterungen.

Im Gegensatz zu anderen Teilen von .NET 8.0 wie Entity Framework Core 8.0 läuft System.Text.Json nicht nur auf .NET 8.0, sondern auch älteren .NET-Versionen. System.Text.Json funktioniert mit dem klassischen .NET Framework ab Version 4.6.2 und dem modernen .NET ab Version 2.0.

Version 8.0 verwendet für die Serialisierung von Objekteigenschaften nach JSON und die Deserialisierung aus JSON die Namenskonventionen KebabCaseLower, KebabCaseUpper, SnakeCaseLower und SnakeCaseUpper in der Enumeration JsonNamingPolicy als Alternative zum bisher fest gesetzten CamelCasing.

Beispiele für diese Namenskonventionen sind:

  • PascalCase: FullName
  • CamelCase: fullName
  • KebabCaseLower: full-name
  • KebabCaseUpper: FULL-NAME
  • SnakeCaseLower: full_name
  • SnakeCaseUpper: FULL_NAME

Im folgenden Listing kommt KebabCaseUpper beim Serialisieren und Deserialisieren einer Instanz der Klasse Consultant zum Einsatz:

var options = new JsonSerializerOptions
{
 // NEU: Enumeration JsonNamingPolicy mit Namenskonventionen KebabCaseLower, KebabCaseUpper, SnakeCaseLower und SnakeCaseUppter als Alternative zum bisher fest gesetzten CamelCase
 PropertyNamingPolicy = JsonNamingPolicy.KebabCaseUpper, // Standard ist CamelCase
};
…
var consultant = new Consultant() { ID = 42, FullName = "Holger Schwichtenberg", Salutation = "Dr.", PersonalWebsite = "www.dotnet-doktor.de" };
consultant.Languages.AddRange(["C#", "JavaScript", "TypeScript"]);
consultant.Address = new Address() { City = "Essen", Country = "Germany" };
Console.WriteLine("Objekt im RAM:");
Console.WriteLine(consultant);
Console.WriteLine();
 
CUI.H3("Serialisierung (KebabCaseUpper):");
string json1 = JsonSerializer.Serialize(consultant, options);
Console.WriteLine(json1); // {"ID":42,"FULL-NAME":"Holger Schwichtenberg","SALUTATION":"Dr.","PERSONAL-WEBSITE":"www.dotnet-doktor.de"}
…
CUI.H3("\nDeserialisierung: (vollständig)");
try
 {
  var jsonString = """
  {"ID":42,"FULL-NAME":"Holger Schwichtenberg","SALUTATION":"Dr.",
   "PERSONAL-WEBSITE":"www.dotnet-doktor.de",
   "ADDRESS":{"COUNTRY":"Germany","CITY":"Essen"}}
  """;
  Console.WriteLine(jsonString);
  var obj = JsonSerializer.Deserialize<Consultant>(jsonString, options);
  if (obj != null) CUI.Success(obj.ToString());
 }
catch (Exception ex)
 {
  CUI.PrintError(ex.Message); 
 }

Das nachstehende Listing 2 zeigt die Datenobjekte Person und Consultant sowie deren Schnittstellen:

using System.Text.Json.Serialization;
 
namespace FCL_JSON;
 
public interface IBusinessObject
{
 UInt128 ID { get; init; } 
}
 
public interface IPerson : IBusinessObject
{
 string? Salutation { get; set; }
 string? FullName { get; set; }
 public Address Address { get; set; }
}
 
public interface IConsultant : IPerson
{
 string? PersonalWebsite { get; set; }
 public List<string> Languages { get; }
}
 
public class Address
{
 public string Country { get; set; }
 public string City { get; set; }
}
 
public class Person : IPerson
{
 public Person() { }
 public required UInt128 ID { get; init; }
 public required string FullName { get; set; }
 public string? Salutation { get; set; }
 public Address Address { get; set; }
 
 public override string ToString()
 {
  return $"Person {ID}: {(!String.IsNullOrEmpty(Salutation) ? Salutation + " " : "")}{FullName} wohnt in {Address?.City ?? "UNBEKANNT"} ";
 }
}
 
public class Consultant : Person, IConsultant
{
 public Consultant() { }
 
 public List<string> Languages { get; } = new();
 
 public string? PersonalWebsite { get; set; }
 
 public override string ToString()
 {
  return $"Consultant {ID}: {(!String.IsNullOrEmpty(Salutation) ? Salutation + " " : "")}{FullName} wohnt in {Address.City} -> {PersonalWebsite} Sprachen: {String.Join('+', Languages)}";
 }
}


URL dieses Artikels:
https://www.heise.de/-9784360

Links in diesem Artikel:
[1] https://www.nuget.org/packages/System.Text.Json
[2] https://www.heise.de/blog/Neu-in-NET-8-0-1-Start-der-neuen-Blogserie-9574680.html
[3] https://www.heise.de/blog/Neu-in-NET-8-0-2-Neue-Anwendungsarten-9581213.html
[4] https://www.heise.de/blog/Neu-in-NET-8-0-3-Primaerkonstruktoren-in-C-12-0-9581346.html
[5] https://www.heise.de/blog/Neu-in-NET-8-0-4-Collection-Expressions-in-C-12-0-9581392.html
[6] https://www.heise.de/blog/Neu-in-NET-8-0-5-Typaliasse-in-C-12-0-9594693.html
[7] https://www.heise.de/blog/Neu-in-NET-8-0-6-ref-readonly-in-C-12-0-9602188.html
[8] https://www.heise.de/blog/Neu-in-NET-8-0-7-Optionale-Parameter-in-Lambda-Ausdruecken-in-C-12-0-9609780.html
[9] https://www.heise.de/blog/Neu-in-NET-8-0-8-Verbesserungen-fuer-nameof-in-C-12-0-9616685.html
[10] https://www.heise.de/blog/Neu-in-NET-8-0-9-Neue-und-erweiterte-Datenannotationen-9623061.html
[11] https://www.heise.de/blog/Neu-in-NET-8-0-10-Plattformneutrale-Abfrage-der-Privilegien-9630577.html
[12] https://www.heise.de/blog/Neu-in-NET-8-0-11-Neue-Zufallsfunktionen-9637003.html
[13] https://www.heise.de/blog/Neu-in-NET-8-0-12-Eingefrorene-Objektmengen-9643310.html
[14] https://www.heise.de/blog/Neu-in-NET-8-0-12-Leistung-von-FrozenSet-9649523.html
[15] https://www.heise.de/blog/Neu-in-NET-8-0-14-Neue-Waechtermethoden-fuer-Parameter-9656153.html
[16] https://www.heise.de/blog/Neu-in-NET-8-0-15-Geschluesselte-Dienste-bei-der-Dependency-Injection-9662004.html
[17] https://www.heise.de/blog/Neu-in-NET-8-0-16-Neue-Methoden-fuer-IP-Adressen-9670497.html
[18] https://www.heise.de/blog/Neu-in-NET-8-0-17-Zeitabstraktion-fuer-Tests-mit-Zeitangaben-9675891.html
[19] https://www.heise.de/blog/Neu-in-NET-8-0-18-Ein-Zeitraffer-mit-eigenem-FakeTimeProvider-9683197.html
[20] https://www.heise.de/blog/Neu-in-NET-8-0-19-Razor-HTML-Rendering-in-beliebigen-NET-Anwendungen-9691146.html
[21] https://www.heise.de/blog/Neu-in-NET-8-0-20-Neue-Code-Analyzer-fuer-NET-Basisklassen-9706875.html
[22] https://www.heise.de/blog/Neu-in-NET-8-0-20-Neue-Code-Analyzer-fuer-ASP-NET-Core-9710151.html
[23] https://www.heise.de/blog/Neu-in-NET-8-0-22-Neues-Steuerelement-OpenFolderDialog-fuer-WPF-9722901.html
[24] https://www.heise.de/blog/Neu-in-NET-8-0-25-Resilienz-im-HTTP-Client-9763586.html
[25] https://www.heise.de/blog/Neu-in-NET-8-0-26-Anpassung-der-Resilienz-im-HTTP-Client-9773126.html
[26] https://www.heise.de/blog/Neu-in-NET-8-0-27-Konfigurierbare-Namenskonventionen-in-System-Text-Json-8-0-9784360.html
[27] https://net.bettercode.eu/
[28] https://net.bettercode.eu/index.php#programm
[29] https://net.bettercode.eu/tickets.php
[30] mailto:rme@ix.de

Copyright © 2024 Heise Medien

Adblock test (Why?)

  • 01. Juli 2024 um 13:01

Schätzung eines Softwareentwicklers: Ich werde Gärtner

Von Golo Roden

(Bild: Lamyai / Shutterstock.com)

Softwareentwicklung ähnelt mehr der Arbeit im Garten als einer Ingenieurswissenschaft – meint zumindest Chris Aitchison. Was ist an dieser These dran?

Vergangene Woche ging es um die Frage, was Softwareentwicklung eigentlich ist: Kunst oder doch eher eine Ingenieurswissenschaft? [1] Meine These war, dass Softwareentwicklung etwas von beidem hat, aber dass wir den künstlerischen Aspekt im Alltag zu oft vergessen und uns häufig gar nicht im Klaren darüber sind, wo wir selbst eigentlich auf dieser Skala stehen: Sind wir Künstler oder Ingenieure?

Zu diesem Blogpost gab es zahlreiche Kommentare, nicht nur hier im Developer-Kanal, sondern auch unter dem zugehörigen Video auf YouTube [2]. Ein Kommentar ist mir dabei besonders aufgefallen: Der Verfasser stimmte meiner Aussage grundsätzlich zu, sah aber einen Punkt anders. Ich hatte nämlich erwähnt, Kunst sei nicht schätzbar, doch seiner Meinung nach könne man alles schätzen: Entwicklerinnen und Entwickler hätten nur zu oft Angst, bei Unsicherheiten oder Unwissen einfach eine große Zahl zu nennen.

Ein Space-Shuttle schätzen

Das hat mich nachdenklich gestimmt, denn wenn ich unsicher bin oder mir grundlegendes Wissen fehlt, dann kann ich nicht deshalb nicht schätzen, weil ich mich nicht traue, eine große Zahl zu nennen. Das Schätzen ist vielmehr unmöglich. Würde ich in einer solchen Situation einfach eine große Zahl nennen, dann wäre das nicht geschätzt, sondern einfach nur geraten.

Wenn Sie mich fragen, wie lange ich persönlich brauche, um ein Space-Shuttle von Grund aufzubauen, dann habe ich absolut keine Ahnung, was ich antworten soll. Dabei hilft mir auch nicht der Mut, eine große Zahl zu äußern, denn das macht die Schätzung nicht solider: Ob ich nun fünf, zehn oder zwanzig Jahre sage – alles hat die gleiche Aussagekraft, nämlich praktisch gar keine. Und deshalb ist es meiner Meinung nach auch keine Schätzung, sondern wie gesagt nur (schlecht) geraten.

Trotzdem hat mich diese Frage nicht losgelassen, und ein befreundeter Unternehmer hat mich vor ein paar Tagen auf den sehr spannenden Blogpost "Are you a Software Gardener? [4]" von Chris Aitchison aufmerksam gemacht. Seine Kernaussage ist, dass wir als Entwicklerinnen und Entwickler keine Ingenieure seien, sondern viel eher Gärtner.

Die Softwareentwicklung als Gartenpflege

Als ich diesen Vergleich zum ersten Mal gelesen habe, fand ich ihn zugegebenermaßen doch ein wenig schräg, aber der Blogpost kommt auf einen sehr guten Punkt zu sprechen: Darin heißt es nämlich, dass Ingenieursprojekte im Wesentlichen vorhersagbar seien und dass es deshalb möglich sei, die Planung und auch den Bau zum Beispiel einer Brücke oder eines Wolkenkratzers zeitlich recht genau vorherzusagen. Denn wie man eine Brücke oder einen Wolkenkratzer baut, sei inzwischen hinreichend bekannt, und unterscheide sich nicht allzu sehr von Instanz zu Instanz und sei außerdem in den meisten Fällen unabhängig von der jeweiligen Umgebung. Natürlich gibt es Unterschiede im Preis, aber das Grundprinzip, wie eine Brücke oder ein Wolkenkratzer gebaut wird, sei im Großen und Ganzen eben immer dasselbe.

Ganz anders sehe es hingegen aus, wenn man einen Garten anlegen möchte. Natürlich hätte man auch dann einen groben Plan und könne sagen, wo welcher Baum, welcher Strauch, welche Blumen und so weiter gepflanzt werden sollen. Aber anders als bei einem Bauwerk, bei dem man in der Regel im Vorfeld schon sehr genau wisse, wo welcher Stein oder welcher Träger zum Einsatz kommen werde, könne man bei einem Garten eben nicht jedes einzelne Blatt oder jede einzelne Blüte im Detail vorhersagen. Und es sei doch auch ziemlich abstrus, wenn man das versuchen würde.

Tatsächlich dürfte auf der Hand liegen, dass nicht vorhersagbar ist, wie viele Blüten ein paar heute gepflanzte Narzissenzwiebeln im kommenden Frühjahr haben werden. Je nach Wetter, Klima, Bodenbeschaffenheit und so weiter kann man noch nicht einmal genau vorhersagen, ob sie überhaupt den nächsten Winter überleben werden. Natürlich hat man als erfahrene Gärtnerin oder als erfahrener Gärtner hier ein gewisses Gefühl und eine gewisse Erfahrung, aber garantieren kann man es eben nicht.

Proaktive Pflege

Und genauso verhält es sich auch bei Software: Auch Software ist einzigartig und hängt maßgeblich von ihrer jeweiligen Umgebung ab. Außerdem ist Software nie fertig, sondern es lässt sich immer noch etwas daran weiterentwickeln, genauso wie man auch in einem Garten niemals fertig sein wird. Das liegt allein schon daran, dass sich die Umgebung wandelt: Die Hardware verändert sich, das zugrunde liegende Betriebssystem ändert sich, Bibliotheken und APIs wandeln sich, und so weiter.

All diesem Wandel muss ich mit meiner Software im Laufe der Zeit immer wieder Rechnung tragen. Klar: Software altert per se nicht, aber sie wird eben eher selten heute noch unter den gleichen Bedingungen ausgeführt wie vor fünf oder zehn Jahren. Damit das funktioniert, muss man proaktiv etwas dafür machen.

Erfahrung erkennen

Das funktioniert natürlich dann deutlich besser, wenn die Gärtnerinnen und Gärtner der Software (also die Entwicklerinnen und Entwickler) eine gewisse Erfahrung mitbringen, ihre Werkzeuge kennen und ein Händchen für geschickte Softwareentwicklung haben. Genauso wie man bei Pflanzen davon spricht, dass jemand einen "grünen Daumen" habe, gibt es auch in der Softwareentwicklung Menschen, die ein besseres Geschick bei der Gestaltung von Algorithmen und Datenstrukturen haben als andere.

Diese Fähigkeit lässt sich nicht gut quantifizieren, es gibt keine besonders geeignete Metrik dafür. Aber erfahrene und geschickte Entwicklerinnen und Entwickler erkennen ihresgleichen innerhalb kürzester Zeit aus dem Gefühl heraus. Anders formuliert: Wer selbst nicht Software entwickelt, wird es schwer haben, die wirklich guten Entwicklerinnen und Entwickler zu identifizieren. Oft entscheidet dabei dann letztlich das Bauchgefühl, gefolgt von der Hoffnung, dass die Entscheidung nicht katastrophal schlecht war.

Übrigens, wenn Ihnen die Metapher mit dem Garten nicht zusagt, gibt es noch andere vergleichbare Disziplinen, wie zum Beispiel das Kochen oder das Spielen eines Instruments. Auch diese beiden Beispiele erfordern den Einsatz von Technik, aber beides geht, wenn es wirklich gut werden soll, weit über reine Technik hinaus. Das Beherrschen der Technik ist also eine notwendige, aber keine hinreichende Vorbedingung.

Meine Schätzung? Maximal 1 Milliarde Euro …

Deshalb, und damit komme ich auf den ursprünglichen Punkt zurück, ist das Schätzen in der Softwareentwicklung meiner Meinung nach kaum sinnvoll.

Klar, wenn Sie mich fragen, wie lange ich brauche, um in Go einen Webserver zu schreiben, der ein paar API-Routen anbietet, die mit einer Datenbank kommunizieren und JSON zurückgeben oder entgegennehmen, dann kann ich Ihnen das ungefähr beantworten, weil ich das schon etliche Male gemacht habe. Aber selbst bei diesem trivialen Beispiel gibt es Unsicherheiten, die einen massiven Einfluss haben können:

  • Verfügt die API über eine Authentifizierung?
  • Wird die API CORS unterstützen?
  • Wie sieht die Test-Strategie für die API aus?
  • Wird eine Dokumentation für die API benötigt?
  • Wird die API versioniert, und wenn ja, nach welchem Schema?
  • Gibt es Besonderheiten bezüglich Caches oder Proxies zu beachten?

Je nachdem, wie diese Fragen beantwortet werden, reden wir unter Umständen über Schwankungen in der Schätzung von mehreren hundert, wenn nicht gar tausend Prozent. Und das wohlgemerkt bei einem grundsätzlich bekannten Problem!

Wenn ich nun aber schon das nicht exakt vorhersagen kann, ohne zunächst alle möglichen Details im Vorfeld durchzusprechen, wie soll ich dann eine Aufwandsschätzung für etwas geben, was ich fachlich und inhaltlich noch nie gemacht habe, was für mich also komplett unbekanntes Terrain ist?

Natürlich kann ich dann den ursprünglichen Hinweis aus dem Kommentar nehmen und sagen: "Na ja, also mehr als eine Milliarde Euro wird’s wohl nicht kosten". Und höchstwahrscheinlich werde ich mit dieser Einschätzung sogar auch richtig liegen – nur nützt die eben niemandem etwas.

Der Weg zu einer fundierten Schätzung

Die Frage ist, was man daraus macht. Denn das Business möchte manchmal einfach Zahlen haben, um abschätzen zu können, ob sich eine Entwicklung überhaupt rentiert und ob sich der Aufwand am Ende voraussichtlich lohnen wird. Und auch, wenn es aus unserer Sicht als Entwicklerinnen und Entwickler oftmals nicht möglich ist, eine sinnvolle Schätzung abzugeben, heißt das nicht, dass die Frage nach der Schätzung nicht grundsätzlich berechtigt wäre. Sich einfach nur hinzustellen und zu sagen "sorry, das kann ich nicht schätzen" nützt wenig und bringt niemandem das eigentliche Ziel näher.

Deshalb glaube ich (und das ist auch das Verfahren, das wir in meinem Unternehmen the native web [5] anwenden): Wenn wir etwas nicht schätzen können, weil es zu viele Unbekannte gibt, muss dem Entwicklungs- zunächst ein Forschungsprojekt vorangestellt werden, in dem man die wichtigsten Probleme zu lösen versucht. Das Ziel ist also zunächst, einen "Proof of Concept" zu entwickeln, einen "Durchstich", einen "Prototypen", oder wie auch immer man das Ganze nennen will. Dabei geht es jedoch zunächst nur darum, mehr Wissen zu erlangen und erste Erfahrungen zu sammeln, um sich selbst in eine bessere Ausgangslage für eine vernünftige Schätzung zu bringen.

Und diese Forschung, die wird nicht geschätzt, sondern durch eine Timebox begrenzt. Man nimmt sich zum Beispiel vier Wochen Zeit, um herauszufinden, wie bestimmte Dinge funktionieren, ob sie überhaupt funktionieren, und so weiter. Was diese vier Wochen kosten werden, ist vorher bekannt, denn sie können nach zeitlichem Aufwand abgerechnet werden. Und danach schaut man sich das Ergebnis an: Wenn es vielversprechend ist, macht man weiter und kommt einer verlässlichen Schätzung auf dem Weg nach und nach näher. Wenn das Ergebnis jedoch nicht vielversprechend ist, kann man sich entscheiden, ob man weiter forschen und noch einmal in eine Timebox investieren möchte, oder ob man es lieber bleiben lässt.

Hand in Hand mit dem Business

Das ist meines Erachtens der deutlich bessere Weg, als einfach irgendeine große Zahl zu sagen, um eine Zahl gesagt zu haben. Natürlich muss auch das Business am Ende des Tages mitspielen. Aber ich glaube, dass man gut vermitteln kann, dass wenn eine Schätzung benötigt wird, man dann auch zunächst eine vernünftige Grundlage schaffen muss, auf deren Basis man eine solide Schätzung überhaupt durchführen kann.

Meine Erfahrung ist, dass man das verständlich erklären kann und das Business es häufig sogar zu schätzen weiß, wenn man das offen und transparent kommuniziert. Denn das zeigt, dass man gerade nicht einfach irgendetwas sagt, sondern dass man die Anfrage ernst nimmt, dass man vertrauenswürdig ist, und dass man versucht, das Problem konstruktiv und vor allem gemeinsam anzugehen. Und das ist es, worauf es letztlich in der Softwareentwicklung ohnehin ankommt: Dass alle Beteiligten gemeinsam an einem Strang ziehen. Warum also damit nicht schon bei der Aufwandsschätzung starten?


URL dieses Artikels:
https://www.heise.de/-9774439

Links in diesem Artikel:
[1] https://www.heise.de/blog/Meinung-Softwareentwicklung-ist-keine-Kunst-9755000.html
[2] https://www.youtube.com/watch?v=tQXfbhXExog
[3] https://www.heise.de/Datenschutzerklaerung-der-Heise-Medien-GmbH-Co-KG-4860.html
[4] https://medium.com/@cmaitchison/are-you-a-software-gardener-f79eba5b7fb7
[5] https://www.thenativeweb.io/
[6] mailto:rme@ix.de

Copyright © 2024 Heise Medien

Adblock test (Why?)

  • 29. Juni 2024 um 09:00

Oracles Lizenzpolitik: Ein Angebot, das Sie nicht ablehnen können

Von Hendrik Ebbers
Oracle-Schild vor dem Waterfront Campus in Austin

(Bild: JHVEPhoto/Shutterstock.com)

Oracles fragwürdige Mittel, Lizenzen für ihre OpenJDK-Distribution einzutreiben, gefährden im schlimmsten Fall Java, meinen Hendrik Ebbers und Falk Sippach.

Sicherlich ist es für viele nichts Neues, dass Oracles Lizenzpolitik nicht gerade nutzerorientiert ist. House of Brick ist ein international tätiger Dienstleister, der Firmen bezüglich der verschiedenen Lizenzmodelle von Oracle berät. Dass es dafür ein Geschäftsmodell gibt, sagt schon einiges darüber aus. Genau diese Firma hat nun Informationen darüber veröffentlicht, dass sich eine immer größer werdende Zahl Kunden im Bereich Java-Lizenzen beraten lässt. Diese Unternehmen wurden offenbar von Oracle kontaktiert, da sie Java SE nicht konform nutzen und einen Lizenzvertrag mit Oracle abschließen müssen.

Aber der Reihe nach: Warum benötigt es so einen Vertrag und wie kam Oracle überhaupt an die Informationen zu diesen Firmen?

Schrauben am Lizenzmodell

Oracle hat im April 2019 zwei neue Lizenzmodelle für die Nutzung des Oracle JDK (ihre kommerzielle Java Distribution) eingeführt. Die bis dahin freie Distribution wurde damit kostenpflichtig. Mit dem Release von Java 20 [1] wurde das Lizenzmodell noch einmal angepasst. Oracle führte nach eigener Aussage ein "einfaches, kostengünstiges, monatliches" Java SE-Universal-Abonnement ein. In diesem neuen Modell müssen Nutzer der Java Distribution von Oracle Lizenzgebühren pro Mitarbeiter des Unternehmens bezahlen. Die Unternehmensberatung Gartner schätzte [2] im letzten Jahr, dass das neue Lizenzmodell pro Mitarbeiter zwei- bis fünfmal teurer sein wird, als das bisherige.

Auf Basis dieses neuen Lizenzmodells "klappert" Oracle nun Firmen ab, um möglichst viele Lizenzverträge abzuschließen. Laut House of Brick hat Oracle ein ganzes Team von Mitarbeitern in Indien eingesetzt, welche Organisationen auf der ganzen Welt kontaktieren. Die Firmeninformationen haben sie hierbei über die letzten Monate gesammelt, indem sie die Downloads ihrer eigenen Java Distribution getrackt haben. Unternehmen, die noch nie mit Oracle zusammengearbeitet haben, sind mit dieser plötzlichen Kontaktaufnahme oft überfordert und wenden sich Hilfe suchend an House of Brick. Laut dessen CEO unterbreitet Oracle diesen "Neukunden" ein Angebot, das sie nicht ablehnen können: Wenn diese Firmen direkt das Abo-Modell abschließen, hat der frühere Einsatz nicht lizenzierter Software keine Folgen. Das bedeutet im Grunde, dass eine Firma entscheiden muss: gehen sie einen Vertrag mit Oracle ein oder nehmen sie das Risiko in Kauf, dass sie gerichtlich zur Nachzahlung von einem solchen Abonnement gezwungen werden.

Soweit die Fakten, welche man auch bei The Register [3] oder im Blog von House of Brick [4] nachlesen kann. Bedeutet das aber nun, dass die Nutzung von Java in Zukunft an ein Abo-Modell bei Oracle geknüpft ist? Natürlich nicht und im Folgenden möchten wir unsere persönliche Sicht der Dinge darlegen. Wir sind sehr besorgt über die jüngsten Entwicklungen hinsichtlich der Lizenzierungspraxis von Oracle für ihre kommerzielle Java Distribution. Dieses Vorgehen kann ein nachhaltig negatives Licht auf die Programmiersprache Java und ihre Laufzeitumgebung werfen. Auch wenn die meisten Entwickler verstehen, dass es sich hier nur um die von Oracle bereitgestellte Distribution von Java handelt, haben Manager und Entscheider oft nicht diesen tiefen Einblick. Anstelle Geld mit Java zu verdienen, kann Oracles Taktik im schlimmsten Fall dazu führen, dass sich Firmen in Zukunft ganz von Java verabschieden.

Pochen auf die Namensrechte

Diese Geschichte zeigt auch, wie verzweifelt Oracle versucht, mit Java Geld zu machen. Mit der Übernahme von Sun Microsystems im Jahr 2009 haben sie Java erworben und sie sind heute der größte Contributor des OpenJDK. Auch die Namensrechte für das OpenJDK und Java liegen bei Oracle. Basierend auf den aktuellen Ereignissen fragen wir uns nun, was Oracle als Nächstes probieren wird, falls die aktuellen Bemühungen nicht den ausreichenden Erfolg bringen. Wir gehen stark davon aus, dass sie durch diese Vorgehensweise keine nachhaltigen und aus Kundensicht sinnvollen Lizenzverträge für Java abschließen werden. Und vielleicht beschließt ein Manager bei Oracle dann, die Mittel für das OpenJDK zu kürzen. Das wäre etwas, das die ganze Java Community betreffen würde. Am Beispiel von JavaScript sieht man [5], wie Oracle als Besitzer des Trademarks auch auf sein Markenrecht pocht, obwohl sie keinerlei Entwicklungsaktivitäten in dieser Sprache betreiben.

Und nein, wir haben kein Problem damit, wenn Oracle Geld mit dem OpenJDK, Java oder der kommerziellen Java Distribution verdient. Aber wir stellen die Frage, ob dieses Vorgehen wirklich gesund und nachhaltig für das Produkt und die Community ist. Daher wünschen wir uns von Oracle, Transparenz und Fairness bei ihren Lizenzierungsprozessen zu gewährleisten. Unternehmen, die die Java Distribution von Oracle nutzen, sollten klar und deutlich über die Lizenzforderungen informiert werden, bevor sie zu kostenpflichtigen Modellen wechseln müssen.

Viele gute Alternativen

An alle Entscheider: Es gibt mehrere hochqualitative und kostenfreie Open-Source-Alternativen [6] zur kommerziellen Java Distribution von Oracle, wie beispielsweise Temurin von Eclipse Adoptium, Corretto von Amazon [7] und andere. Diese Alternativen bieten ähnliche Funktionen und langfristige Unterstützung ohne kommerzielle Lizenzgebühren. Verantwortliche können hier die Unterstützung und Ressourcen der Java-Community nutzen und auf Experten in diesem Bereich (z. B. Open Elements [8]) zurückgreifen.

Das Ziel von Adoptium ist es beispielsweise, zertifizierte und für alle Arten von Anwendungen geeignete Java-Builds zu entwickeln und zu verteilen, ohne dass zusätzliche Lizenzgebühren anfallen. Da alle Arbeiten bei Adoptium in der Eclipse Foundation [9] durchgeführt werden, ist Temurin nicht nur herstellerunabhängig, sondern auch deutlich transparenter in der Entwicklung und Bereitstellung als die meisten anderen Distributionen. Unternehmen sollten daher eine Migration zu Temurin in Erwägung ziehen. Hierdurch entsteht nicht nur eine hohe Kostenersparnis. Im Bereich Security erhält man durch transparente Prozesse und Audits ein klareres Bild der genutzten Laufzeitumgebung. Temurin hat sich erst neulich Security Audits unterzogen und die Ergebnisse öffentlich bereitgestellt [10].

Update

Korrektur bezüglich der Arbeit von Oracle im JavaScript-Ökosystem: Seit 2020 unterstützt Oracle die ECMA-Arbeitsgruppe zur Spezifizierung der Sprache JavaScript durch eine Mitgliedschaft finanziell und hat mit GraalJS eine eigene Implementierung von Ecma-Script auf Basis der GraalVM.


URL dieses Artikels:
https://www.heise.de/-9781727

Links in diesem Artikel:
[1] https://www.heise.de/news/Java-20-erweitert-die-Nebenlaeufigkeit-mit-Scoped-Values-7549078.html
[2] https://www.theregister.com/2023/07/24/oracle_java_license_terms/
[3] https://www.theregister.com/2024/06/20/oracle_java_licence_teams/
[4] https://houseofbrick.com/blog/oracle-java-licensing-risks-2024/
[5] https://www.heise.de/news/Node-js-Entwickler-Ryan-Dahl-bittet-Oracle-Gebt-die-Marke-JavaScript-frei-7254391.html
[6] https://www.heise.de/blog/Java-ohne-Kopfschmerzen-Distributionen-und-Support-jenseits-von-Oracle-9232113.html
[7] https://www.heise.de/news/Java-Amazons-OpenJDK-Variante-Corretto-ist-allgemein-verfuegbar-4295845.html
[8] https://open-elements.com/temurin-support/
[9] https://www.heise.de/news/AdoptOpenJDK-landet-bei-der-Eclipse-Foundation-4789835.html
[10] https://adoptium.net/de/blog/2024/06/external_audit/
[11] mailto:rme@ix.de

Copyright © 2024 Heise Medien

Adblock test (Why?)

  • 28. Juni 2024 um 12:04

Meinung: Softwareentwicklung ist keine Kunst

Von Golo Roden

(Bild: iX / generiert mit ChatGPT)

Was sind Softwareentwicklung und Informatik? Kunst oder Ingenieurswissenschaften? Ein Kommentar.

Ich gebe zu, dass ich ein großer Fanboy bin – und zwar von dem US-amerikanischen Informatiker Donald E. Knuth. Er wurde bereits 1938 geboren und arbeitet seit Jahrzehnten an einem der, wenn nicht gar an dem größten literarischen Werk der Informatik schlechthin, nämlich: "The Art of Computer Programming [1]". Vielleicht kennen Sie ihn aber auch aufgrund eines der zahlreichen Zitate, die auf ihn zurückgehen, beispielsweise:

„Hüten Sie sich vor Fehlern in oben stehendem Code. Ich habe nur bewiesen, dass er korrekt ist, aber ich habe ihn nicht getestet.“

Solche Sätze, die zugleich lustig, tiefgründig und intelligent sind, gibt es einige von ihm. Eine Frage, mit der er sich dabei intensiv und immer wieder beschäftigt, lautet: Was zeichnet Softwareentwicklung eigentlich letztlich aus? Handelt es sich um eine Kunst oder eher um eine Ingenieurswissenschaft?

Code vor dem Kamin lesen

Ein Zitat von Donald E. Knuth habe ich gerade bereits erwähnt, aber es gibt noch ein anderes, das für mich persönlich das mit Abstand schönste ist, nämlich:

"Wann haben Sie es sich das letzte Mal vor dem Kamin gemütlich gemacht und ein gutes Stück Code gelesen?"

Ich vermute, dass Sie das wahrscheinlich noch nie gemacht haben – ja, dass Sie wahrscheinlich noch nicht einmal jemals darüber nachgedacht haben, dass man das eigentlich einmal machen könnte. Da stellt sich doch die Frage: Wo wir als Entwicklerinnen und Entwickler jeden Tag von morgens bis abends mit Code hantieren, wo Code für viele von uns eine Sprache wie Englisch oder Französisch ist, und wo wir dermaßen viel Zeit damit verbringen, Code zu schreiben, warum nehmen wir uns nicht die Zeit, ihn mit der angemessenen Aufmerksamkeit und wohlwollender Wertschätzung zu lesen?

Und zugegeben: Es klingt zunächst reichlich seltsam, das zu machen. Aber, wenn Sie Informatik studiert haben, dann werden Sie sich vielleicht daran erinnern, dass im Studium immer wieder einmal die Rede davon war, man solle nach eleganten und schönen Lösungen suchen. Und das kennen wir auch aus anderen wissenschaftlichen Disziplinen, wie zum Beispiel der Mathematik: Auch dort ist immer wieder von schönen und eleganten Beweisen die Rede. Wenn also Algorithmen oder Beweisen eine Ästhetik innewohnt, warum nehmen wir uns dann nicht die Zeit, sie einmal ganz bewusst wahrzunehmen und sie gegebenenfalls auch, wenn sie besonders gelungen sind, entsprechend zu bewundern?

Code als Kunst?

Vielleicht sagen Sie nun, dass Ihnen das zu akademisch und zu abgehoben ist, aber denken Sie doch einmal kurz über das Wort "Hacker" nach. Heute bezeichnen wir damit jemanden, der mit bösen Absichten in Computer einbricht und Daten stiehlt oder zerstört. Ein Hacker ist heute ein Vandale, ein Verbrecher. Aber das war nicht immer so. Als das Wort in den 1980er- und frühen 1990er-Jahren aufkam, bezeichnete es jemanden, die oder der komplizierte und komplexe Probleme auf intelligente, schlaue und einfache Art lösen und elegante und schöne Lösungen in Code zaubern konnte. Mit anderen Worten: Es gab eine Zeit, in der wir Ehrfurcht vor Codekünstlern hatten.

Und wenn man sich noch einmal den Titel des monumentalen Werks von Knuth vor Augen führt, dann fällt auf: Es heißt "The Art of Computer Programming", nicht einfach nur "Computer Programming" oder ähnlich. Es geht um "the art", also um die Kunst der Programmierung. Und Knuth will das auch tatsächlich genau so verstanden wissen, denn er hat Programmieren verschiedentlich zum Beispiel mit dem Komponieren von Musik oder dem Dichten verglichen, dass das alles ästhetische Erfahrungen seien, bei denen Schönheit geschaffen werde. Ich persönlich empfinde es als bemerkenswert, einmal aus dieser Perspektive über das Schreiben von Code nachzudenken.

Softwareentwicklung als Ingenieurswissenschaft

Wenn wir das nun einmal damit vergleichen, was im Alltag und im Job der meisten Entwicklerinnen und Entwickler passiert, dann ist das üblicherweise weit von Kunst entfernt. Das merkt man unter anderem sehr rasch an den Begriffen, mit denen wir uns umgeben: Da geht es um Software-Engineering, da geht es um Software-Factories, da wird Informatik als Ingenieurswissenschaft gesehen, die vorhersagbar, planbar und deterministisch sein soll. Mit anderen Worten: Das ist dermaßen weit weg von einer künstlerischkreativen Sichtweise, dass es schon erstaunlich (oder, je nach Sichtweise, erschreckend) ist.

Ganz automatisch stellt sich dann die Frage: Wer hat denn nun recht? Was ist Informatik denn eigentlich tatsächlich? Was ist das Wesen und was ist der Kern des Ganzen?

Ein Blick in die Industrie zeigt, wohin die Reise geht: Tests? Werden oft weggelassen, kosten unnötig Geld und sind nicht so wichtig. Man weiß ja: Man bekommt günstigere Software durch weniger Tests [3]. Dokumentation? Auch die braucht nicht unbedingt jemand, auch sie kostet nur Geld und vor allem Zeit. Clean Code? Naja, wenn es unbedingt sein muss, dann können wir vielleicht einmal eine Woche einen Refactoring-Sprint machen, aber danach muss man dann bitte wieder neue Features schreiben, denn der Kunde zahlt schließlich nicht für Clean Code. Der Kunde zahlt nämlich generell nicht für den Code, der ist ihm nämlich komplett egal. In Wahrheit zahlt der Kunde stattdessen dafür, dass wir ein Problem pragmatisch und effizient lösen. Und dass wir das mit Code und nicht mit einem Schraubenzieher machen, ist dabei bestenfalls ein drittrangiger Seitenaspekt.

70.000 Zeilen PHP-Code

Das Erstaunliche an alldem ist, dass es funktioniert. Ich habe vor etlichen Jahren jemanden in einem großen Konzern kennengelernt, der alleine an einer Analyse-Software für den Vorstand gearbeitet hat. Sein Code (und diese Geschichte ist tatsächlich wahr und kein Scherz) bestand aus 70.000 Zeilen PHP-Code in einer einzigen (!) Datei. Es gab keinen einzigen automatisierten Test, kein automatisiertes Deployment, keine CI/CD-Pipeline oder Ähnliches. Er hat nicht einmal mit einer Versionsverwaltung gearbeitet, sondern mit VI direkt die eine einzige PHP-Datei auf dem Produktivserver editiert.

Und tatsächlich fand er das gut so, denn: Wenn er diese eine Datei dann nach Stunden des Editierens endlich gespeichert hat, war die Anwendung sofort neu deployed. Das Schlimmste daran war, dass er in dem Team, zu dem er gehörte, derjenige war, der die mit Abstand stabilste und verlässlichste Software geschrieben hat. Das Sahnehäubchen an alldem: Das PHP-Skript war über mehrere Symlinks erreichbar, und je nachdem, wie es aufgerufen wurde, hat es sich anders verhalten. Der Vorstand hat ihn geliebt, aber alle anderen im Team haben ihn verflucht und jedes Mal gezittert, wenn er in den Urlaub gegangen ist oder krank war.

Woher die Diskrepanz?

Als externer Berater, als der ich damals für dieses Team fungiert habe, steht man dann da, mit all den Best Practices, die man für gute Codequalität vermitteln möchte, wie Unit-Tests, Integration-Tests, statischer Code-Analyse, Versionsverwaltung, Containerisierung, Continuous-Integration, Continuous-Deployment und so weiter, und es wird einem gesagt, das sei ja alles schön und gut, aber es würde alles hervorragend funktionieren, und es bringe nur Unruhe hinein, am bestehenden Vorgehen etwas zu ändern.

Und so sehr mich diese Sichtweise aus der einen Perspektive ärgert, muss ich auf der anderen Seite doch zugeben: Ja, er hat mit seinen 70.000 Zeilen PHP-Code auf dem Produktiv-Server das zugrunde liegende Problem gelöst und dem Vorstand verlässlich und termingerecht die gewünschten Zahlen geliefert. Das war das, was (zumindest aus einer gewissen Perspektive) wichtig war. Dennoch habe ich noch nie, wenn ich diese Geschichte erzähle, jemanden getroffen (und zwar völlig egal ob Entwickler oder Managerin), die oder der gesagt hätte: "Wow, super! So machen wir das ab sofort auch!"

Denn irgendwie wollen dann am Ende doch alle mehr Verlässlichkeit im Hinblick auf Qualität & Co. haben, zumal das auch das ist, was auf jeder Konferenz, auf jedem Meetup, in jedem Blog oder auf YouTube erzählt wird, unter anderem auch von Leuten wie mir. Aber auch ich muss zugeben, dass der Pragmatismus und die rein auf das Lösen des Problems ausgerichtete Entwicklung nicht von der Hand zu weisen ist. Es ist effizient. Aber warum empfiehlt das trotzdem niemand? Woher kommt diese Diskrepanz?

Kunst versus Business

Letztlich glaube ich, dass das daher kommt, dass hier zwei gegensätzliche Sichtweisen aufeinanderprallen: Hier trifft nämlich Kunst auf Business. Und Informatik ist am Ende beides zugleich, Informatik ist eine Dualität. Die Auswirkungen dieser Dualität erleben wir im Alltag ständig, denn es gibt tagtäglich Reibungspunkte, wo diese beiden Welten und diese beiden Perspektiven in Konflikt miteinander geraten. Das fängt schon damit an, wenn man eine Aufwandsschätzung abliefern soll. Ich persönlich denke mir da immer: "Was weiß denn ich, wie lange ich für XY brauchen werde?"

Es heißt schließlich Softwareentwicklung und nicht Softwareproduktion, und ich könnte den Aufwand genau dann vorhersagen, wenn ich die Aufgabe vorher schon einmal so oder zumindest so ähnlich bewerkstelligt hätte, aber dann könnte ich den Code von der vorherigen Implementierung auch einfach kopieren und müsste ihn nicht neu entwickeln. Und das geht nicht nur mir so, das geht ganz vielen Entwicklerinnen und Entwicklern so, weshalb ich persönlich das Schätzen von Aufwand für relativ sinnfrei halte.

Denn letztlich ist es, wenn man eine Entwicklerin oder einen Entwickler nach einer Aufwandsschätzung fragt, wie wenn man Picasso fragen würde, ob er bitte mal schätzen könne, wie lange er für das Bild von einem Krokodil brauchen würde, immerhin sei das von seinem Dackel ja auch nur ein einziger Strich gewesen und könne höchstens fünf Minuten gedauert haben. Die Wahrheit ist aber: Kunst lässt sich nicht schätzen. Umgekehrt kann ich aber auch verstehen, dass man im Business planen können und Ergebnisse sehen möchte: Wenn ich ein Haus baue, will ich auch nicht hören, dass der Rauputz noch nicht fertig ist, weil "die Hand des Maestros seit einer Woche nicht den richtigen Schwung und die richtige Eingebung finde, um die Kelle zu führen".

Es braucht eine Skala

Allerdings sind diese beiden Sichtweisen zugleich auch die beiden Extreme, und wie immer, wenn es zwei Extreme gibt, gibt es auch etwas zwischen den Polen. Das heißt, am Ende sprechen wir bei der ganzen Angelegenheit über eine Skala. An deren einem Ende steht die reine Kunst, die Software und Code als Selbstzweck ansieht, quasi "l’art pour l’art". Am anderen Ende der Skala steht das rein pragmatische Business, wo es nur darum geht, Probleme möglichst effizient und kostengünstig zu lösen und sich (Achtung, Wortwitz) nicht zu verkünsteln. Code und Software sind hier ein reines Mittel zum Zweck.

Die Wahrheit liegt, vermute ich, irgendwo dazwischen, denn Kunst ohne Anwendung kommt nicht aus ihrem Elfenbeinturm heraus. Aber Anwendung ohne Kunst hat keine Seele. Und die alles entscheidende Frage lautet: Wo stehen Sie auf dieser Skala?

Ich glaube, wenn sich mehr Entwicklerinnen und Entwickler über diese Frage Gedanken machen und für sich einen Standpunkt definieren würden, und wenn Unternehmen dasselbe tun würden, und wenn man dann über das jeweilige Wertesystem sprechen würde, dann würde Entwicklung deutlich besser und reibungsloser verlaufen, weil es weniger Konflikte und Missverständnisse über die Natur der Entwicklung an sich gäbe.

Und dann wäre Softwareentwicklung am Ende vielleicht tatsächlich genau das: keine Kunst.


URL dieses Artikels:
https://www.heise.de/-9755000

Links in diesem Artikel:
[1] https://de.wikipedia.org/wiki/The_Art_of_Computer_Programming
[2] https://www.heise.de/Datenschutzerklaerung-der-Heise-Medien-GmbH-Co-KG-4860.html
[3] https://www.youtube.com/watch?v=Eqec4dNgqeQ
[4] mailto:rme@ix.de

Copyright © 2024 Heise Medien

Adblock test (Why?)

  • 21. Juni 2024 um 08:22

Neu in .NET 8.0 [26]: Anpassung der Resilienz im HTTP-Client

Von Dr. Holger Schwichtenberg

(Bild: sirtravelalot/Shutterstock.com)

Entwicklerinnen und Entwickler können eigene Polly-Pipelines zur Handhabung von Fehlersituationen definieren.

Die vorherige Ausgabe dieser Blogserie zu .NET 8.0 [1] hat AddStandardResilienceHandler() vorgestellt. In diesem Beitrag geht es um die Anpassung der Standardeinstellungen.

Alternativ zu AddStandardResilienceHandler() kann man via AddResilienceHandler() eine komplett eigene Polly-Pipeline definieren. Abbildung 1 zeigt die standardmäßige Pipeline.

Der Standard-Handler erledigt fünf Aufgaben in einer sogenannten Pipeline (Abb. 1).

(Bild: Microsoft [2])

Die folgende selbstdefinierte Pipeline verwendet nur die Aufträge 2 bis 5 aus obiger Tabelle mit folgenden Einstellungen:

  • Geamtanforderungs-Timeout: 10 Sekunden
  • Wiederholen: Der Aufruf wird bis zu fünfmal wiederholt. Der Abstand zwischen den Versuchen ist konstant 1 Sekunde. Bei dem Versuch gibt es eine Bildschirmausgabe.
  • Trennschalter: Abbruch, wenn in 10 Sekunden 50 % der Anfragen fehlschlagen, frühestens aber nach 5 Anfragen
  • Versuchs-Timeout: 2 Sekunden
services.AddHttpClient<WeatherServiceClient>(
  // Timeout insgesamt: Hier 10 Sekunden
  client => { client.Timeout = new TimeSpan(0,0,10); })
  .AddResilienceHandler(
   "CustomPipeline",
   static builder =>
   {
   // Wiederholungen bei Fehlern
   // Hier: Der Aufruf wird bis zu fünf Mal wiederholt. Der Abstand zwischen den Versuchen ist konstant 1 Sekunde. Bei dem Versuch gibt es eine Bildschirmausgabe.
   // https://www.pollydocs.org/strategies/retry.html
   builder.AddRetry(new HttpRetryStrategyOptions
    {
     // Customize and configure the retry logic.
     BackoffType = DelayBackoffType.Constant, // oder Linear oder Exponential
     Delay = TimeSpan.FromSeconds(1),
     MaxRetryAttempts = 10,
 
     OnRetry = static (args) =>
     {
      CUI.Cyan($"{DateTime.Now.ToLongTimeString()} Versuch #{args.AttemptNumber} Zeit seit letztem Versuch:{(int)(DateTime.Now - lastTry).TotalMilliseconds} ms Dauer:{args.Duration} Grund:{args.Outcome.Result} \n");
      lastTry = DateTime.Now;
      return ValueTask.CompletedTask;
     },
    });
 
    // Trennschalter, wenn zu viele Fehler passieren
    // Hier: Abbruch wenn in 10 Sekunden 50% der Anfragen fehlschlagen, frühestens aber nach 5 Anfragen
    // https://www.pollydocs.org/strategies/circuit-breaker.html
    builder.AddCircuitBreaker(new HttpCircuitBreakerStrategyOptions
    {
     // Customize and configure the circuit breaker logic.
     SamplingDuration = TimeSpan.FromSeconds(10),
     FailureRatio = 0.5,
     MinimumThroughput = 5,
     ShouldHandle = static args =>
     {
      return ValueTask.FromResult(args is
      {
       Outcome.Result.StatusCode: HttpStatusCode.RequestTimeout or HttpStatusCode.TooManyRequests or HttpStatusCode.InternalServerError
      });
     }
    });
 
    // Timeout für einzelne Versuche
    // hier: 2 Sekunden
    // https://www.pollydocs.org/strategies/timeout.html
    builder.AddTimeout(TimeSpan.FromSeconds(2));
   });


URL dieses Artikels:
https://www.heise.de/-9773126

Links in diesem Artikel:
[1] https://www.heise.de/blog/Neu-in-NET-8-0-25-Resilienz-im-HTTP-Client-9763586.html
[2] https://learn.microsoft.com/de-de/dotnet/core/resilience/http-resilience
[3] mailto:rme@ix.de

Copyright © 2024 Heise Medien

Adblock test (Why?)

  • 21. Juni 2024 um 16:52

Neu in .NET 8.0 [25]: Resilienz im HTTP-Client

Von Dr. Holger Schwichtenberg
Netzwerkstecker

(Bild: asharkyu/Shutterstock.com)

.NET 8.0 enthält die etablierte Bibliothek Polly für Ausfallsicherheit und den Umgang mit temporären Fehlersituationen.

Microsoft hat die etablierte .NET-Bibliothek Polly [1] für Ausfallsicherheit und den Umgang mit temporären Fehlersituationen in .NET 8.0 integriert. Dazu gibt seit .NET 8.0 die neue NuGet-Pakete Microsoft.Extensions.Resilience und Microsoft.Extensions.Http.Resilience.

Die Verwendung in Verbindung mit einem WebAPI-Aufruf ist einfach: Man verwendet AddStandardResilienceHandler() beim Injizieren einer HttpClient-Instanz.

 // Erzeuge einen Service Builder 
 IServiceCollection services = new ServiceCollection();
 
 // Ergänze HTTP Client für Wetterdienst
 // NEU in .NET 8.0: 
 .AddStandardResilienceHandler(); // basiert auf Polly !
 services.AddHttpClient<WeatherServiceClient>().AddStandardResilienceHandler();
 
 IServiceProvider serviceProvider = services.BuildServiceProvider();
 
 for (int i = 0; i < 10000; i++)
 {
  var client = serviceProvider.GetService<WeatherServiceClient>();
 
  try
  {
   var daten = client.GetWeather();
 
   #region Ausgabe der Wetterdaten
   foreach (var item in daten.Result)
   {
    Console.WriteLine(item.Date + " " + 
                      item.TemperatureC + " " + item.Summary);
   }
   #endregion
 
   System.Threading.Thread.Sleep(500);
  }
  catch (Exception ex)
  {
 
   CUI.Error(DateTime.Now + ": " + ex.Message);
  }
 }

Der Standard-Handler erledigt fünf Dinge in einer sogenannten Pipeline (Abb. 1).

(Bild: Microsoft [2])

Hinweis: Die Strategien des Standard-Handlers lassen sich per Programmcode oder per Anwendungskonfigurationsdatei appsettings.json anpassen. Die Dokumentation dazu finden Sie nicht bei Microsoft, sondern bei Polly [3]. Die bei dem Standardhandler geltenden Standardeinstellungen findet man dabei jeweils bei den einzelnen Strategien, beispielsweise sieht man [4], dass ein Aufruf maximal dreimal versucht wird mit einer konstanten Verzögerung von zwei Sekunden.

Durch Übergabe einer Funktion, die ein Objekt vom Typ HttpStandardResilienceOptions liefert, kann man die Polly-Pipeline umkonfigurieren. Das nächste Beispiel zeigt: Der Aufruf wird bis zu fünf Mal wiederholt. Der Abstand zwischen den Versuchen ist konstant eine Sekunde. Bei dem Versuch gibt es eine Bildschirmausgabe.

services.AddHttpClient<WeatherServiceClient>().AddStandardResilienceHandler(options =>
{
 options.Retry.BackoffType = 
   DelayBackoffType.Constant; // oder Linear oder Exponential
 options.Retry.Delay = TimeSpan.FromSeconds(1);
 options.Retry.MaxRetryAttempts = 5;
 options.Retry.OnRetry = static (args) =>
 {
  CUI.Cyan($"Versuch #{args.AttemptNumber} Zeit seit letztem Versuch:{(int)(DateTime.Now - lastTry).TotalMilliseconds} ms Dauer:{args.Duration} Grund:{args.Outcome.Result} \n");
  lastTry = DateTime.Now;
  return ValueTask.CompletedTask;
 };
}
);


URL dieses Artikels:
https://www.heise.de/-9763586

Links in diesem Artikel:
[1] https://github.com/App-vNext/Polly
[2] https://learn.microsoft.com/de-de/dotnet/core/resilience/http-resilience
[3] https://www.pollydocs.org/strategie
[4] https://www.pollydocs.org/strategies/retry.html#defaults
[5] mailto:rme@ix.de

Copyright © 2024 Heise Medien

Adblock test (Why?)

  • 14. Juni 2024 um 14:31

Cisco: Neue Firewalls – natürlich mit KI

Von Heise

(Bild: Cisco)

Im Rahmen der Hausmesse Live hat Cisco mehrere neue Firewall-Serien vorgestellt. Neben dem neuen Topmodell gab es auch einen GenAI-Assistenten zu sehen.

Cisco kümmert sich um die Auffrischung des Desktop-Firewall-Portfolios für Zweigstellen und kleine Unternehmen. Die neue Cisco Secure Firewall der 1200er-Serie soll für die performante und sichere Anbindung kleiner Zweigstellen dienen. Für die Cloud-verwalteten Meraki-MX-Firewalls gibt es ein neues Topmodell namens MX650. Gleichzeitig bringt Cisco einen KI-Assistenten für Firewalls.

Hintergründe Secure Firewall 1200

Es soll ab Oktober 2024 drei neue Modelle [1] geben: Die kleinste 1210 CE bringt 3 Gbit/s Firewall- und 2 Gbit/s IPSec-VPN-Durchsatz. Sie besitzt 8*1000BASE-T Kupferports. Die 1210 CP liefert auf vier der acht Ports zusätzlich noch UPoE+, um beispielsweise WLAN Access-Points oder Telefone mit Strom zu versorgen. Falls es etwas mehr Durchsatz braucht oder der Internet-Uplink oder eine Verbindung zu einem Switch per Lichtwellenleiter erfolgen soll, liefert die 1220 CX zusätzlich zu 8*1000BASE-T Kupferports noch 2*SFP+-Slots und bis zu 6 Gbit/s Firewall- und 4 Gbit/s IPSec-VPN-Durchsatz. Alle drei Varianten kommen mit einem externen Netzteil daher.

Der Hersteller benennt im iX-Interview ein bis zu dreimal besseres Preis-/Durchsatzverhältnis im Vergleich zu Mitbewerbern. Konkrete Preise nannte Cisco auf der Live jedoch nicht, wodurch sich die Angaben nicht überprüfen lassen.

Cisco hat darüber hinaus die neue Software-Version 7.6 von Firewall Threat Defense (FTD) angekündigt, die für alle physischen und virtuellen Firewalls von Cisco verfügbar ist. Sie soll den Rollout von Zweigstellennetzwerken mit vorgefertigten SD-WAN- und Firewall-Vorlagen sowie Zero-Touch-Provisioning unterstützen.

Cloud-Managed Firewall-Topmodell

Das neue Topmodell der cloud-verwalteten Meraki-MX-Firewall stellt die nun frisch vorgestellte MX650 [2] dar. Sie bietet einen SFP28-Einschub für bis zu 25G dediziert auf WAN-Seite sowie konfigurierbar auf LAN-Seite einen 25G SFP28- und zwei 10G SFP+- sowie acht 1G SFP-Einschübe. Sie soll mit bis zu 25 Gbit/s über 5-fachen maximalen IPSec-Durchsatz und mit 16 Gbit/s Durchsatz für erweiterte Sicherheitsfunktionen mehr als doppelte Performance im Vergleich zur MX450 bieten. Auch die maximale empfohlene Client-Anzahl steigt von 10.000 bei der MX450 auf 50.000 Clients bei der MX650. Das Ganze kommt auf Basis einer Höheneinheit daher.

KI-Assistent

Zudem gab es auf der Cisco Live in Las Vegas auch einige Informationen zum sogenannten AI Assistant for Security [3]. Er baut auf dem Firewall Management Center (FMC) oder dem Cisco Defense Orchestrator (CDO) aus der Cloud auf. Mit dieser Kombination sollen Administratoren ihre Firewalls verwalten, Richtlinien konfigurieren und bei Bedarf auf Referenzmaterialien zugreifen, um effizienter zu werden. Dabei handelt es sich nach Angaben des Herstellers um ein generatives KI-Tool auf Basis eines LLMs mit Natural Language Processing (NLP). Auch bei Fehlverhalten, wie unkontrollierten Neustarts, soll der Assistent Empfehlungen geben, beispielsweise Softwareupdates mit entsprechenden Hinweisen.


URL dieses Artikels:
https://www.heise.de/-9759186

Links in diesem Artikel:
[1] https://www.cisco.com/site/us/en/products/security/firewalls/secure-firewall-1200-series/index.html
[2] https://documentation.meraki.com/MX/MX_Overviews_and_Specifications/MX650_Datasheet
[3] https://blogs.cisco.com/security/give-your-firewall-admins-superpowers-with-cisco-ai-assistant-for-security
[4] https://www.heise.de/ix/
[5] mailto:fo@heise.de

Copyright © 2024 Heise Medien

Adblock test (Why?)

  • 12. Juni 2024 um 10:23

Schnelle optische Chip-Interconnects mit Graphen-Technik aus Deutschland

Von Heise

Das Aachener Start-up Black Semiconductor sichert sich eine Viertelmilliarde Euro für die Fertigung von Graphen-Optelektronik.

Die Europäische Union (EU) sowie private Investoren stecken insgesamt 254,4 Millionen Euro in das junge Aachener Unternehmen Black Semiconductor. Dessen Name bezieht sich auf die schwarze Farbe von Kohle, denn das superdünne Material Graphen mit besonderen elektrischen und optischen Eigenschaften ist eine Modifikation von Kohlenstoff.

Black Semi will eine Pilot-Fertigungsanlage für schnelle optoelektronische Komponenten aus Graphen [1] auf 300-Millimeter-Wafern bauen. Ziel ist es, optische Interconnects mit Graphen-Technik in "normale" CMOS-Logikchips wie Prozessoren, Systems-on-Chip (SoCs) und Rechenbeschleuniger zu integrieren: Co-integrated Optics (CIO). Das soll sehr leistungsfähige und energetisch effiziente Chip-zu-Chip-Kommunikation auch über längere Distanzen ermöglichen.

Der Mitgründer Dr. Daniel Schall forscht seit Jahren an Graphen-Optoelektronik [2] und war auch für die Gesellschaft für Angewandte Mikro- und Optoelektronik mbH (AMO GmbH) tätig, die das Advanced Microelectronic Center Aachen (AMICA) betreibt [3]. Black Semiconductor [4] wurde 2019 aus der AMO GmbH ausgegründet.

Optische Chip-zu-Chip-Interconnects

Auch andere Firmen tüfteln daran, CMOS-Logikchips und optische Interconnects eng zu koppeln. Intel meldet seit rund 20 Jahren immer wieder Fortschritte [5] bei Silicon Photonics, also bei in Siliziumtechnik umgesetzter Optoelektronik.

Nvidia-CEO Jensen Huang wies vor wenigen Monaten auf die Nachteile der Umwandlung von elektrischen in optische Signale [6] hin und erklärte, dass man für die schnelle Vernetzung von KI-Clustern per NVLink daher bisher auf Kupferkabel setze. Die Integration optischer Interconnects direkt in Logikchips könnte die Energieeffizienz optischer Interconnects in der Praxis erheblich steigern.

Ein weiterer Ansatz zur Anbindung optischer Transceiver an CMOS-Chips sind Chiplets. Außerdem arbeiten einige Firmen an optischen Prozessoren [7].


URL dieses Artikels:
https://www.heise.de/-9751925

Links in diesem Artikel:
[1] https://www.heise.de/hintergrund/Graphen-Vom-Hype-zur-Anwendung-2792052.html
[2] https://scholar.google.de/citations?user=K6795lYAAAAJ&hl=de
[3] https://www.amo.de/de/ueber-amo/geschichte/
[4] https://blacksemi.com/
[5] https://www.heise.de/news/Intel-plant-Prozessoren-mit-optischen-Schnittstellen-4978154.html
[6] https://www.semianalysis.com/p/nvidias-optical-boogeyman-nvl72-infiniband
[7] https://www.heise.de/hintergrund/Optische-Prozessoren-Aufbau-und-Entwicklungsstand-7446679.html
[8] https://www.heise.de/ct/
[9] mailto:ciw@ct.de

Copyright © 2024 Heise Medien

Adblock test (Why?)

  • 12. Juni 2024 um 09:00
❌