3 puan yazan GN⁺ 2024-10-01 | 1 yorum | WhatsApp'ta paylaş
  • Riot Games, teknik borcu gelecekteki geliştiricilerin bedelini ödeyeceği kod veya veri olarak görüyor ve League of Legends geliştirme örnekleri üzerinden borcu değerlendirmek için ortak bir dil ortaya koyuyor
  • Değerlendirme ölçütleri etki, düzeltme maliyeti ve bulaşıcılık olmak üzere üç başlıkta ele alınıyor; özellikle bulaşıcılık, borcun zamanla diğer sistemlere, verilere ve geliştirme pratiklerine ne ölçüde yayıldığını ifade ediyor
  • Borç türleri; iç uygulamaya hapsolmuş Local Debt, iki sistemi geçici olarak birbirine bağlayan MacGyver Debt, derin varsayımların yapıya gömüldüğü Foundational Debt ve kusurların üzerine içeriklerin yığıldığı Data Debt olarak ayrılıyor
  • Jarvan’ın Cataclysm’i, std::string ile AString’in birlikte kullanımı, BlockBuilder’ın Lua kullanması ve block parameter naming bug, her tür için somut örnekler olarak kullanılıyor
  • Bulaşıcılığı düşük borçlar uzun süre bırakılabilirken, bulaşıcılığı yüksek borçlarda zaman geçtikçe düzeltme maliyeti ve etki büyür; bu yüzden yayılma yolları erken kesilmelidir

Teknik borcu değerlendirmek için üç eksen

  • Teknik borç, “gelecekteki geliştiricilerin bedelini ödeyeceği kod veya veri”dir
  • Belirli bir borcu şimdi mi düzeltmek, sonra mı düzeltmek yoksa gerçekçi olarak olduğu gibi mi bırakmak gerektiğine karar verebilmek için ortak ölçütlere ihtiyaç vardır
  • Riot teknik borcu üç eksende değerlendirir
    • impact: oyuncular ve geliştiriciler üzerindeki etkisi
    • fix cost: düzeltme için gereken süre ve dağıtım riski
    • contagion: olduğu gibi bırakıldığında sorunun ne kadar yayıldığı
  • impact: oyunculara ve geliştiricilere görünen maliyet

    • Oyuncular için hata, eksik özellik veya beklenmedik davranış olarak ortaya çıkar
    • Geliştiriciler için uygulama gecikmesi, iş akışının engellenmesi ve hatırlanması gereken gereksiz ayrıntılar olarak birikir
    • Burada geliştirici yalnızca mühendisleri değil; tasarımcılar, VFX sanatçıları gibi oyun üretimine dahil olan rolleri de kapsar
    • Bazı borçlar mühendislerin yeni kod yazmasını engellerken, bazıları tasarımcıların yeni script yazmasını veya VFX sanatçılarının yeni parçacık üretmesini zorlaştırır
  • fix cost: uygulama süresi ve dağıtım riski

    • Düzeltme maliyeti yalnızca gerçek geliştirme süresini değil, düzeltmeleri dağıtırken ortaya çıkan riski de içerir
    • Tek bir fonksiyondaki basit bir hata birkaç dakika içinde düzeltilebilir; ancak oyunun tüm kod tabanını etkileyen derin bir varsayım haftalar, hatta aylar sürebilir
    • “Yanlış” bir sistem bile hâlihazırda iyi bir oyun yapmanın aracı olarak kullanılıyor olabilir; düzeltildiği anda mevcut içerik bozulabilir
    • Örneğin script motorunun hata işleme biçimini ya da parçacık oluşturma süresi hesaplamasını değiştirmek, 140’tan fazla şampiyonun 500’den fazla yeteneğini etkileyebilir
  • contagion: zaman geçtikçe yayılma derecesi

    • contagion, teknik borç olduğu gibi bırakıldığında diğer sistemlere, verilere ve geliştirme biçimlerine ne kadar aktarıldığını ifade eder
    • Yayılma; sorunlu sistemle kurulan arayüzler, onun üzerine yığılan verilerin kopyala/yapıştırla çoğalması ve yeni özelliklerin uygulanma biçimindeki değişimlerle gerçekleşir
    • İyi yalıtılmış borçları sonradan düzeltmek ile şimdi düzeltmek arasında maliyet açısından büyük fark olmayabilir
    • Bulaşıcılığı yüksek borçlar zamanla düzeltilmesi daha zor hâle gelir; daha fazla sistem temel tavizlerden etkilendikçe etkisi de büyür

