Yapay Zeka Çağında Kıdemli Bir Flutter Mühendisi Gibi Düşünmek
Flutter topluluğunda kimsenin açıkça söylemediği bir sır var: "systems design" denildiğinde çoğu mühendis hemen load balancer ve mesaj kuyruğu diyagramları çizmeye başlıyor. Bak, anlıyorum — mülakat kitapları bize bunu öğretti. Ama bir Flutter uygulamasının *frontend* sistemlerini tasarlamanız istendiğinde — widget ağacı, state akışı, veri katmanı — ortam bir anda sessizleşiyor.
İşin özü şu: frontend systems design gerçekten var, gerçekten zor ve tam da yapay zeka araçlarının sizi ya inanılmaz üretken ya da tehlikeli derecede özensiz hale getireceği yer. Ortası yok.
Son bir yılımı AI kodlama ajanlarının Flutter uygulamalarını korkutucu bir hızla üretmesini izleyerek geçirdim. Üretilen kodun bir kısmı gerçekten çok güzel. Ama çoğu, üç farklı API'ye dokunan bir `StatefulWidget`'ın ayakta tuttuğu bir teknik borç yığını. Bu bir araç sorunu değil. Bu bir düşünme sorunu.
Hadi düzeltelim.
"Systems Design" Flutter İçin Gerçekte Ne Demek?
Kıdemli bir mühendis "bir chat uygulaması tasarla" dediğinde işe `ListView.builder` ile başlamaz. Sınırlarla başlar.
Backend mühendisleri servisler, veritabanları ve kuyruklar üzerinden düşünür. Flutter mühendislerinin düşünmesi gerekenler ise şunlar:
- **Widget decompozisyonu** — 600 satırlık bir widget ne zaman kendi klasörüne sahip odaklanmış widget'lara dönüşür?
- **State sahipliği** — hangi state widget ağacında yaşar, hangisi bir controller'da, hangisi bir repository'de?
- **Veri akışı** — network'ten piksele tek yönlü veri akışı nasıl kurulur?
- **Hata yönetimi** — retry'lar, fallback'ler ve hata durumları nerede yaşar?
Kıdemli bir Flutter mühendisi uygulamaya bir soğan gibi bakar. Dış katman widget ağacıdır (sunum). Orta katman state yönetimidir (uygulama mantığı). Çekirdek ise veri erişimidir (repository'ler, servisler, yerel depolama). Systems design'ın işi, bu katmanların birbirinin içine erimesini engellemektir.
Aklınızı Koruyan Kural: Widget'lar İş Yapmaz
Her mentee'ye verdiğim bir kural var: **widget'larınız iş mantığınızı bilmemeli, iş mantığınız da widget'larınızı bilmemeli.**
Eğer bir `TextFormField` doğrudan bir repository çağırıyorsa, sınırı ihlal ettiniz demektir. Repository'niz bir `TextEditingController`'ın ne olduğunu biliyorsa, ters yönde ihlal var demektir. Bu ayrım, kodun test edilebilir ve değiştirilebilir olmasını sağlar. AI çağında ise çok daha kritik bir şey yapar: bir ajanın tüm uygulamayı patlatmadan kodu düzenleyebilmesini mümkün kılar.
AI Oyunu Nasıl Değiştiriyor?
GitHub Copilot, Claude Code ve Cursor gibi yapay zeka araçları kod yazılma biçimini kökten değiştirdi. Bir öğleden sonra tüm özellikleri çalışan bir CRUD uygulaması çıkarabiliyorum. Bu abartı değil; bu sıradan bir perşembe.
Ama onlarca AI destekli Flutter projesinden sonra öğrendiğim şey şu: **ajanlar kod yazmada mükemmel, mimari karar vermede berbattır.**
Bir ajana eksik bir widget içeren bir klasör ve net bir talimat verin, işi bitirir. "Bu uygulamayı daha iyi yap" gibi muğlak bir komut verin, sessizce kırk tane alakasız karar verir. Bazıları felaket derecede yanlış olur.
OpenClaw ajanının bir spor salonunun rezervasyon sistemini hacklemesinin bu kadar viral olmasının nedeni tam da bu — kod zekice olduğu için değil, ajana *kısıt* olmadan bir *hedef* verildiği için. Flutter kod tabanlarında da aynı paterni görüyorum: ajanlar mimari korkuluklar olmadan başıboş bırakılıyor.
Senaryo Bir: AI'ın Ürettiği Karmaşa
Geçen ay mentorluk yaptığım bir geliştirici projesini açtı ve ajanın ürettiği şeyi gösterdi. Görev basitti: "Sipariş ekranına çevrimdışı destek ekle."
Ajanın yaptıkları:
- `pubspec.yaml` dosyasına `path_provider` ve `sqflite` ekledi
- Bir widget'ın `initState`'i içinde SQLite veritabanı oluşturdu
- Üçüncü taraf bir HTTP istemcisini arayüzü olmayan özel bir sınıfa sardı
- Tüm JSON yanıtlarını global bir static değişkende cache'ledi
Teknik olarak "çalıştı" — mutlu senaryoda. Ama veritabanı bağlantısı sızdı, cache'in geçersiz kılma stratejisi yoktu ve SQLite işlemleri ana izolat üzerinde çalıştığı için yavaş cihazlarda arayüz dondu.
Çözüm daha iyi prompt'lar değildi. Çözüm **daha iyi systems design'dı** — ajana kod yazdırmadan önce kalıcılığın soyut bir repository arkasında yaşayacağına, [drift](https://drift.simonbinder.eu) gibi derleme zamanı güvenli depolama kullanılacağına ve UI'ın sadece gözlemlediği bir state akışı sunulacağına karar vermek.
Her Flutter Mühendisinin Bilmesi Gereken Systems Design Paternleri
Bir Flutter özelliği tasarlamam istendiğinde kullandığım playbook'u paylaşayım — ister bir insan, ister bir ajan, isterse ikisinin kombinasyonu için olsun.
1. Üç Katmanlı Pasta (Sunum / Uygulama / Veri)
- **Sunum katmanı**: widget'lar, animasyonlar, routing. Sadece state tüketir ve intent'ler yayar.
- **Uygulama katmanı**: state yönetimi (Riverpod provider'ları, Bloc cubit'leri, ChangeNotifier'lar). Intent'leri state değişikliklerine dönüştürür.
- **Veri katmanı**: repository'ler, servisler, yerel veritabanları, network istemcileri. Dış dünyayla konuşmanın karmaşık işini halleder.
Her katman sadece doğrudan altındaki katmanla konuşur. Widget'lar asla `Dio`'ya dokunmaz. Repository'ler asla `BuildContext` döndürmez.
"Form doğrulama nerede yaşar?" ya da "API anahtarını Provider'a koymalı mıyım?" diye soruyorsanız — cevap her zaman "o konunun sahibi olan katmanda"dır.
2. Tek Yönlü Akış Olarak State Yönetimi
Hangi state yönetimi kütüphanesini seçtiğiniz umurumda değil — [Riverpod](https://riverpod.dev), [Bloc](https://bloclibrary.dev) ya da düz `InheritedWidget` — akış tek yönlü olduğu sürece:
```
State Akışı -> Widget'lar Render Eder -> Kullanıcı Intent'leri -> State Mutasyonları -> Tekrar
```
İki yönlü binding'lerin olduğu anda bug'larınız var demektir. Widget'ların doğrudan state mutasyonu yaptığı anda, yeniden üretemediğiniz bug'larınız var demektir. Kullanıcı verisini tutan global bir `static var`'ınız varsa, gelecekte bir güvenlik incelemesi sizi bekliyor demektir.
3. Hata Sınırları ve Zarif Bozulma
Kıdemli bir mühendis önce hata için tasarlar. Her ekran şu soruları yanıtlar:
- API çökerse ne olur?
- Kullanıcının interneti yoksa ne olur?
- JSON yapısı değişirse ne olur?
- Veri null gelirse ne olur?
Bu, her şeyi try-catch'e sarmakla ilgili değil. `loading`, `loaded`, `error` ve `empty` durumlarını içeren *state tipleri* tasarlamakla — ve her widget'ın bu dört durumu nasıl render edeceğini bilmesini sağlamakla ilgili. Söz veriyorum, bu herhangi bir obscure paketten çok daha değerli.
AI Destekli Flutter İçin "Önce Spec" Yaklaşımı
AI ajanlarının kısıt olmadan sürüklendiğini söylemiştim. Sürekli işe yaradığını gördüğüm çözüm **spec odaklı geliştirme**. Ajan kod yazmaya başlamadan önce spec'i yazın.
İşte iş akışı:
1. **Özellik için bir sayfalık Mimari Karar Kaydı (ADR) yazın.** 500 kelimenin altında tutun. Widget ağacı yapısını, state yönetimi bağlantı noktalarını ve veri kontratlarını ekleyin.
2. **Dosya sınırlarını tanımlayın.** Klasörleri adlandırın: `features/checkout/widgets/`, `features/checkout/logic/`, `features/checkout/data/`. Ajana açık dosya yolları verin.
3. **Ajana mimari kararları sormasını, vermemesini söyleyin.** Bu tek cümle, AI kaynaklı mimari kabuslarının %90'ını önler.
4. **Ajanın kodunu çalıştırmadan önce ADR'ye göre inceleyin.** Kod incelemesi hâlâ en iyi testiniz.
Bu bürokrasi değil. Bu, ajanın ürettiği 500 satırlık kodun doğru yere düşmesini sağlamak. Çünkü alternatif refactoring — ve AI üretimi kodu refactoring etmek, insan kodunu refactoring etmekten daha kötü. Çünkü hiç kimse o kodu *bir niyetle* yazmadı.
Senaryo İki: AI Yanıtlarını Stream Etmek (Evet, Bir AI Özelliği Geliştiriyorsunuz)
Bir AI chat özelliği geliştirdiğinizi düşünün. Ajan dakikalar içinde güzel animasyonlu bir streaming yanıt ekranı üretebilir. Ama geri çekilin ve sistem seviyesinde düşünün:
- Konuşma geçmişi nerede yaşıyor? Bellekte mi, yerel depolamada mı, sunucuda mı?
- HTTP stream'i yanıtın ortasında koparsa ne olur?
- Rate limiting'i nasıl yaparsınız ve 429'ları nasıl ele alırsınız?
- UI'da güvensiz veya halüsinasyon içerikli yanıtları nasıl ele alırsınız?
Kıdemli bir mühendis tek bir widget yazmadan önce streaming state'ini (`StreamBuilder`, buffer destekli state, retry mantığı) tasarlar. Ajan gerisini doldurabilir.
Senaryo Üç: Offline-First Yapılacaklar Uygulaması
Kullanıcıların uçakta görevlerini yönettiği bir uygulama oluşturun. Systems design sorusu şu: veri kaybetmemeye mi optimize ediyorsunuz, yoksa hıza mı?
`drift` tabanlı bir yerel veritabanı, REST API ile senkronize olan bir repository ve ağ durumunu takip eden bir connectivity provider ile tasarım temiz kalır. Ajan tesisatı yazar; kıdemli mühendis tesisatın *şeklini* tasarlar.
AI Neyi "Gereksiz" Kılıyor (Ve Neyi Kılmıyor)
AI'ın insan geliştiricilere olan ihtiyacı ortadan kaldıracağını iddia eden bir düşünce yazısı dalgası var. İyimser senaryo, yaratıcılara daha fazla özerklik vermesi. Kötümser senaryo ise özerkliğin gizlemeyi zorlaştırdığı boşlukları açığa çıkarması. Andy Budd bunu dijital tasarım için yazdı ve Flutter için de birebir doğru: AI kod yazmanın *sürtünmesini* kaldırır ama ne yazılacağını bilmenin *sorumluluğunu* kaldırmaz.
AI şunları yapabilir:
- Boilerplate widget kodunu sizin yazabileceğinizden daha hızlı üretmek
- Bir tasarım mock'unu saniyeler içinde widget ağacına çevirmek
- Repository'leriniz için unit test yazmak
AI şunları yapamaz:
- State'in nerede yaşayacağına karar vermek
- Cache tazeliği ile API maliyeti arasındaki trade-off'a karar vermek
- API yavaş olduğunda loading skeleton'un neye benzeyeceğine karar vermek
Bunlar tasarım kararlarıdır. Bunlar *sizin* işiniz ve on yıl sonra da işiniz olmaya devam edecek.
Bir Sonraki Flutter Systems Design'ınız İçin Hızlı Bir Kontrol Listesi
Birinden bir Flutter uygulaması tasarlamanız istendiğinde — bir mülakatta, bir tasarım dokümanında ya da sadece kafanızda — bu listeyi uygulayın:
1. **Fonksiyonel atomlar neler?** Uygulamayı özelliklere bölün. Her özellik bağımsız olarak geliştirilebilir, test edilebilir ve kaldırılabilir olmalı.
2. **State atomları neler?** Her özellik için şunları belirleyin: hangi state yerel, hangisi paylaşılan, hangisi kalıcı?
3. **Veri nasıl girer ve çıkar?** Her veri kaynağı bir repository alır. Her repository ham JSON değil, tipli nesneler döndürür.
4. **Bozulduğunda ne olur?** Her async çağrı için hata durumları. Her stream için loading durumları.
5. **Yeni bir geliştirici (veya bir AI ajanı) kodu nasıl bulur?** Klasör yapısı kendini anlatmalı.
Gerçekçi Olalım: "Yeterince İyi" İlkesi
Bu yazıyı bitirip her uygulamanın bir giriş butonu eklemeden önce altı katman soyutlamaya ihtiyacı olduğunu düşünmenizi istemiyorum. Systems design *orantı* ile ilgilidir.
İki ekranlı bir yardımcı uygulama Riverpod ve code generation istemez. Bir `StatefulWidget` ve bir repository yeterlidir. Bir e-ticaret uygulaması, ürün listesini render etmek için otuz provider istemez. Net sınırlar, bilinçli state sahipliği ve UI'a sızmayan bir veri katmanı ister.
İyi kıdemli mühendisler karmaşıklığı ne zaman *uygulamamak* gerektiğini bilir. AI ajanları bilmez — kırk satırlık bir özellik için mutlu mesut bir factory pattern üretirler. Sizin işiniz korkuluk olmak.
Son Düşünceler
AI çağında junior ve kıdemli Flutter mühendislerini ayıran şey şu: **junior'lar AI'a uygulamayı inşa ettirir, sonra bozulan şeyleri düzeltmeye çalışır. Kıdemliler uygulamanın sınırlarını tasarlar, sonra AI'ın o sınırların içinde inşa etmesine izin verir.**
Üç katmanlı zihniyeti benimseyin. Ajanları serbest bırakmadan önce kısa spec'ler yazın. Bilinçle inceleyin. Önce hata için tasarlayın. Ve unutmayın: sistem *ne inşa ettiğinizle* ilgilidir, onu yazan AI ile değil.
Çünkü kodu bir insan da yazsa bir dil modeli de yazsa, birinin state'in nerede yaşayacağına karar vermesi gerekiyor. O biri siz olmalısınız.
SSS
1. Flutter için gerçekten "systems design" gerekli mi? Bu backend işi değil mi?
Frontend systems design kesinlikle gerçek. State'in nerede yaşayacağına, verinin nasıl akacağına ve widget'lar, mantık ve veri katmanları arasındaki sınırların nereye çizileceğine karar vermekle ilgili. Backend tasarımı ölçekle ilgilenir; frontend tasarımı *karmaşıklıkla*. Sınırları olmayan, birbirine bağımlı elli widget'lık bir Flutter uygulaması, spaghetti servislerle dolu bir backend kadar zor bakım gerektirir.
2. Flutter mülakatında systems design'a nasıl yaklaşmalıyım?
İşleri ayırmaya odaklanın. Görüşmeciler widget ağacı decompozisyonu, state sahipliği (yerel vs. global), veri kontratları (repository ne döndürüyor?) ve hata yönetimi hakkında konuştuğunuzu duymak ister. Riverpod veya Bloc gibi araçlardan bahsetmek iyidir, ama *hangisini ne zaman kullanacağınızı* söylemek daha iyidir. Ve hemen koda koşmayın — önce trade-off'ları konuşun.
3. AI ajanlarının Flutter mimarimi sıfırdan tasarlamasına izin vermeli miyim?
Hayır. Ajanlar sınırlar içinde uygulama yapmakta harikadır, ama prompt muğlaksa bir widget'ın içine veritabanı çağrısını gönül rahatlığıyla koyarlar. Ajan başlamadan önce klasörleri, state yönetimi bağlantı noktalarını ve veri kontratlarını tanımlayan kısa bir spec — madde işaretleri bile olsa — yazın. Sonra çıktıyı spec'e göre inceleyin. Spec'iniz en önemli kontrol kolu.
4. Büyük Flutter uygulamaları için Riverpod mu Bloc mu daha iyi?
İkisi de production-ready. Bu bir teknoloji sorusundan çok felsefe sorusu. Riverpod derleme zamanı güvenliği, scope edilmiş provider'lar ve daha fonksiyonel bir tarz sunar. Bloc ise daha kolay dokümante edilen ama verbosity gerektiren katı bir event/state paterni dayatır. Büyük uygulamalar için ekibinizin rahatlığına göre seçim yapın ve tutarlı olun. Birini tutarlı uygulamak, projenin ortasında değiştirmekten iyidir. İki dokümantasyonu da okuyun — [riverpod.dev](https://riverpod.dev) ve [bloclibrary.dev](https://bloclibrary.dev) — ve ekibinizle birlikte karar verin.
تكنولوجيا
Yorumlar (0)
Henüz yorum yapılmamış. İlk yorumu siz yapın!
Yorum Yap