4 puan yazan GN⁺ 2024-10-30 | 1 yorum | WhatsApp'ta paylaş
  • Kod, yazıldığı anda bakım maliyeti doğurur; bu yüzden çoğu zaman yeniden kullanılabilirlikten ziyade ileride silmesi veya değiştirmesi kolay bir yapı daha önemlidir
  • API kullanıcıları arttıkça değişiklik maliyeti büyür; üçüncü taraf API bağımlılığı derinleştikçe dış değişimler kod tabanını daha fazla sarsar
  • Tekrar, boilerplate, katmanlama, büyük kod yığınları, modül ayırma ve özellik bayrakları, duruma göre bağımlılık yönetimi araçlarına dönüşür
  • İyi ayrıştırma, ortak işlevleri bir araya toplamak değil; değişmesi zor ya da değişme olasılığı yüksek tasarım kararlarını birbirinden gizlemeye daha yakındır
  • İyi kod, en baştan kusursuz kod değil; zaman geçse de daha az engel çıkaran legacy koddur ve nihayetinde silmesi kolay koddur

Kod maliyettir, silmek maliyeti düşürmektir

  • Her kod, yazıldığı anda bakım maliyeti yaratır; yeniden kullanım kod miktarını azaltabilir ama sonradan fikir değiştirmeyi zorlaştırabilir
  • Bir API’yi kullanan kod ne kadar çoksa, API değişiklikleri de o kadar fazla yeniden yazma maliyeti getirir
  • Üçüncü taraf API’lere ne kadar çok bağımlı olursanız, o API değiştiğinde alacağınız etki de o kadar büyük olur
  • Büyük ölçekli sistemlerde, kodun birbirine nasıl geçtiği ve hangi parçanın hangi parçaya bağımlı olduğu zaman geçtikçe daha zor bir mesele hâline gelir
  • Kod satırı sayısına “üretilen satır” değil “harcanan maliyet” olarak bakarsanız, kod silmek bakım maliyetini düşürmek demektir
  • Amaç yalnızca yeniden kullanılabilir yazılım yapmak değil, atılabilir yazılım yapmaktır

0. adım: Kod yazmamak

  • Kod satırı sayısı tek başına her şeyi anlatmaz; ama 50 satır, 500 satır, 5.000 satır, 10.000 satır, 25.000 satır gibi ölçek önemlidir
  • 1 milyon satırlık bir monolith’i değiştirmek, 10 bin satırlık bir monolith’i değiştirmekten daha fazla zaman, para ve emek ister
  • Kod arttıkça ortadan kaldırması zorlaşır; ama tek bir kod satırını azaltmak neredeyse hiçbir şey tasarruf ettirmez
  • Silmesi en kolay kod, en başta yazılmamış koddur

1. adım: Kopyala-yapıştır yapmak

  • Yeniden kullanılabilir kodu gelecekteki kullanım yerlerini tahmin ederek önceden yazmaktansa, birden fazla kullanım senaryosu gerçekten ortaya çıktıktan sonra yazmak daha kolaydır
  • Kod tabanında birkaç kez kopyala-yapıştır yapmak, gerçek kullanım biçimlerini anlamak için iyi bir yoldur
  • Bir kodu paylaşılan API hâline getirdiğiniz anda o kodu değiştirmek zorlaşır
  • Bir fonksiyonu çağıran kod, yalnızca belgelenmiş davranışa değil, uygulamada gözlenen kasıtlı ve kasıtsız davranışlara da bağımlı hâle gelir
  • Bir fonksiyonun içindeki kodu silmek, fonksiyonun kendisini silmekten daha basittir

