niedziela, 10 marca 2013

Więcej nie znaczy wolniej cz.3 - projektowanie

zaprojektujmy coś...

Kiedy przeprowadziliśmy już analizę i wiemy, co klient chce abyśmy zrealizowali, wiemy, czego nie chce i obie strony rozumieją co i jak ma działać, możemy ruszać dalej, czyli przełożyć wymagania na coś, co lepiej pasuje do naszego obiektowego świata:)
Jednym zdaniem - pora na zaprojektowanie naszej aplikacji.

a czymże jest ten projekt? Projektowanie != UML

Dla wielu odpowiedź na to pytanie jest jasna i prosta - projekt to jakieś diagramy, jakieś strzałeczki z pustymi bądź wypełnionymi grotami, jakieś atrybuty, metody i wszystko to, co kryje się pod tajemniczym akronimem UML. Czy tak jest w rzeczywistości?

Wielu programistów (niestety) ma w oczach strach, gdy tylko usłyszy nazwę UML, a na pytanie, czy potrafią czytać diagramy napisane w tym języku niepewnie kiwają głową i mruczą pod nosem, że coś tam, kiedyś, ale to było dawno i chyba na studiach, albo i nie... ale tak - raczej... potrafią. Tych wszystkich i tych, którzy nie czują się pewnie z diagramami chciałbym pocieszyć - projektowanie to nie jest UML. Tak samo jak programowanie obiektowe to nie PHP czy Java. To są jedynie języki ułatwiające nam realizację określonych zadań.

Prawda jest taka, że nie musimy używać ani znać UML'a, aby projektować. Oczywiście sam namawiam do nauki tego języka w stopniu co najmniej umożliwiającym czytanie diagramów. Dlaczego? Z jednego prostego powodu - jest to język formalny i bardzo prawdopodobne, że wcześniej czy później z nim się zetkniecie i warto wtedy wiedzieć "z czym to się je".

Mimo to, znajomość UML nie jest wymogiem, co oczywiście nie oznacza, że żadnych wymagań co do projektu nie ma. Jest kilka, a jednym z najważniejszych moim zdaniem jest: Projekt musi być zrozumiały dla wszystkich osób zainteresowanych.

zrozumiały projekt? A da się inaczej?

Niestety się da i szczerze mówiąc, to nie trudno osiągnąć taki stan rzeczy. Nawet wykorzystując język UML, osoba wykonująca projekt może zrobić to w taki sposób, że nikt poza nią nie będzie w stanie połapać się co z czym i gdzie i dlaczego. Niekiedy nawet sam autor ma z tym problemy.
A czym w takim wypadku jest produkt pracy tej osoby, jak nie straconym czasem? Jeżeli nikt nie jest w stanie tego zrozumieć, to nikt z tego nie będzie korzystał, a jeżeli nikt z tego nie będzie korzystał, to nie warto było poświęcać choćby minutę na pracę nad projektem zrealizowanym w taki sposób.

Dlatego też najważniejszą rzeczą, przy tworzeniu projektu jest to, aby każdy osoba, która z jakichś powodów będzie "zmuszona" się z nim zetknąć, bez problemu była w stanie zrozumieć wszelkie jego zawiłości. I co równie istotne - zrozumieć to w taki sam sposób, jak wszystkie pozostałe osoby:) A to czy jest to UML, czy preferujecie inną formę przekazu tych informacji, to już kwestia indywidualna (indywidualna w sensie zespołu).

ach... żeby to jeszcze dla oka przyjemne było

Poza tym warto również pamiętać, że projekt to nie koniecznie jeden diagram/dokument.
Niestety większość osób, która rozpoczyna swoją przygodę z projektowaniem często stara się zmieścić wszystko w jednym miejscu. Jaki jest efekt? Brak czytelności, niekiedy tak wielki, że nawet pomimo tłumaczenia, można mieć spore problemy ze zrozumieniem.

Moja rada jest prosta - zacznijcie od ogółu i na kolejnych ekranach/stronach/dokumentach pokazujcie coraz więcej szczegółów. Umieszczanie wszystkiego w jednym miejscu wcale nie zaoszczędzi czasu, który spędzicie przeskakując z diagramu na diagram, a niekiedy może być powodem bezużyteczności projektu.

Oczywiście jest jeszcze wiele innych cech dobrego projektu, ale nie jest to tematem dzisiejszego wpisu. Natomiast z powyższym "problemem" spotyka się naprawdę większość osób, które próbują swoich sił z projektowaniem. Dlatego też chciałem przed nim przestrzec.

projektowanie jest zbędne - to kod przedstawia wartość!

Jest to pogląd, z którym walczyłem niejednokrotnie. Projekt przecież jest tylko dla programistów, którzy pracują nad aplikacją, nie dość, że trzeba poświęcić czas (czyt. stracić czas:) na jego stworzenie, to jeszcze należy go później zaimplementować, a i tak może się okazać, że projekt nie jest idealny i trzeba będzie nanieść poprawki.

Śmiem nawet stwierdzić z pełnym przekonaniem, że nie będzie, a przynajmniej są na to niewielkie szanse.

Niejednokrotnie w trakcie implementacji decydowaliśmy się na wprowadzenie poprawek do projektu. Z tym, że na poprawkach się kończyło. Nigdy nie zdarzyło się, abyśmy w trakcie implementacji zdecydowali się na spore modyfikacje. W przypadku braku projektu takie całkowite przebudowanie kodu zdarzało się zbyt często.

