🔥 Zapisy zamknięte, ale możesz pobrać Roadmapę .NET i dołączyć do listy oczekujących — Pobierz i dołącz do Listy VIP →

Łamane zasady czystego kodu w C# — 10 przykładów

Najczęściej łamane zasady czystego kodu w C# — grafika

1. Powielanie (duplication)

Ten sam kod występuje więcej niż raz. Jeśli nie jest to zamierzone, powinien zostać przeniesiony do oddzielnej metody lub klasy — zgodnie z zasadą “nie powtarzaj się” (DRY).

// ❌ ta sama walidacja powielona w dwóch miejscach
if (string.IsNullOrEmpty(imie) || imie.Length > 50) throw new ArgumentException();
// ... gdzie indziej w kodzie:
if (string.IsNullOrEmpty(nazwisko) || nazwisko.Length > 50) throw new ArgumentException();

// ✅ jedna metoda, wywoływana z obu miejsc
static void WalidujTekst(string wartosc)
{
    if (string.IsNullOrEmpty(wartosc) || wartosc.Length > 50) throw new ArgumentException();
}

2. Zbyt duże klasy i metody

Klasy i metody powinny mieć “tylko jeden powód do zmiany”, zgodnie z zasadą pojedynczej odpowiedzialności (SRP). Typowe sygnały: za dużo linii kodu, zbyt wiele zależności w konstruktorze, kod dotyczący różnych, niepowiązanych przypadków użycia w jednej klasie.

// ❌ jedna klasa robi walidację, zapis do bazy i wysyłkę e-maila
public class ZamowienieService
{
    public void ZlozZamowienie(Zamowienie z)
    {
        if (z.Suma <= 0) throw new ArgumentException();
        using var conn = new SqlConnection("...");
        conn.Execute("INSERT INTO Zamowienia ...");
        new SmtpClient().Send("potwierdzenie@firma.pl", z.Email, "Zamówienie", "...");
    }
}

// ✅ trzy klasy, każda z jednym powodem do zmiany
public class WalidatorZamowienia { public void Waliduj(Zamowienie z) { /* ... */ } }
public class ZamowieniaRepository { public void Zapisz(Zamowienie z) { /* ... */ } }
public class PowiadomieniaService { public void WyslijPotwierdzenie(Zamowienie z) { /* ... */ } }

3. Niewykorzystany kod

Powstaje na dwa sposoby: kod stał się nieaktualny po refaktoryzacji/zmianie wymagań, albo ktoś dodał funkcjonalność “na zapas”, która nie jest jeszcze potrzebna. W obu przypadkach nieużywany kod dodaje niepotrzebnej złożoności — to dokładnie przypadek, przed którym ostrzega zasada YAGNI (“You Aren’t Gonna Need It”).

// ❌ parametr i gałąź kodu, których nikt jeszcze nie używa "na przyszłość"
public decimal ObliczCene(Produkt p, bool czyPrzyszlaPromocjaSwiateczna = false)
{
    if (czyPrzyszlaPromocjaSwiateczna) { /* funkcja jeszcze nieużywana nigdzie w kodzie */ }
    return p.Cena;
}

// ✅ dodaj tę logikę, gdy faktycznie będzie potrzebna, nie wcześniej
public decimal ObliczCene(Produkt p) => p.Cena;

4. Magiczne stringi i liczby

Kod z bezsensownymi literałami, takimi jak client == 1 albo customer.Type = "AD", jest trudny do odczytania, utrzymania i refaktoryzacji. Wyliczenia (enum) i stałe dają czytelność i sprawdzanie poprawności w czasie kompilacji.

// ❌ magiczne wartości — co znaczy "1"? co znaczy "AD"?
if (client == 1) { }
if (customer.Type == "AD") { }

// ✅ nazwane, sprawdzane przez kompilator
enum TypKlienta { Standardowy = 1, Administracyjny }
if (client == TypKlienta.Standardowy) { }
if (customer.Type == TypKlienta.Administracyjny) { }

5. Za dużo instrukcji warunkowych

Gdy logika biznesowa jest skomplikowana, łatwo o głęboko zagnieżdżone if/else, trudne do przeczytania i zrozumienia. Często da się to rozwiązać zasadą Open/Closed i wzorcem Strategy.

// ❌ każdy nowy typ rabatu to kolejna gałąź if/else
decimal ObliczRabat(string typKlienta, decimal suma)
{
    if (typKlienta == "VIP") return suma * 0.2m;
    else if (typKlienta == "Stały") return suma * 0.1m;
    else return 0;
}

// ✅ nowy typ rabatu = nowa klasa, zero zmian w istniejącym kodzie
interface IStrategiaRabatu { decimal Oblicz(decimal suma); }
class RabatVip : IStrategiaRabatu { public decimal Oblicz(decimal suma) => suma * 0.2m; }
class RabatStaly : IStrategiaRabatu { public decimal Oblicz(decimal suma) => suma * 0.1m; }

6. Brak hermetyzacji

To najczęściej łamana zasada czystego kodu — spotykana niemal w każdym kodzie. Każda klasa jest publiczna, z publicznymi właściwościami i publicznymi metodami, tylko dlatego, że IDE domyślnie dodaje słowo kluczowe public. To nie jest programowanie obiektowe — obiekty powinny ukrywać swoje wewnętrzności.

