YAGNI’nin Hiç Bahsetmediği Maliyet
(newsletter.kentbeck.com)- YAGNI, “henüz ihtiyaç duyulmayan kodu yazma” şeklinde basit bir tasarruf kuralı değil; ihtiyaç kesinleşmeden önce tahmine dayanarak yapıyı önceden kapma işinin maliyetini ele alan bir ilkedir
- Sorunun merkezinde tasarımın kendisi değil, tasarımın ne zaman yapılacağı vardır; çok erken yapılandırma, çok geç yapılandırma kadar riskli olabilir
- Önceden kurulan yapı, bilgi gelmeden seçenekleri kapatan bir opsiyon maliyeti ile maliyeti öne çekip getiriyi geciktiren bir NPV maliyetini birlikte doğurur
- Kod üretme maliyeti neredeyse sıfıra inse bile YAGNI ortadan kalkmaz; aksine ucuz üretim, tahmin temelli framework’ler oluşturmayı daha da kolaylaştırabilir
- “Gerektiğinde yap” sonucunun nedeni kod yazma maliyeti değil; kullanılmamış opsiyonların ve harcanmamış paranın değerinin hâlâ var olmasıdır
YAGNI tasarımı yasaklamaz
- YAGNI, “You Aren’t Gonna Need It” ifadesinin kısaltmasıdır; ihtiyaç olmayan hiçbir şeyi asla tasarlamamak için bir bahane değildir
- Bir şeye ihtiyaç varsa yapılabilir, ancak asıl mesele zamanlamadır
- Bir projede “3 hafta sonra basit uygulama yetersiz kalacak, o yüzden şimdi daha karmaşık bir şey yapmak istiyorum” denilen durumlarda “You aren’t going to need it” yanıtının tekrarlandığı anekdot bu ilkenin çıkış noktasıdır
- Bu ilke, yapıyı hem çok erken oluşturmayı hem de çok geç oluşturmayı riskli görür
Sorun kod yazma maliyeti değil, tahmin temelli yapıdır
- Yaygın yorum, YAGNI’yi “henüz ihtiyaç duyulmayan kod pahalıdır, bu yüzden yazma” diyen bir tasarruf kuralı olarak görür
- Ancak YAGNI’nin hedef aldığı şey kod üretim maliyeti değil, gerçek özelliklerin ihtiyaç duymasından önce önceden yapılmış **spekülatif yapı (speculative structure)**dır
- Bu tür yapılar, farklı zamanlarda ve farklı nedenlerle iki tür maliyet doğurur
İlk maliyet: opsiyon
- Bir özellik gelmeden önce yapı oluşturursanız, henüz bilmediğiniz gereksinimler hakkında tahmine dayanarak taahhütte bulunursunuz
- Önceden hazırlanılan özellik, gerçekte gelecek özellikten genellikle farklıdır; bunun sonucunda iki kez maliyet ödenir
- Yanlış biçimdeki yapının etrafından dolaşma maliyeti
- O yapıyı yeniden söküp çıkarma maliyeti
- Bu sorun yalnızca “tahmin etmek zordur” demekle sınırlı değildir
- Tahmin doğru çıksa bile, önceden taahhüt vermeyip daha sonra doğru yapıyı kurabilme opsiyonunu kaybettiğiniz için zarar kalır
- Beklemek tembellik değil, opsiyon adlı bir varlığı elde tutmaktır
İkinci maliyet: NPV
- Paranın zaman değeri olduğu gibi, özelliklerin de zaman değeri vardır
- 3 ay sonra gerekli olacak bir özellik için şimdi yapı kurarsanız, maliyet öne çekilir ve gerçekten para kazandıran özelliğin çıkışı gecikir
- Bu maliyet, tahmin doğru olsa bile oluşur
- Kusursuz tahmin bile maliyet ve gelirin sırasını değiştiremez; kayıp, maliyetin gelirden önce konumlandığı aralıktan doğar
- Opsiyon maliyeti “bilgi gelmeden taahhüt verme” meselesidir; NPV maliyeti ise “ihtiyaç doğmadan ödeme yapma” meselesidir
- “Sonradan düzeltmek çok pahalı olur” itirazı olsa bile, o pahalı tadilatın kendisi de yine bir tahmin olabilir
Kod üretimi ucuzlasa da YAGNI kalır
- İki maliyetin hiçbirinde kodu klavyeyle yazma maliyeti yer almaz
- Kod yazma maliyeti neredeyse sıfıra yaklaştığında, “kod ucuzladı, öyleyse önceden yapabiliriz” diyen tasarruf odaklı YAGNI yorumu çöker
- Ancak YAGNI bir tasarruf kuralı olmadığı için ucuz kod üretimi YAGNI’yi geçersiz kılmaz
- Opsiyon maliyeti, harcanan çaba miktarından değil, gelecekteki seçenekleri kapatan taahhütten doğar
- NPV maliyeti, üretim fiyatından değil nakit akışının zamanlamasından doğar
- Ücretsiz üretim YAGNI’yi zayıflatmaz; aksine tahmin temelli framework’ler oluşturmayı daha da kolaylaştırır
- Üretilen yapı hâlâ iki maliyeti de doğurur; üstelik doğrudan siz yazmadığınız için anlaşılma düzeyi daha düşük olabilir
- Sonuç “kod pahalı olduğu için bekle” değil; opsiyonlar ve para kullanılmadığında daha değerli olduğu için ihtiyaç olduğunda yaptır
1 yorum
Hacker News görüşleri
Yapı değiştirme maliyetinin de düştüğünü düşünüyorum
Yapay zeka sayesinde, yapı değişikliğinden önce davranışı testlerle güçlendirmenin maliyeti azaldı; kesintisiz migrasyon uygulama maliyeti de düştü
Rust’ın ilgi görmesinin büyük nedenlerinden biri de yapay zekadan önce bile uygulama içi yapı değiştirme maliyetinin düşük olmasıydı; şimdi bu daha da geçerli
Yapıyı güvenli biçimde değiştirememenin fırsat maliyeti ciddi biçimde arttı; bugün kodun ve ürünün büyük kısımlarını hızlı ve güvenli şekilde değiştirebilme yeteneğini en yüksek öncelikle optimize ediyoruz
Ancak yapay zekadan önce yapı değişikliği çok daha uzun sürdüğü için, şu anda optimize etmeye çalıştığımız şeyin değerinin aslında düştüğü de söylenebilir
Hâlâ değerli, ama eskisine göre biraz daha az olabilir
Kolay kırılan, AI tarafından üretilmiş testler arttıkça yapı değiştirme maliyeti eskisinden daha da büyüyor
Test paketini toparlayıp sorunun özünü doğrulamasını, tesadüfi tasarım kararlarını doğrulamamasını sağlamak yapay zekanın hâlâ iyi yaptığı bir iş değil
Ama bunu yapmadan, kabaca %75 pişmiş kırılgan bir test paketi elde etmek de çok kolay
Birçok kişi “insanların yazdığı birkaç sıradan ve kırılgan test”ten “AI’ın yazdığı çok sayıda sıradan ve kırılgan test”e geçmeyi nesnel bir iyileşme sayıp bununla yetiniyor
Araçları bu şekilde kullanma fikrine tamamen katılıyorum; ama bu yüzden çok erken aşamada yanlış bir hayalî temel üzerine yapı kurma konusunda endişelenmeye gerek olmadığı sonucuna varmak zor
Refactoring’e dayanıklı kusursuz bir test sözleşmesi tasarlamak hâlâ oldukça zor
Eski olan yeniden yeni gibi geri dönmüş oldu
DDD veya Clean Architecture gibi yaklaşımların bağlam verimliliğinden bu tür maddelere kadar, yapay zeka yeni ödünleşimler yaratmaktan ziyade bir yükselteç gibi çalışıyor
Doğru yapan ekiplerin üretkenliğini artırıyor; tasarım ve mimari kalite çıtası düşük ekiplerin borcunu da artırıyor
Elde edilen tek şey, derinlemesine düşünmek zorunda kalmamak
Derin düşünmek o kadar çok zaman ya da emek gerektirmediğine göre, AI’ı aynı şekilde kullanıp yine de boşa kürek çekmeyecek kadar düşünenlerin gerisinde kalacaklar
Kent Beck, henüz yazılmamış kodu belirli bir fiyattan satın alınabilen bir finansal opsiyona benzetiyor
Ama bu sonuçta sadece bir benzetme; fazla ileri götürülürse tuhaflaşıyor
Hiç kod yazmadıysak seçeneklerimiz sonsuz mu? Henüz zaman harcamamış olsak bile bu doğru görünmüyor
Hiçbir şeyi kesinleştirmemek için planlama aşamasında kalıp kod yazmayı süresiz ertelemenin gerekçesi de olabilir
Yine de bu benzetme işliyorsa maliyet, kodu okumakta olabilir
Yazılmamış kodu okumaya gerek yoktur; coding agent kullanıyorsanız ilgisiz ayrıntılarla bağlamı da kirletmez
Henüz yazılmamış kodun test edilmesine de gerek yoktur; henüz yazılmamış testlerin çalışma süresi de yoktur
Bu yüzden projeyi mümkün olduğunca küçük tutmak iyidir; özellikleri ertelemek kod tabanının büyümesini olabildiğince yavaşlatır
Bu aynı zamanda başkasının kodunu çalıştırırsanız birçok maliyetten kaçınabileceğiniz anlamına da gelir
Standart bir API kullanabiliyorsanız implementasyonu ayrıntılı anlamanız ya da testlerini çalıştırmanız gerekmez; ancak bağımlılık eklemenin riskleri vardır
Yazılmamış kodun değeri yoktur
Bugün yazılan kodun değer üretmesi için ya bugünün isteğini veya issue’sunu çözmesi ya da yarın bir şeyi kolaylaştıracak şekilde eğimli olması gerekir
Hacky bir çözümle teknik borç almak veya YAGNI’ye aykırı bir şeye zaman harcamak değer üretmez
Önemli olan yazılmamış kod değil, ileride yazılacak kod ve onun amacıdır
Bugünün ticket’ını/yapılacak işini çözmek ile gelecekte kendi ayağına sıkmamak arasında doğru ödünleşimi yapmak gerekir
Kod yazmak bir taahhüttür; bugünkü değer görünürdür, yarının değeri ise daha çok tahmindir
Yine de ileride ödenecek bir maliyet her zaman vardır; bu yüzden neye ihtiyaç duyulacağını öngörüp maliyeti en aza indirmeye çalışırken tahmin yaparız
Yapay zeka çağının en iyi pratiklerinin yeterince vurgulanmadığını düşünüyorum; ama Kent’in tamamen kaçırdığı bir nokta var
Hangi özelliklere ihtiyaç olduğunu daha hızlı öğrenmenin hatırı sayılır bir değeri var
Spekülatif bir yapı kurmak, gereksinimleri netleştirmeye zorlayan bir araç olabilir ve en azından başarısızlık biçimlerini ortaya çıkarmaya başlar
Beklemekten daha pahalı olabilir, bu yüzden çoğu gereksinim için böyle yapılmamalı; ama bazen en iyi seçenek olabilir
Yanlış şeyi yapmanın maliyeti artık çok daha düşük ve bu nedenle YAGNI etrafındaki hesap da değişiyor
Yine de hâlâ hesap yapmak gerekir; bugün her ekibin bunun kendileri için nasıl değiştiğini bizzat anlaması gerekiyor
Atmıyorsanız, bu kirli çıktılar üretmeye zorlayan bir araca dönüşür
YAGNI, mevcut gereksinimlerde olmayan bir şeyi, ileride gereksinimler değişecek diye öngörüp yapma problemidir
Mevcut gereksinimleri ve kısıtları somutlaştırmaktan farklıdır
Bunlar çoğunlukla paydaşlar, kullanıcılar ve müşterilerle yapılan konuşmalardan; kaynaklardan; mühendislik kısıtları ve yetkinliklerinden çıkar
Prototip, paydaşlarla konuşurken, proje yönetimi modeli oluştururken veya mühendislik araştırması yaparken değerlidir
Bunun dışındaki durumlarda neden-sonuç sırası tersine dönmüş olur
Çalışan yazılımı bir varlık olarak görmek doğru bir yaklaşım
Ancak çalıştırma ve yeniden yapma maliyeti ciddi biçimde düştü
Düşmeyen maliyet, öngörülebilir sonuçlara ilişkin güven zincirini kırmanın maliyetidir
Çalışan yazılımın belirli bir sürümü zaman içinde güven biriktirmiştir; sıfırdan yeniden yazarsanız release sırasında bu sermaye sıfırlanır
Bir noktadan sonra fikrim değişti
Somut şeyleri YAGNI diyerek erteleyip, mümkün olduğunca soyut bir sürüm yazıyorum
UserStore mu oluştursam? En basiti o gibi görünüyor ama belirli bir User biçimine ihtiyaç olmayabilir
Bu yüzden saklanabilir her şeyi tutan bir Store oluşturuyorum
Alışık değilseniz aşırı tasarım ve generic karmaşası gibi görünebilir ama paradoksal biçimde, herhangi bir somut uygulamaya en az taahhütte bulunan yöntem bu
Muhtemelen gerekmeyecek bir UserStore arayüzü oluşturmakla kalmayıp, kesinlikle gerekmeyecek genelleştirilmiş bir Store soyutlaması da oluşturmuş oluyorsunuz
Somut bir uygulamaya taahhütte bulunmamak için gereksiz olan ve gelecekte de gereksiz olma ihtimali yüksek yapışkan katmanlar uygulamış oluyorsunuz
Gerçek bir ihtiyaca dayanmayan bir soyutlamaysa, ileride gerekse bile büyük olasılıkla yanlış tasarlanmış olacaktır
Sonuçta UserStore gerekecek; bu yüzden önce onu yapmalıydınız
“Daha keskin bir mimarın bundan kaçınabileceği anlamında tahminin zor olduğu iddiası değil” ifadesine katılmıyorum
Bu iddianın geçerli olabilmesi için tahmin etmek zordur öncülüne ihtiyaç var
Olasılığı çok yüksek bir özellik için önceden zemin hazırlarsınız ve her şey denk gelirse daha hızlı yayınlarsınız
Ekibin mutlaka büyüyeceğinin veya kişi sayısının korunacağının garantisi de yok; bu yüzden son teslim tarihinden hemen önce YAGNI’ye uymaya çalışıp telaşlanmaktansa ölçülülüğünüzü kutlamak daha kötü hissettiriyor
Yakın zamanda YAGNI’nin yığılıp kaldığı bir kod tabanından işlevsel olarak çıkmam gerekti; ajanlar olsa bile muazzam bir işti
Dağıtık bir sistemde neyin gerçekten kullanımda olduğunu nasıl anlarsınız? Benim kaçırdıklarım da oldu, ajanın kaçırdıkları da; tüm süreç gereğinden çok daha uzun sürdü
Sadece bire bir port da yapmadım; bunu basitleştirme fırsatı olarak gördüğüm için eski sistemin nasıl çalıştığını tamamen anlamam gerekiyordu
Gerçekte hiç kullanılmayan şeyler bile, böyle tanımlanamazsa anlaşılması gerekenler arasına giriyordu
Sonuçta bunun problemi keşfetmeye ve çözümü uygulamaya vardığını düşünüyorum
Yanlış problemi çözmenin her zaman bir maliyeti vardır; ihtiyaç bile duyulmayan bir şey için kötü bir çözüm uygulamanın da maliyeti vardır
Yazılım geliştirme bazen keşfedilecek strateji ve problem kümesini düşünmek yerine basit bir deneme yanılma sürecine kayabilir
Gerektiğinden daha fazla belirli bir yönde problemi derinlemesine araştırmanın uzun vadede faydalı olduğu durumlar vardır; ama amaçsızca çözüm uygulamak hiçbir zaman iyi değildir
Kent Beck’in asıl eleştirdiği şeyin, gelecekte gerekebilir diye “ne olur ne olmaz” bir şeyler uygulama tavrı olduğunu düşünüyorum
“Özellik gelmeden önce yapı kurarsanız, bir tahmine taahhüt etmiş olursunuz” denmişti; ama bence her iki durumda da tahmin yapılıyor
Özelliğin gelme olasılığı yüksek olabilir ama kesin değildir
Şimdi yapıyı kurmazsanız refaktörleme maliyeti vardır; çok erken kurarsanız ve özellik gelmezse emeği boşa harcamış olursunuz
Bu olasılıklar arasındaki maliyetler, ihtimaller ve ödünleşimler nelerdir? Elbette duruma göre değişir
YAGNI’nin tamamı bilerek yapılmış büyük bir genellemedir
Sonuçta koşullara bağlıdır
Her iki tarafta da çoğu zaman tahmin ve el kol hareketleriyle açıklama doludur; güvenilir iş tahmini gibi bir meseledir
Belirsiz bir dünyaya pek tahammül edemeyen bazı geliştiriciler her şey için siyah-beyaz kurallar aramaya çalışır
https://www.sebastiansylvan.com/post/the-perils-of-future-co...
Özetle YAGNI tarafını tutuyor
Kent Beck’in yazılarında çip şirketleri için faydalı olabilecek bir şey gördüğümü sanmıyorum
Çip şirketlerinde birçok kişinin uzun süre çalışması gerekir, müşteriler tamamlanana kadar hiçbir şey göremez ve para kazanmak için milyonlarca adet satmanız gerekir
Donanımda güçlü kısıtlar vardır
Zaten yazılımın icat edilme nedeni de tam olarak bu kısıtlardan kurtulmaktı
Birçok çip şirketinin devam eden işleri paylaşmadığı doğru olabilir ama simülasyon, prototip ve mühendislik örnekleri paylaşmak mümkündür ve gerçekten de olur
Elbette genelde büyük bir müşteri olmanız gerekir
Değişim maliyetinin görece düşük olduğu bir sektörden gelen içgörüler, değişim maliyetinin yüksek olduğu bir sektöre kolayca uygulanmaz; tersi de çoğu zaman geçerlidir
Çip şirketleri böyle projeleri nasıl planlıyor? Agile mı, waterfall mı, yoksa yazılım sektöründen farklı bir framework mü kullanıyorlar?