Оверинжиниринг что это

Как известно, классическая концепция бережливого производства выделяет семь видов потерь, которые сформулировал более полувека назад Тайити Оно, исполнительный директор Toyota. На практике одному из видов потерь уделяется, на наш взгляд, меньше внимания, чем остальным. В разных источниках его называют и трактуют немного по-разному. В российской литературе его чаще называют «излишняя обработка» или «ненужные этапы обработки».
Надо признать, что существуют некоторые разночтения в трактовке этого вида потерь. Некоторые источники обобщают его до любых «потерь процесса изготовления», другие связывают его с «необоснованными методами и средствами производства». Есть авторы, которые все сводят к отсутствию у рабочего некоего стандарта, без которого он якобы выполняет лишние процедуры, видимо, самостоятельно принимая решение о процессе изготовления деталей.
Если учесть, что остальные шесть видов потерь связаны либо с последствиями обработки ( перепроизводство, брак), либо с ее ожиданием ( запасы, пролеживание деталей, лишняя транспортировка, лишние перемещения персонала), то можно предположить, что должен быть как минимум один вид потерь, связанных непосредственно с обработкой.
При широкой трактовке к этому виду потерь отнести любые процессы, которых могло бы не быть вовсе или которые могли бы быть минимизированы: купленное сырье, которое требует доработки, операции, которые можно передать на аутсорсинг, использование станков с излишними технологическими возможностями, излишняя автоматизация, заложенные в конструкцию изделия избыточные свойства и т.д.
Кто важнее инженер или клиент ?
В западной литературе для описания этого вида потерь иногда используется термин Overengineering или Over-Engineering, дословно – «сверхинжиниринг».
Слово «оверинжиниринг» проникло и в русский язык, но пока его чаще используют компьютерщики для обозначение излишне громоздкого ( «индусского») кода. Специалисты говорят, что когда-то индийским программистам платили за строчки написанных ими программ, поэтому они выдавали сложный, объемный, витиеватый код.
Оверинжиниринг в производственном смысле имеет два аспекта:
- изготовление продукта слишком сложным и затратным способом – «из пушки по воробьям»,
- сам продукт может быть сверхинжиниринговым — с более высоким качеством, чем это требуется клиенту, с излишними свойствами и опциями.
С оверинжинирингом не связаны все виды потерь процесса изготовления в соответствии с упомянутой выше их широкой трактовкой. Но зато это явление интересно тем, что его иногда сложно распознать, не смотря на его распространенность. Не всегда просто определить являются ли некоторые свойства продукта или способа его изготовления недостатками или преимуществами.

