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

Tek mimari kuralı, üç dil: archlint artık Go + TypeScript + Python

Polyglot bir repoda 'domain altyapıyı import etmesin' kuralı her dilde aynı; değişen, import'un nasıl çözüldüğü. archlint'e TypeScript ve Python ekledim — tek architecture.json üç dilin sınırlarını CI'da zorluyor.


archlint’i ilk yazdığımda sadece Go biliyordu. Ama tipik bir sistem tek dil değil: Go API, TypeScript frontend, Python worker’ları. Üçünde de aynı mimari niyet var — “domain katmanı altyapıyı import etmesin” — ama o kuralı üç dilde birden zorlayan tek bir araç yoktu. Şimdi archlint üçünü de yönetiyor, tek bir architecture.json ile.

Sınır dile bağlı değil; sözdizimi bağlı

Katman düzeyinde kural her dilde aynıdır: domain → db yasak. Diller arasında değişen şey kuralın kendisi değil, import’un nasıl yazıldığı ve hangi dosyaya çözüldüğü:

  • Go: mutlak paket yolu — github.com/acme/app/internal/db. Çözüm: modül-prefix’ini sıyır → internal/db.
  • TypeScript: göreli (../db/repo) ya da alias (@/db/repo). Çözüm: göreliyi dosyanın konumuna, alias’ı tsconfig yoluna göre çöz.
  • Python: noktalı + göreli — from ..db.repo import find_order. Çözüm: göreli noktaları dosyanın paketine göre yukarı çık, sonra modülü yola çevir.

archlint hepsini tek bir şeye indirger: repo-göreli bir yol → bir katman. O noktadan sonra motor aynı: “bu dosya hangi katmanda, bu import hangi katmana gidiyor, kural izin veriyor mu?”

Tek config, karışık repo

İşin güzel yanı: aynı dosya üç dilli bir monorepo’yu birden yönetebiliyor. Katman adları ortak, yollar dile özel:

{
  "module": "github.com/acme/app",
  "aliases": { "@/": "web/src/" },
  "layers": {
    "domain": ["internal/domain", "web/src/domain", "workers/app/domain"],
    "infra":  ["internal/infra", "web/src/infra", "workers/app/infra"]
  },
  "rules": { "domain": [], "infra": ["domain"] }
}

domain katmanı üç serviste de var (Go internal/, TS web/src/, Python workers/app/) ve hiçbirinde altyapıyı import edemez. Tek kural, üç dil, tek CI kapısı.

Nasıl çalışıyor: dil-eklenebilir mimari

İçeride bir Language arayüzü var: her dil yalnızca iki şeyi bilir — bir dosyanın import’larını çıkarmak ve bir import’u repo-göreli yola çözmek. Linter’ın geri kalanı dil-agnostik. Yeni bir dil eklemek = yeni bir Language implementasyonu.

Disiplin aynen korundu: tree-sitter (CGo, ağır bağımlılık) yerine, Go’yu stdlib go/parser ile (kesin), TS ve Python’ı regex tarayıcılarla okuyorum. Dürüst sınır: bunlar tam parser değil — yorum ya da string içindeki import-benzeri bir satır false-positive olabilir. README’de açıkça yazıyor.

Denemek için: üç örnek

Her biri kasıtlı bir ihlal içeriyor:

archlint check examples/sample      # Go     → internal/domain/bad.go
archlint check examples/ts-sample   # TS     → src/domain/bad.ts   ("@/" alias çözülür)
archlint check examples/py-sample   # Python → app/domain/bad.py   ("..db.repo" çözülür)

Üçü de aynı çıktıyı verir: domain → db is not allowed, exit 1, CI kırmızı.


Bunun neden bir wiki sayfasından daha iyi olduğunu sade.dev’de ayrı yazdım: yazılı bir mimari karar, onu her commit’te kontrol eden bir şey olmadan çürür. Şimdi o “şey” üç dilde birden çalışıyor. Sıradaki sınır hangi dil olsun istersen — yaz, sıraya koyayı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