Spaghetti code

Nazwa nawiązuje do splątanych nitek spaghetti, gdzie prześledzenie przebiegu pojedynczej nitki makaronu jest trudne.

Spaghetti code – w informatyce pejoratywny termin określający długi, skomplikowany i trudny do zrozumienia kod źródłowy programu ze względu na brak przejrzystego przepływu sterowania lub generalnej struktury procedur.

Jest to jeden z popularniejszych zapachów kodu, choć istnieją rzadkie przypadki, gdy obecność kodu spaghetti bywa usprawiedliwiona. Przykładem jest sytuacja, gdy kod spaghetti jest zawarty w przejrzystym i wyizolowanym interfejsie lub gdy tempo wdrożenia programu wymagało szybkiej implementacji.

Istnieją badania, wskazujące na to, że wyniki modeli przewidujących występowanie kodu spaghetti są zbliżone do wyników modeli przewidujących występowanie błędów w oprogramowaniu. Może to dowodzić możliwego związku między występowaniem kodu spaghetti a problemami z jakością oprogramowania.

Pojęcie kodu spaghetti znalazło zastosowanie jako analogia w językoznawstwie, a dokładniej w pragmatyce.

Symptomy i cechy

Podstawowym symptomem, który świadczy o obecności kodu spaghetti jest utrudnione zrozumienie kodu przez innych programistów lub nawet samego autora kodu po upływie czasu. Czytanie takiego kodu może być czasochłonne.

W przypadku programowania obiektowego, charakterystyczna jest mała liczba obiektów, które posiadają obszerną implementację bez jednoznacznie określonej odpowiedzialności (złamanie zasady jednej odpowiedzialności). Obiekty mogą nie posiadać parametrów, a w zamian mogą wykorzystywać zmienne globalne. Taki kod z biegiem czasu nie okazuje się reużywalny(inne języki), wprowadzając powtórzenia kodu (wbrew zasadzie DRY). Powtarzające się fragmenty kodu mogą dodatkowo utrudniać jego utrzymanie, choć sama duplikacja kodu nie jest równoznaczna z kodem spaghetti.

Kod spaghetti może charakteryzować się stosowaniem podejścia proceduralnego w programach tworzonych w paradygmacie obiektowym.

Historia

Kod spaghetti był charakterystyczny dla wczesnych języków proceduralnych, typu Fortran czy BASIC, popularnych jeszcze przed powstaniem metody programowania strukturalnego. Używano wtedy wielu instrukcji warunkowych, z zagnieżdżonymi wewnątrz konstrukcjami GOTO i wyjątków. Utrzymanie takiego kodu źródłowego było utrudnione ze względu na trudność w zrozumieniu głównej struktury przepływu sterowania kodu.

Programowanie strukturalne wprowadziło uporządkowanie w procesie tworzenia programów, dzięki dzieleniu zadania do wykonania na mniejsze podzadania, aż do uzyskania wystarczająco prostych do realizacji fragmentów (zgodnie z zasadą dziel i zwyciężaj). Ułatwiło to implementację w poszczególnych modułach procedur, które w całości dadzą pożądany efekt. We współczesnej praktyce zazwyczaj dzieli się program na funkcje, z których każda realizuje określony cel i może być wywoływana wielokrotnie[potrzebny przypis].

W 1968 roku Edsger W. Dijkstra uznał, że instrukcje GOTO powinny zostać całkowicie zakazane w językach programowania wyższego poziomu, aby unikać powstawania kodu spaghetti. Dijkstra argumentował, że obecność instrukcji skoku komplikuje ludzkiemu czytelnikowi zadanie analizy i weryfikacji poprawności programu.

Przykład

10  INPUT count
20  LET steps = count
30  LET bbk = 0
40  LET bk = 1
50  IF count < 1 THEN GOTO 100
60  LET k = bbk + bk
70  LET bbk = bk
80  LET bk = k
90  LET count = count - 1
100 PRINT "Wyraz nr "; steps - count; "ciagu Fibonacciego wynosi: "; k
110 IF count > 0 THEN GOTO 50
120 END

Program wyświetla podaną przez użytkownika liczbę pierwszych wyrazów ciągu Fibonacciego. W kilku liniach trywialnego programu dwukrotnie użyto bezwarunkowej instrukcji skoku – GOTO. Przy bardziej złożonym kodzie i większej liczbie skoków pojawi się problem z jego zrozumieniem.

Ten sam cel zrealizowany przez programowanie strukturalne (w C):

scanf ("%d",&steps);
for (count = 0; count < steps; count++){
    static int bbk = 0, bk = 1;
    int k = bbk + bk;
    bbk = bk; bk = k;
    printf ("Wyraz nr %d ciagu Fibonacciego wynosi: %d\n",
    count + 1,k);
}

Poszczególne kroki wykonywane są w przejrzystej i formalnej pętli. Ciąg instrukcji do wykonania w programowaniu strukturalnym nie może być dowolnie zmieniany, „przejścia” do poszczególnych bloków są obsługiwane przez zaimplementowane konstrukcje (np. for, while, do while czy if else)[potrzebny przypis].

Refaktoryzacja

Jednym ze sposobów ograniczenia kodu spaghetti jest refaktoryzacja oparta na poszukiwaniu podobnych podzadań i wydzieleniu ich do dedykowanych modułów, funkcji lub metod. Takie działanie wymaga wydzielenia i stworzenia odpowiednich abstrakcji kodu.

Szczególnie użyteczne w zwalczaniu kodu spaghetti jest odpowiednie nazewnictwo obiektów oraz implementacja testów jednostkowych.

Przypisy

  1. 1 2 3 4 Antero Taivalsaari, Tommi Mikkonen, Return of the Great Spaghetti Monster: Learnings from a Twelve-Year Adventure in Web Software Development, Tim A. Majchrzak i inni red., Web Information Systems and Technologies, 2018, s. 21–44, DOI: 10.1007/978-3-319-93527-0_2, ISBN 978-3-319-93527-0 (ang.).
  2. 1 2 3 Geanderson Santos, Amanda Santana, Gustavo Vale, Eduardo Figueiredo, Yet Another Model! A Study on Model’s Similarities for Defect and Code Smells, Leen Lambers, Sebastián Uchitel (red.), t. 13991, Cham: Springer Nature Switzerland, 2023, s. 282–305, DOI: 10.1007/978-3-031-30826-0_16, ISBN 978-3-031-30825-3 (ang.).
  3. 1 2 Eric S.: The New Hacker's Dictionary, third edition. MIT Press, 1996, s. 420. ISBN 0-262-68092-0. (ang.).
  4. ↑ Cay S. Horstmann, Java Concepts for AP Computer Science, Wiley, 20 lipca 2007, s. 235, ISBN 978-0-470-18160-7 (ang.).
  5. William J. Brown, Raphael C. Malveau, Thomas J. Mowbray, Hays W. "Skip" McCormick III, AntiPatterns: refactoring software, architectures, and projects in crisis, New York: Wiley, 1998, ISBN 978-0-471-19713-3.
    1. 1 2 3 s. 65
    2. ↑ s. 38
    3. ↑ s. 66
    4. ↑ s. 56
    5. 1 2 s. 67
  6. 1 2 Naouel Moha, Yann-Gaël Guéhéneuc, Anne-Françoise Le Meur, Laurence Duchien, A Domain Analysis to Specify Design Defects and Generate Detection Algorithms, José Luiz Fiadeiro, Paola Inverardi (red.), Fundamental Approaches to Software Engineering, Berlin, Heidelberg 2008, s. 276–291, DOI: 10.1007/978-3-540-78743-3_20, ISBN 978-3-540-78743-3.
  7. 1 2 3 Kate Scott, Pronouns and procedures: Reference and beyond, „Lingua”, 175-176, 2016, s. 69–82, DOI: 10.1016/j.lingua.2015.07.005, ISSN 0024-3841 [dostęp 2026-09-14].
  8. ↑ Edsger W. Dijkstra, Letters to the editor: go to statement considered harmful, „Communications of the ACM”, 11 (3), New York, NY, USA: Association for Computing Machinery, 1968, s. 147–148, DOI: 10.1145/362929.362947, ISSN 0001-0782 [dostęp 2026-09-14].