[Перевод] Любопытные извращения из мира ИТ — 2

Сайт The Daily WTF уже 14 лет собирает курьёзные, дикие и/или печальные истории из мира ИТ. Я перевёл несколько рассказов, показавшихся мне интересными. Все имена и названия компаний изменены. Первая часть находится здесь.

История первая. Назло бабушке…


[Оригинал]

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

Клайв блестяще прошёл интервью и спустя неделю поступил на работу. В почтовом ящике его уже ждало письмо от кого-то по имени Брэндон. Оно гласило: «Надо встретиться».

Брэндон сидел в своём офисе, приклеившись к эргономическому креслу середины 90-х и как будто став с ним одним целым. Он поднял взгляд от монитора и посмотрел на Клайва. «Ты работаешь на меня».

Краткими фразами, состоявшими из односложных слов, Брэндон объяснил, что никто из принимавших решение о найме не будет встречаться с Клайвом. Клайв несёт ответственность только перед ним.

«Ну ладно… Так, когда меня нанимали, то сказали, что нужно настроить Subversion. Мне начинать с этого?», — спросил Клайв.

«Нет».

«Можно узнать, почему? Вы предпочитаете что-то другое? Хотите обсудить варианты?»

«Нет».
Клайв подождал. Брэндон не торопился разворачивать свою мысль. Он просто смотрел на Клайва. Продолжал смотреть и смотреть.

Клайв потихоньку вернулся в свой кубикл и начал с изучения кодовой базы. Она находилась на общем сетевом ресурсе, а управление версиями имело вид «file.pl.old», «file.pl.old.old». Оказалось, что код написан на Perl, и что он нечитаем даже по стандартам Perl. Он вырос в культуре «если парсится, значит запустится», не содержал комментариев и абсолютно не имел тестов. Единственным союзником Клайва был Ли, ещё один нанятый специалист, который тоже отчитывался перед Брэндоном, но у него была двухнедельная фора в анализе кода. Когда Клайв где-то застревал, он выглядывал из-за стены своего кубикла и спрашивал Ли.

Как ледник, спускающийся с горы, Клайв медленно прокладывал путь сквозь код. Неделю за неделей он постепенно нарабатывал понимание. А потом пришло письмо от Брэндона: «Надо встретиться».

«Вы мешаете команде разработчиков», — сказал он.

«Что?»

«Вы с Ли слишком шумите. Это офис, а не клуб по интересам».

«Это безумие. Я просто задавал ему вопросы по работе! Вы что, хотите, чтобы мы устраивали планёрки в конференц-зале, чтобы просто задать вопросы?»

«Да».

Брэндон замолчал и снова начал пристально смотреть на Клайва. Он смотрел, и смотрел… Клайв понял намёк и сбежал в свой кубикл.

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

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

А затем пришло письмо от Брэндона: «Надо встретиться».

«Кэрол говорит, что ты на неё давишь», — сказал Брэндон.

«Что?»

«Ты шлёшь ей письма, даже после того, как она отвечает на вопросы. Она сказала, что ты созвал совещание, а сам на него не явился. Это нужно прекратить».

«Это безумие. Она ни разу не ответила, я могу показать свои входящие и доказать это».

«Кэрол не пользуется электронной почтой», — объяснил Брэндон. «Интерн распечатывает её электронные письма, а она отвечает по внутренней почте офиса. Она очень занята. У тебя есть техническое задание. Выполни его, и перестань ей докучать».

«Что? Вы хотите чтобы я реализовал решение, даже не поговорив с пользователем, который знает все требования?»

Брэндон посмотрел на него. Он продолжал смотреть и…

С помощью Ли за следующие несколько месяцев Клайву удалось добиться серьёзного прогресса. Он научился справляться с абсурдным форматом дат (даты отсчитывались как количество дней с 3 апреля 1974 года, а ещё как количество месяцев с предыдущего понедельника, а ещё как количество недель со следующего воскресенья). Они справились с тем, что никому нельзя обновлять Firefox до версий выше 3, и с тем, что нельзя было работать сверхурочно, потому что все серверы отключались ровно в 18.00. Кэрол не поддерживала связь, Брэндон просто смотрел на них, а остальные сотрудники обращались с ними, как с прокажёнными.

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

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

От уровня высшего руководства поступили комментарии в духе «Не важно, сколько придётся потратить». Бухгалтеры предупреждали: «Если мы пойдём на это, у нас не останется денег на премии в конце года!»

Брэндон оставил собственное примечание: «Наш бизнес слишком специфичен. Они не справятся. Пустая трата денег. Они не справятся».

Всё встало на свои места. Брэндон не предсказывал, а давал обещание. И он его исполнит — за следующие несколько недель Клайв и Ли никак не смогут сделать то, что было обещано изначально.

Вскоре он получил письмо от своего рекрутёра. «Этой компании по-прежнему нужен дополнительный персонал. Хотите продлить договор ещё на шесть месяцев?»

Наученный Брэндоном, Клайв ответил коротко: «Нет».

История вторая. Отбросьте всё невозможное…


[Оригинал]

Отбросьте всё невозможное…
…и то, что останется, будет XML, каким бы невероятным он ни оказался.

9ff64490d143669004ed8c3e0bc737c5.png


Уильям Хогарт, «Абсурдная перспектива»

У разработчиков есть множество слабостей, и одна из них такова: они не любят говорить, что чего-то нельзя сделать. Именно поэтому когда клиент Гленна М, компания TelCo, спросила, будет ли её задача действительно невозможной, он вместо того, чтобы извиниться и решительно покачать головой, ответил: «Ну, теоретически…»

В результате Гленн написал это:


    
        
            
                
                    
                        
                            
(?:0x)?([0-9a-fA-F][0-9a-fA-F])\s*([0-9a-fA-F][0-9a-fA-F])\s*([0-9a-fA-F][0-9a-fA-F])\s*([0-9a-fA-F][0-9a-fA-F]) .1.3.6.1.4.1.2011.2.217.1.4.1.1.6 %4$s%3$s%2$s%1$s 8388607 8388608
1
1 (?:0x)?([0-9a-fA-F][0-9a-fA-F])\s*([0-9a-fA-F][0-9a-fA-F])\s*([0-9a-fA-F][0-9a-fA-F])\s*([0-9a-fA-F][0-9a-fA-F]) .1.3.6.1.4.1.2011.2.217.1.4.1.1.6 %4$s%3$s%2$s%1$s 23 255 127
(?:0x)?([0-9a-fA-F][0-9a-fA-F])\s*([0-9a-fA-F][0-9a-fA-F])\s*([0-9a-fA-F][0-9a-fA-F])\s*([0-9a-fA-F][0-9a-fA-F]) .1.3.6.1.4.1.2011.2.217.1.4.1.1.6 %4$s%3$s%2$s%1$s 31 1 1 -1 1


Это XML DDF, Data-Definition File для приложения мониторинга систем, которое поддерживал Гленн. Видите ли, система может считывать данные из любого устройства с поддержкой протоколов Modbus/TCP или SNMP, если у него есть файл DDF, задающий точки данных и способ их отображения. Схема DDF содержит показанные выше арифметические, булевы, регулярные и условные операторы, необходимые для того, чтобы система знала, как нужно очищать данные.

Логика на XML? Да, это само по себе WTF. Но настоящий WTF в том, что показанный выше код делает. Компания мониторила устройство, выводившее значения температуры (это решить довольно просто), но оно представляло их в виде строки из восьми символов, обозначающей шестнадцатеричное значение 32-битного числа с плавающей запятой в формате IEEE–754. Задача, которую Гленн должен был сразу признать невозможной, заключалась в преобразовании этого безумного значения в численный вид. В DDF, несмотря на всю его выразительную силу, не было оператора приведения типов.

Поэтому Гленн написал показанный выше DDF, который делал следующее:

  • Так как порядок байтов был перевёрнут, используем , чтобы вернуть их обратно в порядок, с которым можно работать
  • Используем , чтобы выполнить преобразование из octetString в uint_32
  • Используем и , чтобы отделить знаковый бит, экспоненту и мантиссу
  • Преобразуем знаковый бит в +/–1
  • Устраняем смещение экспоненты, а затем выполняем 1 на эту величину
  • Делим мантиссу на 223
  • Перемножаем три последних элемента, чтобы получить готовый результат. Так как  и другие операторы принимают только 2 операнда, действия должны быть вложенным


В следующий раз Гленн решил придерживаться той же тактики, потому что недавно услышал, что TelCo модифицирует устройство, чтобы оно выводило температуру в integer.

История третья. Команда А (нти)


[Оригинал]

В 1980-х снимался телесериал под названием «Команда А». В нём был проныра, способный обмануть кого угодно. Чтобы получить нужное, он давал как бы правдивые обещания (похоже на маркетинг?) Ещё в команде был крутой парень, который мог запугать любого, чтобы добиться своего. Он знал, как достичь цели, но в глубине души был добрым парнем. У команды был лидер, способный всегда придумать план и спасти ситуацию. И ещё был один немного безумный (но в хорошем смысле) парень, на которого всегда можно положиться в бою. Время от времени в команде появлялся помощник, занимавшийся вмешательством и разведкой. Эта группа ребят работала как хорошо смазанный механизм. Они не могли потерпеть неудачу! Они были командой!

cf6e89c1fd55bf430732f6b9576e3772.jpg


Команда «А» ни разу не писала документации по методологии управления проектом. Неудивительно, что все они — находящиеся в розыске уголовники.

Alex получил работу в новом проекте по замене устаревшей и неподдерживаемой системы. Естественно, заявлялось, что компания «стремится всё делать правильно!» Проект полностью финансируется. У команды будет нужное оборудование и персонал, необходимый для выполнения работы. Есть полная поддержка шести уровней руководства плюс всех пользователей. Алекс был настроен оптимистично.

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

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

Начало проекта было хорошим.

Первой задачей был найм разработчиков для команды. Для этого компания искала (очень далеко) офшорных специалистов, чтобы найти максимально дешёвых талантов. В конце концов, каждого ведь можно обучить, правда? Команда из 11 разработчиков в сумме имела 13-летний опыт работы, а для управления ими был нанят лид с пятилетним опытом.

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

Руководство проекта решило, что отдел QA можно привлечь позже.

Наконец, настало время реализации детализированной структуры. Лид офшорной команды решил, что можно сэкономить много времени, если создавать дизайн «на лету», в соответствии с запросами. Разумеется, архитекторы были против, но менеджер проекта дал согласие.

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

Настало время для проверки первого спринта, и во время обзора кода обнаружилось множество всевозможных «красных флагов». Лид джуниоров заявил, что архитектурная документация была всего лишь рекомендацией, которую он проигнорировал в угоду желаниям разработчиков. Естественно, это вызвало реакцию типа «да вы что, совсем там …?» и кучу писем вверх по цепочке руководства. Но менеджера проектов и руководство выше это, похоже, не интересовало: они сказали, что джуниоры не должны были этого делать, но они им доверяют.

Работа продолжалась. Архитекторы продолжали указывать на несовместимые с требованиями изъяны и дефекты реализации. Все предложения игнорировались, потому что лид офшорной команды заявил: «Google взращивает атмосферу инноваций и творчества; нам тоже нужно так делать!» Ему напомнили, что Google — это (по большей частиi) «мозговой центр», а лид работает с со строго нормированным проектом в строго регулируемой отрасли. Что архитектура, которую одобрили сорок с лишним менеджеров, — это не вариант или рекомендация, а требование. Что это не детский сад, где поощряется творчество — нужно придерживаться утверждённого плана! Мы же говорим не о том, как правильно писать подпроцедуру или инкапсулировать объект, а о том, что поточная обработка использована неверно и не в тех местах, а доступ к базам данных и межпроцессные коммуникации не будут масштабируемыми. Что нужно не создавать множественные процессы, а просто использовать потоки. Что не стоит использовать файлы в качестве семафоров просто потому, что так делали в школе. И список будет ещё будет долгим.

Но ни на ничто из этого не обратили внимания. Разработчики-джуны пожаловались, что при создании архитектуры не учли их мнения, поэтому они будут продолжать её игнорировать (с благословения их лида). Менеджер проекта продолжал говорить, что в курсе проблем, но ничего с ними не делал. О проблемах сообщали вверх по цепочке, но никто ничего не делал. Ведь все в команде имеют равное право голоса.

