John Ousterhout’un pratik yazılım tasarımına dair fikirlerini, Tcl’in mirasını, Ousterhout ile Brooks tartışmasını ve karmaşıklığın ürünlere maliyetini keşfedin.

John Ousterhout, hem araştırma hem gerçek sistemlerde çalışmış bir bilgisayar bilimci ve mühendistir. Tcl programlama dilini yarattı, modern dosya sistemlerinin şekillenmesine katkıda bulundu ve yılların deneyimini basit ve biraz rahatsız edici bir iddiaya indirdi: karmaşıklık yazılımın baş düşmanıdır.
Bu mesaj hâlâ güncel çünkü çoğu ekip özellik eksikliğinden veya çabadan ötürü başarısız olmuyor—başarısız oluyor çünkü sistemleri (ve organizasyonları) anlaşılması zor, değiştirilmesi zor ve kırılması kolay hale geliyor. Karmaşıklık sadece mühendisleri yavaşlatmıyor. Ürün kararlarına, yol haritası güvenine, müşteri güvenine, olay sıklığına ve hatta işe alıma sızıyor—çünkü işe alıştırma aylar süren bir çileye dönüşüyor.
Ousterhout’un çerçevesi pratiktir: bir sistem özel durumlar, istisnalar, gizli bağımlılıklar ve "sadece bu kez" düzeltmeleri biriktirdiğinde, maliyet sadece kod tabanıyla sınırlı kalmaz. Tüm ürün evrimleşmesi daha pahalı olur. Özellikler daha uzun sürer, QA zorlaşır, sürümler daha riskli hale gelir ve ekipler herhangi bir şeyi dokunmak tehlikeli hissettiği için iyileştirmelerden kaçınmaya başlar.
Bu akademik saflık çağrısı değil. Her kestirme kararın faiz ödemeleri olduğunu hatırlatan bir uyarı—karmaşıklık en yüksek faizli borçtur.
Fikri somutlaştırmak (sadece motive edici olmaması için) üç açıdan bakacağız:
Bu yazı sadece dil meraklıları için değil. Ürün inşa ediyorsanız, ekip yönetiyorsanız veya yol haritası takasları yapıyorsanız, karmaşıklığı erken fark etmenin, onun kurumsallaşmasını önlemenin ve sadeliği lansman sonrası hoş bir lüks yerine birinci sınıf kısıt olarak ele almanın uygulanabilir yollarını bulacaksınız.
Karmaşıklık "çok kod" ya da "zor matematik" demek değildir. Değişiklik yaptığınızda sistemin ne yapacağını düşündüğünüz ile gerçekte ne yaptığı arasındaki uçurumdur. Küçük düzenlemeler riskli hissettiriyorsa sistem karmaşıktır—çünkü etki alanını tahmin edemezsiniz.
Sağlıklı bir kodda şu soruyu yanıtlayabilirsiniz: "Bunu değiştirirsek başka ne kırılabilir?" Karmaşıklık bu soruyu pahalı hale getirir.
Genellikle saklanır:
Ekipler karmaşıklığı daha yavaş gönderim (araştırmaya daha fazla zaman), daha fazla hata (davranışların sürpriz olması) ve kırılgan sistemler (değişiklikler birçok kişi ve servis arasında koordinasyon gerektirir) olarak hisseder. Ayrıca işe alıştırma maliyetini artırır: yeni ekip üyeleri zihinsel bir model kuramaz, bu yüzden kritik akışlara dokunmaktan kaçınırlar.
Bazı karmaşıklık esensiyeldir: iş kuralları, uyumluluk gereksinimleri, gerçek dünyanın uç durumları. Bunları silemezsiniz.
Ancak büyük bir kısmı kazaradır: kafa karıştırıcı API'ler, tekrar eden mantık, "geçici" bayraklar kalıcı hale gelmesi ve detayları sızdıran modüller. Bu, tasarım kararlarının yarattığı karmaşıklıktır ve tutarlı şekilde azaltabileceğiniz tek türdür.
Tcl, pratik bir amaçla başladı: yazılımı otomatikleştirmeyi ve mevcut uygulamaları yeniden yazmadan uzatmayı kolaylaştırmak. John Ousterhout, bir araça "yeterince programlanabilirlik" eklemeyi ve bu gücü kullanıcılar, operatörler, QA veya otomasyon ihtiyacı olan herkese vermeyi hedefledi.
Tcl, küçük, esnek bir script katmanının daha hızlı, daha düşük seviyeli dillerde yazılmış bileşenleri birbirine bağladığı fikrini popülerleştirdi. Her özelliği monolitik olarak inşa etmek yerine, bir dizi komut açığa çıkarıp bunları yeni davranışlar için birleştirebilirdiniz.
Bu model etkiliydi çünkü işin gerçekte nasıl yapıldığını yansıtıyordu. İnsanlar sadece ürün inşa etmez; derleme sistemleri, test harness'leri, yönetici araçları, veri dönüştürücüler ve tek seferlik otomasyonlar yaparlar. Hafif bir script katmanı bu görevleri "bilet oluştur"dan "script yaz"a çevirdi.
Tcl, gömlemeyi birinci sınıf bir mesele yaptı. Bir yorumlayıcıyı uygulamaya bırakabilir, temiz bir komut arayüzü ihraç edebilir ve anında konfigürasyon ve hızlı iterasyon kazanabilirdiniz.
Bugün aynı desen eklenti sistemlerinde, konfigürasyon dillerinde, uzantı API'larında ve gömülü script runtime'larda karşımıza çıkar—script söz dizimi Tcl gibi görünmese bile.
Ayrıca önemli bir tasarım alışkanlığını pekiştirdi: stabil ilkeleri (host uygulamanın çekirdek yetenekleri) değiştirilebilir kompozisyondan (scriptler) ayırın. Bu işe yaradığında, araçlar çekirdeği sürekli istikrarsızlaştırmadan daha hızlı evrilir.
Tcl’in sözdizimi ve "her şey bir string" modeli sezgisel gelmeyebilirdi ve büyük Tcl kod tabanları güçlü konvansiyonlar olmadan mantıksal olarak zorlaşabiliyordu. Yeni ekosistemler daha zengin standart kütüphaneler, daha iyi araçlar ve daha büyük topluluklar sundukça bir kısım ekip doğal olarak göç etti.
Bunların hiçbiri Tcl’in mirasını silmez: genişletilebilirlik ve otomasyonun ekstra olmadığını—ürün özellikleri olduğunu ve sistemi kullanan/koruyan insanlar için karmaşıklığı önemli ölçüde azaltabileceğini normalleştirdi.
Tcl, görünüşte katı bir fikir etrafında kuruldu: çekirdeği küçük tut, kompozisyonu güçlü kıl, ve scriptleri insanlar birlikte çalışabilecek kadar okunabilir kıl.
Özelleştirilmiş büyük bir özellik seti sunmak yerine Tcl, kompakt bir primitif setine (stringler, komutlar, basit değerlendirme kuralları) güvendi ve kullanıcıların bunları birleştirmesini bekledi.
Bu felsefe tasarımcıları daha az kavrama, birçok bağlamda yeniden kullanılan kavramlara yönlendirir. Ürün ve API tasarımı için ders açık: on ihtiyacı iki ya da üç tutarlı yapı taşla çözebiliyorsanız, öğrenilmesi gereken yüzeyi küçültürsünüz.
Yazılım tasarımında tuzak, yapıcıların kolaylığını optimize etmektir. Bir özellik uygulanması kolay olabilir (var olan bir seçeneği kopyalamak, özel bir bayrak eklemek) ama ürünü kullanmayı zorlaştırır.
Tcl’in vurgusu tersiydi: zihinsel modeli sıkı tutun, uygulama arkada daha fazla iş yapmak zorunda kalsa bile.
Bir öneriyi incelerken sorun: bu kullanıcıya hatırlaması gereken kavram sayısını azaltıyor mu, yoksa bir istisna daha mı ekliyor?
Miminalizm yalnızca primitifler tutarlıysa yardımcı olur. İki komut benzer görünüp uç durumlarda farklı davranırsa, kullanıcılar trivia ezberlemeye başlar. Küçük bir araç seti, kurallar ince ince değişiyorsa "keskin kenarlar"a dönüşebilir.
Bir mutfağı düşünün: iyi bir bıçak, tava ve fırın birçok yemeği teknikleri birleştirerek yapmanızı sağlar. Bir avokado dilimleyici gibi tek amaçlı alet çekmeceleri doldurur. Tcl’in felsefesi bıçak ve tavayı savunur: temizce birleşen genel araçlar, böylece her yeni tarif için yeni bir alete gerek kalmaz.
1986'da Fred Brooks, provokatif bir sonuca sahip bir makale yazdı: tek bir atılım—tek bir "gümüş mermi"—yazılım geliştirmeyi bir adımda kat kat daha hızlı, daha ucuz ve daha güvenilir yapmayacaktır.
Onun noktası ilerlemenin imkansız olduğu değildi. Yazılımın zaten neredeyse her şeyi yapabildiği bir ortam olduğunu ve bu özgürlüğün benzersiz bir yük getirdiğini; inşa ederken sürekli olarak nesnenin kendisini tanımladığımızı vurguluyordu. Daha iyi araçlar yardımcı olur, ama en zor kısmı ortadan kaldırmazlar.
Brooks karmaşıklığı iki kovaya ayırdı:
Araçlar kazara karmaşıklığı ezebilir. Yüksek seviyeli diller, versiyon kontrol, CI, konteynerler, yönetilen veritabanları ve iyi IDE'lerden kazandığımız şeyleri düşünün. Ama Brooks, esensiyel karmaşıklığın baskın olduğunu ve araçlar iyileşse bile kaybolmayacağını savundu.
Modern platformlarda bile ekipler çoğunlukla gereksinimleri müzakere etmek, sistemleri entegre etmek, istisnalarla uğraşmak ve davranışı zaman içinde tutarlı tutmak için enerji harcar. Yüzey alanı değişebilir (cihaz sürücüler yerine bulut API'leri), ama temel zorluk aynı kalır: insan ihtiyaçlarını kesin, sürdürülebilir davranışa çevirmek.
Bu, Ousterhout’un eğildiği gerilimi kurar: esensiyel karmaşıklık silinemezse, disiplinli tasarım ne kadarını kodun içine sızmaktan kurtarabilir—ve geliştiricilerin günlük kafasına daha az yük bindirebilir?
İnsanlar bazen "Ousterhout vs Brooks"u iyimserlik ile gerçekçilik arasındaki bir kavga olarak çerçeveler. Daha kullanışlı olanı, bunu aynı problemin farklı parçalarını tanımlayan iki deneyimli mühendisin açıklamaları olarak okumaktır.
Brooks’un "No Silver Bullet"i, yazılımın zor kısmını sihirli bir şekilde kaldıracak tek bir atılım olmadığını savunur. Ousterhout bunu gerçekten tartışmıyor.
Onun itirazı daha dar ve pratiktir: ekipler sık sık karmaşıklığı kaçınılmaz olarak görürken, büyük bir kısmı kendi kendilerine yarattıklarıdır.
Ousterhout’a göre iyi tasarım, karmaşıklığı anlamlı şekilde azaltabilir—yazılımı "kolay" yapmaktan ziyade değiştirmeyi daha az kafa karıştırıcı hale getirir. Bu büyük bir iddia; çünkü kafa karışıklığı günlük işleri yavaş çalışmaya dönüştürür.
Brooks esensiyel zorluğa odaklanır: yazılım, dağınık gerçekleri, değişen gereksinimleri ve kod tabanının dışında var olan uç durumları modellemelidir. İyi araçlar ve akıllı insanlar olsa bile bunları silemezsiniz; yalnızca yönetebilirsiniz.
Tartışmanın gösterdiğinden daha çok örtüşürler:
"Kim haklı?" yerine şu soruyu sorun: Bu çeyrekte hangi karmaşıklığı kontrol edebiliriz?
Ekipler piyasa değişikliklerini veya alanın temel zorluklarını kontrol edemez. Ama yeni özelliklerin özel durumlar ekleyip eklemediğini, API'ların çağırıcıları gizli kuralları hatırlamaya zorlayıp zorlamadığını ve modüllerin karmaşıklığı gizleyip gizlemediğini kontrol edebilirler.
Bu, eyleme geçirilebilir orta yol: esensiyel karmaşıklığı kabul edin ve kazara olanı acımasızca seçin.
Bir derin modül, çok iş yapan ama küçük, anlaşılması kolay bir arayüz sunan bileşendir. "Derinlik", modülün sizin tabağınızdan aldığı karmaşıklığın miktarıdır: çağıranlar karışık detayları bilmek zorunda değildir ve arayüz onları zorlamaz.
Bir sığ modül bunun tersidir: küçük bir mantığı sarabilir ama karmaşıklığı dışarı iter—çok sayıda parametre, özel bayraklar, zorunlu çağrı sırası veya "bunu hatırlamanız gerekir" kuralları aracılığıyla.
Bir restoranı düşünün. Derin modül mutfaktır: menüden "makarna" sipariş edersiniz ve tedarikçi seçimleri, kaynatma süreleri veya servis detaylarıyla ilgilenmezsiniz.
Sığ modül ise size 12 adımlı talimatla beraber çiğ malzemeler veren bir "mutfak"tır ve kendi tavanızı getirmenizi ister. İş hâlâ oluyor—ama işi müşteri yapmak zorunda.
Ek katmanlar, eğer birçok kararı tek bir bariz seçime indiriyorlarsa harikadır.
Örneğin, save(order) diye bir depolama katmanı düşünün: içerde tekrarları, serileştirmeyi ve indekslemeyi hallediyorsa derindir.
Katmanlar zarar verirken çoğunlukla sadece yeniden adlandırma yapar veya seçenek ekler. Yeni bir soyutlama kaldırdığından daha fazla konfigürasyon ekliyorsa—ör. save(order, format, retries, timeout, mode, legacyMode)—muhtemelen sığdır. Kod "düzenli" görünebilir ama bilişsel yük her çağrı noktasında görünür hale gelir.
useCache, skipValidation, force, legacy gibi boolean'lar.Derin modüller sadece kodu kapsüllemekle kalmaz. Kararları kapsüller.
"İyi" bir API sadece çok şey yapabilen bir API değildir. Üzerinde çalışırken insanların akıllarında tutabilecekleri bir şeydir.
Ousterhout’un tasarım merceği API'yı zihinsel çaba açısından yargılamanızı ister: hatırlamanız gereken kural sayısı, tahmin etmeniz gereken istisnalar ve yanlış yapmanın ne kadar kolay olduğu.
İnsan-dostu API'lar genelde küçük, tutarlı ve kötü kullanılmaya zorlayıcıdır.
Küçük, güçsüz demek değildir—yüzey alanının birkaç kavrama yoğunlaşması anlamına gelir. Tutarlı, tüm sistemde aynı desenin çalışması demektir (parametreler, hata yönetimi, isimlendirme, dönüş tipleri). Kötü kullanılmaya zorlayıcı ise API'nın sizi güvenli patikalara yönlendirmesidir: net invariants, sınırda doğrulama ve erken başarısızlık sağlayan tipler veya runtime kontroller.
Her ekstra bayrak, mod veya "sadece olası" konfigürasyon tüm kullanıcıların öğrenmesi gereken bir vergi olur. Sadece %5 çağıranın ihtiyacı olsa bile, %100 kullanıcı bunun var olduğunu öğrenmek, ihtiyacı olup olmadığını merak etmek ve diğer seçeneklerle etkileşimini yorumlamak zorunda kalır.
API'ların gizli karmaşıklığı işte böyle birikerek oluşur: tek bir çağrıda değil, kombinatorikte.
Varsayılanlar bir nezakettir: çoğu çağıranın çoğu kararı atlamasına izin verir ve yine de mantıklı davranış almasını sağlar. Konvansiyonlar (tek bariz yol) kullanıcının zihnindeki dallanmayı azaltır. İsimlendirme gerçek işle yapar: fiil ve isimler kullanıcı niyetiyle örtüşmeli ve benzer işlemler benzer şekilde adlandırılmalıdır.
Bir hatırlatma: iç API'lar kamu API'ları kadar önemlidir. Üründeki karmaşıklığın çoğu arka planda yaşar—servis sınırları, paylaşılan kütüphaneler ve "yardımcı" modüller. Bu arayüzlere ürün gibi davranın: incelemeler ve versiyonlama disiplini uygulayın (bkz. blog/deep-modules).
Karmaşıklık nadiren tek bir "kötü karar" olarak gelir. Zamanla, küçük ve makul görünen yamalarla birikir—özellikle ekipler teslim tarihi baskısı altındaysa ve anlık hedef "göndermek" ise.
Bir tuzak her yerde feature flag kullanımıdır. Flag'ler güvenli açılımlar için yararlı ama uzadıkça her flag olası davranış sayısını çarpar. Mühendisler "sistemi" düşünmeyi bırakıp "sistem, ama flag A açıksa ve kullanıcı segment B'deyse" diye düşünmeye başlar.
Diğer bir tuzak özel durum mantığıdır: "Kurumsal müşteriler X istiyor", "B bölgesinde farklı davran", "hesap 90 günden eskiyse". Bu istisnalar kod tabanına yayılır ve birkaç ay sonra kim hangi istisnanın gerekli olduğunu bilmez.
Üçüncüsü sızan soyutlamalardır. Bir API çağıranları iç detayları anlamaya zorlayınca (zamanlama, depolama formatı, cache kuralları), karmaşıklık dışarı taşar. Bir modül yükü taşıması gerekirken, her çağıran bu tuhaflıkları öğrenir.
Taktiksel programlama bu hafta için optimize eder: hızlı düzeltmeler, minimal değişiklik, "yama yap".
Stratejik programlama gelecek yıl için optimize eder: aynı hata sınıfını engelleyecek küçük yeniden tasarımlar.
Tehlike "bakım faizi"dir. Hızlı bir çözüm şimdi ucuz gelir, ama faiziyle geri ödersiniz: daha yavaş işe alıştırma, kırılgan sürümler ve kimsenin eskilere dokunmak istemediği bir kültür.
Kod incelemelerine şu kısa soruları ekleyin: "Bu yeni bir özel durum ekliyor mu?" "API bunu gizleyebilir mi?" "Geride hangi karmaşıklığı bırakıyoruz?"
Önemli tradeoff'lar için kısa karar kayıtları tutun (birkaç madde yeterli). Ve her sprint'e küçük bir refactor bütçesi ayırın ki stratejik düzeltmeler ekstrakomut iş gibi görülmesin.
Karmaşıklık mühendislikle sınırlı kalmaz. Zaman çizelgelerine, güvenilirliğe ve müşterilerin ürün deneyimine sızar.
Bir sistem anlaşılması zor olduğunda, her değişiklik daha uzun sürer. Piyasaya çıkış gecikir çünkü her sürüm daha fazla koordinasyon, daha fazla regresyon testi ve daha fazla "emin olmak için" inceleme döngüsü gerektirir.
Güvenilirlik de zarar görür. Karmaşık sistemler kimsenin tamamen tahmin edemeyeceği etkileşimler yaratır; hatalar kupona, kayıtlı sepete ve bölgesel vergi kuralına bağlı olarak yalnızca belirli kombinasyonlarda ortaya çıkar. Bu tür olaylar yeniden üretmesi en zor ve düzeltmesi en yavaş olanlardır.
İşe alıştırma gizli bir yük olur. Yeni ekip üyeleri kullanışlı bir zihinsel model kuramadığı için riskli alanlara dokunmaktan kaçınır, anlamadan kalıp kodları kopyalar ve istemeden daha fazla karmaşıklık ekler.
Müşteriler davranışın bir "özel durum"tan mı kaynaklandığını umursamaz. Onlar bunu tutarsızlık olarak yaşar: ayarlar her yerde geçerli değil, akış geldiğiniz yola göre değişiyor, özellikler "çoğu zaman" çalışıyor.
Güven azalır, churn artar ve benimseme durur.
Destek ekipleri uzun ticket'lar ve daha fazla açıklama alma maliyetiyle karmaşıklığı öder. Operasyon ise daha fazla alarm, daha fazla runbook ve daha dikkatli dağıtımlarla öder. Her istisna izlenecek, dokümante edilecek ve açıklanacak bir şeye dönüşür.
"Bir bildirim kuralı daha" isteğini düşünün. Eklemek hızlı gibi görünür ama davranışta yeni bir dal, daha fazla UI metni, daha fazla test vakası ve kullanıcıların yanlış yapılandırabileceği daha fazla yol getirir.
Bunu mevcut bildirim akışını basitleştirmekle karşılaştırın: daha az kural tipi, net varsayılanlar ve web ile mobil arasında tutarlı davranış. Daha az düğme sunabilirsiniz ama sürprizleri azaltır—ürünü kullanması, desteklemesi ve geliştirmesi daha kolay olur.
Karmaşıklığı performans veya güvenlik gibi planlayın, ölçün ve koruyun. Karmaşıklığı ancak teslimat yavaşladığında fark ediyorsanız, zaten faiz ödemeye başlamışsınız demektir.
Özellik kapsamının yanı sıra, bir sürümün getirebileceği net yeni karmaşıklık miktarını da tanımlayın. Bütçe basit olabilir: "net-yeni kavram yoksa yeni kavram eklenebilir" veya "her yeni entegrasyon bir eski yolu değiştirmeli".
Planlamada takasları açıkça belirtin: bir özellik üç yeni konfigürasyon modu ve iki istisna gerektiriyorsa, bu mevcut kavramlara uyan bir özellikten daha pahalı olmalıdır.
Mükemmel sayılara ihtiyacınız yok—doğru yönde trend gösteren sinyaller yeterlidir:
Bunları sürüm başına takip edin ve kararlarla ilişkilendirin: "İki yeni public opsiyon ekledik; telafi etmek için neyi kaldırdık veya sadeleştirdik?"
Prototipler genellikle "yapabilir miyiz?" ile değerlendirilir. Bunun yerine şunu cevaplamasını sağlayın: "Bu kullanması basit ve yanlış kullanması zor mu hissettiriyor?"
Biri özelliğe aşina olmayan birine gerçekçi bir görev verin. Başarıya ulaşma süresini, sorulan soruları ve yanlış varsayımları ölçün. Buralar karmaşıklık sıcak noktalarıdır.
Modern build iş akışları kazara karmaşıklığı azaltabilir—eğer iterasyonu sıkı tutar ve hataları geri almayı kolaylaştırırsa. Örneğin ekipler, bir iç aracı veya yeni bir akışı sohbet üzerinden tasarlamak için Koder.ai gibi bir platform kullandığında, planning mode (niyeti netleştirme) ve snapshots/rollback (riskli değişiklikleri hızlıca geri alma) gibi özellikler erken denemeyi daha güvenli hissettirebilir—yarım kalmış soyutlamalar yığınına commit etmeden. Prototip başarılı olursa, kaynak kodu dışa aktarabilir ve yukarıda anlatılan "derin modül" ve API disipliniyle üretime taşıyabilirsiniz.
"Karmaşıklık temizliği" işini periyodik (her çeyrek veya büyük bir sürümde) yapın ve "bitti"nin ne anlama geldiğini belirleyin:
Amaç soyut olarak daha temiz kod değil—daha az kavram, daha az istisna ve daha güvenli değişiklik yapabilme yeteneğidir.
Ousterhout’un "karmaşıklık düşmandır" fikrini hafta haftaya çeviren birkaç hamle:
Bir sistem seçin ki sık sık kafa karışıklığına neden olsun (işe alıştırma sıkıntısı, tekrarlayan hatalar, "bu nasıl çalışıyor?" soruları).
Yapabileceğiniz iç takipler: planlamada bir "karmaşıklık incelemesi" ve araçlarınızın kazara karmaşıklığı azaltıp azaltmadığını hızlı bir kontrol (blog/complexity-review ve pricing referanslarını dahili olarak kontrol edin).
Bu hafta sadece tek bir özel durumu silebilseydiniz, ilk olarak hangi karmaşıklığı kaldırırdınız?
Karmaşıklık, bir değişiklik yaptığınızda sistemin beklediğiniz şekilde mi davranacağıyla gerçekte nasıl davrandığı arasındaki boşluktur.
Bunu küçük düzenlemelerin riskli hissettirdiği durumlarda fark edersiniz çünkü hangi testlerin, servislerin, konfigürasyonların veya uç durumların etkilenebileceğini öngöremiyorsunuz.
Muhakemenin pahalı olduğunu gösteren işaretlere bakın:
Essensiyel (temel) karmaşıklık alandan gelir (regülasyonlar, gerçek dünya uç durumları, iş kuralları). Bunu silemezsiniz—ancak iyi modelleyebilirsiniz.
Kazara (accidental) karmaşıklık kendi yarattığımız zorluklardır (sızan soyutlamalar, tekrar eden mantık, çok fazla mod/flag, belirsiz API'lar). Bu kısım tasarım ve sadeleştirme ile güvenilir şekilde azaltılabilir.
Bir derin modül, çok iş yapan ama küçük, stabil bir arayüz sunan bileşendir. Tekrar denemeler, formatlar, çağrı sırası ve invariants gibi karmaşık detayları içerde tutar, böylece çağıranların bilmesine gerek kalmaz.
Pratik bir test: Çoğu çağıran, modülün iç kurallarını bilmeden doğru şekilde kullanabiliyorsa modül derindir; eğer çağıranların kural ve sıra ezberlemesi gerekiyorsa modül sığdır.
Yaygın belirtiler:
legacy, skipValidation, force, mode).Aşağıdaki özellikleri tercih edin:
"Bir seçenek daha ekleyeyim" diye düşündüğünüzde önce, çoğu çağıranın o seçeneği düşünmesine gerek kalmayacak şekilde arayüzü yeniden tasarlayıp tasarlamayacağınızı sorun.
Feature flag'leri kontrollü dağıtımlar için kullanın, sonra bunları borç olarak görün ve bir bitiş tarihi koyun:
Uzun ömürlü flag'ler, mühendislerin düşünen sistem sayısını katlar.
Planlamada karmaşıklığı açıkça dahil edin, sadece kod incelemede değil:
Amaç, karmaşıklığın kurumsallaşmadan önce açıkça tartışılmasını sağlamaktır.
Taktiksel programlama bu hafta için optimize eder: hızlı yamalar, minimal değişiklik, "gönder".
Stratejik programlama önümüzdeki yıl için optimize eder: tekrarlayan hata sınıflarını ortadan kaldıracak küçük yeniden tasarımlar ve gelecekteki işi azaltan çözümler.
Kullanışlı bir kestirim: Eğer bir düzeltme çağıranın bilgisi gerektiriyorsa ("önce X'i çağır" veya "prod'ta sadece bu bayrağı ayarla"), muhtemelen modülün içine gizleyeceğiniz daha stratejik bir değişiklik gerektirir.
Tcl'den alınacak kalıcı ders: küçük bir primitif seti ve güçlü kompozisyonun gücü—çokça gömülü "glue" katmanı.
Modern eşdeğerler:
Tasarım hedefi aynı: çekirdeği basit ve stabil tutun, değişimi temiz arayüzlerle yönlendirin.
Sığ modüller genelde "düzenli" görünür ama karmaşıklığı her çağırana taşır.