Kategori arşivi: Yapay Zeka

Kim Yapay Zeka Ile Bir Ürün Geliştirip, Canlıya Alamaz?

Canlı tecrübesi olmayanlar!

Daha önce sürüm yapıp, canlı deployment’i, bir canlı problemi için kök neden analizi, thead ya da ya heapdump ya da memory leak analizi yapmamış ve gerekli monitoring ve tracing altyapısını kurmamış birisi süper bir uygulama da geliştirse, onu canlıda işletemeyeceği için bu alandaki faaliyetlerinin hiçbir anlamı yoktur.

Lokalde çalışıyor söylemine başvuranlara selamlar.

Canlıda Patlayan Uygulamalar

Evet, yeni ortaya çıkan bir yapay zeka söylemini de demistifiye edelim.

Söylem şöyle:

“Yapay zeka ile geliştirilmiş uygulamalar canlıda patlar ve sen ne yaptığını bilmiyorsan başın büyük beladadır.”

Doğru.

Ama insan tarafından geliştirilmiş uygulamalar da canlıda patlar.

Bu yüzden onlarca yıldır yazılım mühendisliğinde şu mekanizmaları oluşturuyoruz:

– Automated tests

– E2E tests

– Static analysis

– Monitoring

– Logging

– Metrics

– Tracing

– Health checks

– Feature flags

– Canary deployments

– Blue/green deployments

– Automated rollback

– Load balancing

– Redundancy

Bunların varlık sebebi zaten yazılımcının yazdığı kodun hatasız olduğuna güvenmememizdir.

Yapay zeka burada yeni bir problem ortaya çıkarmadı. Sadece kod üretim hızını dramatik şekilde artırdı.

Dolayısıyla artık asıl soru:

“Yapay zekanın yazdığı kodu tamamen anlayabiliyor muyum?” değil.

Asıl soru:

“Bu sistem yanlış davrandığında bunu tespit edecek, etkisini sınırlandıracak ve sistemi tekrar sağlıklı duruma getirecek mekanizmalarım var mı?”

Eğer cevabınız hayır ise, kodu yapay zekanın yazmış olması probleminiz değildir.

Probleminiz software engineering’dir.

Yapay zeka çağında iyi yazılım mühendisi, sistemdeki her satır kodu bilen kişi olmak zorunda değil.

Sistemin doğru çalışıp çalışmadığını nasıl kanıtlayacağını, yanlış çalıştığında bunu nasıl göreceğini ve nasıl kontrol altına alacağını bilen kişi olmak zorunda.

Ve tam da bu yüzden yapay zeka ile otonom yazılım geliştirmek için çok iyi yazılım mühendisi olmak hâlâ son derece önemli.

Tam Otonom Yazılım İçin Gerekli Şartlar

Tam otonom yazılım yani kod yazmadan, okumadan ajanların software factory tarzı ve loop engineering ile ürün çıkardikarı bir ortam için gerekli olan şeyler:

1. Tecrübeli ve gidişata hükmedip, yönetebilecek bir senior yazılımcı

2. Bu şahsın ne istediğini ya da müşterinin ne istediğini çok iyi bilmesi

3. İyi gereksinim analizi ve code review yapabilen bir llm (örneğin gpt sol/astra)

4. İyi kod yazabilen bir llm (örneğin opus)

5. İyi tanımlanmış ve teknik detayları ihtiva eden bir CLAUDE.md dosyası

6. Projenin altyapısını kurgulamak için oluşturulmuş referans mimarı

7. Referans kaynaklı, elden implemente edilmiş birkaç modül

8. Software factory pattern ve loop engineering yöntemini kullanabilmek için oluşturulmuş döngü mekanizması ve analiz yapan dil modeli ile oluşturulmuş geniş kapsamlı çalışma paketleri

9. Api hardening ve rate limiting çin gerekli kuralların tanımlanmış olması

10. Test türlerinin ve kapsama alanlarının tanımlanmış olması

11. Ürünü kabul etmek için kullanılacak onay/kabul kriterlerinin tanımlanmış olması

12. Onay/kabul kriterlerini testlere dönüştürüp, koşturabilecek bir test çatısı oluşturulması

13. Sürüm oluşturmak ve canlı deploment için gerekli mekanizmanın oluşturulması (release.sh, deploy.sh; kısaca ship.sh)

14. Canlıda smoke testlerin koşturulabileceği yapının oluşturulması

15. Canlıda log dosyaların ve oluşan hataların dil modelleri ile paylaşımı ve bugfix döngülerinin kurgulanması

16. Uygulamanın karşıladığı her isteği bir traceİd ile işaretlenmesi; bu daha sonra tüm istek zincirini topluca görselleştirmek ve analiz etmek için dil modellerinin kullanacağı en etkili araç olacaktır

17. Monitoring için grafana, prometheus, zıpkın ve graylog gibi araçların kullanımı.

Şimdi loop.sh komutunu girerek, döngüyü başlatabilirsiniz. Hiçbir şeye müdahil olmadan uygulama ihtiva ettiği özelliklere göre 24/36/48/72 saat içinde tamamlanmış olacaktır.

Not: bu vibecoding değildir. Bu ne istediğıini net olarak bilen, bunun karşılığı çıktıyı alabilmek için gerekli kontrol ve yönlendirmeleri yapabilen, ürünü canlıya alıp, orada işletebilecek altyapıyı kendisi kurabilen birisinin yeni çalışma tarzıdır.

Eski ve Yeni Yazılım Dünyasının Çatışması

Eski yazılım mühendisliği dünyası ile yeni, yapay zeka destekli yazılım mühendisliği dünyası arasında muazzam bir çatışma ve çakışma yaşanıyor.

Bunu burada paylaştığım yazılara gelen yorumlarda da açıkça görüyorum.

Siz kör birisine mavi rengin nasıl göründüğünü anlatamazsınız.

Aynı şekilde, eski yazılım mühendisliği dünyasından gelen birisine, yeni yapay zeka destekli yazılım dünyasının sunduğu imkânları anlatmak da çok zor.

Çünkü bazı şeyleri anlamak için onları deneyimlemek gerekiyor.

Eskimiş bir perspektiften bakıyor olmak kötü. Ama daha da kötüsü, o perspektifin eskidiğinin farkında olmamak.

