Почему всё ломается даже у хороших программистов?

После несерьёзной статьи на серьёзную тему Job Safety Driven Development стоит рассказать о том, почему даже опытные и добросовестные программисты волей случая могут попадать в схожие ситуации. Сначала захотелось написать, почему программисты ошибаются вообще, но оказалось, что это слишком разные темы. Потом оказалось, что и на эту тему получился очень длинный текст. По-хорошему его нужно было разбить на части, но здесь я его приведу целиком. Кроме того, нам придётся дополнить понятие «серебряная пуля» понятием «золотая шестерёнка», это занимательное явление может доставить много проблем. Попробую писать простым языком, надеюсь, что у меня получится.

Почему всё ломается даже у хороших программистов?

Меня зовут Константин Митин, я сооснователь и руководитель компании АйТи Мегастар/АйТи Мегагруп. Когда-то был простым разработчиком, работал в L3, дорос до тимлида, затем и до руководителя филиала разработки крупной ИТ-компании. Теперь я в АйТи Мегагруп.

В своё время какой-то мудрый человек (к сожалению, первоисточника я не знаю) на хорошо понятном всем языке раскрыл тему: «Откуда берутся ошибки на крупных проектах». Привожу объяснение, как оно есть.

Маркетолог спрашивает программиста: в чём сложность поддержки большого проекта?

Программист: ну, представь, что ты писатель и поддерживаешь проект «Война и мир». У тебя ТЗ — написать главу, как Наташа Ростова гуляла под дождём по парку. Ты пишешь «шёл дождь», сохраняешь, вылетает сообщение об ошибке «Наташа Ростова умерла, продолжение невозможно». Почему умерла? Начинаешь разбираться. Выясняется, что у Пьера Безухова скользкие туфли, он упал, его пистолет ударился о землю и выстрелил в столб, а пуля от столба срикошетила в Наташу. Что делать? Зарядить пистолет холостыми? Поменять туфли? Решили убрать столб. Получаем сообщение «Поручик Ржевский умер». Выясняется, что он в следующей главе облокачивается о столб, которого уже нет...

Это все действительно так. Чем выше сложность ИТ-системы, тем менее устойчиво и предсказуемо она себя ведёт. В этом ли дело, стоило ли об этом начинать писать целую статью? Конечно нет, дело не в этом.

Сейчас мы будем рассматривать опытных и состоявшихся разработчиков, которые хорошо понимают что и зачем делают, которые заранее просчитывают последствия своих действий. У такого человека уже поставлено мышление, он уже многое видел за время своей работы и многое понял. Ему не надо слепо следовать популярным стереотипам ИТ сферы. Во-первых, он видел их в первоисточнике до того, как инфоцыгане от своего непонимания их исказили. Во-вторых, они же постоянно меняются. То есть «детские» ошибки разбирать нет смысла.

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

Источник дефектов кодирования и проектирования очень часто находится вне программного кода.

Простой случай

Что мы имеем в самом простом случае. Допустим, у нас есть проект либо продукт, который живёт уже 3-4 года. Это большой срок. Скорее всего, требования несколько раз заметно изменились. Технические и архитектурные решения, которые закладывались на старте разработки, могут оказаться не то чтобы неудачными, они могут начать откровенно мешать.

Почему всё ломается даже у хороших программистов?

Перед разработчиками встаёт вопрос: "А что делать-то в такой ситуации?". Откатываться на несколько лет разработки назад и начинать всё заново? Вы серьёзно? А бизнес что скажет? Опытные разработчики понимают, как это для бизнеса будет больно, и не будут предлагать всё переписать с нуля.

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

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

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

Именно в такой ситуации родилась шутка: «...ну, представь, что ты писатель и поддерживаешь проект «Война и мир»...». Система становится слишком сложной и непредсказуемой.

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

Золотые шестерёнки: знакомство

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

Почему всё ломается даже у хороших программистов?

Нам нужен реинжиниринг и обеспечение перехода архитектуры приложения из состояния «as is» к состоянию «to be». Звучит просто, но ведь мы это собираемся сделать на живую, не останавливая работу пользователей, не останавливая разработку нового функционала, причём в системе, которая разваливается от регресса.

Знаете анекдот про кардиохирурга и моториста? Он очень хорошо описывает ситуацию. Если не знаете, то вот он…

Кардиолог приезжает в автосервис, ему работяга машину чинит, потом говорит:

- Слышь, мужик, вот я мотор перебираю - и ты мотор перебираешь, только человеческий - почему тебе платят на порядок больше?

Кардиолог кивает, идёт к машине, включает зажигание и говорит работяге:

- А попробуй при работающем движке теперь перебери!

То есть такой человек:

  1. Знакомится с больной системой.

  2. Восстанавливает историю принятия решений и разработки.

  3. Выявляет неочевидные места, где нельзя терять обратную совместимость.

  4. Строит в своей голове систему, как она есть.

  5. Знакомится с новыми требованиями.

  6. Представляет себе ветки вариантов дальнейшего развития системы.

  7. Строит в своей голове систему, какой она должна стать под новые и старые требования одновременно.

  8. Строит в своей голове карту шагов от состояния «как есть сейчас» к «как должно быть». При условии, что на каждом новом шаге не наступает отказ от обратной совместимости, но удовлетворяются новые требования.

  9. Каким-то образом договаривается с бизнесом.

  10. Каким-то образом втягивает в эту авантюру техническую команду.

  11. Всю дорогу защищает от бизнеса техническую команду и выбранный путь.

  12. Всю дорогу защищает от технической команды бизнес и выбранный путь.

  13. Но не теряет способность слышать других и гибко маневрировать на выбранном пути.

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

Честно говоря, такой человек чаще решает не технические проблемы, хотя является сильным разработчиком, а организационные и политические проблемы.

Аварийная ситуация

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

Почему всё ломается даже у хороших программистов?

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

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

Главному архитектору мало иметь технические компетенции, он должен быть ещё и жёстким управленцем с развитым стратегическим видением.

В случае если со стороны этого самого «главного архитектора» недостаточно контроля за ситуацией либо его вообще нет, начинают происходить аварийные ситуации. Как это происходит? Например, у вас есть сервис, который предоставляет наружу какое-то API. Рядом с вами без предупреждения выскакивает какой-то очень-очень важный для бизнеса сервис, который начинает генерить на вас нагрузки столько, сколько все остальные системы вместе взятые. А о вас просто при планировании забыли. Нет, ну правда. И бюджет на расширение ваших мощностей заложить забыли. Не потому, что программисты плохие, а потому, что менеджер либо владелец системы свой KPI улучшает.

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

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

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

Потом начинается либо эпидемия, либо война, либо просто конец света. Нагрузка на вас растёт ещё и ещё, ваша система перестаёт справляться.

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

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

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

После этого кому-то очень опытному, коммуникабельному и умеющему играть в политику придётся идти и договариваться о транзите из архитектуры «как было» к архитектуре «как надо» через «аварийную архитектуру».

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

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

Высокая квалификация: побочное действие

Оценка уровня разработчика — непростая тема. Достаточно просто отличить джуна и мидла. Не так сложно отличить мидла от сеньора. А вот дальше мы встречаемся с неожиданным явлением, у двух разных «senior developer», которые занимают одинаковые позиции, уровень и эффективность работы могут отличаться в десятки раз. Оба молодцы, оба достойны, но вот как-то так. Причём мы не говорим о технических лидерах, которые глубоко знают и понимают технологии, с которыми работают. Мы говорим о способности человека быстро, легко и эффективно решать задачи, способности сложное делать простым и работать с большими объёмами данных у себя в голове.

Почему всё ломается даже у хороших программистов?

Другая неожиданная вещь — с сильными и талантливыми разработчиками нужно соблюдать технику безопасности.

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

Но не все так хорошо, как кажется. Нужно всегда помнить, что с кодом работают программисты разного уровня. Даже если сейчас у вас в команде есть сильный разработчик, то так может быть не всегда. Например, я люблю битовые операции и битовые сдвиги, код получается компактней и быстрей. Буду ли я так писать коммерческий код? Нет, конечно, рядовому разработчику будет сложно. Опытный разработчик на C++, который знает «магию C++», скорее всего, не будет её использовать в коде потому, что рядовому разработчику будет сложно. Опытный разработчик не будет делать всё через регулярные выражения, даже если умеет и может. Он понимает, что за ним придёт другой человек, которому придётся разбираться с его кодом.

