Yetenek Enflasyonu ve İnsanın Yeni Değer Arayışı Üzerine

Son zamanlarda yazdığım kodlar gibi bu makale de bana aitmiş gibi hissettirmiyor. Bu satırlardan çıkarılacak ana hatlar, temel bakış açıları, içeriği derinleştiren sorular ve son dokunuşlar bana ait olmasına rağmen, yine de başkasınınmış gibi. Çünkü bu makale Gemini’nin Canvas modu ile, çeşitli düşünce ve sorularımdan yola çıkarak, onun eklediği müthiş detaylar, ve bir çok revizeden geçirilerek ortaya çıkarıldı. Son zamanlarda yazdığım kodlar gibi…

Bu sorunsalı, (bu makale lezzetli mi bilmem ama) lezzetli bir yemeğin övgüsünü kimin hakettiğini bilememeye benzetiyorum. Yemeğe katılan malzemeler mi? O malzemeleri yetiştirenler mi? Pişiren mi? Yoksa o tarifi icat eden mi? Fazla dramatize ettim farkındayım. Elbetteki cevap: hepsi. Ama biz yine de çoğu zaman en yakınımızdakine, yani pişirene/garsona/kasiyere “elinize sağlık“ deriz. Günümüzde en yakınımız yapay zeka sohbet araçları oldu. Omuz omuza kod yazdığımız, “pair“ yaptığımız dostların yerini, “context” şiştiğinde saçmalamaya başladığı zamanlar azarladığımız, ama çoğu zaman güzel işler çıkardığı için bağrımıza bastığımız “coding agent”lar aldı. “Eline sağlık“ Gemini. Umarım gelecekte o azarlamaların intikamını almazsın. 😇

Hep iyi ihtimallerin gerçekleşmesi dileğiyle. 🙏


On dört yıllık profesyonel yazılım geliştirme tecrübesine dayanarak ifade etmek gerekirse, bilişim sektörü geçtiğimiz on yıllarda büyük ölçüde öngörülebilir, yönetilebilir ve lineer trendler üzerinden ilerlemekteydi. Kariyerimin ilk yıllarında tanık olduğum Flash teknolojisinin yerini HTML5 standartlarına bırakması, fiziksel sunucu altyapılarından (on-premise) sanallaştırılmış bulut bilişime (cloud computing) geçiş veya hantal monolitik mimariden esnek mikro servislere evrilme süreçleri, her ne kadar ciddi teknik yetkinlik ve adaptasyon gerektirse de, nihayetinde insan zekasının kontrol sınırları dahilinde kalan araçsal değişimlerdi. Bu dönemde yapılan tüm gelecek projeksiyonları, insan kontrolü altındaki araçların verimlilik artışına ve süreç iyileştirmelerine odaklanmaktaydı. Mühendislik paradigması, “daha iyi araçlar kullanan yetkin insan” üzerine kuruluydu.

Ancak günümüzde, özellikle Büyük Dil Modelleri (LLM) ve Üretken Yapay Zeka (Generative AI) teknolojileriyle yaşanan dönüşüm, araçsal olmaktan çıkıp ontolojik ve varoluşsal bir boyuta evrilmiştir. Mevcut durum, sadece bir teknolojinin sürüm yükseltmesi veya optimizasyonu değil, üretim sürecinin tartışmasız öznesi olan insan faktörünün konumunun kökten sarsılması ve yeniden tanımlanmasıdır. Geçmişte teknolojiyi yöneten özne konumundaki profesyoneller, bugün teknoloji tarafından ikame edilme riski taşıyan nesnelere dönüşme tehdidi altındadır. Altı aylık stratejik projeksiyonların dahi belirsizleştiği bu konjonktürde, teknolojik gelişmelere duyulan entelektüel mühendislik ilgisi ile mesleki ve türsel sürdürülebilirlik endişeleri (survival anxiety) eş zamanlı ve paradoksal bir biçimde yaşanmaktadır.

Yetenek Enflasyonu ve Ustalık Kavramının Yeniden Değerlendirilmesi

Geleneksel iktisadi düzende ve insanlık tarihinde, bir disiplinde uzmanlaşmak, zanaatkar veya “usta” sıfatını kazanmak, binlerce saatlik kümülatif eğitim, sabır ve pratik sürecini (Malcolm Gladwell’in 10.000 saat kuralı gibi) zorunlu kılmaktaydı. Yazılım mühendisliği, akademik yazarlık, görsel sanatlar veya hukuk gibi alanlarda harcanan zaman, sarf edilen bilişsel efor ve çekilen entelektüel zahmet, ortaya çıkan değerin nadirliğini ve dolayısıyla piyasa fiyatını belirleyen temel faktördü.