Слово «оверинжиниринг» замечательно тем, что указывает на роль инженеров в происхождение данного вида производственных потерь.
Причиной оверинжиниринга может быть завышенный перфекционизм при производстве продукта. Самые современные станки, самые передовые технологии, самые лучшие материалы – все это составляет предмет гордости технических работников. Производственники часто не задаются вопросом можно ли сделать процесс проще и применить более простые средства. Спросите оператора, почему он выполняет операцию именно таким образом, и если в ответ Вы услышите: «Мы всегда так делали», — это четкое указание на несовершенство процессов.
Оверинжиниринг самого продукта объясняется недостатком знаний о реальных потребностях клиентов. Продукт настолько хорош, насколько его оценивает клиенты. Но часто клиентов никто и не спрашивает – за них решают инженеры, им кажется, что они лучше знают каким должен быть товар.
Любопытно, что иногда гениальное предвидение технарей действительно формирует будущий спрос. Вспомните появление персональных компьютеров, а затем и смартфонов и роль в этом Стива Джобса. Но в большинстве случаев пренебрежение реальными потребностями клиента и подмена их умозрительными предположениями инженеров приводят к печальным последствиям.
Сила и слабость инженерного подхода
Классическая инженерная страна – это Германия. Сложно представить себе техническую задачу, которая бы оказалась не по плечу немецким инженерам и высококвалифицированным рабочим. Но японцы критикуют немецкую промышленность за то, что она часто рождает монстров – самый тяжелый пресс в мире, самый сложный автомобильный мотор, самые точные, но громоздкие и дорогие станки. И все это, невзирая на цену, а главное — на потребности клиентов.
В книге Джеймса Вумека и Дэниела Джонса «Бережливое производство» целая глава называется «Бережливое производство бросает вызов немецкой традиции». В ней приводится драматическая история фирмы Porsche. На производстве трудились самые квалифицированные рабочие и инженеры Германии, они создавали шедевры автомобилестроения, но без оглядки на потери, в том числе и на оверинжиниринг. В результате прибыль в 10 миллионов долларов, которую компания получила в 1990-1991 годах, в 1991-1992 годах обратилась в 40-миллионные убытки при продажах в 1,5 миллиарда долларов. Легендарная марка оказалась на грани краха.
Слабостью немецкой концепции управления производством авторы называют подмену голоса потребителя мнением инженера. В результате продукт становится все сложнее и дороже. Когда в 90-е годы на традиционные немецкие рынки начали вторгаться восточно-азиатские компании, возникла паника и немцы начали переводить свои производства в страны с дешевой рабочей силой. И только через много лет пришло осознание, что причинами проблем были не только высокие заработные платы квалифицированных сотрудников, но и огромные потери из-за неоптимальной организации процессов.
Как бы ни был далек уровень производства в России от такового в Германии, инженерный уклон и у нас также силен. Локомотивами индустрии в СССР были оборонные предприятия. Во главе «фирм» стояли главные конструкторы, задачей которых было создание «изделий», наилучшим образом выполняющих свои функции, надежность, мощность, многократный запас прочности. Никаких упрощений, унификации, никакой технологичности. Об экономике никто не думал — цена не имела никакого значения.
До сих пор даже в таких мирных отраслях, как наша мебельная промышленность, мы чувствуем отголоски таких подходов:
- купить сложный кромкооблицовочный станок с автоматической быстрой переналадкой, специально разработанный для гибких производств, и поставить его на облицовывание меламином корпусных деталей,
- детали каркаса мягкой мебели обработать с теми же параметрами, что и лицевые детали, только потому, что станок позволяет это сделать,
- заставить ОТК контролировать все размеры, в том числе и не влияющие на выполнение данной деталью своих функций,
- предлагать клиенту столько вариантов цветов фасадов, сколько он не состоянии запомнить, а значит и оценить, только на том основании, что в прошлом были, пусть и единичные, заказы с данным цветом,
- сокращать сроки поставки, хотя клиент готов и подождать.
Высшее образование у нас было в основном инженерное, поэтому нас инженеры работают и в управлении, и в финансах, и даже в дизайне. Именно они являются авторами тех самых навороченных компьютерных столов с множеством полочек и подставок, пугающих своим жуткими непропорциональными формами. А детские многоуровневые кроватки ? Не важно, что дети их побаиваются, а среди полусотни деталей нет ни одной одинакового размера, и что даже с инструкцией собрать такое изделие затруднительно. Зато крепко и надежно…

Как избежать оверинжиниринга ?
Практика показывает, что для различных товаров затраты за счет сокращения функций и свойств, которые не требуются потребителям, могут быть снижены от 10 до 30 %, а иногда и больше. Поэтому вложения в изучение предпочтений покупателей окупаются за счет снижения издержек. Целенаправленные улучшения на основе результатов подобных исследований гораздо более эффективны, чем работа под абстрактным девизом: «Делать все лучше».
Оденьте «очки клиентов» и посмотрите на свои процессы и на сам товар. Может выяснится, что решение о покупке потребитель принимает совсем не по тем причинам, о которых Вы думали.
Посторонние люди со свежим взглядом часто могут быстрее обнаружить признаки оверинжиниринга. Почему бы их не пригласить на производство ? Это могут быть как профессиональные консультанты, так и сотрудники непрофильных отделов своего же предприятия: сбытовики, снабженцы, маркетологи и т.д. Проведите их по производству, разберите с ними новые разработки. Возможно иной угол зрения будет полезен, чтобы не пропустить излишние усложнения.
Выделите в неделю хотя бы один час для борьбы с оверинженирингом — как в цехах, так и при разработке новых продуктов. Не допускайте запуск изделий в производство без уверенности, что они с минимальными затратами приносят пользу покупателям.
10 ошибок, приводящих к оверинжинирингу ПО
Несколько вещей гарантированно будут увеличиваться со временем: расстояния между звёздами, энтропия вселенной и бизнес-требования к ПО. Многие статьи пишут «Не усложняйте!», но не пишут почему или как это сделать. Вот вам 10 ясных примеров.
1. Инженерам виднее
Мы, инженеры, считаем себя умнейшими людьми. Ну, поскольку мы создаём разные штуки. И эта ошибка часто приводит к оверинжинирингу. Если вы спланировали и построили 100 модулей — Бизнес всегда попросит у вас 101-ый, о котором вы никогда не задумывались. Если вы соберётесь с силами и решите 1000 проблем — они придут к вам и выложат на стол 10 000 новых. Вы считаете, что у вас всё под контролем, а на самом деле вы даже не представляете, в каком направлении вас завтра поведёт дорога.

