Function as a Service

So finden Sie die richtige Serverless-Plattform

17.03.2021
Von 
Martin Heller schreibt als freier Autor für die Schwesterpublikation InfoWorld.
Es gibt mindestens ein Dutzend Function-as-a-Service-Angebote, angefangen von AWS Lambda und Azure Functions bis hin zu Knative und OpenFaaS. So finden Sie die passende Lösung.
Mit Serverless Computing zahlt man nur noch die Rechen- und Speicherressourcen, die man nutzt und wenn man sie nutzt.
Mit Serverless Computing zahlt man nur noch die Rechen- und Speicherressourcen, die man nutzt und wenn man sie nutzt.
Foto: wacomka - shutterstock.com

Rund um die Uhr mit voller Kapazität eine Serverfarm in der Cloud zu betreiben, kann furchtbar teuer werden. Doch was wäre, wenn Sie den Großteil der Kapazität abschalten könnten, wenn sie nicht benötigt wird? Oder Ihre Server nur bei Bedarf hochfahren und lediglich so viel Kapazität bereitstellen, wie für die jeweilige Last erforderlich ist?

Mit Serverless Computing ist all das möglich. Serverless Computing ist ein Betriebsmodell für die Cloud, in dem der Provider dem Benutzer dynamisch nur die Rechen- und Speicherressourcen zuweist - und in Rechnung stellt, die für die Ausführung eines bestimmten Codes erforderlich sind. Oder anders ausgedrückt: Serverless Computing ist ein bedarfsgesteuertes Backend-Computing, das nach dem Prinzip "Pay-as-you-go" funktioniert. Wenn eine Anfrage bei einem Serverless-Endpunkt eingeht, verwendet das Backend entweder einen vorhandenen, "noch warmen" Endpunkt wieder, der bereits den richtigen Code enthält, weist ihm eine Ressource aus einem Pool zu und passt diese an, oder instanziiert und passt einen neuen Endpunkt an. Die Infrastruktur des Providers lässt dazu in der Regel so viele Instanzen laufen, wie für die Bearbeitung der eingehenden Anfragen erforderlich sind, und gibt ungenutzte Instanzen nach einer Abkühlphase wieder frei.

Die Bezeichung "Serverless" ist natürlich nicht korrekt. Auch in Serverless-Szenarien werden Server verwendet, allerdings muss der Nutzer diese nicht managen. Der Container oder andere Ressourcen, auf denen der Serverless-Code ausgeführt wird, läuft typischerweise in einer Cloud, kann aber auch im Edge laufen.

Function as a service (FaaS) kann sich auf viele Serverless-Architekturen beziehen. Grundsätzlich gilt dabei, dass der Anwender den Code für eine Funktion schreibt - und die Infrastruktur kümmert sich um den Rest: Sie stellt die Laufzeitumgebung bereit, übernimmt das Laden und Ausführen des Codes und steuert den Lebenszyklus der Umgebung. Ein FaaS-Modul kann dabei mit Webhooks, HTTP-Anfragen, Streams, Storage Buckets, Datenbanken und anderen Bausteinen integriert werden, um eine serverlose Anwendung zu erstellen.

Serverless Computing - die Fallstricke