Yapay zeka, yazılım mühendisliğinde sadece kullandığımız araçları değiştirmiyor;

yazılım geliştirme biçimimizi, hızımızı, soyutlama seviyemizi ve hatta yazılım mühendisinin rolünü değiştiriyor.

Bu yüzden mesele birkaç yeni AI aracı öğrenmek değil.

Mesele, yeni yazılım mühendisliği dünyasına geçmek.

Ve bence bunun için fazla vaktimiz yok.

Yapay Zeka Çok Daha İyi ve Çok Daha Hızlı Bugfix Yapabilir

Bir programcının hataları anlama (root cause analizi) ve bugfix yapma hızını düşünün. Programcıların takılıp, kaldığı en belirgin alanlar bunlardır: troubshooting, root cause analizi ve bugfix.

Bunun nedeni nedir?

Programcıların yapay zekaya kıyasla sahip oldukları bağlam kapasitesi.

Ben yapay zekaya milyon satırllık logları bir seferde yükleyip, ana root cause analiz yap diyebilirim. Bu onun 5 dakikasını alır. Sonraki 5 dakika da bugfix yaparak, sorunu ortadan kaldırır ya da tavsiyelerde bulunarak, hatanın giderilmesini sağlar.

Aynı şeyi bir programcı ile yapın. Nasıl bir sonuç alırsınız? Sonuç alıp, almama garatiniz yok. Muhtemelen analiz ya yapılamayacak, çünkü çok karmaşık bir sistemden bahsediyoruz ya da bu analiz çok zaman alacak, çünkü programcının zihninde gerekli mental modeli oluşturması için veriye ihtiyacı var yani milyon satırlık loglara ve koda. Önce onları okuması, sonra anlaması sonra gerekli bağlamı oluşturması gerekiyor. Makina bunu dakikalar içinde yaparken, insan günlerce uğraşabilir.

Bu yüzden yapay zeka çok daha hızlı analiz yapabilir ve çok hızlı da bugfix. 

Ben canlıdaki runtime analizinin yapay zeka araçları için biçilmiş kaftan olduğunu düşünüyorum. Bu amaçla Gpt ve Opus’un canlı ortamında oluşan tüm verilere Grafana, Prometheus, Zıpkın ve Graylog üzerinden oluşmasını ve analiz etmesini sağlayacağım. Bu şekilde oluşan hataları anında lokalize etme, gerekli bugfixleri yapma, yeni bir sürüm oluşturma ve uygulamayı yeniden deploy etmeleri mümkün olacak. Kod bazında refactoring neyse, runtime bazında refactoring de bu olacak.

Yapay Zeka Karşıtı Argümanlar Yetmez Oldu

Yavaş yavaş yapay zeka karşıtı savunmalar runtime’a doğru kaymaya başladı.

İlk zamanlar kod yazmaya gerek yok dediğimizde, “olur mu öyle şey, kod yazabilmek her zaman önemlidir ve yapay zeka bir yere kadar yazabilir” karşılığı veriliyordu.

Sonra kod yazmama olayı kabul gördü bu argüman cephesi kod review tarafına çekildi. Review yapmak hala şarttı ve bunu insanlar yapmalıydı.

Ben artık kod yazmaya gerek kalmadığı gibi kod okumaya da gerek kalmadii iddiasını savunuyorum. Buna karşılık olarak runtime’a bir exception gelirse, yok şu olursa, yok bu olursa gibi argümanlar geliyor. Kodu okuyabilip, düzeltebilmeliymişiz. Yani karşıtlık cephesi bu noktadan itibaren runtime’e taşınmış durumda.

Ben buna da bir karşılık verme idiasındayım. Artık buna da gerek yok, çünkü yapay zeka runtime logları üzerinden çok kolay bir şekilde akışı oluşturup, gerekli hataları tespit ettikten sonra gerekli buğfixleri yapabilir. Aslında yapay zekanın parlayacağı en doğal ortam runtime ortamı olacak, çünkü orada canlı, canlı olup, biteni takip edebilecek, öngörüler yapacak, gerekli adaptasyonları implemente edecek ve tavsiyelerde bulunacak. 

Yeni iddiam yapay zeka çok daha hızlı ve daha iyi buğfix yapabilir.

Bakalım bu noktada yapay zeka karşıtı savunmalar nereye çekilecek.

Runtime’dan sonra gidecek fazla bir yerleri kalmadı. Bence yapay zeka gerçeklerini artık kabullenmek gerekiyor.

Kompozisyon ve Soyutlama

Şimdi çok komplike olan bir sürecin nasıl bir komut ile halledilir hale geldiğinden yani kompozisyon ve soyutlamanın nelere kadir olduğundan bahsetmek istiyorum.

Bir ürün için release ve deployment sürecini düşünün. Sürüm için bir ürüne, deployment için bir altyapıya ihtiyacınız var.

Siz sadece release.sh komutu ile bir sürüm oluşturup, deploy.sh ile bunu altyapınıza deploy ediyorsunuz.

Bu ikisi, özellikle deploy.sh komutu çok karmaşık bir yapıyı çok basit bir şekilde kullanılır hale getiriyor.

deploy.sh komutunun çalışabilmesi için bir sunucuya, onun üzerinde bir işletim sistemine, sunucuya erişmek için ssh’ya, sunucu üzerinde uygulanın çalışma ortamı ayarlarına, deployment işlemi öncesinde kimin bu işi yapabileceğine karar veren bir identity servisine (SSO; Single Sign On), tanımlı rol ve yetkilere, ürün için nginx, postgres, redis gibi altyapı komponentlerine, deployment sürecini yöneten ve hata oluşması durumunda sürümü geri alabilen (rollback) bir araca ihtiyacınız var. Burada uzatmamak için networking, security ve ölçekleme konularına girmedim bile.

Sadece deploy.sh diyebilmek için kocaman bir altyapı dünyası kurmanız gerekiyor. Deploy yapan şahsın bunların hiçbirinden haberi bile olmak zorunda değil.

Benim örneğimde önce release.sh ile bir sürüm oluşturuyorum, akabinde deploy.sh ile sunuculara bu versiyon yükleniyor ve son adımda upload.sh ile oluşan tüm sürüm dosyaları versiyonlu olarak artıfact repository’ye yükleniyor. Bu üç adımın arka arkaya atılması gerekiyor.

Yazılım geliştirme aslında büyük ölçüde kompozisyon ve soyutlama üzerine kurulu. Durum böyle ise, benim bu üç adımı tek bir adıma dönüştürmem gerekir.

Yine benim örneğimde bunun karşılığı ship.sh. Tek bir komut ve altında kocaman bir okyanusvarı bir yapı.

Buraya nasıl geldim?

Önce yapmak istediklerim hakkında bir fikrim vardı. Sonra bunu netleştirdim ve ürünü geliştirdim. Daha sonra gerekli altyapıyı kurdum. Üzerine identity servisini inşa ettim. Akabinde release, deploy ve upload mekanizmasını oturttum. Şimdi sadece ship.sh yazarak, istediğim ürünü, istediğim yere deploy ediyorum. 

Dışardan bakınca tek bir script gibi duruyor: ship.sh

Karmaşıklık ortadan kalkmadı. Organize edildi ve görünmez hale getirildi.

ship.sh sadece bir kompozisyon ve geldiğim soyutluk seviyesine işaret ediyor. Onun altında release/deploy/upload soyutlamaları vardı. Yani soyutlamalar da bir zaman sonra yeni soyutlamalar yapmak için yapı taşına dönüşüyor.

Ben bir zaman sonra şu ürünü canlıya al komutunu sesli olarak beyan edeceğim. Yapay zeka aracı ship.sh komutunu koşturacak ve bu tek cümlenin altında yüzlerce, hatta binlerce teknik işlem gerçekleşiyor olacak.

Son 30 yılda yazılımda olan gelişmeler bu prensibe dayanıyor. Karmaşıklık yok olmuyor, sadece aşağıya doğru taşınıyor.

Makinelerle Olan Münasebetimiz

Programcılığın kısa bir geçmişine bakalım:

Delikli kartlar → Assembly → yüksek seviyeli diller → framework’ler → low-code/no-code → yapay zekâ ile doğal dil

Neden makineler ile münasebetimizi doğal dillere kadar taşıdık?

Doğal dille programlama aslında aniden ortaya çıkmış bir devrim olmayabilir. 70-80 yıldır ilerlediğimiz yönün mantıksal sonucu olabilir.

İnsan doğası gereği etrafını düşündüğü kadar, kullandığı dil ile de algılıyor. İnsan konuştuğu dil ile düşünüyor, kavramlar oluşturuyor ve dünyayı bu kavramlar üzerinden anlamlandırıyor.

Bu yüzden makinelere hükmetmek için geliştirdiğimiz dilleri de zaman içinde kendi dilimize yaklaştırdık.

İlk başlarda insan makinenin dilini öğrenmek zorundaydı. Sonra programlama dilleri makinenin dilinden uzaklaşıp insanın düşünme biçimine yaklaşmaya başladı.

MOV, JMP gibi makineye yakın komutlardan if, else, while, class, person, customer, order gibi insana ait kavramlara geldik.

Java, Python veya başka bir yüksek seviyeli programlama dili bu açıdan sadece teknik bir gelişme değildi. Aynı zamanda insanın makineye:

“Ben senin gibi düşünmek istemiyorum, sen beni anlamaya çalış.”

deme çabasıydı.

Yapay zekâ ile belki de bu uzun yolculuğun en önemli eşiğini geçiyoruz.

70-80 yıl boyunca programlama dillerini insana yaklaştırdık.

Şimdi ise ilk defa programlama dilini aradan çıkarmaya başlıyoruz.

Makineye nasıl yapacağını anlatmak yerine, kendi dilimizde ne istediğimizi anlatıyoruz.

Belki de yapay zekâ ile değişen şey programlamanın kendisi değil. İnsan ile makine arasında kimin kimin dilini öğrenmek zorunda olduğu.

Yazılımcının Yapay Zeka İle Geçirdiği Evreler

Yapay zeka ile çalışmaya başlayan birisinin tipik dönüşüm evreleri:

1.) Hiçbir yapay zeka aracı kullanmadan önceki evre:

“Sadece bir hype, cok gördük.”

2.) İlk temas:

“OMG.”

3.) Yapay zeka araçları ile ilk ciddi çalışma:

“Bu benim işlerimi gerçekten hızlandırıyor.”

4.) Günlük kullanım:

“Bunu daha önce nasıl yapıyordum?”

5.) İş yapış biçiminin değişmesi:

Artık yapay zekayı mevcut iş akışına eklemez. İş akışını yapay zekanın etrafında yeniden tasarlamaya başlar.

6.) Delegasyon evresi:

“Bunu neden ben yapıyorum ki?”

Yapay zekaya soru sormaktan, yapay zekaya iş vermeye geçer.

7.) Orkestrasyon evresi:

Tek bir modelle çalışmak yerine farklı modelleri, agent’ları ve araçları birbirine bağlamaya başlar. Kendisi işi yapan değil, işi yapan sistemi yöneten kişiye dönüşür.

8.) Otonomi evresi:

Promptlar uzamak yerine kısalmaya başlar. Çünkü sistem artık bağlamı, kodu, kuralları ve hedefleri bilir. İnsan giderek daha az “nasıl yapılacağını”, daha fazla “ne yapılacağını” tarif eder.

9.) Son evre:

Yapay zekayı artık bir araç olarak görmez.

Onu, istediği kadar scale edebildiği yeni bir tür iş gücü olarak görmeye başlar.

Ve sonra dönüp ilk evrede söylediği cümleyi hatırlar:

“Sadece bir hype, çok gördük..” 😄

Yapay Zeka İle ürün Geliştirme Yöntemleri

Yapay zeka ile ürün geliştirken iki yöntem kullanıyorum. 

Bunlar:

1. Tuval yöntemi

2. Finetuning yöntemi

Tuval yönteminde uygulamayı nasıl bir ürün istediğinden tam emin olmadığımda, kervan yolda dizilir mantığı ile adım adım şekillendiriyorum. Uygulama bir resmi tuval üzerinde çizermişcesine görsel olarak şekillenmeye başlıyor. Fırça darbeleri yani promptlar ile tuvalde resim çizer gibi uygulamanın oluşmasını seyrediyorum. Bu zaman alan bir iş, lakin bu şekilde zaman içinde ürünün nereye gitmesine dair bir vizyon oluşuyor ve uygulamayı buna göre şekillendirebiliyorum.

İkinci yöntemde net olarak ne istediğimi bildiğim için gerekli analizleri tamamladıktan sonra iş paketlerini Gpt ve Opus’a veriyorum ve onlar otonom olarak uygulamayı baştan sona inşa ediyorlar. Uygulama tamamlandığında finetuning ismini verdiğim işleme başlıyorum. Burada uygulamada değiştirmem gereken yerlere promptlar yazarak tekrar dokunuyorum. Bu işlem çok uzun sürmüyor, çünkü başlangıçta oluşturduğum spec’ler vizyonu ve ürünün kendisini net bir şekilde tanımlıyorlar ve yapay zeka araçları için bunları hayata geçirmek çocuk oyuncağı oluyor.

Birinci yöntem daha çok klasik yazılım geliştirme tarzına benziyor. Kod yazmasamda, ürünün canlı canlı oluşmasına şahit oluyorum ve gerekli yönlendirmeleri promptlar aracılığı ile yapabiliyorum.

İkinci yöntem daha çok software factory şablonuna tekabül ediyor. Bu daha önce bilmediğimiz ve kullanmadığımız bir yöntem. Loop engineering sayesinde tam otonom çalışan yazılım fabrikaları oluşturmak artık mümkün.

İki yöntem arasındaki fark yapay zekanın ne kadar iyi kod yazdığı değil, belirsizliğin nerede çözüldüğü.

Tuval yönteminde belirsizliği ürünü yaparken çözüyorum:

fikir → prompt → ürün → gör → düşün → yönlendir → ürün → …

Ürün aynı zamanda düşünme aracına dönüşüyor. Ortaya çıkan şeyi gördükçe ne istediğimi daha iyi anlıyorum.. Burada bu yüzden döngünün içinde olmam gerekiyor, yani prompt engineering yapmak zorundayım.

İkinci yöntemde belirsizliği kodlamadan önce çözüyorum:

vizyon → analiz → spec → iş paketleri → autonomous loops → çalışan ürün → refinement

Burada kod üretimi artık esas yaratıcı süreç olmaktan çıkıyor. Yaratıcı ve zor iş ürünün doğru tarif edilmesine kayıyor. Spec yeterince iyiyse implementasyon giderek mekanikleşiyor.

Dolayısı ile Software Factory yapay zekanın çok kod yazması değildir. İnsan ile implementasyon arasındaki doğrudan ilişkinin kopmasıdır.

Klasik yazılım geliştirmede insan kodu üretir. Yapay zeka destekli yazılımda insan kodu yapay zekaya ürettirir ve sürekli kontrol eder. Software Factory modelinde ise insan ürünü ve kuralları tarif eder, otonom ajanlar loop’ları, implementasyon, test, review ve düzeltme döngülerini kendi aralarında yürütürler. Böylece insanın işi kod üretmekten, üretim sistemini tasarlamaya doğru kayar.

Bu iki yöntemi birleştirip, hibrit bir yöntem oluşturmak da mümkündür:

tuval → vizyon oluşur → spec çıkarılır → factory devralır → refinement → ürün

Yeni ve Eski Refactoring Yöntemleri

Çok az yapıldığına şahit olmakla birlikte, eskiden nasıl refactoring yapılırdı?

Testler yoksa zaten refactoring diye bir şey söz konusu olamazdı. Testler olsa bile çok büyük çapta refactoringler yapıldığına şahit olmadım. Genelde bir sınıf ya da metot bazında refactoring işlemleri yapılırdı, çünkü oluşacak yan etkilerin tespit edileceğinin garantisini kimse veremezdi.

Oysaki yıllarca SRP, OCP, DIP yani SOLID ile mükemmel mimariler oluşturduk, tüm implementasyonları gizledik, dışarıya tanımlı API’ler sunduk, Spring ile dependecy injection yaptık.

Peki refactoring yapmayacaksak neden bu kadar refactor edilebilir mimariler oluşturduk? Çünkü yapabildiğimiz için.

Kodun yeniden yapılandırılması yani refactoring dış davranışı değiştirmeden, iç implementasyonu yenileme işlemidir. Buradaki amaç implementasyonun mevcut gereksinimleri kapsayacak şekilde yenilenmiş olmasıdır.

Hep OCP (open closed principle) ya da DIP (dependency ınversion principle) mevcut implementasyonu gelecek yeni gereksinimlere açık tutmak için varmış gibi algılandı ve uygulandı. Oysaki bu tasarım prensipleri daha iyi refactoring yapabilmek için vardır. Ama yazılımın bu kısmı çok kişiyi ilgilendirmediği ve SOLID ile kod yazmak daha zevkli olduğu için işin sadece kod yazma kısmına konsantre olundu.

Sonuç: koca koca, yeniden yapılandırılamayan, extend edilemeyen, hantal monolitler.

Bu yüzden bir uygulamanın ömrü on sene ile sınırlı hale geldi.

Ama yapay zeka ile durum tamamen değişti. Artık kodu yeniden yapılandırmak bir maliyet ve zaman problemi olmaktan çıkmaya başladı.

Eskiden aylar sürebilecek, kimsenin dokunmaya cesaret edemediği bir monoliti bugün yapay zeka desteğiyle parça parça yeniden yapılandırmak mümkün.

Üstelik yapay zeka sadece kodu değiştirmiyor. Mevcut sistemi analiz edebiliyor, bağımlılıkları tespit edebiliyor, testler oluşturabiliyor, refactoring işlemini gerçekleştirebiliyor ve ardından testleri tekrar çalıştırarak dış davranışın değişmediğini kontrol edebiliyor.

Bu aslında refactoring’in yıllardır vaat ettiği seydi:

Dışarıdan aynı sistem, içeride tamamen farklı bir implementasyon.

Bence yapay zekanın yazılım dünyasında yaratacağı en büyük değişimlerden biri de burada olacak.

Artık bir uygulamayı 10 yıl boyunca büyütüp, sonunda “buna artık dokunamayız, yeniden yazmamız gerekiyor” demek zorunda değiliz.