За мои 15 лет работы программистом я ещё ни разу не видел, чтобы Бизнес выдал законченные и стабильные раз и навсегда требования к ПО. Они всегда меняются, расширяются. И это природа бизнеса, а не ошибки людей, управляющих им.
Мораль: Казино (бизнес) всегда побеждает.
2. Повторное использование бизнес-функционала
Когда Бизнес подкидывает нам всё больше и больше требований (как и ожидается), мы иногда говорим себе: «Ок, давайте попробуем сгруппировать и обобщить всё, что только можно!».

Вот почему большинство MVC-систем заканчиваются Большой Моделью или Жирным Контроллером. Но, как мы уже выяснили, бизнес-требования никогда не прекратят добавляться, а значит это путь в никуда. На самом деле нам нужно реагировать на это вот так:

Пример: однажды для одного из заказчиков мы разрабатывали модуль профиля пользователя. Начали с классического CRUD-контроллера, ну потому что это же просто профиль пользователя и там всё должно быть просто. Закончилось это всё реализацией 13 различных сценариев создания и заполнения этого профиля: регистрация через социальную сеть, обычная, упрощённая, быстрая с последующим редактированием, совсем иначе выглядящая для подсайтов, и т.д. Они имели между собой очень мало общего. Аналогично отличаются и, например, сценарии «просмотр заказа» и «редактирование заказа».
Попробуйте для начала разделить бизнес-функциональность вертикально, прежде чем делить её горизонтально. Это даже делает более простой задачу разделение монолита на микросервисы. Иногда и вовсе уже становится всё-равно монолит у вас или сервисы. В противном же случае становится всё сложнее и сложнее изменять части вашей системы.
Мораль: Предпочитайте изолированные действия, избегайте комбинирования.
Совет: Возьмите некоторую видимую пользователю часть вашей программы (форму\страницу\команду). Сколько переключений контекста понадобиться программисту, чтобы понять весь код, связанный с ней?
3. Обобщим вообще всё
- Нужно подсоединиться к базе данных? Давайте напишем Обобщённый Адаптер.
- Сделать запрос? Обобщённый Запрос.
- Передать ему параметр? Обобщённый Параметр.
- Собрать несколько параметров во что-то? Обобщённый Builder.
- Отразить полученный результат во что-то? Обобщённый Data Mapper.
- Обработать запрос пользователя? Обобщённый Запрос.
- Что-то выполнить? Обобщённый Исполнитель.
- и т.д.
Иногда инженеров заносит. Вместо решения бизнес-проблем они тратят время для выбора правильного родительского класса. А ответ прост.

