Недостаточное понимание задач > непродуманная формализация задачи > неоптимальное построение архитектуры софта > ...
Как правило в ТЗ у заказчика описано очень общее представление о готовом продукте. Задача по мере разработки обрастает ограничениям и костылями, с которыми приходится мириться. Как правило из экономии времени разработки.
Хорошо формализованные задачи встречаются очень редко. Они исключение
Для новой задачи не всегда возможно (вернее, всегда невозможно) в поставленные сроки сформулировать корректное решение и обработать все возможные проблемы, поэтому вся разработка софта - итеративный процесс, начинающийся с базового прототипирования, в котором главное - достичь функциональности (решения) по какой-то мэйнстримной ветке, а уж затем прорабатывать побочные случаи
Отсутствие полноценной теоретической базы - то самое, регулярно повторяемое на "ответах": "математика программистам не нужна". А без знания математики (разумеется, не школьной пародии, а нормальной вузовской) разработчик не в состоянии оценить качество собственного кода.