Friday, December 14, 2012

Workarounds

Kiedy ostatni raz widziałeś kod w stylu:
if ( param == 4 ) { //workaround, do not touch!

  position.setX( position.getX() + 1 );

}
Workarounds mnożą się niczym wirusy na pożywce i po pewnym czasie potrafią zapaskudzić niezły kawałek kodu. Jest to zmutowana odmiana starego dobrego goto, czyli reagowanie na przypadki szczególne, zamiast spójnej struktury algorytmu.

Skupię się na refaktoryzacji pewnego rodzaju workaround wynikającego z wadliwie działającej klasy.

Wyobraź sobie taką sytuację, że w Twoim projekcie dość intensywnie używana używana jest pewna klasa, np.: związana z jakimś rodzajem obliczeń (finansowych, współrzędnych geograficznych, matematycznych, daty lub czasu itp). Projekt się rozrastał, klasa była używana w kolejnych modułach, kolejni ludzie odwoływali się do niej w swoim kodzie. W konsekwencji mamy taką sytuację, że duża ilość kodu zależy od działania tejże klasy. Tak, można się rozwodzić nad tym, czy ta sytuacja jest ok, czy nie ok. To jest teraz sednem sprawy. Sęk w tym, że z takimi sytuacjami mamy do czynienia.

Nagle okazuje się, że w pewnym przypadku, po wywołaniu pewnej metody z pewnymi parametrami, otrzymujesz niepoprawny wynik. Pomyślisz, że naturalnym krokiem będzie naprawienie błędu. Nic bardziej mylnego! Być może to logiczne, ale ludzie nie działają logicznie (serio!). Jeśli programiści pracują z kodem rozwijanym od lat, a niektórzy z nich "weszli" w temat niedawno, to najważniejszą dla nich rzeczą nie jest ulepszać, lecz nie zepsuć. Ludzie nie biorą się za refaktoryzowanie wadliwie działającego kodu z następujących powodów (w kolejności od najbardziej ważkich):
  • Nie są pewni, że nie popsują czegoś w innym miejscu
  • Brakuje testów (niekoniecznie automatycznych, lecz w ogóle sposobu na przetestowanie czy wciąż jest ok)
  • Obawiają się wziąć odpowiedzialność za skutki swoich działań
  • Wiedzą z grubsza co nie działa i co należy zrobić, lecz nie wiedzą jakie kroki po kolei należy wykonać, aby na końcu wszystko wciąż trzymało się kupy
W konsekwencji zaczynają pisać workarounds podobne do tych przedstawionych wyżej. W miarę upływu czasu bajpasów jest coraz więcej, a zatem jeśli nawet klasę poprawisz i zacznie działać prawidłowo, to problem pojawia się w kodzie klienckim, gdyż jest on przygotowany na wadliwe działanie klasy. Dodajmy do tego, że o niektórych błędach w kodzie klienckim dowiesz się dopiero po paru, parunastu dniach, gdy już trochę podziała. Zatem skoro nie wiadomo, co z tym zrobić, to najczęściej nie robimy nic. A workarounds przybywa. Taki mamy punkt wyjścia.

Kontrola - główny problem refaktoryzacji

Dochodzimy do kluczowego problemu refaktoryzacji. Zespół z reguły wie, co i gdzie jest nie tak z kodem (albo przynajmniej ma feeling). Zazwyczaj wie, jaka powinna być postać docelowa i co konkretnie należy zrobić. Działania nie są podejmowane ponieważ nie wiadomo, jak przeprowadzić przekształcenie w kontrolowany sposób.

Zatrzymaj degradację kodu

Aby nie zapędzić się w pogoń za własnym ogonem, warto uświadomić sobie pewne priorytety. Przede wszystkim najważniejsze jest, aby zatrzymać postępującą degradację kodu. Samo refaktoryzowanie ma drugi priorytet. Jeśli zaczynam refaktoryzować, a w innych miejscach przybywa smellsów, to, jak mówią, lipa.

W jaki sposób zatrzymać degradację kodu? Przede wszystkim nazwij błąd. Programiści najczęściej sami odkrywają wadliwe działanie klasy i sami piszą workarounds. W świadomości zespołu istnieje schemat, że przy użyciu tej a tej metody należy dodać 2 do wyniku. Ludzie uczą się, że należy pisać workarounds. Przede wszystkim trzeba zmienić ten nawyk poprzez zmianę ich myślenia o błędzie. Jeszcze raz, bo to kluczowa sprawa: błąd trzeba nazwać. Na przykład następująco (kontynuuję przykład ze wstępu):
public InvalidCartesianXPatch extends Position {
   private Position patchedPosition ;
   
   public InvalidCartesianXPatch( Position patchedPosition ) {
       this.patchedPosition = patchedPosition;
   }  

   @Override
    public int getX() {
       return param == 4 ? patchedPosition.getX() + 1 : patchedPosition.getX();
    }
}
Jeśli coś nazwiesz, to można o tym mówić (parafrazując Erica Evansa). Zamiast myśleć w kategoriach workarounds, programiści zaczną myśleć w kategoriach patches.

