Aşırı-ölçeklenebilirlik Hatası ve Yaşlanma Üzerine

Yazılım mühendisliği problem için en uygun çözümü tasarlamayı gerektirir. En uygunu burada en optimum demek. Peki en optimum ne demek? Hedefi belli olmayan şeyin optimum’u planlanamaz. Dolayısı ile problem cümlesinin stratejik bazı hedefleri barındırması gerekir ki en optimum belirlenebilsin ve sonucunda doğru mühendislik yapılabilsin. Strateji her zaman iş biriminden gelir. Yazılım mühendisinin işi verilen hedefe yürüyecek bilgi sistemlerini tasarlamaktır. Demek ki yazılım geliştirme faaliyeti “en iyi değil en optimum” sonucu almak için gerçekleştirilmelidir. Bu yazıda yazılımcıyı içten içe yiyerek bu optimumdan uzaklaştıracak aşırı-ölçeklenebilirlik olarak isimlendirdiğim bir hatadan bahsetmek istiyorum.

Burada sadece yazılımcı kaynaklı yazılım geliştirme başarısızlıklarından bahsetmek istiyorum. Daha geniş anlamda proje yönetimsel ve iletişim tabanlı hatalara başka bir yazıda yer vermiştim [1]. İlk aklınıza gelenin aksine konu yazılımcının ne kadar bilgisiz, meraksız olması ile ilgili de değil. Hatta tam aksine bu hatanın kendini geliştiren idealist yazılımcılardan kaynaklandığını görmek daha olası. Bu kavramı literatürde over-design (fazla-tasarım) olarak duymuş olabilirsiniz. Ben kavrama fazla bir şey eklemeden olası sebeplerinin üzerinde durmak istiyorum.

Fazla-tasarım yapmayı problemin gerektirdiğinden fazla kaliteli ve kapsamlı bir çalışma yapmak olarak tanımlayalım. Daha fazla gizem yaratmadan fazla-tasarım ya da benim aşırı-ölçeklenebilirlik olarak adlandırdığım durumlara örnekler vermek istiyorum:

  • Yıllarca idame ettirilmesi gerekmeyen çok küçük bir yazılımı OOP, SOLID, DDD gibi metodolojilere bağlı kalarak geliştirmek.
  • Tüm işlediği veri tek bir makinenin belleğine sığabilen ve 10 saniyede hesaplanabilen veriyi Hadoop ile işlemek.
  • Günde 5–10 bin ziyaretçisi olan sistem için cache sunucuları, load balancer’lar node.js’ler kurup, actor-model mimarisi kurmaya çalışmak.
  • %99'i CRUD işlem olan kritik ya da karmaşık olmayan sisteme TDD yapıp her fonksiyona test yazmaya çalışmak.
  • Üç-beş ekranlık projeyi, daha popüler diye MVC ile yapıp, bilmediği Javascript ile binlerce satır yazıp tek birim testi yazmamak.
  • Yüksek çalışma performansı istenmeyen sistemleri low-level dillerle yazmak. For-each’e karşı olup for daha hızlı diye tutturmak. Yani prematüre optimizasyon yapmak [6].
  • Ve genel olarak sonsuza kadar her problem için bir metodoloj, dil, framework ya da teknolojinin taraftarı olmak.

“DDD iyi bir şey olsaydı Google da kullanırdı”, ya da “Python yavaş olsaydı Quora kullanmazdı” tarzı fanatizme çok maruz kaldığımız için son maddeyi eklemeden edemedim.

Burada abartarak örneklendirdiğim mimari ve teknoloji seçim hataları genellikle ekipte büyük resmi yani mimariyi değerlendirebilecek nitelikte yetkili, bilgili ve tecrübeli bir yazılımcı olmamasından kaynaklanır ve normaldir. Bir de herkes bir önceki projesindeki teknolojileri kullanıp riskleri azaltmak ister, o da anlaşılabilir.

Ben ise hala daha farklı bir psikolojiden bahsediyorum. Bence temel sebep şu: Yazılımcıları ilk günden beri “her seferinde daha ölçeklenebilir bir iş yapacakları varsayımı” ile eğitiliyor. Örneğin daha ilk programını yazan öğrencilere ben OOP anlatırken şimdi tam oturmuyor ama bir gün nasıl lazım olacağını göreceksiniz diyorum. Bütün yazılım kitapları çıtayı her zaman en üste koyuyor, okuyucuya en kompleks sistemin bile altından kalkmasını sağlayacak teorileri ve sistemleri öğretiyor. İdealist yazılımcı şunu bilir: bugün bana gerekmiyor ama 3–5 yıl sonra gerekecek. Gerçektende özellikle OOP konusu yazılımıcıyı 3–5 yıl sonra level atlatır. Neden daha önce bilmiyormuşum der. Sonra büyük bir enterprise’a gider ve OOP’nin yetmediğini SOA ve AOP öğrenmesi gerektiğini farkeder. Bu doğal döngü yazılımcının gelişimini sağlar ve buraya kadar oldukça sağlıklıdır.

Buradaki problem yazılımcının bulunduğu ekosistem ile ilgilidir. Ekosistem yazılımcıdan her seferinde daha kalitelisini istemez. Bu pasta kapitalizmin sürekli büyüyen pastası gibi değildir. Büyüme her alanda sürekli değildir. Zaten kapitalizmde de pasta zaman zaman daralır. Bir noktadan sonra yazılımcı hayatı boyunca mesleğine karşı edindiği “her zaman daha kaliteliye” öğretisinin kurbanı olmaya başlar. Kendi genişlese bile ekosistem genişlemez. Bu genişleme bir alanda olsa bile diğer tarafta olmaz. Örneğin ilk üç çalıştığı firma çalışma performansı konusunda onu sürekli zorlamış, ama yeni çalıştığı firma sadece genişletilebilirlik istemektedir. Bu fonksiyonel olmayan isterler stratejinin bir parçasıdır, ve bütün fonksiyonel olmayan isterler yazılımcının kariyeri boyunca genişleyemez. Bu ciddi bir tatminsizlik problemi yaratmaya başlar. Bu her zaman kişinin kendi kariyeri ile ilgili değildir. Birçok fonksiyonel olmayan ister doğası gereği birbiri ile çelişir. CAP Theorem’de olduğu gibi üç taneden iki tanesini seçmeniz gerektiği gibi durumlarla karşılaşırsınız hep [2][3]. Örneğin Erich Gamma koduna test yazmadığında kendini iyi hissetmediğini bunu bir bulaşıcı hastalık (test-infected) gibi tanımlayacak anlatıyor [4]. Bir kere ona alıştıysanız artık onu yapmamak da çok zor şey. On beş yıl boyunca bir objektifi maksimize etmek için kod yazmış bir insanın parmaklarından onu çekip başka şeyleri maksimize etmesini sağlamak çok zor. En kötüsü ise yazılımcının bütün objektifleri maksimize etmeye çalışması. Bu teorik olarak mümkün değil. Bazen altı üstü yama yapıp çıkılması gereken kod üzerinde 50 yıllık çözümler ürettiğimi görüp kendimi zor tuttuğum oluyor. Örneğin C# ve Java ile edindiğin alışlanlıklarını Python ya da C++ yazarken korumanın bir anlamı genellikle olmaz. “Burada enkapsulasyon niye yok” tarzı homurdanmaların (ben de çok yaparım) sebebi budur genellikle.

Yazılımın Ömrü

Son olarak “2000 yılı problemini” [5] hatırlatmak isterim. Problem yıl bilgisinin 4 hane ile temsil edilmesi gerekirken 2 hane ile temsil edilmiş olmasından kaynaklanmıştı. Bu durumda 1900 ile 2000 birbirinden farklılaşamaz olmuştu. Geliştiricilerin yaptığı varsayım aslında yazılıma önden biçilmiş bir ömürdü. O zamanki genç şimdiki dedeler, “boşver ya 50 yıl sonra kim öle kim kala Johnny” diye gülüşmüş olabilirler.

Yazılım öğrenirken o kadar çok reusability ve performans okuyoruz ki bazen “hiç sonu yokmuş” gibi geliyor. Özellikle bir de benim gibi 15 yıl önce yazdığı kodları hala kullanabilme lüksüne sahip biri için bu his çok daha kuvvetli. Yıllar boyunca bütün yanlış tasarımlarınızın karşınıza çıktığını düşünün. Yetersiz tasarımların er ya da geç karşınıza çıkmak gibi bir huyu vardır. Belki de bu sadece benim gibi yaşlanmaya başlamış yazılımcıların yazacağı türden bir yazıdır. Zaman daralmaya başladıkça idealizm yerini pragmatizme bırakmalı belki de. 70 yaşında olsan o kodu öyle yazar mısın. Tamam o kadar da yaşlı değilim belki ama bugün tasarladığımız sistemler için bir 15 yıl sonraki geri bildirimleri alabileceğimizin garantisi de yok. Yarın doğum günüm, denk mi geldi malum mu oldu bilmem artık. Buraya kadar okuyabildiyseniz ne mutlu bana…

Kaynakça

[1] Az Çorba Az Çeviklik
[2] GOTO 2012 • Introduction to NoSQL • Martin Fowler — CAP Theorem
[3] The Scalability Trilemma
[4] Test Infected
[5] Year 2000 problem
[6] Premature Optimization

Geri bildirimler için yazıyı Medium'da aç.