2. adım: Kopyala-yapıştırı durdurmak

  • Yeterince tekrarlanmış kodu fonksiyona çıkarmanın zamanı gelmiş demektir
  • Yapılandırma dosyasını açıp hash table döndüren kod, dizin silme kodu gibi standart kütüphane üzerinde sık gereken utility türü kodlar buna girer
  • utili tek bir dosya yerine dizin olarak tutup farklı utility’leri farklı dosyalara koymak daha iyidir
    • Tek bir util dosyası büyümeye devam eder; fazla büyüdükten sonra bölmek zorlaşır
  • Uygulamaya veya projeye daha az özgü kodun yeniden kullanımı daha kolaydır; değişme ya da silinme olasılığı daha düşüktür
    • Loglama, üçüncü taraf API’ler, file handle’lar, process’ler gibi kütüphane kodları buna girer
    • Listeler, hash table’lar ve collection’lar yalnızca basit arayüzleri nedeniyle değil, zamanla kapsamları büyümediği için de kolay kolay silinmez
  • Esas nokta, silmesi zor kısımları silmesi kolay kısımlardan olabildiğince uzak tutmaktır

3. adım: Daha fazla boilerplate yazmak

  • Kütüphane yazmak kopyala-yapıştırı önleyebilir; ama pratikte kütüphaneyi kullanmak için bol miktarda boilerplate yazarsınız
  • Boilerplate, her seferinde biraz farklı yerleri değiştirmeniz bakımından kopyala-yapıştırmaya benzer
  • Bu tür tekrar, bağımlılıkları azaltıp esneklik kazanmanın bedeli olarak söze döküklüğü kabullenme biçimidir
  • Boilerplate gerektiren kütüphaneler çoğu zaman ağ protokolleri, wire format’lar, parsing araçları gibi politika ile protokolün karıştırılmasının zor olduğu durumlardır
    • Protokol, programın ne yapabileceğiyle ilgilenir
    • Politika, programın ne yapması gerektiğiyle ilgilenir
  • Bu tür kodlar çoğunlukla başka bilgisayarlarla iletişim kurmak veya başka dosyalarla çalışmak için gereken şartlardır; bu yüzden silmeleri zordur
  • İş mantığını bu kodların içine serpiştirmemek önemlidir
  • Daha fazla satır yazacaksanız bile, bu satırları silmesi kolay kısımlarda yazmak daha iyidir

4. adım: Boilerplate yazmamak

  • Boilerplate fazla çoğaldığında, esnek kütüphaneyi saran; politika, workflow ve durum hakkında görüş sahibi bir kütüphane yazmanın zamanı gelmiştir
  • Kullanımı kolay bir API yapmak, boilerplate’i kütüphaneleştirmeye yakındır
  • Python HTTP istemcisi requests, daha uzun ve ayrıntılı urllib3 üzerinde basit bir arayüz sunan bir örnektir
    • requests, HTTP kullanımının yaygın workflow’unu ele alır ve pratik ayrıntıları gizler
    • urllib3, pipelining, bağlantı yönetimi vb. sağlar ve ayrıntıları kullanıcıdan gizlemez
  • Bir kütüphaneyi başka bir kütüphaneyle sarmak yalnızca ayrıntıları gizlemek değil, concern separationdır
  • util dizinine iş mantığı koymamak; uygulaması basit kütüphanelerin üzerine kullanımı kolay kütüphaneler yığmak daha iyidir
  • Üçüncü taraf kütüphaneleri de sarmanın iyi olduğu durumlar vardır
    • Tüm projenin belirli bir seçime kilitlenmemesi için kendi kodunuza uyan bir kütüphane oluşturabilirsiniz
  • Kullanımı iyi API ile genişletilebilir API çoğu zaman birbiriyle çatışır
  • Katmanlama, ileride silinecek kod yazmaktan ziyade, silmesi zor kodu iş mantığıyla kirletmeden kullanımı kolay hâle getirmeye daha yakındır