W każdym nowym kodzie klienckim powinien być już używany obiekt z poprawkami. Oprócz nazywania i informowania można zachęcić do tego programistów na przykład następująco;
public Position {
    public static Position createPosition(int x, int y) {
        return new InvalidCartesianXPatch( new Position(x, y) );
    }
  
    @Deprecated
    public Position(int x, int y) {
        //...
    }

    @Deprecated
    public Position( ... ) { }
}

Stwórz testy do kodów klienckich

Gdy degradacja kodu została zatrzymana, można rozpocząć akcję refaktoryzowania już istniejących workarounds. W pierwszej kolejności stwórz przypadki testowe. Testujemy te aspekty zachowania metod w kodzie klienckim, który dotyczy istniejącego workaround. Jeśli metoda jest zbyt duża, wygodnie będzie (nieco sztucznie) ją zdekomponować tak, aby wyizolować fragment z workaround. Zanim ruszysz dalej stwórz testy do wszystkich miejsc, w których występują bajpasy. Tak tak, there is no free lunch.

Zrefaktoryzuj kod kliencki

Zastąp workarounds poprzez łatę i uruchom testy.

Przenieś kod z patcha do klasy docelowej

Oczywiście po napisaniu testów, o ile nie istnieją. Przenieś poprawkę z patcha do klasy, która działała wadliwie. Następnie uruchom wszystkie testy. Jeśli wciąż działa, to możesz pozbyć się wrapperów. W przypadku nowego kodu wystarczy zmodyfikować kod metody createPosition. W poprawianym kodzie trzeba je ręcznie pozdejmować. Ponownie uruchom testy i jeśli wciąż wszystko działa, proces można uznać za zakończony.

Podsumowując

Gdyby wszystko w/w ująć w pojedyncze kroki, to mamy następującą procedurę podstępowania:
  1. Nazwij błąd wprowadzając dekoratora z poprawkami
  2. Zadbaj, aby w nowym kodzie programiści używali klasy z poprawką np.: stwórz nazwany konstruktor w postaci prostej metody fabrykującej, a istniejące konstruktory oznacz przez @Deprecated
  3. Stwórz przypadki testowe, dla wszystkich miejsc w kodzie klienckim, w których występują obejścia
  4. Zastąp workarounds w kodzie klienckim użyciem klasy z poprawką.
  5. Uruchom testy kodu klienckiego
  6. Napisz przypadki testowe do wadliwie działającego fragmentu kodu usługi
  7. Przenieś patch z dekoratora do klasy usługowej
  8. Uruchom testy klasy usługowej
  9. Uruchom testy kodu klienckiego
  10. Zdejmij dekoratory z klasy usługowej
  11. Uruchom testy

Przeprowadzenie całego procesu trzeba by liczyć raczej w tygodniach niż w godzinach. Szybkie numerki akcja refaktoryzacja często sprawiają więcej kłopotów niż korzyści. Bardziej strategiczne podejście do refaktoryzacji i przeprowadzanie jej według uporządkowanego procesu jest bezpieczniejsze.

Wednesday, October 17, 2012

Ale jaja...:)

Mariusz właśnie wyczaił, że ktoś na Allegro sprzedaje naszą książkę "Eseje o efektywności programistów". O tutaj i tutaj. Biorąc pod uwagę, że my jej nie sprzedajemy, tylko rozdajemy za darmo na szkoleniach - gratulujemy przedsiębiorczości :)! Dziękujemy bardzo za atrakcyjną wycenę książki. Ufamy, że odzwierciedla ona wartość dla sprzedającego.

Pozdrawiamy i życzymy udanych aukcji:)!
MB & MS

P.S. Na jednej z w/w aukcji sprzedawca oferuje przesłanie darmowego fragmentu. Nieśmiało chcieliśmy zaznaczyć, że zgodnie z deklaracją (C) na wewnętrznej stronie okładki jest to niedozwolone. Aczkolwiek wzruszeni tą inicjatywą handlu drugiego obiegu i świadomi, że osiągamy w ten sposób również cel marketingowy, niniejszym udzielamy rzeczonemu sprzedawcy pozwolenia na wysyłanie darmowych fragmentów nie dłuższych niż jeden rozdział:)

Gdy programista zostaje liderem

Napisano już tony książek na temat leadershipu i efektywności, które z pewnością masz gdzieś na dysku. Nie będę się więc silił na sformułowanie ogólnych zasad do wszystkiego, bo albo ktoś to już zrobił albo takowe nie istnieją :) Mam jednak parę spostrzeżeń na temat, tego o czym warto pamiętać, gdy do tej pory byłeś przede wszystkim programistą, a teraz zostałeś liderem programistów.

1. Akcja powoduje reakcję

Bywa, że programista zostający liderem, w przypływie entuzjazmu zaczyna mylić proaktywność z hiperaktywnością. Często myśli sobie: "do tej pory znosiłem ten kod, ale teraz wszystko się zmieni" i zaczyna zmieniać.
Sęk w tym, że każde rozpoczęte działanie, co jakiś czas "domaga się uwagi". Jeśli komuś coś zlecisz, to w końcu przyjdzie on z jakimś pytaniem na temat zadania. Im więcej działań rozpoczniesz, tym więcej aktywności będziesz musiał później podejmować - wykładniczo więcej. Świeżo upieczony lider, próbuje wprowadzić zmiany zakładając, że zmiana jest to proste przeprowadzenie stanu aktualnego w stan docelowy. Tymczasem jest to nieco bardziej złożone. Model wprowadzania zmiany podobny jest do tego przedstawionego na rysunku (w tym poście tylko skrótowo). Zainicjowanie zmiany to tylko początek, po jakimś czasie przychodzi kryzys, przez który należy zespół przeprowadzić. Bez aktywności lidera, zespół wróci do stanu początkowego, gdyż wtedy "jest źle, ale przynajmniej wiemy co trzeba robić". Z tego względu początkowa hiperaktywność prowokuje zbyt wiele kryzysów w zespole. Lider nie jest w stanie ogarnąć wszystkich i zmiana się nie udaje. Młody lider ma zazwyczaj wyrzuty sumienia. Myśli, że się nie nadaje do nowej roli i chce znów być programistą (@see kryzys w zmianie). Problem zazwyczaj nie tkwi w konkretnej osobie, lecz w niewłaściwym działaniu. Zacznij więc od wprowadzenia jednej zmiany, a gdy się ustabilizuje, pomyśl o kolejnych. Zanim zaczniesz jednak zmieniać, zastanów się co? i po co?.

2. Naucz się rezygnować

Tak to już jest, że najchętniej lubimy robić rzeczy, które nam wychodzą. Jeśli jesteś świetnym programistą i uczysz się jak być liderem, to będziesz często odczuwać pokusę, aby osobiście implementować zadania, z którymi nie mogą poradzić sobie programiści albo będziesz przydzielał sobie tyle samo zadań programistycznych co do tej pory. O tym, czy lider zespołu powinien programować i jak to godzić z zadaniami wynikającymi z roli lidera toczy się wiele dyskusji i jest wiele podejść do tego zagadnienia. Ja jestem przekonany co do jednego: niezależnie od tego, czy programujesz, czy nie Twoja optyka powinna być zawsze nakierowana na zespół. Twój sukces nie oznacza już sukcesu indywidualnego, lecz wprost zależy on od sukcesu zespołu, któremu przewodzisz. Możesz mieć co do tego pewne obawy, więc napiszę o nich wprost. Tak, nie będziesz programować tyle, co do tej pory. Tak, będą okresy, że nie będziesz programował w ogóle. Tak, możesz przestać być na czasie z nowinkami technologicznymi. Tak, szczegółowe zagadnienia dotyczące technologii, frameworków, mogą zacząć blaknąć w Twojej pamięci. Nie, nie zapomnisz jak się programuje. Tak, zaczniesz zauważać, że pewne klasy problemów rozwiązuje się w podobny sposób. Tak, jeśli wprowadzisz proces wymiany wiedzy, będziesz korzystał z wiedzy i doświadczenia programistów, aby na ogólnym poziomie być zorientowanym w temacie. Tak, będziesz zauważał, że niektórzy programiści popełniają błędy podobne do tych, które ty popełniałeś. Tak, rozwijanie umiejętności innych jest równie fascynujące jak rozwijanie własnych.

3. Nawyki są ważniejsze niż cele

