Предъявите ваши аргументы

Стопроцентно ваш код ужасен. Я говорю это не для того, чтобы оскорбить вас или унизить, а лишь для того, чтобы помочь вам. Я программист, и работаю с другими программистами вот уже почти 20 лет. За это время, в большинстве исходных кодов, которые я видел, к многочисленным ошибкам добавлялись ещё и зияющие дыры в безопасности. Более того, эти исходники было очень сложно читать и они были ужасны по своей сути. Само собой, некоторые из них были и моего авторства. Поэтому, я решил рассказать о нескольких принципах и шаблонах написания лучшего софта, адресованных к самым вопиющим ошибкам, с которыми я сталкивался. В этой статье поговорим об аргументах.

Как вы знаете, аргументы это параметры, передающиеся в подпрограммы, функции или методы. В СИ-подобных языках (например, JS) они выделяются скобками справа от названия функции, как-то так:

Эти скобки как врата в совершенный мир вашей функции. Вы должны учитывать тот факт, что абсолютно любой может пройти через эти врата. Включая абсолютных дегенератов, злобных хакеров, Джека Торренса или даже ФСБ. Это приводит нас к основному принципу:

Никогда не доверяйте аргументам!

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

Первое, что вы должны сделать, это гарантировать сам факт существования аргумента. То есть защититься от null или чего-нибудь подобного (в том же JS возможен параметр NaN).

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

Наконец, если передаваемый аргумент должен быть оценен (пример: вставлен в HTML или сформирован в SQL-запрос), помните, что его символы нужно экранировать, так как он получен непонятно откуда и вполне возможно является куском кода вредоносной программы.

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

Из всего этого мы делаем большой вывод, о том, что до того, как использовать аргументы:

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

Вы, должно быть, думаете, что:
Это очевидно. Я это уже знаю. Зачем мне тратить своё время?
Пиф-паф, вы застрелены!

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

Проверка входных данных происходит во front-end’e

— Ой! Хороший мальчик, возьми пирожок на полке!

Вы совершаете две ужасные ошибки.

Ужасная ошибка номер один: вызывать функцию можно обходя фронт-энд.
Как думаете, насколько просто обойти ваш фронт-энд? Прямо сейчас 2-годовалая обезьянка Бонго кодит, не трогая ваш фронт-энд. А если ваша функция доступна в Интернете (как в веб-приложениях) Бонго просто составит запрос на получение или изменение внутренних данных. Если ваша функция в декстопном приложении, Бонго просто подключит DLL и поразвлекается на славу, делая с функцией все, что захочет (в самых немыслимых позах).

Ужасная ошибка номер два: вы вообще единственный, кто использует ваш фронт-энд.
Послушайте, вы же не вечный джун, застрявший на азах кодинга. Вы поменяете место работы. Однажды, вас признают за изумительный вклад и вручат весомый приз! Ну или дадут повышение. Время пройдет, и кого-то нужно будет взять на ваше место. И догадайтесь, кто придёт? Правильно, наш старый друг Бонго. И ленивый Бонго со своим индусским кодом, воткнет свой фронт-энд поверх вашего. После всего, вы — легенда компании, ваш код дороже золота. Но, Бонго едва ли может чистить банан, не то, что контролировать валидность входных данных. Так он постыдно раскроет много глупостей в прекрасном мире вашей маленькой функции.

Эта функция приватна.

— И что, реально работает?

Посмотрите еще раз «ужасную ошибку номер два». Когда Бонго доберется до вашего кода, никому не спастись. Также, иногда ваша public-функция вызывает внутри себя ту private-функцию (и передает ей аргументы). Лучше обезопасить себя сейчас, чем потом лить слезы.

А что насчет падения производительности из-за всех этих повторяющихся if-ов?

— Вы, наверное, шутите?

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

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

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

Перевод статьи «Patterns and Principles for Writing Better Code»