Майже що-небудь можна проаналізувати з точки зору витрат і вигод, і я думаю, що це стосується і тут.
Очевидною перевагою першого варіанту є те, що він мінімізує роботу за короткий термін і мінімізує шанси щось порушити, переписавши робочий код. Очевидна вартість полягає в тому, що вона вносить непослідовність у кодову базу. Коли ви робите якусь операцію X, вона виконується в одному частині коду одним способом, а в іншій частині коду - іншим способом.
Щодо другого підходу, ви вже відзначили очевидну користь: послідовність. Очевидна ціна полягає в тому, що вам доведеться змусити свій розум працювати так, як ви могли інакше відмовилися років тому, і код залишається незмінним для читання.
Для третього підходу очевидною ціною є просто необхідність зробити набагато більше роботи. Менш очевидною ціною є те, що ви можете зламати речі, які працювали. Це особливо ймовірно, якщо (як це часто буває) у старому коді є неадекватні тести, щоб переконатися, що він продовжує працювати правильно. Очевидною перевагою є те, що (якщо ви це зробите успішно) у вас є гарний, блискучий новий код. Поряд із використанням нових мовних конструкцій, у вас є шанс переробити основу коду, що майже завжди покращить себе, навіть якщо ви все ще використовували мову саме такою, якою вона існувала, коли вона була написана - додайте в нові конструкції, які роблять робота легша, і це, можливо, буде головним виграшем.
Ще один важливий момент: однак, схоже, цей модуль давно мав мінімальне обслуговування (навіть незважаючи на те, що проект в цілому підтримується). Це, як правило, вказує на те, що він досить добре написаний і відносно вільний з помилками - інакше він, мабуть, зазнав би більшого обслуговування в проміжку.
Це призводить до іншого питання: яке джерело змін, які ви зараз вносите? Якщо ви виправляєте невелику помилку в модулі, який в цілому все ще добре відповідає її вимогам, це може означати, що час і зусилля на рефакторинг всього модуля, ймовірно, будуть значною мірою витрачені - до того часу, коли комусь потрібно зіпсуватись Знову ж таки, вони, можливо, опиняться приблизно в тому ж становищі, що ви зараз, зберігаючи код, який не відповідає "сучасним" очікуванням.
Також можливо, що вимоги змінилися, і ви працюєте над кодом, щоб відповідати цим новим вимогам. У цьому випадку шанси на те, що ваші перші спроби насправді не відповідають сучасним вимогам. Існує також значно більший шанс, що вимоги пройдуть кілька раундів перегляду, перш ніж вони знову стабілізуються. Це означає, що ви набагато більше шансів виконати значну роботу в цьому модулі протягом (відносно) найближчого періоду, і набагато більше шансів внести зміни протягом решти модуля, а не лише в тій області, про яку ви знаєте правильно зараз. У цьому випадку рефакторинг всього модуля набагато частіше матиме відчутні, короткочасні переваги, які виправдовують додаткову роботу.
Якщо вимоги змінилися, вам може знадобитися також ознайомитись із типом змін і що саме сприяє зміні. Наприклад, припустимо, що ви модифікували Git для заміни його використання SHA-1 на SHA-256. Це зміна вимог, але сфера чітко визначена і досить вузька. Після правильного зберігання та використання SHA-256 ви навряд чи зможете зіткнутися з іншими змінами, які впливають на решту бази коду.
В іншому напрямку, навіть коли він починається невеликим і дискретним, зміна інтерфейсу користувача має тенденцію до повітряної кулі, тому те, що почалося як "додати один новий прапорець на цей екран", закінчується так, як: "змінити цей фіксований інтерфейс користувача для підтримки визначених користувачем шаблонів, спеціальних полів, налаштованих кольорових схем тощо "
У першому прикладі, мабуть, є найбільш сенс мінімізувати зміни та помилитися на стороні послідовності. Для останнього повний рефакторинг набагато частіше окупиться.