Günümüzde ise yapay zeka teknolojileri sayesinde, teknik altyapısı, teorik bilgisi veya estetik görgüsü olmayan bireylerin dahi karmaşık yazılımları, fotorealistik görselleri veya akademik düzeyde metinleri saniyeler içinde üretebildiği bir döneme girilmiştir. Giriş bariyerlerinin neredeyse sıfıra inmesi, ilk bakışta yeteneğin demokratikleşmesi ve fırsat eşitliği olarak yorumlanabilse de, derinlemesine incelendiğinde “emeksiz üretimin” yarattığı ciddi bir tatmin, kalite ve değer krizini beraberinde getirmektedir.

Sadece bilişsel değil, fiziksel iş gücü gerektiren lojistik, depolama ve hatta cerrahi müdahale gibi alanların da otonom robotik sistemlere devredildiği bir süreçte, “Yetenek Enflasyonu” kavramı kaçınılmaz olarak ortaya çıkmaktadır. Ekonomik teorideki arz-talep dengesine göre, bir metanın arzı sınırsızlaştığında fiyatı marjinal maliyetine (sıfıra) yakınsar. Benzer şekilde, yetenek arzının yapay zeka ile sonsuza yaklaşması (zero marginal cost of creation), beşeri yetkinliklerin piyasa değerini marjinalize etme riski taşımaktadır. Beşeri sermaye, yüzyıllardır süregelen birikimini bir anda “batık maliyet” (sunk cost) olarak kaybetme tehlikesiyle karşı karşıyadır.

Makroekonomik Paradoks ve Yapısal Kilitlenme

Mevcut teknolojik dönüşüm, felsefi ve sosyolojik boyutun ötesinde, küresel makroekonomik ve finansal sürdürülebilirlik açısından tarihsel emsali olmayan riskler barındırmaktadır. Modern kapitalist sistem, emeğin sermayeye dönüşümü (ücretli çalışma) ve bu gelirin tüketim harcamalarıyla piyasaya dönmesi döngüsü üzerine kuruludur. Ancak bu döngü, üç ana koldan varoluşsal bir tehdit altındadır:

  1. Talep Krizi ve Ouroboros Etkisi: Bilişsel işlerin (beyaz yaka) yapay zeka, fiziksel işlerin (mavi yaka) ise robotlarca maliyetsiz ve hatasız bir şekilde ikame edilmesi durumunda, gelir elde etme mekanizmaları devre dışı kalan geniş kitlelerin alım gücü ve tüketim kabiliyeti ortadan kalkacaktır. Henry Ford’un “İşçilerime iyi maaş vermeliyim ki ürettiğim arabaları satın alabilsinler” prensibi geçerliliğini yitirmektedir. Tüketici tabanının yok olduğu bir piyasada, üretimdeki hiper-verimlilik ekonomik rasyonalitesini kaybedecektir. Bu durum, sistemin kendi kuyruğunu yiyen yılan (Ouroboros) metaforuyla açıklanabilecek, kendi kendini kilitleyen (deadlock) bir yapısal çıkmazdır.
  2. Finansal Sistemin Krizi ve Kredibilite Sorunu: Modern bankacılık sisteminin en temel gelir kalemi ve varlık nedeni, gelecekteki emeğin bugünden satın alınması, yani kredilendirmedir. Ancak öngörülebilirlik ufkunun (predictive horizon) 6 ayın altına düştüğü bir ortamda, 10, 20 veya 30 yıllık konut kredileri (mortgage) ve uzun vadeli borçlanma enstrümanları fiilen işlevsiz hale gelmektedir. Bir bireyin mesleğinin 5 yıl sonra var olup olmayacağının, gelir akışının sürüp sürmeyeceğinin hesaplanamadığı bir risk ortamında, olasılık hesapları ve risk modelleri çökmektedir. Gelir sürekliliğinin garanti edilemediği bir konjonktürde, kredi mekanizması durma noktasına gelebilir ve bankacılık sektörü, varlıklarının temelsiz kalması riskiyle karşı karşıya kalabilir.
  3. Demografik Daralma ve Biyolojik Geri Çekilme: Gelişmiş ekonomilerde (Japonya, Güney Kore, Avrupa) gözlemlenen doğum oranlarındaki dramatik düşüş, sadece kültürel değil, geleceğe dair ekonomik ve varoluşsal belirsizlikle yüksek korelasyon göstermektedir. “İnsana duyulan ihtiyacın azalması” algısı ve ekonomik güvencesizlik, bireylerde biyolojik bir geri çekilmeyi, yani ürememe davranışını tetiklemektedir. Yapay zeka devriminin vaat ettiği bolluk çağının, paradoksal bir biçimde insan nüfusunun dramatik düşüşüne yol açması; otomasyonun yöneteceği ancak hizmet edeceği insan nüfusunun bulunmadığı “tebaasız krallıklar” senaryosunu doğurmaktadır.

Kaynak Kısıtlılığı Argümanı ve Teknolojik Çözümler

Otomasyonun küresel ölçekte yaygınlaşmasının önündeki en büyük engel olarak sunulan enerji darboğazı ve hammadde kısıtlılığı argümanları, teknolojik ilerlemenin üstel hızı göz önüne alındığında uzun vadede geçerliliğini yitirmektedir.

Yakın geçmişte, doğal dil işleme yeteneğine sahip yapay zekaların bilim kurgu olarak nitelendirildiği, ancak bugün hayatın sıradan bir parçası olduğu unutulmamalıdır. Benzer bir sıçrama enerji ve malzeme biliminde de yaşanmaktadır. Füzyon enerjisi (yapay güneş) alanındaki ticari atılımlar ve sınırsız temiz enerji potansiyeli, enerji maliyetlerini marjinal düzeye çekebilir. Eş zamanlı olarak, astroid madenciliği ve uzaydan hammadde temini konusundaki girişimler (üstelik robotlaşma sayesinde, Dünya’daki madencilik faaliyetleri insanlara kıyasla daha hızlı ve düşük maliyetli hale geliyor; bu iyileşmeler nedeniyle şimdilik o kadar uzağa gitmeye de gerek kalmayacak), nadir toprak elementleri ve metal darboğazını aşarak, robotik üretimin fiziksel sınırlarını ortadan kaldırabilir. Dolayısıyla, mevcut kaynak kısıtları, bu büyük dönüşümü durduracak nihai bir engel değil, sadece aşılması gereken geçici bir mühendislik problemi olarak değerlendirilmelidir.

Teknolojik Asimetri ve “Buzdağı” Riski

Toplumsal endişeyi artıran ve güven krizini derinleştiren önemli bir faktör, teknolojik kapasiteye erişimdeki şeffaflık sorunudur. Bugün halka açık, ticari olarak sunulan yapay zeka modellerinin (ChatGPT, Claude, Gemini vb.) dahi gösterdiği yüksek bilişsel performans, kapalı devre geliştirilen teknolojilerin seviyesi hakkında ciddi ve haklı soru işaretleri doğurmaktadır.

Teknoloji devlerinin, devletlerin ve savunma sanayiinin elindeki, kamuya açıklanmayan “müstakil” (proprietary) teknolojiler ile halkın erişimine sunulanlar arasındaki asimetri, serbest piyasa rekabetini ve demokratik denetim mekanizmalarını işlevsiz kılabilir. “Buzdağının görünmeyen yüzü” olarak nitelendirilebilecek bu gizli kapasite; finansal piyasaları milisaniyeler içinde manipüle etme, kitle psikolojisini yönetme, siber savaş ve biyolojik tasarım gibi konularda teknokratik bir elitin mutlak güç konsolidasyonuna işaret etmektedir. Bu durum, teknolojinin demokratikleşmesi idealinin aksine, teknolojik bir oligarşinin doğuşuna zemin hazırlamaktadır.

Bilişsel Erozyon ve Analiz Felci

Dijital içerik bolluğu, seçeneklerin sınırsızlığı ve yapay zekanın üretim hızı, bireylerde karar verme yetisini felç eden kronik bir “Analiz Felci” (Analysis Paralysis) durumuna yol açmaktadır. Ancak daha kritiği, insan zihninin çalışma prensiplerindeki değişimdir.

Geçmişte öğrenme motivasyonunu sağlayan “süreç odaklılık” (yolculuğun kendisinden ve zorlukları aşmaktan keyif alma), yerini “sonuç odaklı” tehlikeli bir nihilizme bırakmaktadır. Yapay zekanın saniyeler içinde gerçekleştirdiği eylemler (kodlama, çeviri, analiz) için aylar süren öğrenme eforu sarf etmenin rasyonelliği sorgulanmaktadır. Bu durum, “Bilişsel Körelme” (Cognitive Atrophy) riskini doğurur; tıpkı fiziksel aktivitenin azalmasıyla kasların erimesi gibi, zihinsel süreçlerin dışsallaştırılması (outsourcing of thought) ile eleştirel düşünme, hafıza ve problem çözme yeteneklerimizde kolektif bir gerileme yaşanabilir.

Geleceğin “Muhtemel“ Değer Önermeleri

Üretimin metalaştığı, kusursuzluğun ucuzladığı bir gelecekte, “değer” kavramının nicelikten niteliğe, sonuçtan sürece ve bağlama kayacağı öngörülmektedir. İnsanlık, makineleşen dünyada şu alanlarda yeni değer önermeleri geliştirebilir:

  1. İnsan Odaklı Etkileşim ve Güven: Dijital trafiğin %90’ının botlar arası etkileşime döndüğü (“Ölü İnternet Teorisi”) bir ekosistemde, “kanlı canlı” gerçek insan etkileşimi, empati, göz teması ve güvene dayalı ilişkiler en pahalı “lüks” haline gelecektir. Hizmet sektöründe “insan tarafından sunulan” ibaresi, bir kalite ve statü göstergesi olacaktır.
  2. Stratejik Kürasyon ve Filtreleme: Üretim sorununun çözüldüğü ve içerik çöplüğüne dönen dünyada, asıl yetkinlik “üretmek” değil; “seçmek, elemek, bağlam kurmak ve filtrelemek” olacaktır. Gürültü içindeki sinyali ayırt edebilen insan küratörler, yeni dönemin kanaat önderleri olacaktır.
  3. Öznel Kusurluluk ve Provenans (Köken): Kusursuzluğun standartlaştığı ortamda, insani hatalar, öznellik ve eserin arkasındaki insan hikayesi (provenans), otantikliğin temel ölçütü olacaktır. Blockchain gibi teknolojilerle doğrulanan “Human-Made” (İnsan Yapımı) etiketi, organik gıda benzeri niş ama yüksek katma değerli bir pazar oluşturacaktır.

