The Daily WTF – это сайт, на котором разработчики публикуют самые глупейшие случаи из собственной практики в IT.
2К открытий3К показов
The Daily WTF – это сайт, основанный в 2004 году, на котором разработчики публикуют самые глупейшие случаи из собственной практики в IT. Разработчики рассказывают на примерах из жизни, как не стоит разрабатывать программное обеспечение.
Здесь публикуются самые глупые истории о катастрофичных разработках, начиная полным провалом управления проектами и заканчивая написанием непонятного кода.
В этой статье мы разберем несколько историй, с которыми столкнулись разработчики с The Daily WTF.
Ручная база данных
Разработчик С. Уайлс работает в крупной компании, которая занимается медицинским страхованием. Он разрабатывает SAS-приложение для своего работодателя.
Вдруг разработчику поступила задача: нужно открыть базу данных и поменять в ней формат записи даты: сделать так, чтобы запись месяца состояла из двух цифр, а не из одной. К примеру, январь должен быть записан как «01».
Итак, Уайлс открывает базу данных и видит в ней это:
%macro yearmonth;
if year_month = '2010-1' then year_month = '2010-01';
else if year_month = '2010-2' then year_month = '2010-02';
else if year_month = '2010-3' then year_month = '2010-03';
else if year_month = '2010-4' then year_month = '2010-04';
else if year_month = '2010-5' then year_month = '2010-05';
else if year_month = '2010-6' then year_month = '2010-06';
else if year_month = '2010-7' then year_month = '2010-07';
else if year_month = '2010-8' then year_month = '2010-08';
else if year_month = '2010-9' then year_month = '2010-09';
else if year_month = '2010-10' then year_month = '2010-10';
else if year_month = '2010-11' then year_month = '2010-11';
else if year_month = '2010-12' then year_month = '2010-12';
else if year_month = '2011-1' then year_month = '2011-01';
else if year_month = '2011-2' then year_month = '2011-02';
else if year_month = '2011-3' then year_month = '2011-03';
else if year_month = '2011-4' then year_month = '2011-04';
else if year_month = '2011-5' then year_month = '2011-05';
else if year_month = '2011-6' then year_month = '2011-06';
else if year_month = '2011-7' then year_month = '2011-07';
else if year_month = '2011-8' then year_month = '2011-08';
else if year_month = '2011-9' then year_month = '2011-09';
else if year_month = '2011-10' then year_month = '2011-10';
else if year_month = '2011-11' then year_month = '2011-11';
else if year_month = '2011-12' then year_month = '2011-12';
else if year_month = '2012-1' then year_month = '2012-01';
else if year_month = '2012-2' then year_month = '2012-02';
else if year_month = '2012-3' then year_month = '2012-03';
else if year_month = '2012-4' then year_month = '2012-04';
else if year_month = '2012-5' then year_month = '2012-05';
else if year_month = '2012-6' then year_month = '2012-06';
else if year_month = '2012-7' then year_month = '2012-07';
else if year_month = '2012-8' then year_month = '2012-08';
else if year_month = '2012-9' then year_month = '2012-09';
else if year_month = '2012-10' then year_month = '2012-10';
else if year_month = '2012-11' then year_month = '2012-11';
else if year_month = '2012-12' then year_month = '2012-12';
else if year_month = '2013-1' then year_month = '2013-01';
else if year_month = '2013-2' then year_month = '2013-02';
else if year_month = '2013-3' then year_month = '2013-03';
else if year_month = '2013-4' then year_month = '2013-04';
else if year_month = '2013-5' then year_month = '2013-05';
else if year_month = '2013-6' then year_month = '2013-06';
else if year_month = '2013-7' then year_month = '2013-07';
else if year_month = '2013-8' then year_month = '2013-08';
else if year_month = '2013-9' then year_month = '2013-09';
else if year_month = '2013-10' then year_month = '2013-10';
else if year_month = '2013-11' then year_month = '2013-11';
else if year_month = '2013-12' then year_month = '2013-12';
else if year_month = '2014-1' then year_month = '2014-01';
else if year_month = '2014-2' then year_month = '2014-02';
else if year_month = '2014-3' then year_month = '2014-03';
else if year_month = '2014-4' then year_month = '2014-04';
else if year_month = '2014-5' then year_month = '2014-05';
else if year_month = '2014-6' then year_month = '2014-06';
else if year_month = '2014-7' then year_month = '2014-07';
else if year_month = '2014-8' then year_month = '2014-08';
else if year_month = '2014-9' then year_month = '2014-09';
else if year_month = '2014-10' then year_month = '2014-10';
else if year_month = '2014-11' then year_month = '2014-11';
else if year_month = '2014-12' then year_month = '2014-12';
%mend yearmonth;
Оказалось, что все данные об обновлениях дат вносятся в БД вручную для составления запроса. Форматирование даты не было сделано на уровне БД, и для неё не была написана отдельная функция. Однако вместо этого скрипт обновляется вручную. Каждый год.
Сломанная валидация данных
Кэрол много лет работает во фронтенде веб-приложения. Ей достался код, который нужно было поддерживать и который отвечал за проверку данных, введённых, по всей видимости, в поле пароля для входа на сайт.
Кажется, что написать такую функцию просто. По крайней мере, правила для составления пароля довольно просто описать устно: должен быть один знак вроде восклицательного, длина пароля должна быть не меньше 8 символов, и так далее.
На деле написать такой код самостоятельно — довольно непростая задача, потому что код может быть громоздким.
Вот, какой код достался Кэрол:
const validateGeneral = async function (importantDataStructure) {
log.info(`Validating schema for ${importantDataStructure.name} `)
let errors = []
try {
importantDataStructure.importantField === 'onlyThisStringIsAllowed'
? null
: errors.push(' Invalid importantField')
validations.NAME_VALIDATION.test(importantDataStructure.name)
? null
: errors.push(' importantDataStructure name has invalid characters')
importantDataStructure.requiredField === undefined
? errors.push(' importantDataStructure is missing requiredField')
: null
if (errors.length > 0) {
log.error(`Errors detected for ${importantDataStructure.name} `)
throw new Error(errors.toString().trim())
}
} catch (err) {
console.log(err)
}
}
Кэрол обратила внимание на две вещи. Первая — функция validateGeneral выглядит главной и помечена как асинхронная. На деле же она не выполняет ничего значимого и не является асинхронной.
Оказалось, что разработчик, который писал функцию, пометил функцию асинхронной, потому что они обернули все условные операторы в вызов Promise.all, явно пытаясь заставить однопоточный JavaScript выполнять многопоточную проверку.
Когда это не сработало, они удалили вызов Promise.all, но не удалили async.
Раньше функция выбрасывала ошибки по цепочке (хотя возврат значения имел бы больше смысла), но при отладке другой разработчик обернул все это в try/catch. После этого отладочный код не был удалён, а функция сломалась.
Функция прошла код-ревью и тестирование, после чего была выпущена в таком состоянии на продакшн. При этом никто не заметил неисправностей и не сообщил об этом разработке.
Нерабочий код, который сработал
Обычно программисты хорошо понимают, как работает цикл for — это довольно полезный инструмент, который позволяет отсортировать данные.
Если присмотреться, можно заметить, что оператор ++ появляется три раза, а не два, как следовало бы. Однако код работает!
Оказалось, что разработчик допустил ошибку, но при этом получил рабочее решение. i = i++ выполняет постинкремент. Он устанавливает i равным значению, хранящемуся в i, а затем инкрементирует значение, которое раньше хранилось в i. Это то же самое, что и i=i. Получилось что-то вроде тавтологии.
Кажется, разработчик написал код и обнаружил, что тот не работает. Затем он стал добавлять случайные символы и всё же сделал так, чтобы код заработал. Он писал код как ChatGPT, только менее осознанно.
Заключение
От ошибок никто не застрахован. Это нормально: люди учатся на ошибках. Но куда проще, интереснее и безболезненнее учиться на чужих ошибках, а не на собственных, и The Daily WTF поможет вам в этом.
Сталкивались ли вы с такими же глупыми ошибками? Напишите об этом в комментариях или напишите для нас статью! ?
Евгений Домнин делится тем, как писать понятные отчеты о багах, улучшая коммуникацию и ускоряя исправление ошибок. Практические советы для тестировщиков и специалистов по качеству.
Попросили мидл и синьор-разработчиков поделиться любимым развлекательным контентом с другими разработчиками: поделиться подкастами, каналами, сайтами и шоу. Вот, что они посоветовали.