Quasi tutto può essere analizzato in termini di costi e benefici, e penso che questo si applichi qui.
Gli ovvi vantaggi della prima opzione sono che minimizza il lavoro a breve termine e riduce al minimo le possibilità di rompere qualcosa riscrivendo il codice di lavoro. Il costo ovvio è che introduce incoerenza nella base di codice. Quando esegui un'operazione X, viene eseguita in un modo in alcune parti del codice e in un modo diverso in una parte diversa del codice.
Per il secondo approccio, hai già notato l'ovvio beneficio: coerenza. Il costo ovvio è che devi piegare la mente per lavorare in modi che potresti aver abbandonato in passato anni fa e il codice rimane costantemente illeggibile.
Per il terzo approccio, il costo ovvio è semplicemente dover fare molto più lavoro. Un costo meno ovvio è che potresti rompere le cose che stavano funzionando. Questo è particolarmente probabile se (come spesso accade) il vecchio codice ha test inadeguati per assicurare che continui a funzionare correttamente. L'ovvio vantaggio è che (supponendo che lo fai con successo) hai un codice nuovo e brillante. Oltre all'utilizzo di nuovi costrutti del linguaggio, hai la possibilità di ridefinire il codice base, che quasi sempre darà dei miglioramenti in sé, anche se hai ancora usato il linguaggio esattamente come esisteva quando è stato scritto - aggiungi nuovi costrutti che rendono il linguaggio lavoro più facile, e potrebbe essere una vittoria importante.
Un altro punto importante: al momento, sembra che questo modulo abbia avuto una manutenzione minima per un lungo periodo (anche se il progetto nel suo complesso viene mantenuto). Ciò tende ad indicare che è abbastanza ben scritto e relativamente privo di bug - altrimenti, probabilmente avrebbe subito più manutenzione nel frattempo.
Questo porta a un'altra domanda: qual è la fonte del cambiamento che stai facendo ora? Se stai correggendo un piccolo bug in un modulo che nel complesso soddisfa ancora bene i suoi requisiti, questo tenderebbe ad indicare che il tempo e gli sforzi per il refactoring dell'intero modulo rischiano di essere in gran parte sprecati - nel momento in cui qualcuno deve pasticciare di nuovo, potrebbero essere più o meno nella stessa posizione in cui ti trovi ora, mantenendo il codice che non soddisfa le aspettative "moderne".
È anche possibile, tuttavia, che i requisiti siano cambiati e che tu stia lavorando al codice per soddisfare questi nuovi requisiti. In questo caso, è probabile che i tuoi primi tentativi non soddisfino effettivamente i requisiti attuali. C'è anche una possibilità sostanzialmente maggiore che i requisiti verranno sottoposti ad alcuni cicli di revisione prima che si stabilizzino di nuovo. Ciò significa che è molto più probabile che tu stia facendo un lavoro significativo in questo modulo nel (relativamente) breve termine, e molto più probabile che apporti cambiamenti nel resto del modulo, non solo in quella area che conosci di giusto adesso. In questo caso, è molto più probabile che il refactoring dell'intero modulo abbia vantaggi tangibili a breve termine che giustificano il lavoro extra.
Se i requisiti sono cambiati, potrebbe anche essere necessario considerare quale tipo di cambiamento è coinvolto e cosa sta guidando tale cambiamento. Ad esempio, supponiamo che tu stia modificando Git per sostituire il suo uso di SHA-1 con SHA-256. Questo è un cambiamento nei requisiti, ma l'ambito è chiaramente definito e piuttosto ristretto. Dopo aver effettuato l'archiviazione e l'uso corretto di SHA-256, è improbabile che si verifichino altre modifiche che riguardano il resto della base di codice.
Nella direzione opposta, anche quando inizia piccolo e discreto, una modifica all'interfaccia utente ha la tendenza a mongolfiera, quindi ciò che è iniziato come "aggiungi una nuova casella di controllo a questo schermo" si conclude più come: "modifica questa UI fissa supporta modelli definiti dall'utente, campi personalizzati, schemi di colori personalizzati, ecc. "
Per il primo esempio, probabilmente ha più senso minimizzare le modifiche ed errare dal lato della consistenza. Per quest'ultimo, è molto più probabile che il refactoring completo sia più redditizio.