Sürekli Adaptasyon Baskısı ve Tükenmişlik

Modern iş dünyasının talep ettiği “sürekli yetkinlik güncelleme” (reskilling/upskilling) ve “hayat boyu öğrenme” baskısı, insanın biyolojik ve psikolojik sınırlarını zorlamaktadır. Mesleki yetkinliklerin yarı ömrünün (half-life of skills) dramatik biçimde kısaldığı bu dönemde, bireylerin sadece adaptasyon hızlarıyla ve esneklikleriyle değerlendirilmesi, “dijital paryaların” oluşmasına neden olmaktadır. Bu “Kızıl Kraliçe Yarışı” (yerinde saymak için sürekli koşmak zorunda olmak), toplumsal düzeyde anksiyete ve tükenmişlik sendromunu (burnout) tetikleyerek sosyal huzursuzluğa zemin hazırlamaktadır.

Gelecek Projeksiyonları ve Zaman Çizelgeleri

Mevcut teknolojik ve ekonomik veriler ışığında, olası gelecek senaryoları ve tahmini zaman çizelgeleri şu şekildedir:

Dijital Feodalizm (Tahmini: 2030–2045) Teknolojik sermayenin ve üretim araçlarının aşırı merkezileştiği, geniş kitlelerin ekonomik işlevsizlik (“gereksiz sınıf”) nedeniyle marjinalize edildiği, gözetim mekanizmalarının arttığı kötümser senaryo. İşsizlik oranlarının yapısal olarak %50 seviyelerini aşması, sosyal devletin zayıflaması ve gettolaşmanın artması muhtemeldir.

Hibrit Geçiş Dönemi (Tahmini: Önümüzdeki 20–30 Yıl) Kaos ve çözüm arayışlarının iç içe geçtiği, gerçekleşme olasılığı en yüksek senaryo. Mesleklerin dönüştüğü, krizlerin, protestoların ve adaptasyon süreçlerinin yaşandığı, insan-makine iş birliğinin (cobot) zorunlu olduğu sancılı bir araf dönemi. Hayat pahalılığının bazı alanlarda (enerji, gıda) düşerken, hizmet ve barınma gibi alanlarda arttığı dengesiz bir süreç.

Emek Sonrası Toplum (Post-Labor Economy) (Tahmini: 2050 ve Sonrası) Otomasyonun yarattığı devasa verimliliğin adil dağıtıldığı, zorunlu çalışmanın sona erdiği, Evrensel Temel Gelir (UBI) ve Evrensel Temel Hizmetler (UBS) modellerinin hayata geçtiği iyimser “kıtlık sonrası” (post-scarcity) dönem. İnsanlığın kendini gerçekleştirmeye odaklandığı bu ütopik dengeye ulaşılması için, öncesinde büyük sosyal ve politik reformların gerçekleşmesi gerekmektedir.

Geleceğin bu senaryolardan hangisine evrileceği, teknolojik determinizmden ziyade, politika yapıcıların regülasyonlarına, toplumsal taleplere ve etik tercihlerin gücüne bağlı olacaktır. Ancak kesin olan şudur ki; oyunun kuralları değil, oyunun oynandığı saha ve oyuncuların tanımları temelden değişmiştir.


Ufuk Uzun & “Gemini 3.0 Pro (Canvas)”
İstanbul, Türkiye
Ocak 2026

Spring Boot & k8s – Graceful Shutdown

Spring Boot 3.4 release (sürüm) notlarında şu kısım belki sizlerin de dikkatini çekmiştir:

Applications are now shut down gracefully by default. We’ve had graceful shutdowns for years in Spring Boot…

Spring Boot 2.3 ile gelen “graceful shutdown” (zarifçe kapatma ☺️) özelliği meğerse default (varsayılan) davranış değilmiş. (üzgünüm ki ben de yeni farkettim)

Spring Boot 3.4 öncesi uygulamalarda “graceful shutdown” özelliğini aktif etmek için application.yml‘ımıza şunu eklememiz gerekiyor, aksi halde “eski” default değer olan “immediate” geçerli oluyor, devam eden istekler çat diye “kill” ediliyor ve HTTP Status Code 5xx dönülür.

server:
    shutdown: graceful

