Стратегия обработки валидации параметров в библиотеке классов - PullRequest
1 голос
/ 20 декабря 2009

У меня довольно большая библиотека классов, в которой много кода.

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

Позвольте мне привести типичный пример:

  1. A.MethodA1 запускает цикл, перебирает коллекцию, вызывая B.MethodB1 для каждого элемента
  2. B.MethodB1 обрабатывает элемент и возвращает результат, это довольно простой расчет, но поскольку он используется во многих местах, он был помещен в собственный метод вместо того, чтобы копироваться и вставляться там, где это необходимо
  3. A.MethodA1 вызывает C.MethodC1 с результатами B.MethodB1 и помещает результат в список, который возвращается в конце цикла

В случае, который я нашел сейчас, B.MethodB1 выполняет элементарную проверку параметров. Так как метод вызывает другие внутренние методы, я бы хотел избежать нескольких уровней NullReferenceExceptions глубоко в коде и скорее завершить сбои рано, поэтому B.MethodB1 проверяет параметры, такие как проверка на нулевое значение и некоторые базовые проверки диапазона другого параметра.

Однако в этом конкретном сценарии вызова невозможно (из-за другой логики программы), чтобы эти параметры когда-либо имели неправильные значения. Если бы они имели, с точки зрения программы, B.MethodB1 никогда не был бы вызван вообще для тех значений, A.MethodA1 потерпел бы неудачу перед вызовом B.MethodB1.

Итак, я рассмотрел вопрос об удалении проверки параметров в B.MethodB1, поскольку он занимает примерно 65% времени выполнения метода (и это часть некоторого интенсивно используемого кода).

Однако B.MethodB1 является публичным методом, и поэтому его можно вызывать из программы, и в этом случае я хочу подтверждение параметра.

Так как бы вы решили эту дилемму?

  1. Сохраните проверку параметров и получите удар по производительности
  2. Удалите проверку параметров и, возможно, возникли проблемы с опозданием в методе
  3. Разделите метод на два, один внутренний, который не имеет проверки параметров, вызванный «безопасным» путем, и один открытый, который имеет проверку параметров + вызов внутренней версии.

Последнее дало бы мне преимущество отсутствия проверки параметров, в то же время предоставляя общедоступную точку входа, которая имеет проверку параметров, но по какой-то причине она не подходит мне.

Мнения

Ответы [ 2 ]

1 голос
/ 22 декабря 2009

Это интересный вопрос.

Хммм, заставляет меня думать ... "кодовые контракты" .. Казалось бы, возможно, что статически (во время компиляции) технически возможно, чтобы определенные контракты кода были доказаны выполненными. Если бы это было так, и у вас была такая опция проверки компиляции, вы могли бы указать эти контракты, даже не проверяя условия во время выполнения.

Требуется, чтобы сам код клиента был проверен по контактам кода.

И, конечно, это неизбежно будет сильно зависеть от типа условий, которые вы хотите написать, и, вероятно, будет возможно доказать эти контракты только до определенной точки (как далеко вы бы подняли возможный граф вызовов). идти?). Помимо этого, валидатору, возможно, придется начинать и настаивать на том, чтобы вы поместили проверку во время выполнения (или, возможно, подавление предупреждения проверки?).

Все просто пустые домыслы. Меня заставляет задуматься немного больше о контрактах кода C # 4.0. Интересно, есть ли в них поддержка статического анализа? Вы проверили их? Я имел в виду, но изучение F # в данный момент является приоритетным!

Обновление:

Прочитав немного об этом, похоже, что в C # 4.0 действительно есть «статическая проверка», а также двоичный перезаписывающий модуль (который заботится об изменении выходного двоичного файла так, чтобы проверки условий до и после выполнялись в соответствующих место)

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

Вот ссылка на статью о кодовых контрактах

1 голос
/ 20 декабря 2009

Я бы выбрал вариант 3. Я склонен использовать утверждения для частных и внутренних методов и выполнять все проверки в открытых методах.

Кстати, а производительность действительно так велика?

...