Gerektiğinde bir modülü, bir bounded context’i, hatta uygulamanın büyük bir bölümünü yeniden yapılandırabiliriz.

Bu noktada SOLID, Clean Architecture, DDD gibi yaklaşımların anlamı da değişiyor. Bunların amacı sadece “güzel kod yazmak” değil.

Asıl amaç değiştirilebilir yazılım üretmek.

Ve belki de ilk defa elimizde, bu değiştirilebilirliği gerçekten kullanabilecek kadar ucuz ve hızlı bir araç var: yapay zeka.

Bu yüzden geleceğin önemli yazılım geliştirme becerilerinden biri kod yazmak değil, mevcut bir sistemi güvenli bir şekilde sürekli yeniden yapılandırabilmek olacak.

Kod artık kutsal değil.

Davranış kutsal.

Implementasyon değişebilir.

Build vs Buy

Eskiden projelerimizde birçok açık kaynaklı ürünü kullanırdık:

  • SSO için Keycloak, OpenLDAP
  • Chat için Mattermost
  • Git için Gitea, GitLab
  • CI/CD için Jenkins
  • Artifact repository için Nexus
  • Storage için MogileFS, MinIO
  • Wiki için MediaWiki
  • CRM için EspoCRM, SuiteCRM

Bunların yerine geçecek uygulamaları kendimiz geliştirmek aklımızın ucundan bile geçmezdi.

Neden geçsin ki?

Bu ürünleri kullanarak ciddi anlamda zamandan tasarruf ediyorduk. Bunun karşılığında ise kendimizi bu ürünlerin sunduğu yapının içine sokuyor; kurulum, konfigürasyon, güncelleme, migration ve özellikle security açıklarıyla sürekli ilgilenmek zorunda kalıyorduk.

Hatta Mattermost, Gitea ve benzeri ürünleri kullandığım dönemlerde, gerekli security update’lerini zamanında yapmadığım için birden fazla sunucu kaybettiğim bile oldu.

Artık benim için durum değişti.

Yukarıda saydığım ürünlerin hiçbirisini kullanmıyorum.

Onların yerine, doğrudan kendi gereksinimlerime göre tasarlanmış uygulamalar geliştiriyorum.

Örneğin:

SSO / OAuth2

Uydu uygulamalarımızın login işlemleri için kendi SSO/OAuth2 sistemimizi geliştiriyorum.

Ben bu satırları yazarken sistem yaklaşık %70 oranında tamamlanmış durumda.

Gereksinimleri yaklaşık 7 saat önce tanımladım. O zamandan beri GPT ve Opus birlikte büyük ölçüde otonom bir şekilde implementasyonu gerçekleştiriyorlar.

Sistem tamamlandığında bütün uydu uygulamalarını yeni login sistemine geçireceğim.

Böylece bir çalışanın sadece tek bir hesabı olacak ve bütün uygulamalara aynı hesap üzerinden giriş yapabilecek.

Git & CI/CD

Gitea benzeri, tamamen kendi ihtiyaçlarımıza göre şekillendirilmiş bir Git uygulaması geliştirdim.

Artık bütün Git repository’lerimiz burada bulunuyor.

CI/CD süreçleri de sistemin bir parçası. Her commit ile pipeline otomatik olarak çalışıyor.

Dolayısıyla ayrıca Jenkins’e ihtiyacım kalmadı.

Artifact Repository

Oluşturulan uygulama sürümleri için Nexus benzeri kendi artifact repository uygulamamı geliştirmeye başladım.

Implementasyona dün başladım ve şu anda yaklaşık %80’i tamamlanmış durumda.

Nexus’un yüzlerce özelliğine ihtiyacım yok.

Sadece bizim gerçekten kullandığımız kısmını geliştiriyorum.

CRM

Müşteri ilişkilerini yönetmek için kendi CRM uygulamamızı geliştiriyorum.

Büyük ve genel amaçlı bir CRM ürününü kendi süreçlerimize uydurmaya çalışmak yerine, CRM doğrudan bizim süreçlerimize göre şekilleniyor.

Burada da implementasyon büyük oranda tamamlanmış durumda.

Storage

Kullanacağımız bütün görseller, videolar ve dosyalar için kendi storage sistemimi oluşturdum.

MogileFS benzeri çalışan bu sistemde bir dosyanın üç farklı kopyasını farklı node’lar üzerinde tutuyorum.

Bir node kaybolduğunda dosyanın diğer kopyaları sistemde kalmaya devam ediyor.

Peki geriye ne kaldı?

Şu anda kullandığım temel altyapı komponentleri şunlar:

  • Grafana
  • Prometheus
  • Zipkin
  • Graylog
  • WireGuard
  • PostgreSQL
  • Nginx

Bence yazılım dünyasında asıl büyük değişim burada yaşanıyor.

Eskiden sadece bir SSO sistemini geliştirmek bile aylar sürebilirdi.

Bugün ise belirli ve sınırlı gereksinimleri karşılayan bir SSO sistemi birkaç günlük bir işe dönüşebiliyor.

Bu da yıllardır yaptığımız Build vs. Buy hesabını tamamen değiştiriyor.

Eskiden hazır bir ürünü kullanmak çoğu zaman tartışmasız şekilde daha ekonomikti.

Bugün ise yüzlerce özelliğini kullanmadığım, iç yapısını tam olarak bilmediğim, sürekli security update’lerini ve upgrade süreçlerini takip etmek zorunda olduğum büyük bir sistem yerine; sadece kendi gereksinimlerimi karşılayan küçük ve sade bir uygulamayı birkaç gün içinde geliştirmek benim için gerçek bir alternatif haline geldi.

Elbette bunun bir bedeli var.

Kendi yazılımını geliştirdiğinde mimarinin, security’nin, testlerin, backup’ın, monitoring’in ve bakımın sorumluluğunu da tamamen üstleniyorsun.

Fakat artık bunların önemli bir kısmını kontrol eden ve sürekli test eden araçları da yine AI desteğiyle oluşturabiliyoruz.

Bence yapay zekânın yazılım geliştirmede değiştirdiği en önemli şeylerden biri tam olarak bu:

Build vs. Buy dengesi yeniden kuruluyor.

Eskiden başkalarının yaptığı Lego parçalarını kullanıyorduk.

Çünkü her Lego parçasını kendimiz üretmek ekonomik olarak mantıklı değildi.