Аналогично со всем синтаксическим сахаром и нетривиальными инструментами. Опытные разработчики, наоборот, упрощают конструкции в своём коде, помня, что они не одни и не навсегда. Но так происходит не всегда.

Опытные разработчики, наоборот, упрощают конструкции в своём коде, помня, что они не одни и не навсегда.

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

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

Почему это всё важно? Потому что существует организационный антипаттерн «Рыцарь на белом коне» (Knight in shining armor, KISA), который приходит, решает проблемы, которые никто не может решить. Но потом он уходит и больше не возвращается. В результате может получиться уникальный код, созданный божественным разумом, который никто вокруг не может поменять. А бывает надо, бизнес же не стоит на месте.

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

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

Бывает, что в коде и в самой организации заметны трассы вылета золотых шестерёнок, которые, проходя через тело организации, ведут себя, как пуля со смещённым центром тяжести. Что это такое и почему происходит, сейчас расскажу.

Золотые шестерёнки: цена

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

Почему всё ломается даже у хороших программистов?

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

Но есть два негативных момента. Первый — этим начинает пользоваться средний менеджмент. Что такое средний менеджмент — это управляющая административная прослойка между бизнесом и исполнителями. Представители бизнеса не теряют свою адекватность, благодаря обратной связи от окружающей среды. Они свои ошибки быстро ощутят по финансовому потоку. Исполнители, которые работают в поле, тоже имеют непосредственную обратную связь с окружающим миром. Для разработчика это пользователи, внедренцы, техническая поддержка. Средний менеджмент не имеет ни того, ни другого. Они просто пишут отчёты и выполняют свой KPI либо его аналог.

Когда среднему менеджменту в руки попадает золотая шестерёнка, они начинают радоваться. Ведь с помощью этого человека можно выполнять свой KPI и все ошибки тоже можно на него валить. Иногда доходит до культа личности, в такие моменты начинается «это было его решение» и «если даже он не справился». Способ снять с себя ответственность и отвести от себя удар. На такого человека начинают отгружать всё больше и больше сложных задач, всё больше и больше ответственности за принимаемые решения.

Когда среднему менеджменту в руки попадает золотая шестерёнка, они начинают радоваться.

Второй момент — очень коварный. Золотая шестерёнка не ломается под нагрузкой, ломаться начинают люди вокруг и структура организации. Крепостное право отменили, люди устают и просто уходят. Иногда в команде золотой шестерёнки можно услышать: «Если ты уйдёшь, то я тоже уйду, я не согласен заниматься тем, что делаешь ты сейчас». Начинает снижаться взаимозаменяемость.

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

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

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

Личный опыт

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

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

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

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

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

Менеджеру было всё равно, ему нужно было бездумно выполнить задачу, чтобы не получить нагоняй от генерального директора. В общем, я его в грубой и экспрессивной манере отослал от себя подальше. Что было в результате? После нескольких итераций обсуждений, когда люди наконец поняли, что так нельзя и что такого наша платформа не может ни на бэкенде, ни на фронте, но генеральному директору очень хочется, пришлось мне сесть и написать мегакостыль. То есть сесть и написать нетривиальный SQL-запрос (формат выдачи с неожиданной группировкой) с оптимальным планом выполнения (требование компании, за этим яростно следили, и на это были объективные причины), а потом банально подломить платформу на фронтенде (JS же, мы и не такое проворачивали), чтобы она наконец хоть что-то смогла. Ну и несколько сотен строк прикладного кода, куда без него. Костыль имел длинное имя собственное из множества слов, среди которых было всего два цензурных: «волшебный» и «единорог».

Менеджеру было всё равно, ему нужно было бездумно выполнить задачу, чтобы не получить нагоняй от генерального директора.

