Thursday, June 27, 2013

[en] Code Speaks To You

A colleague asked me to translate this post for some non-Polish fellows. I've been thinking about blogging in English for couple months. Some guys from Polish blogosphere have already done so. Who knows, maybe this is sign of times. Let's this one be my first small step.


So, I had an idea for a code readability criteria: code should speaks to you. I took this sentence very seriously.

Take code piece you want to challenge and:
  1. Replace all operators by words.
  2. Replace a "{" following "if" statement by "then".
  3. Split camel case names into words.
  4. Take only right "=" operator argument. Ignore the left one.
  5. Treat each line of code as a sentence ended with a dot.
  6. And now paste the given text into Text-to-Speach engine .
  7. So if you understand (without looking at the code) what you hear, the code is readable.

Let's we try with the following code.
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;
   }
 }
}

Challenging the add method we would have a text similar to this:
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.


Now paste the text above to the Text-to-Speach engine and listen :) Does it make sense?

After small refactoring of the add method it looks little bit differently.
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;
}

This time the text would look a little bit different:
If read only then return.
If at capacity then grow.
Put an element into elements.


Again, paste the text above to the Text-to-Speach engine and listen what your code speaks to you. Better? :)

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? :)

Monday, June 17, 2013

Nie myj zębów, rób retrospekcje!

Trudno zauważyć korzyść z robienia retrospekcji, bez ich robienia. Trudno znaleźć argumenty, zachęcić kogoś do regularnego poświęcania czasu na analizę swoich działań. Mimo wszystko chciałbym Cię namówić właśnie do regularnych (czyt. codziennych) retrospekcji.

Fakty nam "uciekają"

Gdy zastanawiamy się nad tym, co robimy, zazwyczaj popełniamy (przynajmniej) jeden kardynalny błąd. Ulegamy złudzeniu, że to co myślimy, to racjonalny i w miarę obiektywny osąd tego, co się wydarzyło. Wydaje nam się, że gdy skupimy się mocno i wytężymy szare komórki, to z możliwym do oszacowania błędem potrafimy nawet przytoczyć dane liczbowe na temat tego, co zrobiliśmy. Dlaczego myślę, że ulegamy złudzeniu?

Od dzieciństwa używasz liczb do ilościowego wyrażania rzeczy. Wszystko, co skończone można przeliczyć. Mimo, że sprawnie posługujemy się liczbami, to gdy myślimy o ilości, ma miejsce pewne zniekształcenie.
Liczby, jak sądzę, nie są czymś, czym umysł operuje w naturalny sposób. Liczby to twór abstrakcyjny. Aby ująć coś liczbowo, należy przeprowadzić złożony proces myślowy. Gdy naturalnie zastanawiasz się nad licznością, np. ile maili dziś dostałem? Twoja naturalna percepcja wygląda mniej więcej tak: jeden, dwa, trzy, cztery, wiele. Gdy pracujesz w zespole liczącym kilkanaście osób i dostaniesz pytanie: ile pączków trzeba kupić, aby wystarczyło dla wszystkich? to o ile wcześniej nie ujmowałeś liczbowo swojego zespołu, czyli: nie policzyłeś osób i nikt głośnio nie powiedział ilu/e Was aktualnie jest (poważnie! większość z nas wcale nie ma tej liczby ot tak, na zawołanie), to oczywiście podasz właściwą odpowiedź, że potrzeba siedemnaście pączków. Jednak nie przypomnisz sobie liczby, tylko pomyślisz o każdej osobie z zespołu po kolei, a dopiero potem policzysz. Co ciekawe, gdy za jakiś czas, ktoś ponownie zapyta o liczność zespołu, ze zdziwieniem odkryjesz, że nie pamiętasz. Nie jest to wiedza konieczna do pracy zespołowej, więc po prostu ulatuje.

Podobnie jest z myśleniem o czasie.
Gdy myślisz o czasie, to myślenie przebiega mniej więcej tak: dzisiaj, jutro, pojutrze, kiedyś, pewnego dnia albo dzisiaj, wczoraj, przedwczoraj, kiedyś tam, dawno temu. Bądź też orientujesz się wg istotnych wydarzeń: po wakacjach, przed tym jak się tu zatrudniłem.



Co może Cię zaskoczyć?

