
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.
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, 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.
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.
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].
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.