Entwicklung & Code
Von kleinen Hacks, technischen Schulden und Notlügen
„Wie kommt deine Mutter mit der Reha zurecht?“ – „Ganz gut, danke.“ – „Ich habe sie aber gestern beim Einkaufen gesehen.“ – Ups, das ist jetzt peinlich. Ungefähr so peinlich wie die Webanwendung, die zum dritten Mal diese Woche stillsteht. Oder das coole neue Feature, das nach sechs Monaten immer noch nicht implementiert ist.
Weiterlesen nach der Anzeige

ist IT-Beraterin, Coach und freie Wissenschaftlerin. Mit ihrem Hintergrund in Künstlicher Intelligenz, User Experience Design und Entscheidungsfindung macht sie Software- und Entwicklungsteams fit für die harte Realität.
Aller Anfang ist harmlos
Dabei fängt es immer so harmlos an. „Wir fahren am Wochenende auf die Hütte von meinem Onkel. Kommst du mit?“ – „Nee, hab keine Lust, und schon gar nicht auf diese modrige Hütte“ ist eine schlechte Antwort. Daher besser: „Klingt toll. Aber meinen Eltern geht es gerade nicht so gut, da will ich nicht ein ganzes Wochenende so weit wegfahren. Vielleicht brauchen sie mich.“ Höflich, unspezifisch, Problem gelöst.
Oder in der Welt des Programmierens: Da ist jetzt noch ein Sonderfall aufgetaucht. Der passt überhaupt nicht ins Konzept, aber wir können ja kaum alles komplett umschreiben. Also hier ein weiterer If-Block, da eine Funktion kopiert und mit ein paar kleinen Änderungen versehen. Schnell, unkompliziert, Problem gelöst.
Meistens endet die Geschichte hier. Aber nicht immer.
„Kommst du am Sonntag zum IT-Kaffee? A propos, geht es deiner Mutter besser?“ Wie praktisch, dieses Mal wird die Ausrede gleich mitgeliefert. „Eigentlich ganz gut. Aber nach so einer Hüft-OP ist man halt eingeschränkt. Ich helfe ihr am Wochenende beim Putzen.“ – „Das kenne ich. Mein Onkel musste drei Wochen in die Reha. Wieso ist deine Mutter zu Hause?“ – „Sie wartet noch auf einen Platz. Nächste Woche sollte es losgehen.“ Kurve gekriegt, Wochenende frei gehalten, alles gut.
Weiterlesen nach der Anzeige
Parallel dazu im Programmierprojekt: Zu dem Sonderfall haben sich noch ein paar weitere gesellt. Der harmlose If-Block ist zu einem großen Entscheidungsbaum gewachsen, und die kopierte Funktion wurde dreimal erweitert und zweimal weiterkopiert. Alles läuft irgendwie. Also auf zum nächsten Feature, alles gut.
Das bittere Ende
Manchmal geht das Ganze so weit, dass es peinlich wird. Der Schwindel fliegt auf oder die Software wird instabil. Beim Lügen ist oft das Ende klar, etwa weil man sich verplappert. Bei Software ist das weniger eindeutig.
Dort bauen sich technische Schulden auf. Woran erkennt man diese Schulden und ab wann werden sie zum Problem? Software ist nicht per se schuldenbehaftet, nur weil sie alt ist, und nicht jeder kleine Hack führt direkt in eine Schuldenspirale.
Das Problem ist die Passung zwischen Code und Konzept. Peter Naur hat schon 1985 in seinem Artikel „Programming as theory building“ beschrieben, dass ein Programm nicht in erster Linie Code ist, sondern die Instanziierung eines Konzepts – er nennt es sogar Theorie. Ändert man ein Programm, fügt man nicht nur Codezeilen hinzu, ändert oder löscht sie, sondern verändert das Gesamtkonzept.
Wenn Code wächst, verformt sich das Konzept. Das kann auf eine organische Weise passieren, wie ein Anbau an ein Haus. Es kann auch wie eine Delle in einem Luftballon sein: nicht unbedingt schön, aber auch kein Problem. Wenn aber die An- und Umbauten überhandnehmen, verwässern sie das ursprüngliche Konzept. Das Programm ist nicht mehr die Umsetzung eines Konzepts, sondern besteht nur noch aus aneinandergereihten nichtssagenden Codezeilen. Und damit ist absehbar, dass jede Änderung am Code zum Glücksspiel wird.
Nie wieder lügen?
Was sollte man also tun, um die Katastrophe gar nicht erst entstehen zu lassen?
Die naheliegende Lösung wäre, nie zu lügen und Code immer nur so zu ändern, dass er zum Programmkonzept passt oder das Konzept weiterentwickelt.
Aber ist das realistisch? Will man dem besten Kumpel wirklich einen Vortrag über individuelle Unterschiede bei der Farbästhetik halten, wenn er stolz sein neues Cabrio in neonpink präsentiert? Ein einfaches „sieht toll aus“ mag nicht ehrlich sein, unkompliziert ist es allemal.
Und wer weiß, vielleicht stellt sich nächste Woche heraus, dass der Sonderfall doch nicht gebraucht wird. Oder es kommen noch ein paar ähnliche dazu. Hacks sind auch ein Mechanismus zum Lernen. Wenn man Modifikationen erst einmal „quick and dirty“ in den Code wirft, kann man beobachten, wie sie sich entwickeln und welche Probleme tatsächlich auftauchen. Eine Neukonzeption des Programms für jede kleine Änderung bedeutet, die Software ins Koma zu legen, um sie vor dem Tod zu bewahren.
Besser ist es, Hacks zuzulassen und sich dessen bewusst zu sein. Das sind die Momente, in denen ausführliche Kommentare im Code (nicht nur in irgendeiner Dokumentation!) angebracht sind: Welche Funktionalität erforderlich war, warum eine schönere Lösung zu umständlich gewesen wäre, welche Stolpersteine dadurch entstehen. Wenn der nächste Sonderfall auftaucht und man auf den Hack noch einen draufsetzt, sieht man zumindest, dass man auf einem wackeligen Fundament aufbaut. Und spätestens, wenn die Kommentare einen halben Bildschirm einnehmen, sollte man sich geschlagen geben.
Die Stunde der Wahrheit
So wie das Ausräumen der ursprünglich harmlosen Notlüge tut das Aufräumen von Dirty Hacks weh oder kostet zumindest Zeit. Man wollte doch nur den nächsten kleinen Sonderfall einbauen. Wie erklärt man dem Team (und vor allem dem Geldgeber), dass jetzt zwei Monate ohne neue Features anstehen?
Im Grunde ist das der Moment, in dem wir unsere Schulden tilgen müssen. Die kleinen Hacks haben Zeit gespart im Vergleich zum sauberen Umbau des Gesamtkonzepts. Jetzt ist der Zeitpunkt gekommen, das Konzept und den Code wieder in Einklang zu bringen. Das ist auch eine Chance. Offensichtlich haben sich die Anforderungen weiterentwickelt. Wenn man sich diesen Änderungen stellt und das Konzept dafür fit macht, ist man auch für zukünftige Änderungen gerüstet.
Das WG-Problem
Die Frage, wann genau der Zeitpunkt für die Aufräumaktion gekommen ist, ist damit noch nicht geklärt. Ist die Umsetzung neuer Features deshalb so zäh, weil der Code nicht mehr zum Konzept passt oder weil die Features aufwendig sind? Ist der Fehler bei der letzten Änderung technischen Schulden zuzuschreiben oder unvermeidbare IT-Realität? Jede Entwicklerin und jeder Entwickler hat ein gewisses Gespür dafür, wann es einfach keinen Spaß mehr macht, an dem Programm zu arbeiten.
Allerdings haben alle ein unterschiedliches Gespür. Das ist wie bei der Sauberkeit der Küche einer WG. Der eine regt sich schon auf, wenn auf dem Tisch ein paar Brösel liegen, die andere bemerkt das dreckige Geschirr in der Spüle nicht einmal.
Dazu kommt, dass sich nur wenige den Luxus leisten können, die Freude am Programmieren zu optimieren, denn es geht auch um Geld. Leider ist nicht klar, um wie viel. Die Zeit, um ein Ticket abzuarbeiten, kann man messen und in Geld umrechnen. Allerdings kann eine schnell erledigte Aufgabe bedeuten, dass Code und Konzept zusammenpassen und die Änderung deshalb einfach war. Oder die gemessene Zeit enthält undokumentierte Schulden, weil man schnell Code zusammengeklopft hat, der später teuer werden wird.
Erstaunlicherweise scheuen viele Teams die Kosten zum Aufräumen des Codes, die ein paar angekündigte Monate ohne neue Features bedeuten. Dafür nehmen sie die Kosten für überschuldeten Code mit einigen neuen Features und vielen neuen Fehlern hin. Die erste Art von Kosten ist offensichtlich, die zweite ist versteckt. Aber das macht sie nicht günstiger. Wenn eine Bezifferung unmöglich ist, muss man aufs Bauchgefühl vertrauen, idealerweise auf das kollektive.
Das eine Extrem bilden Entwicklerinnen und Entwickler, die schlechten Code erkennen und möglichst frühzeitig vermeiden wollen, quasi die WG-Bewohner, die keine Brösel auf dem Tisch sehen können. Am anderen Ende sitzt das Management, das nicht einsieht, für das dritte kleine Feature zwei Monate gefühlten Stillstand zu akzeptieren, nachdem die letzten beiden kleinen Features in ein paar Stunden erledigt waren. Wer nicht kochen muss, hat kein Problem, wenn die Pfannen schimmelnd in der Spüle liegen.
Es gibt wohl kaum ein IT-Projekt ohne diese Kämpfe. Statt sich gegenseitig zu ärgern, sollten beide Seiten die Sichtweise der jeweils anderen verstehen. Wenn ein erfahrenes Entwicklungsteam unisono schreit, dass der Code auseinanderfällt, wird es einen Grund dafür geben. Wenn eine gesetzliche Anforderung zu einem bestimmten Stichtag umzusetzen ist, kann oder muss auch einmal die Codequalität hinten anstehen. Wichtig ist ein gemeinsames Verständnis und gegenseitiges Vertrauen, dass niemand grundlos Panik verbreitet. Ohne diese Grundlage sollte man sich besser eine andere WG suchen.
Aus Lügen lernen
Mit jeder kleinen oder größeren Lüge wächst die Erfahrung, welcher Kampf größer wird: die aktuelle Situation auszudiskutieren oder die spätere Peinlichkeit, die mit etwas Glück gar nicht eintritt. Genauso wächst die Erfahrung, welche Dirty Hacks zum Problem werden könnten. Trotzdem wird man immer wieder einmal falsch liegen. Man kann die Zufälle der Zukunft nicht einplanen.
Wichtiger als das grundsätzliche Vermeiden ist die Reaktion, wenn Lügen oder Hacks zum Problem werden. Je länger man es aussitzt, desto schlimmer wird es. So peinlich es ist, wenn jemand seine Lüge weiterspinnt, obwohl er längst aufgeflogen ist, so traurig ist es, wenn Software stirbt, weil der Code kein Konzept mehr hat.
(rme)
Entwicklung & Code
Microsoft leitet letzte Phase für SQL Data Sync ein
Microsoft hat die nächste Stufe bei der Einstellung von SQL Data Sync gezündet: Seit dem 9. September lassen sich in Azure-Abonnements, die den Dienst bislang nicht genutzt haben, keine neuen SQL-Data-Sync-Bereitstellungen mehr anlegen. Bestehende Nutzer können Sync-Gruppen und Mitgliedsdatenbanken dagegen noch bis zum vollständigen Aus des Dienstes am 30. September 2027 erstellen, ändern und betreiben.
Weiterlesen nach der Anzeige
Die Einstellung hatte Microsoft bereits 2024 mit dreijähriger Übergangsfrist angekündigt. SQL Data Sync gleicht ausgewählte Daten zwischen mehreren Datenbanken ab, sowohl zwischen Azure SQL Database als auch mit SQL-Server-Instanzen im eigenen Rechenzentrum. Die Daten können dabei je nach Konfiguration in beide Richtungen fließen. Microsoft beschreibt die Einstellung und die vorgesehenen Migrationspfade in seiner Dokumentation.
Keine Einschränkung für bestehende Abonnements
Die neue Einschränkung trifft ausdrücklich ausschließlich Azure-Abonnements, die SQL Data Sync zuvor nie eingesetzt haben. Für Abonnements, die SQL Data Sync bereits nutzen, ändert sich zunächst nichts: Administratoren dürfen weiterhin Sync-Gruppen anlegen und verwalten sowie Datenbanken als Mitglieder hinzufügen. Microsoft will damit verhindern, dass kurz vor dem Endtermin noch neue Abhängigkeiten von dem auslaufenden Dienst entstehen. Die Details zur nun begonnenen letzten Ausmusterungsphase nennt Microsoft im Azure-SQL-Blog.
SQL Data Sync organisiert die Replikation in Sync-Gruppen nach einem Hub-and-Spoke-Prinzip. Als Hub dient stets eine Azure SQL Database; weitere Azure-SQL-Datenbanken oder SQL-Server-Datenbanken können als Mitglieder teilnehmen. Bei lokalen SQL-Server-Datenbanken ist zusätzlich ein lokaler Sync-Agent nötig. Der Dienst kann Daten in beide Richtungen oder nur vom Hub zu einem Mitglied beziehungsweise umgekehrt übertragen.
Inventur vor der Migration
Microsoft rät betroffenen Organisationen, zunächst alle vorhandenen Bereitstellungen zu erfassen – auch inaktive Sync-Gruppen. Dazu gehören Hub- und Mitgliedsdatenbanken, gegebenenfalls installierte Sync-Agenten sowie die Anwendungen, die auf replizierte Daten angewiesen sind. In kleineren Umgebungen lassen sich die Sync-Gruppen über den Bereich „Sync to other databases“ einer Azure SQL Database im Azure-Portal prüfen. Für größere Azure-Landschaften verweist Microsoft auf die PowerShell und die Azure-SQL-Management-REST-API.
Vor der Umstellung sollten Administratoren außerdem Datenfluss, Synchronisierungsrichtung, Intervall, Datenvolumen sowie Anforderungen an Latenz und Verfügbarkeit festhalten. Das ist wichtig, weil SQL Data Sync kein einheitliches Nachfolgeprodukt erhält. Je nach bisherigem Einsatz kann die Migration eine bloße Umkonfiguration sein oder einen Umbau der Replikationsarchitektur erfordern.
Weiterlesen nach der Anzeige
Ersatz hängt vom Einsatzfall ab
Für geplante oder inkrementelle Übertragungen nennt Microsoft Azure Data Factory als Alternative. Das eignet sich etwa, wenn Daten in festen Intervallen für ein Data Warehouse oder einen Reporting-Bestand kopiert werden sollen. Für die einseitige Verteilung von SQL Server zu Azure SQL Database verweist der Konzern auf die transaktionale Replikation.
Geht es vor allem um lesende Replikate oder regionale Verfügbarkeit, kommen etwa aktive Georeplikation und Read Replicas infrage. Für Reporting-Replikate vollständiger Datenbanken nennt Microsoft Always On Availability Groups bei SQL Server auf Azure-VMs sowie Managed Instance Link bei Azure SQL Managed Instance. Daneben führt die Migrationsdokumentation Azure Functions mit Azure-SQL-Triggern für anwendungsspezifische Synchronisation sowie Mirroring in Microsoft Fabric für Analyseumgebungen auf. Welche Variante passt, hängt unter anderem von Quell- und Zielplattform, Datenrichtung, Topologie, zulässiger Verzögerung und Durchsatz ab. Die Migrationsdokumentation enthält dazu eine Übersichtstabelle, die alle Pfade nach Quell- und Zielplattform aufschlüsselt.
Nach erfolgreicher Validierung der Ersatzlösung in einer Nicht-Produktivumgebung empfiehlt Microsoft, die automatische Synchronisierung der bisherigen Gruppe vorübergehend abzuschalten. Erst wenn Anwendungen nicht mehr auf SQL Data Sync angewiesen sind, sollten Unternehmen die alten Ressourcen entfernen. Spätestens zum 30. September 2027 muss der Umstieg abgeschlossen sein.
(fo)
Entwicklung & Code
Neu in .NET 10.0 [40]: JSON Patch zum reinen Testen von Werten
Um Werte zu testen, ohne etwas zu ändern, lässt sich in .NET 10.0 JSON Patch verwenden.
Weiterlesen nach der Anzeige

Dr. Holger Schwichtenberg ist technischer Leiter des Expertennetzwerks www.IT-Visions.de, das mit 53 renommierten Experten zahlreiche mittlere und große Unternehmen durch Beratungen und Schulungen sowie bei der Softwareentwicklung unterstützt. Durch seine Auftritte auf zahlreichen nationalen und internationalen Fachkonferenzen sowie mehr als 90 Fachbücher und mehr als 1500 Fachartikel gehört Holger Schwichtenberg zu den bekanntesten Experten für .NET und Webtechniken in Deutschland.
Das folgende Beispiel zeigt die Anwendung der neuen Klasse JsonPatchDocument aus System.Text.Json Version 10.0 auf ein JSON-Patch-Dokument, dass nur aus Test-Operationen besteht:
CUI.H2("Testen mit JSON Patch-Dokument");
string jsonPatchTest = """
[
{ "op": "test", "path": "/FirstName", "value": "Dr. Holger" },
{ "op": "test", "path": "/PrivateEmail", "value": null},
{ "op": "test", "path": "/PrivateWebsite", "value": null},
{ "op": "test", "path": "/Address/ZipCode", "value": "45257" }
]
""";
// JSON Patch-Dokument laden
JsonPatchDocument? patchTestDoc = JsonSerializer.Deserialize>(jsonPatchTest);
// JSON Patch-Dokument anwenden auf das Person-Objekt
patchTestDoc!.ApplyTo(person, patchError => CUI.PrintError(patchError.ErrorMessage));
In diesem Fall gibt es keine Fehlerausgabe. Wenn man das JSON-Patch-Dokument aber verändert
CUI.H2("Reines Testen eines Objekts mit JSON Patch-Dokument (absichtlich mit drei Fehlern!)");
string jsonPatchTest = """
[
{ "op": "test", "path": "/FirstName", "value": "Dr.Holger" },
{ "op": "test", "path": "/PrivateEmail", "value": null},
{ "op": "test", "path": "/PrivateWebsite", "value": ""},
{ "op": "test", "path": "/Address/ZipCode", "value": "45251" }
]
""";
bekommt man drei Fehlermeldungen:

Drei Fehler zeigt die Ausgabe (Abb. 1).
Dabei ist die Fehlermeldung bei 'PrivateWebsite' ungünstig, denn sie unterscheidet nicht zwischen Leerstring und Null. Im Objekt steht null, getestet wird auf Leerstring. In der Fehlermeldung steht jedoch in beiden Fällen ' '.
Weiterlesen nach der Anzeige
(rme)
Entwicklung & Code
Kommentar: Wenn Transparenz mit einem Rätsel beginnt
In weniger als vier Monaten sollen die Deutschen ihren Ausweis, Führerschein und vielleicht irgendwann auch ihr Schulzeugnis und den Kaninchenzuchtstammbaum auf dem Smartphone vorzeigen können. Eine Brieftasche als App halt. Ein echter, guter Fortschritt – den die EU ja auch erzwingt. Angesichts des offensichtlichen Security-Schabernacks ist das aber auch ein Projekt, das dringend Vertrauen bei den Bürgern aufbauen muss. Der neue Name, den Bundesdigitalminister Karsten Wildberger (CDU) dafür bei einer Veranstaltung in Berlin verkündet hat, lautet: d-you.
Weiterlesen nach der Anzeige

Moritz Förster schreibt seit 2012 für die iX und heise online. Er betreut neben dem iX-Channel den Bereich Arbeitsplatz.
Stop mal – d-you. Was ist denn das? Eine Dating-App? Ein Jugendportal? Ein Motivationspodcast? Wer nicht ohnehin schon von der EUDI-Wallet gehört hat, wird daraus niemals schlau und installiert die App schon einmal gar nicht. So wird ein dämlicher Name zu einem unnötigen Problem.
Ein Name ist keine Kosmetik
Natürlich entscheidet kein Name allein darüber, ob eine Technologie bei IT-affinen Nutzern angenommen wird oder nicht. Sicherheit, Datenschutz, einfache Einrichtung und echte Anwendungsfälle zählen da mehr. Aber der Name ist der erste Berührungspunkt für den Otto-Normal-Bürger. Der kommt dann noch nicht einmal zum Download, liest den verklausulierten Datenschutzhinweis oder erkundet die tollen Funktionen in der App. Ein guter Name beantwortet schon davor und in Millisekunden die Frage: Worum geht es hier, und ist das etwas für mich?
Die Technikakzeptanzforschung weiß das seit Jahrzehnten. Fred Davis zeigte bereits 1989 in seinem Technology Acceptance Model, dass Menschen neue Technologien vor allem dann nutzen, wenn sie deren Nutzen verstehen und sie als leicht handhabbar wahrnehmen. Spätere Forschung ergänzte soziale Einflüsse und Rahmenbedingungen. Was all diese Modelle gemeinsam haben: Der erste kognitive Eindruck zählt. Und im Gegensatz dazu erzeugt ein Name, der keine Orientierung gibt, Reibung – und zwar noch bevor jemand die Funktionen der App überhaupt wahrgenommen hat.
Leer, nicht nur englisch
Weiterlesen nach der Anzeige
Die berechtigte Kritik an d-you ist keine Kulturkritik an Anglizismen. Kunstnamen können funktionieren. Apple erklärt keine Computer, O2 erklärt keinen Mobilfunk. Aber private Marken kaufen sich über Jahre Bedeutung ein: durch Werbung, durch Nutzung, durch Wiederholung. Eine staatliche Identitätsinfrastruktur startet unter anderen Bedingungen. Sie und das Technikkonzept sind für die Bürger neu. Sie berührt sensible Daten. Und sie muss von möglichst vielen Menschen verstanden und genutzt werden, damit sie sich durchsetzt. Dafür genügen nicht nur wenige Early Adopter, die sich ohnehin für digitale Verwaltung interessieren.
d-you ist dabei nicht einmal ein besonders starker Kunstname. Das „d“ könnte für Deutschland stehen, muss es aber nicht. „you“ verspricht Individualität, sagt aber nichts über die Funktion. Der Bindestrich macht die Schreibweise erklärungsbedürftig. Und die Aussprache? „Di-ju“? „Dü“? In Behördenbriefen, Suchmaschinen und mündlicher Weitergabe werden schon bald Varianten kursieren. Vor allem aber: Kein Wort im Namen verrät, dass es hier um Ausweis, Nachweise oder digitale Identität geht. d-you ist also nicht zu Englisch, sondern zu leer.
Die Metapher, die man weggeworfen hat
Mein Gegenvorschlag: schlicht „Digitale Brieftasche“ und gut ist. Das ist technisch gesehen natürlich keine perfekte Bezeichnung. Eine Brieftasche liegt in der Tasche, ist offline, gehört einem allein. Und eine staatliche Wallet ist Software, Sicherheitsarchitektur und Schnittstelle zu Behörden und Unternehmen zugleich. Die EU-Kommission beschreibt die EUDI-Wallet als Ort für digitale Identitätsdaten und attestierte Nachweise. Die Metapher hängt sich also in vielen Details auf.
Aber sie stimmt im Wesentlichen: Eine Brieftasche verwahrt persönliche Dokumente, gibt sie auf Nachfrage vor und bleibt unter der Kontrolle ihres Besitzers. Das ist genau das, was die Wallet verspricht. Die Metapher ist eben ein brauchbarer Einstieg. Und genau deshalb hätte man sie nicht durch einen Fantasienamen ersetzen müssen.
Wildberger betonte bei der Vorstellung, wie wichtig ihm Kontrolle und Transparenz für die Bürgerinnen und Bürger seien. Das ist das offensichtlich richtige Versprechen. Aber wer Datensouveränität verspricht, sollte nicht mit sprachlicher Intransparenz beginnen.
(fo)
-
Entwicklung & Codevor 1 MonatKommentar: KI-Verbote in Open-Source-Projekten können KI nicht stoppen
-
UX/UI & Webdesignvor 2 MonatenRegional & mit Gefühl: Identity für Klimafonds Baden-Württemberg › PAGE online
-
UX/UI & Webdesignvor 2 MonatenVom Scribble zur Sammelkarte: Kreativer KI-Workflow mit Adobe Photoshop, Illustrator und Firefly Boards › PAGE online
-
Datenschutz & Sicherheitvor 2 MonatenKommentar: OpenAI – KI-Sicherheit nur ein Marketing-Gag?
-
Online Marketing & SEOvor 2 MonatenGoogle Unternehmensprofil optimieren ► Anleitung & Tipps
-
Künstliche Intelligenzvor 3 Monaten
Top 10: Der beste ergonomische Bürostuhl im Test – Herman Miller vor Flexispot
-
Künstliche Intelligenzvor 3 Monaten
Top 10: Der beste Saugroboter mit Wischfunktion im Test – Testsieger Roborock
-
UX/UI & Webdesignvor 3 MonatenSchriftfamilie Mainboard: Technisch und windschnittig › PAGE online
