плюс дебаг нужен для отладки логических проблем, когда программа делает не то, что ожидалось. А не банальные NPE и т.п
Внешняя программа, либа, функция? Им доверять нельзя. Сразу на границе проверять на null, exception, пустоту и другие неконсистентности. Можно ещё и автотестами сверху на их код (не свой), чтобы ловить изменения в чужом поведении. ну, я так делаю иногда).
Дебаг нужен чтобы найти проблему, и прекрасен
когда применяется в конкретном обозримом куске функционала. А не когда надо отследить десятки вызовов и логических переходов, нервно куря и паникуя.
Как раз для быстрой локализации: тесты, самопроверки внутри логики, хорошие логи.
Профит в том, что когда код гранулирован, имеет проверки на границах, обвешан тестами, то сообщение об ошибке с прода довольно быстро приведёт в правильное место, где бяка случилась.
А когда место маленькое, то его легко обвешать новыми автотестами с новыми условиями. И затем пофиксить. Дебаг в таком случае вспомогателен, может быть заменён вызовом проблемного куска в REPL.