Organisasi program

Petunjuk / Saran

Baru mengembangkan perangkat lunak? Mulai dengan tutorial Memulai terlebih dahulu. Anda akan belajar tentang organisasi program secara alami saat proyek Anda tumbuh.

Berpengalaman dalam bahasa lain? Jika Anda terbiasa dengan solusi dan proyek di Visual Studio, atau sistem build seperti Maven atau Cargo, artikel ini memetakan konsep tersebut ke .NET.

Seiring berkembangnya aplikasi C#, Anda perlu mengatur kode. .NET menyediakan hierarki alat organisasi—solusi, proyek, rakitan, namespace, dan jenis—yang bekerja sama untuk menjaga basis kode besar tetap dapat dikelola. Konvensi yang dijelaskan di sini mewakili konensi yang luas di komunitas .NET. Anda mungkin menyimpang karena alasan tertentu, tetapi mengikuti konvensi ini membuat kode Anda akrab dan dapat dinavigasi ke pengembang .NET lainnya.

Hierarki organisasi

Atur aplikasi .NET yang khas dalam lapisan, dari yang terluas hingga yang paling spesifik:

Tingkat Deskripsi Example
Solusi Kontainer yang mengelompokkan proyek terkait. MyApp.slnx
Proyek Unit bangun yang menghasilkan satu rakitan. MyApp.Web.csproj
Perakitan Hasil kompilasi .dll atau .exe yang dihasilkan oleh proyek. MyApp.Web.dll
Namespace Pengelompokan tipe secara logis. MyApp.Web.Controllers
Jenis Kelas, struktur, antarmuka, enum, atau delegasi. OrderController

Setiap tingkat melayani tujuan yang berbeda. Solusi mengatur alur kerja pengembangan Anda. Proyek menentukan apa yang akan dikompilasi bersama-sama, dan setiap proyek menghasilkan satu rakitan. Rakitan adalah unit penyebaran dan penerapan versi. Ruang nama mencegah tabrakan nama dan memudahkan pencarian jenis. Satu rakitan dapat berisi beberapa namespace, dan satu namespace dapat mencakup beberapa rakitan. Jenis menentukan perilaku dan data aktual.

Proyek dan perakitan

Setiap proyek dikompilasi ke dalam satu rakitan: pustaka kelas atau dapat dieksekusi. Mulailah dengan satu proyek untuk aplikasi kecil—jangan pisahkan secara prematur. Alasan utama untuk membuat proyek terpisah adalah untuk menggunakan kembali kode tersebut di lebih dari satu aplikasi. Di luar penggunaan kembali, tambahkan proyek saat Anda memiliki alasan konkret:

  • Bagikan kode di berbagai aplikasi — ekstrak logika bersama ke dalam perpustakaan kelas yang dirujuk oleh beberapa aplikasi.
  • Masalah terpisah - menjaga akses data, logika bisnis, dan lapisan presentasi Anda tetap independen.
  • Dependensi kontrol — proyek hanya dapat menggunakan jenis dari proyek yang dirujuknya secara eksplisit.

Satu proyek berfungsi dengan baik untuk banyak aplikasi. Tahan keinginan untuk membuat proyek terpisah "berjaga-jaga." Anda selalu dapat mengekstrak pustaka nanti ketika aplikasi kedua membutuhkan kode yang sama.

Mencocokkan namespace dengan struktur folder

Nama namespace harus mengikuti struktur folder proyek Anda. Saat Anda melihat namespace MyApp.Services.Payments, Anda tahu untuk mencari folder Services/Payments untuk kode sumber dari tipe yang didefinisikan dalam namespace tersebut. .NET SDK mendukung konvensi ini, dan diikuti secara luas sehingga melanggarnya secara aktif membingungkan pengembang lain:

// 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}";
}

Namespace root Anda secara otomatis ditetapkan menjadi nama file proyek Anda. Jenis dalam subfolder tidak secara otomatis mendapatkan sub-namespace—Anda harus mendeklarasikan namespace secara eksplisit di setiap file—tetapi selalu pastikan mereka tetap sinkron.

Petunjuk / Saran

Anda dapat mengubah namespace root dengan mengatur <RootNamespace> dalam file proyek Anda.

<Project Sdk="Microsoft.NET.Sdk">
 <PropertyGroup>
   <RootNamespace>MyCompany.MyApp</RootNamespace>
 </PropertyGroup>
</Project>

Menata namespace menurut fitur, bukan berdasarkan jenis jenis

Kelompokkan jenis terkait ke dalam namespace menurut fitur atau tanggung jawab. Tempatkan antarmuka, implementasinya, dan jenis pendukungnya bersama-sama:

// 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);

Organisasi berbasis fitur menyimpan semua yang Anda butuhkan di satu tempat, membuat kode lebih mudah dinavigasi dan alasannya.

Pengubah akses dan rakitan

Pengubah akses bekerja dengan proyek dan struktur perakitan untuk mengontrol aksesibilitas:

Default ke internal untuk jenis yang tidak diperlukan proyek lain. Praktik ini menyembunyikan detail implementasi dan memberi Anda kebebasan untuk merefaktor tanpa mengganggu pengguna. Sangat penting untuk pustaka bersama:

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);
}
  • Penamaan namespace secara konsisten. Gunakan CompanyName.ProductName.Feature sebagai pola penamaan Anda. Misalnya, gunakan Contoso.Inventory.Shipping. Penamaan yang konsisten membantu pengembang menemukan jenis tanpa mencari.
  • Jaga agar proyek tetap fokus. Setiap proyek harus memiliki tanggung jawab tunggal yang jelas. Ketika proyek menangani terlampau banyak aspek yang tidak terkait, bagilah.
  • Gunakan namespace cakupan file. Sintaks namespace MyApp.Services; mengurangi indentasi dan merupakan gaya yang direkomendasikan. Gunakan ini dalam semua kode baru.
  • Tetapkan ke internal. Hanya tandai tipe public ketika assembly lain benar-benar membutuhkannya. Anda selalu dapat memperluas akses nanti; membatasinya adalah perubahan yang mengganggu kompatibilitas.