Projektowanie aplikacji to złożone i wymagające zadanie. Dr Paweł Prociów – ekspert z zakresu nowych technologii, aplikacji mobilnych, IT i technologii w medycynie, a także wykładowca kierunku informatyka w DSW, opowiada o typowych błędach, jakie pojawiają się w praktyce projektowania aplikacji. Podpowiada również, w jaki sposób działać i realizować swoje projekty tak, by takowych niepożądanych efektów unikać.


Projekt Strefa Podcastów DSW współfinansowany ze środków Ministerstwa Edukacji i Nauki w ramach Programu Społeczna Odpowiedzialność Nauki, na podstawie umowy nr SONP/SN/513479/2021 z dnia 10.12.2021; kwota dofinansowania: 189 472,00 zł.


Transkrypcja podcastu

 

Jak się jest w IT, studiuje się programowanie, ma się cokolwiek wspólnego z tą tak zwaną "branżą", to prawie na pewno przyjdzie do ciebie stary kumpel z podstawówki, ktoś z rodziny i powie Ci, że ma super pomysł na aplikację i że nowy pomysł jest wart miliony. Jedyne co trzeba zrobić to oprogramować i sprzedać. Na szczęście jest pytanie, które od razu może sprawdzić na ile ten pomysł jest realny. Tym pytaniem jest: Jak taka aplikacja ma zarabiać?  Jeżeli pada odpowiedź: "na reklamach w aplikacji", czy "na reklamach na stronie", to już wiadomo, że to jest coś, co nie przystaje do dzisiejszej rzeczywistości i tak naprawdę nawet popularne aplikacje są na tym zjadane. Ale są też takie aplikacje, których celem nie jest zarabianie, których celem jest coś ważniejszego. W swoim życiu zawodowym do takich projektów, takich aplikacji staram się zwracać i z takimi mieć jak najwięcej wspólnego. Na podstawie jednej z nich, jednej z najfajniejszych z jaką miałem przyjemność pracować, stworzyłem nawet taki use case. Aplikacja nazywa się Actidote i była zrobiona ze współpracy z Uniwersytetem w Genewie w Szwajcarii, gdzie pewien młody bardzo psychiatra miał pomysł na stworzenie aplikacji, która miałaby wdrażać jego pomysł na terapię ludzi z depresją. Czyli bardzo ważny temat, bardzo ciekawy koncept. Problem jest taki, że o ile miał nawet jakiś budżet, no bo wiadomo uniwersytety w Szwajcarii mają dość fajne budżety naukowe nawet na takie naukowe projekty, to o tworzeniu aplikacji ta osoba wiedziała znacznie mniej i trzeba było ją trochę naprowadzić. No i to mi dało trochę do myślenia, że często jest tak, że może to nie chodzi o takiego kolegę z podstawówki, ale często jest tak, że tworząc projekty informatyczne mamy do czynienia z kimś, kto nie jest programistą, kto w ogóle nie jest techniczny, a jednocześnie chce zrobić coś fajnego, coś pożytecznego, coś co warto robić. Warto rozmawiać z taką osobą i warto wspólnie dojść do jakiegoś ciekawego projektu. Niestety wpadłem w pewne pułapki i myślę, że trochę jak w szkle powiększającym właśnie ten mały projekt Actidote, bo to był bardzo mały projekt jeżeli chodzi o ilość osób i jego zakres, trochę pokazuje jakie problemy mogą być z takim projektem.

 

Tak czy owak, wraz z malutkim zespołem programistów, grafików, jednym w zasadzie grafikiem, wzięliśmy ten projekt pod swoją strzechę i wyszło moim zdaniem coś bardzo fajnego. Przede wszystkim trzeba mieć świadomość tego, jakie są poszczególne etapy projektu, jakim jest aplikacja mobilna, ale to w zasadzie dotyczy każdego projektu. Czyli mamy etap specyfikacji, który w aplikacji mobilnej bardzo ważnym etapem. Zaraz dojdę do tego, po co jest etap makiety, gdzie tworzymy makiety naszej aplikacji, coś co możemy dotknąć. Wrócę jeszcze do tego. Kolejnym etapem, w zasadzie głównym, jest implementacja, czyli tworzenie całego oprogramowania, które składa się na naszą aplikację. Następnie mamy testowanie, które w zwinnym projekcie, bo teraz już wszystko oczywiście jest agile i zwinne, tak naprawdę przeplata nam się z implementacją i mamy takie mini cykle powracającego testowania i implementacji jako poszczególnych małych etapów. Niemniej na jakiejś większej osi czasu implementację i testowanie można wyróżnić jako dwa oddzielne etapy. No i potem jest coś, co warto wyróżnić jako kolejny etap, to release, proces wypuszczania naszej aplikacji, myślenia o tym co dalej, jak zarządzać nawet niewielką ilością użytkowników i przede wszystkim jak brać ten tak zwany feedback, tę informację zwrotną, że coś jest nie tak. W projekcie, o którym mówię taki spoiler alert, taka najbardziej kryzysowa sytuacja miała miejsce tak naprawdę już po wypuszczeniu tej aplikacji świat, już po release'ie. To wtedy tak naprawdę zdarzył się największy kryzys, jeżeli chodzi o tę aplikację. I to są te etapy, które chciałbym omówić po kolei i jaki może być problem na każdym z tych etapów.


Jak mówiłem, sama aplikacja polegała na tym, że pomagała ludziom z depresją planować pewne aktywności, patrzeć na to, jak one wpływają na ich samopoczucie, jak ich wykonanie wpływa na samopoczucie. Nie mówię o aktywnościach typu sport, tylko takich nawet najprostszych,  jak wizyta u rodziny czy zjedzenie dobrego obiadu. W tej aplikacji użytkownik mógł tym planowanym aktywnościom i zdarzeniom życiowym nadawać pewną wagę i mówić, ile one znaczą. Ważnym elementem tej aplikacji był też proces stymulacji, medytacji prowadzonej na temat tych aktywności. Teoria była taka, że wizualizacja i wyobrażanie sobie aktywności, zwłaszcza tych, które szczególnie przynoszą przyjemność, ma efekt terapeutyczny. To się nawet sprawdziło. Do wyników nie będę się odnosił, ale mogę powiedzieć, że całkiem dobrze to wyglądało i była zauważalna poprawa wśród osób z depresją. Oczywiście to było też monitorowane jakimiś kwestionariuszami i dodatkowymi naukowymi rzeczami. I taki projekt aplikacji do nas trafił. Tutaj pojawił się pierwszy problem, bo o ile ogólnie klient wiedział jak ta aplikacja ma wyglądać, to już kwestia tego, jak to przetłumaczyć na język, nazwijmy to aplikacyjny, jak faktycznie nowoczesne aplikacje są zbudowane, co taka aplikacja musi mieć, z tym było gorzej. I tak naprawdę to jest tak, że w dużych projektach taka specyfikacja powstaje na długo przed rozpoczęciem projektu. W takim małym projekcie, gdzie klient jest nietechniczny, pierwszy raz ma podchodzić do takiego tematu, nie ma szans zamknąć takiej specyfikacji. Ale trzeba to zrobić, trzeba maksymalnie dużo rzeczy określić, bo niektóre rzeczy wydają się oczywiste, a nie są spisane, niektóre rzeczy powinny być spisane i nie są oczywiste. Przydają różne metody analizy, np. taką najprostszą, którą bardzo lubię jest analiza MoSCoW. Nie ma nic wspólnego z miastem, jest to skrót od pierwszych liter angielskich słów must have,  should have, could have i won't have. Czyli po prostu dzielimy sobie rzeczy, które nasza aplikacja musi mieć, które mieć powinna, mogłaby mieć, czyli takie, że fajnie by było, gdyby były, ale nie muszą być. No i ta czwarta kolumna jest też bardzo ważna, czyli won't have. Czyli zdajemy sobie sprawę, że coś takiego by się przydało, że jest wymaganie, ale z jakiegoś powodu, budżetowego, czy po prostu nie mamy czasu, czy z jakiegoś innego powodu nie zrobimy tego. Ale warto mieć świadomość o tym, że była ta dyskusja, że gdzieś tam o tym pomyśleliśmy, bo może kiedyś się zmienią warunki i wrócimy do tej funkcjonalności. I tutaj, tak jak mówię, to jest najważniejszy etap projektu. Jednocześnie przy małych projektach, czy tak jak tutaj z klientem nietechnicznym, nie ma co się oszukiwać, że ta specyfikacja będzie zamknięta i nie ma co dążyć do perfekcji, bo to tylko będzie rodziło frustrację. Jeżeli w miarę jak projekt postępuje, będziemy mieli powtarzającą się dyskusję "OK, rozumiem, że to by się przydało, ale tego nie było w specyfikacji, więc może tego nie róbmy" to jest też frustrujące. Trzeba mieć pewną dozę tolerancji, że takie rzeczy się zdarzają i zawsze coś nowego dojdzie. Używanie argumentu ze specyfikacją ma sens tylko do pewnego momentu, trzeba też mieć pewną tolerancję na zmiany. Takie życie jest w małych projektach, w startupach i tego typu rzeczach.


Tutaj już robimy mały zjazd w kierunku tego, co jest specyficzne dla aplikacji mobilnych. Ważnym elementem specyfikacji jest tworzenie tak zwanych makiet i to jest turbo ważne, bo zmusza nas do myślenia nie tyle funkcjonalnościami, co to nasza aplikacja ma robić, na co ma pozwalać. Nawet nietechniczna osoba wie mniej więcej, co ta jego cudowna aplikacja ma robić, ale zmusza nas do myślenia konkretnymi ekranami i myślenia w sposób: jak włączam aplikację, co ma się pojawić, jakie powinny być elementy w menu, jak powinien wyglądać ekran. Jak wejdę w ekran i funkcjonalności to gdzie mam je prowadzić, gdzie ma prowadzić przycisk wstecz? Czyli całe flow. I to jest bardzo specyficzne dla aplikacji, nawet w projektowaniu serwisów internetowych nie mamy aż takich zagwozdek, jak w przypadku aplikacji. Powiem szczerze, że tzw. flow aplikacji to tak naprawdę najważniejszy czynnik, który decyduje o sukcesie aplikacji, bądź czy ona będzie po prostu niefunkcjonalna. Jest taki magiczny angielski skrót UX, czyli user experience i warto się posiłkować specjalistami UX, którzy wiedzą, jak te poszczególne elementy grają, jak powinny wyglądać, co jest bardziej preferowane przez większość użytkowników, co mniej. Więc to jest ważne. Ale trzeba też pamiętać w tym wszystkim, że makiety to tylko makiety, to jest odpowiednik tekturowego modelu tego, co chcemy zrobić i warto się nie zawieszać na kwestiach takich jak: ta kolorystyka mi się nie podoba, ten button powinien być mniejszy i tak dalej. Nie, makiety mają trochę inne zadanie, mają rozpisać tę naszą aplikację, na estetykę przyjdzie czas, a czasami ciężko się w to nie wkopać. Podobnie nowoczesne technologie w telefonach nie są możliwe do pokazania na makietach, które mimo wszystko są statycznymi obrazkami. I czasami jest tak, że OK, tutaj mamy coś wymakietowane, ale trzeba sobie wyobrazić jak ta funkcjonalność konkretna działa. I to też czasami jest pewien problem, dopóki się tego nie zobaczy i nie dotknie już w postaci aplikacji. Ale trzeba powiedzieć, że makieta to jest pierwszy kontakt, gdzie dotykamy już czegoś konkretnego. Zwłaszcza zbawienne jest to dla użytkownika nietechnicznego, bo może już w pewnym sensie dotknąć pewnych aspektów związanych z twoją aplikacją, kiedy pewne oczywistości wychodzą, że: O nie! Dobrze by było, żeby on miał dostęp do tej ankiety już z ekranu głównego, bo to jest najważniejsze dla mnie na przykład jako naukowca. Dlatego to jest taki bardzo ważny element, mimo że technicznie to jest część definicji projektu, ale tak naprawdę to w niej wychodzi najwięcej rzeczy związanych z tą definicją. I potem, kiedy już mamy te makiety, mamy jakąś tam specyfikację, to mamy etap implementacji. Akurat w przypadku Actidote zespół był niewielki, był grafik i jeden programista, co będzie ważne. Jeden product manager, który był jednocześnie testerem i ten grafik UX-owiec, chyba już wspomniany.


Brak redundancji oznacza małe koszty, więc można nawet całkiem złożony projekt zrobić w małym budżecie. Ale też pewne ryzyko, bo w tym momencie jeśli ktoś wypadnie z projektu, mamy duży problem i nie mamy za bardzo kim go zastąpić. Co do implementacji, ryzyk jest kilka, zwłaszcza przy małym zespole, czy ciasnych ramach czasowych. Stricte programistycznie, są rzeczy w aplikacjach - gotowe kontrolki, jakieś gotowe biblioteki, które już realizują sporą część funkcjonalności. I one mogą być super i oszczędzają kupę czasu, ale np. możemy z nimi dojść do momentu, że nie da się osiągnąć tego, co chcemy, a to jest jakaś bardzo ważna funkcjonalność. Tak więc trzeba stale robić takie trade-off’y, czy rezygnujemy, czy upraszczamy jakąś funkcjonalność, czy może wchodzimy w tą króliczą norę i sami piszemy daną funkcjonalność, nie korzystamy z gotowców. Więc tutaj też są takie ważne decyzje, tak jak mówię, zwłaszcza kiedy mamy mały zespół i mało czasu. Kolejnym problemem jest to, że praca idzie takimi małymi kawałkami i dobrze byłoby móc zapewnić taką modularność, że jesteśmy w stanie oddać mały kawałek pracy, jesteśmy w stanie go przetestować i sprawdzić, czy tylko ten mały kawałek działa. To jest typowe w zwinnym projekcie. I tu wracamy do tego, że z nietechnicznym klientem może być różnie, że może być tak, że ciężko mu sobie wyobrazić, że ma sprawdzić, czy jakaś lista dobrze się wypełnia na ekranie, ale już nie działa kasowanie elementów tej listy albo wchodzenie do poszczególnych elementów i sprawdzanie ich szczegółów. Więc to są takie problemy, które można napotkać. To jest też najdłuższy etap, bo implementujemy zazwyczaj najdłużej. W przypadku Actidote to trwało około ośmiu tygodni, zanim wszystko było w takiej postaci, jak się to mówi modnie, MVP, czyli minimum viable product, czyli po prostu coś, co można było w miarę czystym sumieniem wypuścić. Tutaj dochodzimy do testowania, które jest, jak mówiłem, oddzielnym etapem, ale tak naprawdę przemieszcza się nam z implementacją. Tutaj jest naprawdę dużo problemów, a to jednocześnie bardzo ważny etap, zwłaszcza w małym zespole, zwłaszcza gdy testujemy na relatywnie niewielkiej grupie ludzi. To są tylko ludzie, którzy mają coś wspólnego z projektem. Nie, to nie jest duża aplikacja, która może sobie pozwolić na beta testowanie, dzięki któremu mamy mnóstwo feedbacku, tylko staramy się sami wyłapać błędy. Problemem jest, że kiedy ludzie są blisko projektu, to często mają pewne rzeczy wprogramowane, tak jakby wryte, np. to, że jest dla mnie oczywiste, że jak użytkownik wchodzi do aplikacji, to idzie tutaj, potem przechodzi tutaj. W ogóle nam przez myśl nie przejdzie, że ktoś zupełnie z ulicy weźmie tę aplikację i zamiast wejść w opcje X, jako pierwszą znajdzie opcję Y. I okazuje się, że gdzieś tam wywala do góry nogami. Niestety tak jest, że życie tym projektem sprawia, że te ścieżki, które nam się wydają oczywiste i podstawowe są wyryte. Dużym problemem w testowaniu jest tak zwany confirmation bias, czyli że staramy się raczej potwierdzić swoją tezę niż jej zaprzeczyć. Podświadomie unikamy zepsucia tego, co testujemy, a raczej staramy się udowodnić, że działa. A to nie jest dobre podejście. Raczej powinniśmy się starać szukać dróg, które możemy zepsuć tylko po to, żeby to potem naprawić. Ale to też jest czasami ciężkie, bo nasz mózg jest skrojony tak, że dąży do potwierdzania hipotez, nie do ich obalania. Drugą stroną tego medalu jest to, że testujemy jakieś nierealne scenariusze, których nikt nie używa na co dzień. Czyli np. jak 10 razy wejdę w ustawienia i potem wywalę aplikację, no to coś się dzieje i to trzeba koniecznie naprawić. Oczywiście, że trzeba, ale czy to czasami nie są nienaturalne scenariusze? Więc nie powinniśmy się starać psuć za bardzo, bo tracimy potem czas na naprawianie nierealnych scenariuszy, podczas gdy coś bardziej oczywistego jest na wyciągnięcie ręki. Trzeba powtarzać ten cykl implementacji, testowania, implementacji, testowania aż w końcu dochodzimy do takiego momentu, w którym jesteśmy w miarę zadowoleni z naszego produktu. Na tyle, że chcemy go wypuścić. No i przechodzimy do ostatniego etapu, którym jest to wypuszczenie. Tutaj trzeba pamiętać o tym, że wypuszczamy projekt w zupełnie nie kontrolowanym przez nas środowisku. Mówię o użytkownikach. Zarówno na Androidzie, jak i  na iOS-ie tak naprawdę jedynym sposobem dystrybucji są oficjalne sklepy. Na Androidzie jeszcze jest możliwe wysłanie aplikacji mailem czy jeszcze przez jakieś niestandardowe platformy, ale nawet to się już powoli kończy. Na iOS-ie praktycznie nie mamy szans poza oficjalnym App Store. Trzeba grać trochę według zasad tych sklepów. Czasami to trwa. Czasami jest tak, że nawet głupia zmiana musi być przejrzana. W Apple iOS każdą zmianę przed wypuszczeniem do sklepu fizycznie musi przejrzeć pracownik Apple. O tym trzeba pamiętać, zwłaszcza jeżeli jest jakiś szybki fix do wypuszczenia. Trzeba więc pamiętać, że to wypuszczanie też ma swoją cenę. Więc wypuszczamy tylko przetestowane funkcjonalności, takie, których jesteśmy pewni i o których wiemy, że za dwa dni nie trzeba będzie znowu wypuszczać czegoś nowego. W szerszej skali, użytkownicy nie lubią zbyt częstych update'ów, zwłaszcza starsi użytkownicy komputerów wiedzą, co to znaczy update Adobe Readera, który średnio dwa razy na dzień się update'ował. W przypadku aplikacji to też jest irytujące. W zasadzie wiele dużych aplikacji ma ustalone zasady, że np. nie update'ują swoich aplikacji częściej niż co X tygodni. Trzeba pamiętać, że to po prostu irytuje. Z drugiej strony trzeba też pamiętać, że to zajmuje czas. Sam proces, łącznie z tym, że jest jakiś etap przejrzenia czasami zamyka się w mniej niż 24 godzinach, ale to zawsze jest jakieś opóźnienie.


