TGViewer
C# (C Sharp) programming C# (C Sharp) programming @csharp_ci · 18.1K subscribers
Post #1833 3.87K
Clean Code: сложный `if` лучше превратить в понятное правило

Такой код приходится расшифровывать каждый раз:


if (invoice is not null &&
invoice.Status == InvoiceStatus.Unpaid &&
invoice.DueDateUtc < DateTime.UtcNow &&
invoice.Balance > 0 &&
!invoice.SilenceWarnings &&
invoice.Customer.Email is not null)
{
SendOverdueWarning(invoice);
}


Условие растёт, бизнес-правило теряется среди технических деталей, а изменение одного требования превращается в рискованный рефакторинг.

Вынесем правило в метод с говорящим именем:


if (invoice.ShouldSendOverdueWarning(nowUtc))
{
SendOverdueWarning(invoice);
}


Само правило:


public bool ShouldSendOverdueWarning(DateTime nowUtc)
{
return Status == InvoiceStatus.Unpaid
&& DueDateUtc < nowUtc
&& Balance > 0
&& !SilenceWarnings
&& Customer.Email is not null;
}


Теперь вызывающий код отвечает на вопрос что происходит, а метод хранит детали когда это разрешено.

### Почему исходный вариант плохо тестируется

Он напрямую использует DateTime.UtcNow. Результат зависит от реального времени, поэтому тест может вести себя по-разному в разные моменты.

После передачи времени параметром тест становится предсказуемым:


[Fact]
public void Sends_warning_for_overdue_unpaid_invoice()
{
var invoice = new Invoice
{
Status = InvoiceStatus.Unpaid,
DueDateUtc = new DateTime(2026, 7, 20),
Balance = 1500,
SilenceWarnings = false,
Customer = new Customer { Email = "user@example.com" }
};

var nowUtc = new DateTime(2026, 7, 28);

Assert.True(invoice.ShouldSendOverdueWarning(nowUtc));
}


Для больших проектов вместо DateTime можно внедрить TimeProvider. Главное правило: время, сеть, файловая система и случайность не должны быть скрыты внутри бизнес-логики.
More from @csharp_ci
  1. Sep 21, 2026Awesome Jev - большая подборка инструментов для новой модели TypeSafe AI 🤗 Jev - новая бы…
  2. Sep 21, 2026🔍Тестовое собеседование с Senior C# разработчиком уже завтра 22 сентября(уже завтра!) в 1…
  3. Sep 20, 2026🧩 Задача на C#: почему воркер завис, хотя очередь почти пустая? Есть канал вместимостью о…
  4. Sep 18, 2026Post #1882
  5. Sep 17, 2026🔥 Microsoft выпустила .NET 11 RC1**- первый релиз-кандидат уже с **go-live support, то ес…
  6. Sep 15, 2026photo post
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →