Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Návod
Začínáte s vývojem softwaru? Začněte nejprve kurzy Začínáme . S tím, jak vaše projekty rostou, se dozvíte o organizaci programů přirozeně.
Máte zkušenosti v jiném jazyce? Pokud jste obeznámeni s řešeními a projekty v sadě Visual Studio nebo buildovacími systémy, jako je Maven nebo Cargo, tento článek tyto koncepty mapuje na .NET.
S rostoucím růstem aplikace jazyka C# je potřeba kód uspořádat. .NET poskytuje hierarchii organizačních nástrojů – řešení, projektů, sestavení, oborů názvů a typů – které spolupracují, aby bylo možné spravovat velké základy kódu. Zde popsané konvence představují široký konsensus v komunitě .NET. Můžete se odhodovat z konkrétních důvodů, ale následující konvence váš kód zpřístupňuje a umožňuje navigaci ostatním vývojářům .NET.
Organizační hierarchie
Uspořádejte typickou aplikaci .NET ve vrstvách od nejširšího po nejvýraznější:
| Úroveň | Description | Příklad |
|---|---|---|
| Řešení | Kontejner, který seskupuje související projekty. | MyApp.slnx |
| Projekt | Modul, který vytváří jednu sestavu. | MyApp.Web.csproj |
| Sestavení | Soubor .dll nebo .exe, který je zkompilován projektem. |
MyApp.Web.dll |
| Namespace | Logické seskupení typů. | MyApp.Web.Controllers |
| Type | Třída, struktura, rozhraní, výčet nebo delegát. | OrderController |
Každá úroveň slouží k jinému účelu. Řešení uspořádají pracovní postup vývoje. Projekty definují, co se zkompiluje dohromady, a každý projekt vytvoří jedno sestavení. Sestavení jsou jednotkou nasazení a správy verzí. Jmenné prostory zabraňují kolizím názvů a usnadňují nalezení typů. Jedno sestavení může obsahovat více oborů názvů a jeden obor názvů může zahrnovat více sestavení. Typy definují skutečné chování a data.
Projekty a sestavy
Každý projekt se zkompiluje do jednoho sestavení: knihovny tříd nebo spustitelného souboru. Začněte jedním projektem pro malé aplikace – nerozdělujte se předčasně. Primárním důvodem vytvoření samostatného projektu je opakované použití tohoto kódu ve více než jedné aplikaci. Kromě opakovaného použití přidejte projekty, pokud máte konkrétní důvod:
- Sdílení kódu mezi aplikacemi – extrakce sdílené logiky do knihovny tříd, na kterou odkazuje více aplikací
- Oddělte zájmy – mějte nezávislé vrstvy přístupu k datům, obchodní logiky a prezentace.
- Řídit závislosti – projekt může používat pouze typy z projektů, na které explicitně odkazuje.
Jeden projekt funguje dobře pro mnoho aplikací. Odolávejte nutkání vytvářet separátní projekty "pro jistotu". Knihovnu můžete později kdykoli vytáhnout, pokud ji druhá aplikace bude potřebovat.
Přiřaďte jmenné prostory ke struktuře složek
Názvy jmenových prostor by měly odpovídat uspořádání složek projektu. Když vidíte obor názvů MyApp.Services.Payments, víte, že se máte podívat ve složce Services/Payments na zdrojový kód typů definovaných v tomto oboru názvů. Sada .NET SDK tuto konvenci podporuje a je tak široce následována, že její porušení aktivně mate ostatní vývojáře:
// File: Services/OrderService.cs
// Namespace mirrors the folder path
using MyApp.Core;
namespace MyApp.Services;
public class OrderService
{
public Order CreateOrder(string product, int quantity, decimal price) =>
new() { ProductName = product, Quantity = quantity, UnitPrice = price };
public string FormatSummary(Order order) =>
$"{order.Quantity}x {order.ProductName} = {order.Total:C}";
}
Kořenový obor názvů se automaticky nastaví podle názvu souboru projektu. Typy v podsložkách automaticky nezískají dílčí obory názvů – v každém souboru deklarujete obor názvů explicitně, ale vždy je budete synchronizovat.
Návod
Kořenový obor názvů můžete změnit nastavením <RootNamespace> v souboru projektu.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<RootNamespace>MyCompany.MyApp</RootNamespace>
</PropertyGroup>
</Project>
Uspořádejte jmenné prostory podle funkcí, nikoli podle typu.
Seskupte související typy do oborů názvů podle funkce nebo odpovědnosti. Umístěte rozhraní, jeho implementace a podpůrné typy dohromady:
// Good: group by feature
namespace MyApp.Payments;
public interface IPaymentProcessor
{
bool ProcessPayment(decimal amount);
}
public class CreditCardProcessor : IPaymentProcessor
{
public bool ProcessPayment(decimal amount)
{
Console.WriteLine($"Processing credit card payment of {amount:C}");
return true;
}
}
public record PaymentResult(bool Success, string? TransactionId);
Organizace založená na funkcích udržuje vše, co potřebujete, na jednom místě a usnadňuje navigaci v kódu a pochopení jeho struktury.
Modifikátory přístupu a sestavení
Modifikátory přístupu pracují se strukturou projektu a sestavení pro řízení přístupnosti:
-
public— přístupné z jakéhokoli sestavení, které odkazuje na toto sestavení. -
internal— přístupné pouze ve stejném sestavení (výchozí hodnota pro typy nejvyšší úrovně). -
private,protected,private protectedprotected internal— přístupné na základě typu, sestavení nebo odvozených typů.
Výchozí hodnota internal je pro typy, které ostatní projekty nepotřebují. Tento postup skryje podrobnosti implementace a dává vám svobodu k refaktorování bez přerušení uživatelů. Je to zvlášť důležité pro sdílené knihovny:
namespace MyApp.Inventory;
// Public — other projects can use this type
public class InventoryService
{
public int GetStockLevel(string productName) =>
StockDatabase.Lookup(productName);
}
// Internal — only visible within this assembly
internal static class StockDatabase
{
private static readonly Dictionary<string, int> _stock = new()
{
["Widget"] = 42,
["Gadget"] = 17
};
internal static int Lookup(string productName) =>
_stock.GetValueOrDefault(productName);
}
Doporučené postupy
- Pojmenovávejte jmenné prostory konzistentně. Použijte
CompanyName.ProductName.Featurejako vzor pojmenování. Například použijteContoso.Inventory.Shipping. Konzistentní pojmenování pomáhá vývojářům najít typy bez hledání. - Zaměřte se na projekty. Každý projekt by měl mít jednu jasnou odpovědnost. Pokud projekt zpracovává příliš mnoho nesouvisejících problémů, rozdělte ho.
- Použijte obory názvů omezené na soubor. Syntaxe
namespace MyApp.Services;zmenšuje odsazení a je doporučeným stylem. Použijte ho ve všech nových kódech. - Výchozí je
internal. Označujte typypublicpouze v případě, že je ostatní sestavení skutečně potřebují. Přístup můžete kdykoli později rozšířit; jeho zúžení však představuje zásadní změnu.