Quando la chiamata al modulo diventa brutta

7

Questo ti è mai successo? Hai una suite di moduli ben progettati, a responsabilità unica, coperti da test unitari. In qualsiasi funzione di livello superiore che si codifica, si è (il 95% del codice) semplicemente prendendo l'output da un modulo e passandolo come input al successivo. Quindi, noti che questa funzione di livello superiore si è trasformata in uno script di oltre 100 righe con più responsabilità.

Ecco il problema. È difficile (impossibile) testare quella sceneggiatura. Almeno, sembra così. Sei d'accordo? Nel mio attuale progetto, tutti i bug provenivano da questo script.

Ulteriori dettagli: ogni script rappresenta una soluzione unica, o algoritmo, formato utilizzando diversi moduli in modi diversi.

Domanda: come puoi rimediare a questa situazione?

Risposta per il jerk: rompere lo script in moduli a responsabilità singola.
Commento sulla risposta istintiva: lo è già!

Risposta migliore che riesco a fare finora: creare oggetti connettore di livello superiore che "uniscono" i moduli in un modo particolare (prelevare l'output da un modulo, alimentarlo come input per un altro modulo). Quindi se il nostro script fosse:

Foo.Input fooIn = new Foo.Input(1, 2);
Foo.Output fooOutput =  fooModule.operate(fooIn);
Double runtimevalue = getsomething(fooOutput.whatever);
Bar.Input barIn = new Bar.Input( runtimevalue, fooOutput.someOtherValue);
Bar.Output barOut = barModule.operate(barIn);

Diventerebbe con un connettore:

FooBarConnectionAlgo fooBarConnector = new fooBarConnector(fooModule, barModule); 
Foo.Input fooIn = new Foo.Input(1, 2);
Bar.Output barOut = fooBarConnector.operate(fooIn);

Quindi il vantaggio è che oltre a nascondere un codice e rendere le cose più chiare, possiamo testare FooBarConnectionAlgo.

Sono sicuro che questa situazione si presenta molto. Che cosa fai?

    
posta Pete 01.06.2012 - 16:52
fonte

3 risposte

6

Hai capito bene. Questo è chiamato "Programmazione strutturata". Funziona bene quando si ha un problema da risolvere con una serie di passaggi sequenziali. Si interrompe ogni problema in pochi sotto-problemi, poi si scompongono i sotto-problemi, poi si scompongono i sotto-sotto-problemi, poi ... Sembra che ci si trovi al punto in cui si ha una subroutine di primo livello --er, metodo e un gruppo di quelli di livello inferiore. Quello superiore sta diventando grande, quindi hai bisogno di un livello intermedio, per così dire. Se il tuo problema (mi piacerebbe chiamarlo un programma, ma è davvero una parte di un programma) diventa abbastanza grande, potresti finire con molti livelli di metodi.

Le azioni di ciascun metodo dovrebbero essere determinate esclusivamente dai parametri passati ad esso. Dico questo per essere completo; con la tua concentrazione sui test, lo capisci così come qualsiasi evangelista del programma strutturato vecchio stile. Idealmente, ogni metodo sarebbe chiamato da più di un posto, dimostrando che è generalmente utile, ma è meglio che i metodi utilizzino i sotto-metodi che solo loro chiamano e che chiamano solo una volta, piuttosto che il metodo principale diventa grande e non soddisfacente .

Non sono sicuro di come si rapportino la Programmazione Sbrigliata e l'OOP. Sembrano fondersi bene, ed è sempre ovvio quando usare cosa. OO sembra più utile per tracciare e mantenere lo stato di un programma, per gestire input periodici da parte di utenti e simili. SP è più per i numeri scricchiolanti. Ho scoperto che quando ho scritto grossi numeri crunch, le classi iniziano a insinuarsi ai livelli inferiori della mia gerarchia SP.

    
risposta data 01.06.2012 - 19:53
fonte
2

Penso che quello a cui ti riferisci sia un test di integrazione. Normalmente si avrebbe una serie di dati di test e risultati noti, proprio come per un test unitario, ma in questo caso si sta testando l'intero lavoro integrato, invece di un solo modulo in isolamento.

Un test di integrazione non può entrare in ogni angolo di ogni bit di codice, ma ti darà abbastanza confidenza che hai collegato tutto correttamente.

    
risposta data 01.06.2012 - 19:29
fonte
1

In isolamento, penso che tu sia sulla strada giusta. Non sono sicuro che mi preoccuperei di scrivere "connettori" che si uniscono ai moduli per ogni caso specifico. Tuttavia, fa ha senso creare oggetti che eseguono la logica e possono avere le sue dipendenze iniettate in essa. Perché non farlo per l'intero "script" stesso? Quindi lo script stesso è testabile. È quindi possibile iniettare mock o "doppi" per garantire che le cose accadano nel modo previsto. Dopotutto, mi aspetto che sia lo script nel suo complesso a cui tieni, piuttosto che ogni singola interazione tra i moduli.

    
risposta data 01.06.2012 - 19:23
fonte