From f4f3b3896a002e4e9e93b89dadca8457b92b5d7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ty=C5=84ski?= Date: Sun, 4 Oct 2026 03:49:39 +0200 Subject: [PATCH] docs(backend): document C# conventions in AGENTS.md Add C# language conventions: one type per file, file-scoped namespaces, sealed/internal types, DTO as records, ban on object-valued dictionaries with the enforcing test, layering, naming and formatting rules. --- backend/AGENTS.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/backend/AGENTS.md b/backend/AGENTS.md index 76b2742..0570eab 100644 --- a/backend/AGENTS.md +++ b/backend/AGENTS.md @@ -1,6 +1,6 @@ -# AGENTS.md — Standardy warstwy Controller +# AGENTS.md — Założenia i standardy backendu (C#) -Dotyczy projektu `backend` (ASP.NET Core Web API, .NET 10). +Dotyczy projektu `backend` oraz testów `tests/TarninaHub.Tests` (ASP.NET Core Web API, .NET 10). ## Komunikaty commitów @@ -8,6 +8,19 @@ Dotyczy projektu `backend` (ASP.NET Core Web API, .NET 10). - Zasada obowiązuje **w obu projektach**: repozytorium `DevHeyah` oraz `20_projects/TarninaHub`. - Stosujemy konwencję Conventional Commits (typ: `feat`, `fix`, `docs`, `chore` itd.). +## Założenia języka C# + +- **Platforma:** .NET 10 (`net10.0`), `Nullable enable`, `ImplicitUsings enable`. Nie wyłączaj nullowalności; unikaj operatora `!` (jeśli musisz — uzasadnij). +- **Jeden typ = jeden plik:** każdy typ najwyższego poziomu (klasa, `record`, interfejs, `enum`, `struct`) w osobnym pliku, nazwa pliku zgodna z nazwą typu. Nie zagnieżdżaj typów pomocniczych poza przypadkami prywatnych szczegółów implementacji. +- **Przestrzeń nazw:** wyłącznie file-scoped (`namespace X;`). Kolejność: `using` → `namespace` → typy. Grupuj `using` bez zbędnych duplikatów. +- **Typy:** klasy usług i kontrolerów oznaczaj `sealed`; modele wierszy i typy wewnętrzne jako `internal`. DTO to `public sealed record` (niemutowalne, pozycyjne). +- **Zakaz map z wartościami `object`:** w DTO, interfejsach, `Domain` i modelach `*Row` nie stosuj `Dictionary` ani `IReadOnlyDictionary`. Elastyczne dane (`content`, `payload`, `contact`, `media`, `attachments`) to mapy wartości tekstowych (`IReadOnlyDictionary`), materializowane do konkretnych `Dictionary` przed przekazaniem do `RawQuery`. Powód: błąd deserializacji CBOR (Dahomey) i nieobsługiwana serializacja typów interfejsowych. Egzekwuje test `NoObjectValuedDictionariesTests`. +- **Wzorce:** promuj `record`, pattern matching, wyrażenia (`=>`), kolekcje `[]`; unikaj `null`-owych kolekcji (inicjalizuj puste). +- **Warstwy:** `Domain` (reguły, enumy), `Application` (DTO, abstrakcje, mapowania), `Infrastructure` (persistence, integracje), `Controllers` (tylko HTTP). Zależności kieruj do wewnątrz (Infrastructure → Application → Domain). +- **Nazewnictwo:** typy/metody/właściwości `PascalCase`, parametry i zmienne lokalne `camelCase`, pola prywatne `_camelCase`, interfejsy `I...`, typy generyczne `T...`. Metody asynchroniczne z sufiksem `Async`. +- **Formatowanie:** zgodnie z `.editorconfig` (C#: 4 spacje, LF, final newline, bez trailing whitespace). Weryfikacja: `dotnet format whitespace --verify-no-changes TarninaHub.slnx` i `dotnet format style --verify-no-changes --severity warn TarninaHub.slnx`. +- **Zmienne:** preferuj `var`, gdy typ jest oczywisty; jawne typy przy niejasności. + ## Język nazewnictwa - Wszystkie nazwy zmiennych, parametrów, pól, metod, klas i plików są **wyłącznie w języku angielskim**.