archlint: mimari sınırları CI'da deterministik olarak zorlamak
Mimari kararlar wiki'de doğru kalır, kodda çürür. archlint, architecture.json'daki sınırları her commit'te go/parser ile, modelsiz zorluyor.
Mimari kararların neden çürüdüğünü ayrı yazdım: bir ADR “domain altyapıyı import etmesin” der, iki yıl sonra bir bakarsın yüzlerce yerde import etmiş — çünkü kuralı izleyen hiçbir şey yoktu. Bu yazı o sorunun araç tarafı: küçük, bağımsız bir Go CLI — archlint.
architecture.json: kuralı koda yaz
Katmanları ve aralarındaki izinli bağımlılıkları tek bir dosyada beyan ediyorsun:
{
"module": "github.com/acme/app",
"layers": {
"domain": ["internal/domain"],
"db": ["internal/db"],
"http": ["internal/http"]
},
"rules": {
"domain": [],
"db": ["domain"],
"http": ["domain", "db"]
}
}
domain içeride hiçbir şey import edemez, db yalnızca domain’i, http ikisini de. Başka her iç kenar bir ihlal. Aynı-katman import’u her zaman serbest; [] “hiçbir katmanı import edemez” demek.
Nasıl çalışıyor
archlint check, her Go, TypeScript ve Python dosyasının import’larını çıkarıyor. Go import’ları stdlib’in go/parser’ıyla okunuyor — regex tahmini değil, derlemeye gerek yok, kesin. Her dosyayı ve her import’u (modül yolunu sıyırıp) bir katmana çözüyor; kuralı çiğneyen kenarı dosya:satır ile raporluyor:
$ archlint check examples/sample
Scanned examples/sample against examples/sample/architecture.json — 2 layer(s).
1 boundary violation(s):
internal/domain/bad.go:6 domain → db is not allowed (import "github.com/acme/app/internal/db")
İhlal varsa exit 1 → CI kırmızı. Çiğneyen import main’e ulaşmadan yakalanıyor; iki yıl sonra bir arkeoloji seansında değil.
Tasarım kararları
- Deterministik, modelsiz. Bütün amaç CI’da kapı kurabileceğin bir guardrail: aynı diff, aynı verdict, döngüde model yok. Bir LLM’e “mimariyi gözden geçir” demekten farkı bu.
- Sıfır bağımlılık (Go stdlib). Config şimdilik JSON — YAML bir bağımlılık ekliyor, o yüzden follow-up.
- Go kesin, TypeScript ve Python en iyi çaba.
go/parserGo import’larını kesin veriyor. TypeScript/JavaScript ve Python import’ları, standart biçimleri kapsayan regex tarayıcılarıyla çıkarılıyor; yani tam birer parser değiller.
CI’da
Buradan sonrası, GitHub Actions ile kurduğum akışların alışılmış iki satırı; archlint’in tek beklentisi, ihlalde sıfırdan farklı bir kod dönerek job’ı düşürebilmek.
- run: go install github.com/muhammetsafak/archlint/cmd/archlint@latest
- run: archlint check
Ya da paketlenmiş GitHub Action ile:
- uses: muhammetsafak/archlint@v0.3.0
Sınırlar — dürüst liste
- TS/JS ve Python için regex tarayıcıları. Go import’ları
go/parserile okunuyor (kesin). TS/JS ve Python import’ları regex tarayıcılarından geliyor; bu yüzden yorum ya da string literal içindeki import benzeri bir metin yanlış pozitife yol açabilir. - Statik import grafiği.
checkkatmanlar arası bağımlılık grafiğini yönetir;archlint metrics(v0.3.0’da eklendi) aynı grafik üzerinde bağımlılık (coupling), bounded context ve Conway sinyalleri ekler. “Senkron olması gereken yerde async çağrı” ya da domain sınırını aşan doğrudan bir DB sorgusu, runtime trace’leri ilişkilendirmeyi gerektirir — sonraki faz. - JSON config (YAML follow-up). Deterministik tasarım kasıtlı: gate’lenebilir olsun diye.
Denemek için
architecture.json’unu yaz, archlint check çalıştır — ya da archlint check examples/sample ile kasıtlı bir ihlalin yakalandığını gör. Hangi sınırı bir sonraki sürümde görmek istediğini yazarsan, sıraya koyarım.
Bu konudaki deneyler
Uygulama ile sağlayıcı arasında duran, tek OpenAI uyumlu API sunan ve isteğe RAG bağlamını kendisi ekleyen self-hosted Go gateway.
Şu an ne yapıyor
Uygulamanın tek bir OpenAI uyumlu uca konuşmasını, isteğin hangi modele gideceğini ve — bir doküman havuzu bağlıysa — hangi dokümanlardan bağlam alacağını projenin ayarının belirlemesini sağlıyor. Sağlayıcı anahtarını uygulamalara dağıtmak istemeyen ve harcamayı proje başına sınırlamak isteyen herkes kendi sunucusunda çalıştırabilir.
Dile özgü serileştirme yerine dondurulmuş bir JSON zarfı; polyglot kuyruk standardı BabelQueue'ya dönüştü.
Şu an ne yapıyor
Dondurulmuş JSON zarfı dört dilde — PHP, Python, Go, Node.js — aynı baytları okutuyor; sidecar ya da broker eklentisi gerekmiyor. Polyglot kuyruk kuran ekipler spesifikasyonu ve SDK'ları bugün kullanabilir.
Yorumlar
Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.