Yirmi projeyi tek başına yönetmek: ağaç mı, grup mu, etiket mi?
Kişisel projelerim ona yaklaşırken bir şey fark ettim: bazıları açıkça aynı aileden. Bir ürün, onun lisans sunucusu ve satış sitesi; ya da aynı oyun motorunu kullanan iki oyun. Klasör listesi bunu anlatmıyor. İlk refleks "ana proje, altında alt projeler" demek oluyor. Bu yazıda o refleksi neden frenlediğimi ve yerine ne kurduğumu anlatıyorum.
Bağlam önemli: tek geliştiriciyim, her proje ayrı bir git deposu ve büyük ölçüde AI ajanlarıyla çalışıyorum. Ajanların bir işe başlarken okuduğu her dosya token demek; bu yüzden "gruplama" kararı aynı zamanda bir bağlam maliyeti kararı.
Seçenekler
1. Hiyerarşik alt proje (ağaç). Proje, projeleri içerir. Sezgisel görünür ama iki sorunu var. Birincisi, ağaç yalnız "içerme"yi anlatır: iki oyunun paylaştığı motorun tek ebeveyni olamaz, ya kopyalarsınız ya yanlış yere koyarsınız. İkincisi, miras zinciri uzar: kural ve ajan tanımları "kütüphane → üst proje → alt proje" yolunu izler, kararların hangi seviyede yazılacağı belirsizleşir. GitLab'ın alt grup belgeleri bile teknik sınır yirmi seviye olsa da performans için beş ya da daha az öneriyor.
2. Denk projeler + grup. Projeler düz, grup adlandırılmış bir küme. Linear'ın "initiative" kavramı projelerin üstünde durur ve birden çok proje içerir; Azure DevOps ise yüzlerce uygulama için bile tek proje ve alan yolları önerir. Ortak ders: kap hiyerarşisi sığ, gruplama çapraz ve düz.
3. Etiketler. Her projeye n etiket, gruplama filtreyle türetilir. Sıfır göç maliyeti. Zaafı, üç yıl sonra kendi etiketlerinizi yabancı bulmanız; folksonomilerin bilinen sorunu. Nx bu sorunu kontrollü etiket ile çözer: scope: ve type: gibi ön ekler ve bunlara bağlı bağımlılık kısıtları.
4. Workspace manifestleri. Cargo, pnpm, Turborepo, Bazel: hepsinde tek kök, düz üye listesi ve üyeler arası açık bağımlılık çizgesi var. Turborepo yuvalanmış paketleri açıkça desteklemez. Derleme dünyasının ortak paydası hiyerarşi değil, bağımlılık çizgesi.
5. Backstage ve C4. Backstage'de Component → System → Domain zinciri var; System başka bir System'e ait olamaz, Domain ise "sınırlı bağlam" olarak tanımlanır. C4'te System → Container → Component → Code. İkisinin ortak dersi: platform varyantı (iOS, web, masaüstü) bir Container'dır, ayrı bir sistem değil.
Karar için iki kavram
Seçeneklere bakarken iki düşünce çerçevesi işimi çok kolaylaştırdı.
Conway yasası. Sistem tasarımı, kuruluşun iletişim yapısını yansıtır. Benim "kuruluşum" bir insan ve proje başına kurulmuş ajan ekipleri. Ajanlar projenin dışına yazamıyor; iletişim yapısı zaten proje sınırında kesiliyor. O hâlde bir parçayı ayrı proje yapmanın anlamlı ölçütü şu: ayrı bir ekip ve ayrı yaşam döngüsü gerektiriyor mu? Lisans sunucusu gerektirir (güvenlik kuralları, sır yönetimi, dağıtım farklı). Aynı kod tabanından çıkan iOS derlemesi gerektirmez.
Sınırlı bağlam (DDD). Her projenin kendi bilgi modeli ve sözlüğü var; bağlamlar arası ilişki bir "context map" ile çizilir. Grup, aynı sözlüğü paylaşan bağlamların ailesi; bağ ise context map'in kendisi. Grup içinde bile bağlam ayrı kalır: uygulamadaki "lisans" ile sunucudaki "lisans" aynı kelime, farklı model olabilir.
Kurduğum model
Karma bir model, ama hangi kavramın hangi işi üstlendiği sabit:
- Proje = bir depo, bir sınırlı bağlam, bir ajan ekibi. Denk; hiçbiri diğerinin altında değil.
- Grup = tek seviyeli, yuvalanmayan küme; her projenin en çok bir grubu var. Yalnız kenar çubuğu başlığı, toplu görünüm ve birkaç ortak varsayılan için. Kural, ajan ya da karar mirası taşımaz.
- Bağ = projeler arası yönlü ilişki:
uses,consumes,variant_of,deploys_with. Her proje yalnız kendi çıkan bağlarını kendi dosyasında tutar. Etki analizi ve ajan bağlam paketi bu çizgeden beslenir. - Etiket = serbest yön, ama ön ekli:
platform:,tech:,market:. Ayrı bir etiket yönetim ekranı yok; otomatik tamamlama ve bir doğrulama uyarısı yetiyor. - Platform varyantı aynı kod tabanındaysa proje içinde kalır; ayrı kod tabanıysa aynı grupta ayrı proje olur ve
variant_ofbağıyla asıla bağlanır.
Toplam derinlik: kök → grup → proje → proje içi parçalar. Daha derini yok.
"Aynı proje mi, ayrı proje mi?" sorusuna da üç ölçütlü bir kural yazdım. Şunlardan biri evetse ayrı proje: ayrı kod tabanı; ayrı dağıtım ve yaşam döngüsü (kendi sürümü, kendi sırları); ayrı risk profili (ödeme, lisans gibi). Hiçbiri evet değilse proje içi varyant.
Neden ağaç değil, bir kez daha
Ağacın en büyük maliyeti ilk gün görünmüyor. "Nereye koyayım?" kararı her yeni projede tekrarlanıyor ve yanlış yerleştirmeyi taşımak pahalı. Ajanlar için de kötü: üst projenin kurallarını da okumak zorunda kalıyorlar. Grup + bağ modelinde ise alanlar isteğe bağlı; eski dosyalar değişmeden çalışıyor, klasör taşınmıyor, geri dönüş neredeyse bedava.
Sektördeki karşılığı da bu: GitLab ağaç + etiket, Linear takım ağacı + çapraz inisiyatif, Nx düz üye + kontrollü etiket + bağımlılık çizgesi. Herkes karma kullanıyor; fark, rolleri sabitlemekte.
Yapmayacaklarım
- Alt proje, proje içinde proje.
- Yuvalanmış grup ya da çoklu grup üyeliği (çoklu aidiyet etiketin ve bağın işi).
- Grup düzeyinde ajan, kural, karar klasörü.
- Monorepo zorlaması; her proje ayrı depo kalıyor, ilişki bilgisi çizgede yaşıyor.
Kaynaklar
- Backstage — System Model
- C4 model — Abstractions
- GitLab — Subgroups
- Linear — Conceptual model
- Microsoft Learn — About projects in Azure DevOps
- Nx — Enforce module boundaries
- Turborepo — Structuring a repository
- Cargo — Workspaces
- Martin Fowler — Conway's Law
- Martin Fowler — Bounded Context
- Team Topologies — Key concepts