Żyjemy w obsesji celów. Na każdej rozmowie rekrutacyjnej pytają o największe osiągnięte cele i porażki. Cele same w sobie są nudne. Większość z nas posiada umiejętność "spięcia się w sobie" i osiągnięcia jakiegoś tam celu. Jest jednak coś ważniejszego niż cele - nawyki. Gdyby nawyki i cele położyć na szali, to relacja między nimi jest taka, jak relacja między wartościami po prawej i po lewej stronie w Manifeście Agile. Czyli: wiemy, że cele są ważne i doceniamy je, lecz nawyki cenimy bardziej. Ironia polega na tym, że osiąganie celów bez nawyków (czyli jednorazowe pospolite ruszenie) może być męczarnią. Ale dzięki nawykom cele osiągają same. Jaki z tego pożytek dla lidera programistów? Ano, na przykład taki:
  • nie zmuszaj ludzi, aby wymienili się wiedzą i za dwa miesiące byli zespołem cross-functional (jak to zmierzyć?), zamiast tego wprowadź zwyczaj regularnych (dobrze określonych w czasie) spotkań i dyskusji na tematy techniczne
  • nie baw się w strażnika, który zagania ludzi do pracy, zamiast tego rób codzienne stand-up meetings
  • nie ogłaszaj, że za pół roku system ma być zrefaktoryzowany w całości, zamiast tego wprowadź zwyczaj code review.

4. Wielkie problemy biorą się z małych zaniedbań

Nie chodzi o pedantyzm graniczący z obsesją. Chodzi o świadomość, że nasze działanie to niezliczone ilości ciągów przyczynowo-skutkowych, a końcowy skutek może stać się przyczyną dla kolejnych ciągów przyczynowo-skutkowych. Zupełnie jak to domino. Kiedyś napisałem wpis o refaktoryzacji "Myjcie swoje kubki", w którym chodziło o to, że lepiej regularnie robić drobne refaktoringi (@see nawyk), niż raz na jakiś czas wybebeszać pół systemu (tak, wiem, czasem jest to nieuniknione). Z perspektywy lidera jest podobnie. Jeśli coś Ci się w funkcjonowaniu zespołu rozstraja, reaguj od razu. Nie zwlekaj do momentu, aż drobny kłopot stanie się przyczyną kolejnego ciągu, i kolejnego, i kolejnego, aż możliwość reakcji przekroczy Twój zakres kompetencji.

5. Wielkie osiągnięcia biorą się z małych ulepszeń

Lider często ma marzenie, aby poustawiać wszystko tak, aby było dobrze i niech to to tak już zawsze działa. Po pierwsze nie ma żadnego "dobrze" i nie ma żadnego "na zawsze". Próba zorganizowania pracy zespołu tak, aby potrafił wykonać każde zadanie przypomina trochę implementowanie superelastycznych rozwiązań "na wszelki wypadek". Rzeczywistość tak niestety nie funkcjonuje, co nie oznacza, że jesteś tu bezradny. Pilnuj dwóch głównych zasad:
  1. Szybko rozwiązuj problemy lokalnie
  2. Lokalne rozwiązania standaryzuj tak, aby stały się częścią całego procesu

6. Wprowadzaj FRAMEworks i workFLOWs

(Nie mówimy teraz o bibliotekach programistycznych) Główną perspektywą patrzenia na zespół są procesy w nim działające. Słowa "framework" i "workflow", których częścią jest słowo "work" elegancko oddają, jak lider powinien organizować ową "work" w zespole. Przede wszystkim dla pracy powinien być zdefiniowany "frame". Ludzie muszą widzieć, że coś się dzieje według jakiegoś schematu. Na przykład tablica scrumowa nadaje "frame" pracy zespłu - "coś (karteczka) gdzieś musi się znaleźć (tablica), to coś na jakiejś podstawie (definition of done) przechodzi do kolejnego etapu (done), itd". Ludzie wiedzą: co mają zrobić, jak mają robić i kiedy skończyli.
Drugie słowo uwypukla "flow" procesu. Proces ma być płynny, bez zbędnych przestojów, bez zatorów, z optymalną ilością wykonywanej pracy. Na przykład "flow" w Scrumie stymulowane jest poprzez narzucenie stałych iteracji, mierzenie prędkości zespołu, nacisk na regularność, rytm, szybki feedback.

7. Działa tylko to, co robisz

