Представьте на минутку, что вы — недавно принятый на работу программист, которому предстоит работать с популярной системой управления обучением (LMS) Hot4Learning. Ваш предшественник когда-то поработал над добавлением к системе возможности отправки email — для того, чтобы любой пользователь в школе мог отправить другому пользователю электронное письмо с помощью веб-интерфейса. Но, увы, судьба оказалась к нему неблагосклонна — его сбил автобус, и он так никогда и не завершил свой magnum opus, свою лебединую песню. Ваша задача — довести его дело до конца, добавив функцию валидации введенного email — чтобы можно было уверенным, что письма отправляются только в том случае, когда в качестве адресата вводится правильный адрес, привязанный к школе.
Приведем конкретный пример: допустим, Боб — студент в Университете Макгилла, и он должен иметь возможность отправить письмо на любой валидный адрес @mail.mcgill.ca
или @mcgill.ca
. Если адрес его подружки Джейн выглядит как jane.smith@mail.mcgill.ca
, то тогда Боб имеет полное право отправлять на него письма. В другом случае — скажем, если ее адрес jane.smith@mail.ru
— он, понятное дело, права на это не имеет, как и на отсылку писем на адрес thisisnotavalidemail@mail.mcgill.ca
.
Итак, ваша задача — реализовать эту возможность; при этом предполагается, что у вас есть список валидных адресов почты для конкретного учебного заведения.
Скорее всего, вы сейчас подумали «Да бросьте, ерунда какая-то, а не задача. Сначала, я создаю строку, в которой делаю конкатенацию всех адресов школы в список с разделителем '|****|', затем я передаю ее клиенту, присваивая строку переменной внутри тэга <script>
. Затем, в JavaScript, я создаю массив и присваиваю его переменной, любовно обозванной temp
. Каждый раз, когда пользователь вводит email, я перевожу его в нижний регистр и сохраняю в переменную с заманчивым названием curForwardUserName
… а еще я создам переменную validUserName
, которую я сделаю равной строке '0'
, потому что зачем мне использовать boolean
, если я могу использовать строку? Затем, я в цикле пройду по всему содержимому temp
; для каждого адреса почты в temp
я переведу его в нижний регистр, затем проверю, совпадает ли он с curForwardUserName
— и если это так, то я задам validUserName
равной строке '1'
и вызову break
. Наконец, если validUserName
равняется строке '1'
, то я могу спокойно считать, что curForwardUserName
— валидный адрес; в противном случае, он нам не подходит»
«Что за бред?» — подумали вы наверняка. Я надеюсь, что вам вряд ли пришло в голову написанное выше. Скорее, в вашей голове появилась следующая мысль: «ОК, очевидно, что валидацию я буду делать на стороне сервера. Я могу хранить валидные адреса почты в структуре данных, которая позволяет проводить сравнения со сложностью в O(1), и затем проверять, содержится ли в ней введенный email». И это нормально — ведь это правильный способ решения задачи.
Вот как решит эту задачу ваш мозг
В Python правильный способ решения этой задачи будет выглядеть следующим образом:
if input_email in valid_emails_set:
send_email(input_email, another_param, etc)
А вот как решит эту задачу ваш мозг под наркотиками
Но если злодейка-судьба закинула вас работать с великим и ужасным Hot4Learning, то вы, вполне возможно, всей душой ненавидите свою работу, и вам каждый день приходится от души «упарываться» наркотиками, чтобы вы могли хотя бы до нее дойти. Зато ваш наркомозг способен выдать такое:
Внимание: NSFWUYWOH (Not Safe For Work Unless You Work On Hot4Learning — Небезопасно Для Работы Только Если Вы Не Разработчик Hot4Learning)
<script>
// [какой-то еще код]
var userNamesStr = 'a.fakelastname@mail.mcgill.ca|****|another.fakelastname@mail.mcgill.ca
|****|(представим, что здесь лежит еще 70,000 emailов)|****|zamboni.man@mail.mcgill.ca';
var temp = new Array();
temp = userNamesStr.split('|****|');
var validUserName = '0';
// [вырезано цензурой]
for( i =0; i< temp.length; i++){
if( curForwardUserName == temp[i].toLowerCase() ) {
validUserName = '1';
break;
}
// [и еще немного бесценной мудрости]
</script>
Кстати, вышеприведенный код отправляет все 70,000+ адресов Университета Макгилла на клиент при каждой загрузке страницы. Исходный код страницы весит около 2.5MB, считай что чистого текста. Ну, а поскольку тот человек, что занимается код-ревью, и сам сидит на мете — ваш код легким движением руки попадает в продакшн.
Голая правда
В прошлом году, IT-отдел Университета МакГилла заменил старую LMS (Blackboard) на новую систему (которая на самом деле называется не совсем Hot4Learning, но давайте не будем мелочиться — ведь все остальное в лучших традициях Попова не тронуто). Поскольку старая система рассыпалась на глазах из-за уязвимостей и страдала от кучи других проблем, новую систему ждали с огромной надеждой на светлое будущее. Надежда умерла с той же скоростью, с какой у вышеозначенного наркомана когда-то безвозвратно умерли клетки головного
Клик на вкладку «email» встречал меня 10 секундами белого экрана и ожиданием того момента, когда браузер наконец загрузит страницу. Возник логичный вопрос — «Какого оно вообще столько грузится? Не может же оно пытаться загрузить все валидные адреса, хехех… Стоп. Блин...»
Словами трудно описать тот ужас, что охватил меня при просмотре исходников страницы. Страшнее в моей жизни был только сон про то, что мне удалось проспать экзамен по криптографии.
Увы, «вживую» вам на этот код полюбоваться уже не удастся — был отправлен баг-репорт как об уязвимости утечки данных, и поставщик ПО за две недели все исправил. Код, приведенный выше — один в один тот, что использовался в приложении — разве что, были опущены не имеющие отношения к его работе места. Все соображения по поводу того, на чем сидит программист-автор, принимаются на мой твиттер @dellsystem
.
ПРЕДУПРЕЖДЕНИЕ: Злоупотребление наркотиками плохо влияет на ваш исходный код.
Автор: HotWaterMusic