77 Punkte von GN⁺ 2024-11-18 | 9 Kommentare | Auf WhatsApp teilen
  • Dieser Text ist kein Ratschlag, sondern beschreibt die Entwicklungsgewohnheiten, die der Autor derzeit anwendet
  • Es ist eine Zusammenstellung von Erfahrungen beim Versuch, schlechte Gewohnheiten zu vermeiden und gute aufzubauen, und behandelt 10 Gewohnheiten, die zur Steigerung der Produktivität und zur Sicherung der Qualität geholfen haben

1. Kleine Commits beibehalten

  • Commits sollten so klein wie möglich gehalten werden. Kleine Commits ermöglichen es, bei Bugs nur den betroffenen Commit zurückzusetzen und so komplexe Merge-Konflikte zu vermeiden
  • Als Regel gilt: "Man sollte committen können, wenn die Software kompiliert."

2. Kontinuierliches Refactoring

  • Rat von Kent Beck: "Wenn du Veränderung willst, mache die Veränderung zuerst einfach und mache dann die einfache Veränderung."
  • Mindestens die Hälfte der Commits sollte Refactoring enthalten. Kleine Refactorings helfen enorm, wenn große Anforderungen hereinkommen
  • Große Refactorings sollte man vermeiden. Stattdessen kontinuierlich kleine Verbesserungen durchführen, die in weniger als 10 Minuten erledigt sind

3. Die Bedeutung des Deployments von Code

  • Code selbst ist potenzielle Schuld, und nicht deployter Code ist die größte Schuld
  • Tests geben Vertrauen, aber ein tatsächliches Deployment bedeutet die echte Freigabe
  • Mit steigender Deployment-Frequenz können die Hosting-Kosten steigen, aber zu überprüfen, dass die neueste Arbeit in der Praxis wirklich funktioniert, ist ein wichtiger Vorteil

4. Keine Framework-Funktionen testen

  • Die Funktionen des Frameworks werden nicht getestet. Das Framework ist bereits ausreichend validiert
  • Wenn Komponenten klein bleiben, übernimmt das Framework den Großteil der Arbeit, wodurch weniger Tests nötig sind
  • Große Komponenten erhöhen die Komplexität und erfordern entsprechend viele Tests

5. Neue Module erstellen

  • Wenn eine bestimmte Funktion nicht in ein bestehendes Modul passt, ist es besser, ein neues Modul zu erstellen
  • Es ist besser, es als unabhängiges Modul zu belassen, als die Funktion gewaltsam in ein bestehendes Modul einzubauen

6. Flexible Anwendung von Test-Driven Development (TDD)

  • Wenn das API-Design noch nicht klar ist, werden zuerst Tests geschrieben, um aus Sicht des "Kunden" zu denken
  • TDD wird nicht als religiöses Prinzip befolgt. Falls nötig, kann erst in größeren Einheiten gearbeitet und danach getestet werden
  • Es ist nicht nötig, kleine Codeeinheiten absichtlich in einen Fehlerzustand zu bringen, und man sollte sich nicht an Dogmatismus binden, der die Produktivität beeinträchtigt

7. Copy-Paste nur einmal erlaubt

  • Einmaliges Kopieren ist in Ordnung, aber ab dem zweiten Kopieren entsteht Duplikation
  • An diesem Punkt sollte die Duplikation durch eine passende Abstraktion entfernt werden. Auch wenn die Parametrisierung etwas seltsam aussieht, ist sie besser, als mehrere Implementierungen zusammenzulegen

8. Veränderungen im Design akzeptieren

  • Design altert mit der Zeit. Refactoring kann das Altern verlangsamen, aber letztlich lässt sich Veränderung nicht vermeiden
  • Man sollte nicht zu sehr an früheren Designs festhalten, sondern Veränderungen akzeptieren
  • Perfektes Design gibt es nicht, und die Fähigkeit, gut mit Veränderungen umzugehen, ist der Kern der Softwareentwicklung

9. Drei Arten von Technical Debt

  • Technical Debt lässt sich in drei Arten einteilen:
    1. Dinge, die die aktuelle Arbeit behindern
    2. Dinge, die künftige Arbeit behindern könnten
    3. Dinge, die vielleicht irgendwann behindern könnten
  • Die erste Art von Schuld sollte minimiert werden, auf die zweite sollte man sich konzentrieren, und die dritte sollte ignoriert werden

