Come evitare i metodi di colla gigante?


21

Nel mio attuale lavoro, mi è stato assegnato il compito di ripulire il vecchio codice alcune volte. Spesso il codice è un labirinto e i dati sottostanti sono ancora più intricati. Mi ritrovo a combinare le cose in metodi piacevoli, ordinati e modulari. Ogni metodo fa una cosa e la fa bene. Questo è quando le cose iniziano ad andare a sud ...

Invariabilmente, finisco con un'API pulita e nessun modo reale di legare tutto insieme. La soluzione è stata quella di scrivere un brutto metodo "colla" (generalmente pieno di istruzioni condizionali) che alla fine chiama tutti i miei metodi "puliti".

Il metodo della colla di solito finisce per essere una versione concisa del groviglio di codice / dati che stavo tentando di ripulire. È generalmente più leggibile, ma è comunque fastidioso.

Come posso evitare tali metodi? È un sintomo dei dati aggrovigliati o un riflesso di qualcosa che sto facendo di sbagliato?


3
Le API devono essere utilizzate. Dal disordine aggrovigliato che hai, hai creato un'API e poi l'hai aggrovigliata. Forse è solo il requisito aziendale. Ma hai aggiunto valore perché qualcun altro può venire e far funzionare facilmente un'altra colla usando la tua API. Non c'è bisogno di stringere la mano ...
MP Aditya,

1
Stiamo anche parlando di oggetti qui o semplicemente funzioni dappertutto?
Erik Reppen,

3
Non penso che questo sia un duplicato di quella domanda, sto parlando un po 'più in generale (e su una scala più ampia di una singola funzione).
cmhobbs,

1
erik - Sto parlando di oggetti e metodi qui. Ho preso un paio di pasticci condizionali e li ho trasformati in API. Il problema si presenta quando è il momento di chiamare l'API. La prima risposta qui potrebbe essere esattamente quello che sto cercando, però.
cmhobbs,

2
Come diavolo è un duplicato?
MattDavey,

Risposte:


12

Ti darò la nostra esperienza di refactoring LedgerSMB. Abbiamo preso la decisione di fare le cose in modo diverso all'inizio e stiamo ancora facendo esattamente quello che descrivi, ma senza molti metodi di colla (abbiamo alcuni metodi di colla tra l'altro, ma non molto).

La vita con due basi di codice

LedgerSMB è sopravvissuto con due codebase per circa 5 anni e saranno molti di più prima che la vecchia base di codice venga eliminata. La vecchia base di codice è un vero orrore da vedere. Cattivo design db, Perl costruisce come IS->some_func(\%$some_object);insieme al codice che mostra esattamente perché a volte viene usata la metafora degli spaghetti (percorsi di esecuzione che si snodano tra i moduli e il retro e tra le lingue, senza rima o ragione). La nuova base di codice evita ciò spostando le query db in stored procedure, disponendo di un framework più pulito per la gestione delle richieste e molto altro.

La prima cosa che abbiamo deciso di fare è stata quella di provare a refactoring modulo per modulo. Ciò significa spostare tutte le funzionalità in un'area specifica in un nuovo modulo e quindi collegare il vecchio codice nel nuovo modulo. Se la nuova API è pulita, questo non è un grosso problema. Se la nuova API non è cose, diventa peloso e questo è un invito a lavorare un po 'più duramente nella nuova API ....

La seconda cosa è che ci sono molte volte in cui il nuovo codice deve accedere alla logica nel vecchio codice. Questo deve essere evitato nella misura del possibile perché porta a metodi di colla che sono brutti ma non si può sempre evitarlo. In questo caso i metodi di colla dovrebbero essere minimizzati ed evitati nella misura del possibile ma usati quando necessario.

Per fare questo devi impegnarti a riscrivere tutte le funzionalità in un'area specifica. Se è possibile, ad esempio, riscrivere contemporaneamente tutto il codice di tracciamento delle informazioni sui clienti, ciò significa che il codice che lo chiama dal vecchio codice non è difficile da lavorare e che la spedizione al vecchio codice dal nuovo codice è ridotta al minimo.

