Мы часто задумываемся о том, что нужно изменить, чтобы наша жизнь стала лучше. Но меняться должны не только мы, но и компании, в которых мы работаем. И мы сами можем принимать непосредственное участие в этих положительных изменениях. Вас ждёт маленькая сказка про одну компанию, которая смогла стать лучше. И, конечно же, большие выводы.
— Привет. Меня зовут Андрей Мелихов, и сегодня я попробую выступить в не совсем привычном для себя жанре. Я расскажу вам небольшую сказку. А начнем мы, как водится, с присказки.
![](https://habrastorage.org/r/w780q1/webt/he/na/ke/henakehvelvndseyt50pnggywe0.jpeg)
Давным-давно я был на одной замечательной конференции. Прекрасная конференция, к сожалению, больше не проводится. Был на ней спикер, который рассказал, как он пришел в новую компанию. И эта картина мне настолько в голову запала.
![](https://habrastorage.org/r/w780q1/webt/9f/wd/_g/9fwd_grtmuum057qvpniag9ag-y.jpeg)
Итак, приходит он в новую компанию и видит, что на стене логотип компании, на котором новогодние украшения. На дворе — 2 августа. Рядом кто-то заваривает «Доширак». И в целом атмосфера запустения и нежелания что-то делать дальше.
А пришел он из другой компании, которая была весьма успешной. И очень ему назад захотелось. Подошел он к своему новому начальнику и говорит: «Отпусти ты меня домой?» А тот ему отвечает: «Ты сюда пришел, не чтобы жаловаться, а чтобы всё изменить».
Итак, жил-был Вася, работал этот Вася в стартапах. И тут позвали его в одну самую лучшую компанию, о которой он мечтал много лет.
Мечтал туда попасть и вдруг попал. Это и прекрасный большой офис в городе, прямо в центре города. Всё отлично, кофепоинт, все плюшки, всё, что надо.
![](https://habrastorage.org/r/w780q1/webt/sz/ox/7x/szox7xdss3bkqudgwdt16ydyyvw.jpeg)
Но как только он заглянул в технологии, с которыми компания работает, то увидел, что технологии-то неплохие, да далеко не новые. Совсем не то, с чем он мечтал работать. Вздохнул Вася грустно: ну ладно, жить можно, разберемся.
Повели его в кабинет. А кабинет находился не на том этаже, где он проходил собеседование. Зашел он в кабинет — кабинет, полный народу. И в углу стол стоит, который ему выделили. Ладно, много людей, не так красиво, как было в стартапе, но ничего, с этим тоже справимся, подумал Вася и сел за свой стол. Стол был маленький, настолько маленький, что монитор Васи стоял на столе соседа, а монитор соседа стоял на столе Васи, а иначе не помещалось. Ну ничего, с этим тоже можно справиться, подумал Вася и включил ноутбук.
А ноутбук был бывалый, на Windows, неубиваемый. Просто прекрасный, но на Windows. В те годы — знаете, это происходило много лет назад — Windows совсем не подходил для веб-разработки. Сейчас с этим уже можно как-то жить, а тогда — нет. Ну ничего, виртуалки помогут, справимся, подумал Вася. Мониторчик плохой на ноутбуке, ужасный, маленький, ничего не видно. Ничего, дали внешний монитор, будем жить с ним.
А внешний монитор ему дали просто волшебный. Под каким углом на него посмотришь, такие цвета и видишь. И такой монитор дали человеку, в чьи обязанности входила в том числе и вёрстка. Грустно. Чтобы шея не уставала, подложил Вася два томика Страуструпа под монитор. Стало получше. Ладно, справимся, подумал Вася, и, наконец, загрузилась операционная система. Открыл он почту…
![](https://habrastorage.org/r/w780q1/webt/sb/bf/hs/sbbfhswvhkfjkh6trxtjvnojb94.jpeg)
И увидел, что в этой компании принято писать очень много писем. А еще в этой компании принято проходит код-ревью в почте. Как это? А вот так. Не было у них ни GitLab, ни Bitbucket, ни GitHub. А просто брали они diff и отправляли его по почте. А потом люди начинали кусочки этого diff комментировать. И ладно, если бы комментировали про код. Очень много обсуждений было про то, что поставил пробела два, скобочки не поставил, где надо, точку с запятой забыл. И вот этим была забита почта.
Ну что, страшно? Уже очень страшно, но еще можно жить. И тогда Вася посмотрел в код. А код этот был, как водится у компании, которая не первый год работает, — монолитом. А монолит — это не только то, что все команды в одном коде работали, но и то, что все было жестко сцеплено. Не понятно, кто за что отвечает, циклические зависимости, все ужасно. Но не так ужасно, как то, что в этом коде еще и Node-модули лежали закоммиченные. А почему?
А потому, что нельзя код наружу отдавать. «Нельзя код, который мы пишем, — сказали Васе, — наружу вынести. Ведь завтра там что-то сломается, а мы релиз не соберем». Однако, подумал Вася. Не знают, что ли, люди о том, что можно локально держать код? И решил поговорить об этом с тимлидом. Пошел он к тимлиду. Был ли тимлид? Был тимлид. Да вот только занимался тимлид тем, что релизы собирал.
![](https://habrastorage.org/r/w780q1/webt/gc/fz/oz/gcfzozaiqekvhqv2frxk7rghil4.jpeg)
И ладно, собирается релиз минут 40, так ведь к нему еще надо заполнить очень много бюрократии. Зайти в Confluence, завести страничку. В страничке расписать по строчкам, что у нас в этом релизе катится, какие задачи в него попали. Создать задачи на QA. Как только QA задачу проверят, создать задачу на админов. Как только админы выкатят — написать, что все хорошо. На это убьешь еще час. Два релиза за день, вот и вся работа тимлида. Некогда ему еще чем-то заниматься — релизы катить надо.
![](https://habrastorage.org/r/w780q1/webt/0k/kj/10/0kkj10hl_no4ju3mjtl_dghh0y4.jpeg)
Понял Вася, что у него два пути: уйти из этой компании или все-таки что-то поменять. Пошел он в магазин и купил себе нормальный монитор, просто чтобы глаза свои пожалеть. Дальше пошел он к админу и попросил ноутбук, хоть какой-то, но не на Windows. Нашли ему старенький MacBook, с этим уже можно было работать. Раз к нему хотя бы в этом по-человечески отнеслись, понял Вася, то можно здесь еще что-то поменять.
И начал он потихоньку менять. И оказалось, что не один Вася в этот момент пришел в компанию. Пришло очень много новых людей, которые знали, как оно может быть: не как было, а как в других, молодых компаниях. И люди это были от топов, до самых младших. И все они меняли, каждый по чуть-чуть. Вместе они навалились, и все стало лучше. Появилось в компании что-то нормальное.
![](https://habrastorage.org/r/w780q1/webt/cf/-6/ig/cf-6igaokspyvakcbp98zr2zqme.jpeg)
Код в Bitbucket стал лежать, автоматизацию стал Jenkins делать, все зависимости уехали в Nexus, релизы тоже, появился docker. Тимлид делом занялся. Наконец-то у него появилось время, чтобы взглянуть на своих людей. Он начал проводить встречи one-to-one, понял, где, у кого и что болит. Команды начали переставлять местами. Зарплаты изменились. Все стало гораздо лучше.
![](https://habrastorage.org/r/w780q1/webt/i3/ad/ye/i3adyehdcywwyxd_5-9czpqzxew.jpeg)
Конец ли это сказки? В нашей сказке это конец. Но на самом деле здесь есть еще много чего менять. И, наверное, компания, в которой Вася остался работать, еще многое изменит, станет лучше.
Давайте теперь посмотрим, что же мы можем изменить в той компании, где мы работаем, если у нас все плохо.
Я составил несколько советов, которые мы и рассмотрим по порядку.
Итак, нужно избавиться от хаоса, потому что люди часто боятся энтерпрайза, но в энтерпрайзе есть очень важная черта. В энтерпрайзе всегда настраивают процесс, просто чтобы хаоса было меньше. Чем больше твой продукт, чем он дороже, тем это важнее.
Что мы можем изменить в процессах? Во первую очередь нужно избавиться от того, что все делают всё и мы никогда не знаем, кто конкретно что-то делает. Выделенные команды с понятной зоной ответственности нам это дают: мы знаем, когда что-то сломалось, можем подойти вот к этим ребятам и они это починят.
А чтобы им было удобнее работать, нужны микросервисы или микрофронтенды. Вспомним закон Конвея, который говорит, что каждая организация стремится в архитектуре отразить свою структуру. То есть нужно каждой команде дать кусочек кода.
![](https://habrastorage.org/r/w780q1/webt/tr/kt/ik/trktikynos6c-xnbdxd2j8u6vds.jpeg)
Мы возьмем наш сложный монолит и разобьем его на отдельные части. Каждая команда будет отвечать за свою часть. И им будет проще. Они смогут релизиться, не затрагивая других. Они смогут лучше знать свой код, потому что он не переплетен с чужим кодом. Мы разорвем эти порочные связи, которые были у нас изначально, и у нас наконец-то начнет получаться нечто более красивое.
Ладно. Что еще можно добавить? Правила ветвления кода. Очень часто мы сталкиваемся с тем, что в компании нет никаких правил. Люди просто создают какие-то ветки, как-то это назад вливают. Главное, что есть одна ветка, с которой они как-то собирают релизы, но никаких правил нет. Поэтому рассмотрим два популярных варианта.
![](https://habrastorage.org/r/w780q1/webt/vr/c7/vi/vrc7vivdcq3fy-thuxn2i8egkau.jpeg)
Более старый, но известный — GitFlow. Посмотрим, что это.
GitFlow говорит нам, что нужно завести две ветки — master и dev — и работать с ними. Все разработчики работают с веткой dev. Они не имеют права туда коммитить напрямую. У нас есть только механизм ветвления и пул-реквест.
Итак, мы делаем задачу, ответвляемся от ветки dev, делаем коммиты по нашей задаче. Эта ветка называется feature-ветка, или feature branch. Как только мы решили, что все доделано, тестировщик проверил, мы создаем пул-реквест и вливаемся обратно в ветку dev. Как только мы захотим релизиться, мы с ветки dev срезаемся и получаем релизную ветку.
В этой релизной ветке снова проходит тестирование, и если нашли какие-то проблемы, вносят исправления. Появляется еще коммит в релизной ветке.
Дальше, если все хорошо, мы вливаем релизную ветку в master. Это наша версия 2.0, которую мы и отправляем в продакшен. И одновременно доставляем этот код назад в dev. Теперь наш dev равен мастеру и все могут работать дальше.
Чем хороша эта система? В ней нам всегда понятно, что делать.
Вот очень сложный кейс: нам нужно быстро зарелизить hotfix. Все очень просто.
![](https://habrastorage.org/r/w780q1/webt/st/zk/gw/stzkgwmzmwftvpxzeozaq3hfknc.jpeg)
Мы с ветки master, предыдущей версии, срезаем веточку, которая теперь у нас называется hotfix. Делаем в ней исправления. Вливаем назад в master и релизимся. Это наша версия 1.1, которую мы, конечно же, отправляем в dev. Чтобы наш код доехал в dev, наши релизы тоже должны пересобраться, переподтянуть наш dev. Но в целом все будет хорошо.
Таким образом мы можем очень быстро внести исправления и при этом не подтянуть новый код, который появился в dev с момента прошлого релиза. Мы сделаем только hotfix на конкретное состояние релиза.
Здесь вы можете увидеть, что ветка master становится несколько редуцированной. Мы можем от нее избавиться и превратить наш dev в master. Такая схема и называется GitHub Flow, давайте на нее посмотрим.
![](https://habrastorage.org/r/w780q1/webt/aa/sp/qe/aaspqe751udopcxpwbipwhvqt0o.jpeg)
Когда уже нет отдельной ветки master, это значит, что наш dev переименовался в master. Получается, что наш релиз идет из dev, но опирается на теги. Мы у каждого релиза проставляем теги и всегда можем срезать hotfix с тега. В остальном это тот же самый GitFlow.
Все это отлично автоматизируется, с этим удобно работать. Вот такие у нас есть правила ветвления кода, если мы хотим избавляться от хаоса.
![](https://habrastorage.org/r/w780q1/webt/vv/fe/gu/vvfegufpz-v86dt9j4tfhpltrxu.jpeg)
Что мы еще можем сделать? Добавить обсуждение наших решений. Почему это важно?
Потому что люди собираются вместе, еще не написав ни строчки кода. И те, кто хотят написать новые строчки кода, доносят свои идеи. Две головы лучше, чем одна, а четыре головы лучше, чем две. И те, кто, возможно, разбирается в другом участке кода, могут сразу сказать, что пойдет не так. Поэтому обсуждения до того, как код будет написан, так важны. Документация пишется после того, как код написан. Она тоже важна — чтобы понять, зачем все это было сделано. И, конечно, само архитектурное решение должно быть задокументировано до реализации, и на него можно будет опираться.
Хорошо, мы немножко разгребли хаос, который творился у нас в компании. Что дальше? Мы скажем «нет» рутине и добавим автоматизации. Потому что мы же ленивые люди, любим все автоматизировать. А что можно автоматизировать? Конечно, надо разобраться с код-ревью. Не должно быть споров о том, что здесь пробел не поставили или еще что-то. Код-ревью должно быть автоматизировано. Как это сделать?
![](https://habrastorage.org/r/w780q1/webt/xg/8r/qu/xg8rquwrr-zboycaee8jutqr2jc.jpeg)
Отдадим весь код-стайл линтеру. Пусть линтер проверит. Если все хорошо, только тогда люди будут смотреть в этот код. Пусть заранее исчезнут все спорные вопросы, их решит линтер.
Мы хотим видеть, что все это работает, что тесты не сломаны. Пусть это будет в интерфейсе. Пусть в тулзах, где мы делаем код-ревью, будет сразу показано: тесты прошли отлично, и никаких вопросов к тому, что с тестами что-то не так, уже не возникнет.
И мы не должны разрешать вливать код, который не прошел QA. Почему это важно? Потому что dev должен оставаться рабочим. Если человек вольет туда что-то сломанное, мы можем этого не заметить. Мы можем об этом спорить, но QA нам скажет, что он, как минимум, все кейсы уже проверил и оно работает. Мы должны это понимать, это должно быть не на словах, а запрещено автоматически.
Еще одна очень полезная вещь — политика вычисления ревьюверов. Это либо рандом, либо можно определить, какие люди коммитили в этот кусочек кода последними, посчитать, что они являются в нем экспертами и добавить их в ревьюверов.
Можно назначить специальных ревьюверов, которые всегда отвечают за этот код. Можно даже посмотреть в рабочий календарь и понять, что такие-то люди в отпуске и добавлять их в ревьюверы не надо. Поэтому такая автоматизация тоже сильно повышает качество код-ревью.
Но тут же возникают вопросы: а что делать в тех случаях, когда люди просто не смотрят в код-ревью? Вот оно висит и висит целыми днями. Здесь один из вариантов — указывать размер нашего пул-реквеста. Срабатывает не всегда, но часто. Потому что если пул-реквест маленький, очень атомарный, то на него стоит размер S. На S и SLA маленький, люди должны быстро реагировать на эти пул-реквесты. Скорее всего, он будет рассмотрен быстрее.
Еще можно добавить к нему огонек, показать, что это hotfix, и люди тоже посмотрят в него еще быстрее. Плюс они будут стараться не делать очень большие пул-реквесты. Тоже помогает.
С код-ревью разобрались. Что мы еще можем сделать лучше? Релизный цикл. Чаще всего он весь хорошо описывается. Это некий пайплайн, который можно автоматизировать целиком.
![](https://habrastorage.org/r/w780q1/webt/_r/4u/rg/_r4urg81cp33iabia6jazlnksts.jpeg)
Как только в dev пришел свежий код, можно срезать релиз. Пусть он будет максимально атомарным. Влили одну фичу — отправляем её в релиз, чтобы, если что-то сломалось, мы сразу поняли: эта маленькая фича, влитая час назад, сломала прод. Так бывает, недосмотрели. Но мы знаем, куда нам откатываться и что чинить.
У вас в коде могут быть переводы, их нужно выгружать из какого-то хранилища. Пожалуйста, автоматизируем.
Нужно пройти интеграционное тестирование? Автоматизируем создание задач на интеграционное тестирование. Оно у себя делает ботов, которые разворачивают этот релиз, весь его тестируют, отписываются, что с ним все хорошо, и релиз автоматически едет дальше по пайплайну.
Нагрузочное тестирование — тоже важная вещь. Нужно проверить, что наш продаёт не упадет. Пусть это тоже будет автоматизировано со стороны команды нагрузочного тестирования.
Дальше нужно проверить, что за то время, пока мы катили релиз, у нас не влился hotfix. Поэтому ветки надо, например, актуализировать. Это всё тоже нужно сделать автоматом. И если мы всё прошли, то автоматом выкатываемся на прод, потому что, еще раз, любой релиз — это набор стандартных операций, если только что-то не пошло не так. Тогда уже нужно подключать человека. Таким образом мы можем релизиться чаще. А чем чаще мы релизимся, тем проще разбирать проблемы.
![](https://habrastorage.org/r/w780q1/webt/my/b_/54/myb_54lmyvm2nf0nurwpnqukz9q.jpeg)
В этом нам поможет CI/CD. Для реализации есть много разных тулзов, тот же самый Jenkins, TeamCity. TeamCity — платный. Но его любят за более человечный интерфейс, чем у Jenkins.
У GitLab есть GitLab CI. Да и, на самом деле, есть множество новых решений, которые тоже можно использовать. Пожалуйста, используйте, никто не запрещает. Здесь, наверное, самые заметные на рынке, но я уже слышу, как кто-то говорит: «А как же вот это решение? Оно же самое лучшее!» Пожалуйста. Главное, чтобы оно было. Но мы должны и подстелить себе соломки, максимально уменьшить стоимость нашей ошибки, потому что ошибки будут всегда.
![](https://habrastorage.org/r/w780q1/webt/xe/rl/ss/xerlsssbszb7memmew2lnn2okbe.jpeg)
Как я уже сказал, чем чаще мы релизимся, тем более атомарны наши релизы, тем легче откатываться, тем легче чинить. Поэтому стараемся релизиться максимально часто.
Релиз всегда должен быть воспроизводимым — то есть когда в момент релиза что-то выкачивается из хранилища Node-модулей. Итак, мы решили откатиться, у нас сейчас версия 2.0.0. Мы откатываемся на версию 1.9.0. Мы снова пошли в хранилище и выкачали ту же самую версию Node-модулей, которые уже стояли в версии 2.0.0. И у нас снова все сломалось. Поэтому наш релиз собирается со всеми зависимостями, упаковывается и только так едет на прод.
И мы при откатывании снова берем весь собранный релиз в том виде, в котором он был раньше, и разворачиваем его на прод. Он должен храниться в таком виде. Это либо контейнер, либо деb-пакет. Но это очень важно. Мы должны уметь воспроизводить то, как выглядел наш релиз вчера, в том же самом состоянии.
Каждый билд должен быть протестирован. Мы не должны катить на под не протестированный код. Пока QA не поставит зеленую галочку, что все хорошо, наш релиз на прод не катится в любом случае.
За выкладку на прод тоже не должны отвечать разработчики, — ни фронтендеры, ни бэкендеры. Есть люди, которые отвечают за сервер. Это админы, это эксплуатация. Везде их называют по-разному, например, Ops. Пусть они отвечают за то, что это раскатывается на prod. Пусть они пишут скрипты для этого. Мы на прод не лазаем, только под присмотром Ops.
Еще одна маленькая штучка, которая поможет сделать наши релизы стабильнее: релиз можно раскатить не на всех пользователей. Можно применить то самое A/B-тестирование, раскатить на маленький процент пользователей, так называемый канареечный хост. Canary release, знаете, да? Канарейка в шахте. Ее использовали те же самые шахтеры и проверяли, нет ли углекислого газа в шахте. Если канарейке плохо, надо уходить. Отсюда и пошло понятие канареечного релиза.
Мы должны точно так же релизиться, проверять, что все хорошо, что ничего не отравляет наш релиз. Внешняя среда ведь легко его может отравить. И если мы видим, что ошибок много, мы всегда можем откатиться. Как это сделать? Проще всего — автоматически. А если мы видим, что ошибок мало, мы можем автоматически задеплоить везде, даже не подключая человека.
Смотрим дальше. Что еще нужно автоматизировать?
Инфраструктура как код — тоже очень важное понятие, которое обязательно должно быть.
![](https://habrastorage.org/r/w780q1/webt/i5/uk/jk/i5ukjk1iqjplhysxz1ur7h349fm.jpeg)
Это значит, что никаких конфигураций мы руками не пишем. Все конфигурации у нас должны лежать в Git или d любой другой вашей любимой системе контроля версий. Но главное, что конфигурации лежат в виде шаблонов или даже в виде скриптов, генерирующих конфигурацию. Но это не ручное настраивание.
И мы всегда можем сделать шаблонизацию кода под dev-окружение, под прод-окружение, под тестинг-окружение. Это всё шаблоны, не ручное изменение конфигов. А все изменения идут через пул-реквесты. И мы видим глазами, что именнно решили изменить везде в конфигурации. То есть мы видим, что прилетел пул-реквест, который говорит о том, что, например, какой-то наш бэкенд переезжает на другой адрес. Мы должны подтянуть этот конфиг, запродить, что с ним все хорошо. И, конечно, все эти изменения должны раскатиться везде автоматически, тогда тоже будет лучше.
![](https://habrastorage.org/r/w780q1/webt/ug/es/yk/ugesykxcuee6d1btch_l4n29d4c.jpeg)
Что еще можно автоматизировать? Много чего. Наверное, тут уже не будем разбирать каждое. Например, обновления зависимостей. Можно всегда сигнализировать, что зависимости устарели, и автоматически создавать для команд задачи о том, что нужно обновить зависимости.
Версионирование. Не нужно руками поднимать версии пакетов. Можно тоже добавить автоматизацию. Например, вы вносите изменение, в каком-то файлике пишете changelog и указываете, что вот здесь были минорные изменения или мажорные. И в момент вливания вашего пул-реквеста у этой библиотеки автоматически растет версия на нужную циферку, потому что вы сказали: я довез сюда мажорных изменений.
То же самое с любой другой рутину. Если видите, что что-то можно автоматизировать, — автоматизируйте это.
Также важно понимать: то, что мы делаем, мы должны делать хорошо. Но завтра оно уже может измениться, потому что внешняя среда изменчивая, бизнес должен под нее подстраиваться. И иногда это может случиться просто за ночь, с утра прибегут и скажут: «Наша компания совершает поворот, мы начинаем разрабатывать совершенно другое. Давайте менять наш код».
Как сделать такой код, который будет одновременно надежным и готовым к любым изменениям, то есть гибким? Как ни странно, нужно добавить в него ограничения. Казалось бы, звучит немного, даже не знаю, деспотично, что ограничения — это хорошо, но в случае кода это действительно так. Он от этого только выигрывает.
Давайте подумаем, какие базовые ограничения можно сделать?
В первую очередь сильная статическая типизация. Без этого, кажется, сейчас никуда. На чистом JavaScript писать большие решения может быть очень больно. Это требует очень высокого уровня разработчиков, очень высокого уровня код-ревью. Наверное, я бы не рекомендовал.
![](https://habrastorage.org/r/w780q1/webt/kg/_x/n5/kg_xn5swkqbbq7z2ln6zooa0mjs.jpeg)
Хотя мы говорим о бизнес-коде, а не о том, что должно быть максимально эффективно на уровне инфраструктуры или рендера, Для себя я уже выбрал — только статическая типизация. А мы пишем то, что должно приносить деньги. Лучше типизировать.
как только у нас появляется типизация, мы можем делать контракты. То есть мы должны описывать контракты нашего общения между нашими частями. Вот есть система, мы ее разбили на кучу маленьких микросервисов. Они между собой общаются. И это общение должно быть зафиксировано в контрактах, чтобы контракт не был сломан.
Когда у нас все это есть, мы можем построить поверх этого архитектуру. И эта архитектура даст нам надежность. Архитектура — это ограничение.
![](https://habrastorage.org/r/w780q1/webt/fj/vf/sb/fjvfsbujqyad00xij9m850ken-y.jpeg)
Давайте быстренько посмотрим на коде, как они добавляются, ограничения. Вот обычный JavaScript. Никаких ограничений. В виде сервиса может прилететь что угодно. Мы где-то ошиблись — у нас что-то сломается. Мы добавляем ограничения, добавляем TypeScript и говорим, что в виде сервиса прилетает только то, что соответствует типу класса сервиса. Вот класс service — все хорошо. Мы статически типизировали наш код.
А теперь мы добавляем сюда архитектуру и говорим, что нам неважно, что прилетает на вход, лишь бы оно соответствовало контракту. Любой сервис, который имплементирует этот контракт, подойдет.
Здесь мы сделали наш код гибким. То есть мы уже можем вынуть один сервис и вставить другой, вставить mock, сделать какую-то фабрику со стратегией, которая позволит нам менять эти сервисы на лету. Тогда все станет лучше.
Хорошо? Идем дальше. Теперь мы можем собрать вместе весь наш код, который мы разбили по куче маленьких репозиториев: с автоматизацией, линтерами в каждом отдельном репозитории.
Это, наверное, самый тяжелый, самый опасный и самый интересный совет.
Да, мы можем добавить монорепозиторий или монорепозитории. Как ни странно, очень многие крупные компании приходят к этому, и люди удивляются, зачем они нужны, эти ваши монорепозитории, и почему об этом говорит Яндекс? Почему об этом говорит Google? Почему об этом говорит Facebook, и каждый пилит свое решение? Потому что в рамках большой компании это дает свой профит. Но, конечно, мы можем говорить о маленьких монорепозиториях, в которые складываем отдельные части кода. Это тоже будет хорошо.
У нас появляется единая точка входа в код. Мы знаем, где искать. Нам не нужно искать во множестве разных репозиториев — у нас есть один большой.
Наши правила не могут отличаться. Они уже зафиксированы, прибиты уже к этому репозиторию. Никто не может у себя в репозитории настроить другие правила линтера, другой код-стайл. Он становится единым для всей компании. Когда люди ротируются между командами, они сразу видят тот же самый код-стайл, к которому они привыкли. Они не спорят об этом, потому что это принято на уровне компании.
Тесты. Тоже очень интересная вещь. Когда у нас есть весь код сразу, мы можем тесты прогнать для всего нашего кода. Не для маленького участочка, а мы изменили одну библиотеку и сразу запустили тесты по всему коду, который ее использует.
Это, конечно, грозит тем, что придется чинить упавшие тесты. И здесь уже зависит от компании. Либо есть правило — кто сломал тесты, тот их и чинит, и это может быть больно. Или мы создаем каждой команде отдельную задачу на починку тестов, и она уезжает на предыдущую версию зависимости временно. Чинит тесты и поднимается за всеми. Но мы сразу видим, если что-то не так.
А если все хорошо, то зависимости всегда вечнозеленые. Изменили в одном месте, доехало до всех.
Ну и, конечно, намного проще все это автоматизировать, когда оно лежит в одном месте, а не нужно собирать из множества репозиториев, где каждый может что-то забыть, изменить настройки, как-то все сломать.
И можно сказать, что монорипозиторий — это очень много отрицания, гнева, торга и депрессии. А потом наступает принятие. Или не наступает. Да, это правда. В компаниях, где вводят монорепозитории, они не нравятся очень многим. Почему? Потому что заставляют писать в едином стиле кода. Они делают всё тяжелее, потому что кода становятся больше. Нужно придумывать скрипты. Чаще всего это какие-то самописные решения, которые могут падать. То есть боли бывает много.
Какой у нас выход? Маленькие монорепозитории. Мы можем взять код одного вида и собрать его в небольшой монорепозиторий, который решает маленькую задачу. Вот посмотрите на Babel, для которого придумали lerna. Отличное решение. И очень часто оно решает многое.
Получается, что вы начинаете чувствовать от этого профит. Вам уже не нужно делать много маленьких пул-реквестов в куче библиотек. У вас есть монорепозиторий. Вы делаете в него один пул-реквест, который доезжает сразу до всех необходимых библиотек, и быстрее ревьюится, потому что ревьювер сразу видит все, что затронется этим пул-реквестом, и быстрее едет на prod.
И это был мой самый страшный и самый последний совет. Поэтому перейдем к выводам.
![](https://habrastorage.org/r/w780q1/webt/vh/om/ui/vhomuiaclgb7o2tqj1amz4otplk.jpeg)
Да, сказка ложь, да в ней намек. Думаем.
Изменения — это хорошо. Если компания не хочет меняться, вот тогда нужно думать, что что-то здесь не так. Если компания готова меняться, ищите в этом возможности, потому что всё плохое, что вы видите, — это шанс проявить себя. Если вам это дают, то вы можете подняться в глазах людей, которые с вами работают. Подняться в глазах ваших начальников.
Вы видите, что какой-то кусочек не автоматизирован — вы его автоматизируете. Экономите себе пять минут, а если распространить на 50 разработчиков? Уйма времени. И это каждый день. Если вы видите, что что-то сломано, — почините это, всем станет лучше и вам это зачтется.
Если компания не замечает того, что вы делаете, то тут, конечно, уже возникает вопрос, что, может быть, стоит поискать другую компанию.
Но когда вы будете искать, помните: вы выбираете между энтерпрайзом и стартапом. Многие говорят — нет, энтерпрайз — это ужасно, там все старое, медленное, там ужасные ноутбуки. Пожалуйста, энтерпрайз, ноутбуки… Часто можно видеть ребят из энтерпрайза, которые ходят с гробами, в которые воткнуты специальные ключи, разрешающие им доступ в сеть.
А в стартапе все классно, у них есть смузи, самые лучшие ноутбуки, но завтра стартап может закрыться.
Есть энтерпрайзы, в которых прекрасно налажены процессы, современные технологии. Да, есть ограничения. Вам понадобится VPN, вам понадобятся корпоративные ноутбуки. Но это окупается тем, что вы работаете с мощнейшими системами, к которым доступ вы в стартапе, пока он не превратится в энтерпрайз, никогда не получите. Так что всегда взвешивайте здраво.
И, конечно, в вашей компании, в любой, стартап это или энтерпрайз, постарайтесь, чтобы вас слушали и услышали, чтобы ваши идеи доходили до ушей людей, которые что-то решают. Потому что если вас не слышат, то я снова говорю: возможно, это не та компания, в которой стоит работать. Всегда нужно искать шанс что-то изменить и искать компании, которые дают сделать эти изменения.
Что ж, надеюсь, я вас мотивировал, и, возможно, вы найдете в тех компаниях, где работаете сейчас, возможности для дальнейшего улучшения и компании, и себя. Спасибо.
— Привет. Меня зовут Андрей Мелихов, и сегодня я попробую выступить в не совсем привычном для себя жанре. Я расскажу вам небольшую сказку. А начнем мы, как водится, с присказки.
![](https://habrastorage.org/webt/he/na/ke/henakehvelvndseyt50pnggywe0.jpeg)
Присказка
Давным-давно я был на одной замечательной конференции. Прекрасная конференция, к сожалению, больше не проводится. Был на ней спикер, который рассказал, как он пришел в новую компанию. И эта картина мне настолько в голову запала.
![](https://habrastorage.org/webt/9f/wd/_g/9fwd_grtmuum057qvpniag9ag-y.jpeg)
Итак, приходит он в новую компанию и видит, что на стене логотип компании, на котором новогодние украшения. На дворе — 2 августа. Рядом кто-то заваривает «Доширак». И в целом атмосфера запустения и нежелания что-то делать дальше.
А пришел он из другой компании, которая была весьма успешной. И очень ему назад захотелось. Подошел он к своему новому начальнику и говорит: «Отпусти ты меня домой?» А тот ему отвечает: «Ты сюда пришел, не чтобы жаловаться, а чтобы всё изменить».
Сказка
Итак, жил-был Вася, работал этот Вася в стартапах. И тут позвали его в одну самую лучшую компанию, о которой он мечтал много лет.
Мечтал туда попасть и вдруг попал. Это и прекрасный большой офис в городе, прямо в центре города. Всё отлично, кофепоинт, все плюшки, всё, что надо.
![](https://habrastorage.org/webt/sz/ox/7x/szox7xdss3bkqudgwdt16ydyyvw.jpeg)
Но как только он заглянул в технологии, с которыми компания работает, то увидел, что технологии-то неплохие, да далеко не новые. Совсем не то, с чем он мечтал работать. Вздохнул Вася грустно: ну ладно, жить можно, разберемся.
Повели его в кабинет. А кабинет находился не на том этаже, где он проходил собеседование. Зашел он в кабинет — кабинет, полный народу. И в углу стол стоит, который ему выделили. Ладно, много людей, не так красиво, как было в стартапе, но ничего, с этим тоже справимся, подумал Вася и сел за свой стол. Стол был маленький, настолько маленький, что монитор Васи стоял на столе соседа, а монитор соседа стоял на столе Васи, а иначе не помещалось. Ну ничего, с этим тоже можно справиться, подумал Вася и включил ноутбук.
А ноутбук был бывалый, на Windows, неубиваемый. Просто прекрасный, но на Windows. В те годы — знаете, это происходило много лет назад — Windows совсем не подходил для веб-разработки. Сейчас с этим уже можно как-то жить, а тогда — нет. Ну ничего, виртуалки помогут, справимся, подумал Вася. Мониторчик плохой на ноутбуке, ужасный, маленький, ничего не видно. Ничего, дали внешний монитор, будем жить с ним.
А внешний монитор ему дали просто волшебный. Под каким углом на него посмотришь, такие цвета и видишь. И такой монитор дали человеку, в чьи обязанности входила в том числе и вёрстка. Грустно. Чтобы шея не уставала, подложил Вася два томика Страуструпа под монитор. Стало получше. Ладно, справимся, подумал Вася, и, наконец, загрузилась операционная система. Открыл он почту…
![](https://habrastorage.org/webt/sb/bf/hs/sbbfhswvhkfjkh6trxtjvnojb94.jpeg)
И увидел, что в этой компании принято писать очень много писем. А еще в этой компании принято проходит код-ревью в почте. Как это? А вот так. Не было у них ни GitLab, ни Bitbucket, ни GitHub. А просто брали они diff и отправляли его по почте. А потом люди начинали кусочки этого diff комментировать. И ладно, если бы комментировали про код. Очень много обсуждений было про то, что поставил пробела два, скобочки не поставил, где надо, точку с запятой забыл. И вот этим была забита почта.
Ну что, страшно? Уже очень страшно, но еще можно жить. И тогда Вася посмотрел в код. А код этот был, как водится у компании, которая не первый год работает, — монолитом. А монолит — это не только то, что все команды в одном коде работали, но и то, что все было жестко сцеплено. Не понятно, кто за что отвечает, циклические зависимости, все ужасно. Но не так ужасно, как то, что в этом коде еще и Node-модули лежали закоммиченные. А почему?
А потому, что нельзя код наружу отдавать. «Нельзя код, который мы пишем, — сказали Васе, — наружу вынести. Ведь завтра там что-то сломается, а мы релиз не соберем». Однако, подумал Вася. Не знают, что ли, люди о том, что можно локально держать код? И решил поговорить об этом с тимлидом. Пошел он к тимлиду. Был ли тимлид? Был тимлид. Да вот только занимался тимлид тем, что релизы собирал.
![](https://habrastorage.org/webt/gc/fz/oz/gcfzozaiqekvhqv2frxk7rghil4.jpeg)
И ладно, собирается релиз минут 40, так ведь к нему еще надо заполнить очень много бюрократии. Зайти в Confluence, завести страничку. В страничке расписать по строчкам, что у нас в этом релизе катится, какие задачи в него попали. Создать задачи на QA. Как только QA задачу проверят, создать задачу на админов. Как только админы выкатят — написать, что все хорошо. На это убьешь еще час. Два релиза за день, вот и вся работа тимлида. Некогда ему еще чем-то заниматься — релизы катить надо.
![](https://habrastorage.org/webt/0k/kj/10/0kkj10hl_no4ju3mjtl_dghh0y4.jpeg)
Понял Вася, что у него два пути: уйти из этой компании или все-таки что-то поменять. Пошел он в магазин и купил себе нормальный монитор, просто чтобы глаза свои пожалеть. Дальше пошел он к админу и попросил ноутбук, хоть какой-то, но не на Windows. Нашли ему старенький MacBook, с этим уже можно было работать. Раз к нему хотя бы в этом по-человечески отнеслись, понял Вася, то можно здесь еще что-то поменять.
И начал он потихоньку менять. И оказалось, что не один Вася в этот момент пришел в компанию. Пришло очень много новых людей, которые знали, как оно может быть: не как было, а как в других, молодых компаниях. И люди это были от топов, до самых младших. И все они меняли, каждый по чуть-чуть. Вместе они навалились, и все стало лучше. Появилось в компании что-то нормальное.
![](https://habrastorage.org/webt/cf/-6/ig/cf-6igaokspyvakcbp98zr2zqme.jpeg)
Код в Bitbucket стал лежать, автоматизацию стал Jenkins делать, все зависимости уехали в Nexus, релизы тоже, появился docker. Тимлид делом занялся. Наконец-то у него появилось время, чтобы взглянуть на своих людей. Он начал проводить встречи one-to-one, понял, где, у кого и что болит. Команды начали переставлять местами. Зарплаты изменились. Все стало гораздо лучше.
![](https://habrastorage.org/webt/i3/ad/ye/i3adyehdcywwyxd_5-9czpqzxew.jpeg)
Конец ли это сказки? В нашей сказке это конец. Но на самом деле здесь есть еще много чего менять. И, наверное, компания, в которой Вася остался работать, еще многое изменит, станет лучше.
Давайте теперь посмотрим, что же мы можем изменить в той компании, где мы работаем, если у нас все плохо.
Жизнь
Я составил несколько советов, которые мы и рассмотрим по порядку.
Итак, нужно избавиться от хаоса, потому что люди часто боятся энтерпрайза, но в энтерпрайзе есть очень важная черта. В энтерпрайзе всегда настраивают процесс, просто чтобы хаоса было меньше. Чем больше твой продукт, чем он дороже, тем это важнее.
Что мы можем изменить в процессах? Во первую очередь нужно избавиться от того, что все делают всё и мы никогда не знаем, кто конкретно что-то делает. Выделенные команды с понятной зоной ответственности нам это дают: мы знаем, когда что-то сломалось, можем подойти вот к этим ребятам и они это починят.
А чтобы им было удобнее работать, нужны микросервисы или микрофронтенды. Вспомним закон Конвея, который говорит, что каждая организация стремится в архитектуре отразить свою структуру. То есть нужно каждой команде дать кусочек кода.
![](https://habrastorage.org/webt/tr/kt/ik/trktikynos6c-xnbdxd2j8u6vds.jpeg)
Мы возьмем наш сложный монолит и разобьем его на отдельные части. Каждая команда будет отвечать за свою часть. И им будет проще. Они смогут релизиться, не затрагивая других. Они смогут лучше знать свой код, потому что он не переплетен с чужим кодом. Мы разорвем эти порочные связи, которые были у нас изначально, и у нас наконец-то начнет получаться нечто более красивое.
Ладно. Что еще можно добавить? Правила ветвления кода. Очень часто мы сталкиваемся с тем, что в компании нет никаких правил. Люди просто создают какие-то ветки, как-то это назад вливают. Главное, что есть одна ветка, с которой они как-то собирают релизы, но никаких правил нет. Поэтому рассмотрим два популярных варианта.
![](https://habrastorage.org/webt/vr/c7/vi/vrc7vivdcq3fy-thuxn2i8egkau.jpeg)
Более старый, но известный — GitFlow. Посмотрим, что это.
GitFlow говорит нам, что нужно завести две ветки — master и dev — и работать с ними. Все разработчики работают с веткой dev. Они не имеют права туда коммитить напрямую. У нас есть только механизм ветвления и пул-реквест.
Итак, мы делаем задачу, ответвляемся от ветки dev, делаем коммиты по нашей задаче. Эта ветка называется feature-ветка, или feature branch. Как только мы решили, что все доделано, тестировщик проверил, мы создаем пул-реквест и вливаемся обратно в ветку dev. Как только мы захотим релизиться, мы с ветки dev срезаемся и получаем релизную ветку.
В этой релизной ветке снова проходит тестирование, и если нашли какие-то проблемы, вносят исправления. Появляется еще коммит в релизной ветке.
Дальше, если все хорошо, мы вливаем релизную ветку в master. Это наша версия 2.0, которую мы и отправляем в продакшен. И одновременно доставляем этот код назад в dev. Теперь наш dev равен мастеру и все могут работать дальше.
Чем хороша эта система? В ней нам всегда понятно, что делать.
Вот очень сложный кейс: нам нужно быстро зарелизить hotfix. Все очень просто.
![](https://habrastorage.org/webt/st/zk/gw/stzkgwmzmwftvpxzeozaq3hfknc.jpeg)
Мы с ветки master, предыдущей версии, срезаем веточку, которая теперь у нас называется hotfix. Делаем в ней исправления. Вливаем назад в master и релизимся. Это наша версия 1.1, которую мы, конечно же, отправляем в dev. Чтобы наш код доехал в dev, наши релизы тоже должны пересобраться, переподтянуть наш dev. Но в целом все будет хорошо.
Таким образом мы можем очень быстро внести исправления и при этом не подтянуть новый код, который появился в dev с момента прошлого релиза. Мы сделаем только hotfix на конкретное состояние релиза.
Здесь вы можете увидеть, что ветка master становится несколько редуцированной. Мы можем от нее избавиться и превратить наш dev в master. Такая схема и называется GitHub Flow, давайте на нее посмотрим.
![](https://habrastorage.org/webt/aa/sp/qe/aaspqe751udopcxpwbipwhvqt0o.jpeg)
Когда уже нет отдельной ветки master, это значит, что наш dev переименовался в master. Получается, что наш релиз идет из dev, но опирается на теги. Мы у каждого релиза проставляем теги и всегда можем срезать hotfix с тега. В остальном это тот же самый GitFlow.
Все это отлично автоматизируется, с этим удобно работать. Вот такие у нас есть правила ветвления кода, если мы хотим избавляться от хаоса.
![](https://habrastorage.org/webt/vv/fe/gu/vvfegufpz-v86dt9j4tfhpltrxu.jpeg)
Что мы еще можем сделать? Добавить обсуждение наших решений. Почему это важно?
Потому что люди собираются вместе, еще не написав ни строчки кода. И те, кто хотят написать новые строчки кода, доносят свои идеи. Две головы лучше, чем одна, а четыре головы лучше, чем две. И те, кто, возможно, разбирается в другом участке кода, могут сразу сказать, что пойдет не так. Поэтому обсуждения до того, как код будет написан, так важны. Документация пишется после того, как код написан. Она тоже важна — чтобы понять, зачем все это было сделано. И, конечно, само архитектурное решение должно быть задокументировано до реализации, и на него можно будет опираться.
Хорошо, мы немножко разгребли хаос, который творился у нас в компании. Что дальше? Мы скажем «нет» рутине и добавим автоматизации. Потому что мы же ленивые люди, любим все автоматизировать. А что можно автоматизировать? Конечно, надо разобраться с код-ревью. Не должно быть споров о том, что здесь пробел не поставили или еще что-то. Код-ревью должно быть автоматизировано. Как это сделать?
![](https://habrastorage.org/webt/xg/8r/qu/xg8rquwrr-zboycaee8jutqr2jc.jpeg)
Отдадим весь код-стайл линтеру. Пусть линтер проверит. Если все хорошо, только тогда люди будут смотреть в этот код. Пусть заранее исчезнут все спорные вопросы, их решит линтер.
Мы хотим видеть, что все это работает, что тесты не сломаны. Пусть это будет в интерфейсе. Пусть в тулзах, где мы делаем код-ревью, будет сразу показано: тесты прошли отлично, и никаких вопросов к тому, что с тестами что-то не так, уже не возникнет.
И мы не должны разрешать вливать код, который не прошел QA. Почему это важно? Потому что dev должен оставаться рабочим. Если человек вольет туда что-то сломанное, мы можем этого не заметить. Мы можем об этом спорить, но QA нам скажет, что он, как минимум, все кейсы уже проверил и оно работает. Мы должны это понимать, это должно быть не на словах, а запрещено автоматически.
Еще одна очень полезная вещь — политика вычисления ревьюверов. Это либо рандом, либо можно определить, какие люди коммитили в этот кусочек кода последними, посчитать, что они являются в нем экспертами и добавить их в ревьюверов.
Можно назначить специальных ревьюверов, которые всегда отвечают за этот код. Можно даже посмотреть в рабочий календарь и понять, что такие-то люди в отпуске и добавлять их в ревьюверы не надо. Поэтому такая автоматизация тоже сильно повышает качество код-ревью.
Но тут же возникают вопросы: а что делать в тех случаях, когда люди просто не смотрят в код-ревью? Вот оно висит и висит целыми днями. Здесь один из вариантов — указывать размер нашего пул-реквеста. Срабатывает не всегда, но часто. Потому что если пул-реквест маленький, очень атомарный, то на него стоит размер S. На S и SLA маленький, люди должны быстро реагировать на эти пул-реквесты. Скорее всего, он будет рассмотрен быстрее.
Еще можно добавить к нему огонек, показать, что это hotfix, и люди тоже посмотрят в него еще быстрее. Плюс они будут стараться не делать очень большие пул-реквесты. Тоже помогает.
С код-ревью разобрались. Что мы еще можем сделать лучше? Релизный цикл. Чаще всего он весь хорошо описывается. Это некий пайплайн, который можно автоматизировать целиком.
![](https://habrastorage.org/webt/_r/4u/rg/_r4urg81cp33iabia6jazlnksts.jpeg)
Как только в dev пришел свежий код, можно срезать релиз. Пусть он будет максимально атомарным. Влили одну фичу — отправляем её в релиз, чтобы, если что-то сломалось, мы сразу поняли: эта маленькая фича, влитая час назад, сломала прод. Так бывает, недосмотрели. Но мы знаем, куда нам откатываться и что чинить.
У вас в коде могут быть переводы, их нужно выгружать из какого-то хранилища. Пожалуйста, автоматизируем.
Нужно пройти интеграционное тестирование? Автоматизируем создание задач на интеграционное тестирование. Оно у себя делает ботов, которые разворачивают этот релиз, весь его тестируют, отписываются, что с ним все хорошо, и релиз автоматически едет дальше по пайплайну.
Нагрузочное тестирование — тоже важная вещь. Нужно проверить, что наш продаёт не упадет. Пусть это тоже будет автоматизировано со стороны команды нагрузочного тестирования.
Дальше нужно проверить, что за то время, пока мы катили релиз, у нас не влился hotfix. Поэтому ветки надо, например, актуализировать. Это всё тоже нужно сделать автоматом. И если мы всё прошли, то автоматом выкатываемся на прод, потому что, еще раз, любой релиз — это набор стандартных операций, если только что-то не пошло не так. Тогда уже нужно подключать человека. Таким образом мы можем релизиться чаще. А чем чаще мы релизимся, тем проще разбирать проблемы.
![](https://habrastorage.org/webt/my/b_/54/myb_54lmyvm2nf0nurwpnqukz9q.jpeg)
В этом нам поможет CI/CD. Для реализации есть много разных тулзов, тот же самый Jenkins, TeamCity. TeamCity — платный. Но его любят за более человечный интерфейс, чем у Jenkins.
У GitLab есть GitLab CI. Да и, на самом деле, есть множество новых решений, которые тоже можно использовать. Пожалуйста, используйте, никто не запрещает. Здесь, наверное, самые заметные на рынке, но я уже слышу, как кто-то говорит: «А как же вот это решение? Оно же самое лучшее!» Пожалуйста. Главное, чтобы оно было. Но мы должны и подстелить себе соломки, максимально уменьшить стоимость нашей ошибки, потому что ошибки будут всегда.
![](https://habrastorage.org/webt/xe/rl/ss/xerlsssbszb7memmew2lnn2okbe.jpeg)
Как я уже сказал, чем чаще мы релизимся, тем более атомарны наши релизы, тем легче откатываться, тем легче чинить. Поэтому стараемся релизиться максимально часто.
Релиз всегда должен быть воспроизводимым — то есть когда в момент релиза что-то выкачивается из хранилища Node-модулей. Итак, мы решили откатиться, у нас сейчас версия 2.0.0. Мы откатываемся на версию 1.9.0. Мы снова пошли в хранилище и выкачали ту же самую версию Node-модулей, которые уже стояли в версии 2.0.0. И у нас снова все сломалось. Поэтому наш релиз собирается со всеми зависимостями, упаковывается и только так едет на прод.
И мы при откатывании снова берем весь собранный релиз в том виде, в котором он был раньше, и разворачиваем его на прод. Он должен храниться в таком виде. Это либо контейнер, либо деb-пакет. Но это очень важно. Мы должны уметь воспроизводить то, как выглядел наш релиз вчера, в том же самом состоянии.
Каждый билд должен быть протестирован. Мы не должны катить на под не протестированный код. Пока QA не поставит зеленую галочку, что все хорошо, наш релиз на прод не катится в любом случае.
За выкладку на прод тоже не должны отвечать разработчики, — ни фронтендеры, ни бэкендеры. Есть люди, которые отвечают за сервер. Это админы, это эксплуатация. Везде их называют по-разному, например, Ops. Пусть они отвечают за то, что это раскатывается на prod. Пусть они пишут скрипты для этого. Мы на прод не лазаем, только под присмотром Ops.
Еще одна маленькая штучка, которая поможет сделать наши релизы стабильнее: релиз можно раскатить не на всех пользователей. Можно применить то самое A/B-тестирование, раскатить на маленький процент пользователей, так называемый канареечный хост. Canary release, знаете, да? Канарейка в шахте. Ее использовали те же самые шахтеры и проверяли, нет ли углекислого газа в шахте. Если канарейке плохо, надо уходить. Отсюда и пошло понятие канареечного релиза.
Мы должны точно так же релизиться, проверять, что все хорошо, что ничего не отравляет наш релиз. Внешняя среда ведь легко его может отравить. И если мы видим, что ошибок много, мы всегда можем откатиться. Как это сделать? Проще всего — автоматически. А если мы видим, что ошибок мало, мы можем автоматически задеплоить везде, даже не подключая человека.
Смотрим дальше. Что еще нужно автоматизировать?
Инфраструктура как код — тоже очень важное понятие, которое обязательно должно быть.
![](https://habrastorage.org/webt/i5/uk/jk/i5ukjk1iqjplhysxz1ur7h349fm.jpeg)
Это значит, что никаких конфигураций мы руками не пишем. Все конфигурации у нас должны лежать в Git или d любой другой вашей любимой системе контроля версий. Но главное, что конфигурации лежат в виде шаблонов или даже в виде скриптов, генерирующих конфигурацию. Но это не ручное настраивание.
И мы всегда можем сделать шаблонизацию кода под dev-окружение, под прод-окружение, под тестинг-окружение. Это всё шаблоны, не ручное изменение конфигов. А все изменения идут через пул-реквесты. И мы видим глазами, что именнно решили изменить везде в конфигурации. То есть мы видим, что прилетел пул-реквест, который говорит о том, что, например, какой-то наш бэкенд переезжает на другой адрес. Мы должны подтянуть этот конфиг, запродить, что с ним все хорошо. И, конечно, все эти изменения должны раскатиться везде автоматически, тогда тоже будет лучше.
![](https://habrastorage.org/webt/ug/es/yk/ugesykxcuee6d1btch_l4n29d4c.jpeg)
Что еще можно автоматизировать? Много чего. Наверное, тут уже не будем разбирать каждое. Например, обновления зависимостей. Можно всегда сигнализировать, что зависимости устарели, и автоматически создавать для команд задачи о том, что нужно обновить зависимости.
Версионирование. Не нужно руками поднимать версии пакетов. Можно тоже добавить автоматизацию. Например, вы вносите изменение, в каком-то файлике пишете changelog и указываете, что вот здесь были минорные изменения или мажорные. И в момент вливания вашего пул-реквеста у этой библиотеки автоматически растет версия на нужную циферку, потому что вы сказали: я довез сюда мажорных изменений.
То же самое с любой другой рутину. Если видите, что что-то можно автоматизировать, — автоматизируйте это.
Также важно понимать: то, что мы делаем, мы должны делать хорошо. Но завтра оно уже может измениться, потому что внешняя среда изменчивая, бизнес должен под нее подстраиваться. И иногда это может случиться просто за ночь, с утра прибегут и скажут: «Наша компания совершает поворот, мы начинаем разрабатывать совершенно другое. Давайте менять наш код».
Как сделать такой код, который будет одновременно надежным и готовым к любым изменениям, то есть гибким? Как ни странно, нужно добавить в него ограничения. Казалось бы, звучит немного, даже не знаю, деспотично, что ограничения — это хорошо, но в случае кода это действительно так. Он от этого только выигрывает.
Давайте подумаем, какие базовые ограничения можно сделать?
В первую очередь сильная статическая типизация. Без этого, кажется, сейчас никуда. На чистом JavaScript писать большие решения может быть очень больно. Это требует очень высокого уровня разработчиков, очень высокого уровня код-ревью. Наверное, я бы не рекомендовал.
![](https://habrastorage.org/webt/kg/_x/n5/kg_xn5swkqbbq7z2ln6zooa0mjs.jpeg)
Хотя мы говорим о бизнес-коде, а не о том, что должно быть максимально эффективно на уровне инфраструктуры или рендера, Для себя я уже выбрал — только статическая типизация. А мы пишем то, что должно приносить деньги. Лучше типизировать.
как только у нас появляется типизация, мы можем делать контракты. То есть мы должны описывать контракты нашего общения между нашими частями. Вот есть система, мы ее разбили на кучу маленьких микросервисов. Они между собой общаются. И это общение должно быть зафиксировано в контрактах, чтобы контракт не был сломан.
Когда у нас все это есть, мы можем построить поверх этого архитектуру. И эта архитектура даст нам надежность. Архитектура — это ограничение.
![](https://habrastorage.org/webt/fj/vf/sb/fjvfsbujqyad00xij9m850ken-y.jpeg)
Давайте быстренько посмотрим на коде, как они добавляются, ограничения. Вот обычный JavaScript. Никаких ограничений. В виде сервиса может прилететь что угодно. Мы где-то ошиблись — у нас что-то сломается. Мы добавляем ограничения, добавляем TypeScript и говорим, что в виде сервиса прилетает только то, что соответствует типу класса сервиса. Вот класс service — все хорошо. Мы статически типизировали наш код.
А теперь мы добавляем сюда архитектуру и говорим, что нам неважно, что прилетает на вход, лишь бы оно соответствовало контракту. Любой сервис, который имплементирует этот контракт, подойдет.
Здесь мы сделали наш код гибким. То есть мы уже можем вынуть один сервис и вставить другой, вставить mock, сделать какую-то фабрику со стратегией, которая позволит нам менять эти сервисы на лету. Тогда все станет лучше.
Хорошо? Идем дальше. Теперь мы можем собрать вместе весь наш код, который мы разбили по куче маленьких репозиториев: с автоматизацией, линтерами в каждом отдельном репозитории.
Это, наверное, самый тяжелый, самый опасный и самый интересный совет.
Да, мы можем добавить монорепозиторий или монорепозитории. Как ни странно, очень многие крупные компании приходят к этому, и люди удивляются, зачем они нужны, эти ваши монорепозитории, и почему об этом говорит Яндекс? Почему об этом говорит Google? Почему об этом говорит Facebook, и каждый пилит свое решение? Потому что в рамках большой компании это дает свой профит. Но, конечно, мы можем говорить о маленьких монорепозиториях, в которые складываем отдельные части кода. Это тоже будет хорошо.
У нас появляется единая точка входа в код. Мы знаем, где искать. Нам не нужно искать во множестве разных репозиториев — у нас есть один большой.
Наши правила не могут отличаться. Они уже зафиксированы, прибиты уже к этому репозиторию. Никто не может у себя в репозитории настроить другие правила линтера, другой код-стайл. Он становится единым для всей компании. Когда люди ротируются между командами, они сразу видят тот же самый код-стайл, к которому они привыкли. Они не спорят об этом, потому что это принято на уровне компании.
Тесты. Тоже очень интересная вещь. Когда у нас есть весь код сразу, мы можем тесты прогнать для всего нашего кода. Не для маленького участочка, а мы изменили одну библиотеку и сразу запустили тесты по всему коду, который ее использует.
Это, конечно, грозит тем, что придется чинить упавшие тесты. И здесь уже зависит от компании. Либо есть правило — кто сломал тесты, тот их и чинит, и это может быть больно. Или мы создаем каждой команде отдельную задачу на починку тестов, и она уезжает на предыдущую версию зависимости временно. Чинит тесты и поднимается за всеми. Но мы сразу видим, если что-то не так.
А если все хорошо, то зависимости всегда вечнозеленые. Изменили в одном месте, доехало до всех.
Ну и, конечно, намного проще все это автоматизировать, когда оно лежит в одном месте, а не нужно собирать из множества репозиториев, где каждый может что-то забыть, изменить настройки, как-то все сломать.
И можно сказать, что монорипозиторий — это очень много отрицания, гнева, торга и депрессии. А потом наступает принятие. Или не наступает. Да, это правда. В компаниях, где вводят монорепозитории, они не нравятся очень многим. Почему? Потому что заставляют писать в едином стиле кода. Они делают всё тяжелее, потому что кода становятся больше. Нужно придумывать скрипты. Чаще всего это какие-то самописные решения, которые могут падать. То есть боли бывает много.
Какой у нас выход? Маленькие монорепозитории. Мы можем взять код одного вида и собрать его в небольшой монорепозиторий, который решает маленькую задачу. Вот посмотрите на Babel, для которого придумали lerna. Отличное решение. И очень часто оно решает многое.
Получается, что вы начинаете чувствовать от этого профит. Вам уже не нужно делать много маленьких пул-реквестов в куче библиотек. У вас есть монорепозиторий. Вы делаете в него один пул-реквест, который доезжает сразу до всех необходимых библиотек, и быстрее ревьюится, потому что ревьювер сразу видит все, что затронется этим пул-реквестом, и быстрее едет на prod.
И это был мой самый страшный и самый последний совет. Поэтому перейдем к выводам.
![](https://habrastorage.org/webt/vh/om/ui/vhomuiaclgb7o2tqj1amz4otplk.jpeg)
Да, сказка ложь, да в ней намек. Думаем.
Изменения — это хорошо. Если компания не хочет меняться, вот тогда нужно думать, что что-то здесь не так. Если компания готова меняться, ищите в этом возможности, потому что всё плохое, что вы видите, — это шанс проявить себя. Если вам это дают, то вы можете подняться в глазах людей, которые с вами работают. Подняться в глазах ваших начальников.
Вы видите, что какой-то кусочек не автоматизирован — вы его автоматизируете. Экономите себе пять минут, а если распространить на 50 разработчиков? Уйма времени. И это каждый день. Если вы видите, что что-то сломано, — почините это, всем станет лучше и вам это зачтется.
Если компания не замечает того, что вы делаете, то тут, конечно, уже возникает вопрос, что, может быть, стоит поискать другую компанию.
Но когда вы будете искать, помните: вы выбираете между энтерпрайзом и стартапом. Многие говорят — нет, энтерпрайз — это ужасно, там все старое, медленное, там ужасные ноутбуки. Пожалуйста, энтерпрайз, ноутбуки… Часто можно видеть ребят из энтерпрайза, которые ходят с гробами, в которые воткнуты специальные ключи, разрешающие им доступ в сеть.
А в стартапе все классно, у них есть смузи, самые лучшие ноутбуки, но завтра стартап может закрыться.
Есть энтерпрайзы, в которых прекрасно налажены процессы, современные технологии. Да, есть ограничения. Вам понадобится VPN, вам понадобятся корпоративные ноутбуки. Но это окупается тем, что вы работаете с мощнейшими системами, к которым доступ вы в стартапе, пока он не превратится в энтерпрайз, никогда не получите. Так что всегда взвешивайте здраво.
И, конечно, в вашей компании, в любой, стартап это или энтерпрайз, постарайтесь, чтобы вас слушали и услышали, чтобы ваши идеи доходили до ушей людей, которые что-то решают. Потому что если вас не слышат, то я снова говорю: возможно, это не та компания, в которой стоит работать. Всегда нужно искать шанс что-то изменить и искать компании, которые дают сделать эти изменения.
Что ж, надеюсь, я вас мотивировал, и, возможно, вы найдете в тех компаниях, где работаете сейчас, возможности для дальнейшего улучшения и компании, и себя. Спасибо.