Analizując każdego dnia swoje działanie i zadając sobie wciąż te same pytania retrospekcyjne, nagle orientujesz się, że zanim podejmiesz jakieś działanie, już nie myślisz dzisiaj, jutro, pojutrze, kiedyś lecz na przykład dzisiaj, jutro, pojutrze, za rok, za pięć lat, kiedyś.
Twoje postrzeganie czasu poszerza się. Żeby dobrze to podkreślić: nie tylko podczas retrospekcji widzisz szerszą perspektywę, lecz zaczynasz jej doświadczać w ciągu dnia, w trakcie wykonywania swoich obowiązków. To trochę tak jakby pojawiały Ci się w głowie myśli w stylu: jeśli napiszę taki kod teraz, to przewiduję, że za rok pojawią się takie, a takie konsekwencje. Tego typu "wglądy" wiele zmieniają. Zwyczajnie nie masz ochoty podejmować niektórych działań, ponieważ aż do szpiku kości czujesz kłopoty, które z tego powodu mogą Cię spotkać. I analogiczne z działaniami mającymi pozytywny wpływ.

Podobnie ma się sprawa z naszym postrzeganiem liczności. Dzięki retrospekcjom wyraźniej dostrzegasz co?, jak? i ile? robisz.
Jakiś czas temu odkryłem ciekawe pytanie retrospekcyjne: kim się staję?. Było to mniej więcej tak, że w pewnym momencie zacząłem zauważać, że regularnie powtarzam jakieś tam zachowanie. Jednocześnie zastanowiłem się dlaczego właściwie tak postępuję? skąd się to bierze? Dotarło do mnie, że postępując w jakiś określony sposób, liczmy, że będziemy jacyś. Pretendujemy do jakiejś tożsamości, do bycia postrzeganym jako: profesjonalny programista, charyzmatyczny lider, gracz zespołowy, odpowiedzialny pracownik, przyjaciel, dobry ojciec, itd.

Liczmy więc na to, że poprzez nasze zachowania stajemy się bardziej tacy, jacy chcemy być. Ponieważ zazwyczaj nasze postrzeganie czasu oraz liczności jest mocno ograniczone do teraz i najbliższych okolic, na co dzień raczej nie zdajemy sobie sprawy, czy nasze postępowanie sprawia, że zbliżamy się do pożądanej tożsamości.

Zupełnie inaczej mają się sprawy, gdy zaprzęgniesz do działania retrospekcje. Patrzysz wtedy szerzej, wyraźniej, z odleglejszej perspektywy. I gdy każdego dnia zadajesz sobie pytanie kim się staję?, to może się zdarzyć, że na przykład zawsze chciałeś być świetnym programistą, a poprzez to, co robisz, stajesz się średnim liderem... Z własnego doświadczenia powiem, że odpowiedź na pytanie kim się staję? najczęściej robi w głowie wielkie buuum.

Z tego, co wiem, to niektórzy ludzie w jakimś momencie przeżywają owo wielkie buuum, które ktoś kiedyś nazwał kryzysem wieku średniego:) Wydaje mi się, że dzięki retrospekcjom udaje się w kontrolowany sposób adresować te wszystkie pytania, które w trakcie kryzysu zwalają się na głowę wszystkie na raz. Ale jak to będzie, zobaczymy:)

Od czego zacząć?

Istnieje z pewnością wiele sposobów retrospekcji. Wiele z nich to całe schematy postępowania i kłopot polega na tym, że gdy jeszcze nie czułem w czym rzecz, to rozbudowane checklisty mnie nudziły i nic konkretnego nie potrafiłem z nich wyczytać. Proponuję więc zacząć od czegoś znacznie prostszego.

Od prostej odpowiedzi na pytanie: Jak wykorzystałem dzisiaj czas? i spisania tego na kartce. Tak wiem, że od razu przychodzą do głowy pytania: na kartce? a nie lepiej w pliku? a może w mindmapie? a jak to będę przechowywał? czy się nie pogubię? czy danych nie będzie za dużo? a co z archiwizacją? oraz moje ulubione pytanie: jakie narzędzia to wspierają?:)

Stop! Moja odpowiedź na wszystkie te pytania brzmi: nie wiem, być może. Wiem jednak na pewno, że nie ma co zaprzątać sobie tym głowy teraz.


