Słowem wstępu

iTaxi powstało w 2013 roku, wtedy też została stworzona nowoczesna (wtedy) aplikacja dla kierowców. Dzięki niej możliwe było sprawdzanie, jakie kursy zamówili pasażerowie oraz zrealizowanie takiego kursu wraz z procesem płatności. W aplikacji można było sprawdzić podstawowe statystyki czy przeczytać wiadomości od firmy, wysyłane w bardzo prostej formie.

Pięć lat później aplikacja sprawiała więcej problemów, niż dawała korzyści. Ponieważ była napisana w technologii od dawna przestarzałej, dział IT, zamiast tworzyć nowe funkcjonalności, musiał skupiać się na obsłudze błędów. Praca nad nimi nie była ani trywialna, ani przyjemna. Co więcej, modyfikacja jednego fragmentu kodu starej aplikacji generowała dysfunkcjonalność innych jej części.

W tej wersji oprogramowanie było po prostu barierą w rozwoju firmy. Dlatego też zainicjowany został projekt, którego celem było stworzenie nowej aplikacji dla kierowców. Założeniem było to, by była napisana zupełnie od nowa, z uwzględnieniem najnowszych trendów UX i frameworków oraz by aplikacja była gotowa na dalszy rozwój. Miała być po prostu skalowalna.

Faza pierwsza projektu: sens prototypowania i UX

Projekt rozpoczęliśmy od zebrania wymagań, zarówno od strony biznesowej, jak użytkowników końcowych, czyli kierowców iTaxi. Zdajemy sobie sprawę, że samo przygotowanie opisów funkcjonalności to za mało, by stworzyć użyteczny produkt. Najlepszym sposobem, by wszyscy zainteresowani mieli pewność co do ostatecznego kształtu produktu, zanim napiszemy chociaż linijkę kodu, jest przygotowanie makiet i prototypów. Zamiana słów na schematy wyglądu aplikacji to rozwiązanie, które w naszym przypadku pomogło nam osiągnąć sukces. Zajrzenie do makiet zawsze rozwiązywało wątpliwości, jak dana funkcjonalność ma działać. To pomagało też wprowadzać zmiany zanim napisaliśmy jakikolwiek kod. 

Gdy doszliśmy w firmie do etapu tworzenia grafik, każdy znał już sposób działania poszczególnych elementów. Potem dopiero ustaliliśmy, jak one będą wyglądać.

Trzeba zaznaczyć fakt, że aplikacja została stworzona z uwzględnieniem wariantów urządzeń, z jakich korzystają kierowcy w trakcie jazdy (w tym: uchwytów i mocowań do szyby). Podczas prac zwracaliśmy uwagę na to, czy poszczególne elementy są wygodne w obsłudze i umożliwiają wykonywanie taksówkarzowi swojej pracy, przy zachowaniu bezpieczeństwa na drodze. Na przykład: badaliśmy, czy nowa nawigacja (zarówno górna, jak i dolna) jest wygodna w użyciu przez kierowców leworęcznych i praworęcznych. 

Dodatkowo świadomie zdecydowaliśmy, w którą stronę chcemy pójść z naszą aplikacją w kontekście doświadczenia użytkownika. Postanowiliśmy, że nie będziemy iść w kierunku wprowadzania „presji” na kierowcach (na przykład: by pracowali dłużej i nie wylogowywali się z aplikacji, bo więcej zarobią itd.). Uznaliśmy, że nasza aplikacja ma przede wszystkim nie zmuszać nikogo do pracy poprzez psychologiczne triki – bezpieczeństwo na drodze jest najważniejsze.

opisuje Katarzyna Małecka, UX Designer, Head of Product w iTaxi, magazyn Programista, 2019.05

Faza druga projektu: development

Aplikacja kierowcy postawiła przed nami pewne specyficzne wyzwania, których nie spotkamy w większości aplikacji mobilnych. Chodzi o to, że w aplikacji cały czas „dużo się dzieje”. Na bieżąco spływają zlecenia, pojawiają się przypomnienia i komunikaty. A nasza aplikacja musi być nieustannie „pewna swojego stanu”, zwłaszcza pozycji GPS i statusu w systemie iTaxi (wolny/zajęty). Jeśli którakolwiek z tych wielkości zawiedzie (np. mamy nieaktualną pozycję GPS), może to powodować szereg komplikacji, m.in.  z zamówieniem taksówki. Trzeba też pamiętać, że taksówkarze, w porównaniu do pasażerów, dużo częściej są w ruchu: wjeżdżają do tuneli, na parkingi podziemne, krążą wokół wysokich budynków. Zakłóceń różnego rodzaju jest wiele i mogą one powodować utratę GPS lub Internetu. Wówczas wyzwaniem jest znalezienie „złotego środka” pomiędzy alarmowaniem użytkownika o nieprawidłowościach a pomijaniem chwilowych problemów. Pewne wielkości dobieraliśmy eksperymentalnie, np. akceptujemy nieaktualną pozycję przez określoną liczbę sekund, ale jeśli trwa to dłużej, to uznajemy, że pozycja jest nieznana. Sprawdzaliśmy podczas testów, jaka wartość czasowa jest optymalna i dopiero wtedy wdrażaliśmy to rozwiązanie w aplikacji.

Aplikacja kierowcy iTaxi prowadzi nieustanny dialog z serwerem, również wtedy gdy jest „w tle”. Musi przecież na bieżąco informować o zmianie pozycji i gotowości kierowcy do przyjęcia kursu. Musi też odbierać informacje o przypisanych zamówieniach. Część takiej komunikacji jest cykliczna, część jednorazowa. Niektóre komunikaty muszą następować w określonej kolejności, inne – zupełnie niezależnie od siebie. W starej aplikacji zastosowano metodę kolejki komunikatów. Wszelkie requesty wrzucane były do jednej, synchronizowanej kolejki FIFO i kolejno wywoływane. Powodowało to wiele problemów, bo  niektóre komunikaty są ważniejsze od innych, a kierowca ma krótki czas na reakcję (np. akceptacja kursu).

W nowej aplikacji zrezygnowaliśmy więc zupełnie z kolejki requestów i komunikacja odbywa się asynchronicznie. Jeśli flow wymaga kilku komunikatów w określonej kolejności – tworzymy z nich „łańcuchy”. Pomocna przy tym okazała się RxJava, czyli javowa implementacja ReactiveX. Wydaje się wręcz stworzona do naszego scenariusza: sekwencji komunikatów, które dodatkowo powinny zostać przerwane w przypadku błędu któregokolwiek z nich. Tworzenie cyklicznych requestów, przerywanych na tylko określone błędy (np. brak sesji), również okazało się proste. RxJavę wykorzystaliśmy też do łączenia danych z różnych źródeł (pobieranych w zupełnie inny sposób) w ciąg, który w aplikacji prezentowany jest jako jedna, odświeżana w tle lista. Bez wątpienia RxJava i inne współczesne frameworki pomogły uniknąć wielu błędów i problemów, z którymi borykaliśmy się na starej wersji.

Wkrótce po rozpoczęciu prac nad nową wersją okazało się, że pojawiła się pilna, bardzo duża potrzeba biznesowa, którą trzeba zaimplementować dla kierowców. Terminy były sztywne i stosunkowo krótkie. Od początku było jasne, że nowa aplikacja nie będzie gotowa do tego czasu. Naturalnym wydawało się więc przerwanie prac nad nową wersją i zaimplementowanie zmian w starej, ale bardzo nie chcieliśmy tego robić. Wydawało się to ogromną stratą czasu – starą aplikację mieliśmy wkrótce zamknąć, tworzylibyśmy więc rozwiązanie na kilka miesięcy. Do tego stara wersja była już w takim stanie, że dokładanie nowych funkcji było ryzykowne, implikowało błędy i kolejne tygodnie poświęcalibyśmy na poprawianie rozwiązania, zamiast na rozwijanie nowego produktu. Ostatecznie podjęliśmy decyzję, że nową funkcję stworzymy tylko w nowej, ubogiej na początek wersji. Ustaliliśmy z kierowcami absolutne minimum, jakie muszą mieć w nowej aplikacji, a także zdecydowaliśmy, że obie wersje – stara i nowa – będą na początek ze sobą „połączone” w taki sposób, by wywoływać się nawzajem. Nowa funkcja pojawiła się w starym programie tylko w formie przycisku, który odpalał nową wersję. Stworzyliśmy mechanizm przenoszenia sesji między aplikacjami, tak by kierowcy nie musieli się do każdej z nich oddzielnie logować. Nie było to idealne rozwiązanie, ale w praktyce działało całkiem dobrze. Kierowcy radzili sobie z obsługą obu aplikacji, a zgłoszenia problemów były sporadyczne. Wkrótce mogliśmy powrócić do rozwoju nowej wersji, stopniowo dokładając do niej najważniejsze, „bazowe” dla nas funkcje, czyli przede wszystkim flow kursu. Nie zdecydowaliśmy się jednak na bieżąco wydawać coraz bardziej rozbudowanej wersji. Postanowiliśmy, że dokończymy produkt tak, jak to było pierwotnie zaplanowane, czyli wydamy dopiero pełną nową aplikację. W momencie gdy nowa wersja była gotowa – oba oprogramowania zostały rozłączone. Nie kierowały już jedno do drugiego, ponieważ nowy produkt był już w pełni funkcjonalny i można było pracować tylko na nim. Postanowiliśmy jednak nie wyłączać starej aplikacji od razu. Nowa wersja przechodziła fazę stabilizacji, wciąż ją dopracowywaliśmy. Pozostawienie starej, wysłużonej, ale ustabilizowanej jednak wersji było gwarancją ciągłej pracy kierowców. Na szczęście nowa odsłona była na tyle dobra, że udało się uniknąć sytuacji, w której musielibyśmy poprosić kierowców o nawet chwilowy powrót do starego programu.

