В жизненном цикле каждого растущего стартапа наступает время, когда кодовая база становится чрезмерно сложной и излишне спроектированной. Первоначально, когда создаются стартапы, они строятся с отношением «Готовь дерьмо» / «Двигайся быстрее». Хотя такое отношение помогает компании выстраиваться в первые годы, пока не будет захвачена изрядная доля рынка, в долгосрочной перспективе это создает огромный технический долг. Это практично, потому что для того, чтобы закончить, люди просто пишут говно. Естественно, что инженерия не является приоритетом для многих стартапов в первые дни, даже годы. Так проходит 2/3 года, и люди начинают чувствовать жар. Из-за спроектированного кода api становится очень сложно модифицировать. Чем больше кода добавляют люди, тем больше они увеличивают нагрузку, тем самым оставляя разочарование разработчикам. Поэтому, когда наступает переломный момент, становится очень важно подумать о том, как сломать кодовую базу, чтобы люди могли с радостью ими управлять, а бизнес видел общую продуктивность команды инженеров.

Проблема становится очень вонючей, когда выполняются следующие условия:

  1. Базовая база данных используется несколькими командами. Таким образом, модели, обращающиеся к базе данных, также являются общими для них. Нет конкретного владения данными и ограниченного контекста в общем коде. Это очень большая боль. Это затрудняет решение проблемы, поскольку для ее решения может потребоваться участие нескольких команд.
  2. Иногда люди перезаписывают чей-то код в репозитории git, вероятно, по неосторожности. Таким образом, повторение изменения также требует некоторых усилий от кросс-команд.
  3. Поскольку кодовая база представляет собой единое целое, под ней размещается несколько разложимых сервисов. Итак, один ошибочный код в кодовой базе, полное развертывание требуется командой DevOps.
  4. Кодовая база должна быть обновлена ​​до более масштабируемой технологии. Итак, новые технологии, новый язык программирования и новые фреймворки. Это требует тяжелого обучения, по крайней мере, в течение первых нескольких недель.

Итак, как решить проблему? Каков самый эффективный способ решить проблему?

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

Для решения проблемы, я думаю, в целом сработает следующий подход, хотя он зависит от конкретной организации и их структуры.

  1. Определение возможности разделения на сервисы: когда я говорю сервисы, я не обязательно имею в виду микросервис или SOA. Разложение означает извлечение некоторой части из монолита, которая может функционировать независимо. Возможно, вам потребуется предоставить конечные точки api для доступа к службе. Но я считаю, что в монолите есть несколько частей, которые могут функционировать независимо. Как и в самой простой системе аутентификации. Проще говоря, аутентификация и управление сеансами выполняется внутри кодовой базы с помощью встроенных утилит для управления сеансами и аутентификации во фреймворке. Но все это можно реализовать с помощью шлюза api. Можно создать отдельный сервис для пользовательского сеанса, аутентификации, управления авторизацией и логики маршрутизации API. Точно так же оплата может быть другой услугой. Как только мы идентифицируем разлагаемые части, мы можем проверить, действительно ли мы можем их разложить. Если порции регулярно изменяются несколькими командами, это будет немного сложно. В противном случае он контролирует одну команду, и она может решить, что делать дальше.
  2. Отказ от общей схемы / кода / внутренних технологий базы данных: Можем ли мы воспользоваться подходом снизу вверх, чтобы убрать беспорядок с нижнего уровня? В основном в монолитной кодовой базе отсутствует право собственности на данные, границы кодовой базы. Базы кода, принадлежащие разным командам, изменяют одну и ту же таблицу базы данных, используя одну и ту же модель базы данных. Проблема в том, что вы никогда не знаете, что что-то модифицируете, другой код может сломаться. Они модифицируют то, что может сломать твое. Хуже того, ваши кодовые базы изменяются друг другом. Это очень тесно связанный код, большая боль для всех разработчиков. Итак, чтобы начать решение с нижнего уровня (снизу вверх), вам необходимо определить право собственности на данные. Идея состоит в том, чтобы логически разделить совместное использование кода путем определения границ, сначала имитируя межпроцессное взаимодействие в рамках одной и той же монолитной кодовой базы. Потому что, если вы не можете логически разделить код и совместное использование данных в монолите, было бы чрезвычайно сложно смоделировать его как отдельный сервис. По какой-то причине в монолите разные команды в конечном итоге манипулируют некоторыми общими столбцами в одной и той же таблице базы данных. Итак, чтобы начать рефакторинг, вам может потребоваться создать точные реплицированные таблицы на всех сторонах команды. Должно быть строгое соглашение, что команды будут читать и записывать данные на своей стороне, и они будут обновлять соответствующие столбцы других команд через запрос вызова / запуска API, если это необходимо. Таким образом, некоторые избыточные вызовы API / операции запроса кросс-таблицы будут существовать до тех пор, пока монолит не будет сломан. Точно так же команды могут создавать свои собственные модели и код для управления своими данными. Таким образом, можно создать логическую границу между командами, где команды полностью осведомлены о своих правах собственности на данные и код. Итак, как только ваша кодовая база логически отделится от других команд, вы можете начать миграцию своей кодовой базы, схемы базы данных и моделей и т. Д. В соответствии с вашим желанием, имея в виду, что вы предоставите api другим командам, чтобы при необходимости они могли обновлять данные на вашей стороне. Будет лучше, если вы спроектируете систему таким образом, чтобы постепенно все системы становились независимыми и между ними была очень слабая связь.
  3. Обновление текущей системы. После того, как логические границы данных и кода определены для нескольких команд, вам станет очень легко двигаться дальше. Теперь у вас есть полная свобода проектирования системы с учетом того, какие данные должны быть переданы через API или межпроцессные вызовы. Вы можете обновить фреймворк, технологию, переопределить запрос / ответ API. Другим командам безразлично, смогут ли они общаться с вами через вызовы API, когда это необходимо.
  4. Могут быть и другие вещи, такие как определение правильных интерфейсов для всех ваших функций, чтобы другие могли общаться с вами через интерфейс, но это в основном зависит от базовой технологической структуры и выбора разработчиков, как они хотят это делать. Если вы моделируете свой код как независимую службу, для начала полезно использовать api.

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

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