Zarządzanie wersjami oprogramowania

Najtrudniejsze zadanie z jakim się obecnie spotykam w mojej pracy to zarządzanie wersjami produktu.

Od jakiegoś czasu używamy Subversion i pewnie jest o niebo lepiej niż by było bez tego narzędzia, ale dalej jest cholernie ciężko. Szczególnie wtedy, gdy Ciągle wprowadzane są poprawki w bazie. Bywa tak, że mam trzy wersje do synchronizacji: developerską, do testów wewnętrznych i do testów klienta.

Druga zazwyczaj generuje typową ilość znalezionych bugów, a potem sporą ilość ‘feature requests’ (przegląda ją między innymi manager projektu, który ma dobre pomysły jak usprawnić pracę w systemie; sęk w tym, że poważnie utrudniają one pracę nad systemem).
Trzecia z kolei generuje szum pt. ‘na stronie X, link Z jest w nie takim foncie jak potrzeba’ i inne problemy ;)

*Razem tworzą żyzne środowisko, z którego co jakiś czas wylęgają się pomysły wymagające zmiany struktury bazy danych.

**Wszystkie trzy wersje są update’owane w różnych momentach, do różnych wersji repozytorium.

Z * i ** wynika, że powinno się zdarzać (i zdarza, a jak!), że na każdej wersji systemu jest inna wersja bazy danych.

Jeszcze nie koniec.

W teamie mam pewną ilość programistów, którzy nie rozwinęli jeszcze umiejętności polegającej na pisaniu kodu w taki sposób, aby był on jak najbardziej elastyczny (dzięki wszystkim bogom za CakePHP, bo przy przenoszeniu systemu na serwer klienta przepisywalibyśmy wszystkie linki… aż mnie ciarki przeszły). Jednocześnie nie mogę ich za to zdyscyplinować – przecież nie dostali żadnych wytycznych jak pisać kod (kto próbował coś takiego napisać, ten wie…)

No i to w sumie wystarczy, żeby przy końcówce projektu mieć poczucie braku kontroli.

Jednak jest pewne światełko w tunelu (nikt nie wyłączył z powodu kryzysu;)), o którym napiszę w następnym poście…
Niektóre wskazówki znajdziesz wponiższych postach:

Co jest ważniejsze: funkcjonalność, użyteczność czy marketing?

Jeśli zadałeś sobie kiedykolwiek takie pytanie, to znaczy, że dałeś się wciągnąć w potencjalną świętą wojnę, między działami Twojej firmy.

Programiści pewnie forsowali funkcjonalność, projektanci użyteczność (ang. usability)*, dział marketingu – wiadomo. I wiesz co? Najfajniejsze jest to, że wszyscy oni mają rację!
Jak to możliwe? Ok, wzbogacę to zdanie i wszystko będzie jasne:
Wszyscy oni mają rację, z ich własnego punktu widzenia.
Ty jednak, jako menadżer zobligowany jesteś do widzenia, jeśli nie na ostatecznym poziomie, to chociaż z szerokiej perspektywy. Dlatego musisz wiedzieć (i jeśli chcesz – uświadomić swój zespół), że jest tak:

Bez funkcjonalności nie da się spełnić wymagań użyteczności, nie da się też prowadzić marketingu (produktu, który nie istnieje). Bez użyteczności oprogramowanie o najbogatszym zestawie funkcji jest koszmarne w użytkowaniu, a trudno prowadzić marketing do kiepskiego narzędzia (łatwiej to zrobić z kiepskim szamponem). Na koniec – najgenialniejsze systemy o interfejsie tak intuicyjnym, że przy pierwszym kontakcie każdy jest zaawansowanym użytkownikiem, bez jakiejkolwiek instrukcji jest bezużyteczne, jeśli nikt o tym nie wie.

Ubarwiając wpis pozwolę sobie na metaforę: po co Ci do wyścigów koń, który ma mocne serce, a nie ma nóg? Po co Ci taki, który ma nogi, ale słabe serce? Po co Ci taki, który ma mocne serce i nogi, ale nie ma głowy (innymi słowy – padlina)? Biznes to wyścigi, w których zarabiasz, kiedy jesteś w czołówce, nie tracisz w peletonie, a bankrutujesz w ogonku.

*w Polsce na szczęście coraz większą uwagę zwraca się na to kryterium jakości oprogramowania, do niedawna było to mizerne.

Odpowiednie narzędzia

W poprzednich postach( Czego tak na prawdę ode mnie chcesz [kliencie] ? i Funkcjonalność czy bajery?) napisałem o podstawowych niebezpieczeństwach jakie czyhają na nas w procesie tworzenia dedykowanego systemu dla klienta. W obu przypadkach w pewnym sensie ochroną przed tymi zagrożeniami będzie odpowiedni framework. Poznałem (lepiej lub gorzej) do tej pory trzy frameworki: CakePHP, ZendFramework i Django. Intensywnie pracuję z CakePHP i na nim oprę ten artykuł, pozostałe znam na tyle, żeby mieć pewność, że w podobny sposób pomagają w produkcji oprogramowania i żeby nie musieć opisywać każdego z osobna.

Głównym celem frameworku jest usprawnienie pracy programisty. Ma on dostarczać mechanizmy, które odciążają nas od żmudnego powtarzania nieciekawych czynności (łączenie z bazą, tworzenie milionowego formularza, pisanie kolejnego foreach żeby wydłubać coś z tablicy…). Nieciekawych oczywiście z punktu widzenia doświadczonego programisty, który robi to już długo – zaczynając przygodę z tą dziedziną wszystko jest ciekawe, ale ten stan po jakimś czasie mija.

Jeśli jesteś kompletnie zielony – odradzam zaczynanie przygody z programowaniem od poznania frameworku. Wydaje mi się, że postępując w ten sposób trudniej będzie Ci zrozumieć mechanizmy w nim zachodzące i zamiast mieć możliwość pełnego wykorzystania narzędzia, stanie się on dla Ciebie magiczną różdżką, której potencjału nie wykorzystasz. (oczywiście są wyjątki i możesz robić co chcesz).

Ja jednak nie będę skupiał się na dostarczanych przez framework bibliotekach, bo o tym już wiele napisano. Spróbuję za to napisać jak można go wykorzystać do przeciwdziałania trudnym tendencjom pojawiającym się w procesie produkcji i nie mających wiele wspólnego z samym programowaniem.

Na początek problem specyfikacji wymagań. Maksymalne starania Twoje i klienta, żeby dokładnie określić wymagania i tak nie zabezpieczą Cię w stu procentach. Zawsze po drodze okazuje się, że przydało by się coś innego. Coś mogło by działać lepiej i że pojawił się nowy pomysł. Tak jak z budowaniem samochodu – wkładając wysiłek w obliczenia będziesz pewny, że wycieraczki obejmą maksymalnie przednią szybę, ale dopiero jak się nim przejedziesz to stwierdzisz, że drążek zmiany biegów jest za krótki, a słupek boczny ogranicza Twoje pole widzenia. Gdybyś produkował samochody doświadczenie mógłbyś wykorzystać dopiero w następnym modelu. Ty jednak jesteś farciarzem jakich mało i produkujesz ciągi zer i jedynek, które możesz w każdej chwili zmienić/wyciąć/dodać! Mechanizm zwany w CakePHP Scaffold jest tym, co owo wycinanie, zmienianie i wklejanie czyni bezbolesnym w początkowej fazie produkcji.

W CakePHP scaffolding objawia się w dwóch formach. W pierwszej jest w stanie wygenerować fizycznie modele, kontrolery i widoki na podstawie struktury bazy danych (i podpowiedzi użytkownika). Jest to wykonywane przy pomocy skryptu bake.php znajdującego się w cake/libs/scripts (w wersji 1.19). Efektem tego jest powstanie wszystkich standardowych metod i widoków do operacji takich jak list/view/edit/add/delete. Z uwagi na to, że są one generowane fizycznie – możesz je zacząć zmieniać dostosowując je do swoich potrzeb. Jednak minusem jest to, że w razie zmiany struktury bazy trzeba albo na nowo wygenerować widoki i metody, albo edytować je ręcznie.
Drugą emanacją jest scaffold właściwy. Włącza się go w prosty sposób dodając w kontrolerze linię

var $scaffold;

(Tutaj uwaga – można włączyć scaffold ‘globalnie’ dodając tą zmienną w AppController, ale wtedy nie należy dodawać już jej w kontrolerach).
Efektem tego będzie każdorazowe generowanie metody i widoku dla standardowych operacji na podstawie struktury bazy danych (tej zdefiniowanej w modelach). Dziać się będzie to tak długo, aż nie usuniemy deklaracji zmiennej, albo nie zdefiniujemy w kontrolerze którejś z metod standardowych. W pierwszym przypadku scaffolding wyłączymy całkowicie dla danego kontrolera, w drugim nie będzie on działał dla metody, którą już zdefiniowaliśmy. Minusem jest to, że nie możemy dostosować widoku do naszych widzimisię (widok nie istnieje fizycznie na dysku)*, ale za to przy każdej zmianie struktury bazy danych widok jest uaktualniany bez naszej ingerencji (dodanie pola varchar zaowocuje pojawieniem się w formularzu pola input, text – textarea, enum – listy wyboru).
To rozwiązanie jest genialne w najwcześniejszej fazie produkcji oprogramowania. Wyobraź sobie, że po zaprojektowaniu samochodu od razu możesz się nim przejechać (fakt będzie brzydki, bez maski i tapicerki) i zobaczyć jak się nim jeździ i czy nie przydałby się większy bagażnik. Tak właśnie jest w tym wypadku: projektujesz bazę danych i już możesz pokazać klientowi podstawowe funkcjonalności**. Możecie z klientem UŻYWAĆ tej aplikacji i stwierdzić, że czegoś brakuje.
Oczywiście nie jest tak super cały czas – w pewnym momencie trzeba po prostu napisać trochę kodu, czasem aplikacji nie wpisują się tak łatwo w szablon listuj/wyświetl/dodaj/edytuj/usuń.
Jednak w 8 przypadkach na 10 sprawdza się doskonale. Dorzuć do tego dobrze zaprojektowaną, znormalizowaną bazę i początkowa faza, która obfituje w zmiany jest tak bezbolesna, jak to tylko możliwe.

* te pliki istnieją fizycznie na dysku, są cache’owane, ale nie nadaje się to do edycji (zostanie nadpisane prędzej, czy później). Do tego wydaje mi się, że istnieje możliwość edycji szablonu, który definiuje jak mają być tworzone widoki, jednak nie zajmowałem się tym do tej pory, więc nie będę o tym pisał.
** pod warunkiem, że nauczysz go patrzeć na system pod tym kątem. Jak klient chce tylko ładny interfejs i nie współpracuje to scaffold nie spełni się w 100%.