So attraktiv Serverless Computing sein kann - und tatsächlich haben Unternehmen ihre Cloud-Ausgaben mit dem Umstieg auf Serverless um über 60 Prozent gesenkt, es gibt einige potenzielle Probleme, mit denen Sie sich auseinandersetzen müssen.

  • Das häufigste Problem sind sogenannte Kaltstarts: Sind keine "heißen" Endpunkte verfügbar, wenn eine Anfrage eingeht, muss die Infrastruktur einen neuen Container instanziieren und ihn mit Ihrem Code initialisieren. Die Instanziierung kann mehrere Sekunden dauern, was eine sehr lange Zeit für einen Dienst ist, der im einstelligen Millisekundenbereich reagieren soll. Die Verzögerung kann sogar noch größer sein, wenn Sie eine Architektur haben, in der viele Serverless-Dienste verknüpft sind, und alle einen Kaltstart machen müssen. Es gibt mehrere Möglichkeiten, Kaltstarts zu vermeiden. Eine davon ist, sie mit Pings aktiv zu halten, obwohl das natürlich die genutzte Laufzeit und damit die Kosten erhöht. Eine andere ist, eine einfachere Architektur als Container in der Serverless-Infrastruktur zu verwenden. Eine dritte Taktik besteht darin, den Prozess bereits zu starten, wenn eine Client-Anfrage ihren Security-Handshake mit dem Endpunkt beginnt, anstatt zu warten, bis die Verbindung vollständig aufgebaut ist. Außerdem kann man natürlich einen Container immer "warm" halten und damit bereit, die Skalierungskonfiguration der Cloud zu durchlaufen.

  • Ein zweites Problem rund um Serverless Computing ist eine mögliche Drosselung: Um die Kosten zu deckeln, haben viele Dienste die maximale Anzahl der nutzbaren Serverless-Instanzen limitiert. In Zeiten mit viel Traffic kann die Anzahl der Instanzen an ihr Limit stoßen, und die Reaktionen auf zusätzliche eingehende Requests können sich verzögern oder sogar fehlschlagen. Die Drosselung kann aber durch eine sorgfältige Abstimmung des Limits behoben werden. Damit ist es möglich, legitime Nutzungsspitzen abzudecken, ohne ein Ausufern der Nutzung durch einen Denial-of-Service-Angriff oder einen Fehler in einem anderen Teil des Systems zu ermöglichen.

  • Ein drittes Problem bei der Serverless-Architektur ist, dass der Storage Layer möglicherweise nicht in der Lage ist, Traffic-Spitzen zu bewältigen. Damit stauen sich die laufenden Serverless-Prozesse auf, obwohl genügend Instanzen verfügbar sind. Eine Lösung für dieses Problem ist die Verwendung von speicherresidenten Caches oder Queues, die die Daten im Fall eines Peaks aufnehmen und dann so schnell an die Datenbank weiterleiten können, wie diese die Daten auf die Festplatte übertragen kann.

Nicht vorhandene Monitoring- und Debugging-Tools können zu all diesen Problemen beitragen und ihre Diagnose erschweren. Ach so: Falls Sie den Punkt Vendor Lock-in in der Liste vermissen - das ist eher ein Kompromiss als ein echtes Problem.

AWS Lambda und verwandte Dienste

AWS Lambda ist ein FaaS-Angebot von AWS, aber beileibe nicht das einzige. Insgesamt gibt es derzeit mehr als ein Dutzend Serverless-Produkte im AWS-Katalog. Auch die Annahme, dass der 2014 gestartete Dienst der erste FaaS-Service war, ist falsch. Ihm gingen Zimki (2006), Google App Engine (2008) und PiCloud (2010) voraus.

AWS Lambda unterstützt zustandslosen (Stateless) Funktionscode, der in Python, Node.js, Ruby, Java, C#, PowerShell oder Go geschrieben wurde. Die Lambda-Funktionen werden dabei als Reaktion auf Ereignisse ausgeführt, etwa Objekt-Uploads in Amazon S3, Amazon SNS-Benachrichtigungen oder API-Aktionen. Lambda-Funktionen erhalten automatisch ein temporäres 500 MB großes Scratch-Verzeichnis und können Amazon S3, Amazon DynamoDB oder einen anderen im Internet verfügbaren Speicherdienst für einen dauerhaften Zustand verwenden. Eine Lambda-Funktion kann Prozesse mit jeder von Amazon Linux unterstützten Sprache starten und Bibliotheken aufrufen. Eine Lambda-Funktion kann in jeder AWS-Region ausgeführt werden.

Neben AWS Lambda sind auch einige der anderen AWS Serverless-Produkte erwähnenswert:

  • So können Sie mit Lambda@Edge Lambda-Funktionen an mehr als 200 AWS-Edge-Standorten als Reaktion auf Content-Delivery-Network-Ereignisse in Amazon CloudFront ausführen.

  • Amazon DynamoDB ist ein schneller und flexibler Key-Value- und Dokumentendatenbank-Service mit konsistenten Latenzzeiten im einstelligen Millisekundenbereich.

  • Amazon Kinesis ist eine Plattform für Streaming-Daten auf AWS.

  • Mit AWS Greengrass können Sie auch Lambda-Funktionen auf lokalen, verbundenen Geräten (z. B. Steuerungen für IoT) ausführen.

  • Mit dem als Open Source verfügbaren AWS Serverless Application Model (AWS SAM) können Sie Ihre serverlosen Anwendungen und Services modellieren und bereitstellen. Zusätzlich zu SAM unterstützt AWS Lambda acht weitere Open-Source- und Drittanbieter-Frameworks.

  • Mit dem AWS Serverless Application Repository können Sie serverlose Anwendungen und Anwendungskomponenten für eine Vielzahl von Anwendungsfällen finden und wiederverwenden.

  • Sie können außerdem Amazon CloudWatch verwenden, um Ihre serverlosen Anwendungen zu überwachen, und AWS X-Ray, um sie zu analysieren und zu debuggen.

  • Schließlich kündigte AWS Lambda kürzlich eine Vorschau von Lambda Extensions an, einer neuen Möglichkeit zur einfachen Integration von Lambda mit Tools für Überwachung, Beobachtbarkeit, Sicherheit und Governance.

Microsoft Azure Functions

Microsoft Azure Functions ist eine Event-gesteuerte Serverless-Compute-Plattform, die auch komplexe Orchestrierungsprobleme lösen kann. Sie können Azure Functions ohne zusätzliche Einrichtung lokal erstellen und debuggen, in der Cloud bereitstellen und skaliert betreiben sowie Dienste mithilfe von Triggern und Bindungen integrieren. Die Programmierung ist dabei in C#, F#, Java, JavaScript (Node.js), PowerShell oder Python möglich. Jede einzelne Azure-Functions-App kann allerdings nur eine der oben genannten Sprachen verwenden. Sie können Azure Functions lokal in Visual Studio, Visual Studio Code, IntelliJ, Eclipse und den Azure Functions Core Tools entwickeln. Kleine Azure Functions lassen sich optional direkt im Azure-Portal bearbeiten.

Durable Functions ist eine Erweiterung von Azure Functions, mit der Sie zustandsabhängige Funktionen in einer Serverless-Compute-Umgebung schreiben können. Mit der Erweiterung können Sie zustandsbehaftete Workflows definieren, indem Sie Orchestrator-Funktionen schreiben, und Stateful Entitites, indem Sie Entitätsfunktionen unter Verwendung des Azure Functions-Programmiermodells schreiben. Trigger sind die Auslöser für die Ausführung einer Funktion. Ein Trigger definiert, wie eine Funktion aufgerufen wird, und eine Funktion darf genau einen Trigger haben. Den Triggern werden dabei Daten zugeordnet, oft werden sie als Nutzlast der Funktion bereitgestellt.

Die Bindung an eine Funktion ist eine Möglichkeit, eine andere Ressource deklarativ mit der Funktion zu verknüpfen. Dabei können Bindungen als Eingabebindungen, Ausgabebindungen oder beides verbunden sein. Daten aus Bindungen werden der Funktion als Parameter zur Verfügung gestellt.

Google Cloud Functions

Google Cloud Functions ist eine skalierbare Pay-as-you-go FaaS-Plattform. Sie verfügt über integrierte Monitoring-, Protokollierungs- und Debugging-Funktionen, integrierte Sicherheit auf Rollen- und Funktionsebene sowie wichtige Netzwerkfunktionen für Hybrid-Cloud- und Multicloud-Szenarien. Sie können sich mit ihr zudem über Trigger mit Google Cloud oder Cloud-Diensten von Drittanbietern verbinden, um anspruchsvolle Orchestrierungsprobleme zu optimieren.

Google Cloud Functions unterstützt Code in Go, Java, Node.js und Python. HTTP-Requests werden mit gängigen HTTP-Anforderungsmethoden wie GET, PUT, POST, DELETE und OPTIONS sowie über Hintergrundfunktionen zur Verarbeitung von Ereignissen aus Ihrer Cloud-Infrastruktur. Sie können Cloud Build oder eine andere CI/CD-Plattform für das automatische Testen und Bereitstellen von Cloud-Funktionen verwenden, in Verbindung mit einem Quellcode-Repository wie GitHub, Bitbucket oder Cloud Source Repositories. Außerdem ist es möglich, Cloud-Funktionen auch von Ihrem lokalen Rechner aus zu entwickeln und bereitzustellen.

IBM Cloud Functions

IBM Cloud Functions basiert auf Apache OpenWhisk und ist eine polyglotte "Functions-as-a-Service"-Programmierplattform für die Entwicklung von leichtgewichtigem Code, der auf Bedarf ausgeführt und skaliert wird. Sie können IBM Cloud Functions in Node.js, Python, Swift und PHP entwickeln.