Şimdi ise ihtiyaç duyduğumuz Lego parçalarını birkaç gün içerisinde, tam istediğimiz şekil ve büyüklükte kendimiz üretebiliyoruz.

Belki de önümüzdeki dönemde yazılım geliştirmedeki en büyük değişimlerden biri bu olacak:

Başkalarının yaptığı Lego parçalarını birleştirmek yerine, kendi Lego parçalarımızı üretmeye başlayacağız.

Yazılım Fabrikaları ve Loop Engineering

Eskiden girişimcilikte limitleyici tek faktör sermaye idi. Ne kadar sermayeniz varsa, o kadar ürün geliştirebiliyordunuz.

Bu sınırlayıcı etken ortadan kalkmış durumda.

Yine de geniş kapsamlı bir uygulama geliştirmek aylarınızı alabilir.

Bunun önüne geçmek için kesinlikle prompt engineering kullanmamanız gerekiyor. Bunun yerine loop engineering ile otonom çalışan ajanlar ile uygulamaları geliştirmelisiniz.

Benim örneğimde bu yazıyı kalema alırken 3 değişik uygulama toplamda 6 ajan tarafından otonom bir şekilde geliştiriliyor. Kesinlikle müdahil olmuyorum.

Ben her alt projeye başlamadan önce çok detaylı bir şekilde Gpt ile analiz seansları yapıyorum. Oradan iş paketleri ortaya çıkıyor ve daha önceki yazılarımda bahsettiğim gibi dosyalar ve orkestratör scriptleri ile her projenin iki ajan tarafından otonom implemente edimesini sağlıyorum. Genelde her alt proje 72-80 saat bandında nonstop çalışan ajanlar tarafından implemente edilmiş oluyor.

Bu yönteme yazılım fabrikası diyebiliriz. 

Fabrikadan çıkan ürünler doğal olarak canlıya alınacak türden olmuyorlar ama tayin ettiğim gereksinimleri %90-95 oranında karşılıyorlar. Geri kalan kısmını prompt engineering kullanarak finetuning dediğim işlem ile elden tamamlıyorum.

Özetle prompt enginnering ile yazılm yapmak çok zaman alan bir işleme dönebilir. Yer yer iğne ile kuyu kazmaya benzer. Tüm süreçleri otomatize etmek için kullanılabilecek en iyi yöntem loop engineering yöntemidir. 

İkinci Bir Bretton Woods Vakası

Şimdi olaya biraz da olumlu tarafından bakalım.

Biraz önce modellerin birlikte otonom çalışabilmeleri için Gpt’ye bir orkestratör python script yazdırdım. Script o kadar karmaşık ki benim onu yazmam muhtemelen 2 günümü alırdı.

Burada muazzam bir verimlilik artışı var.

Günümüze kadar bilgiye dayalı üretim kapasitesi büyük ölçüde insan emeğine bağımlıydı ve ölçeklenmesi ek işgücü gerektiriyordu. Yapay zekâ ile birlikte bazı sektörlerde bu bağımlılık önemli ölçüde ortadan kalkıyor.

Nasıl 1971’de Bretton Woods sisteminin sona ermesiyle para arzının altına olan bağı koparıldıysa, yapay zekâ ile de bilgiye dayalı üretim kapasitesinin insan emeğine olan bağı gevşiyor.

Kısaca burada verimlilik artıyor, bu ekonomiye pozitif yansıyacak ve refah seviyesi dolaylı olarak artacaktır.

Burada doğal olarak oluşan ekonomik değerlerin eşit olarak insanlara dağıtılması gerekiyor. Sermayenin kazanımları cebe indirmesi durumunda, durum ters tepecektir.

Belki de gelecekte bu dönemi, bilgiye dahali üretimin kendi Bretton Woods momenti olarak hatırlayacağız.

Yapay Zeka İle Çalışırken Dikkat Edilmesi Gereken İndikatörler

Yapay zeka ile çalışırken dikkat edilmesi gereken üç indikatör var.

1. Test kapsama alanı (test coverage)

2. Prompt sadelliği (prompt simplicity)

3. Bağlam zenginliği (context maturity)

Yapay zeka destekli yazılım geliştirmede sistemin olgunluğunu yalnızca üretilen kod miktarıyla değil, test kapsamının artması ve promptların sadeleşmesiyle de ölçebiliriz.

İlk iki indikatör birbirini tamamlar. Birincisi sistemin güvenilirliğini, ikincisi ise sistemin ne kadar iyi yapılandırıldığını ve yapay zeka tarafından ne kadar kolay anlaşılabildiğini gösterir.

Bir yazılım projesinde yapay zekanın ihtiyaç duyduğu bilgilerin ne kadarının prompt dışında, sistemin kendi içerisinde erişilebilir olduğu ise context maturity indikatöründe gizlidir.

Yapay zeka ile yazılım geliştirmenin olgunluk göstergesi, giderek daha karmaşık promptlar yazabilmek değil, giderek daha az açıklamayla doğru sonuçlar alabilmektir.

İyi bir sistem, yapay zekaya ne yapması gerektiğini söylemeyi kolaylaştırırken, nasıl yapması gerektiğini tekrar tekrar anlatma ihtiyacını ortadan kaldırır.

Özetle;

Kod tabanı olgunlaştıkça, test kapsama alanı artmalı, buna karşı promptlarda karmaşıklık azalmalı ve promptlar sadeleşmelidir. Yapay zeka gerekli bilgileri bağlam üzerinden bir araya getirerek, implementasyonu yapabilmelidir.

Yapay Zeka İle Api Tasarımında Dikkat Edilmesi Gerekenler

Yapay zeka ile api tasarımı yaparken ya da kör bir şekilde yapay zekanın api tasarımı yapmasına izin verirken dikkat edilmesi gereken iki önemli bir husus var.

Öncelikle hangi rollerin hangi haklar ile bu apilere erişilebileceğinin tayin edilmesi gerekiyor. Herkesin herşeyi yapabildiği apiler sistem için çok tehlikeli apilerdir. Apiye girişlerin mutlaka öncelikle api ismi, daha sonra rol ve hak seviyesinde kontrol edilmesi gerekmektedir. Bunun için öncelikle bir authentication ve akabinde de authorızation mekanizmasının oturtulması gerekiyor.