В реальном мире, если студент думает, что учитель ошибается, то ему не изменяют оценку. Стажёр режет там, где показывает ему хирург, и никак не наоборот. Генерал не обсуждает стратегию с рядовыми. Если ты вступаешь в профсоюз, и на правах новичка требуешь тех же полномочий, что и руководители профсоюза, то упокоишься рядом с Джимми Хоффа [американский профсоюзный лидер, неожиданно исчезнувший при загадочных обстоятельствах]. Опыт говорит с восклицательными знаками. Неопытность говорит с вопросительными.

Но не в этой «команде».

Джуниоры продолжали делать то, что им казалось наилучшим, игнорируя все запросы архитекторов. БОльшая часть их кода писалась и переписывалась несколько раз, потому что джуны не всё могли учесть с первого раза. Более опытные разработчики знали бы, на что рассчитывать. Спустя 8 месяцев проекту был нанесён такой урон, что самых сложных требований просто невозможно было добиться, а в начинавшемся с нуля проекте разработки нужно было откатиться на месяц назад.

Примерно в это время руководство уступило просьбам и попросило нескольких коммерческих пользователей написать тесты коммерческого уровня (например электронную таблицу, которую можно передать в JBehave для JUnit-тестирования). Разработчики предоставили код и несколько простых примеров в электронных таблицах. Архитекторы сказали, что нужно нанять сотрудников отдела QA, потому что пользователи редко знают, как работать с пограничными случаями, проблемами точности и т.д. Но деньги нельзя было тратить. Спустя шесть месяцев работы коммерческие пользователи заявили, что все тесты для всего приложения (т.е. всё техническое задание) готово. Только взглянув на него, можно было понять, что они не учли пограничные случаи, пустые примеры, проблемы точности и большинство других аспектов, которые обычно требуют тестов. На самом деле, они поместили все записи, которые могли теоретически (с их точки зрения) существовать, в один огромный тест прохождения-непрохождения (pass-fail test). Разумеется, когда что-то изменится и неизбежно произойдёт сбой, нет никаких возможностей узнать, где он случился.

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

Министерство сэкономило кучу денег благодаря использованию дешёвого труда, отсутствию отдела QA и применению «политически целесообразной» базы данных. Разумеется, весь код в части настройки, написанный офшорной командой, был ужасен. БОльшая его часть была сложна в изучении, поддержке, отладке и улучшении.

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

История четвёртая. Передать через нулевой указатель


[Оригинал]

У Максин возникли проблемы с отображением веб-сайта в браузере с дополнением NoScript. Это неудивительно — некоторые браузеры не могут правильно работать с NoScript, но удивляло то, что браузер выдавал исключения Java. При включении JavaScript страница с ошибкой пропадала, но как же так? Отсутствие JavaScript приводит к исключениям Java?!

Она открыла код страницы и обнаружила, что сервер ожидает параметр «innerCHK»; вероятно, какой-то токен сессии или безопасности, который должен передаваться в строке запроса URL. Если его нет, то сервер возвращает страницу с ошибкой, отображающей java.lang.NullPointerException. К счастью, разработчики фронт-энда придумали следующий великолепный фрагмент JavaScript для решения проблемы:

// Проверка ошибки
if (document.body.innerHTML.indexOf('java.lang'+'.NullPointerException') != -1){   
   if (document.location.href.indexOf('innerCHK=') == -1){    
        document.location.href = document.location.href + "&innerCHK=" + Math.random()*10000 ;
   }
}
// Конец проверки


Но это только верхушка айсберга; страница была перегружена антипаттернами, изобретёнными заново колёсами, запасными колёсами и спущенными колёсами. Всё это держалось на изоленте. Чтобы прочувствовать стиль некоторых странных строковых преобразований и любимого антипаттерна разработчиков — закрытия скриптов только для того, чтобы в следующей строке открыть новый, давайте взглянем на то, как импортируется Dojo. Надо учесть, что cookie-библиотека Dojo импортируется.

     
 


Некоторые, если не все ссылки на CSS обрабатываются таким образом. Я нашёл в исходниках как минимум три (идентичных) вхождения. Повторюсь Dojo.cookie импортируется.