Monday, June 24, 2013

Code Speaks 2U, czyli Test Ivony

Przyszło mi ostatnio do głowy następujące kryterium czytelności kodu: kod musi do Ciebie przemówić. I potraktowałem to bardzo dosłownie.

Zatem weź fragment kodu, który chcesz sprawdzić i:
  1. Operatory zamień na słowa
  2. Klamerkę "{" po ifie zamień na "then"
  3. Rozbij nazwy camel case na pojedyncze wyrazy
  4. Z wyrażeń przypisania bierz pod uwagę tylko prawą stronę, lewą ignoruj
  5. Każdy wiersz kodu traktuj jako osobne zdanie zakończone kropką.
  6. Tak powstały tekst wklej do syntezatora mowy ivona.com
  7. Jeśli to, co słyszysz (bez patrzenia na kod), jest w pełni zrozumiałe, to kod jest czytelny :)

Weźmy taki przykład na przykład:
public class List {

 private final static int DEFAULT_SIZE = 10;
 private Object[] elements;
 private boolean readOnly;
 private int size;

 public List() {
   elements = new Object[DEFAULT_SIZE];
   size = DEFAULT_SIZE;
 }
 
 public void add(Object element) {
   if (!readOnly) {
     int newSize = size + 1;
     if (newSize > elements.length) {
       Object[] newElements = new Object[elements.length+10];
       for (int i = 0; i < size; i++) {
         newElements[i] = elements[i];
       }
       elements = newElements;
     }
              elements[size++] = element;
   }
 }
}

Dla metody add tekst będzie następujący:
If not read only.
Size plus one.
If new size greater than elements length then.
New objects size of elements length plus one.
For each elements: i of elements.
New elements.
Element.

No, a teraz wklej do ivona.com i słuchaj :) Ma sens?

A teraz niewielki refaktoring metody add związany przede wszystkim nazywaniem i pierwszymi dwoma krokami Naturalnego Porządku Refaktoryzacji.

Metoda przybiera następującą postać:


public void add(Object anElement) {
  if (readOnly) {
    return;
  }
  
  if (atCapacity()) {
    grow();
  }
  
  put(anElement, into(elements));
}
 


private Object[] into(Object[] elements) {
  return elements;
}

private void put(Object anElement, Object elements[]) {
  elements[size++] = anElement;
}
 
private boolean atCapacity() {
  return size + 1> elements.length;
}

private void grow() {
  Object[] newElements = new Object[elements.length + 10];
  for (int i = 0; i < size; i++) {
    newElements[i] = elements[i];
  }

  elements = newElements;
}

Tym razem tekst dla Ivony jest następujący:
If read only then return.
If at capacity then grow.
Put an element into elements.

Ponownie odsłuchaj, co Twój kod ma Ci do powiedzenia. Lepiej? :)