Fallstricke, auf die Entwickler achten sollten
(qouteall.fun)- Eine Zusammenstellung nicht intuitiver Fallstricke, in die Entwickler häufig tappen, mit einer Einführung in die Ursachen leicht auftretender Bugs
- Behandelt häufige Probleme in verschiedenen Technologien wie HTML, CSS, Unicode/Textkodierung, Fließkommazahlen und Zeit
- Betont, dass durch subtile Unterschiede in Syntax und Verhalten zwischen einzelnen Sprachen und Frameworks Missverständnisse oder Fehler entstehen können
- Erläutert anhand von Beispielen Fallstricke in zentralen Backend-Bereichen wie Nebenläufigkeit, Netzwerken und Datenbanken, die in realen Betriebsumgebungen auftreten können
- Zeigt mithilfe verschiedener Beispiele und Referenzlinks Problemsituationen, Lösungsansätze und Verbesserungen bei unerwartetem Verhalten auf
HTML und CSS
-
Standardwert von min-width in Flexbox/Grid
min-widthist standardmäßigautomin-width: autowird durch die Größe des Inhalts bestimmt und hat Vorrang vorflex-shrink,overflow: hidden,width: 0undmax-width: 100%- Empfehlung:
min-width: 0explizit angeben
-
Unterschied zwischen horizontal und vertikal in CSS
width: autoversucht, den Platz des Elternelements auszufüllen,height: autorichtet sich nach dem Inhaltwidth: autobei inline-, inline-block- und float-Elementen erweitert sich nichtmargin: 0 autozentriert horizontal,margin: auto 0zentriert nicht vertikal (außer beiflex-direction: column, wo vertikale Zentrierung möglich ist)- Margin-Collapsing tritt nur vertikal auf
- Wenn sich mit
writing-mode: vertical-rlusw. die Layoutrichtung ändert, kehrt sich auch das Verhalten um
-
Block Formatting Context (BFC)
- Ein BFC kann mit
display: flow-rooterzeugt werden (auchoverflow: hidden/auto/scroll,display: tableusw. sind möglich, haben aber Nebenwirkungen) - Sich überlappende vertikale Margins benachbarter Geschwister oder nach außen austretende Kind-Margins lassen sich mit einem BFC verhindern
- Wenn ein Elternelement nur floatende Kinder enthält, kollabiert seine Höhe auf 0 → mit BFC behebbar
- Bei vorhandenem
borderoderpaddingtritt kein Margin-Collapsing auf
- Ein BFC kann mit
-
Stacking Context
- Bedingungen, die einen neuen Stacking Context erzeugen
- Rendering-Eigenschaften wie
transform,filter,perspective,mask,opacity position: fixedodersticky- gesetztes
z-index+ Positionierung mitabsolute/relative - gesetztes
z-index+ Elemente innerhalb von Flexbox/Grid isolation: isolate
- Rendering-Eigenschaften wie
- Eigenschaften
z-indexgilt nur innerhalb des jeweiligen Stacking Context- Die Koordinaten von
position: absolute/fixedbeziehen sich auf den nächstgelegenen positionierten Vorfahren stickyfunktioniert nicht über einen Stacking Context hinweg- Selbst
overflow: visiblewird durch den Stacking Context abgeschnitten background-attachment: fixedwird relativ zum Stacking Context positioniert
- Bedingungen, die einen neuen Stacking Context erzeugen
-
Viewport-Einheiten
- In mobilen Browsern ändert sich
100vh, wenn Adressleiste/Navigationsleiste beim Scrollen vom Bildschirm verschwinden - Aktuelle Lösung:
100dvhverwenden
- In mobilen Browsern ändert sich
-
Bezugsrahmen für Absolute Positioning
position: absolutebezieht sich nicht auf das Elternelement, sondern auf den nächstgelegenenrelative/absolute- oder Stacking-Context-Vorfahren
-
Blur-Verhalten
backdrop-filter: blurberücksichtigt keine umliegenden Elemente
-
Aufhebung von Float
- Wenn das Elternelement
flexodergridist, hatfloatbei Kindelementen keine Wirkung
- Wenn das Elternelement
-
Prozentangaben bei width/height
- Funktionieren nicht, wenn die Größe des Elternelements nicht vorab festgelegt ist (um zirkuläre Referenzen zu vermeiden)
-
Eigenschaften von Inline-Elementen
display: inlineignoriertwidth,height,margin-topundmargin-bottom
-
Whitespace-Verarbeitung
- Standardmäßig werden Zeilenumbrüche in HTML als Leerzeichen behandelt, aufeinanderfolgende Leerzeichen werden auf eines reduziert
<pre>verhindert die Reduzierung von Leerzeichen, hat aber besonderes Verhalten am Anfang und Ende- Leerzeichen am Anfang/Ende von Inhalten werden meist ignoriert,
<a>ist jedoch eine Ausnahme - Leerzeichen/Zeilenumbrüche zwischen
inline-block-Elementen werden als tatsächlicher Abstand dargestellt (bei flex/grid tritt das nicht auf)
-
text-align
- Wirkt auf Text und Inline-Elemente, aber nicht auf die Ausrichtung von Block-Elementen
-
box-sizing
- Standardwert ist
content-box→padding/bordersind nicht enthalten - Bei
width: 100%+ gesetztempaddingkann das Elternelement überschritten werden - Lösung:
box-sizing: border-box
- Standardwert ist
-
Cumulative Layout Shift
- Werden bei
<img>keine Attributewidthundheightgesetzt, kann verzögertes Laden von Bildern zu Layout-Verschiebungen führen - Empfehlung: Attribute setzen, um CLS zu vermeiden
- Werden bei
-
Netzwerkanfragen bei Dateidownloads in Chrome
- Werden im Netzwerk-Panel der DevTools nicht angezeigt (sie werden in einem anderen Tab verarbeitet)
- Falls Analyse nötig ist:
chrome://net-export/verwenden
-
JavaScript-Parsing-Probleme in HTML
- In Fällen wie
<script>console.log('</script>')</script>wird das erste</script>als schließendes Tag erkannt - Siehe auch: Safe JSON in script tags
- In Fällen wie
Unicode und Textkodierung
-
Code Points und Grapheme Cluster
- Grapheme Cluster sind die „Zeicheneinheit“ in einer GUI
- Bei sichtbaren ASCII-Zeichen gilt: 1 Code Point = 1 Grapheme Cluster
- Ein Emoji kann aus mehreren Code Points bestehen und dennoch ein einzelnes Grapheme Cluster bilden
- In UTF-8 belegt ein Code Point 1 bis 4 Byte; Anzahl der Bytes und Anzahl der Code Points stimmen nicht überein
- In UTF-16 belegt ein Code Point 2 oder 4 Byte (Surrogatpaar)
- Der Standard setzt keine Begrenzung für die Anzahl der Code Points in einem Cluster, Implementierungen begrenzen dies jedoch oft aus Performancegründen
-
Unterschiede im String-Verhalten je nach Sprache
- Rust: Verwendet intern UTF-8 für Strings,
len()gibt die Byte-Anzahl zurück, direktes Indexing ist nicht möglich,chars().count()liefert die Anzahl der Code Points, UTF-8-Gültigkeit wird strikt geprüft - Golang: Strings sind faktisch Byte-Arrays, Länge und Indexing erfolgen byteweise, meist wird UTF-8 verwendet
- Java, C#, JS: Basieren auf UTF-16, messen Länge in 2-Byte-Einheiten, auch Indexing erfolgt in 2-Byte-Einheiten, Surrogatpaare kommen vor
- Python:
len()gibt die Anzahl der Code Points zurück, Indexing liefert einen String, der genau einen Code Point enthält - C++:
std::stringhat keine Vorgaben zur Kodierung, verhält sich wie ein Byte-Vektor, Länge/Indexing erfolgen byteweise - Unter den genannten Sprachen gibt es keine, die Länge/Indexing auf Ebene von Grapheme Clustern bereitstellt
- Rust: Verwendet intern UTF-8 für Strings,
-
BOM (Byte Order Mark)
- Manche Textdateien enthalten ein BOM, z. B. EF BB BF als Kennzeichnung für UTF-8-Kodierung
- Wird vor allem unter Windows verwendet; Software außerhalb von Windows kann ein BOM unter Umständen nicht korrekt verarbeiten
-
Sonstige Hinweise
- Beim Umwandeln von Binärdaten in Zeichenketten werden fehlerhafte Teile durch � (U+FFFD) ersetzt
- Es gibt confusable characters (Zeichen, die sich gegenseitig sehr ähnlich sehen)
- Normalisierung (Normalization): z. B. kann é als U+00E9 (ein einzelner Code Point) oder als U+0065+U+0301 (zwei Code Points) dargestellt werden
- Es gibt Zero-width characters und Invisible characters
- Unterschiede bei Zeilenumbrüchen: Windows verwendet CRLF
\r\n, Linux/MacOS LF\n - Han unification: Je nach Sprache verwenden Zeichen mit leicht unterschiedlicher Form denselben Code Point
- Schriftarten rendern dies passend, indem sie sprachspezifische Varianten enthalten
- Bei der Internationalisierung muss die richtige Font-Variante gewählt werden
Gleitkommazahlen (Floating point)
-
NaN-Eigenschaften
- NaN ist mit keinem Wert gleich, auch nicht mit sich selbst (
NaN == NaNist immer false) NaN != NaNist immer true- Ergebnisse von Operationen mit NaN propagieren in den meisten Fällen ebenfalls zu NaN
- NaN ist mit keinem Wert gleich, auch nicht mit sich selbst (
-
Spezielle Werte
- Es gibt +Inf und -Inf, sie unterscheiden sich von NaN
- -0.0 ist ein von +0.0 unterscheidbarer Wert
- Bei Vergleichsoperationen sind sie gleich, in einigen Berechnungen verhalten sie sich jedoch unterschiedlich
- Beispiel:
1.0 / +0.0 == +Inf,1.0 / -0.0 == -Inf
-
Kompatibilität mit JSON
- Der JSON-Standard erlaubt NaN und Inf nicht
- JS
JSON.stringifywandelt NaN und Inf innullum - Python
json.dumps(...)gibt NaN und Infinity unverändert aus (Verstoß gegen den Standard)- Mit der Option
allow_nan=Falsetritt bei NaN/Inf einValueErrorauf
- Mit der Option
- Golang
json.Marshalgibt bei vorhandenem NaN/Inf einen Fehler zurück
- JS
- Der JSON-Standard erlaubt NaN und Inf nicht
-
Präzisionsprobleme
- Direkte Vergleiche von Gleitkommazahlen können fehlschlagen → empfohlen ist die Form
abs(a - b) < ε - JS behandelt alle Zahlen als Gleitkommazahlen
- Der sichere Integer-Bereich ist
-(2^53 - 1)bis2^53 - 1 - Außerhalb dieses Bereichs ist die Integer-Darstellung ungenau
- Für große Integer wird
BigIntempfohlen - Wenn JSON Integer außerhalb des sicheren Bereichs enthält, kann das Ergebnis von
JSON.parseungenau sein - Zeitstempel in Millisekunden sind bis zum Jahr 287.396 sicher, bei Nanosekunden treten Probleme auf
- Der sichere Integer-Bereich ist
- Direkte Vergleiche von Gleitkommazahlen können fehlschlagen → empfohlen ist die Form
-
Nichtanwendbarkeit von Rechengesetzen
- Je nach Reihenfolge der Operationen gelten Assoziativgesetz und Distributivgesetz aufgrund von Präzisionsverlusten nicht streng
- Parallele Berechnungen (Matrixmultiplikation, Summen usw.) können nichtdeterministische Ergebnisse erzeugen
-
Leistung
- Division ist deutlich langsamer als Multiplikation
- Wenn mehrfach durch denselben Wert geteilt wird, kann man optimieren, indem man zuerst den Kehrwert berechnet und dann multipliziert
-
Unterschiede je nach Hardware
- Unterstützung für FMA (Fused Multiply-Add): Manche Hardware führt Zwischenberechnungen mit höherer Präzision aus
- Behandlung des Subnormal range: Moderne Hardware unterstützt ihn, manche ältere behandelt ihn als 0
- Unterschiede bei Rundungsmodi
- Es gibt u. a. RNTE (auf die nächste gerade Zahl runden) und RTZ (auf 0 abschneiden)
- x86/ARM kann dies als thread-lokalen veränderbaren Zustand setzen
- Bei GPUs unterscheidet sich der Rundungsmodus je nach Instruktion
- Unterschiede im Verhalten mathematischer Funktionen wie trigonometrische Funktionen oder Logarithmen
- x86 hat eine Legacy-80-Bit-FPU und einen per-core rounding mode → Verwendung nicht empfohlen
- Auch darüber hinaus können verschiedene Faktoren dazu führen, dass Gleitkommaergebnisse je nach Hardware unterschiedlich ausfallen
-
Methoden zur Verbesserung der Präzision
- Den Berechnungsgraphen flach halten (weniger aufeinanderfolgende Multiplikationsstrukturen)
- Vermeiden, dass Zwischenwerte extrem groß oder extrem klein werden
- Hardware-Operationen wie FMA nutzen
Zeit (Time)
-
Schaltsekunde (Leap second)
- Unix-Zeitstempel ignorieren Schaltsekunden
- Beim Auftreten einer Schaltsekunde wird die Zeit in der Umgebung gestreckt oder verkürzt (Leap smear)
-
Zeitzone (Time zone)
- UTC und Unix-Zeitstempel sind weltweit einheitlich
- Menschenlesbare Zeit hängt von der jeweiligen lokalen Zeitzone ab
- Es wird empfohlen, Zeitstempel in der DB zu speichern und erst in der UI umzuwandeln
-
Sommerzeit (DST)
- In manchen Regionen wird die Uhr im Sommer um 1 Stunde angepasst
-
NTP-Synchronisierung
- Während der Synchronisierung kann es vorkommen, dass die Zeit „rückwärts läuft“
-
Einstellung der Server-Zeitzone
- Für Server wird UTC empfohlen
- In verteilten Systemen entstehen Probleme, wenn Knoten unterschiedliche Zeitzonen verwenden
- Nach dem Ändern der Systemzeitzone ist eine Neukonfiguration oder ein Neustart der DB erforderlich
-
Hardware-Uhr vs. Systemuhr
- Die Hardware-Uhr kennt kein Zeitzonenkonzept
- Linux: behandelt die Hardware-Uhr als UTC
- Windows: behandelt die Hardware-Uhr als lokale Zeit
Java
==vergleicht Objektreferenzen, für den Vergleich des Objektinhalts muss.equalsverwendet werden- Wenn
equalsundhashcodenicht überschrieben werden, beurteilen map/set die Gleichheit von Objekten referenzbasiert - Wenn der Inhalt eines key-Objekts in einer map oder eines Elementobjekts in einem set geändert wird, funktioniert der Container nicht mehr korrekt
- Methoden, die
List<T>zurückgeben, liefern je nach Fall ein veränderbaresArrayListoder ein unveränderlichesCollections.emptyList(); beim Ändern des Letzteren trittUnsupportedOperationExceptionauf - Es gibt Fälle, in denen eine Methode, die
Optional<T>zurückgeben soll,nullzurückgibt (nicht empfohlen) - Wenn im
finally-Block ein return ausgeführt wird, werden Ausnahmen austryodercatchignoriert und der Rückgabewert ausfinallyverwendet - Es gibt Bibliotheken, die interrupts ignorieren; außerdem kann die Initialisierung von Klassen einschließlich IO durch interrupts gestört werden
- Bei Tasks, die in einem thread pool mit
.submit()übergeben werden, werden Ausnahmen standardmäßig nicht ins Log geschrieben und können nur über das future geprüft werden; wird das future ignoriert, bleiben die Ausnahmen unbemerktscheduleAtFixedRate-Jobs werden bei einer Ausnahme stillschweigend beendet
- Wenn ein Zahlenliteral mit 0 beginnt, wird es als Oktalzahl behandelt (
0123→ 83) - Der Debugger ruft
.toString()lokaler Variablen auf; datoString()bei einigen Klassen Nebenwirkungen hat, kann sich das Verhalten des Codes beim Debugging ändern (in der IDE deaktivierbar)
Golang
append()verwendet bei freier capacity denselben Speicher weiter; ein append auf eine subslice kann daher auch den Speicher des übergeordneten Bereichs überschreibendeferwird beim Return der Funktion ausgeführt, nicht beim Ende eines Block-Scopesdefererfasst veränderbare Variablen- Zu
nil- Eine nil slice und eine leere slice sind verschieden
- string kann nicht nil sein, es gibt nur den leeren String
- Eine nil map kann gelesen, aber nicht beschrieben werden
- Eigenartiges Verhalten bei interface nil: Wenn der data pointer null ist, aber die type info nicht null ist, ist es nicht gleich
nil
- Dead wait: Es gibt in Go reale Beispiele für derartige Nebenläufigkeits-Bugs
- Es gibt verschiedene Timeout-Arten, ausführlich behandelt in net/http
C/C++
- Wenn nach dem Speichern eines Zeigers auf ein
std::vector-Element der Vektor wächst, kommt es zu einer Reallokation und der Zeiger wird ungültig - Ein
std::string, der aus einem String-Literal erzeugt wurde, kann ein temporäres Objekt sein; ein Aufruf vonc_str()ist dann riskant - Wird ein Container während der Iteration verändert, werden Iteratoren ungültig
std::removelöscht nicht wirklich, sondern ordnet Elemente nur um; zum Löschen isterasenötig- Beginnt ein Zahlenliteral mit 0, wird es als Oktalzahl behandelt (
0123→ 83) - Undefined behavior (UB): Bei der Optimierung kann UB beliebig verändert werden, daher ist jede Abhängigkeit davon riskant
- Zugriff auf nicht initialisierten Speicher ist UB
- Wird
char*in einen Struct-Zeiger umgewandelt, ist der Zugriff vor Beginn der Objektlebensdauer UB; Initialisierung permemcpywird empfohlen - Ungültiger Speicherzugriff (z. B. Nullzeiger) ist UB
- Integer-Overflow/-Underflow ist UB (bei unsigned ist Underflow unter 0 möglich)
- Aliasing: Wenn Zeiger verschiedener Typen auf denselben Speicher verweisen, kann durch die Strict-Aliasing-Regel UB entstehen
- Ausnahmen: 1) Typen in einer Vererbungsbeziehung 2) Umwandlung in
char*,unsigned char*,std::byte*(gilt nicht für die Rückumwandlung) - Für erzwungene Umwandlungen werden
memcpyoderstd::bit_castempfohlen
- Ausnahmen: 1) Typen in einer Vererbungsbeziehung 2) Umwandlung in
- Zugriff auf unaligned memory ist UB
- Memory Alignment
- Bei 64-Bit-Integern muss die Adresse durch 8 teilbar sein
- Auf ARM kann unaligned Zugriff zu einem Crash führen
- Wird ein Byte-Puffer direkt als Struct interpretiert, können Alignment-Probleme auftreten
- Alignment kann durch Struct-Padding zu Speicherverlust führen
- Einige SIMD-Befehle (z. B. AVX) können nur ausgerichtete Daten verarbeiten; meist ist ein Alignment von 32 Byte nötig
Python
- Standardargumente von Funktionen werden nicht bei jedem Aufruf neu erzeugt, sondern der initiale Wert wird beibehalten
SQL Databases
-
Umgang mit Null
x = nullfunktioniert nicht; stattdessen mussx is nullverwendet werden- Null ist nicht einmal sich selbst gleich (ähnlich wie NaN)
- Ein Unique-Index erlaubt doppelte Null-Werte (mit Ausnahme von Microsoft SQL Server)
- Wie Null bei
select distinctbehandelt wird, unterscheidet sich je nach DB count(x)undcount(distinct x)ignorieren Zeilen mit Null-Werten
-
Allgemeines Verhalten
- Implizite Datumsumwandlungen können von der Zeitzone abhängen
- Komplexe Join- + Distinct-Abfragen können langsamer sein als verschachtelte Queries
- In MySQL (InnoDB) führt ein String-Feld, das nicht
utf8mb4verwendet, beim Einfügen von 4-Byte-UTF-8-Zeichen zu Fehlern - MySQL (InnoDB) ist standardmäßig nicht case-sensitive
- MySQL (InnoDB) erlaubt implizite Umwandlungen:
select '123abc' + 1;→ 124 - Gap Locks in MySQL (InnoDB) können Deadlocks verursachen
- In MySQL (InnoDB) liefert eine Abweichung zwischen
group byundselect-Spalten nichtdeterministische Ergebnisse - In SQLite ist der Feldtyp ohne
strictweitgehend bedeutungslos - Foreign Keys können implizite Locks auslösen und dadurch Deadlocks verursachen
- Locking kann je nach DB die Repeatable-Read-Isolation verletzen
- Verteilte SQL-Datenbanken unterstützen Locking möglicherweise nicht oder verhalten sich ungewöhnlich (je nach DB unterschiedlich)
-
Performance/Betrieb
- Das N+1-Query-Problem erscheint nicht im Slow-Query-Log, weil jede einzelne Query schnell ist
- Lang laufende Transaktionen können Lock-Probleme usw. verursachen → daher sollten Transaktionen schnell beendet werden
- Fälle mit vollständigem Tabellen-Lock
- In MySQL 8.0+ können das Hinzufügen eines Unique-Index oder eines Foreign Keys meist parallel verarbeitet werden
- Bei älteren MySQL-Versionen kann ein vollständiger Tabellen-Lock auftreten
- Fehlt bei
mysqldumpdie Option--single-transaction, wird ein vollständiger Read Lock auf die Tabelle gesetzt - In PostgreSQL verursachen
create unique indexoderalter table ... add foreign keyeinen vollständigen Read Lock auf die Tabelle- Vermeidung:
create unique index concurrentlyverwenden - Bei Foreign Keys die Methode
... not validund anschließendvalidate constraintverwenden
- Vermeidung:
-
Range-Abfragen
- Nicht überlappende Bereiche:
- Die einfache Bedingung
p >= start and p <= endist ineffizient (auch mit zusammengesetztem Index) - Effiziente Variante:
(benötigt nur einen Index auf der Spalteselect * from (select ... from ranges where start <= p order by start desc limit 1) where end >= pstart)
- Die einfache Bedingung
- Überlappende Bereiche:
- Mit einem normalen B-Tree-Index ineffizient
- Empfohlen: Spatial Index in MySQL, GiST in PostgreSQL
- Nicht überlappende Bereiche:
Concurrency and Parallelism
-
volatile
volatilekann keinen Lock ersetzen und bietet keine Atomizität- Für durch Locks geschützte Daten ist
volatilenicht nötig (der Lock garantiert die Memory Order) - C/C++:
volatileverhindert nur bestimmte Optimierungen, fügt aber keine Memory Barrier hinzu - Java: Zugriffe auf
volatilebieten sequentially-consistent ordering (die JVM fügt bei Bedarf Memory Barriers ein) - C#: Zugriffe auf
volatilebieten release-acquire ordering (die CLR fügt bei Bedarf Memory Barriers ein) - Kann Fehloptimierungen im Zusammenhang mit der Umordnung von Speicher-Lese-/Schreibzugriffen verhindern
-
TOCTOU-(Time-of-check to time-of-use)-Problem
-
Behandlung von Constraints in der Anwendungsschicht bei SQL-DBs
- Wenn Constraints, die sich nicht mit einem einfachen Unique-Index ausdrücken lassen (z. B. tabellenübergreifende Eindeutigkeit, bedingte Eindeutigkeit, Eindeutigkeit innerhalb eines Zeitraums), in der Anwendung erzwungen werden:
- MySQL (InnoDB): Auf Repeatable-Read-Level ist nach
select ... for updateund anschließendem Insert sowie bei vorhandenem Index auf der Unique-Spalte die Gültigkeit dank Gap Lock gewährleistet (Gap Locks können bei hoher Last jedoch Deadlocks verursachen → Deadlock-Erkennung und Retry nötig) - PostgreSQL: Dieselbe Logik ist auf Repeatable-Read-Level bei konkurrierenden Zugriffen nicht ausreichend (Write-Skew-Problem)
- Lösungen:
- Serializable Isolation Level verwenden
- DB-Constraints statt Anwendungslogik verwenden
- Bedingte Eindeutigkeit → Partial Unique Index
- Tabellenübergreifende Eindeutigkeit → doppelte Daten in separate Tabelle einfügen und dort per Unique-Index absichern
- Ausschließlichkeit in Zeiträumen → Range-Typ + Exclude Constraint
- Lösungen:
- MySQL (InnoDB): Auf Repeatable-Read-Level ist nach
- Wenn Constraints, die sich nicht mit einem einfachen Unique-Index ausdrücken lassen (z. B. tabellenübergreifende Eindeutigkeit, bedingte Eindeutigkeit, Eindeutigkeit innerhalb eines Zeitraums), in der Anwendung erzwungen werden:
-
Atomare Referenzzählung
- Wenn wie bei
Arcodershared_ptrviele Threads denselben Zähler häufig ändern, leidet die Performance
- Wenn wie bei
-
Read-Write-Lock
- Manche Implementierungen unterstützen kein Upgrade von einem Read Lock auf einen Write Lock
- Der Versuch, bei gehaltenem Read Lock einen Write Lock zu erwerben, kann zu einem Deadlock führen
In vielen Sprachen üblich
- Fehlende Null/None/nil-Prüfungen sind eine häufige Fehlerursache
- Wird ein Container während einer Schleife verändert, kann es zu einem Data Race in einem Single-Thread-Kontext kommen
- Fehler beim Teilen veränderlicher Daten: z. B. ist
[[0] * 10] * 10in Python keine korrekte Erzeugung eines 2D-Arrays (low + high) / 2kann zu Overflow führen → die sichere Variante istlow + (high - low) / 2- Kurzschlussauswertung (short circuit): Bei
a() || b()wird b nicht ausgeführt, wenn a true ist; beia() && b()wird b nicht ausgeführt, wenn a false ist - Der Standard eines Profilers umfasst oft nur CPU-Zeit → Wartezeiten wie z. B. auf die DB erscheinen nicht im Flamegraph und können zu Fehlinterpretationen führen
- Regex-Dialekte unterscheiden sich je nach Sprache → ein Regex, das in JS funktioniert, muss in Java nicht funktionieren
Linux and bash
- Nach einem Verzeichniswechsel zeigt
pwdden ursprünglichen Pfad, der tatsächliche Pfad steht inpwd -P cmd > file 2>&1→ stdout+stderr beide in die Datei,cmd 2>&1 > file→ nur stdout in die Datei, stderr bleibt unverändert- Dateinamen sind groß-/kleinschreibungssensitiv (anders als unter Windows)
- Für ausführbare Dateien gibt es ein Capability-System (prüfbar mit
getcap) - Gefahr durch nicht gesetzte Variablen: Wenn
DIRnicht gesetzt ist, kannrm -rf $DIR/zurm -rf /werden → vermeidbar mitset -u - Umgebung anwenden: Um ein Skript in der aktuellen Shell anzuwenden,
source script.shverwenden → für dauerhafte Anwendung in~/.bashrceintragen - Bash nutzt Command-Caching: Wird eine Datei innerhalb von
$PATHverschoben, kannENOENTauftreten → Cache mithash -raktualisieren - Werden Variablen ohne Anführungszeichen verwendet, werden Zeilenumbrüche als Leerzeichen behandelt
set -e: Beendet das Skript bei Fehlern sofort, funktioniert aber nicht innerhalb von Bedingungen (||,&&,if)- Konflikt zwischen K8s livenessProbe und Debugger: Ein Breakpoint-Debugger kann die gesamte App anhalten, wodurch Health Checks fehlschlagen → der Pod kann beendet werden
React
- State direkt verändern im Rendering-Code
- Hooks innerhalb von if/loop verwenden → Regelverstoß
- Im Dependency-Array von
useEffectnotwendige Werte weglassen - In
useEffectClean-up-Code vergessen - Closure-Falle: Durch Capturing eines veralteten State entstehen Bugs
- Daten an der falschen Stelle verändern → unreine Komponente
useCallbacknicht verwenden → unnötige Re-Renders- Bei memoisierten Komponenten nicht memoisierten Werte übergeben → memo-Optimierung wird wirkungslos
Git
-
Rebase schreibt die Historie um
- Nach einem Rebase führt ein normales Push zu Konflikten → es ist ein Force Push erforderlich
- Wenn sich die Historie eines Remote-Branches geändert hat, sollte auch beim Pull
--rebaseverwendet werden --force-with-leasekann in manchen Fällen verhindern, dass Commits anderer Entwickler überschrieben werden; wer aber nur fetch und nicht pull macht, ist dadurch nicht geschützt
-
Probleme mit dem Revert eines Merge
- Ein Merge-Revert macht die Wirkung nicht vollständig rückgängig → wird derselbe Branch erneut gemergt, gibt es keine Änderung
- Lösung: den Revert revertieren oder einen sauberen Weg wählen (backup → reset → cherry-pick → force push)
-
Hinweise zu GitHub
- Selbst wenn ein Secret wie ein API-Key nach dem Commit per Force Push überschrieben wird, bleibt die Spur in GitHub erhalten
- Wenn ein privates Repo B ein Fork des privaten Repo A ist und A später public wird, wird auch der Inhalt von B öffentlich (und kann selbst nach dem Löschen zugänglich bleiben)
-
git stash pop: Bei Konflikten wird der Stash nicht gedroppt -
.DS_Storewird von macOS automatisch erzeugt → empfohlen wird**/.DS_Storein.gitignore
Networking
- Manche Router und Firewalls trennen inaktive TCP-Verbindungen stillschweigend → dadurch können Connection Pools von HTTP-Clients und DB-Clients ungültig werden → Lösung: TCP keepalive konfigurieren
traceroute-Ergebnisse sind nur begrenzt zuverlässig → je nach Fall isttcptraceroutenützlicher- TCP slow start kann zusätzliche Latenz verursachen → lässt sich durch Deaktivieren von
tcp_slow_start_after_idlebeheben - TCP-Sticky-Packet-Problem: Der Nagle-Algorithmus verzögert die Paketübertragung → lässt sich durch Aktivieren von
TCP_NODELAYbeheben - Bei Backends hinter Nginx muss Connection-Reuse konfiguriert werden → andernfalls können in Hochlastumgebungen Verbindungen wegen interner Portknappheit fehlschlagen
- Nginx betreibt standardmäßig Packet Buffering → dadurch kann es bei SSE (EventSource) zu Verzögerungen kommen
- Der HTTP-Standard verbietet keinen Body bei GET- und DELETE-Requests → manche nutzen einen Body, aber viele Libraries und Server unterstützen das nicht
- Auf einer einzelnen IP lassen sich mehrere Websites hosten → unterschieden wird über den HTTP-
Host-Header und SNI bei TLS → deshalb gibt es Websites, die nicht per bloßem IP-Zugriff erreichbar sind - CORS: Bei Requests von einer anderen Origin blockiert der Browser den Zugriff auf die Response → der Server muss den Header
Access-Control-Allow-Originsetzen- Wenn auch Cookies übertragen werden sollen, sind zusätzliche Einstellungen nötig
- Wenn Frontend und Backend dieselbe Domain und denselben Port verwenden, gibt es kein CORS-Problem
Other
-
YAML-Hinweise
- YAML ist leerzeichenempfindlich →
key:valueist fehlerhaft,key: valueist korrekt - Der Ländercode
NOkann ohne Anführungszeichen alsfalseinterpretiert werden - Ein Git-Commit-Hash kann ohne Anführungszeichen in eine Zahl umgewandelt werden
- YAML ist leerzeichenempfindlich →
-
Excel-CSV-Probleme
- Excel führt beim Öffnen von CSV-Dateien automatische Umwandlungen durch
- Datumsumwandlung:
1/2,1-2→2-Jan - Ungenaue Umwandlung großer Zahlen:
12345678901234567890→12345678901234500000
- Datumsumwandlung:
- Die Ursache ist, dass Excel Zahlen intern als Floating Point verarbeitet
- Durch dieses Problem wurde z. B. der Genname SEPT1 schon falsch verändert
- Excel führt beim Öffnen von CSV-Dateien automatische Umwandlungen durch
Noch keine Kommentare.