Blog

02 października 2015 Wojciech Zawistowski

Budowanie MVP iteracyjnie – praktyczny przykład

Tagi:

Budowanie MVP iteracyjnie – praktyczny przykład

Jakiś czas temu pisałem o dlaczego MVP powinno być budowane iteracyjnie. W tym poście, postaram się zilustrować korzyści takiego podejścia na konkretnym przykładzie, krok po kroku.

Wizja produktu

Często potrzebuję zrobić szybki research jakiegoś tematu związanego z Agile – a wyniki, jakie udaje mi się “wygooglować”, nie zawsze są tak trafne jakbym chciał.

Interesują mnie wyłącznie artykuły, nie strony umożliwiające rejestrację na warsztaty praktyczne, recenzje książek, firmy konsultingowe, konferencje ani narzędzia. Preferuję określoną długość artykułów: dostatecznie długie, by zawierały szczegółowe informacje, ale równocześnie dość krótkie, by dało się je przeczytać w 10-15 minut. Chcę, żeby artykuły były aktualne, skupione na pojedynczym, wąskim zagadnieniu a nie ogólne, obejmujące szeroki temat. Dodatkowo, duży plus dostają u mnie artykuły znanych autorów lub organizacji, albo cieszące się uznaniem w środowisku Agile.

Zabawmy się więc pomysłem na następujący produkt: wyspecjalizowany search engine, przystosowany do wyszukiwania wysokiej jakości artykułów Agile.

Brainstorming listy funkcjonalności

Jest to typowe, że lista niezbędnych i mile widzianych funkcjonalności dla nowego produktu rośnie niemal w nieskończoność. Co jesteśmy w stanie wymyśleć dla naszego search engine-u?

  • Mechanizm wyszukiwania. Powinien on być w stanie wyszukiwać i nadawać ranking artykułom wg. różnych kryteriów (długość, jak bardzo artykuł skupia się na pojedynczym temacie, czy pochodzi z uznanego źródła itp.).
  • Formularz wyszukiwania. Powinien mieć autouzupełnianie i udostępniać zaawansowane opcje wyszukiwania (długość, data publikacji, czy zawiera obrazki itp.)
  • Lista wyników wyszukiwania. Powinna zawiereać zarówno podstawowe jak i dodatkowe informacje (tytuł, streszczenie, URL, datę, autora, popularność, dopasowanie, miniaturę obrazka, czas czytania itp.), powinna być sortowalna wg. różnych kryteriów (data, dopasowanie, popularność itp.) i powinna być stronicowana.
  • Przyciski do udostępniania artykułu poprzez serwisy społecznościowe.
  • Możliwość oznaczania artykułu jako “ulubiony” i zapamiętywania go w zakładkach. Użytkownik powinien być w stanie zobaczyć listę swoich ulubionych i dodanych do zakładek artykułów (co będzie wymagać mechanizmu rejestracji i logowania). Artykuły oznaczone jako “ulubione” przez wielu użytkowników powinny pojawiać się wyżej na liście wyników wyszukiwania. Artykuły dodane przez użytkownika do zakładek nie powinny się pojawiać na wynikach wyszukiwania tego użytkownika.
  • Ramka z promowanymi (płatnymi) wynikami wyszukiwania.
  • Ramka z ręcznie moderowanymi wynikami wyszukiwania (ulubione artykuły redakcji serwisu)
  • Nagłówek z elamentami brandingu (logo, slogan itp.), linkiem do strony z ulubionymi artykułami użytkownika i cross-linkami do innych naszych produktów i usług.
  • Stopka z linkami do dodatkowych stron (O serwisie, Kontakt itp.).
  • Menu boczne z kontekstowymi reklamami.
  • Płatna wersja bez reklam (wymaga różnych form płatności: przelewy bankowe, karty kredytowe itp.).