Oczywiście przekłada się to bezpośrednio na pieniądze.
Poprawka (którą rozumiem jako np. niewielką zmianę definicji metody) nie kosztuje wiele, ot, aktualizacja diagramu i ewentualne uzupełnienie go. Przy dobrych projektach uzupełnianie to rozwój, a nie zmiany. Dodatkowo takie "uzupełnienia" również testują jakość projektu, ponieważ im mniej bolesne jest ich przeprowadzenie, tym lepszy projekt.

Co w przypadku zmian kodu? Po pierwsze, ten kod został już napisany, czyli programista przemyślał go, czyli chcąc nie chcąc, poświęcił czas na pewnego rodzaju niewspółdzielony projekt, który od razu zapisywał w postaci kodu. W trakcie implementacji mógł kilkukrotnie zauważać braki w tym, jak widział problem na początku, co pociąga za sobą zmiany w kodzie. Zmiany w testach jednostkowych? Interfejsach? etc. Na koniec, po walkach z implementacją, po osiągnięciu sukcesu, oddaje kod do review i tam dowiaduje się, że można było to rozwiązać w lepszy sposób, zastosować kilka wzorców, rozdzielić obowiązki klas itp. I wraca do punktu wyjścia z poczuciem (w niektórych przypadkach) porażki.

A wszystkiego można było uniknąć (czyt. zaoszczędzić pieniądze) poprzez wcześniejszy projekt i jego omówienie.

Jak widać owa "strata" czasu i pieniędzy, to tak naprawdę oszczędność.
Z drugiej strony, warto pamiętać, że zaprojektować kod trzeba zawsze, programista siadając do klawiatury musi mieć jakąś wizję. W takim wypadku czemu tej wizji nie spisać? Podzielić się nią i omówić przed przystąpieniem do implementacji? O ile zmniejszymy ryzyko wystąpienia potencjalnych zmian i błędów?

projekt? ale przecież wiadomo o co chodzi?

Wiele osób identyfikuje projektowanie ze zbieraniem wymagań i ich analizą, dlatego też, w przypadku, gdy posiadają te wymagania, dochodzą do wniosku, że jego tworzenie jest czynnością zbędną.
Projekt jednak nie jest równoznaczny ze zbieraniem wymagań, jest to przedstawienie sposobu ich realizacji i aby stworzyć dobry projekt musimy je znać (czyli już je zebraliśmy) oraz wiedzieć o co w nich tak naprawdę chodzi (czyli zostały one już przeanalizowane).

Więc czym jest projekt? Jaki jest jego produkt końcowy?
Powinno nim być rozwiązanie problemu, którym jest konkretne wymaganie przedstawione przez użytkownika.

programiści boją się być sprowadzeni do roli klepacza kodu

To jest największy problem, z którym się spotkałem w swojej karierze. Ciężko przekonać szefa, że warto, trudno to wytłumaczyć managerowi, ale prawdziwe schody zaczynają się wtedy, gdy sami programiści odczuwają mimowolną panikę i brak zrozumienia dla potrzeby stworzenia projektu.

Skąd bierze się tej strach?
Wydaje mi się, że wielu programistów nierozerwalnie łączy etap projektowania z programowaniem dlatego nie lubią jakichkolwiek prób mających na celu ich rozdzielenie na osobne aktywności. Wydaje im się, że po stworzeniu projektu już nic twórczego nie zostaje dla nich. Takie przeświadczenie ma również wiele osób zarządzających projektami.
Nic bardziej mylnego. Implementowanie metod, "tłumaczenie" projektu na kod to tak samo istotne i kreatywne zajęcie, jak tworzenie interfejsów i nie wydaje mi się rozsądnym umniejszać czyjejkolwiek roli. Każda aktywność jest czymś innym i co innego ma na celu. Inny jest jej produkt końcowy. I aby stworzyć ten produkt (przekuć wymagania na projekt, projekt na działającą aplikację) trzeba posiadać spore umiejętności i wiedzę.

lepsze jest wrogiem dobrego

W takich superlatywach piszę o tym całym projektowaniu, a przecież istnieją jeszcze ciemne strony tej aktywności. Jak ze wszystkim - nie wolno przedobrzyć.

Często programiści nie potrafią uciec w swoich projektach od kodu, implementacji. I nie chodzi mi tym razem o powszechne "skażenie technologią", a o poziom szczegółowości produktu wynikowego. Niekiedy zdarza się, że w komentarzach jest tyle "sugestii" dotyczących implementacji, że gdyby posadzić w miarę rozgarniętą osobę, która nigdy nie miała przyjemności programować, to miałaby spore szanse poradzić sobie z tym.
Jednak nie tędy droga, pamiętajcie, że implementacja jest osobną aktywnością. Na nią również przyjdzie czas:)

Minusów takiego zachowania jest kilka:
  • odbierasz zabawę innym:)
  • tracisz czas na coś, co nie jest częścią Twojego zadania
  • eliminujesz wszystkie zalety tworzenia projektu przed implementacją, ponieważ nie unikasz implementacji, a co za tym idzie, w przypadku zmian (czy w wyniku własnych obserwacji, czy zgłoszonych defectów) większa ilość wysiłku zostaje "zmarnowana"

Kolejną rzeczą, nad którą warto jest się zastanowić, to czy wszystkie fragmenty oprogramowania musimy zaprojektować?
Osobiście uważam, że robienie tego dla każdego, najdrobniejszego elementu aplikacji jest bez sensu. Mam na myśli elementy powtarzalne, różniące się szczegółami.

Jeżeli tworzymy dziesięć raportów, to potrzebujemy projekt całego mechanizmu, ale operującego na interfejsach oraz, dla każdego raportu z osobna, opis zapytania do wyciągania danych. Nic więcej. Nie potrzebujemy dziesięciu diagramów, na których konkretne klasy implementują niezbędne interfejsy. Byłoby to zwyczajne dublowanie informacji.