Frankenstein w programowaniu — co to jest, przyczyny i zapobieganie

Autor: IT Sectr Opublikowano: 2026-07-26 Czas czytania: 10 min

Frankenstein w programowaniu to kod złożony z niekompatybilnych części różnych technologii, stylów i architektur. Według badania ThoughtWorks Technology Radar (2024), 28% dużych projektów zawiera objawy syndromu Frankensteina — architektonicznej eklektyki, powstającej przy braku jednolitej wizji technicznej. Analogicznie do powieści Mary Shelley, taki kod działa, ale jego utrzymanie staje się koszmarem.

Najważniejsze

  • Frankenstein — antywzorzec, w którym system składany jest z różnorodnych, słabo kompatybilnych komponentów
  • Główne przyczyny: brak architekta, łączenie projektów, „kreatywność bez granic”
  • Problem — każdy komponent wymaga znajomości swojej technologii, a interakcje są nieprzewidywalne
  • Refaktoryzacja Frankensteina wymaga ujednolicenia stosu technologicznego i wyznaczenia wyraźnych granic
  • Architecture Decision Records i RFC — najlepsze narzędzia profilaktyki

Czym jest Frankenstein w programowaniu

Frankenstein (Frankenstein code, Frankenstein pattern) — to antywzorzec, w którym system oprogramowania składany jest z części nieprzeznaczonych do współpracy. Jak potwór Frankensteina, taki kod może działać, ale jest brzydki, nieprzewidywalny i niebezpieczny przy najmniejszych zmianach.

Termin pochodzi z literatury: w powieści Mary Shelley „Frankenstein, czyli współczesny Prometeusz” (1818) naukowiec stworzył żywą istotę z fragmentów ciał różnych zmarłych osób. W programowaniu analogia jest trafna — programiści biorą fragmenty różnych frameworków, bibliotek, języków i sklejają je „na żywca”, uzyskując działający, ale potworny efekt.

Różnica między Frankensteinem a kodem spaghetti polega na skali i naturze problemu. Kod spaghetti — to zagmatwana struktura w ramach jednego stosu technologicznego. Frankenstein — to eklektyka na poziomie architektury: różne technologie, niekompatybilne paradygmaty, konfliktowe podejścia w ramach jednego systemu.

Frankenstein a mikrousługi

Architektura mikrousług dopuszcza użycie różnych technologii dla różnych usług, ale pod warunkiem wyraźnych granic i standaryzowanych protokołów komunikacji. Frankenstein — to chaotyczne mieszanie bez granic: REST i GraphQL w jednym kontrolerze, dwa ORM-y w jednym module, SQL i NoSQL dla jednej encji.

Dlaczego powstaje syndrom Frankensteina

Brak lidera technicznego lub architekta — to główna przyczyna. Gdy w projekcie nie ma osoby odpowiedzialnej za spójność architektury, każdy programista wybiera narzędzia „pod siebie”. Jeden lubi Spring, drugi — Guice, trzeci — własnoręcznie napisany DI. Efekt — architektoniczny winegret.

Łączenie projektów — druga częsta przyczyna. Dwa zespoły rozwijały swoje moduły niezależnie, używając różnych stosów technologicznych. Gdy moduły trzeba połączyć w jedną aplikację, są one po prostu „sklejane” adapterami i przekładkami. Powstaje Frankenstein.

Przejęcia korporacyjne — trzeci scenariusz. Firma A kupiła firmę B i chce zintegrować jej produkt ze swoim. Zamiast przepisywania — sklejanie przez API, wspólne bazy danych i protezy. Po roku system zmienia się w potwora, którego nikt nie rozumie.

PrzyczynaOpisTypowy rezultat
Brak architektaKażdy programista wybiera własny stos3 różne klienty HTTP w jednym module
Łączenie projektówDwa produkty sklejane w jedenDwa ORM-y, dwa sposoby logowania
M&APrzejęcie firmy z jej produktemHybryda różnych architektur i stylów
EksperymentyWdrażanie nowych technologii bez strategiiJava 8 + Java 21 w jednym pliku
Decyzje polityczneNarzucanie technologii z góry bez uwzględnienia kontekstuEnterprise-framework dla prostego skryptu

Czynnik „kreatywności”

Doświadczeni programiści, którzy chcą wypróbować nowe technologie w produkcji, często stają się źródłem Frankensteina. Zamiast ograniczyć eksperymenty do izolowanego modułu, wdrażają eksperymentalny kod w krytycznej części systemu.

Przykłady Frankensteina w rzeczywistych projektach

Klasyczny przykład — użycie kilku ORM-ów w jednej aplikacji. Część modułów używa Hibernate, część — MyBatis, a część — bezpośrednich zapytań JDBC. Transakcje stają się niezarządzalne, pamięć podręczna — niespójna, a nowy programista nie wie, które podejście wybrać dla nowej funkcji.

Drugi przykład — mieszanie stylów architektonicznych. W kontrolerze REST API pojawiają się wywołania usług SOAP, bezpośrednie zapytania SQL, dostęp do systemu plików i generacja HTML. Takiej aplikacji nie da się testować, rozszerzać ani dokumentować.

Trzeci przykład — stos technologiczny, gdzie Python jest używany do backendu, Node.js — do mikrousługi, C# — do klienta desktopowego, a Java — do aplikacji Android, przy czym cała logika biznesowa jest rozrzucona między nimi bez wyraźnego podziału odpowiedzialności.

javascript
// frankenstein — mieszane style i technologie
// połączenie callbacks, Promises i async/await

// callbacks
db.query("SELECT * FROM users", function(err, rows) {
  if (err) handleError(err);
  // Promise wewnątrz callback
  fetch("/api/data").then(function(data) {
    // async/await wewnątrz then
    (async () => {
      const result = await processData(data);
      sendResponse(result);
    })();
  });
});

// czysty kod — ujednolicony styl async/await
async function getUserData(userId) {
  const user = await db.query("SELECT * FROM users WHERE id = ?", [userId]);
  const data = await fetch("/api/data/" + userId);
  return await processData(user, data);
}

Frankenstein na poziomie danych

Jedna baza danych jest używana jednocześnie jako relacyjna SQL (z normalizacją) i jako dokumentowa NoSQL (z kolumnami JSON). Część zapytań idzie przez ORM, część — przez procedury składowane, część — przez bezpośredni SQL z kodu. Schemat bazy nie jest udokumentowany, migracje są konfliktowe.

Konsekwencje kodu Frankensteina

Trudność onboardingu — pierwsza konsekwencja. Nowy programista musi znać 5 języków, 3 frameworki, 2 style architektoniczne, aby zrozumieć, jak działa system. Onboarding wydłuża się z tygodni do miesięcy. Według LinkedIn (2023), projekty z eklektyką technologiczną tracą nowych pracowników 2 razy częściej.

Nieprzewidywalność zachowania — druga konsekwencja. Zmiana w mikrousłudze w Pythonie może nieoczekiwanie złamać moduł w Javie, ponieważ używają one wspólnej bazy danych bez wyraźnych kontraktów. Debugowanie takich problemów wymaga jednoczesnej znajomości wszystkich technologii w stosie.

Bezpieczeństwo — trzecia konsekwencja. Każda technologia w stosie wymaga własnej konfiguracji bezpieczeństwa, własnych łatek, własnego monitoringu. Utrzymanie bezpieczeństwa na akceptowalnym poziomie dla 5–6 różnorodnych technologii jest praktycznie niemożliwe. Jedna z nich nieuchronnie okaże się podatna na ataki.

Dług techniczny Frankensteina

SonarQube może zmierzyć dług techniczny, ale nie może zmierzyć „długu architektonicznego” — niekompatybilności komponentów. Ten dług objawia się nie w ostrzeżeniach lintera, ale w niemożliwości dodania nowej funkcji bez modyfikacji trzech różnych modułów napisanych w różnych technologiach.

Jak uniknąć stworzenia potwora

Pierwszy i najważniejszy krok — wyznaczenie architekta lub tech leada odpowiedzialnego za spójność stosu technologicznego. Ta osoba ma prawo weta wobec wdrażania nowych technologii bez przeglądu architektonicznego. Nie demokracja, a odpowiedzialna jednoosobowa decyzja w kwestii kluczowych technologii.

Drugi — wdrożenie procesu Architecture Decision Record (ADR). Każda znacząca decyzja architektoniczna (wybór bazy danych, frameworka, protokołu) jest dokumentowana w formie krótkiego tekstu: kontekst, rozważane alternatywy, podjęta decyzja, konsekwencje. ADR są przechowywane w repozytorium i dostępne dla całego zespołu.

Trzeci — ustanowienie zasady „jedno zadanie — jedno narzędzie”. Dla zapytań HTTP — jeden klient. Dla ORM — jedna biblioteka. Dla logowania — jeden framework. Wyjątki są dozwolone tylko przez ADR z uzasadnieniem. Jeśli w projekcie jest już Axios — nie dodawaj fetch, jeśli jest SLF4J — nie pisz przez System.out.

  • Architekt z prawem weta wobec nowych technologii
  • Architecture Decision Records dla każdego znaczącego wyboru
  • Jednolity stos dla każdego zadania — jeden klient HTTP, jeden ORM
  • RFC dla dużych zmian z omówieniem całym zespołem
  • Radar technologiczny do śledzenia, co można wdrażać

Polityka eksperymentalnych technologii

Eksperymenty są dozwolone, ale w izolowanym środowisku. Wydziel moduł lub usługę, którą można przepisać na nową technologię bez wpływu na resztę systemu. Jeśli eksperyment się uda — ustandaryzuj go przez ADR. Jeśli nie — usuń bez konsekwencji.

Jak refaktoryzować istniejącego Frankensteina

Inwentaryzacja — pierwszy krok. Sporządź pełną mapę stosu technologicznego: jakie frameworki, biblioteki, języki, protokoły są używane, w jakich modułach i do jakich zadań. Zobaczysz skalę problemu: duplikowanie narzędzi, konfliktujące technologie, nieużywane zależności.

Standaryzacja — drugi krok. Wybierz jeden instrument dla każdego zadania. Na przykład: tylko Hibernate dla ORM, tylko SLF4J + Logback dla logowania, tylko REST dla API. Udokumentuj standard w ADR. Rozpocznij wymianę od modułów, w których eklektyka przynosi najwięcej problemów.

Strategia Parallel Run — trzeci krok. Stare i nowe narzędzia działają równolegle, aż nowe udowodni swoją niezawodność. Na przykład, stary i nowy klient HTTP działają jednocześnie, ale nowy — tylko dla części zapytań. Po okresie stabilizacji stary jest usuwany.

java
// frankenstein — trzy podejścia HTTP w jednym projekcie
// Moduł A: OkHttp
OkHttpClient client = new OkHttpClient().newCall(request);

// Moduł B: RestTemplate (Spring)
restTemplate.getForObject(url, String.class);

// Moduł C: java.net.HttpURLConnection
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();

// ujednolicone podejście: RestTemplate dla synchronicznego, WebClient dla reaktywnego
@Autowired
private RestTemplate restTemplate;

public String callApi(String url) {
    return restTemplate.getForObject(url, String.class);
}

Rola lidera technicznego w profilaktyce

Lider techniczny — główne narzędzie walki z Frankensteinem. Nie menedżer, nie architekt w wieży z kości słoniowej, ale praktykujący programista, który pisze kod, przegląda PR-y i podejmuje decyzje architektoniczne. Bez takiej osoby projekt nieuchronnie stacza się w technologiczną eklektykę.

RFC (Request for Comments) — proces zapożyczony ze społeczności Open Source. Przed wdrożeniem każdej znaczącej technologii autor pisze RFC: problem, proponowane rozwiązanie, alternatywy, plan wdrożenia. Zespół dyskutuje, głosuje, przyjmuje lub odrzuca. RFC tworzy przejrzystość i zapobiega „cichym” decyzjom architektonicznym.

Radar technologiczny (Technology Radar od ThoughtWorks) — narzędzie kategoryzacji technologii: Adopt, Trial, Assess, Hold. Zespół regularnie przegląda radar i aktualizuje statusy. Pomaga to odróżniać „modne” od „użytecznego” i unikać wdrażania niesprawdzonych technologii w krytycznym kodzie.

Zasada spójności

Najważniejszą cechą architektury jest spójność (consistency). Nawet nie najlepsze narzędzie, używane w całym projekcie, jest lepsze niż najlepsze narzędzie używane tylko w jednym module. Spójność zmniejsza obciążenie poznawcze, upraszcza onboarding i czyni kod przewidywalnym.

Często zadawane pytania

Czym Frankenstein różni się od użycia polyglot persistence?

Polyglot persistence — świadome użycie różnych baz danych do różnych zadań (PostgreSQL dla transakcji, Redis dla pamięci podręcznej, Elasticsearch dla wyszukiwania). Frankenstein — chaotyczne mieszanie bez strategii. Różnica polega na istnieniu decyzji architektonicznej: polyglot — to plan, Frankenstein — jego brak.

Czy architektura mikrousług może przerodzić się w Frankensteina?

Tak, i to częsty problem. Gdy każda mikrousługa używa własnego języka, własnej bazy danych, własnego protokołu i własnego podejścia do wdrażania bez scentralizowanych standardów — powstaje rozproszony Frankenstein. Dla mikrousług ważne są wspólne standardy: jednolity protokół (REST/gRPC), wspólny format logów, scentralizowane observability.

Jak przekonać zespół, aby nie używać nowej technologii?

Nie zakazuj — kieruj. Zaproponuj autorowi RFC: opisz, dlaczego istniejące rozwiązanie nie pasuje, jakie alternatywy rozważyłeś, jak będziesz migrować. Często w trakcie pisania RFC programista sam rozumie, że nowa technologia nie jest potrzebna. Jeśli RFC jest przekonujące — wdrażaj, ale z planem i ograniczeniami.

Jak walczyć z Frankensteinem w odziedziczonym projekcie?

Najpierw inwentaryzacja, potem standaryzacja. Nie próbuj przepisać wszystkiego naraz. Wyodrębnij jedną warstwę (na przykład klienty HTTP lub logowanie), wybierz jednolite narzędzie, napisz ADR i migruj stopniowo. Metoda Strangler Fig — zastępuj stare komponenty nowymi pojedynczo, bez zatrzymywania aplikacji.

Ile technologii jest optymalnych dla jednego projektu?

Im mniej, tym lepiej. Idealnie — jeden język, jeden framework, jedna baza danych, jeden sposób logowania. Realistycznie — 2–3 języki (przy wyraźnym podziale), 1–2 bazy danych, 1–2 frameworki. Każda dodatkowa technologia zwiększa obciążenie poznawcze zespołu i koszt utrzymania.

Podsumowanie

  • Frankenstein — antywzorzec, w którym system składa się z różnorodnych niekompatybilnych komponentów
  • Główne przyczyny: brak architekta, łączenie projektów, niekontrolowane eksperymenty
  • Konsekwencje — trudny onboarding, nieprzewidywalne zachowanie, problemy z bezpieczeństwem
  • ADR i RFC — kluczowe procesy zapobiegania eklektyce architektonicznej
  • Zasada „jedno narzędzie na zadanie” — podstawa profilaktyki
  • Refaktoryzacja zaczyna się od inwentaryzacji i standaryzacji stosu technologicznego
  • Spójność architektury jest ważniejsza niż „najlepsze narzędzie” dla jednego podzadania

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również