Jak pracujemy

Jesteśmy zespołem programistów tworzących aplikacje internetowe. Ściśle współpracujemy ze szwajcarską firmą Brickwork Ventures, świadczącą nam usługi analityczne i doradcze w zakresie wspólnie realizowanych projektów. W naszej pracy kładziemy szczególny nacisk na komunikację, na bieżąco informując naszych klientów o postępach, ale też możliwych zagrożeniach. Wierzymy w wartości zaufania, szczerości i otwartości na opinie innych. Zawsze mówimy naszym klientom co możemy dla nich wykonać, ale nie boimy się też przyznać, że pewnych rzeczy nie jesteśmy w stanie zrealizować. Staramy się być do ich dyspozycji 24 godziny na dobę, porozumiewając się głównie przy pomocy Skype’a oraz emaili. Jeśli to możliwe spotykamy się też z nimi twarzą w twarz. Podczas gdy większość firm informatycznych koncentruje się jedynie na kodowaniu, my jesteśmy przekonani, że dostarczenie wysokiej jakości oprogramowania nie jest możliwe bez dogłębnej analizy oraz przetestowania projektu.

W skrócie, nasza filozofia opiera się na następujących zasadach:
  • Kluczem do sukcesu jest porozumiewanie się. Wielu nieporozumień da się uniknąć jeśli zostaną one odpowiednio wcześnie wyjaśnione. Jedynym sposobem by wpaść na ich trop jest częste rozmawianie ze sobą.
  • Kiepska analiza oraz brak wiedzy technicznej są najczęstszym powodem porażek projektów, przekroczenia budżetu oraz frustracji zarówno klientów jak i członków zespołu programistycznego. Dlatego nim przystąpi się do implementacji warto dwukrotnie sprawdzić czy krótkoterminowe rozwiązania nie staną się w przyszłości długoterminowymi problemami.
  • Tylko odpowiednio zmotywowani ludzie są w stanie zapewnić wysokiej jakości pracę. Motywacja ta pochodzi przede wszystkim ze wspólnie wyznawanych zasad oraz pasji. Dlatego też stosujemy regułę: „Zamiast wielu przeciętnych programistów, przydzielaj do swoich projektów kilku, ale dobrych”.
  • Testowanie, testowanie i jeszcze raz testowanie. To naprawdę ułatwia życie!

Analiza Biznesowa

Głównym zadaniem analizy biznesowej jest wyłonienie konkretnego rozwiązania spośród mnogości abstrakcyjnych idei i zadań, które stawiają przed projektem jego zleceniodawcy. Najlepszym sposobem osiągnięcia tego celu jest zrozumienie potrzeb na które ma odpowiadać oprogramowanie oraz ich źródła. Skąd się biorą? Jak możemy je zaspokoić? Jakimi akceptowalnymi dla zleceniodawcy, możliwościami dysponujemy i jaki wpływ na aspekty techniczne, ryzyko niepowodzenia przedsięwzięcia, koszty oraz czas realizacji projektu będzie miał wybór każdej z tych dróg.

Zazwyczaj, bezpośrednio po pierwszych spotkaniach z klientem sporządzamy ogólny zarys systemu: pomaga nam to w uzyskaniu pełnego obrazu sytuacji. Początkowo, zarys ten pełni przede wszystkim funkcję narzędzia komunikacji ze zleceniodawcą, służy do sondowania w jakim stopniu nasza oferta spełnia oczekiwania jego i przyszłych użytkowników aplikacji. Pomaga nam też w dogłębnym zrozumieniu stojącego przed nami problemu. Lepiej zmierzyć się z problemami na papierze niż w trakcie implementacji.

Krótko po określeniu wysokopoziomowych założeń projektu, przystępujemy do pracy nad modelem danych. To bardzo istotny krok - jeśli zepsujesz model danych, zepsujesz też cały projekt. Nie zapominajmy, że tworzymy systemy informacyjne: cokolwiek się w nich wydarzy, musi zostać odzwierciedlone w strukturze danych reprezentującej nasze wyobrażenie świata zewnętrznego. Jeśli to wyobrażenie jest niekompletne, wewnętrznie sprzeczne lub mgliste, stworzenie dobrego modelu danych jest niemożliwe. Dlatego przed przystąpieniem do realizacji lepiej dwa razy przemyśleć całą koncepcję. Uporządkować wszystko na samym początku.

