Kısa bir süre önce RailsConf 2014'ten "Tüm Küçük Şeyler" izledim. Bu konuşma sırasında Sandi Metz, büyük bir iç içe if ifadesi içeren bir işlevi yeniden düzenler:
def tick
if @name != 'Aged Brie' && @name != 'Backstage passes to a TAFKAL80ETC concert'
if @quality > 0
if @name != 'Sulfuras, Hand of Ragnaros'
@quality -= 1
end
end
else
...
end
...
end
İlk adım, işlevi birkaç küçük işleve ayırmaktır:
def tick
case name
when 'Aged Brie'
return brie_tick
...
end
end
def brie_tick
@days_remaining -= 1
return if quality >= 50
@quality += 1
@quality += 1 if @days_remaining <= 0
end
İlginç bulduğum şey, bu daha küçük fonksiyonların yazılma biçimiydi. brie_tick
örneğin, orijinal tick
işlevin ilgili bölümleri çıkarılarak değil , test_brie_*
birim testlerine atıfla sıfırdan yazılmıştır . Tüm bu birim testleri geçtikten sonra brie_tick
yapıldı. Tüm küçük fonksiyonlar yapıldıktan sonra, orijinal monolitik tick
fonksiyon silindi.
Ne yazık ki, sunumcu bu yaklaşımın dört *_tick
fonksiyondan üçünün yanlış olmasına (ve diğerinin boş olduğuna!) Neden olmadığından habersiz görünüyordu . *_tick
İşlevlerin davranışının orijinal tick
işlevin davranışından farklı olduğu uç durumlar vardır . Örneğin, @days_remaining <= 0
içinde brie_tick
olmalıdır < 0
- bu yüzden brie_tick
ile çağrıldığında düzgün çalışmaz days_remaining == 1
ve quality < 50
.
Burada neyin yanlış gitti? Bu bir test başarısızlığı mıdır - çünkü bu belirli uç durumlar için test yapılmamıştır? Ya da yeniden düzenleme başarısızlığı - çünkü kod sıfırdan yeniden yazmak yerine adım adım dönüştürülmüş olmalı?