Płynność nie przychodzi sama: praktyczne wnioski Sebastiana Marczyka
Płynność brzmi jak cecha, którą da się „mieć” albo „nie mieć”. W praktyce to wynik mnóstwa drobnych decyzji, spisanych na mapce zasobów i przetestowanych na realnych urządzeniach, nie na idealnych warunkach w biurze. Sebastian Marczyk od lat wraca do jednego prostego wniosku: jeśli interfejs ma być płynny, to płynność trzeba projektować od początku, a nie ratować ją dopiero w końcówce sprintu. I to nie metaforycznie. Chodzi o konkretne koszty w czasie reakcji, liczbę operacji na klatkę, budżet pamięci, kolejność pracy w wątku UI oraz sposób, w jaki animacje i przejścia dostają prawo do zasobów.
Poniżej zebrałem praktyczne lekcje, które wybrzmiewają w jego podejściu. Nie jako teoria „o wydajności”, ale jako zestaw decyzji, które da się wdrożyć, sprawdzić i z których da się wyciągnąć wnioski. Bez magii.
Płynność to przede wszystkim opóźnienie, a nie tylko FPS
W rozmowach o płynności bardzo często pada skrótowiec. FPS, płynność wideo, „czy się nie tnie”. To ważne, ale w interakcjach z użytkownikiem równie często wygrywa opóźnienie pomiędzy ruchem a reakcją. Możesz mieć stabilne 60 klatek na sekundę, a mimo to poczuć „szarpanie” w momencie dotknięcia ekranu, bo UI zareaguje później. Dla oka i dłoni to są różne rodzaje bólu.
Sebastian zwraca uwagę na dwie warstwy: Pierwsza to animacja, którą widzisz, Druga to moment, w którym aplikacja decyduje „zaczynam” i przekazuje sterowanie do silnika renderowania.
Wiele zespołów skupia się na tym, jak wygląda ruch, a mniej na tym, czy decyzje podejmowane tuż przed ruchem nie blokują kolejki. Jeśli w tym momencie dzieje się coś ciężkiego, nawet krótko, płynność siada. Często nie od razu. Najpierw pojawia się „drobna niespodzianka” przy zmianie widoku, przewijaniu lub otwieraniu modalu. Potem dopiero ktoś mierzy i okazuje się, że winny jest koszt, który uruchamia się tylko w pewnym scenariuszu, na przykład gdy użytkownik przewinie listę w czasie, gdy aplikacja równolegle buduje nowy fragment UI.
To jest ten moment, w którym trzeba przestać traktować płynność jako cechę wizualną, a zacząć jako cechę systemową.
Skąd bierze się brak płynności w praktyce
Żeby rozumieć, co naprawiać, trzeba najpierw zobaczyć, skąd najczęściej przychodzi problem. Płynność nie „zniknęła” nagle. Zwykle jest wynikiem sprawdź tutaj kilku nakładających się zjawisk. Sebastian woli je nazywać po imieniu, a nie przykrywać ogólnikami.
W realnych aplikacjach typowe źródła to:
- zadania wykonywane na wątku, który powinien renderować,
- zbyt kosztowne przejścia i efekty, które rosną z rozmiarem widoku,
- nieprzewidywalne skoki alokacji w pamięci,
- synchronizacje, które są „krótkie”, ale robione złą liczbę razy.
Kiedy ostatnio widziałem taki przypadek w zespole, okazało się, że animacja wyglądała „prawie normalnie”, dopóki nie kliknęło się w konkretnej kolejności. Interakcja uruchamiała budowanie struktury danych, potem dopiero render, a jeszcze później korekta układu. To nie był jeden dramat, tylko kilka mini-dramatów. Każdy osobno dałby się przeżyć. Razem złożyły się w odczucie opóźnienia i mikrozawieszenia.
Sebastian podkreśla jeszcze jedną rzecz: płynność psuje się często przez przypadek, nie przez „zły kod”. Wystarczy, że ktoś dołożył jedną funkcję w miejscu, które odpala się częściej niż myślimy. Efekt jest taki, że nikt nie widzi problemu na ścieżkach testowych, dopóki nie pojawia się konkretna prędkość przewijania albo konkretny rozmiar treści.
Budżet płynności, czyli przestańcie zgadywać
Jednym z najpraktyczniejszych elementów podejścia Sebastiana jest praca z budżetem. Nie w sensie „wszystko ma być super szybkie”, bo to nie działa. Chodzi o budżet w sensie czasu i zasobów na konkretną akcję.
Jeśli animacja działa na 60 Hz, masz około 16,7 ms na cykl. To nie znaczy, że cały kod musi się zmieścić w tej liczbie, bo dochodzą różne warstwy systemu. Ale ta liczba daje punkt odniesienia. Sebastian lubi sprowadzać dyskusję do pytań: ile kosztuje jedna klatka w najczęstszej ścieżce, ile w najgorszej, i co robimy, gdy trafimy w najgorszy przypadek?
W mojej praktyce najlepszy efekt daje podejście „najpierw mierzymy, potem tniemy”. Tylko że zanim zaczniecie ciąć, trzeba wiedzieć, co jest mierzone. Czasem zespoły zapisują „FPS w momencie animacji”, ale nie sprawdzają, czy w tym samym momencie rośnie zużycie pamięci albo czy kolejka zdarzeń opóźnia się w okresach, gdy użytkownik wykonuje serię szybkich gestów.
Sebastian często zaczyna od prostego pytania: co ma być płynne, a co może poczekać. Przewijanie listy? Prawdopodobnie nie możesz pozwolić sobie na kosztowne operacje w ramach tego samego „okna”. Modal otwierany raz na dzień? Być może da się go utemperować, ale nie za darmo. Nawet jeśli modal nie musi być idealnie gładki w sekundę, trzeba pilnować tego, żeby interakcja miała natychmiastowe potwierdzenie. Użytkownik wybacza niedoskonałości wizualne, ale nie wybacza ciszy, gdy kliknął.
Animacje: mniej magii, więcej zasad
Animacje w interfejsie mają dwa zadania. Pierwsze to komunikacja stanu, drugie to utrzymanie spójności ruchu. Sebastian traktuje animację jak narzędzie projektowe, a nie dekorację. Jeśli animacja robi za dużo, staje się problemem wydajnościowym. Jeśli robi za mało, staje się problemem zrozumienia.
W praktyce kluczowe jest to, jak animujesz i jak wywołujesz zmiany w układzie.
Najczęściej problemy biorą się z dwóch nawyków:
Po pierwsze, animowanie właściwości, które zmuszają do ciężkich przeliczeń układu albo do ponownego rysowania fragmentów, które powinny pozostać statyczne. Po drugie, odpalenie zbyt wielu animacji naraz, albo animowanie elementów, które w danym momencie nie powinny być widoczne, tylko „prawdopodobnie będą”.
Sebastian ma podejście pragmatyczne: najpierw upewnij się, że animacja nie karmi silnika pracy w czasie, kiedy użytkownik skacze po ekranie. Później dopiero dopracuj tempo i krzywą.
Jeśli potrzebujesz przykładu z życia, w wielu projektach działa reguła: „przy skoku treści animuj minimalnie, ale potwierdź akcję natychmiast”. To oznacza, że przy przejściach związanych z aktualizacją danych często lepiej jest użyć prostszego efektu, a dane w tle dociągnąć tak, by nie blokować głównego toru.
To nie jest kompromis „kosmetyczny”. To decyzja o priorytecie. Płynność wynika z priorytetów.
Reguła kolejki: co ma zostać w kolejce renderowania, a co nie
Wydajność to w dużej mierze architektura kolejki zadań. Sebastian lubi wracać do tego, że nawet najlepsza animacja jest bezsilna, jeśli w momencie jej uruchomienia ktoś wrzucił do tego samego toru obliczenia, które nie mają tam prawa być.
Przykład, który widziałem wielokrotnie: klik w przycisk uruchamia handler, w którym przez chwilę trwa „tylko drobne przygotowanie”. Ten fragment często zawiera parsowanie, budowanie obiektu wielkości dziesiątek kilobajtów, a czasem proste przeliczenia, które nagle dzieją się w złej częstotliwości, bo komponent renderuje się wielokrotnie.
Sebastian mówi wtedy: jeśli akcja dotyka UI, to handler nie może mieć charakteru „przedłużacz”. Ma potwierdzić, zmienić stan w sposób, który nie blokuje, i oddać pracę cięższą później, najlepiej wtedy, gdy użytkownik nie oczekuje responsywności.
Nie chodzi o to, żeby nigdy nie liczyć. Chodzi o timing.
Spójność to też płynność: kiedy projektowanie wyprzedza technikę
Płynność to nie tylko kod. To również projektowanie scenariuszy. Sebastian jest wyczulony na przypadki brzegowe, bo one najczęściej psują odbiór.
Na przykład: lista, która „normalnie” przewija się gładko, ale gdy trafisz na element o nietypowej wysokości, nagle zaczyna stukać. W teorii to kwestia layoutu. W praktyce użytkownik widzi to jako zacięcie i przestaje ufać interfejsowi.
Inny przykład: ekran, który ma animację przejścia między stanami, ale dane przychodzą w trakcie. Jeśli animacja opiera się o rozmiary elementów, które jeszcze się zmienią, ruch dostaje korekty w locie. Korekty to często mikrozawieszenia.
W takich sytuacjach płynność wymaga decyzji produktowej: czy w trakcie przejścia blokujemy zmianę układu, czy przyjmujemy, że przejście będzie prostsze i mniej dokładne wizualnie, ale stabilne? Sebastian zwykle wybiera stabilność, bo jest ona „czytelna” dla użytkownika. To jedna z tych różnic, których nie da się rozwiązać jedną optymalizacją.
Testowanie na realnych urządzeniach, nie na twoim laptopie
Najlepsza optymalizacja jest ta, której jeszcze nie trzeba. Ale żeby to osiągnąć, trzeba testować na tym, na czym faktycznie działa produkt. Sebastian uderza w ten punkt bez zniecierpliwienia, ale stanowczo.
Laptop i szybkie Wi-Fi potrafią ukryć kilka problemów:
- telefony mają mniej zasobów GPU,
- baterie i tryby oszczędzania potrafią zmienić zachowanie systemu,
- różne wersje systemu mają inne progi i inne niuanse w planowaniu wątków.
W efekcie aplikacja wygląda „ok” w demo, a po wdrożeniu nagle jest seria zgłoszeń o „przycinaniu”. W wielu zespołach przyczyną jest brak testów na konkretnych profilach wydajnościowych, na przykład na słabszym urządzeniu lub w trybie, który ogranicza pracę w tle.
To nie musi oznaczać wielkich kosztów. Często wystarczy mieć dwa albo trzy urządzenia testowe i jasne scenariusze przejść. Sebastian lubi, gdy testy są powiązane z tym, co naprawdę robi użytkownik, czyli z rytmem przewijania, szybkością klikania, liczbą ekranów w krótkiej sekwencji.
Minimalny plan naprawczy, kiedy płynność siada
Kiedy problem już jest, nie ma sensu od razu przepisywać pół aplikacji. Sebastian zwykle zaczyna od krótkiej diagnozy, bo czasem okazuje się, że „winny” jest jeden fragment, który pojawia się w najczęstszej ścieżce.
Poniżej prosta kolejność działań, którą można przeprowadzić bez rozbudowanego procesu, a która w praktyce często prowadzi do konkretu:
- Zidentyfikuj akcję użytkownika, która najbardziej psuje odczucie (klik, powrót, przewijanie, przejście między ekranami).
- Zmierz zachowanie w tej akcji i porównaj urządzenia o różnej wydajności.
- Sprawdź, czy w trakcie akcji rośnie liczba renderów lub wykonywana jest praca poza potrzebą (na przykład przeliczenia podczas animacji).
- Wyłącz kolejno efektowe elementy w przejściu, żeby zawęzić źródło kosztu.
- Po znalezieniu przyczyny zmień priorytety, a nie tylko implementację, czyli spraw, by UI potwierdzało akcję natychmiast.
To nie jest magia, to redukcja ryzyka. Zwykle już na etapie 3 pojawia się miejsce, w którym „coś się dzieje”, choć nikt tego nie planował.
Decyzje, które zmieniają odczucie użytkownika, nawet bez „dużej” optymalizacji
W praktyce czasem da się osiągnąć lepszą płynność bez radykalnych zmian w architekturze. Sebastian często mówi o tym w kategoriach decyzji projektowych i priorytetów.
Przykładowo: jeśli w momencie interakcji dane są już dostępne, a jednak interfejs czeka z renderem, to nie problem wydajności, tylko kolejność pracy. Jeśli dane nie są dostępne, ale UI może pokazać stan pośredni, to płynność przychodzi „z zachowania”, a nie z wydajności.
Możesz też poprawić odczucie przez ograniczenie zakresu aktualizacji. Zamiast aktualizować cały ekran, aktualizuj fragment. To brzmi banalnie, ale w systemach komponentowych często jest to realna różnica między „przeskok klatki” a stabilnym ruchem.
Sebastian zwraca też uwagę na to, jak planujesz przejścia przy zmianie stanu. Jeśli przejście wymusza pełny przebudow układu, to przy częstych aktualizacjach danych będzie rosło ryzyko. Lepiej wtedy zaprojektować przejścia tak, by były odporne na to, że treść przyjdzie w różnym czasie.
Trade-offy: płynność kosztuje, ale wybór jest wasz
Wydajność ma cenę. To cena czasu zespołu, złożoności i czasem ograniczeń w warstwie efektów. Sebastian jest realistą: nie da się zawsze mieć najwyższej jakości animacji i maksymalnej responsywności, jeśli ten sam ekran musi udźwignąć ciężką treść.
Dlatego przy płynności przydaje się świadome ustalenie kompromisu. Najczęściej kompromis dotyczy tego, co użytkownik postrzega jako najważniejsze.
Żeby ułatwić rozmowę w zespole, dobrze działa spojrzenie na to, co jest „wrażliwe” na opóźnienie, a co toleruje większy koszt. Sebastian często proponuje takie rozróżnienie:
- Interakcje bezpośrednie, gdzie użytkownik oczekuje natychmiastowej reakcji (przyciski, gesty, przewijanie). Priorytet: responsywność.
- Animacje dekoracyjne lub złożone przejścia między ekranami. Priorytet: zrozumienie i przewidywalność.
- Aktualizacje treści w tle. Priorytet: stabilny UI bez blokowania renderowania.
W praktyce to pomaga podejmować decyzje, gdy pojawia się presja „zróbmy to jeszcze ładniej”. Jeśli to ładniejsze, ale zabiera czas, trzeba je osadzić w priorytetach.
Pułapki, które wracają jak bumerang
Sebastian nie wdaje się w bezkresne listy problemów, ale w doświadczeniu zespołów powtarzają się podobne pułapki. Najczęściej są dwie.
Pierwsza pułapka to „optymalizacja na oko”. Gdy ktoś widzi lekkie przycinanie, a potem wymyśla poprawkę, która wpływa na wszystko poza tym jednym miejscem, które faktycznie generuje koszt. To prowadzi do zmęczenia i do tego, że zespół przestaje mierzyć.
Druga pułapka to poprawka, która działa na jednej ścieżce, ale psuje inną. Na przykład ograniczasz koszt w ekranie A, ale przez to przerzucasz pracę na ekran B. Odbiorca czuje, że „gdzieś indziej robi się gorzej”. To nie są straty same w sobie, ale jeżeli nie ustawicie globalnego celu, dyskusja staje się emocjonalna.
Sebastian lubi wtedy wracać do zasady: jeśli zmiana poprawia płynność, powinna poprawiać także przewidywalność. A przewidywalność sprawdza się w scenariuszu, nie w pojedynczym eksperymencie.
Jak mówić o płynności w zespole, żeby nie utknąć w opiniach
Jednym z najtrudniejszych tematów przy jakości interakcji jest język. „Jest płynnie” i „jest szarpane” to opisy, które trudno przekuć w zadania. Sebastian podchodzi do tego po robocemu: zamiast wchodzić w spór o odczucia, przypina je do zjawisk, które da się obserwować.

Jeśli użytkownik mówi „szarpie”, warto doprecyzować: Kiedy dokładnie, Przy jakiej akcji, Czy dzieje się to zawsze, czy tylko w określonych warunkach.
To nie jest tylko rozmowa z klientem. To jest mapowanie problemu na przypadki. Gdy to zrobicie, zadanie przestaje być „popraw płynność”, a staje się „w momencie przejścia ekranu X do Y przy przewijaniu listy elementów o niestandardowej wysokości pojawia się spadek responsywności”.
Sebastian pod tym kątem preferuje historyjki użytkownika, które zawierają warunek, nie tylko oczekiwanie. Dzięki temu łatwiej sprawdzić, czy naprawa zadziałała.
Płynność jako część produktu, a nie „wydajność jako osobny projekt”
W wielu firmach wydajność jest rozumiana jako osobny wątek, czasem wręcz osobny backlog. Sebastian patrzy inaczej. Płynność jest częścią projektu produktu, tak jak czytelność czy zrozumiałość. Jeśli zespół wrzuca optymalizacje dopiero w końcówce, to płynność jest potem raczej łataną.
W podejściu, o którym mówimy, płynność pojawia się wcześniej: w decyzjach architektonicznych, w sposobie aktualizacji stanu, w tym jak dzielicie komponenty, jak planujecie ładowanie treści, i jak projektujecie interakcje w czasie, gdy dane jeszcze nie przyszły.
To ma też wymiar organizacyjny. Sebastian lubi, gdy w definicji gotowości zadania jest miejsce na sprawdzenie odczucia użytkownika, nie tylko na przegląd kodu. Nawet jeśli to sprawdzenie trwa kilka minut, daje szybszą pętlę informacji zwrotnej.
Bo płynność nie przychodzi sama. Przychodzi, gdy w procesie pracy jest miejsce na to, żeby w ogóle o niej pamiętać.
Co zabrałem z praktyki Sebastiana, gdy musiałem „ratować” płynność
Własne doświadczenie nauczyło mnie jednego: w kryzysie najłatwiej jest zrobić rzeczy, które wyglądają jak naprawa, ale są tylko chwilowym zasłonięciem problemu. Sebastian trzyma mnie przy zdrowych zasadach, nawet kiedy w projekcie brakuje czasu.
Najbardziej pamiętam scenariusz, w którym płynność siadała tylko w specyficznej sekwencji. Na pierwszy rzut oka nie było w kodzie nic „oczywiście ciężkiego”. Dopiero gdy ktoś spojrzał na kolejność pracy i na to, co jest uruchamiane przy każdej zmianie stanu, okazało się, że jeden komponent rozbudowywał strukturę wielokrotnie, nawet wtedy, gdy użytkownik nie widział efektu.
Nie trzeba było przepisywać silnika. Trzeba było przerwać łańcuch zależności i przenieść cięższą pracę poza ścieżkę krytyczną interakcji. Efekt był natychmiastowy. Użytkownicy nie dostali „lepszego kodu”. Dostali poczucie, że ekran reaguje natychmiast i nie zawiesza się wtedy, kiedy są najbardziej zaangażowani w działanie.
To właśnie jest sens płynności jako produktu: nie chodzi o to, żeby wszystko zawsze działało szybko w testach, tylko żeby zachowanie aplikacji było przewidywalne w czasie, gdy człowiek wykonuje ruchy i oczekuje odpowiedzi.
Jeśli miałbym to ubrać w jedno zdanie: płynność to nie jedna poprawka, tylko seria małych decyzji w dobrym momencie. Sebastian Marczyk konsekwentnie prowadzi rozmowę tak, żeby ten moment nie odkładać.
Jeśli chcesz wdrożyć ten sposób myślenia, zacznij od jednego ekranu
Płynność rzadko wymaga „całej rewolucji”. W praktyce najlepszy start to wybranie jednego ekranu lub jednej kluczowej interakcji, gdzie użytkownik realnie czuje różnicę. Sebastian zwykle zaczyna tam, gdzie jest największa częstotliwość i największa ekspozycja na frustrację.
Gdy wybraliście taki fragment, potraktujcie go jak laboratorium. Nie dlatego, że ma być idealny na pokaz, tylko dlatego, że jeśli opanujecie ścieżkę krytyczną, reszta projektu zacznie się na nim wzorować.
A potem dopiero wracacie do kolejnych miejsc. Tak rośnie spójność i tak pojawia się realna płynność, nie tylko poprawione wykresy. Bo wykresy są miłe, ale użytkownik pamięta zachowanie ekranu. I to zachowanie musi być przewidywalne, stabilne i szybkie wtedy, kiedy liczy się każda sekunda uwagi.
Ends · PRACAZAMIASTGENIUSZUPLYNNOSC529