Le canard finit par trahir — et toujours au pire endroit.The duck eventually betrays you — always at the worst place.
Deux numéros à vanter le duck typing ; voici sa facture, en toute honnêteté. Quand on fait confiance au message sans jamais vérifier, une donnée malformée traverse sans bruit — et l'erreur n'éclate pas là où elle est née (l'entrée), mais douze appels plus loin, au fond du domaine, sous la forme d'un NoMethodError sur nil. Le bug que Rust attrape à la compilation, Ruby te le sert à l'exécution, au moment le moins commode.Two issues praising duck typing; here's its bill, honestly. When you trust the message without ever checking, malformed data flows through silently — and the error doesn't surface where it was born (the entry), but twelve calls deep, in the domain, as a NoMethodError on nil. The bug Rust catches at compile time, Ruby serves you at runtime, at the least convenient moment.
# à l'entrée HTTP : on fait confiance au JSON reçu, sans rien vérifier payload = JSON.parse(request.body) # { } — "name" est absent ce jour-là user = User.new(payload) # … 12 frames plus loin, au fond de la couche de rendu : def greeting(user) = "Bonjour #{user.name.split.first} !" greeting(user) # NoMethodError: undefined method 'split' for nil # app/views/header.rb:7 ← l'erreur surgit ICI… # … mais la cause est à l'entrée HTTP, douze appels plus haut
La cause (donnée invalide) et l'effet (le crash) sont séparés par douze frames. Plus la donnée voyage avant de trahir, plus le débogage coûte.The cause (invalid data) and the effect (the crash) are twelve frames apart. The further the data travels before betraying you, the costlier the debugging.
« Valide le canard à la frontière (l'entrée externe), fais-lui confiance à l'intérieur. » Le duck typing reste roi dans ton domaine ; mais à la lisière — JSON, params HTTP, ligne CSV, réponse d'API — tu regagnes une garantie, une seule fois, pour que l'erreur naisse là où on peut la lire."Validate the duck at the boundary (external input), trust it inside." Duck typing stays king in your domain; but at the edge — JSON, HTTP params, CSV line, API response — you regain a guarantee, once, so the error is born where it can be read.
Ce numéro ne renie pas le duck typing — il en nomme le prix et le situe. Le coût n'est pas « ça plante parfois », c'est « ça plante loin de la cause ». La parade n'est pas de tout vérifier partout (on y reviendra, c'est le piège), mais de choisir où regagner une garantie : au runtime à la frontière, ou statiquement, hors exécution.This issue doesn't disown duck typing — it names its price and places it. The cost isn't 'it crashes sometimes', it's 'it crashes far from the cause'. The remedy isn't checking everything everywhere (we'll get to that — it's the trap), but choosing where to regain a guarantee: at runtime at the boundary, or statically, outside execution.