Yeniden düzenleme (refaktoring), kodun dış davranışını değiştirmeden iç yapısını değiştirmek anlamına gelen bir BT argo terimidir. Refaktoringin amacı, kodu daha temiz, anlaşılır ve bakımı kolay hale getirmektir. Martin Fowler'ın “Refactoring: Improving the Design of Existing Code” (Addison-Wesley, 2019) kitabına göre, refaktoring kod tabanının sağlığını korumak için zorunlu bir uygulamadır ve düzenli uygulanması projenin toplam sahip olma maliyetini %20-30 oranında azaltır.
Önemli Noktalar
Yeniden düzenleme, gözlemlenebilir davranışını değiştirmeden yazılım kodunun iç yapısını değiştirerek kalite özelliklerini iyileştirme sürecidir. Terim, 1999 yılında Martin Fowler tarafından yaygın kullanıma sunuldu ve uygulamanın kendisi çevik geliştirme ve aşırı programlamanın temellerinden biri haline geldi.
Refaktoringin temel özelliği işlevselliği korumaktır. Refaktoringden sonra program, değişikliklerden öncekiyle tamamen aynı eylemleri gerçekleştirmeli ve aynı sonuçları döndürmelidir. Bunun garantisi, refaktoringin her mikro adımından sonra çalıştırılan otomatik testlerdir. Testler yeşilse — davranış korunmuştur. Kırmızıysa — refaktoring yanlış yapılmış veya davranış değişmiştir, bu da bunun artık refaktoring değil, işlevsellik değişikliği olduğu anlamına gelir.
Sektörde yaygın bir yanlış anlama vardır: her kod onarımına refaktoring denir. Gerçekte, davranış değişiklikleriyle kodu yeniden yazmak bir “yeniden yazma” veya “yeniden işleme”dir, refaktoring değil. Fark temeldir: refaktoring kontrollü, güvenli bir süreçtir, mantık değişiklikleriyle yeniden yazmak ise tüm ilişkili riskleriyle birlikte tamamen yeni bir geliştirmedir.
Refaktoring hakkındaki bilginin sermayeleşmesi Türkçe konuşulan ortamda diğer BT terimleriyle aynı mekanizmalar aracılığıyla gerçekleşir. Yazılım Mühendisliği eğitim programları ve kitap çevirileri bu terimi profesyonel söz dağarcığına yerleştirmiştir.
Refaktoringi tam bir kod yeniden yazmadan (rewrite) ayırt etmek önemlidir. Refaktoring, her biri davranışı koruyan bir dizi küçük, güvenli dönüşümdür. Yeniden yazma, genellikle mimari, teknoloji ve davranış değişiklikleriyle birlikte sıfırdan yeni bir uygulama oluşturmaktır. Standish Group (2023) araştırması, tamamen yeniden yazmayı seçen projelerin vakaların %40'ında başarısız olduğunu, düzenli refaktoring yapan projelerin ise %25 daha düşük teknik borca sahip olduğunu göstermektedir.
Refaktoring, her biri geliştirmenin hızını ve maliyetini doğrudan etkileyen birkaç temel görevi çözer. Bu hedefleri anlamak, ekibin doğru önceliklendirme yapmasına ve paydaşlara refaktoringe harcanan zamanı haklı çıkarmasına yardımcı olur.
Kod bir kez yazılır ancak onlarca ve yüzlerce kez okunur. Bir geliştirici bir fonksiyonun ne yaptığını anlamak için 30 dakika harcıyorsa — bu doğrudan verimlilik kaybıdır. Okunabilir kod bilişsel yükü azaltır ve yeni ekip üyelerinin uyum sürecini hızlandırır. Rename Method, Extract Variable ve Introduce Explaining Variable gibi teknikler tam olarak kod netliğini artırmayı hedefler. Developer Productivity (Microsoft Research, 2023) araştırmasına göre, geliştiriciler zamanlarının %60'ını kod yazmak yerine okumakla geçirir, bu da okunabilirliği verimliliğin ana faktörlerinden biri yapar.
DRY (Don’t Repeat Yourself) ilkesi programlamanın temellerinden biridir. Kod tekrarı, aynı değişikliğin birden fazla yerde yapılmasına yol açarak hata ve unutulan düzeltmeler riskini artırır. Extract Method ve Pull Up Method teknikleriyle refaktoring, tekrarı ortadan kaldırır ve mantığı merkezileştirir.
Siklomatik karmaşıklık ve iç içe geçme derinliği metrikleri, koddaki hata sayısıyla doğrudan ilişkilidir. Bir fonksiyonun siklomatik karmaşıklığı 10-15'in üzerindeyse, test edilmesi zor ve bozulması kolaydır. Replace Conditional with Polymorphism, Decompose Conditional ve Extract Method kullanarak refaktoring, karmaşıklığı kontrol edilebilir bir seviyeye indirir. NIST (2024) araştırması, yüksek karmaşıklığa sahip modüllerin bin satır kod başına 2-3 kat daha fazla hata içerdiğini göstermektedir.
Refaktoringin ana nedenlerinden biri yeni işlevsellik ekleme ihtiyacıdır. Mevcut kod yapısı, var olan davranışı bozmadan bir değişiklik yapmaya izin vermiyorsa, refaktoring zemini hazırlamaya yardımcı olur. “Kamp kuralı” (kodu bulduğunuzdan daha temiz bırakın), Martin Fowler'ın refaktoringi ara sıra yapılan bir aktiviteden sürekli bir uygulamaya dönüştüren önerilerinden biridir.
GitHub'daki 500 açık kaynak projenin analiz verileri (IEEE Transactions on Software Engineering, 2024), düzenli refaktoring yapan projelerin, refaktoringi ara sıra yapan projelere kıyasla %30 daha az “kod kokusu” (code smells) ve %15 daha düşük teknik borç göstergesine sahip olduğunu göstermektedir.
Martin Fowler kitabında 70'ten fazla refaktoring tekniğini kataloglamıştır. Pratikte, çoğu takım düzenli olarak bunların 10-15'ini kullanır. Her geliştiricinin bilmesi gereken temel teknikleri inceleyelim.
En sık kullanılan teknik. Kodun bir bölümü anlamsal olarak ayrı bir fonksiyona çıkarılabiliyorsa — bu yapılmalıdır. Extract Method okunabilirliği artırır, işleme bir ad vermeyi sağlar ve test etmeyi basitleştirir. Kural: bir kod bloğunun ne yaptığını açıklayan bir yorum görüyorsanız — bu blok ayrı bir metoda çıkarılabilir.
// Refaktoringden önce
double total = amount * price;
double discounted = total * (1 - discountRate);
double tax = discounted * taxRate;
// Refaktoringden sonra
double total = calculateTotal(amount, price);
double finalPrice = applyDiscountAndTax(total);
Ad özü yansıtmalıdır. Bir değişken veya metodun adı “burada ne saklanıyor/yapılıyor” sorusunu yanıtlamıyorsa — yeniden adlandırılmalıdır. Modern IDE'ler bu işlemi basit hale getirir. Temiz adlar kodu iyileştirmenin en ucuz ve etkili yoludur.
Koşullu mantık büyüdüğünde ve kafa karıştırıcı hale geldiğinde, çok biçimlilik (polymorphism) daha temiz bir alternatif sunar. Türe göre switch-case yerine — geçersiz kılınmış bir metotla sınıf hiyerarşisi oluşturun. Çok biçimlilik kodu genişletilebilir yapar: yeni bir tür eklemek, mevcut koşulları değiştirmeyi gerektirmez, sadece yeni bir alt sınıf oluşturmayı gerektirir.
// Refaktoringden önce (koşullu)
if (type.equals("email")) {
sendEmail(message);
} else if (type.equals("sms")) {
sendSms(message);
}
// Refaktoringden sonra (çok biçimlilik)
Notifier notifier = new EmailNotifier();
notifier.send(message);
Bir fonksiyon çok fazla parametre aldığında (3-4'ten fazla), bunları okumak ve iletmek zordur. İlgili parametreleri bir parametre nesnesinde gruplamak imzayı kısaltır, okunabilirliği artırır ve gelecekteki değişiklikleri basitleştirir.
| Teknik | Amaç | Ne zaman uygulanmalı |
|---|---|---|
| Extract Method | Mantığı ayrı bir fonksiyona çıkarma | Kod bloğu bir cümleyle açıklanabilir |
| Rename Variable | Değişken/metot adını netleştirme | Ad özü yansıtmıyor |
| Replace Conditional | switch-case'i çok biçimlilikle değiştirme | Nesne türüne dayalı koşullar |
| Extract Interface | Bir sınıftan sözleşme çıkarma | Gevşek bağlantı gerekli |
Yeniden düzenleme kararı teknik değil, yönetseldir. Mevcut verimlilik ile uzun vadeli kod tabanı sağlığı arasında bir denge gerektirir. Refaktoringin haklı olduğu tipik durumları ve ne zaman kaçınmanın daha iyi olduğunu inceleyelim.
İlk durum — değiştirmeniz gereken kodu anlamıyorsunuz. Mevcut kodu anlamak, yeni işlevsellik uygulamaktan daha uzun sürüyorsa — bu önce refaktoring yapılması gerektiğinin bir işaretidir. İkinci durum — geliştirmeyi yavaşlatan ve hata riskini artıran tekrar buldunuz. Üçüncü — mevcut yapıyı bozmadan yeni işlevsellik eklemek imkansız.
Kod tabanı “kod kokuları” (code smells) içerdiğinde de refaktoring yapmaya değer: uzun metotlar, büyük sınıflar, aşırı yorumlar, çağrı zincirleri, paralel kalıtım hiyerarşileri. Fowler'ın kitabındaki kod kokusu kataloğu, her biri için karşılık gelen bir refaktoring tekniği olan 20'den fazla tipik sorun göstergesi içerir.
Kod istikrarlı çalışıyorsa ve değiştirilmesi planlanmıyorsa refaktoring gerekli değildir. “Bozuk değilse, düzeltme” (if it ain’t broke, don’t fix it) ilkesi, nadiren değiştirilen kod için özellikle geçerlidir. Refaktoring için refaktoring, yarardan çok zarar veren bir mühendislik mükemmelliyetçiliği biçimidir.
Ayrıca, yakın gelecekte tamamen değiştirilecek kodu refaktoring yapmamalısınız. Ekip modülü başka bir dilde veya mimaride yeniden yazmayı planlıyorsa, mevcut sürümü refaktoring yapmak zaman kaybıdır. Ve son olarak, testler olmadan refaktoring yapmak, özellikle kod tabanı büyük ve karmaşıksa, bir maceradır. İstisna, geri alınabilen IDE kullanımıyla yapılan basit dönüşümlerdir.
Güvenli refaktoring bir disiplindir. Riskleri en aza indiren ve süreci öngörülebilir kılan birkaç ilke vardır. İlk ve en önemlisi — sadece testler altında refaktoring. Değiştirilen kodu kapsayan testleriniz yoksa — önce onları yazın.
İkinci ilke — küçük adımlar. Her refaktoring işlemi minimal olmalıdır: bir değişkeni yeniden adlandırma, bir metodu çıkarma, bir sınıfı çıkarma. Her adımdan sonra — derleme ve testleri çalıştırma. Mikro adımlara bölme, bir hatayı hemen tespit etmeye ve son değişikliği geri almaya olanak tanır. Martin Fowler'a göre, mikro adımlar refaktoringi büyük değişikliklerden 3-4 kat daha güvenli hale getirir.
Üçüncü ilke — araçları kullanma. Modern IDE'ler (IntelliJ IDEA, VS Code, Eclipse) otomatik refaktoringler sağlar: yeniden adlandırma, metot çıkarma, değişken çıkarma, sınıf taşıma ve onlarcası. Araç tabanlı refaktoringler, dönüşümün doğruluğunu garanti eder ve kodun değiştirilmesi gereken tüm yerlerin manuel olarak aranmasını gerektirmez.
Dördüncü ilke — refaktoringi işlevsellik değişiklikleriyle karıştırmayın. Aynı anda refaktoring yapıp yeni mantık eklerseniz, hangi değişikliğin hataya neden olduğunu belirlemek imkansızdır. Commit'leri “refaktoring” ve “özellik” olarak ayırmak, kod incelemesini ve değişiklik geri almayı basitleştiren bir endüstri standardıdır. Önerilen yapı: önce bir refaktoring commit'i (sadece yapısal değişiklikler, davranış korunmuş), ardından yeni işlevsellik içeren bir commit.
Refaktoring için Git akışı: ayrı bir dal oluşturun, refaktoringi gerçekleştirin, yeşil testlere ulaşın, commit yapın, ardından aynı dalda yeni işlevsellik ekleyin. Bir şey ters giderse — refaktoring değişiklikleri her zaman git revert ile geri alınabilir.
# Git'te refaktoring mikro adımları
git checkout -b refactor/extract-payment
# Adım 1: hesaplama metodunu çıkar
# ...değişiklikler... → derle → testler
git commit -m "refactor: extract calculatePayment method"
# Adım 2: değişkenleri yeniden adlandır
# ...değişiklikler... → derle → testler
git commit -m "refactor: rename amount to grossAmount"
Sıkça Sorulan Sorular
Hayır, bunlar farklı süreçlerdir. Yeniden düzenleme, davranışını değiştirmeden mevcut kodu iyileştirmektir. Yeniden yazma (rewrite), genellikle mimari ve teknoloji değişiklikleriyle birlikte sıfırdan yeni bir uygulama oluşturmaktır. Refaktoring daha güvenli, daha ucuz ve daha öngörülebilirdir.
Önerilen kural, sprint süresinin %20'sini teknik iyileştirmeler ve refaktoring için ayırmaktır. Bu, iş işlevselliği teslimatını yavaşlatmadan teknik borcu kabul edilebilir bir seviyede tutmayı sağlar.
Yapılabilir, ancak risklidir. IDE aracılığıyla basit dönüşümler (yeniden adlandırma, sabit çıkarma) için testler zorunlu değildir. Karmaşık değişiklikler için — testler zorunludur. Testler yoksa — önce mevcut davranışı yakalayan karakterizasyon testleri yazın.
Değişikliklerin maliyeti üzerinden tartışın. Karmaşık kod nedeniyle basit bir özellik eklemek bir hafta sürüyorsa — refaktoringin gelecekteki değişiklikler için zamanı azaltacağını gösterin. Metrikler kullanın: CR süresi, hata sayısı, siklomatik karmaşıklık.
Son değişikliği geri alın. Git kullanıyorsanız — son commit'in git revert'ını yapın. Mikro adımlar yeterince küçükse, kaybedilen değişikliklerin hacmi minimal olacaktır. Bu nedenle büyük refaktoring her zaman bir dizi mikro adıma bölünür.
Ö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