35 puan yazan GN⁺ 2024-12-23 | 4 yorum | WhatsApp'ta paylaş
  • Modern yazılım sürekli dağıtım (CD) ve otomatik testler (CI) sayesinde sık sık güncellense de, "uzun vadeli kullanılan yazılım" farklı bir yaklaşım gerektirir
    • Örnek: nükleer santraller, uçaklar, kalp pilleri, seçim sistemleri vb.
      • Güvenilirlik ve istikrarın kritik olduğu alanlarda, sürekli değişimden ziyade istikrar ve öngörülebilir değişiklikler tercih edilir.

Uzun vadeli yazılım geliştirmenin temel ilkeleri

Bağımlılıklar (Dependencies)

  • Yazılımın bağımlılıkları, uzun vadeli başarının önemli bir unsurudur.
  • Yazılım dış dünyayla etkileşimini hesaba katmalıdır ve programlama dili gibi temel seçimler önemlidir.
  • Yazılım bağımlılığı katmanlarını anlamak
    • Dış dünya: Kontrol edemediğimiz istemci yazılımları (ör. tarayıcılar vb.).
    • Temel seçimler: Değiştirmek için tüm stack'in yeniden yazılmasını gerektiren, programlama dili gibi unsurlar.
    • Framework'ler: Kod tabanına sıkı şekilde bağlanan Spring Framework, React vb. Değiştirilebilirler ama maliyeti çok yüksektir.
    • Veritabanı: Çoğu zaman değiştirilebilir, ancak ayrıntılı ayarlamalar ve çalışma gerektirir.
    • Yardımcı kütüphaneler: Belirli işlevler sunan, değiştirilebilir kütüphaneler.
  • Zaman geçtikçe bağımlılıklar ve dış dünya değişir:
    • Bağımlılıklardaki değişiklikler nedeniyle kod düzeltmeleri veya davranış değişiklikleri gerekebilir.
    • Yeni major sürümlerin çıkmasıyla uyumluluk sorunları oluşabilir.
    • Projenin terk edilmesi ya da ortadan kaybolması riski vardır.
    • Güvenlik riski: Bağımlılıkların kötü niyetli aktörler tarafından ele geçirilme ihtimali vardır (npm, PyPI vb.).
    • Ticarileşme: Yeni risk sermayesi (VC) sahipleri projeyi ücretli hale getirebilir.
    • Bağımlılıklar arasında çatışma sorunları yaşanabilir.
  • Uzun vadeli kullanım düşünülerek bağımlılık seçerken kontrol edilmesi gerekenler:
    • Teknik seviye: Kaynak koda bakarak kaliteyi değerlendirmek mümkün mü?
    • Kullanıcı tabanı: Kimlerin kullandığını doğrulayın.
    • Geliştirme amacı: Geliştiricilerin kim olduğunu ve hedeflerinin ne olduğunu anlayın.
    • Finansal destek: Fon var mı, varsa kaynağı nedir?
    • Bakım: Güvenlik sürümleri düzenli olarak yayımlanıyor mu kontrol edin.
      • Topluluğun bakımı devralma ihtimali.
      • Gerekirse kendiniz bakımını üstlenip üstlenemeyeceğiniz.
      • Gerektiğinde finansal destek sağlayarak projenin sürdürülebilirliğini güvenceye almanın gerekip gerekmediği.
    • Bağımlılıkların bağımlılıkları:
      • Alt bağımlılıkların güvenlik geçmişini de inceleyin.
  • Gerçekçi yaklaşım
    • Bağımlılıkları sınırlayın:
      • 1600'den fazla bağımlılığı olan projelerde kod hızla değişebilir ve istikrarsız hale gelebilir.
      • Çok sayıda bağımlılığı olan projelerde hangi kodun dağıtıldığını anlamak bile zorlaşır.
    • Dikkatli ekleme:
      • Bağımlılık eklerken doğal bir değerlendirme süresi yaratmak için buna bir teknik zorluk atayın.
      • Uzun vadeli projelerde gerekli olmayan bağımlılıklardan kaçınılmalıdır.

Çalışma zamanı bağımlılıkları (Runtime Dependencies)

  • Buraya kadar anlatılanlar build/compile bağımlılıkları ile sınırlıydı.
  • Ancak modern projeler çoğu zaman çalışma zamanı bağımlılıkları da içerir:
    • Örnek: Amazon S3, Google Firebase.
    • Bazıları fiilen standart sayılır (S3 gibi).
    • Ama çalışma zamanı bağımlılıklarının çoğu, belirli bir hizmete güçlü bir lock-in yaratır.
  • 10 yıl sonra bugün kullandığınız hizmetin yerine geçecek bir alternatifi bulmak çok yüksek maliyet doğurabilir.
  • Üçüncü taraf hizmet bağımlılıklarının listesini en aza indirmek veya sıfırlamak gerekir:
    • Özellikle cloud native yazılım geliştirmede çok sayıda gelişmiş üçüncü taraf hizmet kullanmak yaygındır.
    • Uzun vadeli projelerde bu tür bağımlılıklar yüksek risk taşır.
  • Build-time hizmet bağımlılıkları da önemli bir faktördür:
    • Örneğin npm install artık çalışmıyorsa, yazılımı build etmek başlı başına imkansız hale gelir.
    • Bu durum projenin yeniden kullanılabilirliğini ciddi biçimde düşürebilir.
  • Çalışma zamanı bağımlılıklarını titizlikle gözden geçirin:
    • Olası lock-in sorunlarını fark edin, bağımlılıkları azaltın ya da kaldırın.
  • Uzun vadeli sürdürülebilirliği güvence altına alın:
    • Bulut ya da üçüncü taraf hizmetlerin yerine ne konabileceğini önceden düşünün.

Test, test ve yine test

  • Test ihtiyacı, herkesin hemfikir olduğu temel bir ilkedir:
    • Mümkün olduğunca çok test yazın.
    • Tüm testler eşit derecede değerli değildir ama test yazmış olmaktan pişman olmanız neredeyse hiç olmaz.
  • Özellikle bağımlılığı çok olan projelerde test zorunludur:
    • Bağımlılıklar değiştiğinde ya da drift ettiğinde sorunları erken fark etmeye yardımcı olur.
  • Testin rolü
    • Sorun çözümüne destek:
      • Değişen koşullara hızla uyum sağlamayı mümkün kılar.
    • Refactoring desteği:
      • Kod bağımlılıklarını kaldırırken veya değiştirirken güven verir.
    • Uzun vadeli bakım için fayda:
      • Geliştirme 3 yıldan fazla durduktan sonra bile testlerle sistemin hâlâ çalışıp çalışmadığı doğrulanabilir.
      • Yeni compiler, runtime ve işletim sistemi üzerinde işlevlerin korunup korunmadığı kontrol edilebilir.
  • Test bir maliyet değil, yatırımdır
    • Daha fazla test yazın:
      • Testler bakımın ve istikrarın temelidir.
      • Kodu değiştirirken veya genişletirken büyük bir zihinsel destek sağlar.

Karmaşıklık: yazılım geliştirmenin son boss'u

  • Karmaşıklık, yazılım geliştirmenin nihai düşmanıdır:
    • En iyi geliştirici ya da ekip bile karmaşıklık yüzünden çökebilir.
    • Entropi ve insan davranışı nedeniyle karmaşıklık sürekli artar.
    • Karmaşıklık bilinçli şekilde yönetilmezse proje bakımı imkansız bir duruma düşebilir.
  • Karmaşıklık ile kod miktarı arasındaki ilişki
    • Kod miktarı ve karmaşıklık:
      • Kod az olduğunda biraz karmaşık olsa bile yönetilebilir olabilir.
      • Kod arttıkça kontrolü korumak için sadeliği sürdürmek gerekir.
      • Yönetilebilir karmaşıklık, ekibin kapasitesi ve "yeşil üçgen" içinde kalmalıdır.
    • Karmaşıklığın sınırları:
      • Ekip büyütmek ya da çok yetenekli geliştiriciler almak bile karmaşıklığı yönetmede sınırsız çözüm sunmaz.
      • Sınır aşıldığında proje bakımı yapılamaz hale gelir.
  • Kodun neden hep 'sağ üst'e gittiği: (grafikte)
    • Daha fazla özellik talebi.
    • Gereksiz optimizasyon girişimleri.
    • Bug fix yaparken mevcut karmaşıklığı azaltmak yerine yeni kod eklemek.
  • Kötü API tasarımının maliyeti:
    • Örneğin CreateFile fonksiyonu çoğu durumda aslında dosya oluşturmaz.
    • Bu tür karışıklıklar ek bilişsel yük ve hata olasılığını artırır.
  • Karmaşıklığı yönetme stratejileri
    • Refactoring'i erken ve sık yapın:
      • Gereksiz kodu kaldırın ve sadeleştirmeye zaman ayırın.
    • Testlere yatırım yapın:
      • Test ne kadar çoksa karmaşıklığı azaltma işi o kadar kolay olur.
    • Karmaşıklık yönetiminin önemi:
      • Sadeleşmek için önceden çaba harcanmazsa, uzun vadeli projeler sonunda "bakımı imkansız" duruma düşme riski taşır.

Sıkıcı ve basit kod yazın. Sonra daha da basitleştirin. Ve daha da sıkıcı hale getirin.

"Debugging, program yazmaktan iki kat daha zordur. Dolayısıyla kodu yazarken olabildiğince akıllıca yaparsanız, sonra onu nasıl debug edeceksiniz?" - Brian Kernighan

  • Aşırı sıkıcı ve net kod yazın:
    • Naif ama sezgisel olarak anlaşılabilir kod tercih edin.
    • "Premium optimizasyon tüm kötülüklerin kaynağıdır."
  • Optimizasyonu yalnızca gerçekten gerektiğinde yapın:
    • Fazla basit kalması sorun olursa, sonradan karmaşıklık eklemek zor değildir.
    • O an hiç gelmeyebilir de.
  • Karmaşık kod yazmaktan kaçının:
    • Mutlaka gerekli olduğu ana kadar bekleyin.
    • Basit kod yazdığınız için pişman olma ihtimaliniz çok düşüktür.
  • Yüksek performanslı kod ya da özellikler yalnızca belirli ortamlarda çalışabilir.
    • Örnek:
      • LMDB: PowerDNS'te istikrarlı biçimde kullanılana kadar pek çok zorluk yaşandı.
      • RapidJSON: SIMD hızlandırmalı bir JSON kütüphanesi. Performansı çok iyidir ama kullanım koşulları zorludur.
  • "Bu kısıtı aşabilirim" diye düşünseniz bile:
    • Bu yıl mümkün olsa bile 5 yıl sonra siz ya da yerinize gelen geliştirici zorlanabilir.
    • Aynı ilke karmaşık programlama dilleri için de geçerlidir.
  • Sonuç:
    • Kodu sadeleştirin:
      • Gerçekten basit olsun. Hatta daha da basit.
    • Optimizasyonu sonraya bırakın:
      • Karmaşıklık gerektiğinde eklenebilir, ama baştan karmaşık kurarsanız bakım zorlaşır.

LinkedIn tabanlı yazılım geliştirme

  • Gerçeklik vs. ideal
    • İdeal yaklaşım: Bağımlılık seçerken yukarıdaki kontrol listesiyle kapsamlı değerlendirme ve inceleme yapmak gerekir.
    • Gerçekçi yaklaşım: Bazen çekici görünen teknolojileri deneme ve çalışıyorsa kullanmaya devam etme eğilimi vardır.
  • Neden çekici?
    • LinkedIn'deki ünlü isimler veya influencer'ların önerdiği teknolojiler.
    • Hacker News gibi topluluklarda çok övülen "en yeni framework".
  • Trend teknolojiler uzun vadeli olarak yeterince sınanmamıştır:
    • "10 yıldan fazla yaşayacak yazılım projeleri" için uygun olmayabilirler.
    • Yeni teknolojiler erken aşamada istikrar ve bakım yapılabilirlik açısından sorun çıkarma olasılığı taşır.
  • Öneriler
    • Yalnızca deneysel alanlarda kullanın:
      • Yeni teknolojileri önce küçük projelerde veya çekirdek olmayan alanlarda deneyin.
    • Lindy etkisini dikkate alın:
      • Bir teknolojinin ömrü, bugüne kadar kullanım süresiyle orantılı olma eğilimindedir.
      • Daha eski teknolojilerden uzun vadede daha fazla istikrar beklenebilir.
  • Yeni teknolojiler cazip olsa da, uzun vadeli projeler için kanıtlanmış ve istikrarlı teknolojiler daha uygundur.

Loglama, telemetri, performans

  • Yazılım sürekli güncellenmiyor veya dağıtılmıyorsa:
    • Bir web sitesi bozulduğunda anında geri bildirim alma olasılığı düşer.
    • Dağıtımdan sonra gerçek sorunu çözmek uzun sürebilir.
  • İlk sürümden itibaren kapsamlı loglama ve telemetri uygulayın:
    • Yazılımın performansını, hatalarını ve faaliyetlerini kaydedin.
    • Zamanla biriken veriler, nadir görülen bug'ları çözmede çok faydalı olur.
  • Yetersiz loglamanın yol açtığı sorunlar:
    • Bir kullanıcı arayüzü yayımlandı ama 3000 klasör oluşturan bir kullanıcı sorun bildirdi.
    • Kullanıcı sadece "çalışmıyor" dediği için kök nedeni bulmak aylar sürdü.
    • Performans logları ve telemetri olsaydı sorun çok daha hızlı çözülebilirdi.
  • Loglama ve telemetri zorunludur:
    • Yazılım faaliyetlerinin kapsamlı biçimde izlenebileceği şekilde tasarlayın.
    • Uzun vadeli dağıtım ve bakım sürecinde beklenmedik sorunların çözümüne büyük yardım sağlar.

Dokümantasyon

  • Dokümantasyonun önemi:
    • Sadece API dokümanını iyi yazmak yetmez; "neden böyle tasarlandı" sorusunu da açıklamak gerekir.
    • Sistemin nasıl çalıştığına ilişkin fikirleri ve felsefeyi kaydedin.
    • Çözümün neden ayrıştırıldığı ve sezgisel olmayan tasarım kararlarının gerekçesi bırakılmalıdır.
  • Mimari dokümanların dışında faydalı materyaller:
    • Dahili blog yazıları: geliştiricilerin sistem tasarımı üzerine serbest tartışmaları.
    • Ekip röportajları: tasarım kararlarının arka planını içeren konuşma kayıtları.
    • Bu tür belgeler zaman geçse de ekip içinde bilgi aktarımını mümkün kılar.
  • Koda yorum bırakın:
    • "İyi kod yoruma ihtiyaç duymaz" trendine rağmen, kodun 'neden'ini açıklayan yorumlar zorunludur.
    • Belirli bir fonksiyonun neden var olduğunu açıklayan içerik önemlidir.
  • Commit mesajları yazın:
    • Commit mesajları iş geçmişinin çekirdeğidir. Kod değişikliklerinin nedenini izlemeyi sağlar.
    • İnsanların commit mesajlarını kolayca inceleyebileceği bir ortam oluşturun.
  • Dokümantasyon için zaman ayırın:
    • Geliştirmenin iyi gitmediği günlerde faydalı yorumlar ve kayıtlar bırakmaya zaman ayırın.
    • Ekip düzeyinde dokümantasyon için düzenli zaman planlayın.
  • Neden öyle tasarlandığını kaydedin:
    • 7 yıl sonra yeni bir ekibe aktarılabilecek felsefe ve arka plan bilgisi son derece değerlidir.
  • Yorumlar ve commit mesajlarıyla tarih bırakın:
    • Sadece geliştirme sırasında değil, uzun vadeli bakım için de vazgeçilmezdir.

Ekip yapısı

  • Ekibin sürekliliği ve yazılımın uzun vadeli başarısı:
    • Bazı yazılımlar 80 yıl desteklenecek şekilde tasarlanır. Böyle projelerde ekibin korunması kritik önemdedir.
    • Modern geliştirme ortamında ortalama 3 yıl bile uzun çalışma süresi sayılır.
    • İyi dokümantasyon ve testler ekip değişimini bir ölçüde telafi edebilir ama bunun sınırları vardır.
  • Uzun süreli çalışmanın avantajları:
    • Ekip üyelerini 10 yıldan fazla elde tutmak:
      • Onları gerçek çalışanlar olarak istihdam etmek ve geliştiricileri iyi yönetmek önemlidir.
      • Uzun vadeli proje başarısı için kritik bir "hack" olarak görülür.
  • Dış kaynak kullanımının sorunları:
    • Dış kaynak geliştiriciler çoğu zaman kodu teslim ettikten sonra ayrılır.
    • 10 yıldan uzun süre yaşayacak bir yazılım kalitesini hedefliyorsanız bu son derece verimsiz bir yöntemdir.
  • Ekip üyelerinin uzun vadede birlikte çalışabileceği bir ortam oluşturun.
  • Dış danışmanlara bağımlılığı en aza indirip iç ekibin sürdürülebilirliğini artıracak bir strateji gerekir.

Açık kaynağı değerlendirin

  • Açık kaynağın avantajları:
    • Kod kalitesini dış incelemeyle korur:
      • Dışarıdan bakan gözler, geliştiricilerden daha yüksek standartlar talep eder.
    • Daha iyi kod standartlarını korumak için güçlü bir mekanizmadır.
  • Açık kaynağa hazırlık sürecindeki gerçekler:
    • Şirketler veya kamu kurumları, açık kaynak hâline getirme hazırlığının aylar hatta yıllar alacağını sık sık söyler.
    • Sebebi:
      • İçeride dışarıya göstermekten utanılacak kod yazımı yaygındır.
      • Açık kaynaklaştırmadan önce kodu toparlamak gerekir.
  • Uygulanabilirliği değerlendirin:
    • Açık kaynak her zaman mümkün bir seçenek değildir.
    • Mümkünse, kod kalitesini ve şeffaflığı artırmanın iyi bir yoludur.
  • Açık kaynak, mümkün olduğunda kullanılmalı önemli bir stratejidir.
  • Dış bakış ve yüksek standartlar projeyi doğru yönde tutmaya yardımcı olur.

Bağımlılık sağlığını kontrol edin

  • Bağımlılık değişiminin sorunu:
    • Bağımlılıklar zamanla beklentilerden farklı şekilde değişebilir veya sapabilir.
    • Bu göz ardı edilirse:
      • Bug'lar ortaya çıkabilir
      • Build başarısızlıkları yaşanabilir
      • ve başka can sıkıcı sonuçlara yol açabilir.
  • Düzenli sağlık kontrolü önerilir:
    • Periyodik bağımlılık denetimi:
      • Sorunları önceden keşfetme fırsatı verir.
      • Bağımlılıkların yeni özelliklerini fark edip kodu sadeleştirme veya başka bağımlılıkları kaldırma fırsatı da doğurabilir.
    • Önleyici bakımın önemi:
      • Kontrol için kendi zamanınızı planlamazsanız, sonunda bir sorun çıktığında zamanı size zorla o sorun ayıracaktır.
  • Bakım analojisi:
    • Makinistlerin deyişi:
      • "Bakım zamanını sen planla. Yoksa ekipman o zamanı senin yerine planlar."
  • Düzenli bağımlılık kontrolü, uzun vadeli yazılım istikrarı ve verimliliği için vazgeçilmez bir faaliyettir.
  • Sorunları önceden çözmek ve olumlu değişiklikleri keşfetmek için bir fırsat olarak kullanın.

Başlıca referans kitaplar

Son olarak

Uzun vadeli yazılım geliştirme için temel öneriler:

  • Sadeliği koruyun:
    • Basit tutun, hatta daha da basit! Gerektiğinde karmaşıklık eklenebilir; bu yüzden başlangıçta gereksiz yere karmaşıklaştırmayın.
    • Sadeliği korumak için düzenli refactoring ve kod silme gerekir.
  • Bağımlılıkları dikkatle düşünün:
    • Ne kadar az bağımlılık, o kadar iyi. Dikkatle inceleyin ve denetleyin.
    • 1600 bağımlılığı denetleyemiyorsanız planı yeniden düşünmeniz gerekir.
    • Trendleri veya modaları (ör. LinkedIn tabanlı geliştirme) takip eden seçimlerden kaçının.
    • Düzenli bağımlılık kontrolü: bağımlılıkların durumunu sürekli izleyin.
  • Test, test ve yine test:
    • Değişen bağımlılıkları zamanında fark etmeyi sağlar.
    • Refactoring sırasında güven verir ve sadeliği korumaya yardımcı olur.
  • Dokümantasyon:
    • Sadece kodu değil, felsefeyi, fikirleri ve "neden böyle yaptık" arka planını da belgeleyin.
    • Gelecekteki ekip üyeleri için çok değerli bir varlık olur.
  • İstikrarlı bir ekip koruyun:
    • Uzun vadeli proje yatırımı için uzun süreli istihdamı değerlendirin.
    • Ekip üyelerinin projeye uzun yıllar bağlı kalabilmesini destekleyin.
  • Açık kaynağı değerlendirin:
    • Mümkünse açık kaynak sayesinde daha yüksek kod standartlarını koruyun.
  • Loglar ve performans telemetrisi:
    • Sorunları erken fark edip çözmede kritik rol oynar.
  • Bu öneriler yeni olmayabilir, ancak deneyimli geliştiricilerin özellikle vurguladığı noktalar oldukları için üzerinde derinlemesine düşünmeye değerdir.

4 yorum

 
kandk 2024-12-30

İstikrarın önemli olduğu katmanlarla hızın önemli olduğu katmanları ayırmak ve bu ikisi arasındaki ilişkiyi nasıl ele alacağınız, mühendislikte en önemli güçtür.
Toss yalnızca istikrarın peşinden gitseydi, diğer bankalardan farkı kalmazdı.

 
kandk 2024-12-30

Tehlikeli olan SpaceX için de geçerli. Tesla için de öyle..

 
aer0700 2024-12-25

Sorun özgeçmiş odaklı geliştirme mi acaba.

 
GN⁺ 2024-12-23
Hacker News görüşleri
  • Araç zincirini aktif biçimde güncellemek, geliştirme sürecinin önemli bir parçasıdır. Birçok şirket araç zinciri yükseltmelerini önceliklendirmediği için güvenlik açıkları gibi sorunlar ortaya çıkar. Her yeni derleyici veya build sistemi sürümünde bir branch açıp build durumunu kontrol ediyor, hata varsa bunu bug kabul edip hemen ele alıyorum. Bu, kod tabanını en yeni dil özellikleriyle kademeli olarak modernize etmeye ve refactor etmeye yardımcı olur.

  • Üçüncü taraf bağımlılıklar uzun vadede çoğu zaman hayal kırıklığı yaratır. Yeni projelerde üçüncü taraf bağımlılıkları kısa vadede sorun çözmek için kullanılabilir, ancak uzun vadede bunları kendi kodunuzla değiştirmek daha iyidir.

  • Bağımlılıkları vendoring ile projeye dahil etmek ve code review üzerinden yönetmek gerekir. Çoğu zaman üçüncü taraf kodun kalitesi düşüktür ve doğrudan kendiniz yazmanız daha iyi olur.

  • Qt, CMake ve modern C++ kullanarak uzun vadeli ölçeklenebilirliği hedefleyen bir proje üzerinde çalışıyorum. Bu teknoloji yığını sürekli olarak yeni özellikler ve iyileştirmeler sunuyor.

  • Emacs Lisp ile çalışmak tazeleyici bir deneyimdi. Kütüphaneler güncellenmese bile kararlı şekilde çalışması büyük bir avantaj. Gatsby ve Node kullanma deneyimim ise güncelleme sorunları yüzünden zorluydu.

  • Basit kod yazmak önemlidir. Karmaşık kodu yalnızca gerçekten gerektiğinde yazın; basit koddan pişman olmazsınız.

  • Sistemlerin ve kodun dokümantasyonu önemlidir. Yazılım geliştirme deneyiminiz arttıkça dokümantasyonun ne kadar önemli olduğunu daha iyi anlıyorsunuz.

  • Testler planlamada önemli bir rol oynar. NASA'nın geliştirme yaklaşımından hareketle programlama hatalarını bulmaya odaklanmak gerekir. Tıbbi yazılım geliştirmede yoruma açık davranışlardan kaçınılır ve dinamik bellek tahsisi kullanılmaz.

  • Uzun ömürlü yazılım yazmanın en iyi yolu “sıkıcı” kod yazmaktır. Bağımlılıklardan kaçınmalı ve temellere sadık kalmalısınız.

  • Python'da bağımlılık sorunları nedeniyle zorluk yaşadım. Buna “DLL Hell” deniyordu; COM bunu çözmeye çalıştı ama başarılı olamadı.

  • Endüstriyel yazılıma uygulanan pratikler, genel yazılıma uygulanamayacak kadar sağlam değildir. Mühendisler riski azaltmaya çalışır, ama biz risk azaltmayı merkeze koyarız.