İkinci bir nokta api parametrelerinin ve apiye payload olarak gelen verilerin içerikleridir. Örneğin api /api/shop/1000/check şeklinde ise ve 1000 shopId ise, body içinde veri olarak shopId taşınmamalıdır. Eğer işlem için body içinde shopId varsa ve bu shopId kontrol edilmeden kullanılıyorsa, dışardan herhangi bir shopId vererek, başka bir shop için işlem yapılması sağlanabilir. Ayrıca kullanıcının 1000 numaralı shop’a sahip olup, olmadığı kontrol edilmelidir. Burada kaynak bazında erişim kontrolü gerekmektedir. 

Bu işlemlerin hepsi proje başlamadan önce api hardening konusu altında proje dosyalarında sabitlenmelidir. Bu şekilde yapay zeka araçları api tasarımı yaparken api hardening aracılığı ile apilerin izinsiz erişimini engelleyebilirler.

Bunları yapmazsanız benim gibi 2000 e yakın api için sonradan api hardening yapmak zorunda kalırsınız ve bu sizin 10-20 gününüzü alabilir ;-) 

Allahtan loop engineering var ve arka planda gpt ve opus tüm apileri tek tek tam otonom kontrol edip, gerekli ayarları yapıyorlar.

Tam Otonom Yazılım Nasıl Yapılır?

En basit hali ile loop engineering nasıl yapılır?

Aşağıdaki örnekte Gpt Sol analiz ve review, Opus ise implementasyonu üstleniyor. Sadece Opus ya da Sol kullanarak çalışılabilir, ama ortaya çıkacak sonuç çok sağlıklı ya da beklenir tipte olmayabilir.

Atılması gereken adımlar:

1. Gpt ile domain (alan) analizi yap ve iş paketlerini oluştur. İş paketleri ile uygulama adım, adım inşaa edilecek.

2. Gpt tüm gereksinimlerin iş paketleri olarak yer aldığı bir dosya oluştursun.

3. Opus ile olan işbirliğini koordine etmek için projede bir handoff dosyası gerekiyor. Gpt ve Opus bu dosya üzerinden birbirlerine iş paslayacaklar. Gtp’ya bu dosyayı da oluşturmasını şöyle.

4. Gpt ve Opus’un 5 ya da 10 dakikalık aralıklarla bir cronjob aracılığı ile handoff dosyasını check etmesini sağla. Bir cronjob oluştur demen yeterli olacaktır.

5. Gpt’den bir initial prompt alarak, Opus’un çalışmaya başlamasını sağla.

6. Gpt’ye Opus için gerekli kararları proje şartlarına uygun olarak kendisinin vermesini şöyle.

7. Gpt’nin mutlaka çok kritik seviyede kod review yapması talimatını ver.

8. Gpt’ye her iş paketi için birim, entegrasyon ve e2e testlerinin yazılmış olması ve her review içinde bu testlerin koşturulması gerektiği direktifini ver.

9. Gpt’ye oluşturulan APİ’ler için mutlaka hardening kurallarının uygulanması gerektiği direktifini ver.

Projenin büyüklüğüne göre 1-5 gün arasında uygulama çalışır hale gelecektir.

Proje içinde oluşan yönetim dosyaları şu şekilde (Projenin adi: Customer Care):

– customer-care-driver.md

Opus’a nasıl çalışması gerektiğini ve bir sonraki iş paketinin ne olduğunu söyleyen dosya.

– customer-care-handoff.md

Opus ve Gpt işbirliği için kullanılan dosya. Birbirleri ile bu dosya üzerinen iletişim kuruyorlar.

– customer-care-review.md

Gpt’nin Opus’a verdiği review cevapları. Burada ACCEPTED, BLOCKED gibi statüler üzerinden iş paketinin güncel durumu hakkında bilgi alışverişinde bulunuyorlar.

– lessons.md

Proje hakkındaki yapılan hatalar, öğrenmişlikler, çalışma tarzı ve Gpt’nin karar verme sorumluluğu hakkında bilgilerin yer aldığı dosya.

– project-rules.md

Proje kurallarının yer aldığı dosya. Bunlar test yazılması, Opus-Codex çalışma modeli, backend api yapısı gibi konular.

– todo.md

Seçilen mimarı, roller, ürün bilgileri, çözüm türleri gibi konuların yer aldığı dosya.

Bu dosyaları Gpt kendisi talimatlarınız doğrultusunda kendisi oluşturacaktır.

Benim bilgisayarımda şu an loop engineering yöntemi ile tam otonom olarak 2 uygulama geliştiriliyor. Diğer 2 uygulama için prompt engineering yöntemini kullanıyorum, çünkü orada akışı kontrol etmem ve yönlendirmem gerekiyor. 

Bu iki otonom geliştirilen uygulama yazılım fabrikasından çıktık sonra, finetuning yapmaya başlayacağım. Burada prompt engineering devreye giriyor olacak. Yani bir uygulamayı tam anlamıyla otonom oluşturmak ve hemen kullanmaya başlamak mümkün değil. Son dokunuşu yine insan yapmak zorunda.

Asıl Mevzu

