Per me mi piace l'approccio che Kent Beck propone in XP (non sono sicuro che si tratti della "sua" idea o di qualcun altro, ma è lì che l'ho sentito per la prima volta):
È abbastanza difficile risolvere i problemi di oggi senza cercare di capire quali sono i problemi di domani e risolverli.
Gli sviluppatori possono dedicare molto tempo a soluzioni per requisiti inesistenti, casi limite che non si verificheranno mai o addirittura problemi reali in cui l'impatto del problema è significativamente inferiore al costo di prevenirlo.
Questo è il tempo che potrebbe essere messo in cose che gli utenti vorranno e utilizzeranno davvero, cose che daranno loro benefici che supereranno enormemente anche l'inconveniente che sarà causato nell'improbabile caso in cui una di queste cose accada realmente.
Al di là di questo risultato non ottimale per l'utente, l'impatto sullo sviluppatore dell'ingegnerizzazione eccessiva in questo modo tende a superare il codice complesso che è più difficile da supportare e più difficile da migliorare.
Quindi, per me, se sai, o puoi essere abbastanza sicuro, che qualcosa è un requisito o sta per causare un problema, risolvilo, altrimenti non lo fai.
Potrebbe essere necessario tornare indietro e rielaborarlo quando si scopre che c'era un requisito più ampio di quello implementato originariamente, ma in generale lo sforzo totale che si fa attraverso il progetto sarà ancora inferiore perché nella maggior parte dei casi ciò non accadrà.