Почти все можно проанализировать с точки зрения затрат и выгод, и я думаю, что это применимо здесь.
Очевидные преимущества первого варианта заключаются в том, что он сводит к минимуму работу в краткосрочной перспективе и сводит к минимуму шансы что-то сломать, переписав рабочий код. Очевидная цена состоит в том, что это вносит несоответствие в базу кода. Когда вы выполняете какую-то операцию X, она выполняется одним способом в некоторых частях кода и другим способом в другой части кода.
Что касается второго подхода, вы уже отметили очевидное преимущество: последовательность. Очевидная цена состоит в том, что вы должны склонить свой ум к работе так, как вы могли бы иначе отказаться несколько лет назад, и код остается неизменно нечитаемым.
Для третьего подхода очевидная стоимость - это просто сделать гораздо больше работы. Менее очевидной ценой является то, что вы можете сломать вещи, которые работали. Это особенно вероятно, если (как это часто бывает) старый код имеет неадекватные тесты, чтобы гарантировать, что он продолжает работать правильно. Очевидное преимущество состоит в том, что (при условии, что вы делаете это успешно) у вас есть хороший, блестящий новый код. Наряду с использованием новых языковых конструкций, у вас есть возможность реорганизовать базу кода, которая почти всегда дает улучшения сама по себе, даже если вы все еще использовали язык в точности так, как он существовал на момент написания, - добавьте новые конструкции, которые делают работа легче, и это вполне может быть крупной победой.
Еще один важный момент: сейчас кажется, что этот модуль долгое время не требовал минимального обслуживания (хотя проект в целом поддерживается). Это, как правило, указывает на то, что он довольно хорошо написан и относительно не содержит ошибок - в противном случае он, вероятно, должен был бы пройти дополнительное обслуживание в промежуточный период.
Это приводит к другому вопросу: что является источником изменений, которые вы делаете сейчас? Если вы исправляете небольшую ошибку в модуле, которая в целом все еще хорошо соответствует его требованиям, это может указывать на то, что время и усилия по рефакторингу всего модуля, скорее всего, будут в значительной степени потрачены впустую - к тому времени, когда кому-то придется возиться с опять же, они вполне могут находиться примерно в том же положении, в каком вы сейчас находитесь, поддерживая код, который не соответствует «современным» ожиданиям.
Однако также возможно, что требования изменились, и вы работаете над кодом для удовлетворения этих новых требований. В этом случае велика вероятность того, что ваши первые попытки не будут соответствовать текущим требованиям. Также значительно выше вероятность того, что требования пройдут несколько этапов пересмотра, прежде чем они снова стабилизируются. Это означает, что у вас гораздо больше шансов выполнить значительную работу в этом модуле в (относительно) ближайшем будущем, и гораздо больше шансов внести изменения в остальную часть модуля, а не только в одну область, которую вы знаете о правильном сейчас. В этом случае рефакторинг всего модуля с большей вероятностью принесет ощутимые, краткосрочные выгоды, которые оправдывают дополнительную работу.
Если требования изменились, вам также может понадобиться посмотреть, какие изменения происходят, и что является причиной этих изменений. Например, предположим, что вы модифицировали Git, чтобы заменить использование SHA-1 на SHA-256. Это изменение требований, но сфера его действия четко определена и довольно узка. После того, как вы настроили хранение и правильное использование SHA-256, вы вряд ли встретите другие изменения, которые повлияют на остальную часть кода.
В другом направлении, даже когда оно начинается с малого и дискретно, изменение пользовательского интерфейса имеет тенденцию к всплеску, поэтому то, что начиналось как «добавить один новый флажок на этот экран», в конечном итоге выглядит так: «изменить этот фиксированный интерфейс» для поддержки пользовательских шаблонов, пользовательских полей, пользовательских цветовых схем и т. д. "
Для первого примера, вероятно, имеет смысл минимизировать изменения и допустить ошибку на стороне согласованности. Для последнего полный рефакторинг с большей вероятностью окупится.