Benim yazilima bakis ve yazilimi uygulayis tarzimi tamamen extreme programming (https://lnkd.in/d-EdTKsU) sekillendirdi.

Extreme Programming ile test güdümlü yazilimin ve refactoring yapma kabiliyetinin bir yazilim icin ve onu sekillendirme sürecinde ne anlama geldiklerini bu sekilde ögrendim.

Yazilimda cevik olmanin temelinde uygulamayi bir hamur gibi yogurabilme yetisi yatiyor (https://lnkd.in/eh53s4Kr). Her yeni müsteri gereksinimi ile uygulanin hamur gibi yogrulmasi yani yeni bir sekle sokulmasi zorunlu. Bunu sadece refactoring yönetimi ile yapabiliriz. Refactoring de sadece ve sadece yeterli ve kapsama alani genis testler varsa mümkün.

Genel olarak beni kodun yapisal durumu ilgilendirmiyor. Clean code, tasarim sablonlari, tasarim presipleri…. ne uygularsaniz uygulayin, en kutsal ve yüce kodu bile yazsaniz, testleriniz yoksa refactoring yapamazsiniz yani uygulamayi yeni müsteri gereksinimlerini tatmin edecek hale sokamazsiniz, yani uygulamayi hamur gibi yoguramazsinz.

Yazilimcilara yillarca kodu nasil edebi bir eser gibi yazacagi anlatildi, ama bu madalyonun sadece bir tarafiydi. Scrum ile diger tarafini gösterir gibi yaptilar, ama hicbir zaman kodun gercek anlamda nasil hamur gibi yogrulacagi konusuna deginmediler, cünkü bunun nasil yapildigina dair fikirleri yoktu. Scrum yukari, scrum asagi derken cevik oldugunu düsünen ekipler, cevik yazilim yaptiklarini düsünerek, yazilim ürünleri gelistirdiler ve her defasinda uygulama ellerinde patladigi icin duvara tosladilar. Hicbir zaman da bu neden oluyor diye sorgulamadan devam ettiler, cünkü scrum ile herkes cevikti.

Artik bunlarin hepsi mazide kaldi.

Yazlim tarihinde ilk kez hicbir teknik yönteme (clean code, tdd, solid, srp, dip..) ihtiyac olmadan bir uygulamayi hamur gibi müsteri istekleri dogrultusunda yogurmak mümkün. Bunun icin sadece dogru promptlar gerekiyor.

Yazilimdaki en can alici yöntem olan refactoring yöntemine gerekli deger verilmedigi icin bugüne kadar gelistirilen her uygulama tas gibi kaskati olmak zorunda kaldi. Teknik borclarin birikmesi durumu her daim daha da kötülestirdi, ama yine de gerekli refactoring calismalari yapmak yerine, bu hep ötelendi.

Artik bunun icin mazeret kalmadi. Bir uygulamayi gerekiyorsa komple silip, yeniden tasarlamak, yeniden müsteri gereksinimlerini ihtiyava edecek sekilde yogurmak birkac prompt setine bakar.

Artik mevzu clean code degil, clean prompt.

Yapay Zeka Destekl Adım Adım Proje Nasıl Geliştirlir?

Nasil ki tribünden futbol maci seyrederek iyi bir futbolcu olunamiyorsa, uzaktan yapay zeka gelismelerini takip ederek de bu konuda iyi bir yazilimci olunamaz.

Bu konuda ciddi iseniz, icine girmeniz yani oyunu oynamak icin sahaya inmeniz gerekiyor.

Sahaya nasil inersiniz?

Hemen bugün yapay zeka destegi ile bir proje yapmaya baslayarak.

Adim adim yapilmasi gerekenleri anlatiyorum.

1.) Paraya kiyin ve bir adet openai ve bir adet antropic pro hesabi acin. Unutmayin, bu yatirimi kendinize yapiyorsunuz. Cöpe atilmis bir yatirim degil bu. Böyle hissediyorsaniz, okumayi birakin ve kendi hayatiniza geri dönün.

2.) Bilgisayariniza Claude Code ve Codex Desktop’u kurun.

3.) Simdi hangi projeyi hayata gecirmek istediginizi kara kara düsünün.

4.) Basit bir projeyle baslayabilirsiniz. Örnegin bir todo mobil uygulamasi olabilir. Özellikle daha önce kullanmadiginiz bir teknoloji stack secin. Örnegin Java ile hic calismadiysaniz Java ve Spring boot secebilirsiniz. Daha önce mobile development yapmadiysaniz Flutter kullanin. Önemli olan daha önce hic tanimadiginiz bir teknolojik stack dünyasina adim atmaniz, cünkü bu sekilde yapay zekanin nelere kadir oldugunu cok hizli bir sekilde göreceksiniz ve neler yapabildiginizi gördügünüzde, agziniz acik kalacak.

5.) Codex altinda Gpt Sol modelini secin ve onunla sohbet etmeye baslayin. Böyle bir fikrim var, ne diyorsun diye sorun. Daha sonra bu projeyi hayata gecirecegim, bana Opus/Fable icin gerekli promptlari verir misin diye sorun. Size gerekli promptlari vermeye baslayacaktir. Ilk promptu alin ve Claude code penceresine gidin. Oraya copy/paste yapin ve calismasini izleyin. Opus ya da Fable size bir takim sorular ile dönebilir. Bu sorulari anlamaya calisin ama kendiniz cevap vermeyin. Bu sorulari Gpt Sol’a gösterin. Ondan bu sorulari cevaplayacak bir prompt vermesini isteyin. Daha sonra bu promptu Opus’a iletin. Opus isini tamamladiktan sonra size yaptiklarina dair bir özet gösterecektir. Bunu alin ve Sol’a aktarin. Bu sekilde Gpt review yapmaya baslayacak ve eksikleri size listeleyecektir. Bu isleme uygulama tamamlanana kadar devam edin. Gpt Sol analiz ve review, Opus ise implementasyondan sorumlu olacak. Sadece Opus ile calisiyor olmak, sistemin nasil calistigina dair yeterli bilgi edinmenizin önünde bir engel olabilir. Gpt analiz ve review konusunda cok iyidir ve sizin tüm sorulariniza mantikli cevaplar verecek ve Opus’u da dogru yönlendirecektir.

6.) Takildiginiz her yerde Gpt’ye sorun. Onun gidisati web tarayici üzerinden kontrol etmesini saglayin. Bunun icin gerekli pluginleri kendisi kurup, sizden izin isteyecektir.

7.) Gidisati adim, adim takip edip, Olusan kodu okuyun, anlamaya calisin. Anlamadiklarinizi Sol ya da Opus’a “neden böyle yaptin” diye sorun. Size herseyi anlatmalarini saglayin.

8.) Buraya kadar geldiyseniz, tebrik ederim, ilk yapay zeka destekli ürününüzü gelistirdiniz.

9.) Simdi sokaga cikin ve insanlari ve neler yaptiklarini gözlemlemeye baslayin. Cok kisa bir zaman sonra insanlarin karsilastiklari problemleri görmeye baslayacaksiniz. Iste bu problemler icin cözümler gelistirmeye baslayin.

10.) Artik sadece yazilimci degilsiniz. Artik problem bulup, bu problemleri ortadan kaldiran cözümleri olusturan bir yazilimcisiniz.

EOF – End Of Fun