Come strutturare una catena di chiamate di metodo [duplicate]

2

Per semplificarlo per qualsiasi client della mia classe, ho inserito una sequenza di chiamate di metodi private all'interno di un metodo pubblico.

Il client chiama quindi questo metodo e tutti i metodi all'interno dell'esecuzione per completare l'azione. Per esempio:

 public void DoRejection(string comments, string rejectionType)
    {
        GetPartstoReject();
        UpdateRejectedPartsStatus(rejectionType);
        RemoveInitiatingRejectionPart();
        ClearRejectedPartsData();
        CreateNewOpenPart();
        SaveRejectionComments(rejectionType, comments);
    }

Il lato negativo che posso vedere è che è più difficile testare l'unità in quanto ogni metodo privato non verrà testato separatamente (seguendo la best practice dei soli metodi di test di unità pubbliche).

Come può essere meglio progettato per migliorare la testabilità, ma rendere ancora più semplice la chiamata da parte di un client?

    
posta j p 27.10.2015 - 22:52
fonte

1 risposta

5

Hai un problema. Vedete un sintomo di esso nella difficoltà nel testare i metodi alla base di DoRejection() , ma questo è solo un sintomo del problema, non il problema stesso.

Il problema di fondo è che hai un metodo che nasconde il accoppiamento sequenziale .

Un mio collega (alcuni datori di lavoro fa) aveva un detto:

If you use the word 'and' when describing what the method does, you need to break this method into smaller parts.

Un altro modo per dire questo è "Hai violato il principio di responsabilità singola per questo metodo." Sta facendo troppe cose. Il metodo non semplicemente "fa un rifiuto", ma piuttosto:

  1. aggiorna lo stato della parte
  2. rimuove la parte rifiutata
  3. cancella i dati di parte rifiutati
  4. crea una nuova parte
  5. commette il rifiuto con i commenti

Questo è lontano troppe cose che stanno succedendo dietro la scena. Se questo è parte di una transazione, esporre la transazione. Il motivo per cui si riscontrano difficoltà nel testare le parti in isolamento è perché non sono isolate. Lo stato di rimozione dei dati di parte rifiutati richiede che la parte rispettata venga rimossa.

Un approccio classico a questo, come parte dell'esposizione dei metodi, è di imporre un progetto per contratto. Verifica le condizioni preliminari e, se non vengono soddisfatte, genera un errore.

Puoi anche imporre la sequenza restituendo un oggetto che avvolge la classe sottostante e presenta solo gli stati successivi appropriati.

Questo sarebbe particolarmente utile se si desidera essere in grado di aggiornare più parti, ma farlo solo come un unico commit.

Ci sono altri problemi che si insinuano in ciò che hanno odori di codice corrispondenti. I metodi che non accettano argomenti (e non restituiscono valori), specialmente quando l'accoppiamento sequenziale è in gioco, agiscono sullo stato dell'oggetto come valore pseudo-globale. Ci sono metodi che indicano che ci sono effetti collaterali che il metodo next dipende. Ciò solleva alcune domande molto serie sul design sottostante e ha un strong odore di codice per loro.

È difficile dire esattamente dove si trova il problema da questo piccolo campione di codice, ma è abbastanza chiaro che c'è un problema significativo con le basi di progettazione su cui si basa questo codice.

    
risposta data 14.11.2015 - 02:57
fonte

Leggi altre domande sui tag