«У нас кончились столбцы» — Лучшая, худшая кодовая база

в 7:16, , рубрики: разработка

Оу, таблица merchants2? Ну, у нас кончились столбцы в merchants, так что мы сделали merchants2.

Оригинал статьи

На полпути перевода, я узнал о том, что кто-то сделал всю работу за меня. Но увы.

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

База данных живёт вечно

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

Вы знали, что в SQL Server есть ограничение на количество столбцов в таблицах? Вот и я не знал. Тогда, это было 1024 столбца, сейчас вроде 4096. Понятное дело, большинству людей это знать не надо. А вот нам надо было. В Merchants (нашей таблице для хранения данных клиентов) давным-давно кончились столбцы. Merchants2 стала решением. Это таблица с (если меня не подводит память) 500+ столбцами сама по себе.

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

SequenceKey

SequenceKey

1251238

Ради простоты восприятия, я полностью воссоздал таблицу SequenceKey выше. Да. Вы всё верно поняли, - это вся таблица. Таблица из единственного ключа и единственного значения. Если бы простота была добродетелью, можно было бы назвать SequenceKey идеальной таблицей. Что может быть проще?

Но вы можете спрашивать себя : какое применение может быть у таблицы с одним столбцом и одним рядом? Генерация ID. В то время я слышал историю о том, что когда-то давным-давно SQL Server не поддерживал автоинкремент ID. Это был общепринятый, правильный ответ. Мои попытки выяснить, правда ли это, оказались безрезультатными. Но на деле, SequenceKey был гораздо большим, чем это.

SequenceKey был клеем. В каждой хранимой процедуре, создающей новые сущности, вы сначала брали ключ из SequenceKey, увеличивали его, а затем вставляли его в качестве ID для N различных таблиц. Теперь у вас было неявное соединение между всеми этими таблицами сущностей. Если вы видели ID в системе, то высока вероятность, что в смежных таблицах будет строка с точно таким же ID. Честно говоря, довольно умно.

Календарь

База данных может и живёт вечно, но наша система входа в систему была ограничена календарем. И я не говорю об обычном календаре. Я о таблице, названной "calendar". Что в ней было? Вручную заполненный календарь. Спросив местного шамана (которого все называли Манч), я узнал из его уст, что когда в "календаре" закончатся дни, мы все не сможем зайти в систему. Так и случилось пару лет назад. Поэтому они назначили стажёра заполнить "календарь" на 5 лет вперёд, чтобы такого больше не случалось в ближайшее время. Какая часть системы использовала календарь? Никто не знал.

Employees

Каждое утро, в 7:15 ровно, падала таблица "employees". Все данные полностью стерты. Потом в таблицу загружался CSV из ADP. В этот период никто не мог зайти в систему. Иногда и эта процедура нас подводила. Но даже так, это ещё не конец процесса. Данные нужно было направить в штаб-квартиру. Для этого, по электронной почте отправлялось письмо человеку, который каждый день нажимал кнопку, чтобы скопировать данные.

Замена базе данных

Мы можете спрашивать себя : почему бы кому-то не привести базу данных в порядок? Сделать её удобнее для работы? Что же, компания вас опередила. Где-то валялась копия базы данных. Данные из этой копии отставали примерно на 10 минут, и синхронизация была односторонней. Но она была нормализована. Насколько нормализована? Путь от merchants к нужному номеру телефона составлял 7 соединений.

Цифры продаж

У каждого продавана была квота на месяц, называемая "победой". Таблицы, в которых хранились эти данные (не финансовые, а специфические для продаж), были невероятно запутанными. Каждый день служба выясняла, какие строки были добавлены и обновлены, и синхронизировала их с какой-то системой в штаб-квартире. Это не было проблемой, пока один продавец не догадался, что можно просить изменять эти записи вручную.

Этот продавец уже получил свою "победу" и провёл еще одну крупную продажу в том месяце. Он хотел перенести ее на следующий месяц, и стажеру было поручено сделать это. Слово за слово разошлось, и в течение следующих трех лет количество запросов росло в геометрической прогрессии. В какой-то момент у нас было 3 стажера, чьей постоянной работой было написание таких SQL-запросов. Создание приложения для этой задачи было сочтено слишком сложным. Однако перед уходом я постарался помочь стажерам создать собственное приложение. Не знаю, удалось ли им это сделать.

Кодовая база

Но как же база данных без кодовой базы. И что же это была за кодовая база... Когда я устроился туда работать, все было в Team Foundation Server. Если вы не знакомы, это была централизованная система управления версиями от Microsoft. Основная кодовая база, с которой я работал, была наполовину Visual Basic, наполовину C#. Она работала на IIS и использовала состояние сессии для всего. Что это означало на практике? Если вы перейдете на страницу по пути A или пути B, вы увидите на этой странице совершенно разные вещи.

Но описать кодовую базу лишь как "наполовину Visual Basic, наполовину C#" было бы неуважительно. Каждый фреймворк JavaScript, который существовать на тот момент, был загружен в наш репозиторий. Обычно с особыми изменениями, которые желал внести автор. Наиболее примечательно : Knockout, Backbone и Marionette. Ну и конечно чуть-чуть Jquery и его плагинов.

Но кодовая база не стояла особняком. Рядом с ней было около дюжины soap-сервисов и несколько собственных приложений для Windows. Наиболее примечательным был менеджер поставок. По легенде, он был создан одним разработчиком за выходные. Давайте назовем его Гилфойл. По общему мнению, Гилфойл был невероятно быстрым разработчиком. Я никогда не встречался с ним лично, но чувствовал, что знаю его, и не только по его коду в репозиториях, но и по всему коду, что остался на его жёстких дисках.

Жесткие диски Гилфойла

Манч (да, его правда так называли) хранил жесткий диск Гилфойла в RAID-конфигурации на своем столе спустя годы после того, как Гилфойл покинул компанию. Почему? Потому что Гилфойл был известен тем, что не вносил свой код в систему контроля версий. И не только этим, но и созданием рандомных "одноразовых" приложений на Windows для одного пользователя. Так что не было ничего необычного в том, что пользователь обращался к нам с сообщением об ошибке в приложении, которое существовало только на жестком диске Гилфойла.

Ошибка доставок

Большой частью моей работы было выявление ошибок, которым команды не хотели посвящать время. Раз в несколько месяцев, появлялась одна особенно неприятная ошибка. После того, как мы отправляли товары, в очереди на доставку появлялись "застрявшие" товары, которые одновременно заявляли, что были и отправлены, и не отправлены. Я пробовал ряд обходных путей (SQL-скрипт, Windows-приложение и т.д.), чтобы попытаться вывести нас из состояния бага. Мне было сказано не пытаться найти первопричину. Но я ничего не мог с собой поделать.

Попутно я узнал, как мыслит Гилфойл. Это приложение извлекало всю базу данных, затем фильтровало её по дате, сохраняя все заказы после даты запуска приложения. Приложение использовало SOAP-сервис, и не чтобы выполнять какие-то сервисные функции. Нет, сервис был простой функцией. Именно клиент создавал все побочные эффекты. В этом клиенте я обнаружил огромную иерархию классов. 120 классов, каждый с различными методами, наследование шло на 10 уровней вглубь. Единственная проблема? ВСЕ МЕТОДЫ БЫЛИ ПУСТЫМИ. Я не преувеличиваю. Не в основном пустыми. Полностью пустыми.

Это на какое-то время поставило меня в тупик. В конце концов, я узнал, что это было сделано для создания структуры, над которой он мог бы потом поразмыслить. Это размышление позволило бы ему создать строку с разделителем (структура которой полностью зависела бы от базы данных, но была полностью статичной), которую он отправил бы через сокет. Оказывается, все это в конечном итоге было отправлено в Kewill, службу, которая взаимодействовала с перевозчиками. Почему произошла эта ошибка? Компания Kewill каждый месяц повторно использовала длинные 9-значные номера и кто-то отключил cron-задание, которое удаляло старые заказы.

Красивый бардак

Об этой кодовой базе можно рассказать еще много интересного. Например, о команде Super-Senior разработчиков, которые в течение 5 лет переписывали все подчистую, не загрузив ни единой строчки кода. Или о консультантах Red Hat, создававших единую базу данных, которая должна была править всеми. Столько безумных уголков. Столько причин, по которым существовали целые команды, посвятившие себя тому, чтобы переписать с нуля хотя бы одну часть ее функционала.

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

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

Два пути разделения

Почему Джастин смог это сделать? Потому что у этой кодовой базы не было какого-то мастер-плана. Не было общего дизайна, в который должна была вписываться система. Не было ожидаемого формата для API. Не было документированной системы проектирования. Не было архитектурного совета, который бы следил за тем, чтобы все было согласовано. Приложение представляло собой полный и абсолютный бардак. Никто не мог его исправить, поэтому никто и не пытался. Что мы делали вместо этого? Мы выдалбливали свой собственный маленький мир здравомыслия.

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

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

Послесловие

За всю мою карьеру с тех пор, мне никогда не доводилось работать в такой удивительно уродливой кодовой базе. Все уродливые кодовые базы, с которыми я сталкивался впоследствии, так и не преодолели свою потребность в согласованности. Возможно, это происходило потому, что кодовая база была покинута «серьезными» разработчиками задолго до этого. Остались лишь разношерстные стажеры и джуны. А может быть, дело в том, что между этими разработчиками и пользователями не было никакой прослойки: ни переводов, ни сбора требований, ни карт. Лишь вы, стоящие за столом представителя службы поддержки, спрашиваете, как сделать их жизнь лучше.

Я скучаю по этой прямой связи. Быстрой обратной связи. Отсутствие необходимости строить грандиозные планы. По простой связи проблемы и кода. Возможно, это просто наивная ностальгия. Но в тот момент, когда я лежу на диване и мечтаю вернуться в худшие годы своего детства, когда я сталкиваюсь с очередным «enterprise шаблоном проектирования», в моей голове вспыхивают воспоминания о той прекрасной, ужасной кодовой базе.

Автор: rockstar_made

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js