Jeżeli już nie będziesz mógł bez tego zacząć, to powiem, że ja na przykład używam zwykłego książkowego kalendarza. Akurat taki miałem pod ręką. Czasem moje retrospekcje to kilka punktów, a czasem cała strona zapisana drobnym maczkiem. To zależy od tego, co akurat danego wieczoru mam sobie do powiedzenia. Prowadzę retrospekcje w tej formie od dokładnie 13. lutego i muszę stwierdzić, że jest to najlepsza forma, jaką udało mi się dotąd wymyślić. Czy przejdę kiedyś na formę elektroniczną? Nie sądzę. Kalendarz mam ze sobą zawsze. Telefon czy notebook nie. Natomiast robienie wstecznych retrospekcji mija się z celem. No, ale jak mawiała moja lektorka angielskiego: never say never and don't always say always. :)

Dlaczego w formie pisemnej?

Jeśli kilka ostatnich lat spędziłeś w klasztorze albo właśnie zakończyłeś zaawansowany i intensywny kurs panowania nad umysłem, albo po prostu od urodzenia potrafisz w sposób świadomy zarządzać każdą myślą, która przyjdzie Ci do głowy, to oczywiście pisanina nie jest Ci wcale potrzebna.

Umysły większość z nas są jednak mocno niezdyscyplinowane. Jeśli postanowisz przeprowadzać retrospekcję w myślach, w trakcie kąpieli to Twój dialog wewnętrzny będzie prawdopodobnie przebiegał w następującym stylu: yyy zaimplementowałem funkcjonalność... [tutaj Twoją uwagę odwraca zbyt zimna woda] o woda zimna jak w Bałtyku..., podczas ostatnich wakacji... [tu przypominasz sobie o retrospekcji] no, więc byłem na spotkaniu z... [ale przypomina Ci się, że] o cholera! miałem zadzwonić do X! [tu biegniesz do telefonu] ok, skończyłem retrospekcję, dzisiaj było ok..

Z takiej retrospekcji nic nie wynika. Myśli uciekają, rozpraszają się i wychodzi zwykłe bla, bla, bla, bla. Retrospekcja musi mieć swój czas i swoje miejsce. Pisanie pomaga się koncentrować, nadać myślom kierunek i wydobyć z nich użyteczną treść.

Dlaczego codziennie?

A to trudne pytanie:) No bo dlaczego nie co tydzień albo co miesiąc? Porównałbym tu robienie retrospekcji do naliczania odsetek na lokacie. Wiadomo, że lokata z dzienną kapitalizacją przynosi większe zyski niż z miesięczną, ponieważ już po jednym dniu możesz dodać wypracowane odsetki i powiększyć kapitał, od którego są one liczone w dniu kolejnym i tak dalej. Wnioski retrospekcyjne to takie naliczanie kapitału, już następnego dnia możesz skorzystać z tych wniosków.

Poza tym podstawowy rytm człowieka, którym odmierza rzeczywistość to, jak sądzę, rytm dobowy. Powtarzanie jakiejś czynności każdego dnia, staje się elementem codzienności (ang. daily routine) i szybko wchodzi w nawyk.

Przecież ja nie mam na to czasu!

No i na koniec obiekcja, która pojawia się najczęściej: Nie mam czasu! Naprawdę chciałbym, ale nie mam czasu. No bo kiedy? Praca, dom, rodzina, wyjazdy itd. Jeśli Ty również, chciałbyś robić retrospekcje, ale nie masz czasu, to mam dla Ciebie radosną wiadomość: specjalnie dla Ciebie opracowałem autorską technikę, dzięki której znajdziesz czas potrzebny na codzienną retrospekcję. I to znajdziesz już dzisiaj!

W poszukiwaniu owego czasu skontaktowałem się z zaprzyjaźnionym stomatologiem i zapytałem go, przez jaki czas można bez większych szkód nie myć zębów :) Zżymał się, zżymał, lecz udało mi się z niego wydusić, że o ile odżywiasz się normalnie czyli unikasz: sacharozy, fruktozy, maltozy, dekstryny, maltodesktryny, dekstrozy, aspartamu i syropu glugozowo-fruktozowego, to spokojnie możesz odłożyć szczoteczkę i pastę na miesiąc bądź dwa, zastępując mycie szybkim "przepłukaniem":)

Oto więc mój prezent dla Ciebie: czas, który przeznaczałeś na mycie zębów, przeznacz na robienie retrospekcji. Dwa miesiące codziennych retrospekcji to wystarczający czas, aby zauważyć tyle z nich korzyści i nabrać takiego nawyku, że brak retrospekcji stanie się dla Ciebie równie wstrętny, co brak higieny jamy ustnej. A więc do dzieła! Nie myj zębów, rób retrospekcje! :)