Ramping Up On Legacy Code [duplicato]

9

Quando si inizia a lavorare su un progetto con una base di codice esistente, la prima cosa che deve essere fatta di solito è capire l'applicazione & codice esistente. Supponiamo che il codice esistente sia il codice legacy; riferendosi alla definizione di Michael Feathers di "codice senza test".

Sono sicuro che ci sono molti modi diversi per gestire questa fase di accelerazione. Il modo più semplice è quello di passare attraverso l'interfaccia utente dell'applicazione (se ce n'è una) e contemporaneamente eseguire il debug dell'applicazione per capire cosa sta accadendo a livello di codice. Questo è un approccio che richiede molto tempo ed è anche molto facile dimenticare ciò che si impara in una sessione di debug. Inoltre, non esiste un vero modo per condividere (tra la squadra) ciò che si apprende durante il debug.

Comprendendo i lati negativi di questo approccio, ho provato un altro approccio per il mio progetto più recente. Quello che ho fatto è stato scrivere una sorta di strato API che si basi sulla base di codice esistente. Questa API conteneva la funzionalità di praticamente ciò che un utente avrebbe fatto nell'interfaccia utente.

Per essere più specifici, supponiamo che l'applicazione esistente sia una tipica applicazione transazionale con ordini, articoli e carrelli della spesa. La mia API si è rivelata simile a questa:

public class OrderAPI{
    public Order createOrder(customerName);
    public boolean deleteOrder(orderID);
    public List<Order> getOrdersForCustomer(customerName);
}

public class OrderItemAPI{
    public OrderItem createOrderItem(order);
    public boolean deleteOrder(orderID);
    public List<OrderItem> getItemInOrder(order);
}

public class ShoppingCartAPI {
    public ShoppingCart createCart(customer,order);
    public boolean addItemToCart(cart, item);
    public boolean removeItemFromCart(cart, item);
}

I metodi nell'API corrispondono alle azioni che l'utente eseguirà a livello di interfaccia utente. All'interno di questi metodi, vengono effettuate le chiamate alla base di codice esistente.

Scrivere questa API da solo, ovviamente, non significa molto. Quindi, ho scritto test (credo che diventino automaticamente test di integrazione) per garantire che l'API funzioni bene; dimostrando che ho capito come funziona il codice legacy.

Dopo tutta questa introduzione, arriva la mia domanda: puoi definire (possibilmente in termini di ingegneria del software) cosa ho fatto? Quando ho preso questo approccio, sono andato completamente con la mia intuizione. Ad un certo punto, ricordo di essere estremamente confuso; lavorando sull'API, quindi lavorando sui miei test, correggendo la mia API, quindi i miei test. Non ero più sicuro se il mio obiettivo principale fosse quello di imparare il codice esistente o di creare un livello API stabile.

Apprezzerei molto ogni tipo di spiegazione; Sono sicuro che questa deve essere una pratica che altre persone hanno già sperimentato. Ho solo bisogno della giusta guida per indicarmi le discussioni / risorse appropriate.

    
posta Guven 19.10.2011 - 05:46
fonte

3 risposte

4

L'API è una facciata / involucro giusto? Le piume potrebbero anche chiamarlo creando una Seam. Lo chiamo "Ottenere il sistema sotto test".

Se possibile, ora vuoi prendere il livello dell'interfaccia utente e integrarlo in modo che funzioni attraverso questa nuova API. A quel punto hai veri test di integrazione e hai una certa sicurezza del comportamento del sistema dall'API giù. Se lo lasci così com'è, li definirei come Test di apprendimento, che può essere ancora utile per la caccia alle regressioni.

I test di apprendimento sono stati presentati in Pulisci codice , ma non so chi ha inventato il termine. Ecco alcuni link per maggiori informazioni:

risposta data 19.10.2011 - 17:48
fonte
2

Mi piace l'idea di scrivere unit test per familiarizzare con il codice, ma non sono sicuro del livello API. Il codice precedente era troppo difficile da scrivere contro i test senza i wrapper? Hai intenzione di sviluppare qualcosa che usi questa API (oltre ai test)?

In genere non sostengo di scrivere molto codice che non ti aspetti di eseguire in produzione. La persona che viene dopo di te potrebbe essere ancora più confusa da ciò. Se questo è solo parte della tua suite di test, mi limito ad assicurarmi che sia molto chiaro dalla cartella / struttura del progetto.

    
risposta data 19.10.2011 - 15:06
fonte
2

Test di caratterizzazione è il termine utilizzato da Michael Feathers per scrivere test che provano a comprendere e caratterizzare ciò che fa una base di codice sconosciuta. Sembra che, per arrivare a questi test, eri forzato a creare anche questa API, un wrapper o una facciata (come menzionato da Steve Jackson) che prova a esporre un insieme coerente di funzionalità a il giusto livello di astrazione senza passare attraverso l'interfaccia utente . È difficile testare senza una buona separazione e coerenza.

Quindi, per me, questa API sembra necessaria scaffolding per poter scrivere alcuni test di caratterizzazione. Potrebbe essere interessante considerare di evolvere e incorporarlo nell'applicazione stessa, in modo da non avere viste in competizione sullo stesso sistema , cosa che potrebbe ritorcersi contro e rivelarsi una fonte di duplicazione ( e mal di testa di manutenzione).

Altri termini correlati che potrebbero essere di interesse includono:

Per creare dati di test:

Big refactoring:

Modelli di design:

Principi (sui livelli di astrazione):

risposta data 19.10.2011 - 21:56
fonte

Leggi altre domande sui tag