Konunun k8s bağlantılı önemli bir yanı da var. k8s deployment sırasında eski bir Pod’u öldürürken şu adımları izliyor:

  • k8s bir Pod’u silmeye başladığında, bu durum diğer bileşenler tarafından algılanır ve istekler kesilmeye başlanır, ancak bu async bir süreçtir, hemen kesilmez.
  • Bu istek kesme konusuna zaman kazandırmak için genelde preStop hook‘u ile sleep komutu kullanırız.
  • preStop hook’a geçtiğimiz sleep komutuna verdiğimiz süre bittiğinde (çoğunlukla 5 – 10 saniye verilir) k8s Pod’a SIGTERM gönderir.
  • Hala sonlanmamış istekler varsa onlar için de uygulamamız tarafında ayarlanan süre kadar beklenir (spring.lifecycle.timeout-per-shutdown-phase, default 30 saniye).

Buraya kadar geçen süre terminationGracePeriodSeconds ile ayarlanan süreyi geçerse k8s SIGKILL gönderir ve zorla kapatır. terminationGracePeriodSeconds için sleep ve Spring’in timeout-per-shutdown-phase sürelerimizin toplamını dikkate alacak şekilde uygun bir zaman tanımlamalıyız:

terminationGracePeriodSeconds: 45
...
  lifecycle:
    preStop:
      exec:
        command: ["sleep", "10"]

Not: preStop sleep komutu sırasında Pod’unuz istek almayı kesmiş ve elindeki isteklere çoktan cevap verilmiş, ve dolayısıyla uygulamanızın graceful kapanmasına gerek olmayan senaryolar olabilir. Ancak bu istisnai bir durumdur. İdeal senaryoda hem uygun bir preStop ayarlanmalı hem de uygulamamız “graceful” kapanacak şekilde ayarlanmalıdır.

Spring Boot 3.2 ve Java 21 Yenilikleri

Spring Boot 3.2 ve Java 21 güncellemeleri, çeşitli yük testi senaryoları ve onların sonuçlarından bahsettiğim sunum:

Sunumda bahsi geçen git repoları ise şu şekilde:

https://github.com/ufuk/java-new-features-demos -> Java 6’dan Java 21’e (ve sonrasında) neler değişti, birim testi formunda örnek kodlar eşliğinde, kısa bir yolculuk

https://github.com/ufuk/load-test-demos -> Sunumda bahsedilen demo projeler ve yük testi scriptleri

Java 7’den 17’ye Dikkatimi Çeken Yenilikler

2010 yılında -henüz ikinci sınıftayken- tanıştığımda Java 6. versiyonuyla piyasada en çok kullanılan diller arasındaydı, ve bu niteliği halen süregelmekte. Zaman içinde pek çok yeni alternatifi ortaya çıktı, ve mevcut alternatifleri daha da güçlendi. Uzun süre sessiz ve hantal görünse de, zamanla daha efektif bir sürüm politikasına geçiş yapıldı ve Java’nın evrimi oldukça hızlandı. Artık altı ayda bir yeni Java versiyonu çıkmakta, her yeni versiyonla birlikte yeni özellikler ve kuluçkadan henüz çıkmış yeni “ön izleme (preview)” özellikler kullanıma sunulmakta. Bu altı ayda bir çıkan yeni versiyonlardan bazıları LTS (Long Term Support) (Java 8, 11 ve 17) yani güvenlik ve hata düzeltmeleri için “uzun dönem destek” sözü verilmiş versiyonlar olarak lanse edilmekte ve bu sebeple de “production” ortamlarında sıklıkla bu versiyonlar tercih edilmekte.

Ne zamandır aklımda olan, yeni versiyonlarda gelen özellikleri derleme hevesimi, Spring Boot’un 3. versiyonunun yaklaşmasının da motivasyonuyla nihayet gerçekleştirdim. Spring Boot 3 ile birlikte desteklenen minimum Java versiyonu 17 olacak; yani en güncel LTS versiyon.

“Automated” her türlü testin, bizi kodda değişiklikler yapma konusunda çevikleştirmesinin yanında, kodumuz için yaşayan birer dokümantasyon olduğunu vurgulamak niyetiyle, bu derlemeyi yeni özelliklerin sıralandığı bir blog yazısı yerine, özenle seçilmeye çalışılmış isimlendirmelerle bezeli bir test projesi olarak kurguladım. Elbette testlerle hızlı çalıştırılabilir küçük demolar şeklinde tanıtmaya çalıştığım yeni “dilsel” özellikler yanında Java’nın “internal”larında da pek çok yenilik mevcut. Hatta bazıları biz farkına bile varmadan uygulamalarımızın performansını ve kaynak tüketimini iyileştirmeye imkan sağlayan yenilikler. Bunların detaylarını okumak için versiyona özel test sınıfı başlarındaki Javadoc yorumlarındaki bağlantılara göz atmayı ihmal etmeyin.

Bazı yerlerde // TODO‘lara denk geleceksiniz. Fırsat buldukça o eksikleri tamamlamaya, örnekleri çoğaltmaya, ve yeni versiyonlarda gelecek olan yeni özelliklerin örneklerini eklemeye devam etmeyi umuyorum.

Şimdilik, keyifli okumalar:

https://github.com/ufuk/java-new-features-demos

Spring Boot 2.2 vs 2.3 vs 2.4 (Java 11)

