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 tickiş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_tickyapıldı. Tüm küçük fonksiyonlar yapıldıktan sonra, orijinal monolitik tickfonksiyon silindi.
Ne yazık ki, sunumcu bu yaklaşımın dört *_tickfonksiyondan üçü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 tickişlevin davranışından farklı olduğu uç durumlar vardır . Örneğin, @days_remaining <= 0içinde brie_tickolmalıdır < 0- bu yüzden brie_tickile çağrıldığında düzgün çalışmaz days_remaining == 1ve 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ı?