Архитектура ПО всегда играет в догонялки с требованиями бизнеса. Так что даже если вы с помощью какой-то магии найдёте идеальную абстракцию сегодня, в комплекте с ней сразу будет идти срок её годности — см. пункт №1 выше — бизнес всегда побеждает. Так что лучшая характеристика качества сборки вашей архитектуры — как быстро она может быть разобрана. Есть отличная статья о том, как писать код, который будет легко удалить, а не легко изменить.
Мораль: Дублирование кода лучше, чем неверная абстракция.
Более того, дублирование кода иногда помогает найти ту самую правильную абстракцию. Потому, что когда вы видите несколько частей системы, использующий одинаковый код одинаковым образом — вы можете понять, что их объединяет. Качество Абстракции определяется качеством её слабейшего звена. Дублирование кода позволяет взглянуть на разные ситуации под разными углами и увидеть границы Абстракции чётче.
4. Написание обёрток для всех внешних библиотек
Существует практика написания обёрток (врапперов) для каждой используемой внешней библиотеки (в основном из-за следования стилю основного продукта, иногда из-за причин, описанных в предыдущих двух пунктах). Очень популярный подход в энтерпрайз-программировании. Программисты на динамических языках вроде Node/Ruby/Python просто добавляют библиотеку и начинают её использовать. Но Энтерпрайз Разработчик на это пойти не может — ему необходимо создать обёртку. А потом ещё обёртку над обёрткой. Возможно, это имело какой-то смысл в 2000-ых, когда большинство библиотек представляли собой мешанину, да и вообще открытого кода было не так много.
Но сегодня уже 2016-ый год. Внешние библиотеки улучшились на порядок. Они стали просто фантастичны. Скорее всего они написаны отличными программистами и оттестированы лучше вашего основного кода. Они имеют внятный API. В них можно встроить логирование. Вам не нужно тратить своё время на написание обёрток вокруг и так уже хорошего кода. Кроме того, большинство обёрток — совершенно бессмысленны. Их интерфейс очёнь тесно связан с лежащей ниже библиотекой, часто просто в виде отражения функций «один к одному». Если в будущем библиотека измениться, большинство кода с использованием данной обёртки также придётся изменить. Создание «агностической» обёртки, способной остаться неизменной даже, например, при полной замене оборачиваемой библиотеки на другую — нетривиальная задача. Такие задачи иногда ставятся с мыслью о потенциальной «конфигурабельности» общего решения, сама идея которого будет рассмотрена чуть ниже.
Мораль: обёртки должны быть исключениями, а не нормой.
5. Слепое применение метрик качества кода
Бездумное следования концепциям качества кода (вроде того, что все переменные должны быть объявлены как «private final», каждый класс должен иметь интерфейс) не сделает ваш код АВТОМАТИЧЕСКИ хорошим. Посмотрите, если ещё не видели, на энтерпрайз-версию FizzBuzz или Hello World. Прорва кода. На микро-уровне каждый класс следует принципам SOLID и использует отличные паттерны. Если вы натравите на этот код какой-нибудь инструмент анализа качества кода — он скажет, что это прекрасный продукт, прямо загляденье. Но если вы сделаете шаг назад — то сразу увидите каким кошмаром является эта программа, всего лишь печатающая «Fizz Buzz».
Мораль: всегда делайте шаг назад и смотрите на общую картину.
Аналогично, автоматические средства хорошо определяют тестовое покрытие кода, но совершенно ничего не говорят о том, тестируете ли вы то, что нужно, или нет. Они могут измерить производительность в некотором тесте, но ничего не скажут насколько хорошо ваша программа обрабатывает данные в другом случае. Все они смотрят на микро-уровень: что делает этот класс\метод\строка. И только Человек смотрит на общую картину.
Выучите другой язык программирования и попробуйте другие подходы для решения уже известных вам задач. Это сделает вас существенно лучшим программистом. Не зацикливайтесь на чём-то одном.
5.1. Слои сандвича
Давайте возьмём некоторый тесно связанный функционал и разделим его на 10-20 слоёв, где каждый слой не имеет никакого смысла без остальных. Ну, потому что мы хотим реализовать концепцию «Тестируемого кода», или «Принцип единой ответственности», или назовите это ещё как-нибудь модно. В прошлом это делалось через наследование. Класс А наследуется от Б, который наследуется от С и т.д.

Сегодня люди делают всё то же самое, кроме того, что каждый класс теперь представляется парой интерфейс/класс и инжектируется на следующий слой, потому что у нас же SOLID.