Geçen sene Spring Boot 2.2.0 release notlarında bahsi geçen performans iyileştirmelerini gözlemledikten sonra elde ettiğim bulguları şu yazı ile paylaşmıştım: Spring Boot 2.1 vs 2.2: Bellek Kullanımı ve Başlangıç Süresi İyileşmiş

https://start.spring.io/ üzerinden an itibariyle seçilebilen Spring Boot versiyonlarını Java 11 ile ayrı ayrı VisualVM ile gözlemleyerek, yeni bir Spring Boot projesi oluştururken yapacağımız seçimlerin performansa ve kaynak kullanımına ne gibi etkileri olabileceğini yeniden gözlemlemeye çalıştım.

LTS versiyon olmadığı için Java 15 ile ilgilenmedim; onun yerine Java 17’yi beklemeyi düşünüyorum. Ayrıca önceki yazıda Java 8’den Java 11’e geçişte bariz bir iyileşme sağlandığı için Java 8 ile de ilgilenmedim.

Gelelim sonuçlara:

Spring Boot2.2.122.3.72.4.1
Final “ayrılmış” bellek (heap size)~383 MB~383 MB~383 MB
Final “kullanılan” bellek (used heap)~67 MB~70 MB~237 MB
Maksimum “kullanılan” bellek~248 MB~214 MB~237 MB
Uygulama başlangıç süresi~9.5 sn~9.7 sn~11 sn

Not: Önceki yazı sırasında gözlemleri farklı bir uygulama üzerinde yaptığımdan buradaki değerlerle karşılaştırmak yanlış olur.

2.2.12’den 2.3.7’ye geçerken bir miktar iyileşir gibi olan maksimum “kullanılan” bellek dışında bir iyileşme gözlemleyemedim. İyileşme gözlemleyememek bir yana, 2.4.1’e giderken tablo bir miktar kötüleşiyor hatta…

Bu yazıda geçen yazıdaki gibi dramatik bir sonuç çıkmadı. Zaten her yeni Spring Boot versiyonu da performans / kaynak kullanımı iyileştirmesi vaat etmiyor. Ben yalnızca geçen sürede bir şeyler değişmiş mi gözlemlemek istedim…

“Gözlem” derken?

Bu iki yazıda yaptığım şeyi özellikle “performans testi” yerine basitçe “gözlem” olarak nitelendiriyorum. Performans testi gibi daha fazla değişkenin faklı bakış açılarıyla ele alınacağı, daha ciddi uğraş gerektiren bir çabaya henüz girmedim.

Diğer taraftan, dikkatinizi çekmek istediğim başka bir nokta var: Örneğin farklı “garbage collector” türleri ve farklı JDK dağıtımları arasında karşılaştırmalar yapmak gibi uğraşlara da girilse, uygulamanın gerçek çalışma zamanı metrikleri de elde edilse, en nihayetinde burada ortaya çıkacak değerler uygulama karakteristiğine göre değişecek ve uygulama gereksinimlerine göre farklı yorumlanmak durumunda kalacak. Örneğin bir “batch” uygulamasının “key” performans metriği başlangıç süresi ve bellek kullanımından ziyade belirli bir zaman aralığında kaç kayıt işlediği olabilir. Benzer şekilde, örneğin bir REST API uygulamasının eş zamanlı kaç isteği, ne kadar bellek kullanarak, ve ortalama kaç milisaniyede işleyebildiği o uygulamanın asıl irdelenmesi gereken metrikleri olabilir. Bunlar gibi metrikleri ölçecek ve değerlendirecek yazılarda görüşmek dileğiyle…

Spring Boot 2.1 vs 2.2: Bellek Kullanımı ve Başlangıç Süresi İyileşmiş 🥳

Spring Boot 2.2.0 güncellemeleri arasında dikkatimi en çok performans iyileştirmeleri çekti; hem bellek kullanımı hem de uygulama başlangıç süresinde iyileştirmeler getirildiği söylenmiş:

Ben de Spring Boot 2.1.4 (Java 8) kullanan bir projemizi -tek fark Spring Boot versiyonu olacak şekilde- önce birkaç kere 2.1.4 ile, sonra birkaç kere de 2.2.0 ile ayağa kaldırdım ve uygulamayı VisualVM ile gözlemledim. Uygulama başlangıç zamanı / CPU kullanımı anlamında farkedilebilir bir iyileştirme gözlemleyemedim, diğer taraftan bellek kullanımının bir hayli iyileşmiş olduğunu gördüm:

Spring Boot2.1.42.2.0Fark
Final “ayrılmış” bellek (heap size)~1.6 GB~1 GB-37.5 %
Final “kullanılan” bellek (used heap)~600 MB~240 MB-60.0 %
Maksimum “kullanılan” bellek~630 MB~450 MB-28.5 %
Uygulama başlangıç süresi~75 sn~75 sn0

Bu değerler, ayağa kalkmasının üstünden kısa bir vakit geçmiş, fakat henüz hiçbir istek karşılamamış uygulamalardan alındı. Daha gerçekçi bir test, çalışma zamanı davranışlarını daha uzun vadede incelemeyi gerektirir elbette. Ancak yine de bu gördüklerim beni etkilemeyi başardı…

ÖNEMLİ GÜNCELLEME: Eğer Java 11’e geçerseniz…

Yukarıdaki testi Java 8 ile, sadece Spring Boot versiyonunu değiştirerek gerçekleştirmiştim. Java 11 ile test ettiğimde ise gözlerime inanamadım. Spring Boot 2.2.0 ve Java 11 ikilisiyle, Spring Boot 2.2.0 ve Java 8 ikilisine göre hem bellek kullanımında hem de uygulama başlangıç süresinde yaklaşık yarı yarıya iyileşme sağlandı…

Madem Java 11 ile böyle bir iyileşme sağlandı, belki de Java 8’den sonraki LTS (Long-term support) versiyon olan Java 11’e geçmek için güzel bir bahane bulmuş olabiliriz:

Bootiful günler dilerim 🤓

“Başarmak en büyük intikamdır.”

Oktay Mahmuti’nin çok beğendiğim ve canlı izleme şansı da bulduğum ilham verici TEDxIstanbul konuşması:

Ne Olup Bittiğinden Habersiz Testlere Derman: MocksCollector

Test yazmanın en büyük getirisi yazılan koda dair hızlıca geri bildirim alabilmek:

(bkz: https://ufukuzun.wordpress.com/2017/04/19/unit-testing-sunumu/)

Test yazmaya başlayacak yada yeni başlamış geliştiricilerin aklındaki ilk soru genelde şu şekilde oluyor: “Ne kadar test yazmalıyız / nerede durmalıyız / hedefimiz sadece %100 coverage (kapsama) mı olmalı?” — Örnekler çoğaltılabilir. Bu soruların cevabının test yazmanın temel getirisi olan geri bildirim almakta saklı olduğunu düşünüyorum. İdeal durumda testlerimiz öyle kapsayıcı olmalı ki, yapılan her geliştirmeye doğru geri bildirimler vermeli, ve testler geçiyorsa canlıya çıkmaya hazırdır denecek kadar içimizi rahat ettirmeli. İşte tam bu noktada karşımıza “kaliteli test” kavramı çıkmakta. Her geliştirmemize karşılık doğru geri bildirimler veren, deyim yerindeyse arkamızı kollayan testlere “kaliteli”dir diyebiliriz. %100 branch/line coverage bizi bu hedefe yaklaştırsa da çoğu zaman yeterli değildir.

Test kalitesini arttırma çabasına bir örnek olması açısından yaklaşık 5 sene önce n11’de çalışırken karşılaştığım bir test kalitesi sorunsalını çözümeye çalışırken uyguladığım yaklaşımı sizlere paylamak istiyorum:

MocksCollector

Java ile web uygulaması geliştirenlerin neredeyse vazgeçilmezi haline gelmiş Spring çatısı ile geliştirme yaparken Controller / Service / Repository katmanlarına ayrılmış bir şekilde kodlarımızı yazarız. “Service” katmanında ilgili domainin “business logic”leri kodlanır, ve bu sırada ilgili domainin “Repository”si ve pek çok başka “Service” enjekte edilerek (@Autowired) ve kullanılarak business logic gerçeklenir. Bu servisler zamanla büyür, büyüdükçe belli ilgilere göre metotlar gruplanarak başka serviscikler meydana getirilir, böyle devam eder gider.

Şöyle bir durumla karşı karşıyaydım: Geliştirme yapacağım servis 10’dan fazla servisi kullanılıyordu. Bu servislerden bir kaçının farklı şekillerde kombine edilerek çağrıldığı birden fazla public metoda sahipti. Bu metotların birim testleri de yazılmıştı, ve “coverage” %100’dü. Ben de farklı bir business logic için çağrılacak yeni bir metot ekleyecektim. Ekledim de. Fakat testini yazarken şunu farkettim: Metodumda farkında olmadan, aslında benim metodumda çağrılmaması gereken, hatta çağırıldığında çalışma zamanında (runtime) business logic anlamında sıkıntı çıkaracak bir servisi çağırmıştım. Fakat testim bu durumdan habersizdi. Güvendiğim dağlara yazıklar olmuştu. Testim geçiyordu fakat kodum yanlıştı. Hemen testimde değişikliğe giderek o an o test sınıfında tanımlı tüm mock servisleri geçtiğim bir verifyNoMoreInteractions(…) satırı ekledim. Böylece verifyNoMoreInteractions(…) öncesinde verify() ile varlığını kontrol ettiğim mock etkileşimleri (interactions) dışında başka bir etkileşim olmadığı konusunda içim rahatladı. Yanlışlıkla başka bir servis ile etkileşime girildiğinde testim bana anında geri bildirimde bulunacaktı. Ancak o sırada aslında bu durumun ne kadar da yaygın olduğunu farkettim. Mock kullanılan neredeyse tüm testlerde bu durum gözden kaçıyordu. verifyNoMoreInteractions() kullanımı bu farkındalık olmadığı için pek de yaygın sayılmazdı.

Okumaya devam edin Ne Olup Bittiğinden Habersiz Testlere Derman: MocksCollector

Biz Bunları Gist’lerimizde Anlattık! – PostgreSQL

Geliştirici olarak bir projeden/işyerinden ayrılırken “bu projeye çok emek verdi(m)(k), bazı kısımlar şahane, lazım olur günün birinde, zipleyeyim de atayım kenarda dursun” hissiyatı çoğumuzda olur. Ben ise şu iki sebeple bunu yapmaya gerek görmüyorum:

  1. Geçmiş deneyimlerimiz ile yeni çevrede öğrenilen yeni bilgileri harmanlayarak daha iyilerini yazabileceğimize inanıyorum
  2. Geçmiş deneyimlerimi unutmamak için blog ve Gist yazıyorum

(Ayrıca projeyi o şekilde başka yerlere kopyalamak yasal olarak da sıkıntılı olsa gerek.)

github-gist

Gist yazmak da blog yazmak gibi, ama ağırlıklı olarak kod parçaları -hatta çoğu zaman dosyalar- içermekte. Bir baktım 2015’ten bu yana Gist karalıyormuşum. Bazıları public, bazıları private, bazıları blog tarzında uzunca (onları buraya taşısam daha iyi olacak), bazıları bir kaç kelime açıklama ardından bir kaç dosyadan oluşmakta. Her gün işim düşmese de 1-2 ayda bir işim düşüyor oradaki notlarıma.

Bu sabah production ortamındaki bir durumu çözmeye çalışırken öğrendiğim bir yöntem için yeni bir Gist yazınca, ben neden Gist yazıyorum diye tekrardan bir düşünüp yazıya dökmek istedim. Gist PostgreSQL üzerineydi. Geriye dönüp bakınca farkettim, 1 yıl içinde PostgreSQL ile alakalı faydalı olduğunu düşündüğüm 5 adet Gist yazmışım. Günün birinde sizlere de faydalı olması dileğiyle, buyrunuz…

ALTER TABLE ve başka pahalı sorguların çok daha hızlı çalışması için:


BEGIN;
LOCK TABLE … IN SHARE MODE;
SET LOCAL WORK_MEM = '256MB';
ALTER TABLE …;
COMMIT;

Tabloyu kilitlemeden INDEX ekleyip çıkarmak için:


CREATE INDEX CONCURRENTLY your_index_name on your_table_name (your_column_name);
DROP INDEX CONCURRENTLY your_index_name;

Okumaya devam edin Biz Bunları Gist’lerimizde Anlattık! – PostgreSQL

Java 8 Sertifikasyonu (OCAJP 8) – Bölüm 1: Java’nın Temelleri

Bu birinci bölümden itibaren sınavda karşımıza çıkacak konulara değinmeye başlıyoruz. Verilen bilgilerin bazıları zaten bildiğiniz şeyler olacak, ancak bir sınava gireceğimizi ve pek çok yanıltıcı soru olacağını unutmayalım. Bazılarına önceleri benim de dikkat etmediğim, sınavda çeldirici olabilecek bazı özel noktaları “DİKKAT!” etiketiyle belirtiyorum. Verilen bilgilerin çoğunu bu kategoriye girmeye aday olanlardan seçmeye çalıştım. Eğer tamamını okumaktan sıkılırım diyorsanız sadece “DİKKAT!” etiketli kısımları okuyabilirsiniz.

Java Sınıf (Class) Yapısı

  • Java sınıflarının iki temel elemanı vardır: metotlar (methods) ve alanlar (fields).
  • Bunlara aynı zamanda sınıfın üyeleri (members) da denir.
  • Metotlar fonksiyon (function) yada prosedür (procedure) olarak da ifade edilebilir.
  • Alanlar değişkenler (variables) olarak da bilinir.
  • Alanlar sahip oldukları değerler itibariyle sınıf örneğinin (instance) durumunu (object’s state) belirlerken, metotlar sınıf örneğinin durumu üzerinde işlem (operation) yapar ve sınıfın davranışlarını tanımlar.
  • Bir sınıf bu sınıf üyelerinin hiçbirini barındırmayabilir, yada birini veya her ikisini barındırabilir. Yani şu üçü de geçerli sınıf tanımlarıdır:
class Animal {
}
class Animal {

    String name;

}
class Animal {

    String name;

    public String getName() {
        return name;
    }

    public void setName(String newName) {
        name = newName;
    }

}
  • Bir başka sıklıkla karşımıza çıkan kod parçaları ise yorumlardır (comments). Yorumlar kod içerisine eklediğimiz açıklamalardır ve derleyici (compiler) tarafından dikkate alınmaz. Tek satırlı, çok satırlı ve Javadoc tipinde yorumlar mevcuttur:

Okumaya devam edin Java 8 Sertifikasyonu (OCAJP 8) – Bölüm 1: Java’nın Temelleri