IBM wirbt außerdem mit der Integration von Cloud Functions und Watson-APIs innerhalb des Event-Trigger-Action-Workflows, um die kognitive Analyse von Anwendungsdaten zum Bestandteil Ihrer Serverless-Workflows zu machen.

Oracle Cloud Functions und das Fn-Projekt

Oracle Cloud Functions ist eine Serverless-Plattform, mit der Entwickler Anwendungen erstellen, ausführen und skalieren können, ohne eine Infrastruktur zu verwalten. Die Funktionen lassen sich in die Oracle-Cloud-Infrastruktur, Plattformdienste und SaaS-Anwendungen integrieren.

Da Oracle Cloud Functions auf dem Open-Source-Projekt Fn basiert, können Entwickler außerdem Anwendungen erstellen, die auf andere Cloud- und On-Premises-Umgebungen portiert werden können. Oracle Cloud Functions unterstützen Code in Python, Go, Java, Ruby und Node.js.

Cloudflare Workers

Cloudflare ist ein Edge-Netzwerk, das vor allem für den Schutz von Websites vor DDoS-Angriffen (Distributed Denial of Service) bekannt ist. Mit Cloudflare Workers können Sie serverlosen Code im globalen Edge-Netzwerk von Cloudflare bereitstellen. Dort läuft er in Chrome-V8-Isolaten, die einen viel geringeren Overhead als Container oder virtuelle Maschinen haben. Sie können Cloudflare Workers in JavaScript, Rust, C, C++, Python oder Kotlin schreiben.

Cloudflare Workers leidet nicht so sehr unter Kaltstartproblemen wie die meisten anderen Serverless-Frameworks, da sich V8-Isolate in weniger als fünf Millisekunden "aufwärmen" können. Darüber hinaus beginnt Cloudflare bereits beim ersten TLS-Handshake mit dem Laden eines Workers. Das bedeutet in der Regel, dass der effektive Kaltstart-Overhead vollständig verschwindet, da die Ladezeit in den meisten Fällen geringer ist als die Latenz der Website.

Serverless Framework

Serverless Framework ist eine Möglichkeit, das Vendor Lock-in bei Functions-as-a-Service zumindest teilweise zu vermeiden, indem der Funktionscode lokal generiert wird. Unter der Haube stellt die Befehlszeile für das Serverless Framework Ihren Code dann auf einer FaaS-Plattform wie AWS Lambda, Microsoft Azure Functions, Google Cloud Functions, Apache OpenWhisk oder Cloudflare Workers bereit. Auch die Nutzung einer Kubernetes-basierten Lösung wie Kubeless oder Knative ist möglich. Sie können auch lokal testen. Andererseits sind viele der Serverless-Framework-Servicevorlagen spezifisch für einen bestimmten Cloud-Anbieter und eine bestimmte Sprache, wie zum Beispiel AWS Lambda und Node.js.

Serverless Components sind um übergeordnete Anwendungsfälle herum aufgebaut, wie beispielsweise eine Website, ein Blog, ein Zahlungssystem oder ein Bilddienst. Ein Plug-in ist benutzerdefinierter JavaScript-Code, der neue Befehle erstellt oder bestehende Befehle innerhalb des Serverless Frameworks erweitert.

Serverless Framework Open Source unterstützt Code in Node.js, Python, Java, Go, C#, Ruby, Swift, Kotlin, PHP, Scala und mehr. Serverless Framework Pro bietet die Tools, die Sie für die Verwaltung des gesamten Lebenszyklus von Serverless-Anwendungen benötigen, einschließlich CI/CD, Überwachung und Fehlerbehebung.

Apache OpenWhisk

OpenWhisk ist eine Open-Source-Plattform für Serverless-Funktionen zum Erstellen von Cloud-Anwendungen. OpenWhisk bietet dazu ein umfangreiches Programmiermodell zur Schaffung von Serverless-APIs aus Funktionen, zum Zusammenstellen von Funktionen zu Serverless-Workflows und zum Verbinden von Ereignissen mit Funktionen mithilfe von Regeln und Auslösern.