Mógłbym tak wymyślać bez końca (co zresztą interesariusze w rzeczywistych projektach zazwyczaj robią), ale przytnijmy listę w tym miejscu – już i tak jest o wiele za długa. Zastanówmy się teraz, jak możemy zweryfikować czy nasz pomysł na produkt jest rzeczywiście atrakcyjny dla prawdziwych użytkowników?

Prawdziwie minimalne podejście

Idealne podejście to w ogóle nie implementować żadnej z powyższych funkcjonalności. Moglibyśmy zacząć od kampanii na Kickstarterze albo od podejścia typu “concierge”, np. moglibyśmy wysyłać mail z ręcznie przygotowaną listą artykułów, do niewielkiej grupy użytkowników. Załóżmy jednak, że przeszliśmy już przez ten krok i chcemy teraz zbudować pierwszą, minimalną wersję faktycznego produktu. Jak powinniśmy do tego podejść?

Nieiteracyjne MVP

W pierwszej kolejności, zastanówmy się, jak mógłby wyglądać zestaw funkcjonalności dla MVP, gdybyśmy nie planowali iterować, tylko próbowali przewidzieć go z góry. Pytanie, które moglibyśmy sobie zadać, to: Jaka minimalna kombinacja funkcjonalności może zweryfikować naszą wizję, równocześnie będąc postrzegana przez użytkowników jako nadająca się do użytku?

To pytanie błyskawicznie wycina wszystkie nie kluczowe funkcjonalności, takie jak płatne i ręcznie moderowane wyniki, dodawanie do ulubionych, dodawanie do zakładek, udostępnianie poprzez serwisy społecznościowe itp. Co więc pozostaje? I w jakiej kolejności powinniśmy te funkcjonalności implementować?

Ponieważ nie budujemy naszego MVP iteracyjnie – planujemy ocenić i wydać kompletny produkt na produkcję jednorazowo, gdy będzie gotowy – kolejność realizacji funkcjonalności nie ma większego znaczenia. Najłatwiejszą i najbardziej intuicyjną kolejnością wydaje się kolejność “naturalna”: najpierw ogólny layout strony, następnie jej zawartość, w takiej kolejności w jakiej użytkownik ją widzi i jej używa.

Zobaczmy więc, jak mogłyby wyglądać funkcjonalności i kolejność w jakiej je zbudujemy:

Nagłówek

Chcemy, by użytkownicy zaczęli rozpoznawać naszą markę, zaimplementujemy więc prosty nagłówek z logo i sloganem. Podążając za “naturalną” kolejnością funkcjonalności, ogólny layout strony wraz z nagłówkiem to pierwsze, co zaimplementujemy.

Formularz wyszukiwania

Najbardziej oczywistą funkcjonalnością, jaka musi zostać zawarta w MVP, jest formularz wyszukiwania. By móc szukać określonej frazy, musimy być w stanie jakoś tą frazę wprowadzić. Na start wystarczy nam najprostszy możliwy formularz z pojedynczym polem tekstowym. Podążając za “naturalną” kolejnością, ponieważ jest to pierwsza funkcjonalność jakiej użytkownik używa na naszej stronie, będzie to kolejna rzecz, jaką zaimplementujemy.

Mechanizm wyszukiwania

Wypełnienie formularza wyszukiwania prowadzi do wykonania tegoż wyszukiwania, tak więc silnik wyszukiwawczy intuicyjnie wydaja się kolejną funkcjonalnością, jaką należy zaimplementować. Ale jak powinien on działać w pierwszej, minmalnej wersji? Pełny, rozbudowany silnik, przeszukujący cały internet i wagujący artykuły wg. wielu wyszukanych kryteriów jest zdecydowanie zbyt złożony i zbyt drogi by jedynie wstępnie zweryfikować nasz koncept. Z drugiej strony, jeśli silnik będzie zwracał zbyt mało wyników, lub wyniki niskiej jakości, nie będzie tak na prawdę użyteczny i zniechęci użytkowników.

