sozsoft-platform/.github/instructions/dotnet.instructions.md
2026-08-21 22:27:59 +03:00

6.7 KiB
Raw Blame History

.NET / ABP Kod Standardı

Bu doküman api/ altındaki tüm projeler için bağlayıcıdır. Platform davranışına dair kurallar için ai.instructions.md esastır; çelişki olursa o dosya kazanır.

Standart derlemede zorlanır: api/Directory.Build.props analizörleri açar, api/.editorconfig kural şiddetlerini tanımlar. Bu iki dosya standardın tek kaynağıdır; proje dosyalarında tekrar edilmez.

1. Hedef sürümler

Katman Sürüm Nerede tanımlı
SDK .NET 10 (10.0.300) api/global.json
TargetFramework net10.0 proje dosyaları
Dil C# 14 (LangVersion=latest) api/common.props
ABP 10.0.0 Volo.Abp.* paket referansları

Sürüm yükseltmesi tek noktadan yapılır: global.json + common.props + paket sürümleri. Proje dosyalarına TFM/LangVersion tekrar yazılmaz.

2. Nullable

Directory.Build.props içinde çözüm geneli Nullable ayarı yapılmaz. Sebebi EF Core: kolonun zorunlu olup olmadığını, entity assembly'sinin nullable annotation bağlamından türetir. Global bir enable/annotations anahtarı, bir sonraki dotnet ef migrations add çağrısında tüm string özelliklerini sessizce NOT NULL kolona çevirir — seeder'ın doldurmadığı her alan da o anda kırılır.

Kural:

  • Nullable, proje bazında ve bilinçli olarak açılır (<Nullable>enable</Nullable>). Şu an açık olanlar: Sozsoft.Platform.Application, Sozsoft.Notifications.*, test projeleri.
  • Entity taşıyan projelerde (*.Domain) nullable açılacaksa, aynı PR'da dotnet ef migrations add çıktısı gözden geçirilir; şema değişikliği isteniyorsa kabul edilir, istenmiyorsa kolon zorunluluğu PlatformDbContext içinde .IsRequired(false) ile açıkça sabitlenir.
  • Kolon zorunluluğu tercihen NRT'ye değil, PlatformDbContext yapılandırmasına yazılır; böylece derleyici anahtarından bağımsız olur.

3. Ölü kod politikası

Aşağıdaki kurallar ihlal edilmiş kod merge edilmez:

Kural Anlamı
IDE0005 Kullanılmayan using
IDE0051 Çağrılmayan private üye
IDE0052 Yazılıp hiç okunmayan private alan (kullanılmayan enjekte bağımlılık)
IDE0059 Gereksiz değer ataması
IDE0161 namespace X; (file-scoped)

Tarama ve otomatik düzeltme (kalıcı yapılandırma gerektirmez):

# Rapor
dotnet build api/Sozsoft.Platform.sln --no-incremental \
  -p:EnforceCodeStyleInBuild=true -p:GenerateDocumentationFile=true

# Düzeltme
dotnet format api/Sozsoft.Platform.sln --diagnostics IDE0005,IDE0161 --severity warn

Kurallar .editorconfig'te warning seviyesindedir ve EnforceCodeStyleInBuildık olduğu için normal dotnet build de bunları raporlar.

IDE0052 düzeltilirken alan ile birlikte constructor parametresi de silinir; yoksa DI hâlâ gereksiz servisi çözer.

CS0162 (erişilemez kod) Directory.Build.props içinde gerekçesiyle susturulmuştur: veritabanı sağlayıcısı derleme zamanı sabiti olduğu için diğer sağlayıcının dalları erişilemez görünür. Bu durum dışında erişilemez kod bırakılmaz.