Fakt, że przez długi czas mieliśmy właściwie dwie równoprawne aplikacje, sprawił, że nie mogliśmy dowolnie zmieniać komunikacji z backendem. Był to problem, bo przy okazji unowocześniania aplikacji androidowej pojawiła się potrzeba innej obsługi po stronie serwera. Nowa aplikacja oczekiwała czasami innych danych, a nawet innego flow obsługi. Musieliśmy być bardzo ostrożni w takich modyfikacjach, żeby nie powodować problemów na starej aplikacji. Było to też wyzwanie dla działu testów, który wszystko musiał sprawdzać dwa razy – na obu wersjach. Pewne rzeczy upraszczaliśmy, ale backendowo musieliśmy zostawić funkcje bardziej rozbudowane, bo stare aplikacje wciąż działały. Momentami niezbędne okazało się wręcz różnicowanie odpowiedzi w zależności od wersji aplikacji, która odpytuje serwer. Było to na szczęście tylko chwilowe rozwiązanie do czasu przełączenia wszystkich kierowców na nowy produkt.

Ze względu na złożoność aplikacja powstawała zgodnie z tzw. wzorcem architektonicznym VIPER. Jest to wzorzec kojarzony częściej z aplikacjami dla iOS, ale równie dobrze sprawdza się w Androidzie. Jego zaletą jest duży podział odpowiedzialności poszczególnych komponentów aplikacji. Projekt jest więc łatwiej rozwijać i testować, a przez to szansa na popełnienie błędu jest mniejsza. VIPER pomaga też zachować jakość kodu w czasie, nawet jeżeli pracuje nad nim wielu programistów. Wzorzec może być dobrym wyborem dla złożonych projektów, dla których przewidujemy długi czas życia i rozwoju. W aplikacji wykorzystaliśmy też znane i nowoczesne frameworki, które ułatwiają development, wprowadzają pewną przejrzystość kodu i minimalizują ryzyko błędu. Wszystko to sprawia, że mamy stosunkowo niski próg wejścia nowego programisty do projektu, a sam projekt jest łatwiej utrzymywać i rozwijać.

opisuje Anna Orłowska, Senior Android Developer w iTaxi, magazyn Programista, 2019.05

Faza trzecia projektu: testy

Zastosowaliśmy podejście oparte na ryzyku – testy były początkowo skoncentrowane na obszarach o największej możliwości wystąpienia nieprawidłowości oraz o największym priorytecie dla całego biznesu. Następnie były sprawdzane i poprawiane zgłoszenia z obszarów UX czy estetyki.  Bardzo ważne były też testy regresji. Mocno pilnowaliśmy, aby przy dodawaniu nowych funkcjonalności nie pojawiły się błędy w tych, które już działają właściwie. 

Nasze testy podzieliliśmy na fazy. Najpierw dwóch testerów sprawdzało działanie aplikacji w biurze i zgłaszało nieprawidłowości. Potem udali się do miasta, gdyż tam, w rzeczywistych i dynamicznych warunkach, zachowanie aplikacji mogło się trochę różnić i inne aspekty (widok czy funkcjonalności) mogły mieć większe znaczenie. Testerzy jeździli więc z naszymi taksówkarzami, trzymając telefony w ręku i obserwując, co się w aplikacji dzieje. 

W dalszej części testów zorganizowaliśmy grupę 60 testerów – kierowców, którzy sprawdzali działanie aplikacji i wygodę jej obsługi w każdych możliwych warunkach pogodowych na drodze, w ciągu dnia i w nocy, na różnych urządzeniach. Kierowcy mogli kontaktować się z nami na wiele sposobów  –  porozmawiać z nami osobiście, zadzwonić na dedykowaną infolinię lub wysłać e-maila. Dzięki temu ci testerzy na bieżąco, jeszcze w pojeździe, przekazywali swoje uwagi i pomysły oraz komentowali odnalezione w trasie usterki (np. na temat zwiększenia czcionki adresów kursu w celu poprawy widoczności).

