1 Punkte von GN⁺ 2024-06-10 | 2 Kommentare | Auf WhatsApp teilen
  • Ein Startup, das gerade erst die Monetarisierung aktiviert hatte, erlebte eine Störung bei Abo-Zahlungen; intern ließ sie sich jedoch nicht reproduzieren, sodass sich die Ursachenanalyse um 5 Tage verzögerte
  • Die Störung begann damit, dass beim Kopieren eines von ChatGPT erzeugten Prisma/TypeScript→Python/SQLAlchemy-Konvertierungsformats statt einer UUID-Erzeugungsfunktion ein hartcodierter ID-String wie ein Standardwert eingetragen wurde
  • Wegen einer Architektur mit 8 AWS-ECS-Tasks und jeweils 5 Instanzen konnten Nutzer auf einen von bis zu 40 Pools eindeutiger IDs treffen; tagsüber wurde das Problem durch häufige Deployments verdeckt
  • Nachts, als die Deployments stoppten, war die einzelne ID jedes Servers aufgebraucht; danach scheiterten neue Abo-Versuche wegen unique-ID-Kollisionen
  • Bei 50 Beschwerden pro Tag, 5 Tagen und einem Monatspreis von 40 US-Dollar wurde der Verlust auf 10.000 US-Dollar monatlichen Umsatz geschätzt; fehlende Tests, Logging und Alerts sowie kopierter Code vergrößerten die Auswirkungen

Abo-Störung direkt nach der Monetarisierung

  • Das Startup aktivierte im Mai erstmals die Monetarisierung und gewann innerhalb einer Stunde nach dem Launch den ersten Kunden
  • Am nächsten Morgen hatten sich in Gmail mehr als 40 Nutzerbeschwerden angesammelt
    • Nutzer konnten das Abo nicht abschließen
    • Sie meldeten, dass beim Drücken des Abo-Buttons ein endloser Lade-Spinner erschien
  • Das Team legte selbst ein neues Konto an und prüfte den Ablauf, konnte die Ursache intern aber nicht reproduzieren, da das Abo korrekt funktionierte
  • Während der Arbeitszeit gab es kaum Beschwerden; die Störung häufte sich vor allem über Nacht

Monetarisierung unter Zeitdruck implementiert

  • Im Mai begann der YC-S23-Batch, und das Team war sich nach dem Launch nicht sicher, welche Richtung die beste war
  • YC-Group-Partner Dalton riet, zahlende Abonnenten als Richtungsindikator zu verwenden und den gedachten Monatspreis zu verdoppeln
  • Der finale Preis wurde auf 40 US-Dollar pro Monat festgelegt
  • Das Projekt war ursprünglich ein Full-Stack-NextJS-Projekt, wurde aber rund um die Monetarisierungsarbeiten auf Python/FastAPI migriert
    • Für die Migration wurde ChatGPT genutzt
    • Auch die Stripe-Integration wurde abgeschlossen
  • In den folgenden 5 Tagen schlief das Team deutlich weniger und musste täglich 30 bis 50 Beschwerde-E-Mails bearbeiten

Von ChatGPT erzeugtes Modell-Konvertierungsformat

  • Im Zuge der Backend-Migration wurden die Datenbankmodelle von Prisma/TypeScript nach Python/SQLAlchemy übertragen
  • Die Modellkonvertierung war mühsam, und da ChatGPT sie nach Einschätzung des Teams gut erledigte, wurde es für fast die gesamte Migration eingesetzt
  • Der generierte Code wurde kopiert, eingefügt und auf Funktion geprüft; auch in Produktion wirkte er normal, daher wurde so weitergemacht
  • Zu diesem Zeitpunkt übernahm weiterhin die Next API das Einfügen in die Datenbank, während das Python-Backend die Datenbank nur las
  • Mit der Implementierung der Abo-Funktion begann Python erstmals, DB-Records einzufügen
    • Das neue SQLAlchemy-Modell wurde zwar direkt erstellt, übernahm aber das von ChatGPT erzeugte Format aus bestehenden Modellen unverändert
    • In die ID-Erzeugung aller Modelle gelangte derselbe Fehler