Wiemy, że nie da się przewidzieć przyszłości i dlatego też nie jesteśmy w stanie z góry odgadnąć wszystkich możliwych wymagań i problemów, które pojawią się w trakcie realizacji projektu. Mimo to, wybierając dane rozwiązanie, zawsze zastanawiamy się, czy sprawdzi się ono w najbardziej prawdopodobnych scenariuszach, mogących zaistnieć w bliższej lub nieco dalszej perspektywie. W ten sposób upewniamy się, że krótkoterminowe rozwiązania nie przeistoczą się w długoterminowe problemy.

Proces wytwarzania

Metodologia i procesy wytwarzania są narzędziami wspierającymi projekt – nie odwrotnie! Unikamy nadmiaru biurokracji. W wielu projektach bardzo dużą ilość czasu pochłania zaspokojenie różnorakich wymagań formalnych: raportowanie, przygotowywanie analiz ryzyka (i strata cennego czasu na filozoficzne dyskusje o tym, co jest ryzykiem, a co nie) itd. Oczywiście tego typu dokumenty muszą zostać dostarczone, zwłaszcza w firmach funkcjonujących w oparciu o złożone struktury organizacyjne – dlatego piszemy je, jeśli jest to niezbędne. Ale nasza filozofia jest prosta: im jest ich mniej, tym lepiej.