Sie können einen OpenWhisk-Stack lokal ausführen oder in einem Kubernetes-Cluster bereitstellen´- entweder einem eigenen oder einem verwalteten Kubernetes-Cluster eines öffentlichen Cloud-Anbieters. Darüber hinaus gibt es auch Cloud-Anbieter, die OpenWhisk vollständig unterstützen, beispielsweise IBM Cloud. OpenWhisk unterstützt derzeit Code, der in Ballerina, Go, Java, JavaScript, PHP, Python, Ruby, Rust, Swift und .NET Core geschrieben wurde. Sie können auch Ihren eigenen Docker-Container bereitstellen.

Das OpenWhisk-Projekt umfasst eine Reihe von Entwickler-Tools. Dazu gehören:

  • die wsk-Kommandozeile zum einfachen Erstellen, Ausführen und Verwalten von OpenWhisk-Entitäten,

  • wskdeploy zum Bereitstellen und Verwalten all Ihrer OpenWhisk-Pakete, -Aktionen, -Trigger, -Regeln und -APIs über einen einzigen Befehl unter Verwendung eines Anwendungsmanifests,

  • die OpenWhisk-REST-API und

  • OpenWhisk-API-Clients in JavaScript und Go.

Fission

Fission ist ein quelloffenes Serverless-Framework für Kubernetes mit dem Fokus auf die Produktivität der Entwickler und hohe Leistung. Fission arbeitet nur mit dem Code, das heißt, Docker und Kubernetes werden im normalen Betrieb abstrahiert. Sie können aber beide nutzen, um Fission zu erweitern, falls das gewünscht ist. Fission ist auf jede Sprache erweiterbar. Der Kern ist in Go geschrieben, und sprachspezifische Teile sind in so genannten Umgebungen isoliert. Fission unterstützt derzeit Funktionen in Node.js, Python, Ruby, Go, PHP und Bash sowie jede beliebige ausführbare Linux-Datei.

Um Verzögerungen durch einen "Kaltstart" zu vermeiden, verwaltet Fission einen Pool von "warmen" Containern, die jeweils einen kleinen dynamischen Lader enthalten. Wenn eine Funktion zum ersten Mal aufgerufen, d. h. "kalt gestartet" wird, wird ein laufender Container ausgewählt und die Funktion geladen. Dieser Pool ist es, der Fission schnell macht. Die Latenzzeit beim Kaltstart beträgt typischerweise etwa 100 Millisekunden.

Knative

Knative, das von Google mit Beiträgen von mehr als 50 verschiedenen Unternehmen entwickelt wurde, bietet einen grundlegenden Satz von Komponenten zum Erstellen und Ausführen von Serverless-Anwendungen auf Kubernetes. Die Komponenten konzentrieren sich dabei auf die Lösung alltäglicher, aber schwieriger Aufgaben wie das Deployment eines Containers, das Routing und die Verwaltung des Datenverkehrs mit Blue/Green-Deployment, die automatische Skalierung und Größenanpassung von Workloads je nach Bedarf sowie die Bindung laufender Dienste an Eventing-Ökosysteme. Googles Cloud-Run-Service ist auf Knative aufgebaut.

Kubeless

Kubeless ist ein quelloffenes, Kubernetes-natives Serverless-Framework, das für das Deployment auf einem Kubernetes-Cluster entwickelt wurde und die Vorteile der Kubernetes-Primitive nutzt. Kubeless reproduziert einen Großteil der Funktionalität von AWS Lambda, Microsoft Azure Functions und Google Cloud Functions. Sie können Kubeless-Funktionen in Python, Node.js, Ruby, PHP, Golang, .NET und Ballerina schreiben. Die Event-Trigger von Kubeless wiederum verwenden das Kafka-Nachrichtensystem und HTTP-Ereignisse.

Um Funktionen als benutzerdefinierte Kubernetes-Ressourcen erstellen zu können, kommt bei Kubeless eine Kubernetes Custom Resource Definition zum Einsatz. Es führt dann einen In-Cluster-Controller aus, der diese benutzerdefinierten Ressourcen überwacht und bei Bedarf Laufzeiten startet. Der Controller injiziert den Code Ihrer Funktionen dynamisch in die Runtimes und stellt sie über HTTP oder über einen Publish/Subscribe-Mechanismus zur Verfügung.

OpenFaaS

