2012-01-13 5 views
6

Ho questo metodo in C# e desidero refactoring. Ci sono troppi bool e linee. Quale sarebbe il miglior refactoring. Fare una nuova classe sembra un po 'eccessivo, e tagliare semplicemente in due sembra difficile. Qualsiasi intuizione o puntatore sarebbe apprezzato.Refactoring di un metodo con troppi bool in esso

metodo per refactoring

private DialogResult CheckForSireRestrictionInSubGroup(bool deletingGroup,string currentId) 
    { 
     DialogResult result = DialogResult.No; 
     if (!searchAllSireList) 
     { 
      DataAccessDialog dlg = BeginWaitMessage(); 
      bool isClose = false; 
      try 
      { 
       ArrayList deletedSire = new ArrayList(); 
       ISireGroupBE sireGroupBE = sireController.FindSireGroupSearch(); 

       if (sireGroupBE != null) 
       { 
        //if the current group is in fact the seach group before saving 
        bool currentGroupIsSeachGroup = sireGroupBE.TheSireGroup.id == currentId; 

        //if we have setting this group as search group 
        bool selectedAsSearchGroup = this.chkBoxSelectedSireGroup.Checked; 

        //if the group we currently are in is not longer the seach group(chk box was unchecked) 
        bool wasSearchGroup = currentGroupIsSeachGroup && !selectedAsSearchGroup; 

        //if the group is becoming the search group 
        bool becomesSearchGroup = !currentGroupIsSeachGroup && selectedAsSearchGroup; 

        //if the group being deleted is in fact the search group 
        bool deletingSearchGroup = deletingGroup && currentGroupIsSeachGroup; 

        //if the user checked the checkbox but he's deleting it, not a so common case, but 
        //we shouldn't even consider to delete sire in this case 
        bool deletingTemporarySearchGroup = deletingGroup && !currentGroupIsSeachGroup;   

        //if we are not deleting a temporary search group and it's either 
        //becoming one (without deleting it) or we already are the search group 
        bool canDeleteSires = !deletingTemporarySearchGroup && 
              (becomesSearchGroup || currentGroupIsSeachGroup); 
        //we only delete sires if we are in search group 
        if (canDeleteSires) 
        { 
         if (deletingSearchGroup || wasSearchGroup) 
         { 
          // If we deleted all sires 
          deletedSire = new ArrayList(); 
          deletedSire.AddRange(sireGroupBE.SireList); 
         } 
         else 
         { 
          //if we delete a few sire from the change of search group 
          deletedSire = GetDeleteSire(sireGroupBE.SireList); 
         } 
        } 

        EndWaitMessage(dlg); 
        isClose = true; 
        result = ShowSubGroupAffected(deletedSire); 
       } 
      } 
      finally 
      { 
       if (!isClose) 
       { 
        EndWaitMessage(dlg); 
       } 
      } 
     } 

     return result; 
    } 
+0

Questo appare come il modo più pulito di esprimere la logica - è facile da leggere, e è anche ben commentato. Non lo toccherei affatto. – dasblinkenlight

+0

D'accordo .... potrebbe essere lungo ma è leggibile. –

+1

Sono dell'opinione che il codice corrente sia leggibile, ma toglie l'obiettivo del metodo, eliminare le voci. La logica booleana può rimanere invariata e migrare verso un altro metodo in modo tale che il metodo principale possa ridurre il codice di "supporto" che non risolve il problema principale dell'eliminazione di materiale. –

risposta

7

Una possibilità è quella di refactoring di ciascuna delle booleani primarie (canDeleteSires, deletingSearchGroup || wasSearchGroup) in metodi con i nomi che descrivono la versione leggibile della logica:

if (WeAreInSearchGroup()) 
{ 
    if (WeAreDeletingAllSires()) 
    { 
     deletedSire = new ArrayList(); 
     deletedSire.AddRange(sireGroupBE.SireList); 
    } 
    else 
    { 
     deletedSire = GetDeleteSire(sireGroupBE.SireList); 
    } 
} 

È quindi incapsulare la logica booleana corrente all'interno di questi metodi , come si passa lo stato (argomenti del metodo o membri della classe) è una questione di gusti.

Questo rimuoverà i booleani dal metodo principale in metodi più piccoli che richiedono e rispondono direttamente a una domanda. Ho visto questo approccio usato nello stile di sviluppo "commenti sono cattivi". Ad essere onesti, trovo questo un po 'eccessivo se sei un lupo solitario, ma in una squadra può essere molto più facile da leggere.

Fuori di preferenze personali Vorrei anche invertire la prima istruzione if per tornare presto, questo ridurrà il livello di rientro di tutto il metodo:

if (searchAllSireList) 
{ 
    return result; 
} 

DataAccessDialog dlg = BeginWaitMessage(); 
bool isClose = false; 
try 
... 

Ma allora si potrebbe ottenere castigato dai "ritorni multipli sono malvagia "folla. Ho l'impressione pratica di sviluppo è come la politica ...

+0

+1 per l'approccio di ritorno anticipato. Troppi sviluppatori temono questo, ma è un ottimo modo per migliorare la chiarezza di un blocco come questo. E semplice –

+0

@CarlManaster Sono d'accordo con te qui, tendo a favorire i ritorni anticipati se ci sono clausole di bombardamento. Io tendo a favorire i singoli ritorni se ci sono più valori di ritorno possibili che sono rilevanti per la logica, se questo ha senso lol –

+0

Oh, la squadra con cui lavoro è nella setta dell'uno ritorno per metodo. Quindi non c'è molta scelta qui. Personnaly Non sono ancora fissato se questa pratica è cattiva o no. – Xavier

0

In realtà, io personalmente lascerei così com'è. I booleani che hai dappertutto, sebbene inefficienti, rendono questa funzione leggibile e facile da capire.

Si potrebbe fare qualcosa come combinare tutti i bool su una singola riga (come di seguito), tuttavia ciò non è così mantenibile come quello che hai scritto.

x = ((a & b) &! D) | e;

0

Forse puoi provare a rimuovere tutti i commenti. Le variabili bool che hai aggiunto aggiungono valore alla comprensione del codice, potresti metterne molte in linea per canDeleteSires, ma non credo che aggiungerà alcun valore.

D'altra parte, quel codice è nella tua forma, quindi potrebbe essere meglio nel tuo controller in modo da poter mantenere il modulo semplice e il controllore effettivamente controllando il comportamento.

+0

Hehe, hai individuato qualcosa che ho anche notato. In effetti non è nel posto giusto. È il vecchio codice che ritocco per la leggibilità. Probabilmente lo inserirò in qualche controller accanto o in un punto qualsiasi non visibile. – Xavier

+0

Ma questo ti darà la leggibilità. Penso che il codice sia buono nel modo in cui è ora, penso che sia pronto per il "prossimo livello". – ivowiblo

1

Questo è un piccolo refactoring per la rimozione di qualche rientro:

private DialogResult CheckForSireRestrictionInSubGroup(bool deletingGroup,string currentId) 
{ 
    if (searchAllSireList) 
     return DialogResult.No; 

    DataAccessDialog dlg = BeginWaitMessage(); 
    bool isClose = false; 

    try 
    { 
     ISireGroupBE sireGroupBE = sireController.FindSireGroupSearch(); 

     if (sireGroupBE == null) 
      return DialogResult.No; 

     //if the current group is in fact the seach group before saving 
     bool currentGroupIsSeachGroup = sireGroupBE.TheSireGroup.id == currentId; 

     //if we have setting this group as search group 
     bool selectedAsSearchGroup = this.chkBoxSelectedSireGroup.Checked; 

     //if the group we currently are in is not longer the seach group(chk box was unchecked) 
     bool wasSearchGroup = currentGroupIsSeachGroup && !selectedAsSearchGroup; 

     //if the group is becoming the search group 
     bool becomesSearchGroup = !currentGroupIsSeachGroup && selectedAsSearchGroup; 

     //if the group being deleted is in fact the search group 
     bool deletingSearchGroup = deletingGroup && currentGroupIsSeachGroup; 

     //if the user checked the checkbox but he's deleting it, not a so common case, but 
     //we shouldn't even consider to delete sire in this case 
     bool deletingTemporarySearchGroup = deletingGroup && !currentGroupIsSeachGroup;   

     //if we are not deleting a temporary search group and it's either 
     //becoming one (without deleting it) or we already are the search group 
     bool canDeleteSires = !deletingTemporarySearchGroup && 
           (becomesSearchGroup || currentGroupIsSeachGroup); 

     ArrayList deletedSire = new ArrayList(); 

     //we only delete sires if we are in search group 
     if (canDeleteSires) 
     { 
      if (deletingSearchGroup || wasSearchGroup) 
      { 
       // If we deleted all sires 
       deletedSire.AddRange(sireGroupBE.SireList); 
      } 
      else 
      { 
       //if we delete a few sire from the change of search group 
       deletedSire = GetDeleteSire(sireGroupBE.SireList); 
      } 
     } 

     EndWaitMessage(dlg); 
     isClose = true; 
     return ShowSubGroupAffected(deletedSire); 
    } 
    finally 
    { 
     if (!isClose) 
     { 
      EndWaitMessage(dlg); 
     } 
    } 
    return DialogResult.No; 
}