Die tatsächliche Ursache und warum sie tagsüber nicht sichtbar war

  • Der Kernfehler bestand darin, keinen Funktions- oder Lambda-Ausdruck zur UUID-Erzeugung zu übergeben, sondern einen einzelnen hartcodierten ID-String
  • Sobald ein Nutzer auf einer bestimmten Backend-Instanz mit dieser ID ein Abo abschloss, lösten spätere Abo-Versuche auf derselben Instanz eine Kollision eindeutiger IDs aus
  • Die Backend-Konfiguration verbarg dieses Problem noch länger
    • Auf AWS liefen 8 ECS-Tasks
    • Jeder Task führte 5 Backend-Instanzen aus
    • Nutzer konnten potenziell eine von 40 verschiedenen IDs erreichen
  • Tagsüber wurden täglich 10 bis 20 Commits direkt auf den main-Branch gepusht, und jedes Mal erfolgte ein neues Backend-Deployment
    • Bei jedem Deployment entstanden 40 neue IDs, die Kunden verwenden konnten
  • Nachts stoppten Commits und Deployments, wodurch die einzelne ID jedes Servers schnell aufgebraucht war
    • Anfangs gab es noch fast 40 Server, über die ein Abo möglich war; mit der Zeit näherte sich die Zahl fast 0

Höhe des Verlusts und spätere Maßnahmen

  • Der Verlust wurde mit 50 emails/day x 5 days x $40/month berechnet und auf 10.000 US-Dollar monatlichen Umsatz geschätzt
    • Diese Berechnung berücksichtigt nur Nutzer, die eine Beschwerde geschickt hatten
  • Um die Ursache zu finden, brauchte es 5 Tage, zahlreiche E-Mails, Hunderte Sentry-Logs, ein langes Discord-Gespräch mit einem Stripe-Engineer und die Prüfung von fünf zentralen Dateien
  • Nachdem die Ursache entdeckt worden war, stellte Adam schnell einen Fix bereit
  • Danach wurden robuste Unit- und Integrationstests, Alerts und Logging hinzugefügt
  • Der Vorfall zeigt, dass eine kleine einzelne Zeile zu großen Umsatzverlusten führen kann, wenn menschliches Versagen, unzureichende Tests, kopierter Code und direkte Pushes auf main zusammenkommen

2 Kommentare

 
znjadong 2024-06-11

