Refactoring — Mevcut Kodun Tasarımını İyileştirme Sanatı —Giriş Bölümü
Kısım I — Temeller: Refactoring’in Doğası

Refactoring — Mevcut Kodun Tasarımını İyileştirme Sanatı —Giriş Bölümü
Kısım I — Temeller: Refactoring’in Doğası
İçindekiler
Bu giriş bölümünün görevi, önümüzdeki yolculuğun haritasını sermektir. Aşağıda serinin tamamını oluşturan bölümler, beş büyük kısım altında listelenmiştir. Her satır, ilerleyen haftalarda derinlemesine işleyeceğimiz bir durağı temsil eder.
Kısım I — Temeller: Refactoring’in Doğası » *Bölüm 1: Refactoring Nedir, Ne Değildir? — Tanım, İki Şapka ve Davranış Korunumu [» Bölüm 2: Refactoring’in Kısa Tarihi ve Felsefesi — Opdyke’tan Fowler’a](https://medium.com/@sahinyelkenci/refactoring-mevcut-kodun-tasar%C4%B1m%C4%B1n%C4%B1-i%CC%87yile%C5%9Ftirme-sanat%C4%B1-b%C3%B6l%C3%BCm-2-refactoringin-k%C4%B1sa-tarihi-ve-0a074c1bc4fb)* » Bölüm 3: Neden Refactor Ederiz? — Teknik Borç ve Değişim Maliyeti Ekonomisi » Bölüm 4: Güvenlik Ağı — Testler Olmadan Refactoring Olmaz
Kısım II — Teşhis: Kötü Kodu Tanımak » Bölüm 5: Code Smells (I) — Metot ve Fonksiyon Düzeyindeki Kokular » Bölüm 6: Code Smells (II) — Sınıf ve Veri Düzeyindeki Kokular » Bölüm 7: Code Smells (III) — Bağlılık, Mesaj Zincirleri ve Yapısal Kokular » Bölüm 8: Ölçmek — Cyclomatic Complexity, Coupling, Cohesion ve Kod Metrikleri
Kısım III — Katalog: Refactoring Mekaniği » Bölüm 9: Bir Refactoring’in Anatomisi — İsim, Motivasyon ve Mekanik » Bölüm 10: Metot Kompozisyonu — Extract, Inline ve Değişken Refactoringleri » Bölüm 11: Özellikleri Nesneler Arasında Taşımak — Move Method, Move Field » Bölüm 12: Veriyi Organize Etmek — Encapsulation ve Veri Yapıları » Bölüm 13: Koşullu Mantığı Sadeleştirmek — Guard Clauses ve Polymorphism » Bölüm 14: API ve Arayüz Refactoringleri — İmza, Parametre ve Sözleşme » Bölüm 15: Kalıtım Hiyerarşileriyle Çalışmak — Pull Up, Push Down, Delegation
Kısım IV — Büyük Resim: Sistem Ölçeğinde Refactoring » Bölüm 16: Büyük Ölçekli Refactoring ve Branch by Abstraction » Bölüm 17: Legacy Code ile Savaşmak — Seam’ler ve Karakterizasyon Testleri » Bölüm 18: Refactoring to Patterns — Tasarım Desenlerine Doğru Evrim » Bölüm 19: Mimari Refactoring — Strangler Fig ve Modülerleşme » Bölüm 20: Veritabanı Refactoring — Şema Evrimi ve Geçiş Stratejileri » Bölüm 21: Yüksek TPS ve Eşzamanlı Sistemlerde Refactoring
Kısım V — Pratik ve Kültür: Sürdürülebilir Disiplin » Bölüm 22: IDE ve Otomatik Refactoring Araçları — Güvenilir Dönüşümler » Bölüm 23: Refactoring ve Versiyon Kontrol Disiplini — Küçük Commit’ler » Bölüm 24: Refactoring Kültürü — Code Review, Boy Scout Kuralı ve Takım Pratikleri » Bölüm 25: Anti-Patterns, Tuzaklar ve Refactoring’i Ne Zaman Yapmamalı
Ekler » Ek A: Refactoring Katalog Hızlı Referans Tablosu » Ek B: Code Smell → Refactoring Eşleme Matrisi » Ek C: Kaynakça ve İleri Okuma Rehberi » *https://gitlab.com/sahin.yelkenci2/refactoring-canli-bahis*
Bu Seri Neden Var? — Açılış
Yazılım dünyasında en sık anlatılan ama en az anlaşılan hikâyelerden biri şudur: Bir takım, üç yıl önce temiz, hızlı, esnek bir kod tabanıyla yola çıkar. İlk altı ay her şey harikadır; yeni özellikler günler içinde devreye girer, hatalar nadirdir, herkes mutludur. Sonra bir şey değişmeye başlar. Bir gün birisi der ki: “Bu modüle dokunmaya korkuyorum.” Bir başka gün, basit görünen bir değişiklik üç gün sürer çünkü o tek satırın dokunduğu yedi farklı yer vardır. İki yılın sonunda takım, her sprint planlamasında aynı cümleyi kurar: “Aslında burayı sıfırdan yazmamız lazım.” İşte bu cümle, bir mühendislik kültürünün sessiz teslim bayrağıdır.

Bu serinin var olma sebebi tam olarak budur. Çünkü “sıfırdan yazmak” neredeyse her zaman yanlış cevaptır. Joel Spolsky’nin meşhur tespitiyle, bir kod tabanını çöpe atıp baştan yazmak, bir şirketin yapabileceği en stratejik hatalardan biridir; çünkü o çirkin, karmaşık, anlaşılmaz kod aslında yıllarca biriktirilmiş bilginin, düzeltilmiş onlarca sınır durumunun ve gerçek dünyanın acımasız geri bildiriminin kristalleşmiş hâlidir. Onu attığınızda kodu değil, o bilgiyi atarsınız. Refactoring ise bunun tam zıttı bir felsefedir: Kodu çöpe atmadan, davranışını hiç bozmadan, küçük ve güvenli adımlarla tasarımını yeniden hayata döndürme disiplinidir.
Bu seriyi ayrı bir niyetle kurguladık. Piyasada mesajlaşma sistemleri, event-driven mimari, dağıtık sistemler üzerine sayısız kaynak var; bunların çoğu “yeni bir şey nasıl inşa edilir” sorusuna odaklanır. Oysa profesyonel hayatımızın büyük çoğunluğu yeni bir şey inşa etmekle değil, var olan bir şeyi değiştirmekle, anlamakla ve iyileştirmekle geçer. Greenfield projeler kariyerimizin küçük bir azınlığını oluşturur; geri kalan her şey brownfield’dır — yani başkalarının (ve çoğu zaman geçmişteki kendimizin) bıraktığı kodun üzerine inşa etmektir. Refactoring, bu çoğunluk gerçekliğin temel becerisidir ve şaşırtıcı biçimde en az sistematik öğretilen konudur. Çoğu mühendis refactoring’i “kodu güzelleştirmek” sanır; oysa o, davranış korunumu garantisi altında yürütülen, kataloglanmış mekaniklere dayanan, matematiksel kesinliğe yaklaşan bir mühendislik disiplinidir.
Bu yüzden bu seride “ultra detay”dan kastımız, klişe tavsiyelerin ötesine geçmektir. “Fonksiyonların kısa olsun” demek kolaydır; bir 400 satırlık metodu, davranışını tek bir adımda dahi bozmadan, otomatik araçların güvencesiyle nasıl on parçaya böleceğinizi adım adım göstermek ise gerçek iştir. Bizim hedefimiz ikincisidir.
Refactoring Nedir? — Bir İlk Bakış
Bir tanımla başlayalım, çünkü bu serinin tamamı bu tanımın iki kelimesinin üzerine kuruludur. Martin Fowler’ın klasikleşmiş tanımıyla refactoring, “bir yazılımın gözlemlenebilir davranışını değiştirmeden, iç yapısını değiştirerek anlaşılmasını kolaylaştırmak ve değiştirme maliyetini düşürmek için yapılan disiplinli bir tekniktir.” Bu cümlede iki ifade altı çizili olmayı hak eder: “gözlemlenebilir davranışı değiştirmeden” ve “disiplinli teknik”. Refactoring’i kodu kurcalamaktan, “temizlik yapmaktan” veya gelişigüzel yeniden yazmaktan ayıran şey tam olarak bu ikisidir.

Fowler aslında “refactoring” kelimesini hem bir isim hem de bir fiil olarak iki ayrı anlamda kullanır ve bu ayrımı kavramak kritiktir. İsim olarak bir “refactoring”, kodun yapısını değiştiren ama davranışını koruyan, isimlendirilmiş ve adımları kataloglanmış küçük bir dönüşümdür — örneğin “Extract Function” veya “Rename Variable”. Fiil olarak “refactoring yapmak” ise, bu küçük dönüşümlerden bir dizisini art arda uygulayarak kodu istenen hâle getirme sürecidir. Bu ayrım önemlidir, çünkü iyi refactoring büyük bir hamleyle değil, her biri tek başına önemsiz görünen onlarca minik ve güvenli adımın birikimiyle gerçekleşir. Tıpkı bir heykeltıraşın mermerden tek bir darbeyle değil, binlerce küçük yontmayla figür çıkarması gibi.
Burada en sık yapılan kavram karmaşasını şimdiden çözelim. Refactoring, davranışı değiştiren her türlü kod düzenlemesi demek değildir. Eğer bir hata düzeltiyorsanız, bu refactoring değildir — çünkü gözlemlenebilir davranışı değiştiriyorsunuz (kötü davranışı iyiyle değiştiriyorsunuz, ama yine de değiştiriyorsunuz). Eğer yeni bir özellik ekliyorsanız, bu da refactoring değildir. Eğer kodu hızlandırmak için algoritmayı değiştiriyorsanız, bu performans optimizasyonudur ve gözlemlenebilir bir davranış olan “yanıt süresini” değiştirdiği için saf refactoring sayılmaz. Refactoring, davranış sabit kalırken yapının iyileşmesidir — başka hiçbir şey değil.
Aşağıdaki diyagram, bu sınırları görselleştiriyor. Kodu değiştirmenin dört temel sebebi vardır ve refactoring bunlardan yalnızca biridir:

Bu ayrımın pratikteki değeri şudur: Bir refactoring oturumunda hiçbir şüpheniz olmaz. “Bu testler az önce yeşildi, hâlâ yeşil mi?” sorusunun cevabı her zaman “evet” olmalıdır. Eğer bir noktada bir test kırmızıya dönerse, ya yaptığınız şey refactoring değildir ya da bir hata yapmışsınızdır — ve her iki durumda da derhal durup geri almanız gerekir. Bu netlik, refactoring’i mühendislik yapan şeydir; tahmin değil, kontrol vardır.
“İki Şapka” — Kent Beck’in Metaforu
Refactoring konusundaki belki de en güçlü zihinsel model, Kent Beck’in “iki şapka” metaforudur. Bu metafor, deneyimli mühendisleri amatörlerden ayıran o sessiz disiplini kelimelere döker. Beck der ki: Yazılım geliştirirken her an iki şapkadan yalnızca birini takarsınız. Birincisi “yeni özellik ekleme” şapkasıdır; bu şapkayı taktığınızda kod tabanına yeni yetenekler eklersiniz, bunu yaparken yeni testler yazarsınız ve testlerin önce kırmızı sonra yeşil olmasını izlersiniz. İkincisi ise “refactoring” şapkasıdır; bu şapkayı taktığınızda hiçbir yeni yetenek eklemezsiniz, hiçbir yeni test yazmazsınız (çünkü davranış değişmiyor), yalnızca yapıyı iyileştirirsiniz ve mevcut testlerin baştan sona yeşil kalmasını beklersiniz.
Bu metaforun gücü, bir kuralda gizlidir: Aynı anda iki şapkayı birden takamazsınız. Profesyonel olmayan kodun büyük kısmı tam olarak bu kuralın ihlalinden doğar. Bir mühendis “şu özelliği eklerken bir de şu metodu biraz düzeltivereyim” der ve farkında olmadan iki işi birbirine karıştırır. Sonuç, hem riskli hem de okunması imkânsız bir değişikliktir: Kod gözden geçirmede (code review) inceleyen kişi, yapısal değişikliklerle davranışsal değişiklikleri ayırt edemez; bir hata çıktığında bunun yeni özellikten mi yoksa “düzeltmeden” mi geldiği belirsizdir; ve geri almak (revert) gerektiğinde temiz bir nokta yoktur. İki şapkayı ayırmak, sadece bir tarz tercihi değil, risk yönetimidir.
Pratikte bu şöyle işler: Diyelim ki yeni bir özellik eklemeniz gerekiyor ve mevcut kodun yapısı buna elverişli değil. Beck’in tavsiyesi nettir — önce refactoring şapkasını takıp kodu, değişikliğin kolay olacağı bir hâle getirirsiniz (bu adım çoğu zaman zordur), sonra şapkayı değiştirip özellik şapkasıyla artık kolaylaşmış değişikliği yaparsınız. Bu sıralama tesadüfi değildir; “önce zemini hazırla, sonra inşa et” prensibinin yazılımdaki karşılığıdır. Bu seride sürekli geri döneceğimiz bir ritim olacak bu.

Bu iki şapka disiplinini bir kez içselleştirdiğinizde, kod tabanınızdaki commit geçmişi bile değişir. Karışık, “şunu yaptım bir de bunu düzelttim” tarzı dev commit’ler yerine, her biri net bir niyet taşıyan küçük commit’ler görürsünüz: “refactor: extract odds calculation into separate method”, ardından “feat: add live odds adjustment”. Bu disiplin Bölüm 23'te versiyon kontrol pratiklerini işlerken merkezimizde olacak.
Davranış Korunumu: Refactoring’in Değişmez Yasası
Eğer bu serinin tek bir cümlesini hatırlayacaksanız, o cümle şu olmalı: Refactoring, davranış korunumu garantisi altında yapılır. Bu, fizikteki enerji korunumu yasası kadar katı bir kuraldır ve refactoring’i “kodu kurcalamaktan” ayıran tek şeydir. Davranışı korumak demek, refactoring öncesi ve sonrası kodun, her girdi için aynı çıktıyı, aynı yan etkileri ve aynı hata davranışını üretmesi demektir. Dışarıdan bakan hiçbir gözlemci — ne bir kullanıcı, ne bir API tüketicisi, ne bir test — kodun değiştiğini fark edememelidir. Değişen tek şey, kodun içine bakan mühendisin gördüğü manzaradır.
Şimdi dürüst olmamız gereken bir nokta var: “Gözlemlenebilir davranış” ifadesi göründüğünden daha incelikli bir kavramdır. Bir metodun dönüş değeri açıkça gözlemlenebilir davranıştır. Peki ya bir logladığı satır? Ya yan etki olarak bir veritabanı kaydını değiştirmesi? Ya bir istisna (exception) fırlatması — ve fırlattığı istisnanın tam tipi? Ya çağrılma sırası? Genel kural şudur: Bir sistemin bağımlı olduğu her şey gözlemlenebilir davranıştır. Eğer hiçbir test ve hiçbir tüketici bir metodun log ürettiğine bağımlı değilse, o log davranışın bir parçası sayılmayabilir; ama bir başka sistem o logu parse ederek çalışıyorsa, o log artık kutsal bir sözleşmedir. Bu yüzden refactoring’in derin ustalığı, bir kodun “gerçek sözleşmesinin” nerede başlayıp nerede bittiğini görebilmektir. Bunu Bölüm 14'te API sözleşmeleri bağlamında derinlemesine ele alacağız.
Bu yasayı pratikte uygulayan güç ise testlerdir. İşte refactoring’in en sık atlanan ön koşulu burada yatar: Güvenilir bir test takımı olmadan, “davranışı korudum” iddiası bir temenniden ibarettir. Çünkü davranışın korunduğunu kanıtlayan tek mekanizma, refactoring öncesinde yeşil olan testlerin sonrasında da yeşil kalmasıdır. Test yoksa, kanıt da yoktur; geriye sadece umut kalır, ve umut bir mühendislik stratejisi değildir. Bu yüzden bu seri, refactoring kataloğuna girmeden önce Bölüm 4'ün tamamını test güvenlik ağına ayırır. Test edilemeyen legacy kodun nasıl test edilebilir hâle getirileceği — yani Michael Feathers’ın “seam” kavramı — ise Bölüm 17'nin konusudur.
Aşağıdaki Java örneği, davranış korunumunu somutlaştırıyor. Önce bir “Extract Method” refactoring’i öncesi ve sonrasını görelim. Dikkat edin: Hesaplanan değer, fırlatılabilecek istisnalar ve dönüş tipi birebir aynıdır — değişen tek şey okunabilirliktir.
// ÖNCESİ — her şey tek metotta, niyet gizli
public Money hesaplaBahisTutari(Bahis bahis) {
// oran doğrulama
if (bahis.getOran() == null || bahis.getOran().compareTo(BigDecimal.ONE) < 0) {
throw new GecersizOranException(bahis.getId());
}
// taban tutar hesabı
BigDecimal taban = bahis.getMiktar().multiply(bahis.getOran());
// komisyon kesintisi
BigDecimal komisyon = taban.multiply(new BigDecimal("0.05"));
BigDecimal net = taban.subtract(komisyon);
return Money.of(net, bahis.getParaBirimi());
}
// SONRASI — aynı davranış, açık niyet (Extract Method x3)
public Money hesaplaBahisTutari(Bahis bahis) {
dogrulaOran(bahis);
BigDecimal taban = hesaplaTabanTutar(bahis);
BigDecimal net = komisyonDus(taban);
return Money.of(net, bahis.getParaBirimi());
}
private void dogrulaOran(Bahis bahis) {
if (bahis.getOran() == null || bahis.getOran().compareTo(BigDecimal.ONE) < 0) {
throw new GecersizOranException(bahis.getId());
}
}
private BigDecimal hesaplaTabanTutar(Bahis bahis) {
return bahis.getMiktar().multiply(bahis.getOran());
}
private BigDecimal komisyonDus(BigDecimal taban) {
BigDecimal komisyon = taban.multiply(new BigDecimal("0.05"));
return taban.subtract(komisyon);
}
İki versiyon da aynı girdi için aynı Money nesnesini döndürür, aynı koşulda aynı GecersizOranException'ı fırlatır ve hiçbir yeni yan etki üretmez. İşte davranış korunumu budur. "Sonrası" versiyonunun okunabilirliği niçin daha yüksek? Çünkü hesaplaBahisTutari metodu artık tek bir soyutlama seviyesinde konuşuyor: doğrula, taban hesapla, komisyon düş. Ayrıntılar, isimlendirilmiş alt metotlara çekildi. Bu, "kompozisyon" refactoringlerinin kalbidir ve Bölüm 10'un tamamını buna ayıracağız.

Çalışan örnek kodlara erişmek için: » https://gitlab.com/sahin.yelkenci2/refactoring-canli-bahis
Refactoring, Tasarım ve Test Üçgeni
Refactoring tek başına yaşayan bir pratik değildir; iki kardeş disiplinle — otomatik testler ve evrimsel tasarım — ayrılmaz bir üçgen oluşturur. Bu üçgeni anlamadan refactoring’i anlamak, bir bisikletin sadece tek tekerleğini incelemek gibidir. Üçgenin mantığı şudur: Testler size davranışı koruduğunuza dair güven verir; bu güven sayesinde cesaretle refactoring yaparsınız; refactoring kodun tasarımını sürekli temiz tutar; temiz tasarım yeni testler yazmayı ve yeni özellik eklemeyi kolaylaştırır; ve bu döngü kendini besler. Üçgenin herhangi bir kenarı zayıfsa, diğer ikisi de çöker. Testsiz refactoring körlemesine yürümektir; refactoring’siz testler ise zamanla taşlaşmış, dokunulamaz bir kod tabanını koruyan müzayede güvenliğine dönüşür.
Bu üçlü ilişki, *Test-Driven Development’ın (TDD) o meşhur “Red-Green-Refactor” döngüsünde en saf hâliyle görünür. *Önce başarısız bir test yazarsınız (red), sonra onu geçecek en basit kodu yazarsınız (green), sonra da o kodun yapısını — testler yeşilken — iyileştirirsiniz (refactor). Refactoring adımı bu döngünün vazgeçilmez üçüncü ayağıdır; pek çok ekibin atladığı ve bu yüzden TDD’den umduğu tasarım kalitesini bir türlü elde edemediği ayak da budur. Bu seri TDD serisinin doğal bir devamı sayılabilir: Orada testin kendisine, burada o testlerin koruması altında yapılan tasarım evrimine odaklanıyoruz.

Burada altını çizmek istediğim incelikli bir nokta var: Refactoring, “büyük önden tasarım” (Big Design Up Front) felsefesine bir alternatiftir. Geleneksel görüş, doğru tasarımı en başta, kod yazılmadan önce bulmanız gerektiğini söyler. Refactoring’in dünya görüşü ise daha alçakgönüllüdür: Doğru tasarımı baştan bilemezsin, çünkü gereksinimler değişir ve problemi ancak çözmeye başlayınca gerçekten anlarsın. O hâlde yapman gereken, tasarımı kodla birlikte sürekli evrimleştirmek için kendine güçlü bir refactoring yeteneği kazandırmaktır. Bu görüşün kurucu metinlerinden biri Fowler’ın “Is Design Dead?” makalesidir; orada savunulan tez, refactoring’in iyi tasarımı öldürmediği, aksine onu mümkün kıldığıdır. Tasarım ölmedi — sadece bir defalık bir etkinlik olmaktan çıkıp sürekli bir pratiğe dönüştü.
Değişim Maliyeti ve Teknik Borç — Refactoring’in Ekonomisi
Refactoring’in neden yapıldığını gerçekten kavramak için, onu estetik bir tercih olarak değil, ekonomik bir karar olarak görmek gerekir. Kötü tasarımın bedeli soyut bir “çirkinlik” değildir; çok somut bir para birimiyle ölçülür: her değişikliğin maliyeti. Temiz tasarımlı bir sistemde bir özelliği eklemek bir gün sürerken, çürümüş bir sistemde aynı özellik bir hafta sürebilir. İşte bu fark, kötü tasarımın gerçek faturasıdır ve her sprint, her ay, her çeyrek tekrar tekrar ödenir.

Bu fenomeni anlatan en güçlü metafor, Ward Cunningham’ın ortaya attığı “teknik borç”tur (technical debt). Tıpkı finansal borç gibi, teknik borç da bazen akıllıca alınan bir karardır: Bir özelliği pazara hızlı yetiştirmek için kasıtlı olarak kestirme bir çözüm yazarsınız, tıpkı bir işi büyütmek için kredi çekmek gibi. Sorun borcun kendisi değil, faizidir. Teknik borcun faizi, o kestirme çözümün üzerine inşa ettiğiniz her yeni özelliğin biraz daha zorlaşması, biraz daha çok zaman almasıdır. Ve finansal borçtan farklı olarak, teknik borcun faizini görmezden gelmek onu yok etmez; bileşik faiz gibi büyür. Refactoring, bu borcu geri ödeme eylemidir. Bir takımın olgunluğu, hangi borcu bilerek aldığını, hangisinin faizinin tehlikeli biçimde biriktiğini ve ne zaman geri ödemesi gerektiğini bilmesiyle ölçülür.
Burada kritik bir ekonomik kavrayış var: “Tasarım Dayanıklılığı Hipotezi” (Design Stamina Hypothesis). Fowler’ın gözlemine göre, kısa vadede özensiz kod yazmak hızlı görünür — ilk birkaç özellik gerçekten de daha çabuk teslim edilir. Ama bir eşik noktasından sonra, iyi tasarımın kümülatif hızı özensiz kodu geçer ve aradaki makas giderek açılır. Yani “düzgün yazmaya vaktimiz yok” cümlesi, neredeyse her zaman matematiksel olarak yanlıştır; çünkü o eşik, çoğu projede sanılandan çok daha erken gelir — genellikle haftalar içinde. Refactoring, sistemi bu hipotezin “iyi tasarım” eğrisinde tutma disiplinidir.
Aşağıdaki diyagram, teknik borcun nasıl bir kısır döngüye dönüştüğünü gösteriyor. Bu döngü kendiliğinden durmaz; onu kıran tek müdahale bilinçli refactoring’dir:

Bu ekonomik bakış, refactoring’i yöneticilere ve ürün sahiplerine anlatırken de elinizdeki en güçlü silahtır. “Kodu güzelleştireceğim” demek bütçe almaz; “bu modüldeki değişiklik maliyetini yarıya indireceğim, böylece önümüzdeki çeyrekteki üç özelliği iki yerine bir sprintte teslim edebileceğiz” demek alır. Bölüm 3'ün tamamı bu ekonomik dile, teknik borcu nasıl ölçeceğinize ve refactoring yatırımının getirisini (ROI) nasıl gerekçelendireceğinize ayrılmıştır.
Bu Seri Kimin İçin? — Ön Koşullar ve Kazanımlar
Bu seri, kod yazmayı yeni öğrenenler için bir başlangıç kitabı değildir. Hedef kitlemiz, halihazırda üretim koduyla boğuşan, bir kod tabanının zamanla nasıl çürüdüğünü ilk elden yaşamış ve “bunun daha iyi bir yolu olmalı” diyen mühendislerdir. Daha somut söylersek: Kıdemli geliştiriciler (Senior Developers), takım liderleri (Tech Leads) ve yazılım mimarları (Software Architects) için tasarlanmıştır. Eğer bir sınıfın ne olduğunu, kalıtımla kompozisyon arasındaki farkı ve bir birim testinin nasıl yazıldığını biliyorsanız, bu serinin gerektirdiği zemin sizde var demektir.
Diliniz Java olmak zorunda değil. Örneklerin büyük çoğunluğunu Java ile vereceğiz, çünkü Java’nın tip sistemi ve olgun IDE araçları, otomatik refactoring’in gücünü göstermek için ideal bir tuval sunuyor. Ancak refactoring kataloğundaki her dönüşüm dilden bağımsızdır; “Extract Function” bir Java metodunda da, bir PHP fonksiyonunda da, bir TypeScript dosyasında da aynı mantıkla işler. Bu yüzden örnekleri okurken sözdizimine değil, altında yatan dönüşümün mekaniğine odaklanın. Yüksek işlem hacimli (TPS) ve eşzamanlı sistemler bağlamındaki ileri örnekler ise, gerçek dünyanın acımasız performans ve doğruluk gereksinimlerini refactoring disipliniyle nasıl bağdaştıracağınızı gösterecek; bu konuyu Bölüm 21'de derinlemesine ele alacağız.
Bu seriyi tamamladığınızda elde edeceğiniz somut yetenekler şunlardır. Bir kod tabanına baktığınızda, “kokuları” (code smells) refleks hâline gelmiş bir gözle anında teşhis edebileceksiniz; her kokuya karşılık gelen kataloglanmış refactoring’i bileceksiniz; bir 1000 satırlık dev metodu, davranışını tek bir adımda dahi bozmadan, küçük ve geri alınabilir hamlelerle parçalayabileceksiniz; testi olmayan legacy bir koda nasıl güvenle “tutamak” (seam) açacağınızı bileceksiniz; ve belki en önemlisi, refactoring’i ne zaman yapmamanız gerektiğini — çünkü her kötü kod refactor edilmeyi hak etmez — yargılayabileceksiniz. Bu son yetkinlik, ustalığın gerçek işaretidir ve Bölüm 25'te onurlandırılacaktır.
Serinin Yazım Metodolojisi — Bir Bölüm Nasıl Okunmalı
Bu serinin her bölümü bilinçli ve tutarlı bir pedagojik ritimle yazılmıştır; bu ritmi şimdiden bilmeniz, içeriği daha hızlı sindirmenizi sağlar. Her kavram dört katmanda işlenir ve bu katmanların sırası tesadüfi değildir. Önce kavram, öğretmen sesiyle, düz anlatımla açıklanır — bir analoji, bir “neden önemli” gerekçesi ve zihinsel modelin kurulması. Bu katman bilerek madde imleriyle değil, akan paragraflarla yazılır; çünkü bir fikrin “neden”ini madde madde sıralamak, onu anlamak değil, ezberlemektir. İkinci katmanda kavram somut kodla — çoğunlukla “öncesi/sonrası” karşılaştırmasıyla — elle tutulur hâle gelir. Üçüncü katmanda bir Mermaid diyagramı, kurulan zihinsel modeli görsel bir özetle çiviler. Dördüncü ve gerektiğinde devreye giren katman ise iyi/kötü örnek kıyasıdır; bir refactoring’in nereye kadar gidip nerede durması gerektiğini gösterir.

Bu sıralamanın özellikle bir kuralı var ki, onu burada açıkça belirtmek isterim: Diyagram her zaman anlatımdan sonra gelir, asla önce değil. Çünkü bir diyagram, ancak zihninizde önce bir model kurulduktan sonra o modeli pekiştirir; model yokken gösterilen bir diyagram ise anlamsız kutular ve oklar yığınından ibarettir. Bu yüzden bir bölümü okurken, diyagrama gelmeden önce kendinize “bu kavramı kendi cümlelerimle anlatabiliyor muyum?” diye sorun. Cevap evetse, diyagram sizin için bir ödül olur; hayırsa, paragrafa geri dönün.
Her bölüm aynı çatı altında ilerler: motive edici bir açılış, teknik gövde, görsel diyagramlar, ve sonunda üç tane “Üç Gözlem Sorusu”. Bu sorular sınav değildir; okuduğunuzu kendi kod tabanınıza taşımanızı sağlayan köprülerdir. Her bölüm ayrıca felsefi bir kapanış cümlesiyle ve bir sonraki bölüme uzanan bir köprüyle biter. Bölümler arası göndermeler metin içinde sade bir ↗ okuyla yapılır; bir konuyu burada yüzeysel geçip ileride derinleştireceksek, sizi o durağa bu okla yönlendiririz.
Serinin Yol Haritası — Beş Kısımda Yolculuk
Şimdi önümüzdeki yolculuğun haritasını açalım. Seri, birbirinin üzerine inşa edilen beş kısımdan oluşur ve bu sıralama önemlidir; her kısım bir öncekinin kurduğu zemine basar.

Kısım I — Temeller, refactoring’in ne olduğunu, nereden geldiğini, neden yapıldığını ve onsuz yapılamayacağı tek koşulu (testler) inşa eder. Bu kısmı atlamak, bir binayı temelsiz çatıdan başlamak gibidir; burada kurulan kavramsal çerçeve, geri kalan her şeyin dilini belirler. ↗ Bölüm 1'den ↗ Bölüm 4'e kadar uzanır.

Kısım II — Teşhis, bir cerrahın hastayı muayene etmesi gibi, kötü kodu tanıma sanatına odaklanır. Fowler ve Beck’in kataloglaştırdığı “code smell” taksonomisini üç bölüme yayarak — metot düzeyi, sınıf/veri düzeyi ve yapısal düzey — sistematik biçimde işleriz. Sonra Bölüm 8'de bu sezgisel kokuları, ölçülebilir metriklere (cyclomatic complexity, afferent/efferent coupling, LCOM kohezyon ölçütü) bağlarız. Çünkü “bu kod kötü kokuyor” demek bir sanat, “bu metodun cyclomatic complexity’si 34” demek bir bilimdir; ustalık ikisini birleştirmektir.

Kısım III — Katalog, serinin kalbidir. Burada refactoring’in gerçek mekaniğine ineriz. Önce bir refactoring’in nasıl yazıldığını — isim, motivasyon, mekanik, örnek — Bölüm 9'da çözümleriz, sonra altı bölüm boyunca kataloğun ailelerini tek tek, adım adım uygularız: metot kompozisyonu, nesneler arası taşıma, veri organizasyonu, koşul sadeleştirme, API refactoringleri ve kalıtım hiyerarşileri. Bu kısmı bitirdiğinizde, elinizde her duruma karşı kullanabileceğiniz, ezberlenmiş değil içselleştirilmiş bir dönüşüm cephaneliği olacak.

Kısım IV — Büyük Resim, refactoring’i tek bir metottan çıkarıp sistem ölçeğine taşır. Aylar süren büyük dönüşümleri sistemi çalışır tutarak nasıl yöneteceğinizi (Branch by Abstraction), testi olmayan legacy kodla nasıl savaşacağınızı (Feathers’ın seam ve karakterizasyon testleri), refactoring’i bilinçli olarak tasarım desenlerine doğru nasıl yönlendireceğinizi (Kerievsky), mimari düzeyde modülerleşmeyi (Strangler Fig), şema evrimini ve yüksek TPS sistemlerinin özel zorluklarını işleriz. Burası, kıdemli mühendisi mimardan ayıran düzeydir.

Kısım V — Pratik ve Kültür, tüm bu bilgiyi sürdürülebilir bir günlük disipline dönüştürür. IDE’nin otomatik refactoring araçlarının gerçekte nasıl çalıştığı ve neden manuel düzenlemeden daha güvenli olduğu, versiyon kontrolüyle kurulan küçük-commit disiplini, code review ve “İzci Kuralı” (Boy Scout Rule) etrafında bir takım kültürü kurmak, ve en olgun bölüm olarak — refactoring’in tuzakları ve onu ne zaman yapmamanız gerektiği. Çünkü disiplinsiz refactoring, hiç refactoring yapmamaktan daha tehlikeli olabilir.

Bu Seriyi Diğerlerinden Ayıran Ne?
Refactoring üzerine yazılmış pek çok kaynak vardır ve bunların önemli bir kısmı, kataloğun maddelerini bir sözlük gibi sıralar: “Extract Method şudur, Inline Variable budur.” Bu seri bilinçli olarak farklı bir yol seçiyor. Birincisi, biz kataloğu ezberlenecek bir liste olarak değil, bir dil olarak öğretiyoruz; tıpkı satranç açılışlarını tek tek ezberlemek yerine, açılış prensiplerini kavrayan bir oyuncunun yeni pozisyonlarda da doğru hamleyi bulabilmesi gibi. Amacımız, daha önce hiç görmediğiniz bir kötü kod karşısında bile hangi dönüşümün gerektiğini sezebilmeniz.
İkincisi, bu seri “neden”e takıntılıdır. Her refactoring’in mekaniğini gösterirken, onu ne zaman uygulamanız ve daha da önemlisi ne zaman uygulamamanız gerektiğini de tartışırız. Çünkü her aracın bir maliyeti vardır ve gereksiz soyutlama, gereksiz karmaşıklık kadar zararlıdır. “Speculative Generality” — yani belki bir gün lazım olur diye eklenen soyutlama — bir code smell’dir, ve aşırı hevesli refactoring tam da bunu üretir. Olgunluk, ne zaman duracağını bilmektir.
Üçüncüsü, bu seri gerçek dünyanın kirini görmezden gelmez. Ders kitaplarındaki temiz örnekler güzeldir ama profesyonel hayat öyle değildir; siz testi olmayan, on yıllık, kimsenin tam anlamadığı, ama gece yarısı milyonlarca işlem akıtan bir sisteme dokunmak zorunda kalacaksınız. Bu serinin Büyük Resim kısmı, tam da bu “korkutucu” senaryoları merkezine alır. Yüksek TPS, eşzamanlılık, dağıtık veri ve canlı sistemlerde sıfır kesinti gibi gerçek kısıtlar altında refactoring yapmayı öğreteceğiz — çünkü asıl ustalık, steril laboratuvarda değil, çalışan motorun parçalarını yolda giderken değiştirebilmektedir.
Üç Gözlem Sorusu
Her bölümü, okuduklarınızı kendi gerçekliğinize taşımanız için üç soruyla kapatacağız. İşte bu serinin ilk üçü; cevaplarını şimdi bir kenara not edin, çünkü seriyi bitirdiğinizde aynı sorulara çok farklı cevaplar vereceksiniz:
Birinci Gözlem Sorusu. Şu an üzerinde çalıştığınız kod tabanında, son altı ayda en çok hangi dosyaya/sınıfa dokundunuz? O dosyayı açıp şu soruyu dürüstçe yanıtlayın: Buradaki son değişikliğiniz “korkarak” mı yoksa “güvenle” mi yapıldı? Eğer korkuyla yapıldıysa, davranış korunumunu garanti edecek testler orada mıydı — yoksa sadece dikkatli olmaya mı güvendiniz?

İkinci Gözlem Sorusu. Takımınızda en son ne zaman birisi “burayı sıfırdan yazmamız lazım” dedi? O cümlenin arkasındaki gerçek sorun neydi — kodun davranışı mı yanlıştı, yoksa yapısı mı değiştirilemez hâle gelmişti? İkincisiyse, o sistem bir rewrite’a değil, disiplinli bir refactoring kampanyasına aday olabilir mi?

Üçüncü Gözlem Sorusu. Son bir ayda yaptığınız commit’lere bakın. Kaç tanesi “iki şapkayı” karıştırıyor — yani aynı commit’te hem yeni davranış hem de yapısal düzenleme barındırıyor? Bu commit’leri ikiye bölmek mümkün olsaydı, code review yapan arkadaşınızın işi ne kadar kolaylaşırdı?

Kapanış — Bir Felsefe
Refactoring’i bir teknik beceri olarak öğrenmek mümkündür ve bu serinin büyük kısmı tam da bunu yapacak: mekanikleri, kataloğu, araçları öğreteceğiz. Ama refactoring’in özünde teknik değil, ahlaki bir tutum yatar — geleceğe ve gelecekteki insanlara karşı duyulan bir sorumluluk. Yazdığınız kodu okuyacak olan, büyük olasılıkla altı ay sonraki, bağlamı unutmuş hâlinizdir; ya da hiç tanımadığınız, sizin bıraktığınız enkazı temizlemek zorunda kalacak bir meslektaşınızdır. Refactoring, o kişiye gösterdiğiniz nezakettir.

Bu yüzden bu seriyi, sektörün en bilinen ama en az uygulanan iki cümlesiyle açıyoruz. İlki Martin Fowler’dan: Herhangi bir aptal, bir bilgisayarın anlayabileceği kod yazabilir; iyi programcılar ise insanların anlayabileceği kod yazar. İkincisi Kent Beck’ten, ve belki de tüm serinin tek cümlelik özetidir: Önce değişikliği kolay hâle getir — ki bu kısım çoğu zaman zordur — sonra o artık kolaylaşmış değişikliği yap. İşte refactoring, o ilk cümlenin “kolay hâle getirme” kısmının disiplinli adıdır. Geri kalan her şey, bu iki cümlenin nasıl yapılacağının ayrıntısıdır.
Hazırsanız, lafı uzatmadan işin doğasına inelim. Çünkü refactoring hakkında konuşmak değil, onu yapmak öğretir.
Sonraki Bölüm
↗ Bölüm 1: Refactoring Nedir, Ne Değildir? — Tanım, İki Şapka ve Davranış Korunumu’nda, bu giriş bölümünde yüzeyine değindiğimiz tanımı cerrahi bir kesinlikle parçalarına ayıracağız. Fowler’ın tanımındaki her kelimeyi ayrı ayrı sorgulayacak, “gözlemlenebilir davranış” kavramının görünmez sınırlarını çizecek, ve ilk gerçek refactoring’imizi — adım adım, her ara durakta testleri çalıştırarak — birlikte uygulayacağız. Mermerin içindeki figürü görmeye başlıyoruz.
**» Sonraki **[Bölüm 1: Refactoring Nedir, Ne Değildir? — Tanım, İki Şapka ve Davranış Korunumu] » https://gitlab.com/sahin.yelkenci2/refactoring-canli-bahis
메타데이터
- post_id
- a3c470577aba
- slug
- refactoring-mevcut-kodun-tasarımını-i̇yileştirme-sanatı-giriş-bölümü-a3c470577aba
- url
- https://medium.com/@sahinyelkenci/refactoring-mevcut-kodun-tasar%C4%B1m%C4%B1n%C4%B1-i%CC%87yile%C5%9Ftirme-sanat%C4%B1-giri%C5%9F-b%C3%B6l%C3%BCm%C3%BC-a3c470577aba
- canonical_url
- https://medium.com/@sahinyelkenci/refactoring-mevcut-kodun-tasar%C4%B1m%C4%B1n%C4%B1-i%CC%87yile%C5%9Ftirme-sanat%C4%B1-giri%C5%9F-b%C3%B6l%C3%BCm%C3%BC-a3c470577aba
- author_url
- https://medium.com/@sahinyelkenci
- status
- ok
- fetched_at
- 2026-07-24 23:22:17