Prawie wszystko można przeanalizować pod kątem kosztów i korzyści, i myślę, że dotyczy to tutaj.
Oczywistymi zaletami pierwszej opcji jest to, że minimalizuje ona pracę w krótkim okresie i minimalizuje szanse na uszkodzenie czegoś przez przepisanie działającego kodu. Oczywistym kosztem jest to, że wprowadza niespójność do podstawy kodu. Kiedy wykonujesz jakąś operację X, odbywa się to w jeden sposób w niektórych częściach kodu, a w inny sposób w innej części kodu.
W przypadku drugiego podejścia zauważyłeś już oczywistą korzyść: spójność. Oczywistym kosztem jest to, że musisz pochylić umysł, aby pracować w sposób, który w przeciwnym razie mógłbyś porzucić lata temu, a kod pozostaje konsekwentnie nieczytelny.
W przypadku trzeciego podejścia oczywistym kosztem jest po prostu dużo więcej pracy. Mniej oczywistym kosztem jest to, że możesz zepsuć rzeczy, które działały. Jest to szczególnie prawdopodobne, jeśli (jak to często bywa) stary kod ma nieodpowiednie testy, aby upewnić się, że nadal działa poprawnie. Oczywistą korzyścią jest to, że (zakładając, że zrobisz to skutecznie) masz ładny, błyszczący nowy kod. Oprócz korzystania z nowych konstrukcji językowych masz szansę na przebudowanie podstawy kodu, co prawie zawsze da ulepszenia samo w sobie, nawet jeśli nadal używałeś języka dokładnie tak, jak istniał w chwili jego napisania - dodaj nowe konstrukcje, które praca łatwiejsza, a może to być duża wygrana.
Jeszcze jedna ważna kwestia: obecnie wydaje się, że moduł ten od dłuższego czasu wymaga minimalnej konserwacji (mimo że cały projekt jest utrzymywany). To wskazuje, że jest dość dobrze napisane i stosunkowo wolne od błędów - w przeciwnym razie prawdopodobnie zostałby w międzyczasie poddany większej konserwacji.
To prowadzi do kolejnego pytania: jakie jest źródło zmian, których dokonujesz teraz? Jeśli naprawiasz mały błąd w module, który ogólnie dobrze spełnia jego wymagania, może to wskazywać, że czas i wysiłek związany z refaktoryzacją całego modułu prawdopodobnie zostanie w dużej mierze zmarnowany - do czasu, gdy ktoś będzie musiał zadzierać to znowu może być mniej więcej w tej samej pozycji, co teraz, utrzymując kod, który nie spełnia „nowoczesnych” oczekiwań.
Możliwe jest jednak, że wymagania się zmieniły i pracujesz nad kodem, aby spełnić te nowe wymagania. W takim przypadku istnieje duża szansa, że Twoje pierwsze próby nie spełnią obecnych wymagań. Istnieje również znacznie większa szansa, że wymagania przejdą kilka rund zmian, zanim ponownie się ustabilizują. Oznacza to, że znacznie bardziej prawdopodobne jest, że będziesz wykonywać znaczącą pracę w tym module w (względnie) bliskiej perspektywie, a znacznie bardziej prawdopodobne jest dokonywanie zmian w pozostałej części modułu, a nie tylko w jednym obszarze, o którym dobrze wiesz teraz. W takim przypadku refaktoryzacja całego modułu jest bardziej prawdopodobne, że przyniesie wymierne, krótkoterminowe korzyści uzasadniające dodatkową pracę.
Jeśli wymagania się zmieniły, być może będziesz musiał sprawdzić, jakiego rodzaju zmiana jest wymagana i co jest przyczyną tej zmiany. Załóżmy na przykład, że modyfikujesz Gita, aby zastąpić jego użycie SHA-1 SHA-256. Jest to zmiana wymagań, ale zakres jest jasno określony i dość wąski. Po skonfigurowaniu i prawidłowym użyciu SHA-256, prawdopodobnie nie napotkasz innych zmian, które wpływają na resztę kodu.
Z drugiej strony, nawet jeśli początkowo jest niewielka i dyskretna, zmiana interfejsu użytkownika ma tendencję do tworzenia balonów, więc to, co zaczęło się jako „dodaj jedno nowe pole wyboru do tego ekranu”, kończy się bardziej: „zmień ten stały interfejs użytkownika do obsługi szablonów zdefiniowanych przez użytkownika, niestandardowych pól, niestandardowych schematów kolorów itp. ”
W poprzednim przykładzie prawdopodobnie najbardziej sensowne jest zminimalizowanie zmian i pomyłka po stronie spójności. W tym ostatnim przypadku pełne refaktoryzacja jest znacznie bardziej prawdopodobne.