Local Debt: yalnızca içi dağınık olan kara kutu

  • Local Debt, klasik kara kutu programlama modeline benzer
  • Dışarıdan bakıldığında sistem kararlı çalışır; ancak iç uygulama korkunç veya karmaşık olabilir
    • Örn: yetenek, ağ katmanı, script motoru
  • Çevre sistemleri geliştirirken iç borcun farkında olmak gerekmiyorsa bulaşıcılığı düşük sayılır
  • Gerçek dünya benzetmesi: insan gözü

    • İnsan gözü yapısı gereği görüntüyü ters alır ve retina sinirleri her gözün merkezine yakın bir noktada kör nokta oluşturur
    • Beynin görme merkezi veriyi ters çevirir ve kör noktayı doldurarak beynin geri kalanının “doğru” görüntüyle etkileşmesini sağlar
    • Bu tuhaflık göz ve optik sinir sistemine yereldir; diğer sistemler bunu kolayca atlatabildiği için “yeterince iyi” durumdadır
  • League örneği: Jarvan’ın Cataclysm’i

    • Jarvan’ın Cataclysm’i bugün bile minion olarak yapılmıştır
    • Tasarımcılar belirli bir konuma veya konum kümesine oynanış etkisi eklerken “invisible minion” oluşturan bir araç kullanabilir
    • RiotXypherous, Reddit yorumunda burada geçen “minion” kavramını açıklıyor
    • Bu tür oyun nesneleri, script mantığını izlemek ve çalıştırmak için kararlı ve iyi anlaşılmış bir yöntemdir
    • Jarvan’ın duvarının oyuncuların dışarı çıkmasını engellemesi için tam olarak 24 minion gerekir
    • Eskiden 12 taneydi; ancak oyuncular ara sıra duvarların arasından kaçabildiği için Riot Exgeniar bunu 24’e çıkardı
    • Alternatif, Cataclysm’in pathability durumunu kontrol eden tek bir mantıksal parça olan ring-terrain yapısıdır; bu, mantığı toparlayabilir ve hesaplama maliyetini biraz azaltabilir
  • Cataclysm’in değerlendirmesi

    • impact: 1/5
      • Duvarın minion’lardan yapılmış olması, yeni içerik üreten diğer geliştiricileri neredeyse hiç etkilemez
      • “Jarvan Ult Hitch”, bu borç ile eksik auto-attack tanımını okumaya çalışan bir yükleme hatasının birleşmesi sonucu ortaya çıkmıştı
    • fix cost: 2/5
      • Şu anda yeni kod olmadan bileşik şekillerle özel geometri oluşturulamıyor
      • Ring biçiminde bir “area trigger” oluşturmak için ring çarpışma hesaplarına yönelik özel matematik kodu gerekir
      • Riot başka amaçlar için Constructive Solid Geometry araştırıyor; bu da düzeltme maliyetini önemli ölçüde düşürebilir
    • contagion: 1/5
      • Özellik geliştirirken Jarvan duvarının uygulamasını dikkate almak gerekmediğinden iyi yalıtılmıştır
      • Bulaşma riski, başka bir tasarımcının bu uygulamayı yeni bir şampiyona kopyala/yapıştırla taşımasıdır; pratikte bu ara sıra olmuştur
      • Bir uygulama sorunu olarak Cataclysm’in potansiyel yayılımı düşük ve iyi anlaşılmış durumdadır
  • Local Debt ile başa çıkma biçimi

    • Local Debt’in tipik özelliği düşük contagion puanıdır
    • impact, fix cost’tan yüksekse iyi vatandaş rolü üstlenen geliştiriciler genellikle çok geçmeden bunu düzeltir
    • Gerçekten bulaşıcı değilse gerektiği kadar uzun süre bırakılması güvenlidir
    • Mühendislerin mükemmeliyetçiliğini tetikleyen ama yeterince geniş etkisi olmayan Local Debt’e hemen saldırmak en büyük hatalardan biridir
    • Değişiklik kapsamı yerel olduğundan düzeltmenin doğrulanması ve regresyon testi genellikle kolaydır
    • Yakın zamanda düzeltilen örnekler arasında inhibitor ile ilgili hatalar, Janna’s Monsoon ve Tear of the Goddess yer alır
      • Belirli durumlarda inhibitor’ın şampiyonları 0,0,0 koordinatlarına pathing yapmaya zorladığı hata
      • Janna’s Monsoon’un spell shield’ı yok sayması sorunu
      • Tear of the Goddess’ın mana gerektirmeyen kullanımlarda yük biriktirmesi sorunu