Na koniec najcenniejsze, ale jak to zazwyczaj bywa - najbardziej oczywiste spostrzeżenie - żeby coś zadziałało, musisz to robić. Zadziwiające, że czasem gdy pracuję z zespołem omawiamy konkretne techniki, to wszyscy kiwają głowami - tak to jest ok, to jest ważne, a potem nikt nic nie robi i jednocześnie wszyscy są przekonani, że nie działa. Entuzjazm po szkoleniu trwa jakiś tydzień, potem się kończy i często kończy się noworozpoczęte działanie (@see kryzys w zmianie). Pamiętaj, konkretne techniki działają jeśli je robisz. Jeśli ich nie robisz, nie będą działać. Na przykład Daily Scrum. Zespoły, często robią, potem trochę im się spotkania przeciągają, czasem spotkanie odwołają, a w końcu stwierdzają, że wystarczy jedno w miesiącu. Jednocześnie wszyscy mają miliony racjonalizacji dlaczego to jest ok. Owszem, powody są nieraz ważkie, ale powiedzmy jasno: nie, nie, nie i jeszcze raz nie. W ten sposób Daily Scrum nie będzie działał. I to nie Scrum jest zły, tylko ktoś przed zastosowaniem nie przeczytał ulotki i teraz jest zaskoczony, że pojawiły się skutki uboczne. Myśl długo nad wprowadzeniem danej praktyki do zespołu, ale jeśli już wprowadzisz, to konsekwentnie ją kontynuuj i daj jej szansę zadziałać.

Wednesday, October 3, 2012

Cytat miesiąca

Źródło: Wikipedia

Bardzo często zainteresowania takie obracają się obecnie wokół komputerów do tego stopnia, że zespół Aspergera nazywany jest w krajach zachodnich "geek syndrome", czyli chorobą maniaków komputerowych. Spowodowane jest to tym, że komputery zostały stworzone z myślą o składowaniu i przetwarzaniu informacji, co jest ulubionym zajęciem ludzi z tym zespołem

Thursday, August 2, 2012

Zawsze pracuj na twardych danych

Czasem zdarza Ci się spotkać z jakimś problemem związanym z algorytmem, architekturą, sprawami organizacyjnymi itp. Sporo pracuję z ludźmi nad rozwiązywaniem problemów tego rodzaju i zauważyłem, że czasem umysł albo nasze własne przyzwyczajenia utrudniają nam znalezienie rozwiązania. Poniżej spisałem kilka rzeczy, o których warto pamiętać, gdy szukasz rozwiązania jakiejś kwestii. Być może te rzeczy wydadzą Ci się oczywiste, ale zdążyłem się już przekonać, że oczywistych rzeczy nauczyć się najtrudniej. Oczywiste jest na przykład, że korzystniej dla zdrowia swojego i innych być zrelaksowanym, a mimo to obroty z leków uspokajających są obrzydliwie wielkie. Rzecz trudną i oczywistą poznasz po tym, że wszyscy o niej mówią i wszyscy wiedzą, ale mało kto ją robi.

Myśleć o problemie, czy o rozwiązaniu?

Lubimy czasem powtarzać zasłyszane frazesy. Jednym z nich jest "myśl o rozwiązaniu zamiast o problemie". To mądre zdanie w powszechnym użytku staje się frazesem. Na czym polega frazesowanie, tej światłej myśli? Otóż przede wszystkich chodzi to o "koncentrowanie się" na problemie. O sytuacje, w których tak obsesyjnie myślisz o danym błędzie lub sprawie do rozwiązania, że to myślenie przesłania kreatywności i nie pozwala dostrzec rozwiązań. To trochę tak, jakbyś spędził kilka dni na projektowaniu warstwy dostępu do danych z użyciem Hibernate, stosując najbardziej wyrafinowane mapowania i ani razu nie zastanowił się nad pytaniem Czy Hibernate jest tu w ogóle potrzebny?


Przede wszystkim pamiętajmy, że nie znajdziesz rozwiązania, jeśli nie rozumiesz natury problemu, z którym masz do czynienia. Najpierwszejsze pytania, które trzeba sobie zadać, to O co właściwie chodzi? Z czym właściwie mam do czynienia? Jak to działa? Co po kolei się wydarza, że jest taki a taki rezultat?

Posługuj językiem twardych liczb

I tu najczęściej jest klops. Pewien programista, z którym ostatnio pracowałem mierzył się ze złośliwym problem. Miał stworzyć transformaty migrujące dane z jednego systemu do drugiego. Z różnych powodów posiadał w tamtej chwili szczątkową wiedzę na dany temat, co więcej polecono oszacować mu czas realizacji zadania. Do tego momentu jeszcze wszystko w miarę gra.

Sformułowanie problemu jest kluczowe
Kłopot tkwił w tym, w jaki konkretnie sposób ten programista podchodził do pracy. Otóż, gdy tłumaczył mi na czym polega rzecz mówił mniej więcej tak "powiedzmy, że mamy obiekt A i A'. A' znaczy w tym systemie co innego niż w tamtym A. I teraz nie do końca wiemy jak stworzyć taką trasnformatę, jak zmapować obiekty na siebie. Jakie są podejścia do tego typu zadań?" Odpowiadam: nie ma żadnych podejść. I nie wynika to z natury problemu, lecz z błędnego jego sformułowania.

Zauważ, że programista sformułował problem na dość wysokim poziomie abstrakcji. Uogólnił go, jeszcze nie w pełni rozumiejąc w czym rzecz. W ten sposób przeszedł do bardzo abstrakcyjnego myślenia. I tak powiem...konkretne sformułowanie problemu => konkretne rozwiązanie, abstrakcyjne sformułowanie problemu => abstrakcyjne rozwiązanie. Dlaczego? Dlatego, że przy tego typu sformułowaniach, za każdym razem, gdy wpadnie Ci do głowy jakieś rozwiązanie, jesteś tak zteoretyzować problem, że znajdziesz takie konteksty i takie przypadki szczególne, że rozwiązanie będzie do bani.

Na ogólnym poziomie nie ma rozwiązań, problemów, owszem, jest od groma. Rozwiązania istnieją tylko w konkretnych rzeczywistych mierzalnych danych. A zatem zawsze pracuj na twardych liczbach, gdy tylko próbujesz rozwiązać jakiś problem. Dopiero potem, gdy będziesz już mieć wystarczająco wyraźny obraz rzeczywistości, będziesz mógł postawić hipotezy rozwiązania, a następnie próbować je w ogólnym przypadku. W tej właśnie kolejności: najpierw konkret, potem abstrahowanie. Nigdy odwrotnie.

Procedura postępowania

Jak zatem wygląda procedura działania? Posługując się w/w przykładem z transformatami, mamy:
  1. Zrozum wszystkie przypadki szczególne (Co reprezentują poszczególne obiekty w każdym systemów? Jakie jest ich znaczenie biznesowe? Jakie informacje przechowują? Jakie są reguły spójności danych?)
  2. Zbuduj rozwiązanie dla najprostszego przypadku (Napisz transformatę dla konwersji pojedynczych pól)
  3. Zbuduj rozwiązanie dla każdego przypadku szczególnego (Stwórz transformatę dla: konwersji prostego obiektu, dwóch obiektów w relacji 1-1, dwóch obiektów w relacji *-1...)
  4. Poszukaj części wspólnej (Czy, któraś z kolejnych transformat, "załatwia" poprzednie? Czy można napisać jedną transformatę dla 90% przypadków, a pozostałe 10% przypadków obsłużyć małymi transformatami?)
  5. itd

Tak, to zajmuje czas. Czasem dużo czasu. Ale z każdą godziną, rozwiązanie pokrywa coraz większą część problemu. Przeciwnie, gdy od samego początku próbujesz rozwiązać teoretyczny ogólny problem, to z każdą godziną problem się komplikuje, a rozwiązań nie ma.

Wednesday, July 25, 2012

Nowy czelendż

Postanowiłem spróbować czegoś nowego. Będę prowadził zajęcia na studiach podyplomowych na kierunku Komunikacja i sprzedaż w branży IT w Uczelni Łazarskiego w Warszawie. Mój przedmiot to Zbieranie i analizowanie wymagań klienta. Szczególnie niecierpliwie czekam na pracę z resztą wykładowców. Uczelnia zgromadziła naprawdę doborową kadrę - górna półka coachów i trenerów biznesu działających na naszym rynku (mb: rzecz jasne mam na myśli swoich współwykładowców). Ciekawe jak będzie? :)

Tuesday, July 17, 2012

3 kluczowe przekonania i 1 umiejętność

Trzy kluczowe przekonania skutecznego "zarządzania czasem" (do uszczegóławiania w dalszej przyszłości):

  1. Wielkie problemy biorą się z małych zaniedbań.
  2. Wielkie osiągnięcia biorą się z małych ulepszeń.
  3. Żeby coś zacząć robić, trzeba coś przestać robić.

Kluczowa umiejętność: aserytwność. Żadna technika zarządzania czasem nie zadziała, jeśli pozwalasz sobie wepchnąć każde zadanie i jesteś zwyczajnie przeładowany. Nie daj sobie wmówić, że powinieneś robić jeszcze więcej, jeśli Twój bufor się przepełnia. Z drugiej strony pamiętaj, że każdy z nas potrafi świetnie racjonalizować dlatego nie ma czasu na zajęcie się nowym zadaniem. Ta chwiejna równowaga jest elementem cennej postawy jaką jest samoświadomość.

