Les pièges dont les développeurs doivent se méfier
(qouteall.fun)- Répertorie les pièges contre-intuitifs dans lesquels les développeurs tombent souvent, en présentant les causes de bugs susceptibles de se produire facilement
- Traite des problèmes fréquents dans diverses technologies comme HTML, CSS, Unicode/l’encodage de texte, les nombres à virgule flottante et le temps
- Souligne que des malentendus ou des erreurs peuvent naître de différences subtiles de syntaxe et de comportement selon les langages et les frameworks
- Explique, à l’aide d’exemples, les pièges pouvant survenir en environnement réel dans des domaines clés du backend comme la concurrence, le réseau et les bases de données
- À travers divers exemples et liens de référence, présente les situations problématiques, leurs solutions et des améliorations face à des comportements inattendus
HTML et CSS
-
Valeur par défaut de
min-widthdans Flexbox/Gridmin-widthvaut par défautautomin-width: autoest déterminé par la taille du contenu et prévaut surflex-shrink,overflow: hidden,width: 0,max-width: 100%- Recommandation : définir explicitement
min-width: 0
-
Différence entre l’horizontal et le vertical en CSS
width: autotente de remplir l’espace du parent, tandis queheight: autos’adapte au contenu- Pour les éléments inline, inline-block et float,
width: autone s’étend pas margin: 0 autocentre horizontalement,margin: auto 0ne permet pas le centrage vertical (sauf avecflex-direction: column, où le centrage vertical est possible)- La fusion des marges ne se produit qu’à la verticale
- Si la direction de mise en page change avec
writing-mode: vertical-rl, par exemple, le comportement s’inverse également
-
Block Formatting Context (BFC)
- Création d’un BFC avec
display: flow-root(d’autres options existent aussi, commeoverflow: hidden/auto/scrolloudisplay: table, mais avec des effets de bord) - Un BFC permet d’éviter le chevauchement des marges verticales entre éléments frères adjacents ou les marges des enfants qui débordent du parent
- Si un parent ne contient que des enfants flottants, sa hauteur s’effondre à 0 → cela peut être corrigé avec un BFC
- S’il y a une
borderou unpadding, la fusion des marges ne se produit pas
- Création d’un BFC avec
-
Stacking Context
- Conditions qui créent un nouveau stacking context
- Propriétés de rendu comme
transform,filter,perspective,mask,opacity, etc. position: fixedoustickyz-indexdéfini + positionnementabsolute/relativez-indexdéfini + élément à l’intérieur d’un conteneur flexbox/gridisolation: isolate
- Propriétés de rendu comme
- Caractéristiques
z-indexne s’applique qu’à l’intérieur du stacking context- Les coordonnées de
position: absolute/fixedsont calculées par rapport à l’ancêtre positionné le plus proche stickyne fonctionne pas au-delà d’un stacking context- Même avec
overflow: visible, le contenu peut être rogné par un stacking context background-attachment: fixedest positionné par rapport au stacking context
- Conditions qui créent un nouveau stacking context
-
Unités de viewport
- Sur les navigateurs mobiles, quand la barre d’adresse/la barre de navigation disparaît au défilement, la valeur de
100vhchange - Solution moderne : utiliser
100dvh
- Sur les navigateurs mobiles, quand la barre d’adresse/la barre de navigation disparaît au défilement, la valeur de
-
Référence pour le positionnement absolu
position: absolutese base non pas sur le parent, mais sur l’ancêtrerelative/absoluteou le stacking context le plus proche
-
Fonctionnement du blur
backdrop-filter: blurne tient pas compte des éléments environnants
-
Annulation du float
- Si le parent est en
flexougrid, lefloatdes enfants n’a aucun effet
- Si le parent est en
-
Unités en pourcentage pour width/height
- Elles ne fonctionnent pas si la taille du parent n’est pas déterminée à l’avance (pour éviter les références circulaires)
-
Caractéristiques des éléments inline
display: inlineignorewidth,height,margin-topetmargin-bottom
-
Gestion des espaces
- Par défaut, les retours à la ligne en HTML sont traités comme des espaces, et les espaces consécutifs sont réduits à un seul
<pre>empêche cette réduction des espaces, mais son comportement au début et à la fin est particulier- Dans la plupart des cas, les espaces au début et à la fin du contenu sont ignorés, sauf pour
<a> - Les espaces/retours à la ligne entre éléments
inline-blocksont affichés comme un espacement réel (ce qui n’arrive pas en flex/grid)
-
text-align- S’applique à l’alignement du texte et des éléments inline, mais pas à celui des éléments block
-
box-sizing- La valeur par défaut est
content-box→paddingetborderne sont pas inclus - Avec
width: 100%+padding, l’élément peut déborder de la zone du parent - Solution :
box-sizing: border-box
- La valeur par défaut est
-
Cumulative Layout Shift
- Si les attributs
widthetheightne sont pas définis sur<img>, le chargement différé de l’image peut provoquer des décalages de mise en page - Recommandation : définir ces attributs pour éviter le CLS
- Si les attributs
-
Requêtes réseau de téléchargement de fichier dans Chrome
- Elles n’apparaissent pas dans le panneau réseau de DevTools (elles sont traitées dans un autre onglet)
- Si une analyse est nécessaire, utiliser
chrome://net-export/
-
Problème d’analyse de JavaScript dans le HTML
- Dans un cas comme
<script>console.log('</script>')</script>, le premier</script>est interprété comme une balise de fermeture - Référence : Safe JSON in script tags
- Dans un cas comme
Unicode et encodage de texte
-
Points de code et clusters de graphèmes
- Un cluster de graphèmes correspond à l’« unité de caractère » dans une interface graphique
- Un caractère ASCII visible correspond à 1 point de code = 1 cluster de graphèmes
- Un emoji peut être un seul cluster de graphèmes composé de plusieurs points de code
- En UTF-8, un point de code occupe 1 à 4 octets, et le nombre d’octets ne correspond pas au nombre de points de code
- En UTF-16, un point de code occupe 2 ou 4 octets (paire de substituts / surrogate pair)
- La norme ne fixe pas de limite au nombre de points de code dans un cluster, mais les implémentations imposent souvent des limites pour des raisons de performance
-
Différences de comportement des chaînes selon les langages
- Rust : les chaînes internes utilisent l’UTF-8,
len()renvoie le nombre d’octets, l’indexation directe est impossible,chars().count()donne le nombre de points de code, la validité UTF-8 est vérifiée strictement - Golang : une chaîne est en pratique un tableau d’octets, la longueur et l’indexation se font en octets, l’UTF-8 est généralement utilisé
- Java, C#, JS : basés sur l’UTF-16, la longueur est mesurée en unités de 2 octets et l’indexation se fait aussi sur cette base, avec présence de paires de substituts
- Python :
len()renvoie le nombre de points de code, et l’indexation renvoie une chaîne contenant un seul point de code - C++ :
std::stringn’impose aucune contrainte d’encodage, se comporte comme un vecteur d’octets, et la longueur/l’indexation se font en octets - Parmi les langages mentionnés, aucun ne mesure la longueur ni n’indexe au niveau des clusters de graphèmes
- Rust : les chaînes internes utilisent l’UTF-8,
-
BOM (Byte Order Mark)
- Certains fichiers texte contiennent un BOM, par exemple
EF BB BFpour indiquer un encodage UTF-8 - Il est principalement utilisé sous Windows, et des logiciels non-Windows peuvent ne pas le gérer correctement
- Certains fichiers texte contiennent un BOM, par exemple
-
Autres points d’attention
- Lors de la conversion de données binaires en chaîne de caractères, les parties invalides sont remplacées par � (U+FFFD)
- Existence de confusable characters (caractères qui se ressemblent)
- Normalisation (Normalization) : par ex. é peut être représenté par U+00E9 (un seul point de code) ou U+0065+U+0301 (deux points de code)
- Existence de zero-width characters et de invisible characters
- Différences de fin de ligne : Windows utilise CRLF
\r\n, Linux/MacOS utilise LF\n - Unification des Han (Han unification) : des caractères dont la forme diffère légèrement selon la langue utilisent le même point de code
- Les polices intègrent des variantes par langue pour effectuer un rendu approprié
- En internationalisation, il faut sélectionner la bonne variante de police
Virgule flottante (Floating point)
-
Propriétés de NaN
- NaN n’est égal à aucune valeur, y compris lui-même (
NaN == NaNest toujours false) NaN != NaNest toujours true- Le résultat d’une opération impliquant NaN se propage le plus souvent en NaN
- NaN n’est égal à aucune valeur, y compris lui-même (
-
Valeurs spéciales
- Existence de +Inf et -Inf, distincts de NaN
- -0.0 est une valeur distincte de +0.0
- Elles sont identiques dans les comparaisons, mais se comportent différemment dans certains calculs
- Exemple :
1.0 / +0.0 == +Inf,1.0 / -0.0 == -Inf
-
Compatibilité avec JSON
- Le standard JSON n’autorise ni NaN ni Inf
- En JS,
JSON.stringifyconvertit NaN et Inf ennull - En Python,
json.dumps(...)affiche NaN et Infinity tels quels (non conforme au standard)- Avec l’option
allow_nan=False, la présence de NaN/Inf provoque uneValueError
- Avec l’option
- En Golang,
json.Marshalrenvoie une erreur si NaN/Inf sont présents
- En JS,
- Le standard JSON n’autorise ni NaN ni Inf
-
Problèmes de précision
- Une comparaison directe de nombres à virgule flottante peut échouer → forme recommandée :
abs(a - b) < ε - En JS, tous les nombres sont traités comme des nombres à virgule flottante
- La plage des entiers sûrs est
-(2^53 - 1)à2^53 - 1 - En dehors de cette plage, la représentation des entiers devient imprécise
- Pour les grands entiers, l’usage de
BigIntest recommandé - Si JSON contient des entiers au-delà de la plage sûre, les valeurs renvoyées par
JSON.parsepeuvent être imprécises - Les timestamps en millisecondes sont sûrs jusqu’en l’an 287396, ceux en nanosecondes posent problème
- La plage des entiers sûrs est
- Une comparaison directe de nombres à virgule flottante peut échouer → forme recommandée :
-
Lois de calcul non applicables
- Selon l’ordre des opérations, la perte de précision fait que l’associativité et la distributivité ne sont pas rigoureusement vérifiées
- Les calculs parallèles (multiplication de matrices, sommes, etc.) peuvent produire des résultats non déterministes
-
Performances
- La division est bien plus lente que la multiplication
- Lorsqu’on divise plusieurs fois par la même valeur, on peut optimiser en calculant d’abord l’inverse puis en multipliant
-
Différences selon le matériel
- Prise en charge de FMA (Fused Multiply-Add) : certains matériels effectuent les calculs intermédiaires avec une précision plus élevée
- Traitement de la plage subnormale : pris en charge par le matériel récent, mais parfois traité comme 0 sur certains anciens systèmes
- Différences de mode d’arrondi
- Il existe notamment RNTE (arrondi au pair le plus proche), RTZ (troncature vers 0), etc.
- Sur x86/ARM, cela peut être configuré comme un état mutable local au thread
- Sur GPU, le mode d’arrondi varie selon l’instruction
- Différences de comportement des fonctions mathématiques comme les fonctions trigonométriques ou les logarithmes
- x86 dispose d’un FPU historique en 80 bits et d’un rounding mode par cœur → utilisation déconseillée
- De nombreux autres facteurs peuvent aussi faire varier les résultats en virgule flottante selon le matériel
-
Méthodes pour améliorer la précision
- Garder un graphe de calcul peu profond (réduire les chaînes successives de multiplications)
- Éviter les cas où les valeurs intermédiaires deviennent extrêmement grandes ou extrêmement petites
- Exploiter des opérations matérielles comme FMA
Temps (Time)
-
Seconde intercalaire (Leap second)
- Les timestamps Unix ignorent les secondes intercalaires
- Lorsqu’une seconde intercalaire survient, le temps peut être allongé ou raccourci dans la zone voisine (Leap smear)
-
Fuseau horaire (Time zone)
- UTC et les timestamps Unix sont communs à l’échelle mondiale
- L’heure lisible par les humains dépend du fuseau horaire local
- Il est recommandé de stocker les timestamps en base de données et d’effectuer la conversion dans l’UI
-
Heure d’été (DST)
- Dans certaines régions, l’horloge est avancée d’une heure en été
-
Synchronisation NTP
- Pendant la synchronisation, il est possible que le temps « recule »
-
Configuration du fuseau horaire du serveur
- Il est recommandé de configurer les serveurs en UTC
- Dans un système distribué, des fuseaux horaires différents entre nœuds peuvent poser problème
- Après avoir modifié le fuseau horaire du système, il faut réinitialiser ou redémarrer la base de données
-
Horloge matérielle vs horloge système
- L’horloge matérielle n’a pas de notion de fuseau horaire
- Linux : traite l’horloge matérielle en UTC
- Windows : traite l’horloge matérielle comme une heure locale
Java
==compare les références d’objet ; pour comparer le contenu d’un objet, il faut utiliser.equals- Si
equalsethashcodene sont pas redéfinis, l’identité des objets dans une map/set est évaluée sur la base de la référence - Si l’on modifie le contenu d’un objet servant de clé dans une map ou d’élément dans un set, le comportement du conteneur est cassé
- Une méthode qui retourne
List<T>peut, selon le cas, renvoyer unArrayListmutable ou unCollections.emptyList()immutable ; modifier le second provoque uneUnsupportedOperationException - Certaines méthodes censées retourner
Optional<T>renvoient parfoisnull(ce qui n’est pas recommandé) - Si un
returnse trouve dans un blocfinally, l’exception survenue danstryoucatchest ignorée et c’est la valeur de retour dufinallyqui s’applique - Certaines bibliothèques ignorent les interruptions, et l’initialisation de classes, y compris avec des E/S, peut être perturbée par une interruption
- Dans un thread pool, les exceptions d’une tâche passée via
.submit()ne sont par défaut pas affichées dans les logs et ne sont consultables qu’au travers de la future ; si la future est ignorée, l’exception l’est aussi- Une tâche
scheduleAtFixedRates’arrête silencieusement si une exception se produit
- Une tâche
- Si un littéral numérique commence par 0, il est interprété en octal (
0123→ 83) - Le débogueur appelle
.toString()sur les variables locales ; certaines classes ont untoString()avec effets de bord, ce qui peut modifier le comportement du code pendant le débogage (désactivable dans l’IDE)
Golang
append()réutilise la mémoire si la capacité restante le permet ; un append sur un subslice peut donc écraser jusqu’à la mémoire du parentdefers’exécute au retour de la fonction, pas à la fin d’un bloc de portéedefercapture les variables mutables- À propos de
nil- un nil slice et un empty slice sont différents
- une string ne peut pas être nil, seule la chaîne vide existe
- une nil map peut être lue mais pas modifiée
- comportement particulier de interface nil : si le pointeur de données est nul mais que les informations de type ne le sont pas, ce n’est pas égal à
nil
- Dead wait : il existe de vrais cas de bugs de concurrence en Go
- Il existe de nombreux types de timeout, traités en détail dans net/http
C/C++
- Si vous stockez un pointeur vers un élément de
std::vectorpuis que le vector grandit, une réallocation peut se produire et invalider le pointeur - Un
std::stringcréé à partir d’une chaîne littérale peut être un objet temporaire ; appelerc_str()peut alors être dangereux - Modifier un conteneur pendant son parcours peut invalider les itérateurs
std::removene supprime pas réellement les éléments ; il les réorganise, et il fauterasepour les supprimer- Si un littéral numérique commence par 0, il est traité comme un octal (
0123→ 83) - Undefined behavior (UB) : pendant l’optimisation, un UB peut être transformé librement, il est donc dangereux d’en dépendre
- Accéder à une mémoire non initialisée provoque un UB
- Convertir un
char*en pointeur de struct puis y accéder avant le début de vie de l’objet provoque un UB ; il est recommandé d’initialiser avecmemcpy - Un accès mémoire invalide (pointeur null, etc.) provoque un UB
- Un overflow/underflow entier provoque un UB (pour les types unsigned, un underflow en dessous de 0 est possible)
- Aliasing : si des pointeurs de types différents référencent la même mémoire, la strict aliasing rule peut provoquer un UB
- Exceptions : 1) types en relation d’héritage 2) conversion via
char*,unsigned char*,std::byte*(la conversion inverse n’est pas concernée) - Pour les conversions forcées,
memcpyoustd::bit_castsont recommandés
- Exceptions : 1) types en relation d’héritage 2) conversion via
- Un accès à une mémoire non alignée provoque un UB
- Alignment mémoire
- Un entier 64 bits doit se trouver à une adresse divisible par 8
- Sur ARM, un accès non aligné peut provoquer un crash
- Interpréter directement un buffer d’octets comme une struct peut créer des problèmes d’alignement
- L’alignement peut introduire du padding dans une struct et gaspiller de la mémoire
- Certaines instructions SIMD (AVX, etc.) ne peuvent traiter que des données alignées ; un alignement de 32 octets est généralement nécessaire
Python
- Les arguments par défaut d’une fonction ne sont pas recréés à chaque appel ; la valeur initiale est conservée telle quelle
SQL Databases
-
Gestion de
Nullx = nullne fonctionne pas ; il faut utiliserx is nullNulln’est pas égal à lui-même (commeNaN)- Un index unique autorise les doublons de
Null(sauf dans Microsoft SQL Server) - Dans
select distinct, la manière de traiterNullvarie selon la base de données count(x)etcount(distinct x)ignorent les lignes où la valeur estNull
-
Comportement général
- Les conversions implicites de dates peuvent dépendre du fuseau horaire
- Un
joincomplexe avecdistinctpeut être plus lent qu’une requête imbriquée - Dans MySQL(InnoDB), si un champ texte n’est pas en
utf8mb4, l’insertion d’un caractère UTF-8 sur 4 octets provoque une erreur - MySQL(InnoDB) est par défaut insensible à la casse
- MySQL(InnoDB) autorise les conversions implicites :
select '123abc' + 1;→ 124 - Les gap locks de MySQL(InnoDB) peuvent provoquer des deadlocks
- Dans MySQL(InnoDB), si
group byet les colonnes deselectne correspondent pas, le résultat peut être non déterministe - Dans SQLite, sauf en mode
strict, le type des champs a peu d’importance - Les foreign keys peuvent créer des verrous implicites et provoquer des deadlocks
- Le locking peut, selon la base, rompre l’isolation repeatable read
- Les bases SQL distribuées peuvent ne pas prendre en charge le locking ou avoir un comportement particulier (variable selon la base)
-
Performance / exploitation
- Le problème des requêtes N+1 n’apparaît pas dans les slow query logs, car chaque requête individuelle est rapide
- Les transactions longues peuvent provoquer des problèmes de verrouillage ; il est donc recommandé de les terminer rapidement
- Cas de verrouillage de table entière
- Dans MySQL 8.0+, l’ajout d’un index unique ou d’une foreign key peut généralement se faire de manière concurrente
- Les anciennes versions de MySQL peuvent verrouiller la table entière
- Si
mysqldumpest utilisé sans l’option--single-transaction, un verrou de lecture sur la table entière est pris - Dans PostgreSQL,
create unique indexoualter table ... add foreign keyprovoquent un verrou de lecture sur la table entière- Évitement : utiliser
create unique index concurrently - Pour les foreign keys : utiliser
... not validpuisvalidate constraint
- Évitement : utiliser
-
Requêtes par intervalle
- Intervalles non chevauchants :
- La condition simple
p >= start and p <= endest inefficace (même avec un index composite) - Méthode efficace :
(seul un index sur la colonneselect * from (select ... from ranges where start <= p order by start desc limit 1) where end >= pstartest nécessaire)
- La condition simple
- Intervalles pouvant se chevaucher :
- Inefficace avec un index B-tree classique
- MySQL : index spatial recommandé ; PostgreSQL : GiST recommandé
- Intervalles non chevauchants :
Concurrency and Parallelism
-
volatile
volatilene peut pas remplacer un lock et ne fournit pas l’atomicité- Les données protégées par un lock n’ont pas besoin de
volatile(le lock garantit l’ordre mémoire) - En C/C++ :
volatileempêche seulement certaines optimisations, sans ajouter de memory barrier - En Java : les accès
volatilefournissent un sequentially-consistent ordering (la JVM insère si besoin des memory barriers) - En C# : les accès
volatilefournissent un release-acquire ordering (le CLR insère si besoin des memory barriers) - Peut éviter certaines optimisations erronées liées au réordonnancement des lectures/écritures mémoire
-
Problème TOCTOU (Time-of-check to time-of-use)
-
Gestion des contraintes au niveau applicatif dans une base SQL
- Lorsqu’une contrainte impossible à exprimer avec un simple index unique (par ex. unicité entre deux tables, unicité conditionnelle, unicité sur une période) est imposée par l’application :
- MySQL(InnoDB) : au niveau repeatable read, faire
select ... for updatepuisinsert, et si la colonne unique est indexée, cela fonctionne grâce aux gap locks (mais les gap locks peuvent provoquer des deadlocks sous forte charge → détection de deadlock et retry nécessaires) - PostgreSQL : au niveau repeatable read, cette même logique est insuffisante en situation de concurrence (problème de write skew)
- Solutions :
- utiliser le niveau d’isolation serializable
- utiliser des contraintes de base de données plutôt que l’application
- unicité conditionnelle → partial unique index
- unicité entre deux tables → insérer les données dupliquées dans une table séparée avec un unique index
- exclusivité sur une période → range type + exclude constraint
- Solutions :
- MySQL(InnoDB) : au niveau repeatable read, faire
- Lorsqu’une contrainte impossible à exprimer avec un simple index unique (par ex. unicité entre deux tables, unicité conditionnelle, unicité sur une période) est imposée par l’application :
-
Comptage de références atomique
- Avec
Arc,shared_ptret similaires, si de nombreux threads modifient fréquemment le même compteur, les performances se dégradent
- Avec
-
Read-write lock
- Certaines implémentations ne prennent pas en charge l’upgrade d’un read lock en write lock
- Tenter de prendre un write lock tout en détenant un read lock peut provoquer un deadlock
Common in many languages
- L’oubli des vérifications Null/None/nil est une cause fréquente d’erreurs
- Modifier un conteneur pendant une boucle peut provoquer une condition de concurrence sur les données en mono-thread
- Erreur de partage de données mutables : ex. en Python,
[[0] * 10] * 10ne crée pas correctement un tableau 2D (low + high) / 2peut provoquer un overflow → la méthode sûre estlow + (high - low) / 2- Évaluation courte (short circuit) :
a() || b()n’exécute pas b si a vaut true,a() && b()n’exécute pas b si a vaut false - Par défaut, le profiler n’inclut que le temps CPU → les attentes DB, etc., n’apparaissent pas dans le flamegraph, ce qui peut induire en erreur
- Le dialecte des expressions régulières diffère selon les langages → une regex qui fonctionne en JS peut ne pas fonctionner en Java
Linux and bash
- Après un changement de répertoire,
pwdpeut afficher le chemin d’origine ; pour le chemin réel, utiliserpwd -P cmd > file 2>&1→ stdout+stderr vont tous deux dans le fichier,cmd 2>&1 > file→ seul stdout va dans le fichier, stderr reste inchangé- Les noms de fichiers sont sensibles à la casse (contrairement à Windows)
- Les exécutables disposent d’un système de capabilities (vérifiable avec
getcap) - Danger des variables non définies : si
DIRn’est pas défini,rm -rf $DIR/risque d’exécuterrm -rf /→ on peut s’en prémunir avecset -u - Application de l’environnement : pour appliquer un script au shell courant, utiliser
source script.sh→ pour l’appliquer de façon permanente, l’ajouter à~/.bashrc - Bash met les commandes en cache : si un fichier est déplacé dans
$PATH, une erreurENOENTpeut se produire → rafraîchir le cache avechash -r - Quand une variable non quotée est utilisée, les retours à la ligne sont traités comme des espaces
set -e: quitte immédiatement en cas d’erreur dans un script, mais ne fonctionne pas à l’intérieur des conditions (||,&&,if)- Conflit entre livenessProbe K8s et débogueur : un débogueur à points d’arrêt peut stopper toute l’application, empêchant les réponses aux health checks → le Pod peut être tué
React
- Modifier directement le state dans le code de rendu
- Utiliser un Hook dans un if/une boucle → violation des règles
- Oublier des valeurs nécessaires dans le dependency array de
useEffect - Oublier le code de nettoyage (clean up) dans
useEffect - Piège des closures : des bugs apparaissent à cause de la capture d’un state obsolète
- Modifier les données au mauvais endroit → composant impur
- Oublier d’utiliser
useCallback→ provoque des rerenders inutiles - Passer une valeur non mémorisée à un composant mémorisé annule l’optimisation de memo
Git
-
Rebase réécrit l’historique
- après un rebase, un push normal entre en conflit → il faut absolument faire un force push
- si l’historique de la branche distante change, utiliser aussi
--rebasepour le pull --force-with-leasepeut, dans certains cas, éviter d’écraser les commits d’un autre développeur, mais si on fait seulement fetch sans pull, cette protection ne fonctionne pas
-
Problème du revert de merge
- un revert de merge a un effet incomplet → si on merge à nouveau la même branche, il n’y a aucun changement
- solution : faire le revert du revert, ou employer une méthode propre (backup → reset → cherry-pick → force push)
-
Points d’attention liés à GitHub
- même si un secret comme une clé API est écrasé par un force push après commit, GitHub en conserve une trace
- si B est un fork privé du dépôt privé A, et que A devient public, le contenu de B devient lui aussi public (et peut rester accessible même après suppression)
-
git stash pop: en cas de conflit, le stash n’est pas supprimé -
.DS_Storeest créé automatiquement par macOS → il est recommandé d’ajouter**/.DS_Storeà.gitignore
Networking
- Certains routeurs et pare-feu coupent silencieusement les connexions TCP inactives → cela peut invalider les pools de connexions des clients HTTP et DB → solution : configurer TCP keepalive
- Le résultat de
tracerouteest peu fiable → selon les cas,tcptraceroutepeut être plus utile - Le TCP slow start peut augmenter la latence → on peut y remédier en désactivant
tcp_slow_start_after_idle - Problème de sticky packets TCP : l’algorithme de Nagle retarde l’envoi des paquets → on peut y remédier en activant
TCP_NODELAY - Quand un backend est placé derrière Nginx, il faut configurer la réutilisation des connexions → sinon, en forte charge, l’épuisement des ports internes peut provoquer des échecs de connexion
- Nginx bufferise les paquets par défaut → cela peut retarder les SSE (EventSource)
- Le standard HTTP n’interdit pas le body des requêtes GET et DELETE → certains l’utilisent, mais beaucoup de bibliothèques et serveurs ne le prennent pas en charge
- Il est possible d’héberger plusieurs sites web sur une seule IP → la distinction est assurée par l’en-tête HTTP
Hostet le SNI de TLS → certains sites ne sont donc pas accessibles via une simple connexion par IP - CORS : lors d’une requête vers une autre origin, le navigateur bloque l’accès à la réponse → le serveur doit définir l’en-tête
Access-Control-Allow-Origin- des réglages supplémentaires sont nécessaires si les cookies doivent être transmis
- si le frontend et le backend utilisent le même domaine et le même port, il n’y a pas de problème de CORS
Other
-
Points d’attention YAML
- YAML est sensible aux espaces →
key:valueest incorrect,key: valueest correct - le code pays
NO, écrit sans guillemets, peut être interprété commefalse - un hash de commit Git écrit sans guillemets peut être converti en nombre
- YAML est sensible aux espaces →
-
Problèmes de CSV avec Excel
- Excel effectue des conversions automatiques à l’ouverture d’un CSV
- conversion de date :
1/2,1-2→2-Jan - conversion imprécise des grands nombres :
12345678901234567890→12345678901234500000
- conversion de date :
- la cause est qu’Excel traite les nombres en floating point en interne
- ce problème a déjà conduit à une modification erronée du nom de gène SEPT1
- Excel effectue des conversions automatiques à l’ouverture d’un CSV
Aucun commentaire pour le moment.