5. adım: Büyük kod yığınları yazmak

  • Kopyala-yapıştır, refactoring, katmanlama ve composition yapsanız da kodun eninde sonunda bir iş yapması gerekir; bu yüzden bazen geri kalanı bir arada tutan büyük bir kod yığınına ihtiyaç olur
  • İş mantığı, bitmeyen edge case’ler ve hızlı hack’lerle tanımlanabilir
  • Oyun kodu veya kurucu kodu da önemli ölçüde zaman kazanmak için kestirme yollar seçen aynı tür kod olarak görülebilir
  • Birbirine dolanmış 18 küçük hatayı ortadan kaldırmaktansa tek bir büyük hatayı silmek bazen daha kolaydır
  • Programlamanın çoğu keşifseldir; bu yüzden en baştan doğruyu tutturmaya çalışmaktansa birkaç kez yanılıp yinelemek daha hızlı olabilir
  • İlk oyununuzu yaparken önce motor yazmayın; bir uygulama yazmadan önce web framework’ü yapmaya kalkmamak daha iyidir
  • Monorepo da benzer bir ödünleşimdir
    • Kodu önceden nasıl böleceğinizi bilmek zordur ve güçlü biçimde bağlı 20 parçadansa tek büyük hata dağıtmak daha kolaydır
  • Kodun yakında atılacağını, silineceğini veya kolayca değiştirileceğini biliyorsanız daha fazla kestirme yol seçebilirsiniz
  • Amaç aynı çamur yığınını on kez tekrarlayıp hatayı mükemmelleştirmek değil; her seferinde yeni hatalar yapıp yeni riskler alarak iterasyonla biriktirmektir
  • Projeler sonunda ya başarısız olur ya da legacy code’a dönüşür; başarısızlık başarıdan daha sık yaşanır
  • Kodu parça parça silmektense tamamını silmek daha kolaydır

6. adım: Kodu parçalara ayırmak

  • Büyük çamur yığınını yapmak en kolaydır ama bakım maliyeti en yüksektir
  • Basit görünen bir değişiklik, kod tabanının neredeyse her yerini geçici çözümlerle kurcalamanıza yol açabilir
  • Bütün hâlinde silmesi kolay olan kod, parça parça silmesi zor hâle gelir
  • Modülleri ortak işlevlere göre değil; geri kalanla paylaşılmayan şeylere ve gizlenmesi gereken tasarım kararlarına göre ayırmak daha iyidir
  • D. Parnas’ın ölçütü gibi, zor veya değişme olasılığı yüksek tasarım kararlarını listeleyip her modülü bu kararları diğer modüllerden gizleyecek şekilde tasarlayabilirsiniz
  • Modüller yeniden kullanım için değil, değişebilirlik için yapılır
  • Tek sorumluluk ilkesi, “her modül yalnızca tek bir zor problemle ilgilenmeli” diye görülebilir; ama daha önemli olan, “her zor problem yalnızca tek bir modülde ele alınmalı” noktasıdır
  • Bir modül iki iş yapıyorsa, çoğu zaman bir tarafı değiştirmek için diğer tarafı da değiştirmeniz gerektiği içindir
  • Basit arayüzlü korkunç tek bir component, dikkatli koordinasyon gerektiren iki component’ten daha kolay olabilir

Gevşek bağlılık ve ortak arayüz

  • Diğer kısımları yeniden yazmadan bazı parçaları silebildiğiniz sistemlere genellikle gevşek bağlı denir
  • Gevşek bağlılık, fikir değiştirdiğinizde çok fazla kodu değiştirmeniz gerekmeyen duruma yakındır
  • Bir değişkeni bir kez hardcode etmek, değişken yerine komut satırı flag’i kullanmak bile duruma göre gevşek bağlılık olabilir
  • Microsoft Windows, dış API ile iç API’yi ayırarak bu amaca ulaşır
    • Dış API, masaüstü programlarının yaşam döngüsüne bağlıdır
    • İç API, temel kernel’a bağlıdır
    • API’yi gizlemek, çok sayıda yazılımı bozmadan esneklik sağlar
  • HTTP de gevşek bağlılığa örnek sunar
    • HTTP sunucusunun önüne cache koyabilirsiniz
    • Görselleri CDN’e taşıyıp yalnızca linkleri değiştirseniz de tarayıcı bozulmaz
    • HTTP hata kodları, yaygın problemlere benzersiz kodlar vererek client’ın çok sayıda hatayı onun yerine ele almasını sağlar
  • Arıza işleme biçimi, kodu küçük parçalara bölerken birlikte düşünülmelidir