Warto pamiętać o tym, że trzeba sobie zapewnić jakiś sposób kontaktu ze swoimi użytkownikami, żeby mogli coś zgłaszać, że coś jest nie tak i to w sposób zautomatyzowany, więc wystarczy email "W razie problemów napisz". Ale też są sposoby jak monitorować żywotność naszej aplikacji w sposób programistyczny. Są platformy jak Crashlytics, które mówią nam na przykład ile jest aktywnych sesji, ile wyskoczyło błędów, jakie to były błędy, bo często są błędy, o których użytkownik może nie wiedzieć, bo np. gdzieś tam w tle wystąpiły i już możemy coś zrobić z nimi zanim spowodują jakiś większy problem. W projekcie, o którym mówię, taka sytuacja kryzysowa miała miejsce tuż po release i miała związek tak naprawdę ze wszystkimi etapami. Na etapie specyfikacji ustaliliśmy, że przez tydzień użytkownik będzie się samomonitorował, a aktywna część naszej aplikacji będzie się włączała dopiero po tygodniu od instalacji. W ramach tego samomonitorowania użytkownik mógł wypełniać swój kalendarz, co robił. I oceniał to. Tam były jeszcze dodatkowe metryki i tak to zostało zaimplementowane. No i gdzieś pod koniec projektu, który szedł bardzo dobrze i w testowaniu nie za bardzo wychodziły jakieś błędy, widzieliśmy, że mamy jeszcze trochę czasu przed ustaloną datą wypuszczenia i że może coś dodamy z kolumny "nice to have", takiej listy, że mogłoby być, ale tego na razie nie robimy. Wybraliśmy coś, co się wydawało najprostsze i najszybsze - w pamiętniku mogłem aktywnie zaznaczyć, że nic nie robiłem.  Że po prostu dodaję element, który się nazywa brak aktywności. Tak żeby było wiadomo, że jak nie ma aktywności, to nie znaczy, że ktoś nie wypełnił tego kwestionariusza, a po prostu może go wypełnić, ale z taką informacją, że nie było żadnej aktywności. Taka mała, wydaje się, zmiana. Co się okazało? Po tygodniu, czyli kiedy wchodził ten aktywny element naszej aplikacji, wszystko się wykrzaczyło, ponieważ dodanie nowego rodzaju elementu w bazie danych, mówiąc kolokwialnie, przesunęło wszystko o jedno w prawo i powodowało, że wyświetlanie statystyk absolutnie wykraczało poza aplikację. Wyszło to dopiero po tygodniu od momentu zmiany, a nie w trakcie. A że aplikacja była wypuszczona do określonej grupy testowej, więc oni wszyscy mniej więcej jednocześnie zainstalowali tę aplikację, przynajmniej w pierwszym rzucie, toteż wszyscy w jednym rzucie po tygodniu nagle zaczęli mieć problemy. Tutaj też taka śmieszna anegdota, że dobra, mamy jakiś problem, potem wyszło co to jest. Może nie idealnie, ale wiadomo - jak jest kryzys, to kryzys i co można? Co jest takiego ważnego, co się robi w sobotę, żeby nie móc na chwilę jakiegoś jednego bardzo ważnego krytycznego błędu ogarnąć? Akurat jedyny programista w projekcie brał ślub, więc takie było zrządzenia losu. Na szczęście udało się tę sytuację opanować jeszcze przed wyjazdem na miesiąc miodowy. Pokazało to, że warto testować bardzo intensywnie, bo ta funkcjonalność była dodana w ostatniej chwili. Warto mieć redundancje w zespole i warto mieć sposób monitorowania tego rodzaju błędów. Akurat to ostatnie mieliśmy. Dzięki temu w miarę szybko ustaliliśmy, co było problemem. Tak naprawdę najważniejsze co pokazuje ta sytuacja, to że najważniejszym elementem każdego projektu dużego, małego, skomplikowanego, prostego jest właściwy zespół i ludzie, którzy są w stanie jak trzeba dać te ekstra 10% od siebie, żeby wszystko poszło dobrze. Bo tak naprawdę ta sytuacja mogła być dużo gorsza, gdyby nie to, że każdy był gotów coś tam od siebie dodać i zrobić coś fajnego. I dzięki temu ten projekt był jednym z fajniejszych, w których miałem przyjemność brać udział. Warto pamiętać o tym, że w każdym projekcie, czy to informatycznym, czy jakimkolwiek innym, ale też w szczególności projekcie aplikacji jak ten, o którym opowiadam, błędów uniknąć się nie da i nigdy się nie będzie dało. Jedynie, co można robić, to mitygować pewne ryzyka tych błędów i mieć na uwadze, że one mogą wyjść na każdym z etapów. Powiedziałem już, że bardzo ważny w zarządzaniu takimi błędami, bo te tak zwane fakapy zawsze się znajdą, jest dobry zgrany zespół, który jest gotów zaradzać tym błędom, który się nie posypie w momencie, kiedy wyjdzie jakaś sytuacja kryzysowa, który umie reagować na pewne nieoczekiwane rzeczy. To są zarówno metodologie, które nam pomagają unikać tych błędów, czyli dobre zarządzanie projektem, jasne rozdzielenie etapów, świadomość tego, jakie są te etapy, czyli to, o czym tutaj powiedziałem. Są też technologie, które nam pomagają unikać błędów. Na szczęście dzisiejsza technologia pozwala nam łapać jakieś błędy, jakieś odczyty z logów czy wszelkiego rodzaju krytyczne sygnały jeszcze zanim to dojdzie do użytkownika, zanim pójdzie na przykład wściekły e-mail czy jedna gwiazdka na sklepie z aplikacjami. Więc na to też warto proaktywnie reagować, rezerwować sobie czas, że coś takiego musi być. No i najważniejsze to, żeby w obliczu błędu nie być sparaliżowanym niczym ta sarna w świetle reflektorów, tylko po prostu być gotowym na to, móc reagować, kreślić nawet gdzieś w myślach jakieś scenariusze co może pójść nie tak. Tutaj wracamy do confirmation bias, bo wiemy, że niestety nasze mózgi lubią potwierdzać pewne hipotezy. Warto też poświęcać jakąś część naszej wyobraźni na to, co może pójść nie tak i jak mogę temu zaradzić. I myślę, że to jest bardzo ważne w każdym projekcie.  

 

Zobacz także