Ek kurallar:

  • Bir tip/dosya silinmeden önce repo genelinde (api + ui + configs) referans taraması yapılır. DI ile çözülen tipler (AppService, Manager, Provider, Repository, Seeder, Localizer, Notification sağlayıcıları) düz metin aramasında "referanssız" görünür — bunlar yalnızca modül/DI kaydı incelendikten sonra silinir.
  • Yorum satırına alınmış kod bloğu bırakılmaz; ihtiyaç varsa git geçmişinden alınır.
  • "İleride lazım olur" gerekçesiyle kullanılmayan DTO/Input/Consts tutulmaz.
  • Migrations/ ve *.g.cs üretilmiş koddur, bu kuralların dışındadır.

4. Modern C# kullanımı (yeni kod)

  • File-scoped namespace: namespace Sozsoft.Platform.ListForms;
  • Primary constructor: public class XAppService(IRepository<X, Guid> repo) : PlatformAppService — parametre doğrudan kullanılır, private readonly ... = param; şeklinde tekrar tanımlanmaz.
  • Koleksiyon ifadeleri ([], [.. items]), is not null, switch ifadesi, desen eşleme, Index/Range, hedefi belli new().
  • out var, tuple deconstruction; kullanılmayan çıktı için _.
  • async metotlar Async ile biter ve Task/Task<T> döner; async void yasak. ABP'de ConfigureAwait kullanılmaz.
  • Biçim: api/.editorconfig geçerlidir (4 boşluk girinti, using blokları namespace dışında ve System önce, dosya sonunda satır sonu, UTF-8 BOM).

5. ABP kuralları

  • Katman sınırı: Domain.Shared → Domain → Application.Contracts → Application → HttpApi → HttpApi.Host. Ters yönde referans verilmez; EntityFrameworkCore yalnızca Domain'e bakar.
  • AppService: PlatformAppService'ten türer, arayüzü Application.Contracts'ta tanımlanır. Controller yazılmaz — ABP otomatik API üretir. Controller sadece ABP konvansiyonunun karşılamadığı durumda (dosya indirme, harici webhook) eklenir.
  • Yetki: her AppService/metot [Authorize(PlatformConsts.AppCodes....)] ile korunur; izin adları PermissionDefinitionProvider içinde tanımlanır. Yetki kontrolü koda gömülmez, izin adı sabitten okunur.
  • Tenant izolasyonu: sorgular ICurrentTenant bağlamında çalışır; IMultiTenant entity'lerde manuel TenantId filtresi yazılmaz, veri filtreleri devre dışı bırakılacaksa (ICurrentTenant.Change, IDataFilter) gerekçe yorumla yazılır.
  • Repository: özel sorgu gerekiyorsa Domain'de arayüz + EntityFrameworkCore'da implementasyon. AppService içinde DbContext doğrudan kullanılmaz.
  • Dinamik SQL: parametreli çalıştırılır; string birleştirme ile sorgu kurulmaz.
  • Mapping: Mapperly ([Mapper] partial class) kullanılır; AutoMapper eklenmez. RMG012 uyarısı "hedefte karşılığı olmayan alan" demektir; yeni mapper eklerken bu uyarı bırakılmaz.
  • Localization: kullanıcıya görünen metin koda gömülmez, PlatformResource anahtarı üzerinden verilir.
  • Sabitler: bağlantı dizesi, tenant id, anahtar/secret koda yazılmaz; konfigürasyon veya SettingDefinition üzerinden okunur.

6. Değişiklik öncesi kontrol listesi

dotnet build api/Sozsoft.Platform.sln --no-incremental \
  -p:EnforceCodeStyleInBuild=true -p:GenerateDocumentationFile=true   # 0 hata, yeni IDE00xx yok
dotnet format api/Sozsoft.Platform.sln --verify-no-changes --diagnostics IDE0005,IDE0161 --severity warn
dotnet test  api/test/Sozsoft.Platform.EntityFrameworkCore.Tests

Not: EntityFrameworkCore testleri şu an SQLite şema oluşturmada (nvarchar(max)SQLite Error 1) kırık; bu kırıklık bu standarttan önce de vardı ve ayrı bir iş olarak ele alınmalıdır.