Arıza yönetimi ve bağlılık

  • Erlang/OTP, arızaları supervision tree ile ele alan görece özgün bir yöntem kullanır
  • Erlang sistemindeki her process kabaca bir supervisor tarafından başlatılır ve izlenir
    • Process’te sorun çıkarsa sonlandırılır
    • Process sonlanırsa supervisor onu yeniden başlatır
    • Supervisor’ı bootstrap process başlatır; supervisor’da arıza olursa bootstrap process onu yeniden başlatır
  • Temel fikir, hatayı işlemeye çalışmaktansa hızlı başarısız olup yeniden başlamanın daha hızlı olduğudur
  • Geçici arızalar bazen kapatıp açma yöntemiyle bastırılır
  • Hata işleme ve kurtarma işlerini kod tabanının dış katmanlarında yapmak daha iyidir; bu end-to-end principle olarak bilinir
  • Hataları bağlantının ortasında değil iki ucunda ele almak daha kolaydır; içeride ele alınsa bile en üst seviye kontrol yine gerekir
  • Hata işleme, sistemi güçlü biçimde birbirine bağlayan birçok yoldan biridir

IMAP, dosya sistemleri, SQL, middleware

  • IMAP, neredeyse her işlemin kendine özgü seçenek ve işleme sahip istisnai bir biçim olduğu; bu yüzden hata işlemenin sancılı olduğu bir örnektir
  • IMAP’te hata, başka işlem sonuçlarının ortasında belirebilir
  • UUID yerine her mesajı tanımlamak için benzersiz token’lar üretir; bu token’lar da işlem sonuçlarının ortasında değişebilir
  • Birçok IMAP işlemi atomic değildir
  • E-postayı bir klasörden diğerine güvenilir biçimde taşımanın bir yolunun ortaya çıkması 25 yıldan fazla sürdü
  • Özel UTF-7 encoding’i ve kendine özgü base64 encoding’i de vardır
  • Dosya sistemleri ve veritabanları, uzak depolama için daha iyi karşılaştırma örnekleri sunar
    • Dosya sistemi sabit bir işlem kümesine ve birden fazla nesneye sahiptir
    • SQL, dosya sisteminden daha geniş bir arayüz gibi görünür; ama kümeler üzerinde birden fazla işlem ve birden fazla satır örüntüsünü izler
  • Veritabanları her zaman birbirinin yerine geçemez; ama kendi sorgu dilinizi yazmaktansa SQL ile çalışan bir şey bulmak daha kolaydır
  • Twitter’ın Finagle’ı, servisler için ortak bir API kullanarak timeout işleme, retry mekanizması ve kimlik doğrulama kontrollerinin istemci ve sunucu koduna kolayca eklenmesini sağlar
  • Gevşek bağlılığın iyi örnekleri çoğu zaman tekdüze arayüz örnekleridir de
  • Sağlıklı bir kod tabanının kusursuz modüler olması gerekmez; ama hareketli parçalar arasında yeterli mesafe olmalıdır
  • Gevşek bağlı kodun silmesi illa kolay değildir; ama değiştirmesi ve yerine başkasını koyması çok daha kolaydır

7. adım: Kod yazmaya devam etmek

  • Eski kodla uğraşmadan yeni kod yazabiliyorsanız yeni fikirleri denemek çok daha kolaydır
  • Esas mesele microservice mi monolith mi olduğu değil; ne yaptığınızı anlamaya çalışırken sistemin üzerine bir iki deney koyabilmenizdir
  • Özellik bayrakları, sonradan fikir değiştirebilmenin bir yoludur
  • Özellik bayrakları yalnızca özellik denemeleri değil, yazılımı yeniden dağıtmadan değişiklikleri dağıtmayı da mümkün kılar
  • Google Chrome, düzenli yayın döngüsünde uzun ömürlü feature branch’leri birleştirmenin en zor kısım olduğunu gördü
  • Yeni kodu yeniden derlemeden açıp kapatabiliyorsanız büyük değişiklikleri küçük merge’lere bölebilir ve mevcut kodu etkilemeyebilirsiniz
  • Yeni özellik aynı kod tabanında daha erken görünürse, uzun vadeli özellik geliştirmenin diğer kısımlara etkisini daha net görebilirsiniz
  • Özellik bayrağı basit bir komut satırı anahtarı değil; özellik yayınını branch merge’ünden ve kod dağıtımından ayırmanın bir yoludur
  • Yeni yazılım dağıtımı saatler, günler, haftalar alabildiğinde runtime’da fikir değiştirebilme yeteneği daha da önemli hâle gelir

İyi kod, engel çıkarmayan legacy koddur

  • Yineleme yapmanızdan daha önemli olan, bir geri bildirim döngüsüne sahip olmanızdır
  • Modülleri yeniden kullanım için yapmak yerine, değişiklik için component’leri izole etmek esastır
  • Değişime yanıt vermek, yalnızca yeni özellik geliştirmeyi değil eski özellikleri kaldırmayı da kapsar
  • Genişletilebilir kod yazmak, üç ay sonra ilk seçimin hâlâ doğru olmasını ummaktır
  • Silinebilir kod bunun tersi varsayımdan yola çıkar
  • Katmanlama, izolasyon, ortak arayüz ve composition; iyi yazılımın kendisinden ziyade zamanla değişebilen yazılım üretmenin yollarıdır
  • Her şeyi atmanız gerekmez ama bazı şeyleri silmeniz gerekir
  • İyi kod, en baştan doğru yazılmış kod değil; engel çıkarmayan legacy koddur
  • İyi kod silmesi kolay koddur

1 yorum

 
GN⁺ 2024-10-30
Hacker News yorumları
  • Sevdiğim sözlerden biri şudur: basitlik sağlamlıktır
    Lehman’ın sürekli değişim yasasına benzer şekilde, bir sistemin karmaşıklığı ne kadar düşükse onu değiştirmek de o kadar kolay olur demek
    Geleceğe hazırlık için genişletilebilir kod yazmaktansa, sezgisel kod ile geleceğe hazırlanmanın daha iyi olduğunu düşünüyorum
    Örneğin soyutlamayı yalnızca gerçekten gerektiğinde yapmak, basit tekrarları kabul etmek, başlangıçta monolit olarak başlamak ve yatay ölçeklemeden önce dikey ölçeklemeyi denemek gibi
    Birden fazla 0→1 sistem geliştirdim; hepsinde ortak akış bu yöndeydi
    https://en.m.wikipedia.org/wiki/Lehman%27s_laws_of_software_...

    • Doğru, ama basitlik sağlamlıktır ilkesini uygularken içsel karmaşıklığı da anlamak gerekir
      Uç durumları ele almamak kodu sağlam yapmaz; ne kadar daha basit görünürse görünsün
    • Benim izlediğim kural şöyle: ilkini sadece yaz, ikincisini kopyala, üçüncüde refactoring’i düşün
    • Katılıyorum ama simple is robust ifadesinin yeterince sezgisel olup olmadığından emin değilim
      “Basitlik” nedir ve sisteme nasıl uygulanır tartışması açılıyor; Rich Hickey’nin ele alacağı kadar karmaşık bir soru bu
      Belki “aptal olan sağlamdır” ya da “dolaysız olan sağlamdır” niyeti daha iyi anlatabilir
    • Çok güçlü biçimde katılıyorum. Yazılımdaki çok fazla çöp, hayali sorunları çözmeye çalışmaktan çıkıyor
      Sadece gereken işi yapan kodu yazmak yeterli. Varsayımsal ölçekleme sorunları icat etmeyin, akıllı görünmek için zeki soyutlamalar üretmeyin; monolit olarak yazıp bir VM’e koyarsanız hemen üretime alınabilir
      Sorun çıkarsa o zaman çözersiniz; mümkünse nakit akışı pozitife döndükten sonra olması daha iyi
      0 kullanıcılı “köpekler için AirBnb” girişimi neden C100K’yı dert ediyor? AWS’nin sizi serverless’a para ödemeye ikna etmesi sizin çıkarınız için miydi, yoksa sizden para çekmek için mi
    • İş mantığının karmaşıklığı istemekle ortadan kalkmaz. Çok büyük ve birbirine dolanmışsa kod da öyle olur
  • İlgili yazılar:
    Write code that is easy to delete, not easy to extend (2016) - https://news.ycombinator.com/item?id=24989351 - Nov 2020 (30 comments)
    Write code that is easy to delete, not easy to extend (2016) - https://news.ycombinator.com/item?id=23914486 - July 2020 (109 comments)
    Write code that is easy to delete, not easy to extend - https://news.ycombinator.com/item?id=18761739 - Dec 2018 (2 comments)
    Write code that is easy to delete, not easy to extend - https://news.ycombinator.com/item?id=11093733 - Feb 2016 (133 comments)

  • Gençken yaptığım hataları kısaca özetlemek gerekirse, artık tersine silmek için tasarıma inanıyorum
    Eskiden her durumu öngören ve her gereksinimi karşılayan harika bir sanat eseri yapabileceğimi sanırdım. Ama kimse gelecekteki gereksinimleri bu kadar iyi tahmin edemez
    Bir gün yaptığım şey birinin gözünde “şu aptal şey” olacak ve ben bugün onunla ne kadar gurur duyarsam duyayım, onların hepsini yıkıp atması haklı olabilir
    Bu yüzden kaldırması kolay hale getirmeye enerji harcamak daha iyi. Bu çoğu zaman bağımlılığı azaltır; ama önemli nokta, bunun her şeyi meta yapılandırılabilir bir framework’e ayırmaya hevesli genç geliştiricinin bağımlılıktan arındırmasıyla aynı şey olmamasıdır
    Bazen anlaşılması kolay güçlü bağlılık daha iyi olabilir
    https://news.ycombinator.com/item?id=41219130

    • Bir şeyi kaldırması kolay yapabilirsiniz, ama başkaları memnuniyetle soyutlamalar ve mantıklar oluşturup bunları projenin çekirdeğine gömer; sonra da kaldırılması imkânsız bir seviyede katılaştırabilir
      Örneğin CommonExcelFileParser, CommonExcelFileParserUtilities, HasExcelParseStatus, ProductImportExcelParser, ProductImportExcelParserView, ProductImportExcelParserResultHandler gibi şeyler ortaya çıkar ve çevredeki kodun temeli haline gelir
      Bir frontend projesine React veya Angular ile başlarsanız başka bir şeye taşımak Sisifos’un işi haline gelir; buna benzer
      Gerçekte insanlar bütün bir platform inşa eder ve gelecekte sorun çıkaracak seçimler olsa bile, bağlılık nedeniyle refactoring yapmak az soyutlanmış bir kod tabanına kıyasla çok daha zorlaşır
      İnsanlar KISS ve YAGNI uygulayıp silmesi kolay kod yazmaktansa böyle şeyleri daha çok seviyor gibi; böyle olduğunda ne yapmak gerektiğini bilmiyorum
    • Yine de duruma bağlı. İş uygulaması ise evet; hem de on kez evet
      İş gereksinimleri değişir ve hareket eder; bu yüzden onları tahmin etmeye çalışmayın, değiştirmesi ya da atması kolay şeyler yazın
      Framework’ler ve kütüphaneler biraz farklıdır. Dünyadaki değişime uyum sağlamaları gerekir ama bunu çok daha ılımlı bir hızda yapmaları yeterlidir
      En büyük sorun, Rails veya Asp.Net gibi bir framework’ün zaten kullanıldığı iş uygulamalarında geliştiricilerin bir de “framework” yapmak istemesidir
    • Bazı şeyler değişir ve bazen yanlış soyutlamayı seçersiniz
      Linux çekirdeği yazmıyorsanız Linux çekirdeği gibi yazmamalısınız
  • Bu yazıda testler ve gözlemlenebilirlik konusuna hiç değinilmemesi epey tuhaf
    Testlerin de bakım maliyeti var, ama bir şeyi kaldırdığınızda bir şeyleri bozma riskini azaltırlar
    Üstelik bir servisi dış çağıranlara açtıysanız, bazı çağrıları kullanımdan kaldırılacak olarak işaretleyip daha sonra silebilmenin sağlam bir yoluna da, hâlâ çağrılıp çağrılmadığını ve kimin çağırdığını gözlemlemenin bir yöntemine de ihtiyacınız var
    Yakın zamanda dışa açık bir GraphQL resolver’ı ilk kez yarı otomatik biçimde kaldırdık; belirli bir resolver’ın ne kadar sık kullanıldığına dair metrikler zaten vardı, bunları parse ederek silinemeyecek resolver’ların listesini elde ettik
    GraphQL’de zaten deprecated annotation var, ama bizim servisimiz bu annotation’ı özel olarak işlemiyordu
    Bu yüzden deprecated bir fonksiyon çağrıldığında bunu gösteren gözlemlenebilirlik ekledik ve prod ortamında yeterince uzun süre çalıştırdıktan sonra, dışa açık kodu güvenle silebilir hâle geldik

    • Biraz basitleştirirsek, silmesi kolay şeyler yaptığınızda silerken istemeden bug üretmezsiniz
      Aşırı karmaşık hâle getirmeye başlarsanız her şey birbirine bağlı bir karmaşaya dönüşür ve geliştirici bir değişikliğin neyi etkileyeceğini bilemez
      Elbette bunu berbat etmenin birçok yolu var. Aptalca “en iyi pratik” ilkelerini izleyebilirsiniz ya da hangi servisi kimin tükettiğini bilmediğiniz bir şekilde “mikroservis” yapabilirsiniz. Ama o zaman silmesi kolay bir şey yapmış olmazsınız
      Dış tüketim iyi bir örnek. Bir servisi devreden çıkarma konusunda tüketicilere makul bir uyarı vermek mantıklıdır; ama istediğinizde gerçekten kapatamıyorsanız kolayca silinecek şekilde tasarlanmış bir sistem değildir
      Doğru yaklaşım buysa öyle yapabilirsiniz. Yalnız testlerin ve gözlemlenebilirliğin bir şeyin kırılıp kırılmadığını size söylemesini beklemek muhtemelen pek iyi çalışmaz
      Testlere karşı değilim, ama uzun ve karmaşık bir zincirde bir şeyi kırıp kırmadığınızı söyleyen bir güvenlik mekanizması olarak olağanüstü olduklarını söylemek zor. Çünkü gerçekten koruma sağlayacak test kapsamına sahip olmak da çok zordur
    • Kod satırı sayısı fazlaysa buna belli ölçüde orantılı test satırı sayısı da olacağını bekleyebilirsiniz
      Kodun bir kısmını silerseniz testlerin de bir kısmını silebilirsiniz
      Yazıdaki gibi yalnızca koddan bahsedilip testler üzerindeki ilgili etkilerin örtük olarak dahil edildiği düşünülebilir
      Yazı testlerden bahsetmedi diye test yazmayın dediği varsayılamaz
    • Testler iyidir ama programlama yalnızca test yazmaktan ibaret değildir. Her yazıda testlerden söz etmek gerekmez
  • Şu bölüme bakınca başlığın her zaman doğru olmadığını hissediyorum: silmesi kolay kod çoğu zaman genişletmesi de kolay kod olur
    Çünkü katmanlıdır, modülerdir ve arayüzler ya da başka tip sözleşmeleri gibi soyutlamalar üzerinden farklı parçaları birbirinden yalıtır

  • Hesaplamalı fizik öğrencilerine en iyi hesaplamanın, hiç yapmak zorunda kalmadığınız hesaplama olduğunu söyleyegeldim

  • Kişisel olarak kodu iki parçaya ayırıyorum: iş mantığı ve gerçek implementasyon
    İş mantığı doğası gereği yinelenebilir, ama teknik ayrıntılar çok fazla yinelenmemeli
    Gerçek implementasyon, iş mantığını doğrudan barındırmadığı ve uygulamadan bağımsız tutulduğu sürece istediği kadar dağınık olabilir
    Böyle yaptığınızda bir şeylerin berbat ve düzgün çalışmadığını fark ettiğinizde, implementasyondan gerçek spesifikasyonu geriye doğru izleyip zorla düzeltmek yerine tüm implementasyonu silip atma seçeneğiniz olur

  • İlk paragraftaki “kod yeniden kullanımının sorunu, daha sonra fikrinizi değiştirmenizi engellemesidir” ifadesi bariz bir hata
    Genel olarak söylersek yanlış. Fikriniz değiştiğinde kod on yere kopyala-yapıştır yapılmışsa on yeri düzeltmeniz gerekir
    Buna karşılık bir fonksiyonun içindeyse bir kez değiştirmeniz yeter. On çağrıdan birinin değişmemesi gerektiğini sonradan fark etseniz bile, o noktada kopyala-yapıştır yapabilir ya da fonksiyonu daha genel hâle getirebilirsiniz
    Karşıdan karşıya geçerken bakmadan geçmek gibi, kopyala-yapıştır neredeyse her zaman kötü bir fikirdir

    • Benim deneyimime göre kötü kopyala-yapıştır kodu, sinir bozucu bir öğleden sonralık teknik borç ödeme ve düzeltmeyle biter
      Ama kötü soyutlama aylar süren teknik borç ödemesine yol açar
      Elbette cevap “kötü soyutlamalar yapmayın”dır; ama ekipler ve değişen ürün gereksinimleri içinde bunun nasıl sonuçlandığını hepimiz biliyoruz
    • Yeniden kullanılan kod çoğu zaman birden çok yerde doğru koddur; bu yüzden değiştirmek için yavaşlayıp o noktaları birbirinden ayırmanız gerekir
      Ortak UI widget’larını içeren bir git submodule’ümüz var; artık içlerinden birini değiştirmek neredeyse imkânsız, bu yüzden bileşeni projenin içine kopyalayıp yerelde değiştirmek daha kolay
      Bu bir sorun. Paylaşılan kod mümkün olduğunca az olmalı; paylaşımın kendisi değişikliği zorlaştırır
    • 10 fonksiyon çağrısından 3’ünün bir şekilde, 5’inin başka bir şekilde değişmesi, kalan 2’sinin ise artık aynı soyutlamayı kullanmadığı için tamamen yeniden yazılması gerekiyorsa ne olur
      Her şey tek bir fonksiyondaysa çoğu geliştirici o fonksiyonu 10 durumun hepsini karşılayacak şekilde değiştirmeye çalışır. Oysa en başta tek bir fonksiyon olmaması gerekirdi
      Bir kez bağlanıp sistemin parçalarını tutan yanlış bağlanmış bir düğümü çözmektense, kopyala-yapıştır yapılmış on yeri düzeltmek çok daha kolaydır
    • Yazar muhtemelen o kodun bir modüle ya da fonksiyona taşınması gerektiğini söylerdi
      Dışarıdan bakınca bu konuda kendi içinde çelişiyor gibi görünüyor, ama yavaş okuyunca kopyala-yapıştırı hangi kodun soyutlanması gerektiğini ve gerçekten izlenmesi gereken desenin ne olduğunu gösteren bir sinyal olarak kullandığını görüyorsunuz
  • Yazılımla ilgili türlü türlü kaidenin, neredeyse dinî ilkeler gibi şeylerin sürekli tekrarlanması tuhaf
    Kâğıt üzerinde hepsi harika görünüyor ve sağduyu gibi geliyor, ama 50 yıl geçmesine rağmen yazılım vakaların %90’ında çöp
    Yine de bunlar dâhiyane içgörüler ya da gümüş kurşunlarmış gibi sürekli tekrar gündeme getiriliyor

    • Bence o çöpün %90’ı, böyle yazıları okumayan ya da yazmayan kişiler tarafından yazıldığı için böyle
  • Burada harika bir sonuç önerme var. Kötü kodu kaldırmak çok daha zor olduğu için daha uzun süre kalır