Des guides pratiques et perennes pour les developpeurs. Chacun s’appuie sur de vraies commandes et des exemples concrets, et dit clairement quand ne pas utiliser l’outil traite.
Tout est ci-dessous, du plus recent au plus ancien.
Des guides pratiques et perennes pour les developpeurs. Chacun s’appuie sur de vraies commandes et des exemples concrets, et dit clairement quand ne pas utiliser l’outil traite.
Tout est ci-dessous, du plus recent au plus ancien.
Exécutez 0.1 + 0.2 dans un shell Python et vous n’obtenez pas 0.3. Vous obtenez 0.30000000000000004. Essayez en JavaScript, Java, Go, C ou Rust et vous retrouvez la même traîne de dix-sept chiffres. Chacun de ces langages fait exactement ce que lui impose le matériel. Un nombre qui demanderait une infinité de chiffres binaires est compressé dans 64 bits, et quelque chose doit céder. Pourquoi 0.1 ne peut pas être stocké exactement en binaire Les ordinateurs stockent les nombres à virgule flottante en base 2. En base 2, la fraction 1/10 a un développement périodique, tout comme 1/3 se répète indéfiniment en base 10 (0.3333...). Développé en détail, 0.1 en binaire commence ainsi : ...
Un endpoint de login vous renvoie un JWT, et vous avez trois endroits où le stocker : un cookie, localStorage, ou sessionStorage. Faites le mauvais choix et soit une faille XSS embarque le token avec elle, soit le token n’arrive jamais jusqu’à votre API. Les trois stockent des chaînes de caractères dans le navigateur. Ce qui change, c’est qui peut les lire, combien de temps elles survivent, et si le serveur les voit un jour. ...
Une recherche dans un dictionnaire Python prend environ 100 nanosecondes, que le dictionnaire contienne 1 000 clés ou 1 000 000. Une double boucle qui cherche des doublons dans une liste prend une demi-milliseconde sur 200 éléments et 136 millisecondes sur 3 200. Seize fois l’entrée, presque 280 fois l’attente. Même machine, même Python. La notation Big O est le nom de cette différence. Ce que mesure la notation Big O Big O décrit comment le temps d’exécution (ou l’utilisation de la mémoire) d’un morceau de code croît quand l’entrée grandit. Ce n’est pas une mesure au chronomètre, et peu importe que votre ordinateur soit rapide ou lent. Ce qui compte, c’est la forme de la courbe de croissance : quand vous doublez l’entrée, le temps double-t-il, quadruple-t-il, ou bouge-t-il à peine ? ...
Lancez git reset --hard sur un commit que votre équipe a déjà récupéré par pull, et votre historique local se met à diverger du leur. Lancez git revert sur une simple faute de frappe que vous n’avez pas encore poussée, et vous ajoutez un commit inutile au log. Git propose quatre commandes pour annuler un changement, restore, reset, commit --amend et revert, et elles ne sont pas interchangeables. Choisissez la mauvaise et elle ne fait rien, ou elle fait bien plus que ce que vous vouliez. ...
Un JOIN mal écrit ne lève pas d’erreur. Il s’exécute, renvoie un résultat, et les lignes sont fausses : des clients manquants, des totaux gonflés, des enregistrements orphelins invisibles. La plupart du temps, la requête a obtenu exactement ce qu’elle demandait, et son auteur a choisi le mauvais type de join, ou filtré au mauvais endroit. Un join combine les lignes de deux tables selon une condition que vous écrivez. Les lignes qui survivent dépendent du type de join, et les six types ci-dessous donnent six réponses différentes à partir des mêmes deux tables. ...
Voici une classe que vous ne pouvez pas tester unitairement sans une base de données active et un serveur SMTP opérationnel : 1 2 3 4 5 6 7 8 9 10 11 public class OrderService { private readonly SqlOrderRepository _repository = new SqlOrderRepository("Server=prod-db;Database=Orders;..."); private readonly SmtpEmailSender _emailSender = new SmtpEmailSender("smtp.company.com"); public void PlaceOrder(Order order) { _repository.Save(order); _emailSender.Send(order.CustomerEmail, "Order confirmed"); } } OrderService construit lui-même ses SqlOrderRepository et SmtpEmailSender avec new, chaîne de connexion comprise. Chaque test qui touche à PlaceOrder a besoin d’une vraie base de données Orders et d’un vrai serveur de mail, sinon il échoue avant même que votre assertion s’exécute. La logique que vous voulez tester tient en deux lignes : enregistrer la commande, envoyer la confirmation. Elle est soudée à deux classes concrètes que vous ne pouvez pas remplacer. ...
Installez deux projets Python sur la même machine et le second peut casser le premier. L’un a besoin de requests==2.28, l’autre de requests==2.32, et pip n’a qu’un seul répertoire site-packages global dans lequel écrire. La dernière installation gagne, silencieusement. Vous le découvrez quand l’autre projet commence à lever des erreurs qui n’ont rien à voir avec le code que vous venez de modifier. Un environnement virtuel donne à chaque projet son propre site-packages. Rien de global n’est touché, et deux projets peuvent dépendre de versions incompatibles de la même bibliothèque sans que l’un remarque l’autre. ...
Une fonction peut avoir 100 % de couverture de tests unitaires, et la page qui l’appelle peut quand même renvoyer une 500 en production. Ce n’est pas une contradiction. Les tests unitaires, d’intégration et end-to-end vérifient des choses différentes, et une suite chargée sur l’un et légère sur l’autre présente un trou précis et prévisible. Ce que vérifient les tests unitaires, d’intégration et end-to-end Prenez une fonctionnalité d’inscription : une fonction valide la saisie, écrit une ligne dans une base de données et envoie un email de bienvenue. Trois tests peuvent la couvrir, et chacun répond à une question différente. ...
Exécutez ceci dans Node ou dans la console d’un navigateur : 1 2 3 4 console.log("1"); setTimeout(() => console.log("2"), 0); Promise.resolve().then(() => console.log("3")); console.log("4"); Le résultat est 1 4 3 2. Un setTimeout avec un délai de 0ms s’exécute quand même après le callback de la promise, et les deux attendent que chaque ligne de code synchrone en dessous se termine. async/await repose sur cet ordre, ce n’est pas un mécanisme différent. La plupart des comportements surprenants du JavaScript asynchrone viennent du fait qu’on écrit await comme s’il mettait en pause tout le programme, alors qu’il ne met en pause que la fonction dans laquelle il se trouve. ...
Sur une table d’un million de lignes, la même SELECT peut prendre cinquante millisecondes, ou nettement moins d’une seule milliseconde. Toute la différence tient à un choix : la base de données lit chaque ligne pour trouver celles que vous avez demandées, ou elle saute directement dessus. Un index est ce qui lui permet de sauter, et vous le payez à chaque écriture. Concrètement, un index est une seconde copie triée d’une ou plusieurs colonnes, stockée à côté de la table et mise à jour automatiquement à chaque modification de la table. La base de données l’utilise pour atteindre les lignes correspondantes sans toucher au reste. ...