Dzisiaj rano dowiedziałem się, że zawaliliśmy projekt. Dokładniej: że tak to zapamiętał klient, z którym rozstaliśmy się ponad rok temu. W mojej głowie rozstaliśmy się w dobrych warunkach, podaliśmy sobie ręce, bez żalu. Pierwsza reakcja była prosta: to niesprawiedliwe. Druga, po kawie, była mniej przyjemna: to częściowo nasza wina, tylko nie z tego powodu, o który nas obwiniono.
Opiszę ten case, bo myślę, że większość agencji, software house’ów i firm pracujących w modelu „kilku dostawców, jeden klient” prędzej czy później przez to przejdzie. Wolę, żebyście przeszli przez to na moim tekście niż na własnym kontrakcie.
Opisuję sytuację z Naszej perspektywy. Nazwy firm pomijam celowo, bo nie chodzi o to, kto, tylko o mechanizm.
Jak to się zaczęło
Ten projekt nie zaczął się od czystej kartki. Przejęliśmy sklep internetowy w totalnym bałaganie po innej agencji, z którą klient rozstał się w sporze.
Im dłużej czytaliśmy kod, tym lepiej rozumieliśmy, że to nie była zła agencja. W kodzie było widać dwie różne historie. Są w nim miejsca zrobione starannie, z myślą o przyszłości, bo ktoś liczył na długą współpracę i uczciwy zarobek. Są też miejsca, w których widać pośpiech, skróty i „byle działało”. Tam widać było w kodzie straty finansowe agencji który był wynikiem sporu w którym strony przepychały się o to, co w kontrakcie ze sztywną ceną jest poprawką, a co pracą dodatkową.
Kod nie kłamie. Pokazuje dokładnie, w którym momencie ktoś przestał wierzyć, że ta współpraca mu się opłaca. Każdy, kto przejmował cudzy projekt, zna tę pokusę. Działa jak u mechanika: „panie, a kto to panu tak spie…?”. Łatwo zbudować sobie pozycję na tym, że poprzednicy byli beznadziejni. My tego nie robiliśmy. Nie wybielaliśmy ich, po prostu uczciwie mówiliśmy klientowi, co widzimy, bez dokładania negatywnej narracji. Powiedzieliśmy wprost: to nie był zły programista w złej agencji. To był zły model rozliczeń i zła komunikacja między stronami, które miały dobre intencje.
Zapamiętajcie to zdanie, bo wróci pod koniec tej historii.
Od sprzątania do rozwoju
Sprzątanie poszło szybko. Potem zaczęła się właściwa praca, czyli rozwój. Rozbudowywaliśmy sklep o nowe funkcje, poprawialiśmy UX, pracowaliśmy nad SEO i wdrażaliśmy kolejne pomysły, które realnie przekładały się na biznes klienta. Równolegle regularnie wdrażaliśmy poprawki i aktualizacje bezpieczeństwa, żeby sklep spełniał aktualne normy.
To była dobra współpraca, z wynikami, które dało się pokazać w liczbach.
Uczciwie trzeba też powiedzieć, że z naszego punktu widzenia projekt cały czas miał dług technologiczny. Mógł spokojnie funkcjonować, ale jego fundamenty pochodziły z czasów, kiedy nikt nie myślał o nim w perspektywie lat. Każdą aktualizację planowaliśmy ostrożnie. To było miłe gdy usłyszeliśmy, że “to dzięki i waszej pracy wogóle pojawiły się nam zamówienia”. Po dwóch latach opublikowana została aktualizacja bezpieczeństwa, po której podniesienie wersji stało się bardzo ryzykowne. Od tego momentu każdy miesiąc bez przebudowy powiększał dług, zamiast go zmniejszać.
Problem skali i nasz pomysł na niego
Był jeszcze drugi, poważniejszy problem: integracje z dostawcami.
Na starcie sklep miał dwie integracje. Docelowo miało ich być dwadzieścia. Wszystko przetwarzało się operacyjnie na serwerze sklepu, więc każda nowa integracja oznaczała ogromne opóźnienia, kolejne rundy optymalizacji i coraz bardziej zamulony serwer. Rozwiązanie, które działało przy dwóch dostawcach, przy dwudziestu przestawało być możliwe. Nie trudne, tylko niewykonalne.
Zaproponowaliśmy więc inne podejście, czyli hub danych. To osobny system na osobnym serwerze, który zbiera dane od wszystkich producentów, niezależnie od źródła i formatu, strukturyzuje je i przetwarza. Do sklepu trafia jeden uporządkowany strumień danych, a sklep przestaje być jednocześnie witryną, magazynem i przetwórnią danych.
To był nasz pomysł na to, jak rozwiązanie architektoniczne może wprowadzić nową jakość.
Podział projektu
Dług technologiczny sklepu i nowa architektura danych razem dawały naturalny moment na decyzję o nowym sklepie.
W tym samym czasie klient podjął decyzję, którą dziś rozumiem lepiej niż wtedy: nie chciał mieć wszystkiego w jednych rękach. Po doświadczeniu z poprzednią agencją trudno mu się dziwić. Rozdzielił projekt. My odpowiadaliśmy za hub danych, czyli integrację producentów i dostarczanie danych. Druga agencja miała te dane odbierać i budować nowy sklep, w praktyce nową wersję tego, który przez dwa lata rozwijaliśmy.
Z perspektywy klienta to rozsądna hipoteza: dywersyfikacja ryzyka, brak uzależnienia od jednego dostawcy, zdrowa konkurencja. Dwie agencje pracujące równolegle nad dwoma projektami. Mieliśmy gotowy drugi team do projektu ale rozumieliśmy taką decyzję.
Co widzieliśmy po naszej stronie
Dostarczyliśmy API. Specyfika projektu była taka, że każda kategoria produktowa miała inną strukturę danych i każda musiała komunikować się osobno. To wymaga po obu stronach jednego: usiąść, przejść kategorię po kategorii i zebrać wymagania w jedną listę. W tej kategorii potrzebujemy jeszcze takiego parametru, w tamtej innego, tu zmieniamy format. Taką listę zamyka się w kilka dni pracy.
Takiej listy nie dostaliśmy. Dostawaliśmy za to odbicia i kolejne maile, w których pojawiały się nowe problemy. Pojedynczo, kawałek po kawałku, z przerwami. W naszym odczuciu te maile nie przybliżały projektu do końca, tylko rozciągały go w czasie i szukały powodów, żeby integracji jeszcze nie robić.
Nie musieliśmy się długo zastanawiać, skąd się to bierze. Druga agencja publicznie szukała ludzi do zespołu, a ogłoszenie rekrutacyjne wisiało w sieci, na oferi oraz innych miejscach i w czasie, kiedy integracja miała już trwać. Branża programistyczna jest mała, ludzie się znają i rozmawiają szczególnie z tego samego miasta. Dość szybko wiedzieliśmy, że problem jest organizacyjny, a nie techniczny. Wiedzieliśmy też, jaka wersja wydarzeń trafia do klienta.
A ta wersja brzmiała: integracja nie może ruszyć, bo po stronie hubu danych są stale błędy. W naszych logach nie znajdowaliśmy na to żadnego potwierdzenia.
Problem na trzy minuty
Kiedy dane w końcu zaczęły być odbierane, narracja się nie zmieniła. Zmieniła się tylko skala.
Pamiętam zgłoszenie, które trafiło do klienta jako dowód, że nasza struktura nie działa. Poprawka zajęła trzy minuty. Nie trzy dni, nie trzy sprinty, tylko trzy minuty. Sprawa, którą załatwia jedna wiadomość między programistami, urosła do rangi eskalacji.
Nie wiem, jakie intencje za tym stały, i nie będę zgadywał. Wiem za to, jak to działa z perspektywy klienta. Kiedy słyszysz o problemach z tym samym dostawcą piąty raz, przestajesz pytać, jak duże one były. Zapamiętujesz tylko, że były.
Dlaczego nic nie powiedzieliśmy
Mieliśmy logi, historię zgłoszeń, całą korespondencję, czasy reakcji i dość dobre wyobrażenie o tym, co dzieje się po drugiej stronie. Nie użyliśmy niczego.
Jeden z naszych ludzi powiedział mi wtedy wprost: nie komunikuj tego, zostaw to dla siebie, czas nas obroni. Miał swoje powody, dobre i ludzkie. Do tego dołożyliśmy zasadę, która dobrze nam służyła od początku tego projektu: nie dokładamy negatywnej narracji o innych dostawcach. Przy przejęciu sklepu to działało. Uznaliśmy, że zadziała i teraz.
Czas nas nie obronił.
I tu jest część, która boli najbardziej. Zasada była dobra, tylko źle ją zrozumieliśmy. Przy przejęciu nie milczeliśmy: mówiliśmy klientowi uczciwie, co widzimy, tylko bez złośliwości. Tym razem nie powiedzieliśmy nic. A żeby pokazać klientowi prawdę, nie trzeba było opowiadać ani jednej historii z cudzej firmy. Wystarczyły nasze własne logi, nasza korespondencja i nasza historia zgłoszeń, łącznie z tym na trzy minuty. Pomyliliśmy dwie rzeczy: brak negatywnej narracji i brak jakiejkolwiek narracji. Pierwsze było słuszne. Drugie nas pogrążyło.
Dlaczego prawda nie wyszła na jaw
Bo prawda nie wychodzi na jaw sama. Ktoś musi ją wynieść.
Po kilku miesiącach wiedzieliśmy już, że kontrakt przejdzie w całości do drugiej agencji. Rozstanie przebiegło spokojnie. Oficjalny powód był biznesowy i dla mnie zrozumiały: druga strona zaproponowała cenę ryczałtową, która na starcie wyglądała atrakcyjniej niż nasz model rozliczeń. A nasz model był, i tego będę bronił, uczciwszy i finalnie korzystniejszy dla klienta. Klient płacił za realnie wykonaną pracę, z pełną przejrzystością.
Z tego, co było widać z zewnątrz, realizacja po drugiej stronie mocno się przeciągnęła.
Rok później słyszymy podsumowanie: „nie dowieźli”. Kto? My. Mechanizm jest banalnie prosty i dlatego tak groźny. Kiedy projekt się sypie, każda strona buduje opowieść, która chroni jej wizerunek. To nie jest cecha złych firm, tylko cecha ludzi pod presją. Jedna strona miała opowieść i regularnie ją powtarzała. My nie mieliśmy żadnej, bo uznaliśmy, że fakty obronią się same. Klient nie siedział w logach. Klient słuchał tego, kto mówił.
W takiej sytuacji nie wygrywa ten, kto ma rację. Wygrywa ten, kto ma narrację.
Hipoteza, którą obaliłem na własnym kontrakcie
Moja hipoteza brzmiała dokładnie tak jak rada, którą usłyszałem: czas nas obroni.
Test: posprzątany projekt, dwa lata rozwoju z mierzalnymi wynikami, autorski pomysł na architekturę, która rozwiązała problem skali, dobra orientacja w tym, co dzieje się po drugiej stronie, i zero komunikacji na ten temat.
Wynik: po roku klient pamięta nas jako tych, którzy nie dowieźli.
Wniosek: czas nikogo nie broni. Czas utrwala tę wersję wydarzeń, którą ktoś powtarzał najczęściej.
Co powinniśmy byli zrobić
Kiedy dziś rozkładam ten projekt na części, widzę co najmniej sześć momentów, w których mogliśmy zmienić jego zakończenie. Żaden z nich nie wymagał mówienia złego słowa o drugiej agencji.
- Raportować fakty, nie opinie. Nie „tamci nie pracują”, tylko cotygodniowy status: „API dostępne, dane z X producentów zaktualizowane, zgłoszenia w tym tygodniu: tyle, rozwiązane: tyle, średni czas rozwiązania: tyle, otwarte pytania czekające na drugą stronę: takie”. Suche liczby. Klient sam wyciąga wnioski i nikt nie może Ci zarzucić, że kogoś oczerniasz.
- Zrobić logi i monitoring widocznymi dla klienta. Jeśli ktoś twierdzi, że Twój system ma błędy, najlepszą odpowiedzią jest dashboard, do którego klient ma dostęp. Nie trzeba się bronić, kiedy dane bronią się same. Ale tylko wtedy, kiedy ktoś na nie patrzy.
- Mierzyć czas rozwiązania każdego zgłoszenia. Gdybyśmy mieli prosty rejestr „zgłoszone, rozwiązane, czas”, problem na trzy minuty byłby widoczny jako problem na trzy minuty. Bez rejestru stał się kolejnym dowodem w cudzej opowieści.
- Wymusić jedną listę wymagań i wspólne spotkania. Przy integracji z wieloma strukturami danych maile po kawałku to przepis na projekt bez końca. Trzeba zażądać jednego dokumentu z wymaganiami dla wszystkich kategorii, zamkniętego w konkretnym terminie, i cotygodniowego spotkania obu ekip z klientem przy stole. Przy takim formacie żadna narracja nie przetrwa dłużej niż do następnego czwartku.
- Zapisać w umowie odpowiedzialność za styk. Kto definiuje format danych, kto i w jakiej formie zgłasza wymagania, kto zgłasza błąd, w jakim trybie, w jakim czasie jest odpowiedź. Jeśli tego nie ma na piśmie, to przy pierwszym problemie odpowiedzialność ląduje u tego, kto najciszej się broni.
- Zamknąć współpracę raportem, a nie uściskiem dłoni. Rozstaliśmy się miło i to był błąd. Powinniśmy byli zrobić porządne podsumowanie: co zastaliśmy na początku, co naprawiliśmy, co rozwinęliśmy, jaką architekturę zaprojektowaliśmy i dlaczego, w jakim stanie przekazujemy system, jaki dług technologiczny zostaje, jakie dostępy zostają odcięte i od kiedy. Na piśmie. Nie jako obronę, tylko jako profesjonalne domknięcie. Taki dokument po roku jest wart więcej niż najlepsze wspomnienia ze wspólnej kawy.
Kilka słów o cenie ryczałtowej
Muszę wrócić do tego wątku, bo on w tej historii nie jest przypadkowy. Pojawia się w niej dwa razy.
Ryczałt wygląda bezpiecznie dla klienta: znam kwotę, wiem, ile wydam. W projektach integracyjnych, gdzie każda kategoria produktów ma inną strukturę, a dostawców ma być dwudziestu, ryczałt przenosi ryzyko na wykonawcę. A wykonawca, który wziął na siebie ryzyko i zaczyna je przegrywać, ma w praktyce dwa wyjścia: dołożyć z własnej kieszeni albo szukać przyczyn gdzie indziej.
Najbardziej gorzkie jest dla mnie to, że zaczęliśmy tę historię od sprzątania po sztywnej cenie. Widzieliśmy w kodzie, co się dzieje z projektem, kiedy wykonawca zaczyna na nim tracić. Tłumaczyliśmy klientowi, że zawiódł model, a nie ludzie. A potem przegraliśmy kontrakt z tym samym modelem, tylko w nowym opakowaniu. Nie oceniam, co wybrała druga strona w tym konkretnym projekcie. Mówię tylko, że jako klient warto zadać sobie pytanie: co zrobi mój dostawca, kiedy jego wycena okaże się zbyt optymistyczna? Bo to, że się okaże, jest w projektach IT raczej regułą niż wyjątkiem. Ten klient przerobił to już raz.
Nie wiem, czy na końcu zapłacił mniej. Wiem, że zapłacił czasem, a czas w e-commerce to też pieniądze.
Czego się nauczyłem
Nie zawsze wszystko wygląda tak, jak się wydaje. Klient widział projekt przez opowieść, którą słyszał. My widzieliśmy go przez logi, korespondencję i przez to, co branża mówiła między wierszami. Obie perspektywy były niepełne, tylko jedna z nich trafiła do decydenta.
Na początku tej współpracy tłumaczyliśmy klientowi, że poprzednia agencja nie była zła, tylko zawiódł model i komunikacja. Dziś mogę to samo zdanie powiedzieć o nas. Model nas nie uratował, a komunikację po prostu odpuściliśmy bo nie chcieliśmy zaatakować partnera w projekcie klienta.
Najważniejsza lekcja jest dla mnie taka: milczenie nie jest neutralne. Można nie obgadywać konkurencji i jednocześnie mówić klientowi o własnej pracy wszystko. Kiedy nie komunikujesz, zostawiasz miejsce, które ktoś inny wypełni. Po swojemu. Nie zamierzam dzwonić do klienta i tłumaczyć się po takim czasie. To byłoby spóźnione i wyglądałoby właśnie jak tłumaczenie się. Zamierzam za to zmienić sposób, w jaki prowadzimy projekty z kilkoma dostawcami. Jeśli jesteście w podobnym układzie, zróbcie to, zanim dostaniecie po głowie:
- Ustalcie rytm raportowania faktów: co tydzień, liczbami, bez przymiotników.
- Dajcie klientowi wgląd w działanie Waszej części systemu, zanim ktoś zapyta.
- Prowadźcie rejestr zgłoszeń z czasem rozwiązania. Trzy minuty muszą wyglądać jak trzy minuty.
- Żądajcie jednej listy wymagań z terminem, zamiast maili po kawałku. Organizujcie wspólne spotkania na styku z udziałem klienta. Jeśli druga strona ich unika, to też jest informacja.
- Zapiszcie odpowiedzialność za integrację w umowie, łącznie z trybem zgłaszania wymagań i błędów.
- Nazywajcie dług technologiczny na głos i na piśmie, razem z tym, skąd się wziął i co go powiększa.
- Kończcie współpracę raportem zamknięcia, z listą przekazanych elementów i odciętych dostępów.
- Przy porównaniu z ofertą ryczałtową pokażcie klientowi, kto nosi ryzyko i co się z nim dzieje, kiedy wycena nie wytrzyma kontaktu z rzeczywistością.
Nie da się wygrać każdego kontraktu. Da się za to zadbać o to, żeby historię Waszej pracy opowiadali Wasi klienci na podstawie faktów, a nie Wasi konkurenci na podstawie wygody.
A jeśli ktoś Wam kiedyś powie „czas nas obroni”, odpowiedzcie mu, że czas nie ma dostępu do Waszych logów. Klient też nie, dopóki mu ich nie pokażecie.