Äh, von KI automatisch generierten Code muss man unbedingt reviewen — warum verwendet man den einfach unverändert?

 
GN⁺ 2024-06-10
Meinungen auf Hacker News
  • Das fehlende Monitoring hat die 10.000 Dollar gekostet. Die App hat fortlaufend und in großer Zahl Datenbank-Exceptions geworfen, aber niemand wurde benachrichtigt.
    Mit so einer Benachrichtigung wäre es keine fünftägige Untersuchung, sondern eine fünfminütige Untersuchung gewesen. Wenn sie ihr Alerting nicht behoben haben, haben sie tatsächlich gar nichts behoben.

    • Genau. In der Log-Meldung hätte gestanden, dass die ID nicht eindeutig ist, und das hätte die Debugging-Zeit erheblich verkürzt.
      Programmieren ist einfach, wenn alles gut läuft; schwierig ist der Teil, der Probleme behandelt.
    • So etwas wird immer häufiger. Unternehmen und Gründer denken nicht über Infrastruktur nach, weil sie glauben, der von ihnen gewählte Cloud-Anbieter werde schon alles wie von Zauberhand erledigen.
      Sobald zahlende Kunden da sind, braucht man jemanden mit Wissen und Erfahrung in Logging, Monitoring, Alerting, Security usw. Man darf DevOps nicht amateurhaft behandeln.
    • Keine Tests zu haben ist ebenfalls schlecht, und es ist riskant, etwas von KI Erzeugtes zu verwenden, ohne es dreifach zu prüfen.
      Aber dass es für die Datenbank kein Fehler-Logging und Alerting gibt, ist der wirklich verrückte Teil. Das ist kein 20 Jahre alter Legacy-Code, sondern ein neues Produkt, und auch kein Code aus Zeiten, in denen DB-Fehler als Datenvalidierung genutzt wurden.
    • Dass sie deployed haben und direkt schlafen gegangen sind, wirkt hier wie ein Warnsignal. Sie hätten gegen 9 Uhr morgens deployen und die Probleme während der Arbeitszeit monitoren sollen.
    • Offenbar hat ChatGPT ihnen nicht gesagt, dass Monitoring nötig ist.
  • Der Blogpost liefert einen 404, daher hier ein Web-Archive-Link:
    https://web.archive.org/web/20240610032818/https://asim.bear...
    Der Autor hat eine wichtige Ergänzung hinzugefügt: Die hier beschriebenen Praktiken seien sehr schlecht und peinlich, und man habe seitdem robuste Unit-/Integrationstests sowie Alerting/Logging ergänzt. Letztlich sei es ein menschlicher Fehler gewesen und im Rückblick eindeutig vermeidbar.
    Außerdem fügte er hinzu, dass dies in den ersten Wochen des Unternehmens unter großem Zeitdruck passiert sei und man es als lustige Geschichte über einen Bug betrachten solle, der in der Produktion auf ungewöhnliche Weise reproduzierbar war.

  • Der Fehler war sofort sichtbar. Bei allem Respekt vor dem Team: Das hat wenig mit ChatGPT zu tun, sondern eher damit, dass das Team ein Programmiermodell verwendet hat, mit dem es nicht ausreichend vertraut war.
    Selbst wenn es durch ein Code-Review gekommen wäre, hätten ihn wahrscheinlich schon Monitoring-Tools gefunden, die man in fünf Minuten einrichten kann.

    • Fairerweise glaube ich, dass ich diesen Bug nicht gesehen hätte, wenn ich nicht gezielt danach gesucht hätte. Trotzdem stimmt es, dass ihn Monitoring oder schon der grundlegendste manuelle Test sofort erwischt hätten.
    • Es sieht so aus, als hätte das Team nicht einmal grundlegendes Troubleshooting anhand von Datenbank- oder Applikationslogs hinbekommen. Das war ein simpler Fehler; ich frage mich, was passiert, wenn ein temporärer Fehler wie implizites Locking einer Tabelle auftritt.
    • Das war kein naiver Fehler, sondern der Titel ist absichtlich Clickbait und auf Suchbegriffe optimiert. Er suggeriert, ChatGPT habe einen Fehler gemacht, und erzeugt so Angst-Klicks.
      Ein Titel wie „Wir machten beim Einsatz eines LLM einen Programmierfehler und gaben wegen fehlender Qualitätssicherung 10.000 Dollar aus“ würde bei Führungskräften keine Reaktion auslösen wie: „Wenn ChatGPT etwas vermasselt, wie hoch ist dann unser Exposure?“ Es wird haufenweise mittlere und höhere Manager geben, die diesen Artikel auf LinkedIn posten.
      Ein LLM kann keine „Fehler“ machen. Es ist nicht deterministisch, kann nicht schlussfolgern, denken oder Logik ausführen. Es ist ein sehr schicker Wortsalat-Generator, der statistische Wahrscheinlichkeiten nutzt, und es gibt keine Garantie, dass seine Ausgaben richtig oder korrekt sind; daher passt der Begriff Fehler definitionsgemäß nicht.
      Update: Nachdem der Beitrag aus offensichtlichen Gründen stark downgevotet wurde, schoss sein Ranking plötzlich nach oben, was danach aussieht, als hätte ein Moderator ihn geboostet: https://hnrankings.info/40627558/
      Amüsant, dass ein Clickbait-Beitrag, dessen Titel nach den Regeln hätte geändert werden müssen, von einem Moderator geboostet wurde. Und dass der Autor offenbar zu einer Y-Combinator-Firma gehört, ist sicher reiner Zufall: https://news.ycombinator.com/item?id=40629998
    • Interessanterweise war eine weitere Instanz, die diesen Fehler gefunden hat, ChatGPT-4o. Chats mit Bildern kann man nicht teilen, aber ich habe das Bild mit dem fehlerhaften Code eingefügt und gefragt: „Was ist am Code falsch?“, worauf es Folgendes sagte:
      Für die UUID-Erzeugung des Primärschlüssels solle man nicht str(uuid.uuid4()) verwenden, sondern direkt das aufrufbare uuid.uuid4, und SQLAlchemy rufe die Funktion auf, wenn es den Wert erzeugt. Beim Datums-Default könne server_default=text("(now())") möglicherweise nicht wie erwartet funktionieren, man solle func.now() verwenden; außerdem solle man die Imports von uuid und SQLAlchemys text prüfen und für die Zeitzonenbehandlung auch DateTime(timezone=True) in Betracht ziehen.
      Anschließend schlug es als korrigierten Code id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()), unique=True, nullable=False) vor; das hinzugefügte lambda: behebt hier das Problem.
    • Wenn man kaum Python-Erfahrung hat, hätte man uuid.uuid4() vermutlich wie eine Schemadefinition in etwas wie Prisma verstanden. Daher überrascht mich dieser Bug an sich nicht, und ich hätte denselben Fehler machen können.
      Trotzdem hätte ein einziges kubectl logs das sofort ans Licht gebracht. Und außerdem: von Next.js und Prisma zu Python? Warum?
  • Der Fehler an sich ist nachvollziehbar. Er sieht so aus, als könnte man ihn auch beim Schreiben von Code ohne ChatGPT relativ leicht übersehen.
    Aber ich verstehe nicht, warum er nach dem ersten Fehlschlag nicht gefunden wurde. Hatte diese Firma kein Logging? Dass das Backend versucht, eine UUID wiederzuverwenden, hätte aus der Fehlermeldung sofort ersichtlich sein müssen.

    • Sie wussten nicht einmal, dass ein Fehler auftrat, bis sich Kunden beschwerten. Man sollte vor den Kunden wissen, welche Fehler auftreten; Logging, Alerts oder irgendeine Form von Monitoring hätten geholfen.
    • Das ist das eigentliche Problem. Bei einem Projekt, das sich schnell bewegt, ist es sehr wahrscheinlich, dass irgendwann wieder so ein Produktionsbug auftritt. Hoffentlich dauert die Identifikation beim nächsten Mal keine fünf Tage.
    • Fünf Tage, um diesen Bug zu verstehen, ist ziemlich verrückt.
    • Es ist durchaus plausibel, dass ein Spezialfall wie mehrere Stripe-Abos in normalen Unit-Tests fehlt. Wie im Artikel beschrieben, wäre er wohl auch nicht leicht als Akzeptanztest zu reproduzieren gewesen, und der Fokus auf ChatGPT ist sowohl vom Autor als auch von anderen etwas übertrieben.
      Einer Funktion, die ein Callable erwartet, versehentlich einen String statt String zu übergeben, ist ein häufiger Fehler. Ohne ORM wäre dieses konkrete Problem vermutlich vermieden worden, aber das ist vielleicht meine persönliche Voreingenommenheit gegenüber ORMs. Ähnliche Bugs können auch in Kontexten entstehen, die nichts mit Datenbanken zu tun haben.
      Leute, die großspurig behaupten, sie hätten diesen Bug mit Sicherheit gefunden, sind entweder viel bessere Engineers als ich oder, wahrscheinlicher, sie überschätzen ihre eigenen Fähigkeiten ein wenig.
      Dass es aber keine Logs gab oder niemand in die Logs geschaut hat, ist wirklich schwer nachvollziehbar. Bei ECS hätte eine Duplicate-Key-Exception ohne zusätzliche Konfiguration an CloudWatch weitergereicht werden sollen; ich frage mich, ob das nicht passiert ist oder ob es passiert ist und trotzdem niemand über Nacht nachgesehen hat, welche Exceptions aufgetreten sind.
    • Wegen solcher Prozessfehler gibt es bei Amazon die Fehlerkorrektur, also einen Postmortem-Prozess: https://aws.amazon.com/blogs/mt/why-you-should-develop-a-cor...
      In so einer Situation ist es hilfreich zu fragen, warum die Erkennung verspätet war und warum die Diagnose so lange gedauert hat.
  • Ich habe denselben Fehler schon mehrfach in von Menschen geschriebenem Code gesehen. Besonders in React / TypeScript / JavaScript kommt es häufig vor, dass jemand die Lambda-Funktion vergisst.
    Der Blogbeitrag erklärt die eigentliche Ursache des Problems nicht wirklich und springt gefühlt direkt dazu, ChatGPT die Schuld zu geben. Wenn man unter Zeitdruck arbeitet und große Änderungen oder Commits ohne Peer Review in main bringt, passiert so etwas.
    Das eigentliche Problem ist: Wenn man hetzt, Abkürzungen nimmt und nicht ausreichend testet oder Code Reviews durch Kolleg:innen macht, entstehen Fehler. Schon ein Test, der mehrere Anmeldeoptionen ausprobiert, hätte das vermutlich sofort gefunden.

    • Mein mentales Modell von ChatGPT ist ein Junior Engineer, der niemals befördert wird. Jemand, der irgendwann entlassen würde, aber dafür unendlich schnell tippen kann und daher nützlich sein kann, wenn man ihn sehr vorsichtig einsetzt.
      Wenn man so jemanden in die Nähe von finanziell kritischem Code lässt, bekommt man ähnliche Probleme, und ich würde das Urteilsvermögen der Person infrage stellen, die entschieden hat, diesen Code mit kaum Tests zu deployen.
    • Solche Probleme sind an vielen Stellen verbreitet. Zum Beispiel können Komponenten-Properties in Vue Default-Werte haben; wenn man aber statt einer Funktion, die ein Objekt oder Array zurückgibt, ein literales Objekt oder Array als Default-Wert verwendet, geht das böse aus.
      Es ist überraschend, dass es dafür keine Lint-Regel gab.
    • ChatGPT ist nur ein Ablenkungsfaktor. Entscheidend ist nicht, wodurch der Code erzeugt wurde, sondern was man mit diesem Code macht.
    • Die Struktur war also: ChatGPT schreibt den Code, pusht ihn, und danach macht ChatGPT auch noch das Review. /s
      Ich hoffe, es war nicht so.
  • Die Stelle „Das ursprüngliche Projekt war Full-Stack NextJS, aber zuerst wollte ich alles auf Python/FastAPI migrieren“ hat mir die Augen geöffnet.
    Ich weiß nicht, wie ein Startup ohne Kunden eine Neuschreibung rechtfertigt.

    • Ich dachte dasselbe und kam mir schon verrückt vor. Eine so frühe Neuschreibung ergibt für mich keinen Sinn, und ich dachte, niemand in den Kommentaren würde das ansprechen.
      Unabhängig davon, ob es Kunden gibt oder nicht: Warum macht man in einem so frühen Stadium im Grunde eine horizontale Verschiebung von Node zu Python? Wenn es Hunderte Kunden gäbe und man auf etwas wie Go wechseln wollte, könnte ich es vielleicht eher verstehen, aber selbst das wäre weiterhin fragwürdig.
    • Außerdem schrieben sie in einer Sprache neu, in der sie offenbar zu unerfahren waren, um einen ziemlich offensichtlichen Bug zu erkennen.
    • In meinem Fall könnte es bei einem echten Projekt, an dem ich gerade arbeite, daran liegen, dass C# zwar eine gute Sprache ist und auch Runtime und Web-Framework in Ordnung sind, es aber die Entwicklung verlangsamt und sich immer mehr Schmerzpunkte ansammeln.
      Zum Beispiel muss man massenhaft DTO-Objekte erstellen, aber AutoMapper funktioniert mit der von mir verwendeten Versionskombination und Projektkonfiguration nicht, und Entity Framework sowie JSON-Serialisierung/-Deserialisierung verursachen mehr Schmerz, als sie Nutzen bringen.
      Natürlich kann man das schrittweise lösen: tief in die Dokumentation einsteigen, Hacks einbauen, Pakete upgraden und die Konfiguration neu schreiben. Aber als Mensch möchte man irgendwann metaphorisch den Benzinkanister holen, alles abfackeln und das zweite System besser machen. Natürlich wird es in Wirklichkeit nicht besser, sondern bekommt nur andere Schmerzpunkte und kann möglicherweise nicht einmal alles, was das erste System konnte, oder nicht richtig.
      Auch bei der Arbeit habe ich jedes Mal denselben Impuls, wenn ich Legacy- oder umständliche Systeme sehe. Es braucht aktive, kontinuierliche Anstrengung, um das Gehirn zu überstimmen, das nach einer Neuschreibung schreit. Manchmal gehen Architekturänderungen wie eine Neuschreibung oder die Einführung von Containern gut aus, aber meistens führen sie direkt ins Feuer oder zu endloser Arbeit.
      Wenn ich nicht sehr sicher bin, dass es den Betrieb des Systems oder die Developer Experience anderer Entwickler verbessert, bin ich froh, diesem Impuls nicht nachzugeben.
    • ChatGPTs einziges Versagen in dieser Sache war, dass seine Fähigkeiten den Eindruck erweckten, eine Neuschreibung vor dem Launch sei eine vernünftige und einfache Art, Runway zu verbrauchen.
  • ChatGPT war eher der Teil, der das Geld für die App überhaupt eingebracht hat. Ohne ChatGPT hätten sie nicht die Fähigkeit gehabt, sie umzusetzen.
    Der Mangel an Fähigkeit beim Coding, Debugging, Logging und Monitoring hat die 10.000 Dollar gekostet; in dieser Geschichte ist der Nettoeffekt von ChatGPT positiv.

    • Wenn man sich die Projekte dieses Teams auf github.com/reworkd ansieht, erkennt man sofort die Reife von Produkt und Team. Emoji-getriebene Entwicklung.
      In jeder Commit-Message steckt ein Emoji. Affen, Bananen, Raketen, Feuerwerk – es gibt nichts, was nicht dabei wäre.
    • Besonders, wenn man es als Kosten von 20 Dollar pro Monat betrachtet.
    • 10.000 Dollar sind Kleingeld. Elon verliert wegen des heutigen xAI-Fehlers vielleicht 500 Milliarden Dollar.
      https://grook.ai/share?id=e269e88a7b1a71eff4f176c864b30161&x...
    • Es war wohl bereits implementiert, also hatten sie offenbar die Fähigkeit dazu.
      Es heißt, das ursprüngliche Projekt sei Full-Stack NextJS gewesen, und beim Migrieren des Backends auf Python/FastAPI hätten sie das Datenbankmodell aus Prisma/Typescript nach Python/SQLAlchemy übersetzt. Diese Arbeit sei langweilig gewesen, und weil ChatGPT darin ziemlich gut zu sein schien, hätten sie es für fast die gesamte Migration genutzt.
      Wenn es ChatGPT von Anfang an nicht gegeben hätte, hätten sie diese vorgelagerte Migration wohl nicht versucht; daher ist es schwer, den Nettoeffekt als positiv zu sehen. Der bestehende Stack hatte vielleicht besseres Error Logging, vielleicht auch nicht, und weil sie den Code selbst geschrieben hatten, kannten sie seine Struktur möglicherweise besser und brauchten es weniger.
      Die Entscheidung, „den gesamten Code ein zweites Mal neu zu schreiben“, bevor man Monetarisierung einschaltet, ist an sich schon interessant.
  • Es gibt die Formulierung: „Ich möchte zuerst sagen, dass die Praktiken hier schlecht waren und vermeidbar gewesen wären. Das geschah in einer anderen Phase mit großem Zeitdruck. Bitte lest es mit diesem Kontext.“
    Wegen solcher Rahmenbedingungen machen mir Software-Abos Angst.

    • Ich respektiere sehr, dass der Autor diese Geschichte öffentlich gemacht hat, besonders mit einer solchen Einleitung. Es ist wirklich nützlich zu wissen, welche Fehler andere machen, aber eigene Fehler öffentlich zu machen, kann ziemlich peinlich sein.
    • Selbst wenn man Abos nicht mag: Die alte Welt, in der man Lizenzen für mehrere Hundert Dollar pro Usersitz gekauft hat, war auch nicht großartig.
    • Ich habe schon mit Legacy-Abo-Code gearbeitet, und der kann ziemlich dreckig sein.
      Wegen Race Conditions haben wir Nutzer auch schon doppelt abgerechnet. Deshalb werde ich bei Timeouts oder Fehlern rund um Geld paranoid: Ich gehe erst einmal davon aus, dass die Zahlung erfolgt ist, und prüfe später noch einmal nach.
    • Die Alternative ist, es selbst zu schreiben, aber dann schränkt das alles andere ein.
    • Eine Neuschreibung unter „großem“ Zeitdruck ist ebenfalls ungewöhnlich.
  • Code in TypeScript und Python, ein Framework wie Next.js, acht AWS-Tasks mit jeweils fünf laufenden Instanzen, und dabei 40 Dollar Umsatz und nur ein paar Wochen Entwicklungszeit?
    Da fragt man sich wirklich, was da los war. Es ist schon schlimm genug, das mit Zeitdruck zu entschuldigen, weil der Code deshalb ein Chaos gewesen sei; noch schlimmer ist aber, dass dann Zeit in Refactoring über Sprachgrenzen hinweg und in den Aufbau eines grundlosen verteilten Systems gesteckt wurde.
    Das ist selbstverletzende Komplexität: gleichzeitig Features und völlig absurde technische Komplexität jonglieren. Keine Ahnung, was man sich dabei gedacht hat.
    Korrektur: Das ist ein Unternehmen aus YC Sommer 2023, aber offenbar steht das Produkt auch im Sommer 2024 noch hinter einer Warteliste. Vermutlich, weil es gerade in Rust neu geschrieben wird.

    • Weil es 500.000 Dollar Startkapital gibt, obendrauf weitere 1,2 Millionen Dollar und außerdem kostenlose AWS-Credits, die verbrannt werden wollen.
  • Ich habe wahrscheinlich insgesamt nicht einmal 1.000 Zeilen Python geschrieben, aber das Problem wurde treffend erkannt.
    Python hat den Fehler, die Auswertungsstrategie von Common Lisp nicht richtig übernommen zu haben. Wenn es bei den Default-Ausdrücken optionaler Funktionsargumente ein Argument wie foo=obj.whatever() gibt, wird obj.whatever() nicht beim Funktionsaufruf ausgewertet, sondern zu dem Zeitpunkt, an dem die Funktionsdefinition verarbeitet wird.
    Ich vermute, dass das aus Effizienzgründen absichtlich so gemacht wurde. Python hat noch einen weiteren Fehler: Es gibt keine echte Literal-Syntax für gängige Objekte wie Listen. [1, 2, 3] ist kein Literal, sondern eher ein Konstruktor; bei jeder Auswertung muss eine neue Liste erzeugt und mit Werten befüllt werden.
    Die Designer wollten wohl nicht, dass ein Parameter wie list=[] jedes Mal eine neue leere Liste erzeugt, wenn das Argument weggelassen wird. In Lisp sind '(1 2 3) und '() echte Literale und verweisen bei jeder Referenz auf dasselbe Objekt. Programmierer können wählen, ob sie als Default-Ausdruck (list 1 2 3) oder '(1 2 3) verwenden.
    Ersteres erzeugt wie [1, 2, 3] jedes Mal ein neues veränderbares Objekt, Letzteres gibt mit ziemlicher Sicherheit dasselbe Objekt zurück und lässt sich zuverlässig und portabel nicht verändern. Moderne populäre Sprachen haben die meisten Funktionen von Lisp übernommen; das wirkt wie ein Witz nach dem Motto, man habe dabei nichts zu verlieren.

    • Inhaltlich stimmt das zwar, aber genau das ist in dem Blogbeitrag nicht passiert. Das Problem lag nicht in einer Funktionsdefinition, sondern innerhalb einer Klassendefinition.
    • Die Aussage, dass bei foo=obj.whatever() obj.whatever() nicht beim Funktionsaufruf, sondern bei der Verarbeitung der Funktionsdefinition ausgewertet wird, kann so kaum stimmen.
      Ich weiß nicht, was passieren soll, wenn .whatever() von internem Zustand abhängt, der sich nach der Objektinitialisierung ändert.