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

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

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

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

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

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

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

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

4 ответа

Решение

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

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

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

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

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

    //rest of method
}

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

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

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

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

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

Другие вопросы по тегам