I jedno pytanie do przemyślenia. Wszyscy mówią: "rób przede wszystkim rzeczy ważne, uważaj na rzeczy pilne, żeby nie wypełniły Ci całego dnia". Proste pytanie: Jak?
  • Po jakich konkretnie atrybutach poznasz, że dane zadanie jest pilne?
  • Po jakich konkretnie atrybutach poznasz, że dane zadanie jest ważne?
  • Macierz Eisenhowera mówi: rzeczy pilne deleguj. A jeśli nie masz komu delegować?
  • Czy jeśli cały dzień robię tylko rzeczy ważne, a pilne przesuwam to jest ok?
  • Macierz Eisenhowera mówi: rób rzeczy ważne zanim staną się pilne. Czy to znaczy, że pilne nigdy nie stają się ważnymi? A jeśli tak, to kiedy?

Saturday, June 30, 2012

Confitura 2012

UPDATE: Dostaję pytania o prezentację z konferencji. Ostrzegam, że jest oszczędna, bo stawiam raczej na gadanie niż na pokazywanie. Komuś, kto nie był na prezentacji, niewiele ona powie.Umieszczam tutaj.

To, w jaki sposób zorganizowaliście darmową konferencję w takim full wypasie, to chyba pozostanie Waszą tajemnicą. Dziękuję!

Żałuję, że nie mogłem się podwoić a potem znów podwoić, aby być na wszystkich prelekcjach. Szczególnie ubolewam, że nie dowiedziałem się o tym dlaczego pozbywać się wzorców i nic o testach, bo odbywały się tym samym czasie co moja prezentacja. Może dla prelegentów powinny być powtórki :) Byłem u Grześka Dudy i Piotra Burdyło - to był wyjątkowo dobrze zainwestowany czas. Zyskałem przede wszystkim inne spojrzenie na kwestie, nad którymi sam pracuję i się zastanawiam.

Jeżdżę sobie trochę po konferencjach i muszę uczciwie przyznać, że na tej doświadczyłem czegoś zupełnie nowego. Było...rodzinnie. Zaraz po wejściu do budynku Tomek Dziurko przywitał mnie jak starego dobrego znajomego, a przecież znamy się tylko z wymiany paru maili. Nie wiem co sprawiło, że pojawiła się ta rodzinna więź. Może tweetowanie, może czujne oko organizatorów gotowych do pomocy w każdej chwili, a może coś innego.

Zazwyczaj znikam z konferencji zaraz po swojej prezentacji, tym razem z powodów rodzinnych również tak było. Lecz tym razem po raz pierwszy było mi na prawdę z tego powodu przykro. Nawet puściłem to na tłyterze. Potem już zupełnie rozbroił mnie Bartek Zdanowski, który myśląc, że jako uczestnik nie miałem zaproszenia na spoinę, zapytał po prostu: "A może chcesz przyjść?". I jak tu się nie wzruszyć? Za wartościowe prezentacje i przede wszystkim za te przeżyte emocje Kapitule Confitura 2012 bardzo dziękuję.

Tuesday, June 26, 2012

Ludzie książki piszą

Dwa lata temu pewna firma postanowiła wesprzeć swoje procesy za pomocą systemu ERP. Mieli wiele małych systemów, ale marzyło się im kompleksowe rozwiązanie. Tak się złożyło, że dostałem zlecenie zebrania wymagań, a następnie zaprojektowania architektury owego.

Dwa tygodnie później zachodziłem w głowę jak to się mogło stać, że uzbrojony w całą wiedzę z wiązaną z UMLem (i zakupionym na tę okazję EA), architekturą, programowaniem i doświadczeniem związanym z wytwarzaniem oprogramowania, poniosłem katastrofalną Klęskę. Dokładnie tak Klęskę przed duże "K". Czułem podskórnie, że ten projekt się nie uda i po jakimś czasie okazało się, że miałem rację. Lecz co z tego, ze miałem rację, skoro klient był niezadowolony? Pozostał z nierozwiązanym problem. Problem, którego ja nie potrafiłem namierzyć oraz nazwać.

Kilka tygodni później przypadkiem brałem udział w szkoleniu i prowadzący niby przypadkiem powiedział takie zdanie: "Problem jest początkiem rozwiązania". Do końca szkolenia nie mogłem się już skupić na niczym innym niż to, kołaczące mi w głowie zdanie: "problem jest początkiem rozwiązania".

Po powrocie do domu napisałem ten post. Potem obsesyjne zacząłem zastanawiać się nad moim problem związanym ze zbieraniem wymagań do wspomnianego systemu ERP. Potem w trakcie kolejnych rozmów z klientami zacząłem zauważać coraz więcej reguł jakimi rządzą się takie rozmowy. Powoli włączałem moje odkrycia do swoich szkoleń. W końcu postanowiłem napisać książkę.