Gdzie więc leży złoty środek? Dopóki nie zaimplementujemy silnika i nie zobaczymy wyników, ciężko zgadnąć. Z jednej strony moglibyśmy przeszukiwać jedynie kilka ręcznie wybranych, popularnych serwisów Agile. Zagwarantowałoby to wysoką jakość artykułów, jednak przy ryzyku, że będziemy zwracać za mało wyników. Z drugiej strony, moglibyśmy przeszukiwać cały internet, ale przy użyciu maksymalnie uproszczonego algorytmu – jedynie proste dopasowanie słów kluczowych i długości artykułu. To zagwarantowałoby dostatecznie dużo wyników, ale przy ryzyku niskiej jakości artykułów.

Dla bezpieczeństwa, wybierzmy coś po środku: przeszukiwanie całego internetu, przy użyciu odrobinę bardziej złożonego, kontekstowego algorytmu bazującego na treści artykułu, ale nie uwzględniającego popularności, jakości źródła artykułu, zawężenia artykułu do pojedynczego tematu itp. To rozwiązanie nie jest tak tanie, jakbyśmy sobie życzyli, ale przynajmniej istnieje przyzwoita szansa, że będzie ono użyteczne.

Lista wyników wyszukiwania

To kolejna funkcjonalność, która z całą pewnością musi być w MVP. Ponieważ wyniki wyszukiwania są generowane na końcu (najpierw użytkownik wprowadza frazę, następnie przeprowadzane jest wyszukiwanie, dopiero po nim wyniki są wyświetlane użytkownikowi), podążając za “naturalną” kolejnością, zaimplementujemy tą funkcjonalność jako ostatnią.

Pytanie, jak powinna ona wyglądać? Na początek, możemy wyświetlać jedynie najbardziej podstawowe informacje o artykule: tyuł, streszczenie i URL, jako że są one najłatwiejsze i najtańsze do pozyskania. Pominiemy też na razie możliwość sortowania – będziemy zawsze sortować wyniki po trafności dopasowania.

Wydaje się też intuicyjne, że powinniśmy ograniczyć ilość wyników wyświetlanych naraz na ekranie i zaimplementować jakiś rodzaj stronicowania albo nieskończonego scroll-owania. Na początek wybierzemy stronicowanie, jako że wydaje się prostsze w implementacji. Zgadujemy, że optymalna ilość pozycji wyświetlanych naraz to 10 (chcemy wyświetlać streszczenia, więc pozycje będę prawdopodobnie dosyć duże – stąd niska ilość wyników na pojedynczym ekranie).

Mając na tym etapie ukończone wszystkie funkcjonalności, wydajemy nasze MVP na produkcję, by w końcu przekonać się, czy nasze założenia okazały się poprawne.

Iteracyjne MVP

Zobaczmy teraz, jak podejście iteracyjne może wpływać na to, w jaki sposób budujemy produkt.

Przede wszystkiem, powoduje ono zmianę pytania, jakie sobie zadajemy. Przestaje mieć sens pytanie (zgadywanie) jaki zestaw funkcjonalności będzie użyteczny, ponieważ będziemy to oceniać po każdej iteracji. Pytanie, jakie będziemy sobie teraz zadawać, to: Jaka jest najbardziej wartościowa funkcjonalność, którą powinniśmy zbudować jako następną? Będziemy budować tą funkcjonalność i oceniać, czy produkt jest już użyteczny; jeśli jeszcze nie jest użyteczny, pytamy ponownie jaka w tej chwili jest najbardziej wartościowa funkcjonalność; jeśli jest użyteczy, nasze MVP jest gotowe i możemy je wypuścić na produkcję.

Ma to duży wpływ na kolejność w jakiej budujemy funkcjonalnośći. Kolejność “naturalna” przestaje być odpowiednia, ponieważ nie współgra ona z budowaniem najbardziej wartościowej funkcjonalności najpierw. Zobaczmy więc, jakie funkcjonalności i w jakiej kolejności mogłyby powstać, jeśli skupimy się na ich wartości:

Lista wyników wyszukiwania

Najważniejszą funkcjonalnością jest, bezdyskusyjnie, lista wyników wyszukiwania. To wyniki są tym, po co użytkownik odwiedza wyszukiwarkę.

Budowanie najpierw listy wyników może się wydawać nieintuicyjne. Taka lista jest niewątpliwie nieużyteczna bez formularza, pozwalającego wprowazdzić frazę do wyszukania. Bez formularza, lista wydaje się wręcz niemożliwa do przetestowania. Nie jest to jednak prawdą. Możemy wygenerować wyniki wyszukiwania np. ręcznie ustawiając parametry w URL-u. Takie rozwiązanie oczywiście nie nadaje się do udostępnienia prawdziwym użytkownikom, niemniej jednak doskonalne nadaje się do prezentacji naszym interesariuszom albo do tego, by przeprowadzić na nim testy użyteczności.

Iterując, nie musimy od samego początku implementować wszystkich elementów, które sprawiają, że lista wyników będzie użyteczna. Możemy więc pominąć na razie stronicowanie i nie musimy się głębiej zastanawiać, jaka powinna być optymalna ilość wyników na stronie – wystarczy na razie, że wyświetlimy jedynie pojedynczą stronę z arbitralnie dobraną ilością pozycji.

By przekonać się jak lista wygląda, nie potrzebujemy nawet podpinać do niej prawdziwego mechanizmu wyszukiwania – możemy przetestować layout listy wyników na zmockowanym mechanizmie, zwracającym zdefiniowane na sztywno wyniki.

Lista wyników wyszukiwania – feedback po przeglądzie

Organizujemy przegląd naszej listy wyników i otrzymujemy ciekawy feedback: streszczenia nie zapewniają wystarczającej ilości informacji, by były użyteczne. Usuwamy je więc, pozostawiając jedynie tytuły. Mając przed oczami finalny layout listy, tylko z tytułami, łatwo możemy zadecydować jaka powinna być optymalna ilość wyników na stronie: 50, w przeciwieństwie do naszego pierwotnego założenia, że będzie to 10.

Na tym etapie nadal nie dodajemy stronicowania, ponieważ jest ono związane nie tylko z listą wyników, ale też z mechanizmem wyszukiwania, który jeszcze nie jest zaimplementowany.

Mechanizm wyszukiwania

Jaka jest następna najbardziej wartościowa funkcjonalność? Nasza wstępna implenetacja listy wyników jest już gotowa, nadszedł więc czas, by zaczęła ona wyświetlać prawdziwe wyniki. Gdy pracowaliśmy nieiteracyjnie, obawialiśmy się, że mechanizm będzie zwracał zbyt mało wyników, zdecydowaliśmy się więc poszerzyć na wszelki wypadek zakres przeszukiwanych stron. Pracując iteracyjnie, możemy poszerzać ten zakres stopniowo, nie stanowi więc dla nas problemu, że zaczniemy od mocno zawężonego zakresu – będziemy przeszukiwać jedynie pojedynczy popularny blog Agile.

Dodatkową korzyścią z przeszukiwania jedynie znanego, popularnego serwisu jest to, że utomatycznie gwarantuje nam to wysoką jakość artykułów, nie musimy więc implementować skomplikowanego algorytmu do wyliczania trafności wyszukań.

Mechanizm wyszukiwania – feedback po przeglądzie

Przegląd wyraźnie pokazuje, że dla większości fraz przeszukiwanie tylko jednego bloga zwraca zbyt mało wyników. Poprawiamy to iteracyjnie, dodając drugi ręcznie wybrany blog, dokonując przeglądu, dodając trzeci blog, dokonując przeglądu itd. Po kilku takich szybkich iteracjach, zatrzymujemy się na 12 czołowych blogach Agile. Gwarantuje nam to wystarczającą ilość wyników, będąc przy tym wciąż o wiele prostsze i tańsze niż implementacja przeszukiwania całego internetu.

