Gran parte di ciò che abbiamo appreso nella pratica dell'ingegneria del software negli ultimi 30 anni è nella forma "la tecnologia X può accelerare lo sviluppo iniziale di nuovi software, ma se non passi troppo o più tempo a pensare a come e quando usarlo come hai salvato usando, a lungo termine trasformerà la tua applicazione in una palude risucchiata di debito tecnico, costandoti ordini di grandezza più tempo e fatica nella manutenzione. "
Le tecnologie che rientrano in questo rasoio includono: linguaggio assembly codificato a mano, compilatori, interpreti, librerie di procedure, programmazione imperativa, programmazione funzionale, programmazione orientata agli oggetti, allocazione manuale della memoria, garbage collection, tipi statici, tipi dinamici, ambito lessicale, ambito dinamico , puntatori "sicuri", puntatori "non sicuri", assenza di puntatori come concetto di linguaggio, formati di file binari, formati di file con marcatura strutturata, macro, modelli, prevenzione di macro e modelli, memoria condivisa, passaggio di messaggi, thread, coroutine, loop di eventi asincroni, servizi remoti centralizzati, servizi distribuiti, software installato localmente, array, elenchi collegati, tabelle hash e alberi.
Il fatto che molti degli elementi dell'elenco precedente appartengano a gruppi che insieme esauriscono lo spazio di soluzione noto è molto intenzionale e dovrebbe di per sé dirti qualcosa. Si potrebbe sostenere che l' unica inequivocabile, across-the-board miglioramenti nella prassi che abbiamo avuto da quando prima acceso il Z3 sono strutturato a blocchi di programmazione (al contrario di spaghetti code) e la protezione della memoria (ragazzo, faccio mai non perdere i giorni in cui un errore di battitura potrebbe distruggere il mio intero computer).