Насколько «защитным» должен быть мой код?

StackOverflow https://stackoverflow.com/questions/869599

  •  22-08-2019
  •  | 
  •  

Вопрос

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

Как понять, где провести черту?

Это было полезно?

Решение

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

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

Другие советы

Что-нибудь пользователь входит прямо или косвенно, вам следует всегда санитарная проверка.Помимо этого, несколько assertТо тут, то там не повредит, но в любом случае вы ничего не сможете поделать с сумасшедшими программистами, редактирующими и ломающими ваш код!-)

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

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

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

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

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

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

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

А теперь давайте начнем отрицательные голоса...

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

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

Я всегда отлаживаю. Подтверждаю свои предположения.

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

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

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

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

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

Два других

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

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

//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
}

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

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

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

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

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

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

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

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

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

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

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

В этой ситуации я, вероятно, выбрал бы золотую середину, где бы я использовал только «пуленепробиваемые» процедуры, которые:

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

(б) имеет логику, которая ВЕРОЯТНО изменится

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

(г) программу нельзя изящно «провалить»

Темная ночь

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top