La seconda cosa è che se hai delle astrazioni ragionevoli al tuo posto, dovresti essere in grado di scegliere quale livello dell'API chiamare e come mantenerlo pulito. Tuttavia, dovresti pensare di riscrivere le parti che chiamano l'API in modo che siano anche un po 'più pulite.

Esistono molte aree di strumenti aziendali irriducibilmente complesse. Non puoi liberarti di tutta la complessità. Ma puoi gestirlo concentrandoti su API pulite che fanno specificamente ciò che devi fare e su moduli che utilizzano tale API in modo costruttivo. La colla dovrebbe essere l'ultima risorsa solo dopo aver considerato che riscrivere il resto del codice chiamante potrebbe essere più veloce.


Penso che potresti aver colpito l'unghia sulla testa. Il motivo per cui esiste la colla potrebbe essere dovuto al codice che chiama l'interfaccia che ho creato. Aspetterò altre risposte per vedere se ci manca qualcosa, ma credo che questo riassuma abbastanza bene.
cmhobbs,

1
"percorsi di esecuzione che si snodano tra moduli e ritorno, e tra lingue, senza rima o ragione" - questo mi ricorda anche alcune pratiche OO moderne.
user253751

8

Suona come quello che hai fatto è preso un aggrovigliato pasticcio di un precedural base di codice e ha creato un bel modulare precedural codebase.

Invariabilmente, finisco con un'API pulita e nessun modo reale di legare tutto insieme. La soluzione è stata quella di scrivere un brutto metodo "colla" (generalmente pieno di istruzioni condizionali) che alla fine chiama tutti i miei metodi "puliti".

Con il codice procedurale (anche se mascherato da OO), finirai sempre con un qualche tipo di flusso di lavoro sequenziale definito da qualche parte, spesso pieno di complessi rami condizionali come descrivi. Sospetto che sia questa natura procedurale del codice che ti fa sentire che qualcosa non va. Questa non è necessariamente una cosa negativa e quando si lavora con il codice legacy può essere del tutto inevitabile


6

Dovresti ripulire il grosso e brutto metodo di colla nello stesso modo in cui hai ripulito la base di codice originale. Dividilo in metodi modulari accurati. Probabilmente hai gruppi di righe di codice che svolgono alcune attività suddividendo queste righe in metodi, se condividi alcune variabili potresti considerare di mettere le variabili condivise e i nuovi metodi in una classe.


2
Allora non hai un albero della colla?
Pieter B,

3
@PieterB forse, ma è più facile estrarre le diverse dipendenze quando si hanno le diverse attività con metodi diversi. È possibile eseguire un'altra pass di refactoring dopo aver estratto i nuovi metodi.
Impallidire il

1

Fondamentalmente, continui ad aggiungere livelli di astrazione, fino a quando non guarda bene ogni livello preso da solo . La cosa paradossale dell'astrazione è che aggiungi complessità per ridurla, perché quando leggi il codice astratto, ti preoccupi solo di un livello alla volta. Se ogni strato è abbastanza piccolo da essere facilmente compreso, non importa su quanti strati poggia.

Questo è anche ciò che rende difficile scrivere le astrazioni. Anche qualcosa di semplice come una matita è piegare la mente se provi a tenere tutti i suoi strati di astrazione in testa contemporaneamente. La chiave è ottenere un livello come piace a te, cosa che hai fatto, quindi dimenticare tutta la complessità che sta alla base di quel livello e fare la stessa cosa al livello successivo.


0

Sembra che tu stia eseguendo il refactoring dell'API semplicemente pensando all'implementazione dell'API, ma senza pensare abbastanza al codice che utilizza l'API, ovvero al "codice colla" di cui stai parlando.

Se questo è vero, potresti provare a iniziare dall'altra parte. Riscrivi le cose che minacciano di diventare il tuo brutto codice di colla e crea un paio di interfacce non ancora implementate che diventeranno la tua API in quel processo. Non pensare ancora troppo all'implementazione effettiva di questa API: va bene se hai la sensazione di poterlo fare. E solo allora riscrivi il labirinto di codice per renderlo conforme a quell'API. Ovviamente ci saranno alcune modifiche nell'API e nel codice colla in questo processo, ma dovrebbe adattarsi meglio.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.