Надежная структура кода?

Я ненавижу писать код, который делает мою программу более надежной. Это то, что должен был сделать фреймворк! Итак, кто-нибудь знает об утилите, «улучшающей» код, которая укрепляет код?

Если бы мне пришлось создать что-то подобное самому, это работало бы следующим образом: когда вы компилируете свой код с флагом отладки, он автоматически волшебным образом добавлял бы «затвердевающий» код для каждого метода:

Деформируйте код с помощью try-catch и поместите Debug.Assert(true) в catch (чтобы исключения перехватывались в их источнике).

Регистрируйте запись каждого метода, печатая значения аргументов «ToString()», чтобы я мог отслеживать, что происходит.

Проверяйте каждый аргумент на null.

Используйте структуру «IsValid» для проверки самого объекта и каждого аргумента, где IsValid() — это способ объекта объявить, что его ожидания верны (например, если я TableOfContentsEntry, я ожидаю, что всегда буду в книге, которая является действительной () и указать на страницу, которая является IsValid().

Так почему бы не?


person Avi    schedule 13.01.2010    source источник
comment
Также хотелось бы услышать больше предложений о том, что должна содержать такая структура. Основное внимание уделяется C#, и, очевидно, это дополнение к правилам статической проверки кода.   -  person Avi    schedule 13.01.2010


Ответы (4)


Если вы хотите регистрировать вызовы методов, вы можете использовать структуру АОП, например PostSharp. Такие вещи, как принудительное выполнение предварительных/постусловий метода, лучше всего выполнять с помощью механизмов проектирования по контракту, таких как новый Code Contracts, которая будет поставляться с .net4.0. Конечно, нет смысла просто проверять аргументы на наличие null, поскольку это может быть допустимым значением в зависимости от метода. Внедрение Debug.Asserts в код может быть проблематичным, поскольку вы можете не захотеть/не иметь возможности обрабатывать исключения в исходной функции. Я думаю, что было бы непрактично, если вообще возможно, создать общую структуру для такого рода вещей, поскольку требования будут сильно различаться между проектами.

РЕДАКТИРОВАТЬ: Чтобы уточнить мой комментарий о добавлении отладочных утверждений в методы, я прочитал ваше предложение о преобразовании тела метода во что-то вроде этого:

public void SomeMethod(args)
{
    try
    {
        //original method body
    }
    catch(Exception ex)
    {
        Debug.Assert(false);
        throw;
    }
}

Проблема в том, что Asserts указывает на вещи, которые никогда не должны быть ложными, поэтому эта конструкция означает, что метод никогда не может выдать что-то, что в общем случае неверно. Теперь проблема заключается в том, что если метод вызывает исключение, утверждение завершится ошибкой, даже если вызывающий метод обработает исключение надлежащим образом. Из вашего комментария кажется, что вы делаете что-то вроде этого:

public void SomeMethod(object arg)
{
    Debug.Assert(arg != null);
    if(arg == null) throw new ArgumentNullException("arg");

    //rest of method
}

Это полезная практика, и я считаю, что библиотека кодовых контрактов поддерживает «устаревшую» проверку предварительных условий (создание исключений) в своем статическом анализе.

person Lee    schedule 19.01.2010
comment
Спасибо - отличные ссылки, посмотрю на них. ИМХО Debug.Assert не вызывает исключения и обеспечивает важное преимущество остановки выполнения вблизи точки, где обнаружена проблема. Проблема в том, что он умирает во время выполнения, и если возникает ошибка, он остается без обработки. Итак, что я начал делать: #region ArgCheck bool badCond=(theArgument == null) //например, Debug.Assert(!badCond); if(badCond) генерировать новое исключение ArgumentNullException(); #endregion ArgCheck Решение бедного программиста. Но меня раздражает, что пошаговое выполнение этого кода расширяет регион. - person Avi; 20.01.2010

Приятно видеть, что мою книгу подключают! Для меня большая проблема заключается в том, что я считаю, что генерация кода должна быть направлена ​​«рядом» с кодом разработчика, т.е. в идеале сгенерированный код не будет смешиваться с кодом разработчика. Интересно, есть ли способ добавить этот «твердый» код в качестве частичного класса или в качестве прокси, который будет устанавливаться между классом и вызывающим его клиентом? Конечно, вполне возможно сгенерировать код и вставить его в код разработчика, но вы хотели бы создать какое-то соглашение, чтобы, когда разработчик вносит изменения и регенерирует «закрепляющий» код, инструмент мог удалить старый код и генерировать новый код на основе последней версии кода разработчика.

person Peter Vogel    schedule 19.01.2010

Мне бы хотелось что-то, что не теряет ваш стек, когда вы передаете что-то рабочему потоку. Я даже не знаю обходного пути для этого (С#). Было бы здорово узнать стек родительского потока до момента создания рабочего потока.

В общем, я думаю, что многие действительно полезные вещи должны быть встроены в язык и не могут быть достигнуты чисто с помощью одной только библиотеки или фреймворка. Я помню, в старших классах учили всегда писать условия до/после в комментариях к функции, но что мне действительно хотелось бы видеть, так это писать условия до/после, которые проверяются, если возможно, во время компиляции, а если нет, то во время компиляции. время выполнения. Они будут помечены каким-то образом, чтобы редактор мог по желанию показать или скрыть их, чтобы они не мешали чтению реального кода.

person Davy8    schedule 19.01.2010

Я сомневаюсь, что есть что-то подобное, и если, то это точно не годится для использования. Это зависит от ваших определений правил, разные люди думают по-разному, имеют разные потребности и рамки... То, что вы описали, может быть достигнуто с помощью метапрограммирования или некоторой макросистемы. В Java есть несколько проектов, которые могли бы помочь реализовать такой подход с использованием аннотаций, не знаю, есть ли какой-то эквивалент во вселенной С#. Однако функциональность isValid() очень похожа на идею проектирования по контракту, возможно, для этого есть какие-то рамки.

person Gabriel Ščerbák    schedule 14.01.2010
comment
Я увидел черновой вариант (т.е. превью) книги «Практическая генерация кода в .NET» Питера Фогеля в Safari Books Online и начал думать, зачем генерировать код, а потом подумал, что избавиться от этой ручной работы по проверке достоверности было бы отличное использование, поэтому мне интересно, делает ли это кто-нибудь. А что касается правил/определений и т. д. — это было решено с помощью статического анализа кода и инструментов обеспечения соблюдения правил, таких как FxCop — очевидно, такая структура должна быть настраиваемой. - person Avi; 14.01.2010
comment
Не забывайте, что статический анализ просто использует какие-то метрики, но ничего не доказывает, иначе это было бы частью компиляторов. Генерация кода, безусловно, является одним из способов. - person Gabriel Ščerbák; 15.01.2010