Interesującym efektem ubocznym wszystkich tych przeglądów jest spostrzeżenie, że najciekawsze i najlepiej dopasowane tematycznie wyniki to przeważnie pierwsze 20-30 pozycji. Ponieważ nasza lista wyników może pomieścić do 50 wyników na pojedynczym ekranie, oznacza to, że na razie nie musimy w ogóle implementować stronicowania – możemy bezpiecznie przyciać ilość zwracanych wyników do 50 pozycji, nawet jeżeli nasz silnik zwróci ich więcej, bez specjalnej szkody dla jakości tych wyników.

Formularz wyszukiwania

Na tym etapie, kolejną najbardziej wartościową funkcjonalnością jest formularz wyszukiwania. Mamy już działającą wyszukiwarkę, nadeszła więc pora by umożliwić naszym klientom jakąś drogę skorzystania z niej.

Nasz pierwotny pomysł jak formularz mógłby wyglądać, był i tak maksymalnie prosty, tak więc ciężko tu uprościć cokolwiek jeszcze bardziej. Implementujemy po prostu formularz z pojedynczym polem, w które można wprowadzić frazę do wyszukania.

Formularz wyszukiwania – feedback po przeglądzie

Mimo że zaimplementowaliśmy najprostszy możliwy formularz, jego przegląd i tak ujawnia ciekawe spostrzeżenia. Jeden z naszych interesariuszy zauważył, że formularz wydaje się dosyć pusty, a ponieważ zawiera tylko jedno pole tekstowe, jest w nim cała masa miejsca na wizualne ozdobniki. W efekcie rodzi się pomysł, by zawrzeć elementy brandingu bezpośrednio w formularzu, zamiast w osobnym nagłówku.

Ponieważ nagłówek okazał się zbędny, na tym etapie stwierdzamy, że mamy już wszystkie funkcjonalności niezbędne do pierwszego wydania – nasze MVP jest gotowe! Jednakże, przegląd ujawnił jeszcze jedną istotną obserwację:

Stopka

Jeden z bardziej zorientowanych w kwestiach prawnych interesariuszy, zwrócił podczas przeglądu uwagę, że nie prezentujemy nigdzie polityki prywatności ani warunków użytkowania serwisu – a są one prawnie wymagane na niektórych rynkach. W związku z tym podejmujemy decyzję, by zaimplementować prostą stopkę z linkami do tych dwóch dokumentów.

Na tym etapie nasze MVP jest już rzeczywiście komplete i wydajemy je na produkcję.

Podsumowanie

Jak widać, podejście iteracyjne zaowocowało bardziej minimalnym zestawem funkcjonalności, pozwoliło nam lepiej stuningować nasz algorytm wyszukiwania, mocniej utwierdziło nas w przekonaniu, że produkt jest rzeczywiście użyteczny a nawet pozwoliło nam odkryć istotną funkcjonalność, którą moglibyśmy przegapić próbując przewidzieć wszystkie funkcjonalności z góry.

Oczywiście powyższy przykład jest sztucznie wymyślony, jednak podobne pozytywne efekty iteracyjnego podejścia występują też przy prawdziwych projektach – często nawet na znaczne większą skalę!

Jakie są Twoje doświadczenia z iteracyjnym budowaniem MVP, albo w ogóle z iteracyjnym sposobem pracy? Jakie korzyści takiego podejścia dostrzegasz? Podziel się proszę swoimi przemyśleniami w komentarzach poniżej!

Zobacz na blogu

09.09.2022
Marcin Jahn
It’s Not Just HTTP It’s Not Just HTTP

In today’s world of cloud-based solutions, distributed systems, and microservices-based architectures, network communication is a...

23.08.2022
Adam Mrowiec
Konferencja IPC 2022 Berlin Konferencja IPC 2022 Berlin

Pandemia wreszcie się kończy, dlatego w tym roku postanowiliśmy wrócić do naszych wyjazdów na konferencje....