C# Web API – Kompletny przegląd strukturyzacji API zgodnie z podejściem Dereka Comartina
Przy rozpoczynaniu projektu C# Web API programiści często stają przed przytłaczającą liczbą wyborów dotyczących struktury kodu. Czy powinieneś podążać za wzorcem warstwowym ASP.NET Core Web API? Czy powinieneś trzymać się folderu kontrolerów z domyślnego szablonu w Visual Studio? A może powinieneś spróbować bardziej nowoczesnego stylu, jak Minimal APIs?
W swoim filmie "Utrzymuj prostą strukturę projektu!" Derek Comartin z CodeOpinion.com przyjmuje zdecydowane, ale odświeżająco praktyczne podejście. Przeprowadza on przez swoje pomysły dotyczące budowy i organizacji Web API w sposób, który działa w rzeczywistych systemach programistycznych, skupiając się na tym, co naprawdę się liczy: prostocie.
Ten artykuł podąża krok po kroku za filmem Dereka, aby pomóc ci zorganizować projekt ASP.NET Core Web API w sposób klarowny, łatwy do utrzymania i skalowalny w rzeczywistych warunkach.
Przegląd wspólnych struktur API
Derek zaczyna od pytania, które napotykają większość programistów podczas tworzenia nowego projektu Web API w Visual Studio:
"Jak powinieneś zorganizować swoje HTTP API?"
Natychmiast przyznaje, że projekty Web API mogą być organizowane na wiele sposobów. Wśród najczęstszych struktur folderów, które widzi Derek:
-
Grupowanie według kwestii technicznych - umieszczanie modeli w folderze Models, kontrolerów w folderze Controllers i usług w Services.
-
Używanie Clean Architecture lub Onion Architecture - gdzie projekty są podzielone na warstwy (API, Application, Domain, Infrastructure) w celu ukierunkowania zależności.
- Łączenie Domain-Driven Design (DDD) z architekturą wertykalnych przekrojów - grupując punkty końcowe według funkcjonalności, ale zachowując obiekty bogate w domenę.
Derek zaznacza, że każdy z tych wzorców może stworzyć RESTful API wykorzystujące oczekiwane metody HTTP (GET, POST, PUT, DELETE) do pracy z zasobami. Ale ostrzega przed nadmiernym interpretowaniem samej struktury folderów:
"Możesz zobaczyć encje, agregaty lub usługi domenowe, ale to nie oznacza, że kod naprawdę stosuje design oparty na domenie – tylko używa tych wzorców."
Rozpoczęcie od prostoty, nie od złożoności
Derek mówi, że jego cel jest prosty:
"Jedną z głównych rzeczy, które chciałem osiągnąć z tą strukturą, jest prostota."
Zamiast od razu sięgać po ciężką architekturę stylu .NET Framework lub kopiować wzorce z książek, Derek wybiera Minimal APIs w ASP.NET Core. Dłączego? Ponieważ umożliwiają one łatwe tworzenie API bez nadmiernego obciążenia kontrolerami i kodem szablonowym.
Kiedy tworzysz nowy projekt Web API w Visual Studio, a nawet Visual Studio Code, możesz zacząć od okna dialogowego Nowy Projekt i wybrać ASP.NET Core Web API. Domyślnie otrzymasz kontrolery, foldery i dużo skaffolding. Derek twierdzi, że zaczynanie od czegoś mniejszego – prostej, czystej struktury – jest często lepsze.
Podstawowa struktura Web API Dereka
Derek wprowadza swoją strukturę aplikacji webowej przy użyciu .NET Core. Jest ona zbudowana, aby wspierać popularne usługi HTTP i RESTful APIs, które umożliwiają komunikację pomiędzy różnymi aplikacjami programistycznymi.
Oto jak organizuje swój projekt Web API:
-
Plik Endpoints – Jeden plik, aby zobaczyć wszystkie dostępne trasy w API. Zamiast przekopywać się przez wiele kontrolerów, Derek chce szybki przegląd każdej metody GET, metody POST, żądania PUT czy żądania DELETE, które API wspiera.
-
Wspólny folder – Zawiera współdzielony kod, taki jak filtry i rozszerzenia używane w różnych systemach oprogramowania.
-
Feature Folders – Pojęcie wertykalnych przekrojów; każdy nowy zasób lub istniejący zasób otrzymuje swój własny folder. Na przykład, folder Postów może zawierać wszystko, co potrzebne do GET /posts/{id}, POST /posts, PUT /posts/{id} i DELETE /posts/{id}.
- Folder Danych – Zawiera model danych i mapowania encji. Tutaj można użyć Entity Framework Core do bezproblemowej integracji z bazą danych.
Dzięki grupowaniu punktów końcowych według funkcji, Derek unika rozpraszania logiki w wielu niepowiązanych folderach.
Dłączego nie wymusza Domain-Driven Design
Derek korzystał kiedyś z Domain-Driven Design, ale w tej strukturze C# Web API podejmuje kluczową decyzję:
"Nie będziemy korzystać z projektowania opartego na domenie."
Zamiast tego "pozwala danym być danymi". Jego modele danych są prostymi klasami z prostymi właściwościami, jak:
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
}
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
}
Nie ma tutaj niepotrzebnego zachowania. Gdy wysyłasz żądanie POST, aby utworzyć nowy zasób, API po prostu go zapisuje. Gdy wysyłasz żądanie DELETE z parametrem id, usuwa ten zasób.
To podejście obejmuje styl architektoniczny Representational State Transfer (REST) poprzez traktowanie punktów końcowych API jako czasowników (metoda GET, metoda POST, metoda PUT, metoda DELETE) działających na zasobach takich jak Post, User lub Comment.
Przeglądanie rozwiązania w Visual Studio
W tym momencie Derek otwiera swoje rozwiązanie Visual Studio i daje nam tournée:
-
Plik Endpoints wymienia każdą trasę - czy to żądanie GET pobierające dane, żądanie POST dodające nowy zasób, żądanie PUT aktualizujące dane, czy metoda DELETE usuwająca istniejący zasób.
-
Folder Danych zawiera mapowania dla encji takie jak Post, User i Comment - połączone z bazą danych poprzez Entity Framework.
-
Wspólny folder zawiera współdzieloną logikę dla usług HTTP, takich jak filtry walidacji i rozszerzenia.
- Każdy Folder Funkcji (Posty, Komentarze, Autoryzacja) zawiera cały kod potrzebny dla tego zasobu.
Ten czysty układ folderów projektu unika bałaganu z przekopywaniem się przez zbyt złożony dialog projektu czy rozproszony folder kontrolerów.
Rozłożenie punktu końcowego na części
Derek wyjaśnia, że każdy punkt końcowy w jego ASP.NET Core Web API to autonomiczna jednostka pracy z trzema wyraźnymi krokami:
-
Mapowanie – Definiuje metodę HTTP i trasę. Na przykład, żądanie DELETE może mapować DELETE /posts/{id} na metodę obsługującą.
-
Kontrakty żądania i odpowiedzi – Każdy punkt końcowy ma swoje własne ciało żądania i typ odpowiedzi. To sprawia, że usługi HTTP są bardziej przejrzyste i unika tworzenia warstw zduplikówanych DTO.
- Logika – Rzeczywista metoda obsługująca, w której API przeszukuje bazę danych, aktualizuje model danych lub zwraca kod statusu jak return CreatedAtAction lub return NoContent.
Ponieważ Derek korzysta z Minimal APIs, te obsługiwacze są metodami statycznymi. W ASP.NET Core oznacza to, że możesz wstrzykiwać zależności bezpośrednio - nie potrzeba tu nieporęcznej klasy kontrolera.
Dłączego Minimal APIs się sprawdzają
Derek chwali Minimal APIs za ich prostotę. Dzięki minimalistycznemu szablonowi ASP.NET Core możesz rozpocząć projekt web API zaledwie kilkoma liniami w Program.cs:
var app = WebApplication.CreateBuilder(args).Build();
var app = WebApplication.CreateBuilder(args).Build();
Od tego momentu dodajesz swoje metody GET, metody POST i żądania PUT w prosty sposób.
Ta prostota pomaga unikać nadmiernie rozbudowanych rozwiązań – coś, co Derek widzi zbyt często, gdy programiści ślepo kopiują szablony pakietów nuget lub wymuszają nowe klasy kontrolerów dla każdego drobnego punktu końcowego.
Jak złożoność może ewoluować z czasem
Derek podaje prawdziwy przykład: funkcja "polubić post".
-
Na początku jest to proste – sprawdź, czy istnieje polubienie, dodaj jedno, jeśli nie.
-
Ale później aplikacja programistyczna może wymagać natychmiastowego zwrócenia liczby polubień dla stron internetowych lub urządzeń mobilnych.
- Aby skalować, możesz zdenormalizować dane, dodając właściwość LikeCount do modelu danych Post.
To stwarza nowe wyzwania:
-
Każda metoda PUT lub metoda DELETE, która wpływa na polubienia, musi prawidłowo aktualizować licznik.
- Jeśli ktoś doda rekord polubień bez wywoływania API, licznik jest błędny.
Derek pokazuje, że gdy złożoność wzrasta, możesz dodać wzorce takie jak:
-
Wzorzec repozytorium do kapsułkowania dostępu do danych.
-
Korzenie agregatów do obsługi zachowań (takich jak inkrementacja LikeCount).
- Wzorzec Outbox do zapewnienia, że wydarzenia (takie jak "PostLiked") są opublikowane.
Ale jego kluczowy punkt jest jasny:
"Nie zaczynaj tutaj. Zacznij od prostoty i rozwijaj tylko wtedy, gdy to konieczne."
Zamknięcie z kluczowym przekazem Dereka
Derek kończy, wracając do swojej głównej lekcji dla programistów C# Web API:
"Zacznij od prostoty."
Gdy używasz ASP.NET Core Web API lub ASP.NET Web API w Visual Studio, łatwo jest od pierwszego dnia przesadzić – dodając każdy folder, wzorzec i pakiet NuGet, jaki kiedykolwiek widziałeś.
Ale Derek ostrzega: nie stosuj rozwiązań bez refleksji. Zrozum metody HTTP, których potrzebujesz, dane, z którymi pracujesz, i systemy oprogramowania, między którymi umożliwiasz komunikację. Buduj swoje RESTful API krok po kroku.
Dla tych, którzy używają Visual Studio Code lub jakiegokolwiek innego zintegrowanego środowiska programistycznego, jego rada jest prawdziwa: Niezależnie od tego, czy to nowy projekt, czy istniejący zasób, utrzymuj strukturę projektu tak prostą, jak to możliwe, i dodawaj wzorce tylko wtedy, gdy rzeczywista złożoność tego wymaga.
Wnioski
Jeśli chcesz zobaczyć to podejście w akcji i usłyszeć perspektywę Dereka z pierwszej ręki, jego wideo jest doskonałym zasobem. Jego kanał jest pełen równie wnikliwych dyskusji na temat systemów oprogramowania, usług sieciowych i rozwoju w ASP.NET Core — nieodzowny dla każdego dewelopera, który chce poprawić swoje umiejętności i utrzymywać swoje projekty w czystości, praktyczności i rozwojowości.