OpenFaaS ist ein Open-Source-basiertes Serverless-Framework für Kubernetes, das nicht zu Unrecht den Slogan "Serverless functions made simple" trägt. OpenFaaS ist Teil des "PLONK"-Stack von Cloud-native Technologies: Prometheus (Monitoring system und Zeitreihen-Datenbank), Linkerd (Service-Mesh), OpenFaaS, NATS (Secure Messaging und Streaming) und Kubernetes. Sie können OpenFaaS verwenden, um ereignisgesteuerte Funktionen und Microservices in Kubernetes zu implementieren, indem Sie dessen Template Store oder eine Docker-Datei verwenden.

Serverless-Plattformen - Auswahlkriterien

Um angesichts der großen Auswahl an Lösungen die geeignetste Serverless-Plattform finden, sollten Sie zunächst einmal Ihren vorhandenen Softwarebestand und Ihre Ziele bewerten. Ein Unternehmen, das mit in Cobol geschriebenen Legacy-Anwendungen beginnt, die auf hauseigenen Mainframes laufen, hat einen ganz anderen Weg vor sich als ein Unternehmen, das über eine umfangreiche Cloud-Software verfügt.

Für Unternehmen mit einer Cloud-Installation wiederum lohnt es sich, eine Liste der Implementierungen, der verwendeten Clouds und der Verfügbarkeitszonen zu erstellen. Außerdem ist es von Vorteil, wenn man weiß, von wo aus Kunden und Anwender auf die Dienste zugreifen und welche Nutzungsmuster es gibt. Beispielsweise ist eine rund um die Uhr mit gleichbleibender Auslastung genutzte Anwendung wahrscheinlich kein guter Kandidat für ein Serverless Deployment: Ein richtig dimensionierter Server, eine VM oder ein Cluster von Containern ist möglicherweise kostengünstiger und einfacher zu verwalten.

Andererseits könnte eine Anwendung, die in unregelmäßigen Abständen und in sehr unterschiedlichem Umfang genutzt wird und durch eine wichtige Aktion ausgelöst wird (z. B. das Einchecken von Quellcode), ein perfekter Kandidat für eine Serverless-Architektur sein. Ähnliches gilt für einen weltweit genutzten Service, der eine sehr niedrige Latenzzeit benötigt.

Ein Unternehmen, das Erfahrung mit Kubernetes hat, könnte eine der Open-Source-Serverless-Plattformen in Betracht ziehen, die auf Kubernetes bereitgestellt werden. Fehlt die Kubernetes-Erfahrung, ist man möglicherweise besser damit bedient, wenn eine native Cloud-FaaS-Infrastruktur bereitgestellt wird - unabhängig davon, ob es sich um ein Open-Source-Framework wie das Serverless Framework oder ein proprietäres Framework wie AWS Lambda, Google Cloud Functions oder Azure Functions handelt.

Wenn die Serverless-Anwendung, die Sie erstellen, von einer Cloud-Datenbank oder einem Streaming-Dienst abhängt, sollten Sie außerdem in Erwägung ziehen, diese in der gleichen Cloud bereitzustellen, um die Latenzen innerhalb der Anwendung zu minimieren. Das schränkt die Wahl des Frameworks weniger stark ein, als Sie vielleicht denken: Zum Beispiel kann eine Anwendung, die einen Google Cloud Bigtable-Datenspeicher hat, ihre Serverless-Komponente in Google Cloud Functions, Google Cloud Run, Serverless Framework, OpenWhisk, Kubeless, OpenFaaS, Fission oder Knative haben und trotzdem wahrscheinlich eine minimale Latenz aufweisen.

In vielen Fällen wird Ihre Anwendung die gleiche oder eine ähnliche sein wie die gängigen Anwendungsfälle. Haben Sie einige Serverless-Plattformen in die engere Auswahl gezogen, kann es sich daher lohnen, bestehende Beispiele und Bibliotheken zu prüfen. Gut möglich, dass es bereits eine Referenzarchitektur gibt, die die Aufgabe für Sie erfüllt.

Es ist auch nicht so, dass für die meisten FaaS-Szenarien eine Menge Code geschrieben werden muss: Vielmehr profitiert man durch die Wiederverwendung von FaaS-Code von gut getesteten, bewährten Architekturen und vermeidet die Notwendigkeit, viel Debugging betreiben zu müssen.(mb)

Dieser Artikel basiert auf einem Beitrag unserer US-Schwesterpublikation Infoworld.