Фаулер уже на эту тему много всего написал и рассказал. Трудно быть оригинальным. Но общие правила примерно такие: не давайте джунам дизайнить код; не делайте заведомую фигню, которая, может, и решает текущую проблему, но в будущем приносит еще больше проблем; не пренебрегайте принципами разработки; организуйте хорошие процессы; думайте о коде в терминах complexity, requirements, goals; делите его на слои с независимыми интерфейсами и имплементациями; пишите код бизнес-логики относительно интерфейсов, а не имплементации; разделяйте вещи, которые должен видеть клиент, и детали имплементации, которые не должен; и даже в Haskell полагайтесь на дисциплину software design, а не на стремление сделать красиво и математично. Ну и так далее.