Мораль: концепции требуют вдумчивого применения. Их нельзя применять просто везде и всегда, как инструменты.
6. Синдром Новинки
Изучили дженерики. Теперь у нас простой «HelloWorldPrinter» станет «HelloWorldPrinter<String,Writer>».
Не нужно использовать дженерики, когда реально необходимая форма будет всегда инстанциироваться одними и теми же типами данных. Параметров достаточно в большинстве случаев.
Изучили паттерн Стратегия. Теперь все операторы «if» будут стратегией.
Почему?
Научились писать DSL. Теперь у нас DSL будет везде и для всего.
Ну я даже не знаю…
Обнаружили моки. Теперь у нас будет замокано всё вдоль и поперёк.
Да ну как же…
Метапрограммирование — шикарная вещь, давайте используем здесь и здесь!
Объясни зачем…
Методы расширения\концепты\что-то ещё — хорошая штука, давайте будем использовать кругом!
А давайте не будем!
Мораль: ничего не надо применять везде и всегда. И раздел «Мораль» тоже не надо бы писать в каждый пункт.
7. «X–сть»
- Конфигурабельность
- Безопасность
- Масштабируемость
- Поддерживаемость
- Расширяемость
- .
Расплывчато. Неизменно. Трудно поспорить.
Пример 1: Давайте создадим CMS, чтобы клиент смог сам добавлять поля вот в эту форму.
Результат: Клиенты никогда не будут ею пользоваться. Когда понадобятся — они найдут разработчика и озадачат его. Возможно вместо полноценной CMS стоило набросать короткую инструкцию о том, как быстренько добавить поле.
Пример 2: Давайте спроектируем большой слой для работы с базами данных, для упрощения «Конфигурабельности». Мы должны получить возможность сменить базу данных правкой одного конфиг-файла.
Результат: За 10 лет работы я видел лишь один проект, где понадобилось менять одну базу данных на другую по объективным причинам. И, когда до этого дошло дело, то «правкой одного конфиг-файла» дело совсем не обошлось. Была масса сопутствующей работы. Несовместимость, пробелы в функционале. А ещё однажды клиент попросил на перевести ПОЛОВИНУ наших моделей данных в новую NoSQL базу данных. У нас был «магический файл» с подключением базы данных, но во-первых, только реляционной, а во-вторых для всех данных, а не для половины. Возможно все эти пляски с конфигурабельностью имеют смысл, когда речь идёт о чём-то вроде Оракловской базы данных, которая стоит как найм 20-ти программистов — там и правда удобно иметь возможность переключиться на что-то другое при необходимости. Но для современных баз данных, всё что нам необходимо — это простой набор вертикальных DAO-классов вместо широкого горизонтального слоя ORM. Не существует единой модели, удачно сочетающей в себе SQL и NoSQL, так что, возможно, нам действительно стоит их разделять, используя в каждом случае то одно, то другое, вместо того, чтобы пытаться совместить несовместимое и городить ужасные неверные абстракции.
Пример 3: Мы построили систему OAuth-авторизации для энтерпрайз-клиентов. Для администраторов этой системы нас попросили добавить ещё один уровень — авторизацию администраторов через Google OAuth. «Потому, что должно быть безопасно». Если кто-то взломает нашу OAuth-авторизацию, нужно чтобы хотя бы учётки администраторов остались недоступны. Google OAuth — надёжная штука, так что возражать тут вроде бы особо нечего.
Результат: Тому, кто захочет взломать данную систему совсем не нужно пробиваться через OAuth-слой. Можно найти уязвимость в чём-нибудь попроще (такие всегда есть). В итоге все затраты на поддержку двух уровней OAuth (а они проходили насквозь через всю систему) дали примерно никаких результатов. Лучше было потратить это время на устранение обычных уязвимостей.

Мораль: Не принимайте все эти характеристики с окончанием на «-сть» как неизменную данность. Они имеют свою цену — так что чётко определяйте Сценарий\Историю\Использование.
8. Велосипедостроение
- Свои библиотеки (HTTP, мини-ORM, кеширование, конфигурация)
- Свои фреймворки (CMS, обработка событий, многопоточность, фоновые задачи)
- Свои инструменты (система сборки, система деплоя)
- Тривиальные, казалось бы, задачи на самом деле требуют приличных знаний и глубокого погружения в предметную область. Какой-нибудь «запускатель процессов» требует понимания менеджмента процессов в ОС, работы демонов, системы ввода\вывода и ещё кучи всего. CMS — это не просто что-то, подставляющие данные в шаблоны — там есть зависимости, проверки, визарды, обобщения и т.д. Самая простая на вид библиотека может иметь нетривиальную функциональность.
- Всё это нужно ещё и поддерживать, обновлять.
- Если вы выложите код в открытый доступ — всем будет плевать. Ну, может, кроме тех, кто работал над этим кодом раньше.
- Люди, которые разбираются в этом коде — рано или поздно уйдут. А кроме них в этой реализации не разбирается никто в мире.
- Внедрение в проект уже существующих библиотек и фреймворков, заточка их под ваши нужды требует время прямо сейчас. Но изобретение собственных велосипедов требует куда больше времени в долгосрочной перспективе.
Мораль: Переиспользуйте. Заимствуйте хорошее. Пересматривайте свои решения.
Если вы всё-же решили строить свой велосипед — по крайней мере делайте его по принципу «внутреннего опенсорса» в своей компании. Объясните людям, зачем это нужно. Покажите первый набросок. Предложите им использовать или улучшать это. И подумайте 10 раз, стоит ли продолжать строить этот велосипед, если даже ваши коллеги не выскажут своего одобрения.
9. Развивайте свой код
Как только вы реализовали что-нибудь определённым образом — все остальные начинают это использовать в том виде, в каком это реализовано. Никто не задумывается, правильно ли это. Пока ваш код работает — это «хороший код». Люди начинают применять его даже для задач, которые он изначально не должен был решать. Получается иногда хорошо, а иногда очень плохо. И тут нужно не бояться брать и менять ваш код, совершенствуя его под текущие задачи. Здоровые программные системы всегда живут, меняются. Нездоровые — лишь дополняются. Если кусок кода не видел коммитов очень давно — с ним что-то не так, он «попахивает». Каждая часть кода должна развиваться. Вот отличная статья, описывающая это.
Вот как команды работают над задачами, а вот как они должны это делать, Каждый День:

Мораль: рефакторинг — это часть любой разработки. Никакой код не остаётся неизменным.
10. Неверные оценки сроков
Часто мы видим, как неплохие вроде бы команды или отдельные кодеры вдруг выдают откровенно слабый продукт. Мы смотрим на кодовую базу и удивляемся — «Как же так, неужели это было действительно создано этой командой\человеком, а я же считал их\его такими умными\умным!». Качество требует не только умения, но и времени. Даже умные разработчики часто переоценивают свои возможности. И вдруг обнаруживают себя перед горящим дедлайном, мучительно вписывающих в код ужасный костыль, дающий шанс как-то уложиться в сроки.
Мораль: неверная оценка сроков наносит вред качеству вашего проекта ещё до того, как написана первая строка кода.
/dev/energy
Сайт о том, как стать программистом и как с этим жить потом
Вам не нужна вся эта инфраструктура
Кажется, предыдущая статья буквально взорвала мой блог. Честно говоря, ни одна статья ещё не вызывала такую бурную реакцию. Это не может меня не радовать, а я хочу поблагодарить всех, кто принял и примет участие в обсуждении!
Я обратил внимание на то, что в комментариях многие подняли тему неуместности применения некоторых технологий и подходов. И по счастливому стечению обстоятельств на Medium.com я наткнулся на статью, которая во многом отражает и моё понимание проблемы оверинжиниринга в проектах средней руки. А потому я с удовольствием спешу поделиться переводом этой небольшой неоднозначной статьи и своими комментариями.
Как Вы запускаете свои web-продукты?
В кластере Kubernetes? Балансировщики нагрузки между географически распределенными облаками? Полностью автоматизированное, сине-зелёный деплой, основанный на метриках, получаемых в реальном времени из пайплайна самого деплоя?
Это всё очень здорово. И если Вы проводите много времени на Хабре или читая свежие статьи от DevOps-волшебников из фирм FAANG, Вы убеждены, что все предлагаемые там вещи абсолютно необходимы для вашего сайта. Но всё это сущий кошмар. Установка всего этого — огромная трата времени. И если Вы не хотите устанавливать и настраивать всё это самостоятельно, то это ещё и ужасно дорого. И даже тогда это все ещё кошмар, а Вы только что заплатили за то, чтобы им обладать.
Есть ли хорошие новости?
Вам всё это не нужно *.
(* вообще-то кое-что нужно … но точно гораздо меньше, чем Вы думаете)
YAGNI
В Twitter Питера Левелса (Pieter Levels) — многократного победителя в номинации «Охота за продуктами года», основателя увеличивающегося списка сайтов, приносящих тысячи долларов дохода в месяц, и в основном бога сообщества инди-создателей — спросили, какую инфраструктуру он использовал для размещения всех своих безумно успешных инди-проектов.
Я не говорю о том, что отлично знаю, какая инфраструктура крутится у Питера на самом деле. Но я почему-то уверен, что там нет сложных скалируемых групп, нет парка дорогих облачных серверов или сложных кластеров Kubernetes.
Ваша цель при запуске продукта — построение продукта, который будет решать проблемы Ваших пользователей. Не строить крутейшие пайплайны развёртывания, или мультизональные геораспредлённые облачные защищённые от ядерной зимы высокодоступные сервера. Я как-то встретился с идеей о том, что каждая минута, потраченная на инфраструктуру — это минута, не потраченная на доставку пользователям новых возможностей. Очевидно, это не стопроцентная истина; Вы не можете доставлять функционал пользователю, если у Вас нет сервера или какого-либо способа перенести свои функции на Ваш сервер (и, желательно, хотя бы ненадолго оставить их там). Но это неплохая идея сама по себе. Вам нужна самая простая и минимально трудоемкая инфраструктура, которая поможет Вам достичь цели.
Когда я строил свой сайд-проект Curated Design Boutique, я потратил часы, устанавливая простые и бесплатные средства непрерывной интеграции и доставки и настраивая пайплайны в них. По коммиту в Git Semaphore CI собирает Docker-образ, загружает образ в реестр контейнеров, затем отправляет его и перезапускает контейнер на моём сервере. Это реально круто. Я чувствовал себя волшебником, когда всё это заработало … и всё это бесплатно! Вообще-то, я хотел написать о том, как сделать такую же сборку самостоятельно, пока не осознал, как много времени я потратил на то, чтобы это получить и какую ценность я доставил этим пользователям (в конце концов: как много денег я получил на свой банковский счёт) — полный ноль. Разумеется, автоматическая сборка и выгрузка в реестр — это великолепно! Это спасает меня от часто повторяющихся ошибок. Но действительно трудоемкой и ненадёжной частью системы было автоматическое развертывание. Запуск сценария `docker-compose` на моем сервере вручную ничего не стоит (и я обращаю на это внимание, поэтому мне не нужна дополнительная инфраструктура автоматического мониторинга, которая будет говорить мне, когда я все испортил).
Вашим пользователям неважно, как Ваш код попадает на сервер. 99.9% времени им также неважен Ваш крутой высокодоступный набор систем. Понятно, если Вы находитесь на уровне FAANG или являетесь авторитетным источником, где 0,1% простоя приводят к огромным потерям денег на Вашем счёте, всё это прекрасно. У Вас есть средства, чтобы сделать всё «правильно». Ваша крутая полностью автоматизированная CD система экономит Вам тысячи, а то и миллионы долларов в год. Но масштаб простого разработчика (“Эй, посмотрите какую крутую штуку я построил… пожалуйста, ну, пожалуйста, посмотрите на неё”) — масштаб огромного количества сайтов в сети Интернет — эта 0.1% пренебрежительно мала.
«Инженеры отвлекаются на вещи, которые волнуют инженеров, а не решают реальные проблемы для пользователей» — мы слышали всё это раньше. И это не шокирующее откровение. Но, похоже, широко распространено мнение, что Вы не можете запустить продукт без одного или двух кластеров Kubernetes, с балансировкой нагрузки в нескольких регионах, и если Вам придется что-то разворачивать вручную, то как Вы вообще можете ожидать получения прибыли?
Короче говоря, воплощая следующую идею Unicorn-проекта в код, помните — Вам не нужна вся та инфраструктура, которую вы запланировали.
Комментарии к статье
При невдумчивом чтении статья может сформировать очень категоричный взгляд на вещи, вплоть до выкатки кода методом копирования файлов по FTP вручную («ну а чё, работает же!»). Автор довольно мало внимания уделил вопросу правильного определения достаточности выбираемых решений на том или ином проекте. Хотя, и статья не про это, а про старый добрый YAGNI.
На моей практике встречалось много проектов, которые при скромном охвате показывали и показывают амбициозные подходы к архитектуре. Это и кластеры из нескольких мощных серверов, которые обслуживают несколько сотен заказов в день, и приватные облака, единственной задачей которых является разворачивание довольно статичных монолитов опять же — при сравнительно небольшой нагрузке на систему, и команды из четырёх разработчиков, пишущих на восьми языках программирования. Я сам до сих пор не понимаю, к чему нужен этот IT-кич.
Многие вещи действительно можно построить гораздо проще. Только не надо путать «проще» и «тупее». Если построить систему, которая постоянно меняется командой разработки, и не предусмотреть в ней версионирования, то это усложнение, а не упрощение. И в наше время довольно сложно вовремя себя остановить в выборе технологий и понять, что следующий шаг будет избыточен.
Переводя эту статью, я бы хотел написать здесь о своём видении того, какие инструменты на каком уровне нужны. Но потом переосмыслил это желание и понял, что и здесь вместо отсутствующей серебряной пули решения помогать будет только опыт, основанный на успехах и уроках, вынесенных из ошибок.
Ни в коем случае не надо отрицать всё новое, модное и крутое. Но нужно относиться к нему с осторожностью. И если Вы работаете в компании средней руки (давайте на чистоту — таких гораздо больше, чем тех же FAANG), дождитесь, пока технология и её понимание созреют, прежде чем, очертя голову, бросаться в реализацию прекрасного нового мира.