Dlaczego ta książka warta jest Twojego czasu? Zwróć uwagę, że wszystkie popularne metodyki w inżynierii oprogramowania: począwszy na OOD a na DDD skończywszy mówią o: odwzorowywaniu rzeczywistości, modelowaniu procesów biznesowych, modelowaniu dziedziny, kruszeniu dziedziny, itd. I tylko drobnym druczkiem jest w tych książkach napisane, że zakłada się, iż wiadomo, co trzeba zrobić. A guzik prawda! Nie bez powodu narzekamy na nieprecyzyjne wymagania. Zapewniam Cię, że gdybyś dokładnie wiedział, co należy zrobić, to nie miałbyś najmniejszych kłopotów z zastosowaniem OOD, TDD, BDD, DDD, DDDD i jeszcze więcej "D". Z architekturą i późniejszym utrzymaniem też by nie było kłopotów.

Metody inżynierii oprogramowania zajmują się modelowaniem rzeczywistości. Ta rzeczywistość znajduje się w głowach Twoich klientów. I o odkrywaniu właśnie tej rzeczywistości jest książka Oprogramowanie szyte na miarę. Jak rozmawiać z klientem, który nie wie, czego chce?.



Friday, March 23, 2012

Craftsmanship nie dla wszystkich?

Big szacun dla tych, co wrzucają po 2 posty dziennie. Ja opierałem się wyrzutom sumienia aż do tej pory. Chyba właśnie regularność i rytm są tu kluczowymi rzeczami. Wiele razy przychodził mi pomysł na wpis, ale odkładałem na później. Pomysł tracił na wyrazistości, blakł, aż całkiem zupełnie znikał. No nic, pożyjemy zobaczymy.

Nawiedziło mnie następujące przemyślenie czy Craftsmanship jest dla wszystkich? Jeśli mówimy o ciągłym doskonaleniu warsztatu to jak najbardziej. Jako myśli filozoficzna i reguła życia zawodowego jest warta rzetelnego praktykowania. Zmieńmy jednak punkt widzenia i wejdźmy w buty szefa działu developmentu.

Ilu minimalnie czarodziei potrzebuję?

Umiejętności kosztują. W doświadczonego osobnika, który ma wysoko rozwinięte cechy pożądane u adepta Craftmanship
trzeba dużo zainwestować. Zupełnie naturalnie przychodzi do głowy pytanie, czy wszyscy programiści muszą być świetni.
Z całą odpowiedzialnością muszę powiedzieć, że nie. Tu niestety rządzi ekonomia. No i rozkłady statystyczne. Jeżeli na dwudziestu programistów przypada jeden czarodziej, który będzie strzegł ładu i składu w architekturze, to zespół spokojnie da sobie radę. Jeszcze raz bez ogródek: nie wszyscy programiści są tyle samo warci, nie we wszystkich warto w równym stopniu inwestować, można zadowolić się określoną liczbą ludzi przeciętnych albo nawet słabych i ile tylko będą potrafili napisać to, co im się każe. Jeśli w kilkusetosobowym dziale uda się zebrać powiedzmy 6-8 osobowy dream team, który wymyśli superrozwiązanie każdego problemu, to reszta tłumu może spokojnie robić swoje.

Jak uniezależnić się od kodera?

Kiedyś przy jakieś okazji powiedziałem "nie da się programisty zastąpić skończoną liczbą studentów; to tak jakby prezesa chcieć zastąpić skończoną liczba konsultantów". Trzeba uściślić tę opinię "nie każdego programistę można zastąpić skończoną ilością studentów". Tych pojedynczych najlepszych pewnie nie, ale znakomitą większość jak najbardziej. Potrzeba tylko, aby niezastąpieni tworzyli takie architektury, przygotowywali takie półprodukty, takie frameworki, w których nie trzeba za wiele myśleć, wystarczy kodować. W ten sposób można już traktować większość programistów jako wymienny zasób. Doprowadzenie do tej sytuacji to kwestia odpowiedniej strategii, czasu i pieniędzy.

Bezpańscy czeladnicy

Trzymajmy się dalej tej perspektywy. Za Craftmanship idzie zapomniany już niestety model Mistrz-Czeladnik. Uczeń szukał swojego mistrza, u boku którego praktykował. Myślę, że wielu programistów nie ma od kogo się uczyć. Albo nie spotykają na swojej drodze wystarczająco kompetentnych i cierpliwych mistrzów albo wtłoczeni w rolę wymiennego kodera, włóczą się od firmy do firmy. Tacy właśnie bezpańscy czeladnicy. Zdobędą trochę doświadczenia to tu to tam na własnych błędach, nie mając nikogo u boku kogo wskazał by im kierunki rozwoju i doradził.

No, na czarno dzisiaj trochę. Ale tak mnie dopadło:)