Code Smell ve Refactoring — Davranışı Değiştirmeden Değiştirmek
Önce şunu oku: Temiz Kod — İsimler, Fonksiyonlar, Yorumlar
30 saniyede özet
Code smell bir hata değil, 'buraya bir bak' diyen bir ipucudur. Refactoring kodun davranışını aynı bırakıp düzenini değiştirmektir; aynı kaldığını testler kanıtlar. Küçük adım at, her adımda test et.
“Sadece biraz topladım” denilen bir değişiklik yayına alındı. Bir hafta sonra muhasebe bazı faturalarda bir kuruş fark buldu. Temizlik, fark ettirmeden bir davranışı değiştirmişti.
Adım adım oku
- Önce kodun bugün ne yaptığını olduğu gibi sabitleyen testler yazılır: bir güvenlik ağı.
- Her küçük düzenlemeden sonra testler çalışır ve yeşil kalır. Sonra bir adım daha.
- Tek büyük sıçramada isim, yuvarlama ve sıralama birlikte değişir. Test kırmızı, ama hangisi yüzünden?
- Küçük adımlarda kırmızı test tek bir değişikliği gösterir; sebep hemen bellidir.
-
Bayt: Sadece biraz topladım, davranışa hiç dokunmadım. Yayına aldık.
-
Sen: Bir hafta sonra muhasebe aradı: bazı faturalarda bir kuruş fark varmış.
-
Bayt: Nasıl yani? Ben sadece düzenlemiştim!
-
Bayt: Davranışın aynı kaldığını neyle kanıtladın? Asıl soru bu.
Koku bir ipucudur, hata değil
Bir code smellKodda daha derin bir tasarım sorununa işaret edebilen, kendisi hata olmayan bir belirti: uzun metot, tekrar, anlamsız isim. Teşhis değil, bakılacak yeri gösteren bir ipucu.Sözlükte gör → kendisi hata değildir. Daha derin bir tasarım sorununun nerede olabileceğini gösterir.
| Smell | Belirti | Genelde çözümü |
|---|---|---|
| Uzun metot | Yorumlarla bölümlere ayrılmış gövde | Extract Method |
| feature envyBir metodun kendi sınıfından çok başka bir sınıfın verisiyle uğraşması. Genelde o davranışın verinin durduğu sınıfa taşınması gerektiğini gösterir.Sözlükte gör → | Başka sınıfın getter’larıyla dolu metot | Move Method |
| Primitive obsession | Hep birlikte gezen amount ve currency | Değer nesnesi |
| Anlamsız isim | d, tmp, data2 | Rename |
Kafam karıştı, daha basit anlat
Code smell, buzdolabından gelen tuhaf bir koku gibidir. Kokunun kendisi sorun değildir, ama içeride bir şeyin bozulduğunu haber verir.
Refactoring'i herhangi bir kod değişikliğinden ayıran şey nedir?
Her smell'i genelde onu gideren refactoring ile eşleştir.
Davranış aynı kalır
refactoringKodun dışarıdan görülen davranışını değiştirmeden iç yapısını küçük, güvenli adımlarla değiştirmek. Davranış değişiyorsa artık refactoring değildir.Sözlükte gör → yapıyı değiştirir, davranışı değil. Bu bir iddiadır ve iddiayı doğrulayan şey testlerdir.
Para hesabını double'dan BigDecimal'e geçirdin ve HALF_EVEN yuvarlama seçtin. Kod daha doğru. Bu bir refactoring mi? Cevabı göster
Hayır. 10,125 TL eskiden 10,13 idi, şimdi 10,12. Sonuç değişiyorsa davranış değişmiştir — belki doğru bir değişiklik, ama ayrı ve bilinçli yapılmalı.
Testi olmayan kodda ilk adım, bugünkü davranışı kaydeden bir karakterizasyon testiLegacy kodun doğru olduğunu değil, şu an ne yaptığını kaydeden test. Yanlış davranışı da sabitler — amaç değişikliğin neyi bozduğunu görebilmektir.Sözlükte gör → yazmaktır. Doğruyu değil, olanı sabitler.
Kafam karıştı, daha basit anlat
Refactoring, odayı toplamaktır: eşyalar yer değiştirir ama hiçbiri kaybolmaz. Testler, toplarken hiçbir şeyin kaybolmadığını gösteren listedir.
Para hesaplarında `double`'dan `BigDecimal`'e geçerken yuvarlama modu da değişti. Bu değişiklik bir refactoring midir?
Testi olmayan eski bir sınıfı değiştirmen gerekiyor. İlk adım ne olmalı?
Kendin gör
Refactoring — küçük adımlar ve güvenlik ağı
Tohum 846929- checkout() satır48
- Kalan smell4
- Doğrulanmamış değişiklik0
- Oynat ya da adımla.
Şu an ne oldu?
checkout(): 48 satır, 4 smell
Dört temizlik hamlesi planlandı. Biri masum görünüyor ama bir sonucu 1 kuruş değiştiriyor.
Görevler0/3
Bir davranış değişikliğini "temizlik" diye yayına çıkaraçık
İpucu
Kimsenin fark etmesi için bir mekanizma olmasın.
Testler kırmızı olsun ama hangi değişikliğin bozduğu belli olmasınaçık
İpucu
Güvenlik ağı var, ama değişiklikler tek bir büyük adımda.
Davranış değişikliğini yaptığın anda yakalaaçık
İpucu
Test + her hamleden sonra çalıştırmak.
Olay günlüğü (0)
Henüz olay yok. Oynat veya adımla.
- Varsayılanla oynat. Test yok, hepsi tek seferde: kod temiz, kuruş farkı yayında.
- Testleri aç. Kırmızı — ama dört değişiklikten hangisi?
- “Her adımdan sonra test” seç. Kırmızı yalnızca dördüncü adımda, suçlu belli.
- Testleri kapat, küçük adımları bırak. Adım küçük ama kimse bakmıyor.
Refactoring'de "küçük adımlar" neden bu kadar vurgulanır?
Satır satır: kuralı verinin yanına taşımak
Feature envy'den Move Method'a
BigDecimal discountFor(Order order) { var customer = order.getCustomer(); if (customer.getTier() == GOLD && customer.getYears() > 3) { return order.getTotal().multiply(RATE_15); } if (customer.getTier() == GOLD) { return order.getTotal().multiply(RATE_10); } return BigDecimal.ZERO;}Debug
okuyucu Karar tamamen Customer'ın verisine dayanıyor. OrderService bu kuralı neden biliyor?
Sol/sağ ok tuşlarıyla da gezebilirsin.
Her hamle tek başına ve testle doğrulandı. Sonuç aynı; değişen yalnızca kuralın nerede durduğu.
Aynı hamleyi bir bankanın EFT ücretiyle deneyelim. Önce bugünkü ücretleri bir testle sabitliyoruz, sonra kuralı hesabın yanına taşıyoruz; test baştan sona yeşil kalıyor.
Derinleş · EFT ücreti: kuralı taşı, kuruşu koru 4 dosya · ~68 satır · ilk okumada atlayabilirsin
Kafam karıştı, daha basit anlat
Her küçük adımdan sonra testleri çalıştır. Bir şey kırılırsa hangi adımın kırdığını hemen bilirsin.
Bu metotta en belirgin smell hangi satırlarda?
Tuzaklar
Refactoring ve özellik aynı commit’te. Kırmızı test ya da hata raporu hangisinden geldiğini söylemez.
Metin olarak bul-değiştir. İlgisiz yerler değişir, bazı kullanımlar kaçar. IDE’nin Rename’i sembolü bilir.
Baştan yazmak. Eski kodun belgelenmemiş davranışları sessizce kaybolur.
Smell’i kural sanmak. Okunaklı bir 12 satırı, adı olmayan parçalara bölmek kodu iyileştirmez.
Bir alanın adını değiştirmek için projede metin olarak bul-değiştir yapıldı. Asıl risk ne?
Kendini sına
Refactoring, kodun davranışını aynı bırakıp düzenini değiştirmektir.
Ekip, 6 ay sürecek bir "baştan yazma" önerisini tartışıyor. En güçlü karşı argüman hangisi?
Aklında kalacak üç şey
- 1 Refactoring davranışı değiştirmez. Sonucu değiştiren bir temizlik, adı ne olursa olsun bir davranış değişikliğidir.
- 2 Test olmadan refactoring bir umuttur. Testi olmayan kodda ilk adım, bugünkü davranışı olduğu gibi sabitleyen testler yazmaktır.
- 3 Adım ne kadar küçükse kırmızı test o kadar net konuşur. Düzeni ve davranışı aynı commit'te değiştirmek hatanın kaynağını gizler.
5 kart sonraki derste seni bekliyor