Ta faza testów była o tyle trudna, że wymagała analitycznego podejścia do różnego rodzaju zgłaszanych uwag, problemów, a także subiektywnych opinii. Agregowanie zgłoszeń i wybieranie, które z nich przechodzą do backlogu, a które do dalszej obserwacji (np. pod względem rosnącej skali), wymagało dużego skupienia i zaangażowania zespołu. Warto zaznaczyć, że każde zgłoszenie przeanalizowaliśmy. Jeśli natomiast została podjęta decyzja o odrzuceniu danej zmiany w aplikacji (np. ze względów biznesowych), zespół wiedział, dlaczego tak się stało, i że była to decyzja świadoma. 

Zgłoszenia kierowców nie dotyczyły tylko nieprawidłowości. Z chęcią zgłaszali także pomysły, które miały ułatwiać im korzystanie z aplikacji. Dotyczyły one zarówno samej realizacji kursów, jak i lepszej komunikacji z firmą. Na przykład poprosili o zaimplementowanie trybu nocnego, który zmieniał kolory i przyciemniał widok, aby łatwiej można było używać aplikacji w warunkach nocnych. Początkowo zaplanowaliśmy tę opcję na późniejsze fazy, jednak okazało się to dla kierowców na tyle istotne, że znacznie przyspieszyliśmy wydanie. Na ich prośbę wdrożyliśmy także komunikat informujący o tym, ile jeszcze kursów brakuje, aby dostać obniżkę abonamentu lub móc otrzymywać więcej zleceń w kolejnym tygodniu. Dzięki testom kierowców okazało się, że należy przygotowane przez nas komunikaty przedstawić w bardziej zrozumiały sposób. Zmodyfikowaliśmy je bardzo szybko.

Z ciekawych sytuacji warto wspomnieć, że testowanie aplikacji w terenie przy użyciu kilku urządzeń i w różnych punktach miasta budziło często zainteresowanie przechodniów, a nawet ochrony okolicznych obiektów, szczególnie na lotnisku Chopina w Warszawie. Całe szczęście skończyło się tylko na czujnej obserwacji służb!

Ważne jest, że problemy i pomysły zgłoszone przez kierowców były sukcesywnie rozwiązywane i implementowane  przez zespół iTaxi, dzięki czemu aplikacja – można pokusić się o takie stwierdzenie – jest pracą zarówno zespołu iTaxi, jak i kierowców.

opisuje Sylwia Okraska, Senior Tester w iTaxi, magazyn Programista, 2019.05

Podsumowując

Aplikację wydawaliśmy w dwóch fazach: najpierw kierowcom testowym, następnie –stopniowo – wszystkim pozostałym. Nie naciskaliśmy na szybką przesiadkę na nową wersję, chcieliśmy bowiem, by mogli się z nią spokojnie oswoić i sami zdecydować, kiedy chcą zrezygnować z poprzedniej wersji. Obecnie mamy jeszcze grono kierowców, którzy używają obu aplikacji („dla pewności” ;)). Niebawem będziemy stare oprogramowanie wygaszać i wtedy nowa aplikacja będzie widoczna już we wszystkich samochodach iTaxi!

Linki do artykułów:

Grafika przedstawiająca proces tworzenia aplikacji mobilnej iTaxi dla kierowców taksówek
Przykład – screen z poprzedniej oraz z nowej aplikacji
Grafika przedstawiająca proces tworzenia aplikacji mobilnej iTaxi dla kierowców taksówek
Przykłady (od lewej): makieta, początkowa wersja designu, finalna wersja designu. Dwie pierwsze zawierają dodatkową funkcjonalność, której start przełożyliśmy. Wersja z białym tłem wygrała – okazała się bardziej czytelna w warunkach jazdy, co przetestowaliśmy, poruszając się po mieście samochodem!
Grafika przedstawiająca proces tworzenia aplikacji mobilnej iTaxi dla kierowców taksówek
Materiał z testów aplikacji w terenie

Źródło

Nazwa Wartość
Tytuł Aplikacja mobilna iTaxi dla kierowców – case study
Autor Małecka, Katarzyna oraz Orłowska Anna S. oraz Okraska, Sylwia
Czasopismo Programista
Wydanie 82
Rok 2019
Wydawca Dom Wydawniczy Anna Adamczyk
Link https://programistamag.pl/programista-3-2019-82/