Even i Odd, czyli DRY in Action 2

Przeglądam ostatnio jakiś stary moduł do softu, który piszę. Trafiłem na ciekawy przypadek złamania zasady DRY. W poprzednim wpisie opisałem czym jest ta zasada. Dla przypomnienia DRY, czyli skrót od angielskiego Don’t Repeat Yourself jest zasadą dobrego programowania, która mówi, żeby unikać powtórzeń kodu. Pozwala to na lepsze zarządzanie kodem (dokładnie zmianą kodu) i tym samym lżejsze życie programistów i supportu.
Dość częstym błędem związanym z DRY jest przetwarzanie warunkowe z powtórzeniem kodu. koronnym przypadkiem jest kolorowanie wierszy parzystych i nieparzystych. Poniżej bardzo zły kod wykonujący to zadanie.

Listing 1. Zły pomysł

if (lp % 2 == 0) {                                       
	_lpLbl.setStyleName("result-table-even");       
	_clrrunLbl.setStyleName("result-table-even");   
	_clrdayLbl.setStyleName("result-table-even");   
	_brnorgidtLbl.setStyleName("result-table-even");
	_brnrcvidtLbl.setStyleName("result-table-even");
	_msgsubgrpLbl.setStyleName("result-table-even");
	_doktypLbl.setStyleName("result-table-even");   
	_pointerLbl.setStyleName("result-table-even");  
	_msgvolLbl.setStyleName("result-table-even");   
	_msgvalLbl.setStyleName("result-table-even");   
} else {                                                 
	_lpLbl.setStyleName("result-table-odd");        
	_clrrunLbl.setStyleName("result-table-odd");    
	_clrdayLbl.setStyleName("result-table-odd");    
	_brnorgidtLbl.setStyleName("result-table-odd"); 
	_brnrcvidtLbl.setStyleName("result-table-odd"); 
	_msgsubgrpLbl.setStyleName("result-table-odd"); 
	_doktypLbl.setStyleName("result-table-odd");    
	_pointerLbl.setStyleName("result-table-odd");   
	_msgvolLbl.setStyleName("result-table-odd");    
	_msgvalLbl.setStyleName("result-table-odd");    
}                                                        

Znacznie prostszym rozwiązaniem w tym przypadku jest użycie zmiennej lokalnej:

Listing 2. Lepsze rozwiązanie

String el = lp % 2 == 0 ? "even" : "odd";             
_lpLbl.setStyleName("result-table-" + el);       
_clrrunLbl.setStyleName("result-table-" + el);   
_clrdayLbl.setStyleName("result-table-" + el);   
_brnorgidtLbl.setStyleName("result-table-" + el);
_brnrcvidtLbl.setStyleName("result-table-" + el);
_msgsubgrpLbl.setStyleName("result-table-" + el);
_doktypLbl.setStyleName("result-table-" + el);   
_pointerLbl.setStyleName("result-table-" + el);  
_msgvolLbl.setStyleName("result-table-" + el);   
_msgvalLbl.setStyleName("result-table-" + el);   

Dlaczego nie Strategia

Jeszcze lepszym rozwiązaniem jest użycie wzorca strategii. Z drugiej strony jeżeli mamy problem w którym warunek ma naturę binarną to wprowadzanie dodatkowego wzorca projektowego jest tylko niepotrzebnym komplikowaniem kodu. Jeżeli warunek trzeba by było rozszerzyć dla np. 3 rodzajów rekordów to dopiero w tym momencie należy wprowadzić dodatkowy wzorzec.

2 myśli na temat “Even i Odd, czyli DRY in Action 2

  1. hello,

    tylko po co x razy dodajesz w kółko te same dwa stringi: „result-table-” + el ?


    pozdrawiam
    Tomek Kaczanowski

  2. Bo przykład został „zanonimizowany” i wyleciał początek z każdego stringa. Ale racja, jeżeli był by to pełen przykład operacja dodawania powinna odbyć się tylko raz.

Napisz odpowiedź

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax