Подтвердить что ты не робот

Как "защитный" должен быть мой код?

У меня была дискуссия с одним из моих коллег о том, как защищать ваш код. Я все прозащитное программирование, но вы должны знать, где остановиться. Мы работаем над проектом, который будет поддерживаться другими, но это не значит, что мы должны проверять ВСЕ сумасшедшие вещи, которые мог сделать разработчик. Конечно, вы могли бы это сделать, но это добавит очень большие накладные расходы на ваш код.

Как вы узнаете, где рисовать линию?

4b9b3361

Ответ 1

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

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

Ответ 2

Все, что пользователь вводит прямо или косвенно, должен всегда проверять работоспособность. Кроме того, несколько assert здесь и там не повредит, но вы не можете сильно поделать о том, как сумасшедшие программисты редактируют и нарушают ваш код, в любом случае! -)

Ответ 3

Я стараюсь изменить размер защиты, которую я ввел в свой код на основе языка. Сегодня я в основном работаю на С++, поэтому мои мысли дрейфуют в этом направлении.

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

Ответ 4

Я не поклонник термина "защитное программирование". Для меня он предлагает такой код:

void MakePayment( Account * a, const Payment * p ) {
    if ( a == 0 || p == 0 ) {
       return;
    }
    // payment logic here
}

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

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

Изменить: Я не согласен с некоторыми другими ответами и комментариями здесь. Я не думаю, что все функции должны проверять их параметры (для многих функций это просто невозможно). Вместо этого я считаю, что все функции должны документировать допустимые значения и указывать, что другие значения приведут к поведению undefined. Это подход, используемый наиболее успешными и широко используемыми библиотеками, когда-либо написанными - стандартными библиотеками C и С++.

А теперь давайте начнем вниз...

Ответ 5

Если вы работаете над публичными API-интерфейсами компонента, то стоит потратить немало проверки параметров. Это привело меня к привычке делать валидацию повсюду. Это ошибка. Весь этот код проверки никогда не тестируется и потенциально делает систему более сложной, чем она должна быть.

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

Ответ 6

Я всегда Debug.Assert мои предположения.

Ответ 7

Моя личная идеология: защита программы должна быть пропорциональна максимальной наивности/незнанию потенциальной базы пользователей.

Ответ 8

Защита от разработчиков, использующих ваш код API, не отличается от защиты от обычных пользователей.

  • Проверьте параметры, чтобы убедиться, что они находятся в соответствующих границах и ожидаемых типах.
  • Убедитесь, что количество вызовов API, которые могут быть сделаны, находится в ваших Условиях обслуживания. Обычно называемое дросселирование обычно применяется только к веб-службам и функциям проверки пароля.

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

Ответ 9

Оборонительное программирование - это всего лишь один способ заключить контракт по способу кодирования по контенту.

Остальные два:

  • общее программирование и
  • номинальное программирование.

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

//precondition : par is so and so and so 
function doSth(par) 
{
debug.assert(par is so and so and so )
//dostuf with par 
return result
}

Ответ 10

Думаю, вам нужно задать вопрос о том, создаете ли вы тесты. Вы должны защищаться в своем кодировании, но, как указано JaredPar, я также считаю, что это зависит от языка, который вы используете. Если это неуправляемый код, то вы должны быть очень защитным. Если это удалось, я считаю, что у вас есть немного wiggleroom.

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

Ответ 11

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

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

Ответ 12

Если здесь обсуждается, как защищать код от будущих (возможно, злонамеренных или некомпетентных) сопровождающих, существует предел тому, что вы можете сделать. Использование контрактов через покрытие тестирования и либеральное использование утверждений о ваших предположениях, вероятно, является лучшим, что вы можете сделать, и это должно быть сделано таким образом, чтобы в идеале не загромождать код и не усложнять работу для будущих незрячих разработчиков код. Утверждения легко читаются и понимают и дают понять, что представляют собой предположения данной части кода, поэтому они, как правило, отличная идея.

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

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

Ответ 13

Системы должны иметь хорошо разработанные границы, где происходит защитная проверка. Должно быть принято решение о том, где пользовательский ввод проверяется (на какой границе) и где другие потенциальные защитные проблемы требуют проверки (например, сторонние точки интеграции, общедоступные API-интерфейсы, взаимодействие с механизмами правил или разные блоки, закодированные различными командами программистов). Более защитная проверка, чем во многих случаях, нарушает DRY, и просто добавляет затраты на обслуживание для очень небольшого эффекта benifit.

Если говорить, есть определенные моменты, когда вы не можете быть слишком параноидальными. Потенциал переполнения буфера, искажения данных и аналогичные проблемы должны быть строго защищены.

Ответ 14

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

Ответ 15

Хороший вопрос, я перевернулся между проверками здравомыслия и не делал их. Его 50/50

я бы, вероятно, занял среднюю позицию, где я бы только "Bullet Proof" выполнил любые подпрограммы:

(a) Вызывается из более чем одного места в проекте

(b) имеет логику, которая LIKELY для изменения

(c) Вы не можете использовать значения по умолчанию

(d) процедура не может быть "неудачной" изящно

Darknight