W naszej pracy używamy metodologii zwanej Agile (http://agilemanifesto.org). Projekt podzielony jest na tygodniowe okresy - iteracje. Pod koniec każdego tygodnia planujemy jakie funkcje programu i błędy zostaną zaimplementowane i naprawione w kolejnej iteracji. W czasie, gdy zespół programistów pracuje nad stworzeniem nowych funkcjonalności i naprawieniem zgłoszonych błędów, analitycy opracowują specyfikację dalszych modułów. Zazwyczaj wiemy z jedno- lub dwutygodniowym wyprzedzeniem, które funkcje aplikacji będą wkrótce wymagały zaimplementowania, dlatego mają one pierwszeństwo przy opracowaniu. Programowanie w metodologii Agile wymaga, by przez cały czas prac nad systemem była dostępna jego działająca wersja. Choć początkowo aplikacja może mieć bardzo ograniczone możliwości, stopniowo się one zwiększają. Istotne jest, że odzwierciedla ona aktualny etap rozwoju systemu i może być testowana i oceniana przez analityków oraz przyszłych użytkowników.

Komunikujemy się – w ramach samego zespołu, z klientami i użytkownikami - tak często jak to tylko możliwe. Wielu nieporozumień można uniknąć, jeśli odpowiednio szybko wyjaśni się wątpliwości. Jedynym sposobem uzyskania odpowiedzi na pytania jest rozmawianie z ludźmi. Analitycy, mający bezpośredni kontakt z klientem, stale współpracują z programistami i natychmiast odpowiadają na zadawane przez nich pytania – wyjaśnienie danego aspektu systemu zajmuje zwykle mniej czasu niż wypicie filiżanki kawy. Dzięki poświęceniu tych kilku minut, projekt może być realizowany bez zbędnych opóźnień. W ten sposób oszczędzamy godziny. Dzięki współczesnym technologiom komunikacja jest tak łatwa, jak nigdy przedtem. Jednak niezwykle istotny jest też dla nas bezpośredni kontakt z drugim człowiekiem. Tak, używamy Skype’a i doceniamy jego użyteczność, ale spotykamy się też osobiście przy kuflu piwa (lub szklance wody, jak kto woli).

Technologia

Koncentrujemy się na określonych technologiach i narzędziach programistycznych. Pozwala nam to być ekspertami w tym co robimy i daje możliwość dogłębnego poznania budowy i sposobu działania systemów z których korzystamy, ale także zastosowań do których nie powinny być one używane. «Jeśli jedynym narzędziem, którym dysponujesz, jest młotek, każdy problem wygląda jak gwóźdź» - cóż, my mamy różne narzędzia do rozwiązywania różnych problemów. Co ważniejsze: nie są one technologiami niszowymi, ale powszechnie uznanymi, dysponującymi wsparciem rozbudowanej społeczności i najczęściej dostępnymi na zasadach oprogramowania otwartego (open source). Tworzymy obiektowe aplikacje biznesowe dostępne za pośrednictwem sieci web. Nasz zespół doszedł do perfekcji w posługiwaniu się technologiami Seam 2 i 3 oraz CDI, będącymi lekkimi kontenerami wstrzykiwania zależności (dependecy injection), które stanowią bazę dla naszych projektów. Lata doświadczenia z tymi technologiami pozwoliły nam aktywnie przyczynić się do ich rozwoju, poprzez współpracę ze skupioną wokół nich społecznością. Współczesne aplikacje nie są z reguły programami zupełnie niezależnymi od otoczenia. Gdy projekt tego wymaga, integrujemy nasze rozwiązania z istniejącymi już systemami przy pomocy takich standardów jak JMS czy WebServices (zarówno RestEasy, jak i JBossWS).

Każdemu zależy na szybkich i efektownie wyglądających aplikacjach, jednak IT Crowd troszczy się też o łatwość ich utrzymania i rozbudowy. Nasze rozwiązania korzystają z Java Server Faces (JSF) - wydajnej technologii, przyspieszającej tak powszechne zadania jak walidacja danych, ich konwersja, nawigacja pomiędzy stronami itd. Dzięki jej znacznie ułatwiającej pracę konstrukcji, opartej na komponentach i zdarzeniowym modelu komunikacji między nimi, nasi programiści mogą się skupić na właściwych zadaniach biznesowych stojących przed aplikacją. Poza standardowymi komponentami JSF, w naszych projektach korzystamy także z bogatej palety rozwiązań dostarczanych przez bibliotekę RichFaces. W ten sposób aplikacje uzyskują spójny i łatwo modyfikowalny wygląd oraz sposób działania. Czasem, gdy wymaga tego sytuacja, korzystamy też z czystego HTML, CSS i JavaScriptu, wspieranego przez biblioteki takie jak jQuery, Prototype czy Angular. Nasz zespół dokonał znacznego wkładu w projekty open-source dotyczące warstwy prezentacji, przede wszystkim za sprawą wprowadzenia do JSF kilku użytecznych dodatków znanych z jQuery. Uważamy się za ekspertów w tworzeniu komponentów JSF, szczególnie tych opartych o RichFaces CDK.

Oprogramowanie, które tworzymy, jak każda aplikacja biznesowa, wspierane jest przez sprawdzone systemy bazodanowe. Dzięki standardom Object-Relational Mapping (ORM) oraz technologiom, takim jak Java Persistence API i Hibernate, nasze rozwiązania są niezależne od konkretnej bazy danych. W prosty sposób można je dostosować do działania na systemach Oracle, MySQL, H2SQL, Derby lub – naszym ulubionym – PostgreSQL. Gdy pojawia się potrzeba archiwizacji danych w bazie, używamy Hibernate Envers, który bierze na siebie cały ciężar tego zadania, w sposób niezauważalny integrując się z rdzeniem Hibernate’a. Jesteśmy również świadomi wymagań związanych z bezpieczeństwem danych, takich jak ich szyfrowanie w bazie. W tym celu używamy Jasypt, biblioteki, która także w sposób przezroczysty dla programisty integruje się z Hibernate’em.

Testowanie i kontrola jakości

Bez testowania nie ma jakości. Ręczne testy aplikacji, choć będące koniecznością, nie wystarczają. Przede wszystkim są one zbyt drogie, dlatego też muszą zostać zautomatyzowane. Oprogramowanie testujemy na kilku poziomach. Używamy testów jednostkowych do testowania niewielkich fragmentów kodu. Jednak sprawdzenie działania samych klas to zbyt mało, szczególnie jeśli ściśle zależą one od danych pochodzących z kontenera aplikacyjnego. Testowanie systemu w sztucznym środowisku zawsze pozostawia furtkę dla błędów, które można zaobserwować dopiero w normalnych warunkach użytkowania programu. Dlatego nasze testy integracyjne korzystają z Arquilliana, dzięki czemu są uruchamiane bezpośrednio w docelowym kontenerze. Również w zakresie tej ostatniej technologii nasz zespół wniósł znaczący wkład i został doceniony przez środowisko. Poza testami jednostkowymi i integracyjnymi, które sprawdzają funkcjonowanie wnętrza aplikacji, tworzymy też testy operujące bezpośrednio na interfejsie użytkownika. Używamy do tego takich narzędzi, jak JSFUnit, HtmlUnit, Warp, Graphene lub Selenium.

Poza testami, stosujemy też ścisłe konwencje gwarantujące, że nasz kod jest czytelny i łatwy w utrzymaniu. Ich przestrzeganie kontrolują takie narzędzia, jak Checkstyle, PMD i Findbugs. Większa część procesu zapewnienia jakości jest zautomatyzowana, dzięki wykorzystaniu Jenkinsa zainstalowanego na naszym serwerze integracyjnym, który sprawdza poprawność aplikacji po każdej aktualizacji kodu.