Платформа обещала в скором времени отдать функционал, который позволит всё это убрать. Вот только я не помню, когда он появился, когда они смогли. Через два года? Через три? Где-то в ожидании этого момента я несколько раз грустно смеялся, когда падала платформа на фронтенде, а костыль продолжал прекрасно работать.

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

Написал я прикладную функцию, куда-то её положил (не стал делать её библиотечной, костыль же) и спокойно её использовал. Как-то мы провели рефакторинг, в ходе которого переработали эту функцию и переместили её в другое место. У нескольких команд из соседних филиалов рухнул их функционал. На вопрос, зачем они такое сделали, ведь мы её как API никому не обещали, внятного ответа дать они не смогли. На моей памяти библиотечной функции в платформе так и не появилось. Зато появилась куча копий этого функционала по разным модулям. Люди сделали выводы и подстраховались.

На самом деле это был всего лишь маленький эпизод длинного пути, в результате которого родился волшебный метод API, который в одиночку осуществлял многопараметрический поиск по всему моему модулю и где-то пяти (либо десяти?) соседним модулям с богатым набором форматов выдачи данных и нетривиальных группировок. Причём это всё происходило исключительно быстро, так как под каждый случай собирался свой оптимальный SQL-запрос. Всё это счастье объяснялось «требованиями генерального директора». Код за авторством моего ведущего разработчика и меня лично.

На самом деле это был всего лишь маленький эпизод длинного пути...

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

Вообще, генеральным директором и его «самодурством» в компании было принято очень многое объяснять. Только это было не до конца правдой. Генеральный директор был человеком умным и в прошлом талантливым разработчиком. Моей команде пришлось как-то своими руками повторить то, что он лет 10-15 назад сделал своими руками для десктопной версии. Ну, я то его алгоритм понял (раза с третьего), мне решение понравилось. А вот техлиды и ведущие разработчики — нет, алгоритм слишком неочевидным был. Им просто не хватило масштабности и строгости мышления.

Вообще, генеральным директором и его «самодурством» в компании было принято очень многое объяснять. Только это было не правдой.

Самодуром он тоже не был. Просто он сам был золотой шестерёнкой, на которую вся компания пыталась валить все решения, чтобы снять с себя ответственность и не думать своей головой. А когда человек изо дня в день проводит от 16 и более встреч по разным техническим вопросам, к концу дня от усталости он может принимать решения любой степени неадекватности. Если вообще сможет что-то делать. Генеральный директор — мог.

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

Нагрузка росла, мы даже один раз успели по моей инициативе сходить в «смертельный марш». Что это такое и как оно делается, хорошо описал в своей книге Эдвард Йордон «Путь камикадзе [Смертельный марш]». Я не смог смотреть, как наша компания теряет замечательный и новый рынок, который открывался благодаря изменениям законодательства в сфере розничной торговли.

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

Мой модуль опять стал точкой интеграции множества систем. Ведь наиболее быстро я мог менять свой функционал, а времени было до обидного мало.

Тогда мы успели и заняли какую-то долю нового рынка. Самым важным было зацепиться. Через какое-то время крупные компании вытеснили мелких игроков и увеличили свою долю. Мы были крупной компанией.

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

Весь найм сотрудников шёл через меня. Адаптацией сотрудников, фактически, занимался тоже я. В филиале было много отделов в каждом из которых была команда от 4 до 8 человек. Один отдел принадлежал лично мне. То есть я возглавлял одну команду и половину своего времени ещё и код писал, выполняя роль играющего тренера. Таково было требование компании.

В какой-то момент моя личная команда разработки начала уменьшаться. Ведущие разработчики из неё начали уходить со словами: «Да ну это всё на фиг». Я знаю, что такое bus factor и почему он не должен равняться единице. Поэтому я всегда сам выступал дублирующим носителем знаний. Мог себе позволить.

Когда мой собственный bus factor стал равен единице, я начал поднимать тревогу. И дело не в том, что всем было глубоко безразлично. Сhief-уровень компании сказал «у меня просто нет других людей». А средний менеджмент этому даже обрадовался, это удобно для политических игр и для торговли между собой. Кроме того, чем больше я был занят, тем меньше успевал доставлять им проблем. Например, я не успевал заставлять их работать. Они, кстати, были вне моего подчинения.

Кроме того, чем больше я был занят, тем меньше успевал доставлять им проблем. Например, я не успевал заставлять их работать.

Прошёл год - безразлично стало и мне. Я подумал, что если я сам себя уволю, то уж точно не пострадаю от того, что мой bus factor равен единице. И если всем вокруг на это было всё равно, то зачем я переживаю-то?

В процессе этого всего мы сходили в ещё один «смертельный марш», чтобы вдохнуть жизнь в замерший функционал и выйти на новые рынки. Уже работали объединённой командой нескольких филиалов. Мне пришлось реализовать синхронизацию данных из облака с оффлайн-устройствами. Мастер-мастер синхронизацию. И опять по «требованию генерального директора» были нюансы. Бывает односторонняя синхронизация, бывает двухсторонняя, а у меня была «полуторная». Новые записи от оффлайн устройств принимались через волшебный метод типа «Найти или создать» с нетривиальной логикой работы. А после того, как оно создалось в облаке и потом приехало назад, приходилось зачищать дубли.

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

В процессе реализации этого счастья внезапно выяснилось, что, когда я из базы данных получаю 64 мегабайта данных, мой поток на python падает из-за того, что у него заканчивается 2 гигабайта памяти. Вот так оптимально работал ActiveRecord от платформы на бэкенде. Кроме того, благодаря платформе на бэкенде методы API не могли принимать более 10 параметров, потому что кто-то в коде на C++ написал конструкцию типа: «Если передан 1 параметр, то … Если передано 2 параметра, то … если передано 10 параметров, то...». А мне нужно было больше 10. Вариант с JSON тоже не подходил, всё падало из-за памяти. Кроме того, версия базы данных была старой и там вместо JSON был доступен только hstor.

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

Нет, я решил проблему через интересный SQL-запрос (с оптимальным планом выполнения), который возвращал мне hstor, из которого я делал строку, и ещё в SQL перегонял её в base64. Чтобы когда это придёт из БД на бэкенд, платформа не падала. Потом декодировал уже на python, подменял данные через замены текста в строке, затем опять закодировал (чтобы платформа не упала уже на передаче данных) и передавал на оффлайн устройство.

Я понимаю, всю нелепость и неправильность ситуации, а ещё глубокую сомнительность данных технических решений. Однако, мной было выписано множество ошибок на платформу. Они попробовали сопротивляться и отклонять их. У нас было несколько разборов на Сhief-уровне компании, в процессе которых мне удалось показать, что платформа работает неправильно. Где-то дошло до того, что я просто показывал скриншоты кода платформы на С++, где было сразу же видно, что оно работать не может.

Заведённые ошибки не исправили до моего ухода, прожили они больше года. В компании было правило, что командам с просроченными ошибками не давали премий. Сhief-уровень компании сделал исключения для команд платформы.

Кстати, на рынок мы успешно вышли. Бизнес-цель была достигнута.

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

Генеральный директор — человек смелый, он понимает, что незаменимых людей нет. Есть только стоимость замены. Я бы тоже себя уволил. Руководитель платформы кричал от восторга, когда я увольнялся. Наверное, я был чуть ли не единственным, кто мог заставить их работать. Среднему же менеджменту было безразлично.

Незаменимых людей нет. Есть только стоимость замены.

На самом деле, компания теряла только сильного разработчика и, возможно, его команду. В филиале оставалась очень сильная и слаженная команда руководителей. Потом, после того, как решатся проблемы с площадями, эта команда руководителей в неизменном составе отмасштабирует филиал разработки раз в 5. Этим достижением я горжусь.

Часть моей личной команды ушла со мной. Тот же чудный код синхронизации жил практически неизменным ещё больше года после моего ухода. Нетривиальное API модуля, кстати, тоже.

К чему же всё это?

То, чем занималась моя команда из 5 человек, попробовали отдать другим. Они не справились. Передали второй команде. Они не справились. Передали третьей команде. Они не справились. Пришлось пилить на куски и раздавать по нескольким командам. Путь полный боли и страдания длиной в год-два, не меньше.

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

Говоря честно, виноваты тут совсем не разработчики.

Но именно в руках разработчиков потом всё и рассыпалось. Именно им пришлось что-то делать со сложным и непонятным кодом. Причём не зная истории его создания и не видя кучи взаимосвязей, ведь все носители знаний ушли. У менеджеров тоже знаний не осталось, они же предпочитали все хранить в моей голове. ТЗ они тоже не могли писать, я несколько раз заставил их это сделать, получилось очень плохо.

Научило ли это кого-то чему-нибудь? Да нет, конечно. У генерального директора действительно нет других людей, он работает с тем, что есть. А разработчики в компании и так более, чем сильные.

Подводя итоги

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

Почему всё ломается даже у хороших программистов?

Отдельно скажу руководителям, что нужно опасаться работать с «золотыми шестерёнками». Они всегда вылетают. У них всегда bus factor равен единице. Они классные и по-своему талантливые, но берут за это высокую цену. Часто внезапно. У меня решений по аварийному сбросу из системы золотых шестерёнок нет.

Нужно опасаться работать с «золотыми шестерёнками», они всегда вылетают.

Если вы дочитали до конца и что-то для себя поняли, то спасибо вам.

3333
14 комментариев

Специально зарегистрировался чтобы поаплодировать - настолько хирургически (кардиологически) точно вскрыты и описаны проблемы и боль руководителя R&D

4
Ответить

"Программист: ну, представь, что ты писатель и поддерживаешь проект «Война и мир». У тебя ТЗ — написать главу, как Наташа Ростова гуляла под дождём по парку. Ты пишешь «шёл дождь», сохраняешь, вылетает сообщение об ошибке «Наташа Ростова умерла, продолжение невозможно». Почему умерла? Начинаешь разбираться. Выясняется, что у Пьера Безухова скользкие туфли, он упал, его пистолет ударился о землю и выстрелил в столб, а пуля от столба срикошетила в Наташу. Что делать? Зарядить пистолет холостыми? Поменять туфли? Решили убрать столб. Получаем сообщение «Поручик Ржевский умер». Выясняется, что он в следующей главе облокачивается о столб, которого уже нет..."

Как бы функциональное программирование и ООП это как раз про это?

2
Ответить

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

1
Ответить

Комментарий недоступен

Ответить

Очень хорошая статья, но позволю себе сделать несколько замечаний:
1. Довольно банальное замечание, но "Ломается у хороших программистов" - потому что они что-то делают, не ломается только у тех, у кого ничего нет и они ничего не делают))) "Хороших" отличает то, что у них ломается реже на единицу функционала (не на строчку кода) и самое главное, что у хороших молния не бьет два раза в одно место, отсюда замечание №2
2. В статье довольно часто упоминается, что это какие-то внешние факторы что-то сломали или являлись причинами сбоев. Это действительно так и с кейсами не поспоришь, но упущено главное следствие - что делать, когда такое произошло ("менеджер сказал сделай костыль, а то уволю", "соседняя команда дала сумашедший RPS", "требования поменялись в процессе разработки" и т.д.). Хорошего программиста отличает умение писать премортемы и постмортемы, проводить ретроспективы по крупным задачам/проектам, или по простому учится на ошибках) Тут есть очень тонкая грань - как только ты говоришь что виноват внешний фактор, то перестаешь подстраивать процессы и вероятность повторения стремится к 100%, если же вместо "почему так получилось" задаваться вопросом "а как можно было предотвратить", то все улучшается прямо на глазах)) Все эти не сложные практики позволяют подстраивать процессы под текущие реалии, оставаться гибкими в изменчивых внешних условиях. В конце концов, если руководство совсем невменяемое, то по статистике понять, что теряешь свой скилл и перейти в другую компанию.
3. Мне очень понравился термин "золотая шестеренка", это прямо бомба и теперь буду его использовать, но "нужно опасаться работать с «золотыми шестерёнками». Они всегда вылетают" - звучит как "я не буду с вами работать, вы слишком хороши для нашей компании"))) Лично я утверждаю, что нужно наоборот как можно больше золотых шестеренок, вместе они работают только лучше. Но золотые шестеренки должны быть не только на на позициях инженеров, а и в менеджменте, вплоть до владельца компании. Именно такие компании делают прорывные продукты и изменяют рынок. Без золотых шестеренок компания становится забюрократизированной, так как новшеств она уже не производит, некому, поэтому все идет в сторону стандартизации, структурирования, фиксирования, комитетов и других матерных слов. На самом деле работать с "золотыми шестеренками" достаточно просто, говорю это на довольно большом опыте. Необходимо просто выделить в золотой шестеренке главное в чем он/она хороши, они всегда немного "перекособечены" (отлдичный разраб, плохие софтскиллы, отличный менеджер, ничего не понимает в ИТ и так далее), при этом отличает их зачастую фанатичный свет в глазах и заставлять заниматься их тем, что им не нравится - верный шаг к тому чтобы их потерять. Поэтому просто даешь такой шестеренке фронт работ, который вызывает наибольший интерес и подстраиваешь процессы, чтобы не было негативных факторов, пусть даже полуиндивидуально именно под эту шестеренку. Это даст гигантский буст продукту и команде, ведь если золотая шестеренка среди команды разработки, то именно на него будут равняться остальные, он будет движетелем технологий. Если шестеренка в менеджменте, то его команда будет показывать лучшие результаты и так далее. Так что я бы не опасался работать с ними, а наоборот старался работать именно с ними))

1
Ответить

1. С первым пунктом сложно согласиться. В описанных ситуациях, если ничего не делать, то сломается ещё быстрее. Стоять на месте — тоже ошибка.
1.1. Конечно, молния бьёт дважды в одно место. Если причина возникновения аварийной ситуации свойства внешней среды, то приобретение пострадавшей стороной опыта никак не меняет внешнюю среду. Особенно, в ситуации, когда эту внешнюю среду уже Chief-уровень поменять не может.
2. Тут не ситуации, когда менеджер говорит «сделай костыль, а то уволю». В ходе аварийной ситуации вы рискуете потерять экономическую базу существования разработки/поддержки вообще. Если не будет функционировать бизнес, то прекратится денежный поток. Если прекратится денежный поток, то бизнес не сможет выплачивать зарплату своим сотрудникам. ИТ-специалисты — ровно такие же сотрудники, как и все остальные.
2.1. Если мы говорим о «золотой шестерёнке», то начинаем говорить не о схеме «ИТ-специалист – менеджер», а о схеме «Руководитель – Chief-уровень». Кого там менеджер сможет уволить, если проблемы уже на уровне генерального директора и руководителей департаментов обсуждаются, сложно представить. Там иногда и акционерам-миноритариям достаётся. Менеджера тоже не увольняют, так как у генерального «Нет других людей». И дело не в невменяемости, а в том, что их действительно нет. Из-за чего компания для компенсации жёсткого кадрового кризиса с управленцами начинает переносить вес принятия решений на сторону ИТ-специалистов. Не от хорошей жизни это происходит.
3. Рассматривать золотую шестерёнку, как нечто «перекособоченное», не очень благоразумно. Именно из-за способности эффективно действовать на любом уровне организации золотая шестерёнка становится золотой шестерёнкой. То есть человек может поговорить с разработчиками, указать им на их ошибки, и не дать себя дезинформировать. Аналогично с менеджерами и руководителями среднего звена. Кроме того, золотая шестерёнка понимает бизнес и умеет играть в политические игры. Именно за счёт понимания всей системы разом и высокого потенциала достигается высокая убойная сила.
Выстроить систему на золотых шестерёнках у вас не получится. Во-первых, их мало. Во-вторых, вам им банально будет нечего предложить. В-третьих, у золотой шестерёнки и характер золотой, то есть очень тяжёлый.
Кроме того, вот вы пишите «...Это даст гигантский буст продукту и команде...». А что они с этим то делать будут, позвольте спросить? Быстро решат все задачи и уволятся со скуки? Они лучше поиграют в конкуренцию друг с другом, на открытом рынке, чем будут сидеть без дела в болоте.

1
Ответить

Много букв. У каждой системы есть свой жизненный цикл. И вот в этом главная задача - показать владельцу, что пациент уже мёртв и оперировать его бесполезно

1
Ответить