// ❌ pełna ekspozycja stanu — każdy może ustawić dowolną, nawet niepoprawną wartość
public class KontoBankowe
{
    public decimal Saldo; // dowolny kod może zrobić: konto.Saldo = -1000000;
}

// ✅ stan chroniony, zmieniany tylko przez kontrolowane metody
public class KontoBankowe
{
    public decimal Saldo { get; private set; }
    public void Wplac(decimal kwota) { if (kwota > 0) Saldo += kwota; }
}

7. Niechlujne formatowanie

Nie wpływa na wykonanie kodu, ale wpływa na czytelność — a to problem, nawet jeśli wydaje się drobny. Formatowanie w profesjonalnym kodzie to standard, nie opcja, tak samo jak w dobrze wydanej książce.

// ❌ brak spójnego wcięcia i formatowania
public class Foo{public int X;public void Bar(){if(X>0){Console.WriteLine("x");}}}

// ✅ EditorConfig + formatter (Ctrl+K, Ctrl+D w Visual Studio) wymuszają jeden standard
public class Foo
{
    public int X;

    public void Bar()
    {
        if (X > 0)
        {
            Console.WriteLine("x");
        }
    }
}

8. Za dużo komentarzy

Komentarze tłumaczące oczywisty kod nie są potrzebne — kod mówi sam za siebie, a kontrola źródła (Git) i tak zapamięta historię zmian. Komentarze mają sens tylko w dwóch przypadkach: dokumentowanie publicznego API i wyjaśnienie nietypowego obejścia (hacka), którego nie da się inaczej wytłumaczyć.

// ❌ komentarz powtarza to, co kod już mówi
// sprawdź czy wiek jest większy niż 18
if (wiek > 18) { }

// ✅ zamiast komentarza — nazwa, która mówi to samo bez tłumaczenia
bool czyPelnoletni = wiek > 18;
if (czyPelnoletni) { }

Technika refaktoryzacji nazywana Extract Method (wydzielenie fragmentu kodu do osobnej, dobrze nazwanej metody) zwykle zastępuje potrzebę komentarza lepiej niż sam komentarz.

9. Złe i niespójne nazewnictwo

Nazewnictwo jest często pomijane, szczególnie przez mniej doświadczonych programistów — a nie powinno tak być. Dobre nazewnictwo bywa trudne, ale bezpośrednio wpływa na poprawność i łatwość utrzymania kodu.

// ❌ nic nie mówiące nazwy
var d = DateTime.Now;
var lst = GetData();
void Proc(int x) { }

// ✅ nazwa mówi, czym coś jest i po co istnieje
var dataZlozeniaZamowienia = DateTime.Now;
var aktywniKlienci = GetAktywnychKlientow();
void ObliczRabat(int liczbaZamowien) { }

10. Zła obsługa wyjątków

Zawsze łap najbardziej specyficzny wyjątek (np. DivideByZeroException, nie ogólny Exception). Uważaj też na ponowne rzucanie wyjątku — throw ex; niszczy oryginalny stack trace, podczas gdy throw; go zachowuje.

// ❌ złapanie wszystkiego + throw ex niszczy informację, gdzie faktycznie wystąpił błąd
try { return 10 / dzielnik; }
catch (Exception ex) { throw ex; }

// ✅ konkretny wyjątek + throw (bez ex) zachowuje oryginalny stack trace
try { return 10 / dzielnik; }
catch (DivideByZeroException) { throw; }

Podsumowanie

Dziesięć wzorców, które najczęściej psują czystość kodu, ma jedną wspólną cechę: każdy da się wykryć bez uruchamiania programu, samym czytaniem kodu. Duplikacja, magiczne wartości, brak hermetyzacji i złe nazewnictwo to najtańsze do naprawienia problemy — bo nie wymagają zmiany logiki biznesowej, tylko sposobu, w jaki ta logika jest zapisana. Warto je eliminować na bieżąco, zanim skumulują się w kod, którego nikt już nie chce dotykać.

Powiązane: te same błędy w praktyce rekrutacyjnej: 5 rzeczy, które zdradzają juniora w code review.

👨‍💻
Mariusz Jurczenko
Senior .NET Developer · 10+ lat doświadczenia komercyjnego

Programista .NET z doświadczeniem komercyjnym w firmach takich jak NFZ, Kamsoft, Diagnostyka, Hermes Reply Polska czy Etisoft Smart Solutions. Twórca kursów, z których skorzystało już ponad 11 000 osób w Strefie Kursów i ponad 1 000 kursantów na dev-hobby.pl.

Specjalizacja: Clean Code, Clean Architecture i uczenie programowania tak, żeby dało się je naprawdę zrozumieć — nie wykuć.

🚀 Co dalej?

Zobacz to w praktyce na wideo i pobierz darmową roadmapę, żeby ułożyć naukę w spójną ścieżkę do pierwszej pracy.

8 comments

Dodaj komentarz

czytanie to początek

Zamień wiedzę w umiejętności

Pobierz darmową Roadmapę .NET i ułóż takie tematy jak ten w spójną ścieżkę do pierwszej pracy.

Pobieram roadmapę →