Чи потрібно все-таки використовувати Debug.Assert сьогодні?


23

Нещодавно я натрапив на якийсь нещодавно написаний код, який перемішувався з великою кількістю Debug.Assert (C #).

Чи повинні ми все ще широко використовувати це, незважаючи на використання TDD, BDD та Unit Testing в цілому?


9
Я не бачу, як одне виключає інше.
superM

2
@superM Я, безумовно, бачив, як ліниві розробники додавали тести як твердження раніше, оскільки вони написали свій код таким чином, що важко було знущатися із залежностей. Само собою, я б не рекомендував цього
jk.

Відповіді:


23

Я не бачу жодної причини, чому ви не повинні використовувати Assert. Тим самим ви вже визнали потребу в охоронцях, як-от передумови та інваріанти, і робите рух у напрямку проектування за контрактом . Затвердження - це лише один із способів досягнення цього ...

// Precondition using Asert
void SomeMethod(Foo someParameter)
{
    Debug.Assert(someParameter != null)
}

// Precondition using If-Then-Throw
void SomeMethod(Foo someParameter)
{
    if (someParameter == null)
        throw new ArgumentNullException("someParameter");
}

// Precondition using Code Contracts
void SomeMethod(Foo someParameter)
{
    Contract.Requires(someParameter != null);
}

// Precondition using some custom library
void SomeMethod(Foo someParameter)
{
    Require.ArgumentNotNull(() => someParameter);
}

Усі способи досягнення одного і того ж: надійність у коді. Це просто зводиться до вибору варіанту, з яких Assert є правильним вибором.

Зауважте, що я досі не згадував одиничні тести, оскільки вони виконують щось зовсім інше. Тест одиниці формально доводить надійність коду, здійснюючи охорону:

[Test]
void SomeMethod_WhenGivenNull_ThrowsArgumentNullException()
{
    delegate call = () => someObject.SomeMethod(null);

    Assert.That(call).Throws<ArgumentNullException>();
}

Це зовсім інший вид твердження ...

** Зауважте, що в деяких рамках фактично досить складно провести тест на збій твердження, оскільки помилка твердження може знизити весь час виконання, тому один із інших варіантів може бути кращим ... *


10

Я вважаю, що твердження та одиничні тести є двома різними інструментами в моїй панелі інструментів. Деякі речі краще підходять одній, а деякі - іншим.

Як приклад, сьогодні я здебільшого використовую твердження для перевірки параметрів для непублічних методів.


5

Я розглядаю Debug.Assert як передчасну оптимізацію в наш час. Якщо вам дійсно не потрібна продуктивність, придушення Assert в режимі випуску може приховувати помилки довше.

Як зазначає MattDavey, кодові контракти можуть бути вищими, забезпечуючи статичну перевірку замість динамічної перевірки, і якщо такої немає, я б вважав за краще Trace.Assert або звичайний старийif(x) throw SomeException;


4
Варто зазначити, що генерування коду з Visual Studio у режимі випуску призведе до того, що всі виклики методів Debugкласу можуть бути пропущені з компіляції ... тому придушення викликів Assertпросто для продуктивності - це не просто передчасна оптимізація, це проста дурниця.
Конаміман

@Konamiman у цьому суть, я майже завжди хочу, щоб це не вийшло так само у режимі випуску:. Debug.Assert не приносить мені користі 97% часу
jk.

Що це за 3%, @jk? Лише застарілий код чи якийсь інший примірник?
DougM

Критичний код продуктивності @DougM, його посилання на цитату knuth. Я також додам, що я думаю, що сердечна помилка демонструє, що мій погляд є правильним, якщо у вас немає іншого вибору, не знімайте перевірки передумов у коді випуску
jk.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.