Overengineering, czyli nadmierna inżynieria, to budowanie rozwiązania bardziej złożonego, niż wymaga problem. Kojarzy się z dużymi systemami, ale przy audytach stron firmowych i sklepów spotykam go równie często: kilkadziesiąt wtyczek do prostej wizytówki, framework aplikacyjny do pięciu podstron, trzy rodziny czcionek i kontener tagów, którego nikt nie rozumie. Taka strona zwykle dobrze wygląda w dniu oddania, ale jest wolna, droga w utrzymaniu i trudna do zmiany. W tym wpisie pokazuję, po czym rozpoznaję przesadę, gdzie najczęściej ją znajduję i według jakich pytań decyduję, czy kolejna warstwa jest potrzebna.
Jak rozpoznaję overengineering
Przesadnie złożony projekt rzadko wygląda źle na pierwszy rzut oka. Rozpoznaję go po objawach, które wychodzą dopiero w trakcie utrzymania:
- prosta zmiana, np. nowa sekcja na stronie głównej, zajmuje dni zamiast godzin,
- nikt w zespole nie potrafi wyjaśnić, po co jest dana wtyczka, biblioteka albo usługa,
- aktualizacje są odkładane, bo każda grozi awarią w innym miejscu,
- strona zbudowana „nowoczesnym stosem” ładuje się wolniej niż prosta strona konkurencji,
- koszt hostingu, licencji i utrzymania rośnie szybciej niż korzyści z kolejnych funkcji.
Źródło tych objawów najczęściej znajduję w kilkunastu powtarzalnych miejscach. Tabela pokazuje je w skrócie, a w kolejnych sekcjach opisuję każde z nich dokładniej.
| Obszar | Przesada, którą widzę najczęściej | Co robię zamiast |
|---|---|---|
| JavaScript | każdy element interfejsu oparty na skryptach | HTML i CSS tam, gdzie wystarczą, skrypty tylko do realnej logiki |
| Frameworki | pełna aplikacja JavaScript do kilku podstron z treścią | gotowy HTML z generatora stron albo zoptymalizowany CMS |
| CSS | kilka bibliotek komponentów w jednym projekcie | zmienne CSS, Grid i Flexbox w małych projektach |
| Czcionki | kilka rodzin we wszystkich grubościach z zewnętrznych serwerów | jedna rodzina, kilka grubości, pliki na własnym serwerze |
| Animacje | animowany każdy element i przejścia blokujące treść | krótkie efekty, które pomagają zrozumieć interfejs |
| CMS | page builder i kilkanaście wtyczek do strony wizytówki | CMS tylko tam, gdzie treść edytują osoby nietechniczne |
| Wtyczki | zdublowane funkcje i skrypty ładowane na każdej podstronie | kilka aktualizowanych wtyczek, drobiazgi w motywie potomnym |
| Własny kod | własny CMS albo builder do prostej strony | gotowe narzędzia i własny kod tam, gdzie daje przewagę |
| Komponenty | osobny komponent i plik stylów dla każdego akapitu | komponenty dla elementów, które się powtarzają |
| CDN | zasoby z kilku publicznych CDN na lokalnej stronie | CDN przy ruchu z wielu krajów i dużych plikach |
| Treści | setki generowanych podstron różniących się nazwą miasta | osobne podstrony tylko z unikalną treścią |
| Analityka | śledzenie każdego kliknięcia bez planu analizy | zdarzenia odpowiadające na konkretne pytania biznesowe |
Front-end, czyli więcej kodu, niż potrzebuje przeglądarka
JavaScript tam, gdzie wystarczy HTML i CSS
Rozwijane sekcje, zakładki czy proste menu da się dziś zbudować w HTML i CSS, np. elementem <details>, który działa bez
jednej linii skryptu i jest dostępny dla czytników ekranu. Każdy dodatkowy skrypt to kod do pobrania, wykonania i utrzymania, a do tego
potencjalna przyczyna wolnej reakcji na kliknięcie. Zanim dodam JavaScript, sprawdzam, czy przeglądarka nie robi tego sama.
Framework aplikacyjny do strony z treścią
Frameworki do budowy aplikacji, takie jak Next.js czy Nuxt, sprawdzają się przy panelach klienta, konfiguratorach i serwisach z dużą ilością interakcji. Gdy jednak cała strona to kilka podstron z treścią marketingową, a front-end wysyła do przeglądarki pełną aplikację JavaScript, użytkownik płaci za złożoność, której nie potrzebuje. Przy stronach z treścią wybieram rozwiązanie, które generuje gotowy HTML i dodaje JavaScript tylko tam, gdzie jest potrzebny, np. Astro albo dobrze zoptymalizowany WordPress. Wybór modelu renderowania zależy od tego, jak często zmienia się treść, co pokazuje porównanie metod renderowania CSR, SSR, SSG i ISR. Przy większych projektach rozważam też, kiedy warto przejść na headless CMS.
Frameworki CSS a własne style
Tailwind czy Bootstrap przyspieszają pracę, ale przy małej stronie potrafią dodać więcej kodu i zależności niż sama treść. Przesadą jest też łączenie kilku bibliotek komponentów w jednym projekcie, bo ich style zaczynają ze sobą konkurować. Przy niewielkich projektach wystarczają mi zmienne CSS, Grid i Flexbox. Framework wybieram, gdy nad projektem pracuje kilka osób i wspólny system klas oszczędza im czas.
Nadmiar czcionek
Każda czcionka i każda jej grubość to osobny plik do pobrania. Trzy rodziny czcionek po pięć grubości to kilkanaście plików, które opóźniają wyświetlenie tekstu, a przy podmianie czcionki zastępczej na docelową przesuwają układ strony. W większości projektów wystarcza mi jedna rodzina w dwóch lub trzech grubościach, a jeśli czcionka obsługuje warianty w jednym pliku, wybieram tę wersję. Pliki hostuję lokalnie, a resztę załatwia optymalizacja ładowania czcionek.
Animacje i efekty
Animacje nie są ozdobnikiem do usunięcia. Dobrze zaprojektowana animacja pokazuje, skąd pojawił się element, potwierdza kliknięcie i buduje charakter marki. Przesada zaczyna się, gdy efekty opóźniają dostęp do treści, np. pełnoekranowe przejścia przed wyświetleniem strony, gdy każdy element na stronie wjeżdża przy przewijaniu albo gdy animacje są liczone w JavaScripcie i na słabszym telefonie przycinają się przy przewijaniu. Animuję wtedy tylko właściwości, które przeglądarka obsługuje bez przeliczania układu, a pozostałe efekty usuwam. Od tego zależy płynne przewijanie i animacje w JavaScript.
CMS, wtyczki i własne rozwiązania
Za ciężki CMS do prostej strony
Landing page z trzema sekcjami i formularzem nie potrzebuje bazy danych, panelu administracyjnego i kilkunastu wtyczek. Jeśli treść zmienia się kilka razy w roku, a edytuje ją programista, statyczna strona jest szybsza, tańsza i bezpieczniejsza. CMS ma sens tam, gdzie treść regularnie edytują osoby nietechniczne. Dlatego zanim wybiorę CMS do projektu, pytam, kto i jak często będzie zmieniał treść.
Zbyt duża liczba wtyczek
Liczba wtyczek sama w sobie nie jest problemem. Problemem są wtyczki, które ładują swoje skrypty i style na każdej podstronie, dublują funkcje innych wtyczek albo nie są aktualizowane. Przy każdej stronie na WordPressie zadaję o każdą wtyczkę trzy pytania: czy jest używana, czy jej funkcji nie zapewnia już inna wtyczka lub motyw i czy da się ją zastąpić kilkoma liniami kodu. Wtyczka do zmiany koloru przycisku albo wstawienia jednego skryptu to typowy przykład czegoś, co lepiej przenieść do motywu potomnego. Do pozostałych stosuję te same kryteria co przy wyborze przydatnych wtyczek do WordPressa.
Własne rozwiązania a gotowe narzędzia
Własny kod daje pełną kontrolę, ale każda linia to koszt utrzymania. Gdy ktoś pisze własny system zarządzania treścią albo builder do strony z kilkoma podstronami i formularzem, pytam, jaki problem rozwiązuje, którego nie rozwiązują gotowe narzędzia. Jeśli odpowiedzią są ambicje techniczne, a nie potrzeby projektu, to klasyczny overengineering. Z drugiej strony przesadą jest też ciężki page builder do strony, którą da się zbudować z kilku prostych bloków. Granicę wyznacza dla mnie koszt utrzymania przez kolejne lata, a nie czas pierwszego wdrożenia.
Kod i infrastruktura
Przesadna modularność kodu
Podział na komponenty ułatwia rozwój i testowanie, ale komponent na każdy akapit, z osobnym plikiem stylów i testów, sprawia, że prosta zmiana wymaga otwarcia kilkunastu plików. Wydzielam komponent, gdy ten sam fragment powtarza się w kilku miejscach albo ma własną logikę. W pozostałych przypadkach prosty kod w jednym miejscu jest czytelniejszy. To jedna z zasad, dzięki którym kod pozostaje czytelny i zrozumiały.
CDN dla wszystkiego
CDN to dla mnie standard przy ruchu z wielu krajów, dużej liczbie zdjęć i wideo oraz przy potrzebie ochrony przed atakami. Przy lokalnej stronie firmowej z dobrze skonfigurowaną pamięcią podręczną na serwerze zysk bywa niewielki, a każda dodatkowa warstwa to kolejne miejsce, w którym trzeba szukać błędów przy problemach z cache czy przekierowaniami. Przesadą nazywam też ładowanie skryptów i czcionek z kilku różnych publicznych CDN, z których każdy wymaga osobnego połączenia. Gdy CDN faktycznie jest potrzebny, kluczowa jest jego konfiguracja, a nie samo włączenie.
SEO i analityka
Masowo generowane strony
AI przyspiesza pisanie kodu i treści, ale masowe generowanie podstron, np. setki stron „usługa plus miasto” różniących się nazwą miejscowości, to overengineering po stronie SEO. Taka struktura jest trudna w utrzymaniu, nie daje użytkownikowi niczego nowego i może zostać uznana przez Google za skalowane treści niskiej jakości. Osobną podstronę tworzę tylko wtedy, gdy mam dla niej unikalną treść, np. realizacje, opinie czy ofertę z danego miejsca.
Śledzenie każdego zdarzenia w GA4
Śledzenie przewinięcia co 10%, każdego kliknięcia i każdego pola formularza daje dużo danych, ale rzadko daje wnioski. Każde zdarzenie to też kolejny tag w kontenerze i kolejny kod wykonywany w przeglądarce. Zaczynam od listy pytań biznesowych, na które dane mają odpowiedzieć, i śledzę tylko zdarzenia potrzebne do odpowiedzi. Od strony kodu porządkuje to dobrze zaprojektowana warstwa danych w Google Tag Managerze.
Pytania, które zadaję przed dodaniem kolejnej warstwy
- Jaki konkretny problem rozwiązuje i czy ten problem już mamy, czy tylko możemy mieć w przyszłości?
- Czy przeglądarka, serwer albo obecne narzędzia nie robią już tego samego?
- Kto będzie to utrzymywał za dwa lata i czy zrozumie, po co to jest?
- Jak wpłynie na szybkość strony i czy zmierzę ten wpływ przed i po wdrożeniu?
- Ile kosztuje usunięcie tej warstwy, jeśli okaże się zbędna?
Jeśli na pierwsze pytanie nie ma konkretnej odpowiedzi, nie dodaję warstwy. Każda z nich zostaje w projekcie na lata, a jej koszt rośnie razem z długiem technologicznym. Dlatego przy każdej decyzji pytam nie o to, czy rozwiązanie jest nowoczesne, tylko czy jest potrzebne.