İçeriğe geç
Muhammet Şafak
en
Günlük 2 dk okuma

archlint: mimari sınırları CI'da deterministik olarak zorlamak

Mimari kararlar wiki'de doğru kalır, kodda çürür. archlint'i yazdım: architecture.json'daki katman+kural sınırlarını her commit'te go/parser ile, modelsiz, CI'da zorlayan bağımsız bir Go CLI. Niye böyle kurduğumu anlatıyorum.


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 dosyasının import’larını stdlib’in go/parser’ıyla çıkarıyor — 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.
  • Önce Go. go/parser Go import’larını kusursuz veriyor; keskin bir MVP tek dilde iyi yapılır. TypeScript ve Python, kendi parser’larıyla sıradaki adım.

CI’da

- run: go install github.com/muhammetsafak/archlint/cmd/archlint@latest
- run: archlint check

Ya da paketlenmiş GitHub Action ile:

- uses: muhammetsafak/archlint@v0.1.0

Sınırlar — dürüst liste

  • Go, şimdilik. Import’lar go/parser ile okunuyor (kesin); TS/Python kendi parser’larıyla sıradaki adım.
  • Import sınırları, şimdilik. Katmanlar arası bağımlılık grafiğini yönetir. “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 (TS? Python?) görmek istediğini yazarsan, sıraya koyarım.

Paylaş:

Yorumlar

Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.

İlgili Yazılar

Sitede Ara

Yazı, proje ve sayfalarda arama yapmak için yazmaya başlayın.

Esc ile kapat Pagefind ile güçlendirildi