Zamień ten tekst na URL Webhooka

Full-stack i Programowanie

Move fast and break things - o budowaniu swoich produktów

Wydanie nr
27
opublikowane
2023-07-15
Daniel Noworyta
Daniel Noworyta
Full stack Developer
No items found.

Ostatnio mam wrażenie, że mamy do czynienia z wielkim hypem na technologie typy Rust, czy GoLang. Jest to poniekąd zrozumiałe. Jeżeli podchodzisz do kodu poważnie, to zależy Ci na tym, żeby Twoje rozwiązanie było jak najbardziej skalowalne i działało szybko. Jednak zastanówmy się teraz, czy takie podejście jest prawidłowe podczas budowania produktu?


Przekraczając granice kodowania: Dlaczego naprawdę piszemy kod?

Kiedy przyjdzie Ci budować swoje produkty i rozwiązania. Będziesz mieć wiele rzeczy, o których trzeba będzie pomyśleć. Mógłbym je tutaj wymieniać, jednak chcę zadać Ci pytanie. Jaka jest najważniejsza rzecz podczas pisania kodu, czy wdrażania jakiejś funkcjonalności?

rozwiązanie konkretnego problemu użytkownika końcowego

To jest cel naszego kodu. To jest to, dlaczego Twoje rozwiązanie istnieje. Pisząc kolejne linijki swojego kodu, zawsze miej na uwadze to, że rozwiązujesz jakiś problem i to jest Twoim celem nadrzędnym.

I teraz jednakowo podczas podejmowania decyzji architektonicznych, czy pisania konkretnego kawałka kodu wprowadzającego nową funkcjonalność do aplikacji. Dopóki nie będziesz mieć pewności, czy rozwiązujesz problem, to czy jest sens zawracać sobie głowę skalowalnością i niezawodnością danego rozwiązania?

Szybkie iteracje to klucz w początkowej fazie

Bardzo często w początkowej fazie budowania aplikacji, czy wdrażania konkretnej funkcjonalności będziesz poruszać się w obszarze wielkiej niepewności. Warto wtedy byś skupił swoją uwagę na odnalezieniu rozwiązania problemu. Iteruj szybko, bo póki co działasz w środowisku wielkiej niepewności.

Jest to całkiem normalne, że musisz iterować i szukać tzw. Product Market Fit. Co prawda jest to pojęcie często używane w środowisku startupowym, ale jakby się nad tym głębiej zastanowić. Można to jak najbardziej odnieść do nowej funkcjonalności, czy nawet kawałka kodu, który ma na celu rozwiązać jakiś problem.

Przyznaje się bez bicia, że sam bardzo często łapię się na tym, że do wbicia przysłowiowego gwoździa używam nie tego narzędzia. Popatrz na przykład kodu poniżej:

Jesteśmy w komponencie Reactowym. Budujemy aplikację typu chat, gdzie potrzebujemy globalnie przechowywać sobie mapę widoczności użytkowników i robimy to w formie Presence context. Jest to moment inicjalizowania mapy widoczności użytkowników w naszej aplikacji.

Na pierwszy rzut oka wszystko z tym kodem w porządku. Iterujemy sobie po użytkownikach i wstawiamy do naszej bazy nowy rekord w postaci id i aktualnego statusu użytkownika.

Jednak co pomyślisz sobie jeżeli będziesz wiedział, że w momencie odpalania pętli forEach masz już informacje na temat wszystkich użytkowników i ich widoczności presence? W przykładzie mamy tylko 3 użytkowników w naszej tablicy, ale co gdyby mieć ich setki?

Skoro używamy react context API, to oznacza, że za każdym razem, kiedy aktualizujemy widoczność dla danego użytkownika nasz kontekst się zmienia i re renderujemy wszystkie komponenty, które dany kontekst konsumują. Poniżej optymalne rozwiązanie tego problemu:

Na początku, dopóki nie rozwiązujesz problemu. Jest rzeczą całkiem normalną, że iterujesz i szukasz rozwiązania.

Moment na skalowanie: kiedy powinieneś to zrobić?

Z czasem, kiedy nasze rozwiązanie czy API aplikacji staje się bardziej stabilne. Wprowadzamy coraz mniej nowych funkcjonalności. Wtedy nadchodzi czas, by zastanowić się nad innymi aspektami naszego rozwiązania. Kiedy pojawia się ruch w naszej aplikacji, wtedy warto skupić swoją uwagę na kosztach i niezawodności naszego rozwiązania.

Myślę, że fajnie przedstawi to poniższa grafika

Po lewej stronie w pierwszej ćwiartce mamy początkowy cykl życia aplikacji/kodu. Mamy względnie mały ruch i osoby korzystające z danego rozwiązania nie są jakąś specjalnie liczną populacją. Z czasem, kiedy jest coraz więcej użytkowników i zaczynają nam doskwierać problemy rosnących kosztów i niezawodności przesuwamy sie w kierunku ćwiartki numer 4.

Najgorsze co możesz zrobić to wylądować w ćwiartkach 2 lub 3. Ćwiartka numer dwa przedstawia przespany moment, w którym niezbędna jest niezawodność Twojego rozwiązania przez dużą liczbę użytkowników, ale ty ciągle poruszasz się w obszarze szybkiego iterowania i niepewności. W tym momencie Twoje API powinno być już na tyle stabilne, że Twoja uwaga powinna skupić się na niezawodności i kosztach Twojego rozwiązania.

Inaczej sytuacja wygląda jak wylądujesz w ćwiartce numer 3. Bardzo często widzę osoby, które do budowania swojego bloga wykorzystują kubernetesa, czy golanga. Jeżeli jest to projekt po godzinach to nie mam z tym problemu. Jednak jeżeli jest to rozwiązanie produkcyjne, to ruszamy z czołgiem na kanarki. Stosowanie wymyślnych rozwiązań w celu walidacji pomysłu mija się z celem.

Działaj szybko, nie bój się błędów: klucz do szybkiej adaptacji

"Move fast and break things" to motto, które zyskało na popularności dzięki Markowi Zuckerbergowi, założycielowi Facebooka. Choć ta filozofia bywa kontrowersyjna, to ma swoje silne strony w kontekście szybkiego iterowania i budowania produktów.
Zasada ta polega na szybkim wprowadzaniu zmian i ciągłym poszukiwaniu innowacji, nawet jeśli może to prowadzić do błędów. W kontekście tworzenia oprogramowania "Move fast and break things" oznacza, że niewielkie błędy, które powstają w wyniku szybkiego tworzenia i wdrażania nowych funkcji, są akceptowalne, o ile generalnie przyspieszają one rozwój produktu.
Jednak co się dzieje, kiedy "Move fast and break things" staje się mantrą, która przyćmiewa inne ważne aspekty, takie jak skalowalność czy niezawodność kodu? Na długą metę, podejście to może prowadzić do problemów. Często musimy balansować pomiędzy szybkością wprowadzania zmian a utrzymaniem jakości kodu i zapewnieniem, że nasze rozwiązania są solidne i skalowalne.

Pamiętaj, że niezależnie od technologii, w której piszesz, czy to jest Rust, GoLang, czy coś innego, najważniejsze jest, abyś skupiał się na tworzeniu rozwiązań, które naprawdę rozwiązują problemy użytkowników.

"Move fast and break things" nie powinno oznaczać, że ignorujesz problemy z jakością kodu czy zaniedbujesz potrzebę skalowalności i niezawodności. Oznacza to, że jesteś gotowy do szybkiego działania, wprowadzania zmian i uczynienia swojego produktu lepszym. Jednak, gdy twoje rozwiązania zaczynają się stabilizować i przynoszą wartość użytkownikom, ważne jest, aby zwrócić uwagę na te aspekty, które zapewniają długotrwały sukces twojego produktu.

Zatem ruszaj szybko, nie bój się popełniać błędów, ale pamiętaj, że musisz również skupić się na jakości i skalowalności swojego kodu, aby na dłuższą metę osiągnąć sukces. "Move fast and break things", ale pamiętaj o wyważeniu szybkości z jakością.

Podsumowanie

Podczas tworzenia nowych rozwiązań i funkcjonalności, istotne jest pamiętanie o balansie pomiędzy szybkim iterowaniem a dbałością o jakość kodu. O ile na początku istotne jest szybkie wprowadzanie zmian, o tyle z czasem, gdy nasze rozwiązania zaczynają się stabilizować, ważne staje się skupienie na skalowalności i niezawodności kodu. Przykładem takiego podejścia może być motto Facebooka "Move fast and break things".

Nie zapominajmy, że niezależnie od technologii, której używamy Rust, GoLang czy innej. Kluczowe jest tworzenie rozwiązań, które rozwiązują realne problemy użytkowników. Wprowadzanie zmian jest ważne, ale nigdy nie powinno zasłonić nam celu, jakim jest tworzenie trwałych, stabilnych i wartościowych produktów.

Stosowanie odpowiedniego narzędzia w odpowiednim momencie to klucz do sukcesu. Zawsze pamiętaj o celu swojego kodu i twórz go z myślą o użytkownikach i problemach, które mają być rozwiązane. Takie podejście pozwoli na szybkie iterowanie w początkowej fazie tworzenia produktu, a wraz z rozwojem skupienie na jakości i niezawodności kodu. W efekcie "Move fast and break things", ale nie zapominaj o długoterminowym sukcesie twojego produktu poprzez dbałość o jakość i skalowalność.

Pamiętaj, że języki programowania i technologie są narzędziami, które pomagają nam rozwiązać problemy, ale to od nas zależy, w jaki sposób je wykorzystamy. Wykorzystuj narzędzia mądrze, nie zapominając o tym, do czego służą i jak mogą pomóc w rozwiązaniu problemów użytkowników.


  • Budowanie swoich produktów
  • Kiedy warto skalować?
  • Kiedy skupić się na szybkim wdrażaniu?