10. Der Zusammenhang zwischen Testbarkeit und gutem Design

  • Wenn etwas schwer zu testen ist, gibt es wahrscheinlich ein Problem im Design
  • Auch das Testdesign kann verbessert werden. Wenn es zum Beispiel schwerfällt, einen Mock für em.getRepository(User).findOneOrFail({id}) zu schreiben, ist es sinnvoll, ihn in eine separate Funktion auszulagern oder Test-Utilities zu verwenden
  • Der Grund, warum Tests nicht geschrieben werden, ist oft, dass sie schwer zu schreiben sind, und das kann ein Designproblem sein

9 Kommentare

 
yangeok 2024-11-25

Es scheint, dass eher SRP als DRY erreicht werden sollte, damit selbst dann, wenn man es der AI überlässt, kein Unsinn herauskommt.

 
progdesigner 2024-11-21

Ich denke, am wichtigsten ist, wie gut man Code und Umgebung so gestaltet hat, dass sie sich schnell an Veränderungen anpassen können.

Außerdem kann man durch angemessene Abstraktion die Wiederverwendbarkeit und Erweiterbarkeit des Codes erhöhen und mithilfe von AI-Tools die Entwicklungsgeschwindigkeit maximieren.

 
pcj9024 2024-11-20

Das ist wirklich ein sehr guter Artikel. Den würde ich gern überall weiterempfehlen.

 
tsboard 2024-11-20

Veränderungen annehmen, Copy-and-Paste nur einmal, Tests besser machen, Commits kleiner halten ...!

 
aer0700 2024-11-19

Ein guter Artikel.

 
puersum 2024-11-19

Ich denke, bei diesem Artikel lohnt es sich wirklich, unbedingt das Original zu lesen.
Wenn es Nachrichten sind, die mich interessieren, schaue ich mir ohnehin oft die Originalquelle an, aber hier gilt das ganz besonders. Bei Punkt 1 steht im Originaltext:
Keep commits small enough that you wonder if you're taking this "keep commits small" thing a little too far. Das wurde dann zu „Commits möglichst klein halten“ zusammengefasst..

 
ilbanin00 2024-11-19

Das ist wirklich ein sehr guter Artikel.

 
joon14 2024-11-19

Punkt 7 ist wirklich ein sehr guter Inhalt.

 
GN⁺ 2024-11-18
Hacker-News-Kommentar
  • Es ist gut, Parameter zu verwenden, um mehrere Implementierungen zu vermeiden. Parameter zu verbessern ist einfacher, als mehrere Implementierungen zusammenzuführen.

    • Wenn sich „seltsame Parameter“ nicht vermeiden lassen, ist es besser, den Code aufzuteilen. Boolesche Flags und mehrere Enum-Parameter sollte man vermeiden.
    • Komplexe Funktionssignaturen erschweren die Wartung.
  • Code zu kopieren ist einmal in Ordnung, aber ab dem zweiten Mal sollte man Duplikate vermeiden. Gute Abstraktionen sollte man schaffen, wenn genügend Datenpunkte vorhanden sind.

    • Auch wenn Code anfangs gleich aussieht, sollte man sich darauf konzentrieren, ob er sich bei nötigen Änderungen gemeinsam verändern muss.
    • Das Ziel ist nicht, Codeduplizierung zu vermeiden, sondern Code, der sich gemeinsam weiterentwickeln muss, auch gemeinsam zu pflegen.
  • DRY (Don’t Repeat Yourself) oder WET (Write Everything Twice) sind keine absoluten Regeln. Zu verstehen, wann Code dupliziert und wann er zusammengeführt werden sollte, ist die schwierige Frage.

  • Als Alternative zu kleinen Commits kann man statt eines Reverts für einen großen Commit einen neuen Commit hinzufügen, der den Bug behebt.

    • Es ist nicht klar, warum große Refactorings per se schlecht sein sollen.
    • Eine unabhängige Struktur zu schaffen ist besser, als etwas mit Gewalt in ein bestehendes Modul zu pressen.
    • Beim API-Design kann man statt Unit-Tests auch Design-Sessions durchführen.
  • Testbarkeit hängt mit gutem Design zusammen. Was sich nicht leicht testen lässt, kann ein Signal dafür sein, dass das Design geändert werden muss.

    • Testcode sollte auch auf andere Weise überprüft werden.
  • Beim Testen von Framework-Funktionen ist Vorsicht geboten. Frameworks können sich im Laufe der Zeit verändern.

    • Eine wichtige Rolle von Tests ist es, beim Upgrade von Abhängigkeiten zu prüfen, ob alles weiterhin sicher funktioniert.
  • Bei der Commit-Größe sollte man Commits anstreben, die sich leicht rückgängig machen lassen, falls eine bestimmte Änderung zurückgenommen werden muss.

  • Unternehmen wollen eine stabile Codebasis, aber kontinuierliches Refactoring ist notwendig. Das kann mit Stabilität in Konflikt geraten.