MacGyver Borcu: İki sistemin koli bandıyla birbirine tutturulmuş hâli

  • MacGyver Debt, adını 1980’lerin ortasındaki MacGyver TV dizisinden alan bir türdür
  • Teknik borç bağlamında, çatışan iki sistemin kod tabanı genelindeki arayüz noktalarında “koli bandıyla” birbirine tutturulmuş olmasını ifade eder
  • Gerçek dünya benzetmesi: Seattle

    • Seattle’da geçmişte her biri kendi ızgara planına sahip iki rakip yerleşim vardı
    • Bu iki yerleşim günümüzün Emerald City’sine dönüşürken biraz farklı ızgaralar birleşti; bunun sonucunda tuhaf şekilli adalar ve binalar ile verimsiz alan kullanımı ortaya çıktı
  • League örneği: std::string ve AString

    • League kod tabanında C++ std::string ile Riot’un özel AString sınıfı birlikte bulunur
    • İkisi de dizeleri saklama, değiştirme ve aktarma yöntemleridir
    • Riot, std::string’in çok sayıda “gizli” bellek ayırmaya ve performans maliyetine yol açtığını, kötü kod yazmayı kolaylaştırdığını düşünür
    • AString, dikkatli bellek yönetimi gözetilerek tasarlanmıştır
    • Değiştirme stratejisi, iki sistemi yan yana tutup .c_str() ve .Get() üzerinden birbirlerine dönüştürülebilir kılmaktı
    • AString’e kullanılabilirliği artıran iyileştirmeler eklendi ve mühendislerin kodu değiştirirken kendi inisiyatifleriyle std::string’i değiştirmeleri teşvik edildi
    • Bu yaklaşımla std::string yavaş yavaş aşamalı olarak ortadan kalkıyor; iki sistem arasındaki “koli bandı” arayüzü de kod temizliğiyle birlikte azalıyor
  • std::string vs AString değerlendirmesi

    • impact: 2/5
      • std::string’den kaynaklanan yüksek etkili ayırmaların çoğu profiling yoluyla zaten kaldırıldı
      • Şu anki başlıca maliyet, bir sistemden diğerine dönüşüm yaparken oluşan küçük zihinsel geçiş maliyetidir
    • fix cost: 3/5
      • AString’e geçiş basit bir find-and-replace işi değildir
      • AString’in stack bellekte ilk ayırmayı yapan AStackString, static string referansları için ARefString ve heap ayırma tabanlı AString gibi amaca özel varyantları vardır
      • Doğru değişim için bir kişinin her noktaya doğrudan bakıp karar vermesi gerekir; mevcut sistemi aşamalı olarak kaldırma süreci uzun ve yavaş olacaktır
    • contagion: -2/5
      • AString’i std::string’den daha kullanışlı hâle getirerek contagion’ı olumlu yöne çevirdiler
      • Mühendisler oyun kodunda yaptıkları değişiklikleri her check-in ettiğinde AString’in daha da yayılma olasılığı doğar
  • MacGyver Debt’i düzeltme yöntemi

    • MacGyver Debt’in büyük maliyeti çoğu zaman sınırları geçerken mod değiştirmeyi gerektiren entelektüel maliyettir
    • Bir hata ya da özellik “yanlış” sistemde olduğu için tıkanıyorsa, hedef noktayı “doğru” sisteme taşımak genelde doğrudan bir iştir
    • Yeni sistem ile mevcut sistemin göreli contagion’ı temel göstergedir
    • Dengeyi yeni sistem tarafı daha çok yayılsın diye tersine çevirirseniz, daha iyi sistem sonunda kazanır
    • Küresel ölçekte daha iyi olan sistemi yerel düzeyde de daha cazip hâle getirmek gerekir
    • Zaman baskısı altındaki mühendisler günlük işleri sırasında açgözlü optimizasyon yaparken bile istenen nihai duruma doğru seçim yapıyorsa doğru yönde ilerleniyor demektir
    • Diğer yaklaşım büyük ölçekli brute-force refactor’dır; sistemlerin birbirine ne kadar yakın eşlendiğine bağlı olarak clever regex ile bir kısmı ya da tamamı düzeltilebilir

Temel Borç: Derin bir varsayımın tüm yapıya işlemiş olması

  • Temel Borç, sistemin derinlerindeki bir varsayımın tüm çalışma biçimine yerleşmiş olmasıdır
  • Sistemin deneyimli kullanıcıları bunu “zaten böyle” gördüğü için fark etmesi zor olabilir
  • Gerçek dünya benzetmesi: United States Customary Units

    • ABD’de büyüyen biri 1 milin 5.280 fit, 1 quart’ın 2 pint, 1 galonun 4 quart olduğu gibi dönüşümleri ezberler
    • ABD hükümeti metrik sisteme geçişi birkaç kez değerlendirdi, ancak hâlâ Système International’ı resmi ölçüm sistemi olarak benimsememiş 7 ülkeden biridir
    • Bu borç; yol tabelalarına, tariflere, ilkokullara ve insanların zihnine işlemiştir
  • League örneği: BlockBuilder ve Lua

    • Riot’ın ele aldığı büyük Temel Borç örnekleri arasında League of Legends’ta Determinizm ve Game Data Server yer alır
    • League’in Lua scripting language kullanımı da bir Temel Borç örneğidir
    • League tasarımcıları, BlockBuilder adlı bir araçla işlev bloklarını birbirine ekleyerek karmaşık davranışlar oluşturur
    • İşlev blokları; noktalar arasındaki mesafeyi bulma, minion oluşturma, damage işleme ve çeşitli script flow control mekanizmalarını içerir
    • Tasarımcının seçtiği işlem kümesi çeşitlidir ancak sınırlıdır; her işlemin parametreleri de kısıtlanmıştır
    • League of Legends’ın ilk dönemlerinde blokları ve parametreleri veriye uygun, basit ve kısıtlı bir biçimde saklamak yerine; güçlü ama bu amaç için gereğinden karmaşık olan Lua dilinin arrays ve tables yapılarında saklamaya karar verildi
    • Sonrasında yaklaşık 10 yıllık oyun geliştirme bu temel üzerinde ilerledi ve Lua object manipülasyonu motordaki en yaygın işlemlerden biri hâline geldi
  • BlockBuilder Lua’nın değerlendirmesi

    • impact: 4/5
      • Lua ile söz konusu problem alanı arasındaki uyumsuzluk çok fazla maliyet doğurur
      • BlockBuilder mantığının her frame’inde callstack yaklaşık 6 marshalling stack frame ile kirlenir
      • marshalling işlemleri server CPU kullanımı açısından ucuz değildir
      • script değişiklik diff’lerini okumak gereksiz yere zordur
      • Bir işlevi anlamak için script file’ı parsing/searching yapmak, Lua dili hakkında epey derin bir anlayış gerektirir
    • fix cost: 4/5
      • Lua motorun derinlerine işlemiş olduğu için kaldırılması zordur
      • Mevcut önerilerden biri, Lua object gibi davranan ama içeride çok daha basit bir struct olan bir wrapper class oluşturarak scripting iç yapısını yavaş yavaş daha uygun bir forma dönüştürmektir
      • Hangi yaklaşım seçilirse seçilsin, dikkatli ve düşünülmüş biçimde ilerlemek gerekir
    • contagion: 4/5
      • Sistem scripting ile her temas ettiğinde, o sistem Lua backend’in işlemleri ve gereksinimleri tarafından şekillendirilir
      • scripting, LoL’ün temel logic birimidir
      • Riot ortalama yaklaşık her 3–4 günde bir yeni Building Block ekler ve her Building Block doğrudan Lua object’i manipüle eder
      • Lua’yı değiştirmek ne kadar ertelenirse, Lua’yı değiştirmek o kadar zorlaşır
  • Temel Borcu azaltma yöntemi

    • Temel Borç; impact, fix cost ve contagion eksenlerinin üçünde de yüksek puan alma eğilimindedir
    • Yüksek fix cost, kusurlu sistemi kullanmaya devam ettirir; bazen bu doğru tercih de olabilir
    • Ancak yüksek impact ve yüksek contagion nedeniyle, ciddi Temel Borçları düzeltmek büyük bir karşılık sağlayabilir
    • Riot’ta gözlemlenen en yaygın düzeltme stratejisi, yeni sistemi mevcut sistemin yanına kurmaktır
    • Mümkünse mevcut foundational debt’i MacGyver Debt’e dönüştürüp conversion operation ile yeni sistem ve mevcut sistem arasında gidip gelerek yavaş yavaş port edilir
    • Bu yöntem, belirli alanlarda avantaj elde etmeye başlarken riske maruz kalmayı sınırlar
    • Böyle bir geçiş mümkün olmadığında, compile time switch; mümkünse loading time switch oluşturularak yeni sisteme güven inşa edilebilir
    • compile time switch yöntemi GDS geçişinde kullanılıyor
    • loading time switch yöntemi Determinism kapsamında işe yaradı

Data Debt: Kusurların Üzerine Büyük Miktarda İçerik Birikmesi

  • Data Debt, diğer teknik borç kategorilerinin üzerine çok miktarda içerik yığıldığında ortaya çıkar
  • Başlangıç noktası scripting system’deki bir bug, item’a uygun olmayan bir file format, birbiriyle iyi uyuşmayan iki sistem vb. olabilir
  • Bu kod kusurunun üzerine art, scripts, sounds gibi büyük miktarda içerik üretildiğinde, başlangıçtaki teknik borcu düzeltmek çok riskli hale gelir
  • Zamanla neyin bozulacağını anlamak acı verecek kadar zorlaşır
  • Gerçek dünya benzetmesi: DNA

    • Bir organizmanın genome’u milyonlarca yıl boyunca mutation, transcription error ve evolutionary pressure ile yavaş yavaş birikir
    • Bazı kopyalama hataları işe yaramaz ama zararlı değildir, bazıları zararlıdır, bazıları ise güçlü bir avantaj sağlar
    • Bir DNA parçasının gerçekte ne yaptığını anlamak çok zordur
    • base pair’in ne anlama geldiğini ve base pair kümelerinin protein construction için amino acid’lere nasıl çevrildiğini tamamen anlıyoruz
    • DNA’nın bazı non-encoding role’leri hakkında da daha fazla şey anlamaya başladık
    • Ancak insan genome’undaki 3 milyardan fazla base pair içinde hâlâ neredeyse hiç anlamadığımız çok sayıda bölüm var
    • Radiolab’in CRISPR bölümü, yakın zamanda çözülen bu tür bulmacalardan birini ele alıyor
  • League örneği: block parameter naming bug

    • League of Legends’taki Data Debt, aslında küçük bir düzeltme olacak bir işi zahmetli bir çalışmaya dönüştürdüğünde en büyük etkisini gösterir
    • game engineer’lar oyun sistemlerinin nasıl uygulandığına dair derin bilgi biriktirir ve hangi kod değişikliğinin hangi veriyi bozacağını öngörme konusunda ustalaşır
    • Data Debt, LoL engine değişikliklerinde en önemli değerlendirme konularından biridir
    • Birkaç yıl önce düzeltilen bir Data Debt örneği, BlockBuilder scripting language’daki block parameter ile ilgili bir bug’dı
    • toy example’da Owner’ın armor’unu bir değişken ve bir sabitle artırmaya çalışırsanız beklenen değer, Delta değişkeni 20 ile 5 sabitinin toplamı olan 25 bonus armor’dır
    • Değişken adı parameter adıyla aynıysa, eskiden sonuç 40 oluyordu
    • Yazar, neden 45 olmadığını kendisinin de bilmediğini söylüyor
  • Gerçek düzeltme süreci

    • Champions team mühendisi NoopMoney bu davranışı düzeltmeye çalıştığında, gerçek kod düzeltmesi yalnızca 4 satır silmekten ibaretti
    • Ancak çok bulaşıcı olan borç, küçük bir değişiklikte bile kapsamlı planlama gerektiriyordu
    • LoL’ün 400.000 satırlık script’inin herhangi bir yerindeki herhangi bir numerical parameter bu bug nedeniyle iki katına çıkıyor olabilirdi
    • Daha büyük sorun, oyunun potansiyel olarak iki katına çıkmış bu değerlere göre balance ve tuning edilmiş olması; yani ilgili script’lerin “correctly” çalışıyor olmasıydı
    • NoopMoney, beklenmeyen bug’lara karşı fix’i Live’da toggle edilebilir hale getirmek zorundaydı
    • Hangi script’in bu bug’a dayandığını belirlemek için kapsamlı regex searching ve QA sweep yürütüldü
    • Sonuçta düzeltmenin yol açtığı sorunlar görece küçüktü ve yalnızca az sayıda champion script’inin değiştirilmesi gerekti
    • Data Debt nedeniyle sonucu öngörmek zordu
  • Parameter Naming Bug değerlendirmesi

    • impact: 2/5
      • Ortaya çıktığında etkisi küçüktü
      • Aktarılan değeri iki katına çıkarma ve sabiti atma ihtimali vardı
      • Bunu öğrenen designer ve engineer’ların hatırlamak zorunda kaldığı bir başka işe yaramaz tribal knowledge haline geldi
      • developer mindshare, böyle boşa harcanamayacak kadar değerli bir kaynaktır
    • fix cost: 2/5
      • Genel olarak düzeltmenin kendisi doğrudandı
      • live feature toggle oluşturarak fix’in güvenliğine dair güven artırılabildi
      • En pahalı kısım, test hedeflerini belirlemek için sorunun kapsamını değerlendiren ilk screening oldu
    • contagion: 4/5
      • Bu bug’ın çok mantıklı bir davranışı hedef almış olması talihsizdi
      • Bir unit’e damage vermek için değeri “Damage” adlı bir değişkende saklamak tamamen mantıklıdır
      • ApplyDamage block’u aynı adlı bir parameter ile amount aldığında bug tetiklenir
      • Başka biri benzer bir spell yapmak için ilgili block’u copy/paste ederse bug daha da yayılır
  • Data Debt’in çok bulaşıcı olmasının nedeni

    • Data Debt, değişiklik etkisini değerlendirmeyi zorlaştırdığı için genellikle düzeltme maliyeti yüksek kabul edilir
    • Daha endişe verici olan, data’nın doğası gereği neredeyse her zaman çok bulaşıcı olmasıdır
    • Mevcut data’yı copy/paste ederek yeni data oluşturma yöntemi genellikle kabul görür
    • Yeni bir skillshot spell’i oluştururken Ezreal’s Mystic Shot’tan başlamak çok zaman kazandırabilir; mevcut data’daki sorunlar da onun soyundan gelen data’ya yayılır
    • data, code review’ye benzer teknik incelemelerden nadiren geçtiği için, kötü uygulamalar yaygın olarak bilinse bile yayılmayı fark etmek ve durdurmak zordur
    • data’daki bir sorunu düzeltmek için genellikle gözleri ve beyni olan bir kişinin doğrudan doğrulama yapması gerekir; compiler ve formal logic tek başına yeterli değildir
  • Data Debt’i düzeltmek için iki yaklaşım

    • İlk yaklaşım do it right checkbox’tır
      • data creator için mevcut “broken” behavior ile yeni “fixed” behavior arasında toggle oluşturma yöntemidir
      • İdeal olarak fixed version varsayılan yapılır, old content ise broken version’ı kullanır
      • Sonrasında MacGyver Debt’te olduğu gibi yavaş ve istikrarlı replacement ile yeni sürüme taşınabilir
      • Dezavantajı, editing UI’ya giderek daha fazla gereksiz öğe ekleyen kalıcı bir maliyet doğurmasıdır
    • İkinci yaklaşım just fix the damn thing’dir
      • NoopMoney’nin parameter naming bug için kullandığı yöntemdir
      • Bug düzeltildikten sonra anlamlı biçimde etkilenen tüm data onarılmaya çalışılır
      • Bunu daha az korkutucu hale getiren teknikler arasında theoretical impact’i anlamak için çok sayıda grep ve regex searching, targeted testing ve ship sonrasında daha kötü bir eksik bulunursa mevcut davranışa geri dönecek bir toggle hazırlamak yer alır
      • Determinism, değişiklik öncesi ve sonrası sunucunun aynı sonucu üretip üretmediğini doğrulamayı sağlayarak bu tür değişikliklerin test edilmesine büyük yardım eder

Özet: Bulaşıcılık maliyet değerlendirmesine dahil edilmeli

  • Teknik borç ölçütleri impact, fix cost ve contagion’dır
    • impact, müşteriler ve geliştiriciler üzerindeki etkidir
    • fix cost, zaman ve risktir
    • contagion, sorunun yayılma derecesidir
  • Çoğu geliştirici impact ve fix cost’u düzenli olarak dikkate alır, ancak contagion tartışması görece daha nadirdir
  • contagion, bir sorun derine işleyip giderek kaldırılması zorlaştığında geliştiricinin en büyük düşmanı olabilir
  • Tersine, fix’i sorundan daha bulaşıcı hale getirirseniz contagion’ı bir silaha dönüştürebilirsiniz
  • League’de gördüğümüz teknik borçların çoğu dört kategoriden birine girer
    • Local Debt: içi dağınık bir black box gibi olan borç
    • MacGyver Debt: 2 veya daha fazla sistemin conversion function ile koli bandı gibi birbirine tutturulduğu borç
    • Foundational Debt: tüm yapının talihsiz varsayımlar üzerine kurulduğu borç
    • Data Debt: diğer borç türlerinin üzerine devasa data’nın yığıldığı; düzeltmesi riskli ve zaman alıcı olan borç

1 yorum

 
GN⁺ 2024-10-01
Hacker News yorumları
  • Bulaşıcılık, arayüzlerin tasarımın en önemli unsurlarından biri olmasının ve üzerinde yeterince düşünülmesi gerekmesinin bizzat nedenidir.
    Güzel bir arayüzün arkasında ideal olmayan bir implementasyon varsa, zaman bulunduğunda kolayca toparlanabilir; ama bunun tersi neredeyse hiç geçerli değildir.

    • Katılıyorum; ama düzgün tasarlamak için genelde iki şeyden biri eksik olur: tasarlamaya zaman ve bugün ile bir yıl sonra tam olarak ne yapılması gerektiğine dair bilgi.
      Bazen ikisi de yoktur.
      Böyle durumlarda küçük modülleri ve tek sorumluluğu bileşimsel biçimde dayatmak, bulaşmanın fazla yayılmasını engelleyebilir. Geleceğe dair çok bilgi ya da zaman gerektirmez; birden çok davranış varyasyonunu parametrelerle kontrol eden Rus matruşkası tarzı geniş yüzey alanlı arayüzlerden kaçınmak yeterlidir. Yapılandırma, parsing ve davranış kararlarını mantığın kenarlarına taşımak, bunların alt modelin tamamına sızmasına izin vermemek daha iyidir.
    • Katılıyorum; ancak sağlam ve geleceğe dayanıklı arayüzler tasarlamak, yazılım geliştirmedeki en zor problemlerden biri olmuştur.
      Teknik borçtan ne pahasına olursa olsun kaçınma niyetiyle yola çıksanız bile bunu doğru yapmak zordur; basit teknik özgüven ya da mimari vizyondan fazlasını gerektirir. Pratikte geleceği tahmin etme alanına girer.
    • İyi bir arayüz ortaya koymak için iyi bir iç implementasyonun nasıl göründüğünü anlamak gerekir.
      Aptalca bir implementasyonu arayüzün içine örtük olarak gömerseniz, yalnızca implementasyonu değiştirerek düzeltmek çoğu zaman imkânsız hale gelir. Aklıma gelen örnek sıralama ve sayfalama davranışı. Junior geliştiriciler ve artık daha iyi bilmesi gereken birçok senior bile çoğu zaman limit/offset türü parametreler kullanan isteklerle başlıyor; bu da berbat performans sorunlarına ve garip davranışlara yol açıyor. Sayfalamanın verimli çalışması ve performanslı biçimde desteklenebilecek sıralama seçenekleri, verinin biçimine ve veri deposu seçimine özünde bağlıdır. Alt katmanlarda bu süreçten geçmemiş biri, önce implementasyonun yeterince içine dalmadıkça üst seviye arayüzü doğru kurma ihtimali düşüktür.
    • Bu yüzden OCaml ya da Ada gibi arayüzleri çok açık hale getiren dilleri seviyorum.
      Çoğu durumda implementasyonu görmek istemem; yalnızca düzgün belgelenmiş arayüzü görmek isterim. Arayüzün davranışını basit sözlerle açıklayamıyorsanız bir şeyler yanlıştır.
    • Tarihte epey karşı örnek var gibi görünüyor.
      QWERTY'nin en iyi fiziksel arayüz olmadığı bilinir; direksiyon simidi de benzer bir örnek olabilir. Bilgisayar tarafında ise x86, yüzeyde ideal olmayan bir arayüzün başlıca örneklerinden biridir.
  • Bu yazıyı bir mühendislik yöneticisinin yazmış olması oldukça şaşırtıcı.
    Birlikte çalıştığım yöneticilerden hiçbiri kod tabanımız hakkında bu düzeyde teknik ayrıntıyla konuşamazdı. Daha önce mühendis olanlar da dahil.
    Yine de adil olmak gerekirse, içeriden terfi etmiş yöneticimiz yoktu; içeridekiler, ben dahil, mühendisliği bırakmak istemediği için yöneticileri dışarıdan alma gibi kötü bir alışkanlığımız var.

  • Gördüğüm en yaygın borç türü eksik gibi: kurucu borcu.
    Kurucuların hızlı ve değerli teknolojiyi piyasaya çıkarmak için oluşturduğu borç. Kolay kazanım gibi görünen bir şeyin tüm sistemin temeline dönüşmesi durumu.
    Birçok ülkenin kuruluş belgeleri de bu kategoriye girer lol (ama USA! USA! USA! değil).
    MacGyver borcu ve temel borç buna en yakın olanlar, ama ikisi de bu olguyu tam olarak yakalamıyor.

  • Teknik açıdan harika bir yazı.
    Ancak bunun bir “sınıflandırma sistemi”nden çok adlandırma sistemine daha yakın olduğunu düşünüyorum. Çünkü kasıtlı olarak ne kapsayıcı ne de birbirini dışlayan kategoriler sunuyor; yanılıyor olabilirim. Her başlıktaki fiziksel örnekler özellikle iyiydi ve düşündürücüydü.
    Her zamanki gibi felsefi açıdan küçük bir takıldığım nokta var. Baştaki “üç eksen”, geleneksel RoI'nin getiri ve yatırımına, belirli bir gelecek odaklı ve koşullu getiri alt kategorisi eklenmiş gibi görünüyor. Bu kararın pratikte iyi işlemiş olabileceğini tahmin ediyorum; video oyunu geliştirme pratiklerinin mutlak anlamda bilimsel olması gerekmez, ama biraz daha felsefi kesinlik zarar vermezdi.

  • O dönemde de tartışılmıştı:
    A Taxonomy of Technical Debt - https://news.ycombinator.com/item?id=16810092 - Nisan 2018 (113 yorum)
    Bir de bu var:
    A Taxonomy of Tech Debt (2018) - https://news.ycombinator.com/item?id=39782923 - Mart 2024 (1 yorum)

  • “Teknik borcu, gelecekteki geliştiricilerin bedelini ödeyeceği kod ya da veri olarak tanımlıyorum” açıklaması gördüklerim arasında en iyilerden biri.
    Tüm borçlarda olduğu gibi, borç alırken anlık ihtiyaçla gelecekteki maliyet arasında denge kuran bir eşik uygulanmalı. Bence çoğu insan, yalnızca geliştiriciler değil, anlık ihtiyacı abartıyor ve gelecekteki maliyeti küçümsüyor.
    Kişisel olarak her tür borçtan neredeyse patolojik derecede hoşlanmıyorum. Gelecekte işe yarayabilecek bir şeyi ayrıştırmak için fazladan bir gün harcadığım oluyor. Haklı çıkma oranım kabaca %50; ama böyle bir işi her yaptığımda alışkanlığım güçleniyor ve temel iş akışım da hızlanıyor.

  • Şimdiye kadar 3 “startup”ta çalıştım; hepsine, normale yakın maaş verecek kadar gelir elde etmeye başladıktan sonra katıldım.
    En sık gördüğüm şey, birden fazla kurucunun akıllarına gelen fikri, gerçekten yapılmış olanı ve implementasyonun gerçekten çalışan kısmını bulanık biçimde birbirine karıştırmasıydı.

  • Bu yazıyı ilk okuduğumdan beri teknik borcu anlatırken bulaşıcılık kelimesini kullanıyorum ve oldukça iyi oturuyor.

  • “Yerel borç”un normal koşullarda teknik borç sayılıp sayılamayacağından pek emin değilim.
    Gerçekte bir yerlerde her zaman dağınık kısımlar olur; bunları kapsülleyip kimse zarar görmeyecek şekilde gizlemek normaldir. Gereksinimler değişmediği sürece neredeyse hiç değiştirmeniz gerekmiyorsa ve değişirse zaten her implementasyonun değiştirilmesi gerekecekse, bunda sorun yoktur.
    Örnekteki 24 minion instance'ı yalnızca zarif olmamaktan öte gerçek bir sorunsa, “minion” en basit temel birim haline gelmiş ve daha hafif bir şey mümkün olabilirmiş anlamına geldiği için bu daha çok temel borca yakın görünüyor.

    • Yazıda da biraz değiniliyor ama maliyet, gerçekten üzerinde çalışmanız gerektiğinde onu anlamanın bilişsel maliyeti; buna araçları aynı tutmanın maliyetini de eklemek isterim.
      Geliştiricileri, eski ve olgun olup dokunulması gerekmeyen modüller dahil değişiklik yapmaya teşvik etmek, bunun sorun olacak kadar birikmesini önlemenin iyi bir yoludur.
  • Önemli bir boyut da kısa vadeli fayda elde etmek için bilinçli olarak teknik borç alınmasıdır.
    O zaman bu fayda da tartılması gereken başka bir eksen olur.

    • Gerçek borçla tamamen aynı.
      15 yıl sonra sermayeniz olana kadar beklemek yerine şimdi yeni bir bina yapıp işi bitirmek mi istiyorsunuz? Borç alırsınız.
      Borç bir araçtır; ama güçlü ve tehlikeli bir araçtır. Onu kullandığınızı kabul edip saygı duymazsanız zarar görürsünüz. Ya da elinizden el bombası devralan biri zarar görür. Gerçek borçta olduğu gibi.
    • Böyle şeylere “teknik borç” yerine taktik borç dendiğini duydum.
    • Genelde sebep hızdır.