Spagetti kodu (spagetti kodu, erişte kodu) — mantıksal blokların herhangi bir düzen olmadan iç içe geçtiği karmaşık, kaotik bir program yapısıdır. TIOBE Index (2024) araştırmasına göre, yüksek düzeyde spagetti kodu içeren projeler, yeni özellikler uygulamak için 2,5 kat daha fazla zaman gerektirir. Terim, goto deyiminin programın herhangi bir noktası arasında atlama yapmasına izin verdiği ve okunamaz yapılar oluşturduğu erken programlama çağında ortaya çıktı.
Anahtar noktalar
Spagetti kodu — yapısı bir tabak spagettiyi andıran kodu tanımlamak için bir metafordur: bireysel teller (mantıksal bloklar) birbirine dolanmış, yapışmış ve birbirinden ayrılamaz. Bu tür kodda katmanları, modülleri veya bileşenleri ayırmak imkansızdır — her şey tek bir büyük kütlede karışır.
Sadece özensiz olabilen kötü koddan farklı olarak, spagetti kodu temel bir mimari sorundur. İyi değişken adlarıyla mükemmel biçimlendirilmiş kod bile, mimarisi kaotikse spagetti kodu olabilir. Sorun yazma stilinde değil, program yapısı seviyesindedir.
IEEE'ye (2022) göre, büyük projelerdeki tüm hataların yaklaşık %35'i, geliştiricinin mantıksal hatalarından değil, kod yapısının karmaşıklığından kaynaklanır. Geliştirici, görevi yanlış anladığı için değil, spagetti kodunda yürütme akışını takip edemediği için hata yapar.
Kötü kod tek bir fonksiyon veya dosya ölçeğinde kötü kod ise, spagetti kodu tüm uygulama ölçeğinde kötü mimaridir. Erişte, tek tek iyi yazılmış fonksiyonlardan oluşabilir, ancak etkileşimleri kaotik ve öngörülemezdir.
Terim “spagetti kodu” 1970'lerde goto deyiminin eleştirisiyle birlikte ortaya çıktı. Erken programlama dillerinde (BASIC, FORTRAN, COBOL), goto yürütme akışını kontrol etmenin ana yoluydu. Bir program, numaralandırılmış satırların bir dizisiydi ve goto bunlardan herhangi birine atlamaya izin veriyordu. Bu, çözülmesi imkansız bir atlama “dolaşıklığı” yarattı.
1968'de, Edsger Dijkstra, yapılandırılmış programlama çağının başlangıcını işaretleyen ünlü mektubu “Go To Statement Considered Harmful”ı yayınladı. Dijkstra, herhangi bir algoritmanın goto olmadan, yalnızca üç yapı kullanılarak uygulanabileceğini kanıtladı: sıra, dallanma (if) ve döngü (while). Bu, modern programlamanın temeli oldu.
Yapılandırılmış programlama sorunu tamamen ortadan kaldırmadı. Spagetti kodu yeni bir seviyeye taşındı — fiziksel gotolar yerine, geliştiriciler mantıksal “goto”lar oluşturmaya başladı: global değişkenler, JavaScript'te callback cehennemi, karmaşık çağrı zincirleri ve bileşenler arasında örtük bağımlılıklar. Sorun kaldı, sadece biçim değişti.
Callback cehennemi, derin iç içe Promise'ler, hata yönetimi olmayan async/await, kimin veya ne zaman tetiklediği anlaşılmayan olaylar — bunların hepsi spagetti kodunun modern çeşitleridir. Anti-desen yaşıyor ve gelişiyor, sadece şimdi goto deyimini kullanmıyor.
Katman eksikliği — ilk ve ana belirti. Spagetti kodunda, iş mantığı, veritabanı işlemleri, HTML işaretlemesi ve ağ iletişimi tek bir dosyada veya hatta tek bir yöntemde karışır. Bir veritabanı sorgusunu değiştirmek, UI görüntülemesini bozabilir çünkü bu katmanların kodu ayrılmamıştır.
Global değişkenler ve singleton'lar — ikinci belirgin belirti. Uygulama durumu global nesnelerde depolandığında, yürütme akışı öngörülemez hale gelir. Herhangi bir fonksiyon global durumu değiştirebilir ve bunun nerede ve ne zaman olduğunu izlemek pratik olarak imkansızdır.
God sınıflar ve god fonksiyonlar — üçüncü belirti. İş mantığını, görüntülemeyi ve veri işlemlerini yöneten 2000+ satırlık bir sınıf — bu tipik spagetti kodudur. 10 parametre alıp 5 farklı şey yapan bir fonksiyon — o da spagetti.
| Belirti | Açıklama | Örnek |
|---|---|---|
| Katman karışımı | UI kodu içinde SQL sorguları | Doğrudan DB yazma ile denetleyici |
| Global değişkenler | Her yerden erişilebilir durum | Her sınıfta static SessionManager |
| God sınıflar | Bir sınıf her şeyi yapar | 3000 satırlık OrderManager |
| Uzun yöntemler | Ayrıştırılmamış fonksiyonlar | 5 sorumlulukla 200 satırlık yöntem |
| Callback cehennemi | Sonsuz iç içe callback'ler | JavaScript'te 6 seviye iç içelik |
Eğer 15 mock nesnesi oluşturmadan bir fonksiyon için birim testi yazamıyorsanız — bu spagetti kodudur. Tek bir modülü test etmek tüm uygulama altyapısını başlatmayı gerektiriyorsa — bu spagetti kodudur. Test edilemezlik, karmaşık mimarinin objektif bir göstergesidir.
Mimari tasarım eksikliği — en yaygın neden. Bir ekip plansız kod yazmaya başladığında ve mimariyi “yol üzerinde” seçtiğinde, sonuç kaçınılmaz olarak spagettiye dönüşür. Her yeni özellik, mantıksal olarak ait olduğu yere değil, “şimdi uygun” olan yere eklenir.
Evrimsel gelişim — ikinci neden. Bir proje küçük bir betik olarak başlar, sonra özelliklerle büyür, sonra bir uygulama ve ardından bir monolit haline gelir. Bu arada mimari yeniden değerlendirilmez. 100 satır kod için çalışan şey, 100.000 satır için felakete dönüşür.
SOLID ilkelerinin ihlali — üçüncü neden. Özellikle tek sorumluluk ilkesi (S) ve bağımlılığı ters çevirme ilkesi (D). Bir sınıf her şeyden sorumlu olduğunda, bağımlılıklar katı ve modüller sıkı sıkıya bağlı olduğunda — spagetti kodu elde edersiniz.
Son teslim tarihleri ve hotfix kültürü — spagetti kodunun katalizörleri. “Dün gerekiyordu” dendiğinde, geliştiriciler mimariyi düşünmeden kodu ilk uygun yere ekler. Bu tür on hotfix — ve uygulama mimarisi yok olur.
Ana sonuç — kod tabanı üzerinde kontrol kaybı. Geliştiriciler uygulamanın bir bütün olarak nasıl çalıştığını anlamamaya başlar. Bir yerdeki değişiklik, görünüşte ilgisiz başka bir yeri bozar. Her yama iki yeni hata oluşturur. Ekip “değişiklik korkusu” durumuna girer.
Ekip üretkenliği üstel olarak düşer. Microsoft Research (2023), spagetti kodunda yeni bir özellik ekleme süresinin kod tabanı boyutuna göre ikinci dereceden arttığını gösterdi. Temiz mimari için bu artış doğrusaldır. Fark, 50.000+ satır kodda kritik hale gelir.
Güvenlik — başka bir kurban. Spagetti kodunda, işlenmemiş bir istisnayı, hatalı girdi doğrulamayı veya veri sızıntısını gözden kaçırmak kolaydır. Karmaşık mimariye sahip bir projede güvenlik denetimi pratikte imkansızdır — kullanıcı girişinin kullanıldığı tüm yerleri bulmak gerçekçi değildir.
İş gücü devir hızı, spagetti kodu olan projelerde ortalamanın üzerindedir. Deneyimli geliştiriciler “erişte” ile çalışmak istemedikleri için ayrılır. Yeni çalışanlar kodu anlayamaz ve ilk aylarda işten ayrılır. Proje uzmanlığı kaybeder, bu da kod kalitesini daha da kötüleştirir — bir kısır döngü.
Birinci — katmanları ayırarak başlayın. Kodu üç seviyeye ayırın: sunum (UI, denetleyiciler), iş mantığı (hizmetler, kullanım durumları) ve veri erişimi (depolar, DAO). Kısmi ayırma bile yapıyı hemen iyileştirir ve kodu test edilebilir hale getirir.
İkinci — dependency injection uygulayın. Bağımlılıkların doğrudan oluşturulmasını, yapıcılar veya parametreler aracılığıyla iletilmeleriyle değiştirin. Bu, bileşenler arasındaki katı bağlantıları kırar ve her modülün izole bir şekilde test edilmesini sağlar.
Üçüncü — god sınıfları ve god fonksiyonları çıkarın. Bunları tek sorumluluklu küçük sınıflara ve yöntemlere bölün. Karmaşık alt sistemleri basitleştirmek için Facade desenini kullanın. Unutmayın: 20 satırlık bir sınıf, 2000 satırlık bir sınıftan daha anlaşılırdır.
// spagetti — her şey bir yöntemde
function handleRequest(req, res) {
const db = new Database("mysql://...");
const user = db.query("SELECT * FROM users WHERE id =" + req.params.id);
let html = "";
html += ""
+ user.name + "";
html += "Balance: "
+ user.balance + "";
html += "";
res.send(html);
}
// temiz mimari — ayrı katmanlar
class UserController {
constructor(userService) {
this.userService = userService;
}
async getUser(req, res) {
const user = await this.userService.findById(req.params.id);
res.json(new UserResponse(user));
}
}
class UserService {
constructor(userRepository) {
this.userRepository = userRepository;
}
async findById(id) {
return await this.userRepository.findById(id);
}
}
Tüm kod tabanını bir kerede yeniden yazmaya çalışmayın — bu garantili başarısızlıktır. Bir modül seçin, mevcut davranışı yakalayan karakterizasyon testleri yazın ve ancak ondan sonra yeniden düzenleyin. Yavaş yavaş, modül modül, spagettiyi çözeceksiniz.
Mimari planlama — önlemenin temeli. Geliştirmeye başlamadan önce bir mimari stil onaylayın: MVC, MVVM, Clean Architecture, VIPER veya başka birini. Seçimi gerekçelendiren bir ADR (Architecture Decision Record) yazın. Kod incelemesinde mimariye uyulmasını talep edin.
Bağımlılığı ters çevirme ilkesi (DIP) — spagetti koda karşı güçlü bir araç. Üst düzey modüller, alt düzey modüllere bağlı olmamalıdır. Her ikisi de soyutlamalara bağlı olmalıdır. Dependency Injection, bu ilkenin pratik uygulamasıdır.
Testler — en iyi önleme. Koddan önce test yazarsanız (TDD), kaçınılmaz olarak gevşek bağlı bileşenler tasarlarsınız. Test edilebilir kod, iyi yapılandırılmış koddur. Test edilemeyen kod neredeyse her zaman spagetti kodudur.
SonarQube — döngüsel karmaşıklığı, kalıtım derinliğini, yöntem boyutunu izler. JDepend (Java) — paketler arasındaki bağımlılıkları ölçer. PhpMetrics — PHP projeleri için bakım yapılabilirlik indeksi sağlar. CI/CD'de metrikleri izleyin — erişteyi sonradan mücadele etmek yerine ortaya çıkmasını önleyin.
Sıkça sorulan sorular
Evet, aşamalı yeniden düzenleme tercih edilir. Strangler Fig yöntemini kullanın — uygulamayı durdurmadan eski bileşenleri yenileriyle kademeli olarak değiştirin. Veri katmanını veya iş mantığını ayırarak başlayın. İşlevselliği kaybetmemek için değişikliklerden önce eski kodu testlerle kaplayın.
Spagetti kodu — tüm uygulama katmanlarının kaotik bir iç içe geçmesidir. Lazanya kodu, sıkı çok katmanlı bir mimaridir, ancak her katman o kadar izole edilmiştir ki aralarındaki veri aktarımı bürokratik hale gelir. Her iki anti-desen de zararlıdır, ancak spagetti kodu daha tehlikelidir — kodu öngörülemez hale getirir.
Bağımlılıklara bakın: bir modül, uygulamanın tüm katmanlarından modüller içe aktarıyorsa — bu şüphelidir. Yöntem boyutuna dikkat edin — 30 satırdan fazlası genellikle kötüdür. Bir fonksiyonun UI işini, iş mantığını ve veriyi karıştırıp karıştırmadığını kontrol edin. Öyleyse — bu spagetti kodudur.
Robert Martin'in Clean Architecture'u ve Hexagonal Architecture (Ports & Adapters) — en iyi iki yaklaşım. Her ikisi de katman ayrımını, iş mantığının çerçevelerden bağımsızlığını ve test edilebilirliği garanti eder. Mobil geliştirme için — Repository deseni ile MVVM.
Kısmen. Döngüsel karmaşıklık (McCabe), modül bağlantısı ve kalıtım ağacı derinliği (DIT) gibi metrikler potansiyel spagetti kodu gösterir. SonarQube, CodeClimate ve PhpMetrics bu metrikleri otomatik olarak hesaplar. Ancak, tam teşhis insan mimari analizi gerektirir.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun