Fluent API w C#

Fluent API w C# – jak uprościć kod i poprawić czytelność

Fluent API w C# – jak uprościć kod i poprawić czytelność

Masz kod w C#, w którym wielokrotnie wywołujesz te same metody na tej samej instancji?
Powtarzalność rośnie, czytelność spada, a refaktoryzacja zaczyna boleć.

W tym artykule pokażę Ci, jak wykorzystać Fluent API w C#, aby uprościć kod, poprawić jego czytelność i pisać bardziej „płynne” API dokładnie tak, jak robi to LINQ.


🧱 Problem: powtarzalny kod i niska czytelność

Załóżmy prosty model domenowy:

public class Customer
{
    public int Id { get; }

    public string Name { get; }

    public Customer(int id, string name)
    {
        Id = id;
        Name = name;
    }

    public override string ToString() => $"Customer Id={Id} Name={Name}";
}

public class Sale
{
    public Customer Customer { get; }

    public decimal Value { get; }

    public Sale(Customer customer, decimal amount)
    {
        Customer = customer;
        Value = amount;
    }
}

public class SalesList
{
    private List<Sale> _sales = new();

    public IEnumerable<Sale> EnumerateItems()
    {
        foreach (var item in _sales)
            yield return item;
    }

    public void AddSale(Sale item)
    {
        _sales.Add(item);
    }
}

❌ Użycie (problem)

Customer marcin = new(1, "Marcin");
Customer iga = new(2, "Iga");
Customer tomek = new(3, "Tomek");
Customer ala = new(4, "Ala");

SalesList sales = new();
sales.AddSale(new(tomek, 600));
sales.AddSale(new(marcin, 500));
sales.AddSale(new(ala, 200));
sales.AddSale(new(iga, 700));
sales.AddSale(new(marcin, 1000))
sales.AddSale(new(iga, 600))
sales.AddSale(new(ala, 400))
sales.AddSale(new(tomek, 100));

👉 Ten kod działa, ale:

  • powtarzasz referencję sales
  • trudniej zobaczyć „flow”
  • rośnie szum przy większej liczbie operacji

Rozwiązanie: Fluent API w C#

🔧 Kluczowa zmiana

Zmieniamy jedną rzecz: zamiast void, zwracamy this.

public class SalesList
{
    private List<Sale> _sales = new();

    public IEnumerable<Sale> EnumerateItems()
    {
        foreach (var item in _sales)
            yield return item;
    }

    public SalesList AddSale(Sale item)
    {
        _sales.Add(item);
        return this;  // 🔥 klucz do fluent API
    }
}

✅ Użycie (Fluent Code)

SalesList sales = new();
sales.AddSale(new(tomek, 600))
     .AddSale(new(marcin, 500))
     .AddSale(new(ala, 200))
     .AddSale(new(iga, 700))
     .AddSale(new(marcin, 1000))
     .AddSale(new(iga, 600))
     .AddSale(new(ala, 400))
     .AddSale(new(tomek, 100));

👉 Efekt:

  • mniej powtórzeń
  • lepsza czytelność
  • naturalny „flow” operacji

🔍 Dlaczego to działa?

Mechanizm jest prosty:

return this;

Zwracasz tę samą instancję → możesz wywołać kolejną metodę.

To dokładnie ten sam pattern, który znasz z LINQ:

var result = sales.EnumerateItems()
    .Where(s => s.Value > 500)
    .OrderBy(s => s.Customer.Name);

⚖️ Fluent API a wydajność

✅ W tym przypadku

  • brak nowych alokacji
  • zwracana referencja (this)
  • koszt ≈ 0

❗ Kiedy pojawia się problem

Jeśli API:

  • tworzy nowe obiekty (immutable)
  • robi kopie kolekcji
  • ukrywa kosztowne operacje

Przykład (niebezpieczny):

public SalesList AddSale(Sale item)
{
    return new SalesList(_sales.Append(item).ToList()); // ❌ alokacje
}

🧠 Best Practices (production)

✅ Kiedy używać Fluent API

  • masz sekwencję operacji
  • operujesz na tym samym obiekcie
  • chcesz poprawić czytelność

❌ Kiedy unikać

  • pojedyncze operacje
  • API z ukrytymi side-effectami
  • bardzo długie chainy (10+ metod)

🧱 Fluent API w kontekście architektury (Clean Architecture)

Fluent API to sposób użycia, nie warstwa.

Najczęściej stosuj:

  • ✔ Domain (jeśli operacje są biznesowe)
  • ✔ Application (workflow / use-case)
  • ✔ Builder pattern (np. konfiguracja)

Unikaj:

  • ❌ Infrastructure (jeśli zaciemnia IO)
  • ❌ public API bez jasnych kontraktów

⚠️ Najczęstsze błędy

  • 🔴 ukrywanie mutacji (brak jasności)
  • 🔴 mieszanie sync + async w chainie
  • 🔴 brak walidacji w metodach
  • 🔴 zbyt „magiczne” API

🧪 Checklist – czy warto użyć Fluent API?

Zadaj sobie pytania:

  • Czy mam kilka operacji na jednym obiekcie?
  • Czy mogę poprawić czytelność?
  • Czy unikam ukrytych kosztów?
  • Czy API będzie przewidywalne?

👉 Jeśli większość = TAK → Fluent API ma sens


Zobacz także — powiązane artykuły

👉 MCP w .NET (C#) – jak zbudować serwer AI krok po kroku

👉 Tworzenie klas i obiektów w C# — kompletny przewodnik

👉 Pattern Matching w C# – switch expressions i type patterns


📣 Call To Action

Jeśli ten materiał był pomocny:

👉 Zostaw komentarz – jak używasz Fluent API u siebie?
👉 subskrybuj nasz kanał na YT!
👉 udostępnij artykuł komuś, kto zaczyna z programowaniem


Szybkie podsumowanie

  • Fluent API = chaining metod (return this)
  • poprawia czytelność i redukuje powtarzalność
  • koszt = 0 (dla mutowalnych obiektów)
  • używaj świadomie (czytelność > „ładny kod”)

Dołącz do Listy VIP

I otrzymaj roadmapę Junior .NET Developer oraz najlepszą ofertę, gdy tylko ruszą zapisy!!!

Kontakt: mariuszjurczenko@dev-hobby.pl
Zero spamu. Możesz wypisać się w każdej chwili.

Dodaj komentarz