Web appOpen in Telegram
CCoding Learn

Coding Learn

@metacodelearn · channel · indexed since 2026-08-26
5 083subscribers
226average post reach
4.4%ER — reach to subscribers
15posts in 30 days
C
Coding Learn
⚡ ASTUCE Rust — OWNERSHIP : LA RÈGLE QUI SAUVE DES VIES 1️⃣ Le principe fondamental : une seule variable possède la donnée let s1 = String::from("hello"); let s2 = s1; // s1 est "moved" vers s2 println!("{}", s1); // ❌ Erreur : s1 n'est plus valide 2️⃣ Pour dupliquer vraiment : clone() let s1 = String::from("hello"); let s2 = s1.clone(); // copie profonde println!("{} {}", s1, s2); // ✅ les deux valides 3️⃣ Le borrow checker en action — références immuables vs mutables fn longest(a: &str, b: &str) -> &str { if a.len() > b.len() { a } else { b } } let r1 = &mut String::from("hi"); let r2 = &r1; // ❌ une mutable + une immuable = interdit println!("{} {}", r1, r2); // OK : plusieurs immuables OU une seule mutable let r1 = &String::from("hi"); let r2 = &r1; // ✅ plusieurs & partagées ✅ Pas de garbage collector, pas de data races à la compilation. Le compilateur est ton meilleur QA. 💾 Enregistre ce post pour ne pas l'oublier. #Rust #RustLang #WebDev #DevTips #MetaCodeLearn
420 ·
Coding Learn
⚡ ASTUCE JavaScript — ARRAY.FROM : LE COUTEAU SUISSE OUBLIÉ 1️⃣ Transformer un objet en array proprement // Le piège : length-only ne suffit pas const obj = { 0: 'a', 1: 'b', length: 2 }; [...obj]; // ❌ TypeError: object is not iterable // La solution : Array.from avec mapping direct const arr = Array.from(obj, (v, i) => `item-{i}:{v}`); // ['item-0:a', 'item-1:b'] 2️⃣ Générer une séquence numérique (remplace les boucles) // 0..4 en une ligne const range = Array.from({ length: 5 }, (_, i) => i); // [0, 1, 2, 3, 4] // Avec une fonction const squares = Array.from({ length: 5 }, (_, i) => i * i); // [0, 1, 4, 9, 16] 3️⃣ Bonus : Array.fromAsync pour itérer sur des promesses const urls = ['/api/users', '/api/posts', '/api/comments']; const results = await Promise.all( urls.map(url => fetch(url).then(r => r.json())) ); // Ou plus élégant avec Array.fromAsync (ES2024) const responses = await Array.fromAsync( urls.map(url => fetch(url).then(r => r.json())) ); ✅ Plus concis que les boucles, plus lisible que les hacks. Un outil à toujours avoir sous la main. 💾 Enregistre ce post pour ne pas l'oublier. #JavaScript #JavaScript #WebDev #DevTips #MetaCodeLearn
320 ·
C
⚡ ASTUCE CSS — CONTAINER QUERIES : LE RESPONSIVE ENFIN LOGIQUE 1️⃣ Le problème des media queries classiques /* On se base sur la taille de l'écran */ /* Mais le composant est peut-être dans une sidebar */ .card { display: flex; flex-direction: column; } @media (min-width: 768px) { .card { flex-direction: row; } } 2️⃣ La révolution : @container (CSS Containment Level 3) .card-wrapper { container-type: inline-size; container-name: card; } @container card (min-width: 400px) { .card { flex-direction: row; } } @container card (min-width: 600px) { .card { font-size: 1.2rem; } } 3️⃣ Bonus : style queries (Chrome 111+, Safari 18+) @container card style(--theme: dark) { .card { background: #1a1a1a; color: #fff; } } /* On peut même lier un custom property */ .card-wrapper { --theme: light; } .dark-mode .card-wrapper { --theme: dark; } ✅ Les composants s'adaptent à leur conteneur, pas à l'écran. Design systems enfin réutilisables. 💾 Enregistre ce post pour ne pas l'oublier. #CSS #CSS #Frontend #WebDev #DevTips #MetaCodeLearn
1 · 303 ·
Coding Learn
⚡ ASTUCE TypeScript — SATISFIES : L'OPÉRATEUR QUI CHANGE LA DONNE 1️⃣ Le problème classique : typage strict vs inférence // ❌ On perd l'inférence des littéraux type Config = { api: string; debug: boolean; features: string[]; }; const config: Config = { api: 'https://api.example.com', debug: false, features: ['auth', 'cache'] }; config.features.map(f => f.toUpperCase()); // OK mais features est string[] 2️⃣ La solution : satisfies (TS 4.9+) // ✅ On valide la forme, on garde l'inférence const config = { api: 'https://api.example.com', debug: false, features: ['auth', 'cache'] } satisfies Config; config.features.map(f => f.toUpperCase()); // ✅ features reste ('auth' | 'cache')[] // Erreur immédiate si une prop est manquante 3️⃣ Bonus : as const vs satisfies // as const : fige tout en readonly literal const a = { x: 1, y: 'hello' } as const; // type : { readonly x: 1, readonly y: 'hello' } // satisfies : valide sans transformer const b = { x: 1, y: 'hello' } satisfies { x: number, y: string }; // type : { x: number, y: string } — toujours flexible ✅ Validates without losing the original type. Best of both worlds. 💾 Enregistre ce post pour ne pas l'oublier. #TypeScript #TypeScript #WebDev #DevTips #MetaCodeLearn
313 ·
C
⚡ ASTUCE Python — WALRUS OPERATOR := : ASSIGNER SANS POLLUER 1️⃣ Le pattern classique : assigner puis tester # ❌ On duplique l'appel coûteux data = fetch_data() if data: process(data) 2️⃣ La solution propre : := (Python 3.8+) # ✅ Assignation dans l'expression if data := fetch_data(): process(data) # Encore plus lisible dans une boucle while (line := file.readline().strip()): process_line(line) 3️⃣ Bonus : dans les list comprehensions # Avant : deux passes sur la liste results = [compute(x) for x in items if compute(x) is not None] # Avec walrus : une seule passe results = [y for x in items if (y := compute(x)) is not None] # Lecture de fichier ligne par ligne total = 0 with open('data.txt') as f: [total := total + int(n) for line in f if (n := line.strip()).isdigit()] ✅ Moins de répétitions, moins d'appels redondants, code plus expressif. 💾 Enregistre ce post pour ne pas l'oublier. #Python #Python #WebDev #DevTips #MetaCodeLearn
295 ·
Coding Learn
⚡ ASTUCE JavaScript — STRUCTUREDCLONE : COPIER PROFOND EN 1 LIGNE 1️⃣ Le piège classique : la fausse copie // ❌ Référence partagée, pas une copie const original = { user: { name: 'Aliou', score: 10 } }; const copy = { ...original }; copy.user.score = 99; console.log(original.user.score); // 99 ! mutation inattendue 2️⃣ La solution native : structuredClone() (Node 17+, tous navigateurs modernes) // ✅ Copie profonde native, zéro dépendance const original = { user: { name: 'Aliou', score: 10 } }; const copy = structuredClone(original); copy.user.score = 99; console.log(original.user.score); // 10 ✅ intact console.log(copy.user.score); // 99 ✅ vraiment copié # Supporte : Date, Map, Set, ArrayBuffer, RegExp... const data = structuredClone({ date: new Date(), tags: new Set(['js', 'web']), items: [1, 2, 3] }); 3️⃣ Bonus : l'astuce de l'objet gelé pour forcer l'immutabilité const state = Object.freeze({ user: Object.freeze({ name: 'Aliou' }) }; // Lance TypeError en mode strict, échoue en sloppy state.user.name = 'Bob'; // silencieux en sloppy, erreur en strict ✅ Native, rapide, et plus safe que JSON.parse(JSON.stringify() qui perd les Dates et les undefined. 💾 Enregistre ce post pour ne pas l'oublier. #JavaScript #JavaScript #WebDev #DevTips #MetaCodeLearn
279 ·
C
⚡ ASTUCE SQL — CTE RÉCURSIVES : TRAVERSER DES ARBRES EN SQL 1️⃣ Le problème : récupérer toute une hiérarchie d'un coup -- Sans récursion : impossible en une seule requête -- Tu faisais du Python + plusieurs SELECT ? C'était ton cas ? 2️⃣ La solution : WITH RECURSIVE -- Parcourt un arbre parent → enfants WITH RECURSIVE org_tree AS ( -- Ancrage : les racines SELECT id, name, parent_id, 1 as level FROM employees WHERE parent_id IS NULL UNION ALL -- Récursion : les enfants SELECT e.id, e.name, e.parent_id, t.level + 1 FROM employees e INNER JOIN org_tree t ON e.parent_id = t.id ) SELECT * FROM org_tree ORDER BY level, name; 3️⃣ Bonus : générer des séries de nombres à la volée -- Génère 1..100 sans table temporaire WITH RECURSIVE nums AS ( SELECT 1 as n UNION ALL SELECT n + 1 FROM nums WHERE n < 100 ) SELECT n FROM nums; -- MySQL nécessite SET cte_max_recursion_depth = 1000; -- PostgreSQL et SQLite gèrent par défaut Note : pense à limiter la récursion sur MySQL. Requête unique, zéro code applicatif, performances SQL natives. 💾 Enregistre ce post pour ne pas l'oublier. #SQL #PostgreSQL #WebDev #DevTips #MetaCodeLearn
289 ·
Coding Learn
⚡ ASTUCE React — USEDEFERREDVALUE : INPUT FLUIDE SUR GROSSE LISTE 1️⃣ Le problème : input qui lag sur du gros volume function SearchList({ query }) { // ❌ À chaque frappe, re-filtrage bloquant de 10k items const filtered = hugeList.filter(item => item.name.includes(query) ); return filtered.map(renderItem); } 2️⃣ La solution : useDeferredValue (React 18+) import { useDeferredValue, useMemo } from 'react'; function SearchList({ query }) { const deferredQuery = useDeferredValue(query); // ✅ Le filtrage passe en priorité basse const filtered = useMemo( () => hugeList.filter(item => item.name.includes(deferredQuery) ), [deferredQuery] ); const isStale = query !== deferredQuery; return ( <ul style={{ opacity: isStale ? 0.7 : 1 }}> {filtered.map(renderItem)} </ul> ); } 3️⃣ Bonus : useTransition pour les états plus larges import { useTransition } from 'react'; function App() { const [isPending, startTransition] = useTransition(); const [query, setQuery] = useState(''); return ( <> <input value={query} onChange={(e) => { setQuery(e.target.value); // urgent : la frappe startTransition(() => { setExpensiveFilter(e.target.value); // peut attendre }); }} /> {isPending && <Spinner />} </> ); } ✅ Input toujours réactif, liste filtrée sans bloquer l'UI. 💾 Enregistre ce post pour ne pas l'oublier. #React #React #WebDev #DevTips #MetaCodeLearn
301 ·
C
⚡ ASTUCE Go — ERRORS.IS & ERRORS.AS : LE CHAINAGE D'ERREURS MODERNE 1️⃣ L'ancien problème : la perte de contexte // ❌ fmt.Errorf avec %v perd le type de l'erreur if err != nil { return fmt.Errorf("failed to open file: %v", err) } // Impossible de savoir si c'est os.ErrNotExist plus tard if errors.Is(err, os.ErrNotExist) { // toujours false, on a perdu l'info } 2️⃣ La solution : fmt.Errorf avec %w (Go 1.13+) // ✅ %w wrappe l'erreur, garde son identité if err != nil { return fmt.Errorf("failed to open file: %w", err) } // Maintenant errors.Is fonctionne ! if errors.Is(err, os.ErrNotExist) { return c.SendStatus(404) } // errors.As permet d'extraire le type var pathErr *os.PathError if errors.As(err, &pathErr) { log.Printf("path: %s, op: %s", pathErr.Path, pathErr.Op) } 3️⃣ Bonus : créer ses propres erreurs wrappables type ValidationError struct { Field string Reason string } func (e *ValidationError) Error() string { return fmt.Sprintf("%s: %s", e.Field, e.Reason) } // Dans le caller var verr *ValidationError if errors.As(err, &verr) { return JSON{"field": verr.Field, "issue": verr.Reason} } ✅ Contexte préservé, debugging simplifié, gestion d'erreurs propre. 💾 Enregistre ce post pour ne pas l'oublier. #Go #Go #Golang #WebDev #DevTips #MetaCodeLearn
375 ·
Coding Learn
⚡ ASTUCE Python — LE WALRUS OPERATOR := : ASSIGNER EN PLEINE EXPRESSION 1️⃣ Le problème : la double computation # ❌ On appelle len() deux fois, ou on crée une variable inutile data = get_data() if len(data) > 10: print(f"Processing {len(data)} items") process(data) 2️⃣ La solution : := (Python 3.8+) # ✅ Walrus : assigne ET retourne la valeur en une expression if (n := len(get_data())) > 10: print(f"Processing {n} items") process(data) 3️⃣ Bonus : dans les compréhensions et les regex import re # Filtrer + extraire en une passe matches = [m.group(1) for line in lines if (m := re.search(r'@(\w+)', line))] # Lis une ligne tant qu'elle n'est pas vide (avec := dans while) while (line := file.readline().strip()) and line != 'END': process(line) # Avant : il fallait soit une variable avant la boucle, # soit un break, soit une boucle infinie avec break ⚠️ Attention : n'en abuse pas. Si le := rend le code moins lisible, ne l'utilise pas. C'est un outil, pas une religion. ✅ Moins de variables, moins de calls, plus de clarté... quand c'est bien utilisé. 💾 Enregistre ce post pour ne pas l'oublier. #Python #Python #WebDev #DevTips #MetaCodeLearn
318 ·
C
⚡ ASTUCE TypeScript — SATISFIES : TYPER SANS PERDRE L'INFÉRENCE 1️⃣ Le problème : l'annotation ": Type" écrase l'inférence // ❌ On perd le littéral "primary" / "secondary" const config: Record<string, string> = { theme: "primary", size: "large" }; config.theme.toUpperCase(); // OK, mais on perd l'autocomplétion // config.theme.startsWith("p") // ne marche pas : theme est "string" 2️⃣ La solution : satisfies (TS 4.9+) // ✅ On valide la forme, MAIS on garde l'inférence littérale const config = { theme: "primary", size: "large" } satisfies Record<string, string>; config.theme.toUpperCase(); // OK config.theme.startsWith("p"); // OK : theme est "primary", pas string config.theme; // type: "primary" (literal!) 3️⃣ Bonus : config + autocomplete, le combo parfait type Theme = "primary" | "secondary" | "danger"; const themes = { primary: "#000", secondary: "#666", danger: "#f00" } satisfies Record<Theme, string>; // themes.primary // type: string (littéral du mapping) const t: Theme = "primary"; console.log(themes[t]); // OK, garanti de l'exister ✅ Type-checking strict, inférence préservée, autocomplétion maximale. 💾 Enregistre ce post pour ne pas l'oublier. #TypeScript #TypeScript #WebDev #DevTips #MetaCodeLearn
299 ·
Coding Learn
⚡ ASTUCE JavaScript — STRUCTUREDCLONE : COPIER EN PROFONDEUR, PROPREMENT 1️⃣ Le problème : la shallow copy et le piège de la mutation // ❌ {...original} ne copie que le 1er niveau const user = { name: "Aliou", tags: ["dev", "crypto"] }; const clone = { ...user }; clone.tags.push("design"); console.log(user.tags); // ["dev", "crypto", "design"] 💀 // JSON.parse(JSON.stringify(x)) perd les fonctions, Date, Map, etc. 2️⃣ La solution : structuredClone() (natif depuis 2022) // ✅ Copie profonde, native, performante const user = { name: "Aliou", tags: ["dev", "crypto"], meta: { lastLogin: new Date(), level: 42 } }; const clone = structuredClone(user); clone.tags.push("design"); clone.meta.level = 99; console.log(user.tags); // ["dev", "crypto"] ✅ console.log(user.meta.level); // 42 ✅ 3️⃣ Bonus : disponible aussi pour les transfert d'objets // 🎯 Bonus : dans un postMessage entre fenêtres/Web Workers worker.postMessage(structuredClone(hugeState)); // 🎯 Bonus : copie profonde d'un FormData const formCopy = structuredClone(originalFormData); // 🎯 Bonus : snapshot d'un état avant mutation (Redux-like) const prevState = structuredClone(currentState); updateState(newPartial); if (error) rollbackTo(prevState); ⚠️ Limites connues : ne copie pas les fonctions (lance DataCloneError), ni les Symbols en clés. Pour 99% des cas (state, API responses, undo/redo), c'est parfait. ✅ Plus de lodash.clonedeep, plus de JSON hack. Une fonction native, rapide, moderne. 💾 Enregistre ce post pour ne pas l'oublier. #JavaScript #JavaScript #WebDev #DevTips #MetaCodeLearn
1 · 329 ·
C
⚡ ASTUCE Bash — PROCESS SUBSTITUTION : COMPARER SANS FICHIERS TEMPORAIRES 1️⃣ Le problème : comparer deux sorties de commandes # ❌ Méthode brute : créer des fichiers temporaires ps aux > /tmp/before.txt sleep 5 ps aux > /tmp/after.txt diff /tmp/before.txt /tmp/after.txt rm /tmp/before.txt /tmp/after.txt # Beurk, ça pollue /tmp et c'est lent 2️⃣ La solution : process substitution <( ) # ✅ Une seule ligne, pas de fichier, pas de pollution diff <(ps aux) <(sleep 5; ps aux) # ✅ Lire une commande comme un fichier while read line; do echo "Ligne : $line" done < <(ls -la | head -5) # ✅ Avec grep pour comparer deux snapshots comm -23 \ <(curl -s https://api.example.com/v1/users | jq -r '.[].email' | sort) \ <(curl -s https://api.example.com/v2/users | jq -r '.[].email' | sort) # → liste les utilisateurs supprimés entre v1 et v2 3️⃣ Bonus : combiner avec tee pour le debug # 🎯 Bonus : pipe et process substitution ensemble mkfifo /tmp/myfifo 2>/dev/null || true my_function() { echo "out1" echo "err1" >&2 } my_function > <(tee /tmp/out.log) 2> <(tee /tmp/err.log >&2) # 🎯 Bonus : commander les sources de données paste <(echo "Aliou") <(echo "Mira") <(echo "Code") # → Aliou Mira Code ⚠️ Limites : ne marche que sur bash/zsh (pas POSIX sh), crée quand même un FD temporaire (/dev/fd/63), certains vieux outils ne le supportent pas. ✅ Plus rapide, plus propre, plus lisible. Le genre de truc qui transforme un script de 30 lignes en 5. 💾 Enregistre ce post pour ne pas l'oublier. #Bash #Bash #Linux #DevTips #MetaCodeLearn
341 ·
Coding Learn
⚡ ASTUCE SQL — ROW_NUMBER() VS RANK() VS DENSE_RANK() : LA DIFFÉRENCE QUI COMPTE 1️⃣ Le problème : 3 fonctions, 3 comportements différents -- Imaginons des scores : 100, 95, 95, 80 -- ❌ Confusion classique : utiliser LIMIT sans gérer les ex-aequo SELECT user, score FROM scores ORDER BY score DESC LIMIT 3; -- → 100, 95, 95 — mais tu n'as aucune idée qu'il y a un "3e rang partagé" 2️⃣ La solution : les 3 window functions -- Données de test WITH scores AS ( SELECT 'Aliou' AS u, 100 AS s UNION ALL SELECT 'Mira', 95 UNION ALL SELECT 'Code', 95 UNION ALL SELECT 'Kai', 80 ) SELECT u, s, ROW_NUMBER() OVER (ORDER BY s DESC) AS row_num, RANK() OVER (ORDER BY s DESC) AS rank, DENSE_RANK() OVER (ORDER BY s DESC) AS dense_rank FROM scores; Résultat : u | s | row_num | rank | dense_rank ---------+-----+---------+------+----------- Aliou | 100 | 1 | 1 | 1 Mira | 95 | 2 | 2 | 2 Code | 95 | 3 | 2 | 2 ← rang partagé Kai | 80 | 4 | 4 | 3 ← RANK saute, DENSE non 3️⃣ Cas d'usage : top N par groupe -- 🎯 Top 1 utilisateur par pays (avec ex-aequo) WITH ranked AS ( SELECT user_name, country, score, ROW_NUMBER() OVER (PARTITION BY country ORDER BY score DESC) AS rn FROM users ) SELECT * FROM ranked WHERE rn = 1; -- 🎯 DENSE_RANK : leaderboard sans "trous" de classement SELECT user_name, score, DENSE_RANK() OVER (ORDER BY score DESC) AS position FROM leaderboard; ⚠️ La règle simple : • ROW_NUMBER → toujours unique (pagination, dédoublonnage) • RANK → "vrai" rang avec sauts (compétition officielle, 1er, 2e, 2e, 4e) • DENSE_RANK → rang compact sans sauts (leaderboard utilisateur, 1er, 2e, 2e, 3e) ✅ La fonction qui te manquait pour arrêter de galérer avec des sous-requêtes imbriquées. 💾 Enregistre ce post pour ne pas l'oublier. #SQL #SQL #PostgreSQL #Database #DevTips #MetaCodeLearn
1 · 484 ·
C
⚡ ASTUCE React — USEDEFERREDVALUE : FLUIDITÉ D'UI SANS DÉGRADER L'UX 1️⃣ Le problème : la recherche qui lag à chaque frappe // ❌ La liste se recalcule à chaque touche tapée function SearchList({ query }) { const results = heavyFilter(items, query); // filtre 10k items return <List data={results} />; } // L'input se fige dès qu'on tape vite → input laggy // L'utilisateur rale, ferme l'onglet 2️⃣ La solution : useDeferredValue (React 18+) import { useDeferredValue, useState } from 'react'; function SearchList() { const [query, setQuery] = useState(''); const deferredQuery = useDeferredValue(query); // 👈 la clé // query : MAJ instantanée (l'input reste fluide) // deferredQuery : MAJ différée (le filtre peut prendre son temps) const results = heavyFilter(items, deferredQuery); return ( <> <input value={query} onChange={e => setQuery(e.target.value)} /> <List data={results} isStale={query !== deferredQuery} /> <> ); } 3️⃣ Bonus : isPending pour le feedback visuel import { useDeferredValue, useState, useTransition } from 'react'; function SearchList() { const [query, setQuery] = useState(''); const [isPending, startTransition] = useTransition(); const handleChange = (e) => { startTransition(() => { setQuery(e.target.value); // MAJ non-urgente }); }; return ( <> <input onChange={handleChange} /> {isPending && <Spinner />} {/* feedback subtil */} <List data={heavyFilter(items, query)} /> </> ); } ⚠️ Différence avec debounce : • debounce : attend X ms, puis update → input potentiellement figé entre les frappes • useDeferredValue : l'input update toujours, le render lourd est en pause → UX perçue bien meilleure ✅ Le hook que t'aurais aimé connaître il y a 2 ans. Utilise-le sur TOUT ce qui est potentiellement lourd : filtres, tris, listes virtualisées, autocompletes. 💾 Enregistre ce post pour ne pas l'oublier. #React #React #WebDev #DevTips #MetaCodeLearn
1 · 619 ·
Coding Learn
💡 LE SAVIEZ-VOUS — Le bug à 370 millions de dollars Le 4 juin 1996, la fusée Ariane 5 décolle pour son premier vol (Vol 501). Tout se passe bien… jusqu'à T+37 secondes. Un capteur d'accélération transmet sa mesure (64-bit float) à l'ordinateur de bord qui la convertit en entier signé 16 bits. Problème : la valeur d'Ariane 5 dépasse largement la capacité d'un int16. Overflow → exception → autopilote se met en mode secours → la fusée se retourne à 90° → autodestruction. Bilan : 370 millions de dollars envolés en 37 secondes. Cause : un bout de code ré-utilisé d'Ariane 4 sans revalidation, parce que personne n'avait documenté l'hypothèse que la mesure resterait dans une certaine plage. ✅ Leçon : un overflow silencieux, c'est pas un détail. C'est un missile. 💾 Enregistre ce post pour ne pas l'oublier. #DevHistory #BugFamous #Ariane5 #Programming #MetaCodeLearn
220 ·
📱 ANDROID — Pourquoi ton app "perd la mémoire" quand tu reviens dessus T'as déjà ouvert une app, switché sur WhatsApp, répondu à un message, et quand tu reviens sur l'app, elle est en mode "Loading… je retrouve mes petits" ? C'est pas un bug. C'est le lifecycle d'une Activity. Sur Android, ton écran (l'Activity) c'est comme un acteur sur scène. Le système peut lui dire à tout moment : « T'es en pause. » → onPause() « Tu passes en arrière-plan. » → onStop() « On a besoin de ta mémoire, dégage. » → onDestroy() Et ton app ? Elle a 3 secondes pour obéir. Sinon le système la tue, peu importe ce qu'elle faisait. Pourquoi c'est utile : Imagine 50 apps ouvertes. Tu scrolles TikTok. Une autre app a besoin de RAM pour afficher une grosse image. Android dit à TikTok "lâche ta mémoire" → TikTok obéit → l'autre app s'affiche. Si TikTok gardait tout pour elle, ton téléphone se transformerait en grille-pain 😭 Le piège que font tous les juniors : Ils mettent leur code "important" dans onCreate() en pensant qu'il s'exécute "au démarrage de l'app". Faux. onCreate() s'exécute à chaque fois que l'Activity est recréée. Si t'as téléchargé une image de 20 Mo dans onCreate(), elle se retélécharge à chaque fois que le système détruit puis recrée ton Activity. La bonne pratique : State à sauvegarder → onSaveInstanceState() (le bundle survit à la mort) Données lourdes → ViewModel (survit aux changements de config) Téléchargements → WorkManager (survit même si l'app est tuée) ✅ Résultat : tu scrolles, tu quittes, tu reviens — ton app est exactement où tu l'as laissée. 💾 Enregistre ce post pour ne pas l'oublier. #Android #MobileDev #Activity #DevTips #MetaCodeLearn
195 ·
C
⚡ ASTUCE SQL — FILTER, l'arme secrète des agrégations conditionnelles (PostgreSQL) T'as déjà écrit ça ? SELECT COUNT(*) FILTER (WHERE status = 'active') AS actives, COUNT(*) FILTER (WHERE status = 'banned') AS banned FROM users; Ou encore : SELECT user_id, SUM(amount) FILTER (WHERE type = 'purchase') AS total_achats, SUM(amount) FILTER (WHERE type = 'refund') AS total_rembourses FROM transactions GROUP BY user_id; Tu vois la différence ? Pas de CASE WHEN dans l'agrégat, pas de duplication de la colonne, pas de sous-requête qui rame. Juste FILTER. C'est quoi en vrai ? FILTER (WHERE condition) est une clause PostgreSQL (norme SQL standard) qui dit : « applique cette agrégation UNIQUEMENT aux lignes qui matchent la condition ». Pourquoi c'est mieux que CASE WHEN ? Compare les deux écritures pour le même résultat : Cas 1 — FILTER (propre, rapide) : SELECT COUNT(*) FILTER (WHERE paid) AS paid_orders, COUNT(*) FILTER (WHERE NOT paid) AS unpaid_orders FROM orders; Cas 2 — CASE WHEN (verbeux) : SELECT COUNT(CASE WHEN paid THEN 1 END) AS paid_orders, COUNT(CASE WHEN NOT paid THEN 1 END) AS unpaid_orders FROM orders; Cas 3 — sous-requête (lourd) : SELECT (SELECT COUNT(*) FROM orders WHERE paid) AS paid_orders, (SELECT COUNT(*) FROM orders WHERE NOT paid) AS unpaid_orders; Cas 1 gagne. Plus lisible, plus rapide (un seul scan de la table), et zéro ambiguïté. ✅ Valeur : FILTER est standard SQL (SQL:2003), disponible dans PostgreSQL, SQLite 3.30+, et quelques autres. Sur MySQL par contre, faudra rester sur CASE WHEN. 💾 Enregistre ce post pour ne pas l'oublier. #SQL #PostgreSQL #DevTips #WebDev #MetaCodeLearn
1 · 164 ·
Coding Learn
💡 LE SAVIEZ-VOUS — Creeper, le premier virus de l'histoire (1971) En 1971, un ingénieur américain du nom de Bob Thomas crée un programme qui se propage sur ARPANET (l'ancêtre d'Internet). À l'époque, ARPANET relie une vingtaine d'universités et labos aux US. Le programme s'appelle Creeper. Et quand il infecte une machine, il affiche ce message : "I'm the creeper, catch me if you can!" "Creeper", c'est la première chose qu'on a appelée un "virus informatique". Sauf qu'à l'époque, c'était plus une preuve de concept qu'une attaque. Bob Thomas voulait juste montrer qu'un programme pouvait sauter d'une machine à une autre via le réseau. La réplique ne tarde pas. Un autre ingénieur, Ray Tomlinson (le mec qui a inventé le @ dans les emails, au passage), crée Reaper — un programme qui se propage aussi, mais pour détruire Creeper. Reaper est considéré comme le premier antivirus de l'histoire. ✅ Leçon : en 1971 déjà, la dynamique "attaque → défense" était en place. Rien de nouveau sous le soleil, juste des noms plus jolis. 💾 Enregistre ce post pour ne pas l'oublier. #DevHistory #CyberSecurity #Virus #Programming #MetaCodeLearn
1 · 155 ·
C
⚡ ASTUCE JAVASCRIPT — Promise.all vs Promise.allSettled vs Promise.any T'as 3 URLs à fetch en parallèle. Tu prends laquelle ? 1️⃣ Promise.all — "toutes ou rien" const results = await Promise.all([ fetch('/api/users'), fetch('/api/posts'), fetch('/api/comments') ]); // Si 1 échoue → TOUT échoue (reject immédiat) // results = [users, posts, comments] Cas d'usage : tu as besoin des 3 pour avancer (sinon ta feature est cassée). 2️⃣ Promise.allSettled — "toutes, peu importe le résultat" const results = await Promise.allSettled([ fetch('/api/users'), fetch('/api/posts'), fetch('/api/comments') ]); // Aucune reject globale, même si tout plante // results = [ // { status: 'fulfilled', value: ... }, // { status: 'rejected', reason: ... }, // { status: 'fulfilled', value: ... } // ] Cas d'usage : dashboard, logs, batch jobs. Tu veux savoir ce qui a marché et ce qui a planté. 3️⃣ Promise.any — "la première qui réussit" const result = await Promise.any([ fetch('https://cdn1.example.com/data'), fetch('https://cdn2.example.com/data'), fetch('https://cdn3.example.com/data') ]); // Prend le PREMIER fulfilled, ignore les autres // Si TOUS échouent → AggregateError Cas d'usage : retry multi-sources (mirror CDN, fallback API). Le piège classique : Écrire Promise.all sur 50 appels indépendants. Si 1 seul timeout, les 49 autres résultats sont JETÉS — alors que tu pourrais afficher 49 widgets et 1 message d'erreur. C'est du gâchis. allSettledSolved ce problème. ✅ Résumé simple : - Besoin de tout ? → Promise.all - Besoin de savoir ce qui marche ? → Promise.allSettled - Besoin du premier qui répond ? → Promise.any 💾 Enregistre ce post pour ne pas l'oublier. #JavaScript #Promise #WebDev #DevTips #MetaCodeLearn
1 · 137 ·
Coding Learn
💡 LE SAVIEZ-VOUS — Therac-25 (1985) : 6 morts à cause d'une race condition Entre 1985 et 1987, une machine médicale appelée Therac-25 envoie des doses de radiation 100 fois supérieures à la normale à 6 patients. Tous meurent dans des conditions atroces. C'est quoi Therac-25 ? Une machine de radiothérapie qui traite des cancers. Ses concurrents (Therac-6 et Therac-20) tournent sur du hardware avec des sécurités physiques. Mais Therac-25 est la première à tout déléguer au logiciel. Que s'est-il passé ? Le logiciel de la machine a deux modes : "électron" (faible dose) et "X-ray" (haute dose). L'opérateur tape les paramètres sur un clavier. Quand il tape trop vite, le système reste bloqué sur le mode "électron"... mais sans placer le filtre de protection qui va avec. Résultat : le bras est en mode "électron" mais la machine tourne en mode "X-ray" sans filtre. La dose qui sort est massive. Le patient reçoit l'équivalent de plusieurs mois de radiothérapie en quelques secondes. C'est quoi le bug exactement ? C'est une race condition. Deux Threads (les paramètres de l'utilisateur ET l'état du hardware) accèdent à la même variable partagée sans verrou. Si l'utilisateur clique plus vite que le thread de vérification met à jour l'état, le système passe en "prêt à tirer" alors que le hardware n'est pas en sécurité. Pire : les ingénieurs ont débugué après le premier accident, mais n'ont pas compris que le bug venait du modèle concurrent. Ils ont juste ajouté des messages d'alerte. Trois autres patients sont morts dans les 6 mois qui ont suivi. ✅ Leçon pour nous, devs : 1. Une race condition, ça ne se voit pas en test normal. Faut stress-test, fuzzing, et model-checking pour les attraper. 2. "On ajoutera un message d'alerte" n'est jamais une solution à un bug de sécurité. 3. Quand la vie des gens dépend de ton code, les standards ne sont pas optionnels. Ce bug a contribué à créer les normes de sécurité logicielle pour les dispositifs médicaux (IEC 62304). Si t'as écrit
1 · 131 ·
C
⚡ ASTUCE PYTHON — match/case, le pattern matching (Python 3.10+) Python 3.10 a ajouté match/case. C'est un switch sous stéroïdes — il peut matcher sur la structure d'une donnée, pas juste sa valeur. Exemple basique : status = 200 match status: case 200: print("OK") case 404: print("Not found") case 500: print("Server error") case _: print("Unknown") OK, classique. Mais regarde ça : def handle(event): match event: case {"type": "click", "x": x, "y": y}: print(f"Click at ({x}, {y})") case {"type": "keypress", "key": key}: print(f"Key pressed: {key}") case {"type": "scroll", "direction": d} if d in ("up", "down"): print(f"Scroll {d}") case _: print("Unknown event") Tu vois ? match déstructure le dict, capture les valeurs, ET supporte un guard (if d in (...)). Encore plus fort — matcher sur des classes : class Point: __match_args__ = ("x", "y") class Circle: __match_args__ = ("center", "radius") def describe(obj): match obj: case Point(0, 0): return "Point at origin" case Circle(center=Point(0, 0), radius=r): return f"Circle r={r} centered at origin" case Circle(radius=r) if r > 10: return "Big circle" case _: return "Unknown" print(describe(Point(0, 0))) print(describe(Circle(Point(1, 1), 5))) Le __match_args__ permet à match de déstructurer les objets par leurs attributs. C'est le pattern matching d'Haskell, OCaml, Rust, Scala... maintenant en Python. ✅ Quand l'utiliser : - Quand t'as une longue série de if/elif qui checkent la structure (API, événements, AST). - Quand tu veux du code qui se lit comme une spec : "si c'est UN click, FAIS X. Si UN scroll, FAIS Y." ⚠️ Quand NE PAS l'utiliser : - Pour des checks de valeurs simples → un dict ou un set reste plus clair. - Si t'es encore en Python <3.10 → oublie. 💾 Enregistre ce po
114 ·
Coding Learn
💡 LE SAVIEZ-VOUS — Le miroir du télescope Hubble : le bug à 2,5 milliards de dollars (1990) En avril 1990, la NASA lance le télescope spatial Hubble. Coût total : 2,5 milliards de dollars. À peine 2 mois après sa mise en orbite, les premières images arrivent... et elles sont floues. Le miroir principal est défectueux. Que s'est-il passé ? Pendant la fabrication du miroir principal (2,4 m de diamètre), un petit instrument de mesure — appelé un reflectometer — a été mal calibré. L'écart : 1,3 millimètre. 1,3 mm. C'est rien. Sauf que sur un télescope optique spatial, le résidu de fabrication tolère 50 ns de précis. 1,3 mm, c'est 25-26 fois la tolérance. Le résultat : Hubble ne pouvait pas faire la mise au point correctement. Les images étaient aussi floues qu'un appareil photo avec une lentille de travers. Comment la NASA a corrigé ? Ils ont envoyé les astronautes de la navette spatiale Endeavour avec une pièce de remplacement : COSTAR (Corrective Optics Space Telescope Axial Replacement). En installant un miroir correctif (modif) devant les instruments, ils ont compensé le défaut du miroir principal. Mission terminée en décembre 1993. Hubble a ensuite livré les images les plus célèbres de l'histoire de l'astronomie. ✅ Leçon pour nous, devs : 1. Un bug d'unité (cm vs mm, secondes vs ms, ASCII vs UTF-8) peut tout faire planter. Toujours vérifier que tout le monde parle la même unité. 2. Une erreur de 1,3 mm au bon endroit peut coûter 2,5 milliards. Idem en prod : un bug de 1 ligne au mauvais endroit peut faire tomber un site à 10 M€/jour. 3. La calibration des outils de mesure compte autant que les outils eux-mêmes. Les tests unitaires passent, donc le code est correct ? Pas forcément. Les rapports d'enquête de la NASA sont publics et téléchargeables — c'est un cas d'école dans les universités d'ingénierie. Si t'es dev, lis-le au moins une fois dans ta vie. 💾 Enregistre ce post pour ne pas l'oublier. #DevHistory #SpaceEngineering #Bug #SoftwareEngineering #M
109 ·
C
⚡ ASTUCE GIT — git merge vs git rebase (avec un dessin) Tu travailles sur une branche feature/x. Tu veux récupérer les commits de main. Deux options : 1️⃣ git merge — combine, garde l'historique brut git checkout feature/x git merge main # Résultat : # main: A---B---C # \ # feature/x: D---E---F---M (M = merge commit) Tu vois un commit de merge (M). L'historique est COMPLET, mais aussi plus bruité. Si tout le monde merge main dans sa feature toutes les 2 heures, l'historique ressemble à une pelote de laine. 2️⃣ git rebase — rejoue tes commits par-dessus main git checkout feature/x git rebase main # Résultat : # main: A---B---C # \ # feature/x: D'---E'---F' Pas de commit de merge. Tes commits D', E', F' sont de NOUVEAUX commits (avec des nouveaux hashes). L'historique est LINÉAIRE, propre, lisible. Mais : tu as "réécrit l'histoire". ⚠️ La règle d'or du rebase : Ne JAMAIS rebase une branche partagée. Si quelqu'un d'autre a déjà pull ta branche, et que tu rebases : tes commits changent de hash. Les collègues vont avoir des conflits dans tous les sens, et tu vas devenir leur pire ennemi de la semaine. ✅ Quand utiliser quoi ? - merge sur main (ou n'importe quelle branche partagée) — toujours. - rebase sur ta branche locale, AVANT de merger dans main, pour nettoyer ton historique. - rebase sur une branche feature que TOI seul utilise. La combo que les pros utilisent : # Sur ta branche feature locale git fetch origin git rebase origin/main # Puis tu push --force-with-lease (pas --force !) git push --force-with-lease # Enfin, merge dans main git checkout main git merge feature/x # fast-forward, pas de commit de merge --force-with-lease vérifie que personne n'a push entre temps sur ta branche. Si oui, le push est refusé. C'est la version safe de --force. 💾 Enregistre ce post pour ne pas l'oublir. #Git #DevTips #Programming #WebDev #MetaCodeLearn
67 ·
C
Coding Learn
⚡ ASTUCE WEB — CORS, enfin compris en 3 minutes Tu ouvres la console : "Access to fetch at 'https://api.example.com' from origin 'https://myapp.com' has been blocked by CORS policy". Tu fixes ça comment ? Tu copies-colles un snippet StackOverflow. Mais qu'est-ce que ça veut dire, vraiment ? Le problème : Ton navigateur charge https://myapp.com. Ton JS essaie de faire un fetch('https://api.example.com/users'). Pour des raisons de sécurité, le navigateur BLOQUE la requête par défaut. Pourquoi ? Parce que si je vais sur https://mauvais-site.com et que mon JS peut faire un fetch('https://banque.com/compte/virements') avec mes cookies de session attachés automatiquement, c'est la catastrophe. C'est ce qu'on appelle une attaque CSRF. CORS = Cross-Origin Resource Sharing. C'est LE mécanisme qui dit : "OK, le navigateur, toi https://mon-app.com, je t'autorise à me lire." Comment ça marche : Quand ton frontend fait un fetch, le navigateur envoie une preflight request (OPTIONS) : OPTIONS /users HTTP/1.1 Origin: https://mon-app.com Access-Control-Request-Method: GET Access-Control-Request-Headers: Authorization Le serveur répond : HTTP/1.1 204 No Content Access-Control-Allow-Origin: https://mon-app.com Access-Control-Allow-Methods: GET, POST, OPTIONS Access-Control-Allow-Headers: Authorization Access-Control-Max-Age: 86400 Si Access-Control-Allow-Origin matche l'origine du frontend, le navigateur laisse passer la vraie requête. Sinon, bloqué. Les 3 erreurs classiques et leurs fixes : 1️⃣ "No 'Access-Control-Allow-Origin' header is present" Le serveur ne renvoie pas le header. Côté backend, ajoute : # Express.js app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', 'https://mon-app.com'); res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE'); res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization'); next(); }); 2️⃣ "The value of the 'Access-Control-Allow-Origin' header is '*, which is not valid when
25 ·

An open public feed from the search index ChatCrawler — “Google for public Telegram”; refreshed as the venue is crawled. Times are UTC.

Public content only, official Telegram API. About · FAQ · What we do not do · Remove a page · Catalog · Search · How we count