четверг, 28 марта 2019 г.

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


Вы будете использовать ружьё для того  чтобы застрелить муху? Разумеется нет. Тот же принцип следует использовать когда вы пишете приложение микросервиса, размер которого не будет превышать 10К строк кода. Не делайте код избыточным. Допустим у вас есть большой код который вы поддерживаете. Это может быть 100К+ строк кода, но вам следует изменить вашим привычкам и начать думать по-другому. Эта публикация позволит вам приобщится к магии написания простого кода для микросервисов, который легко поддерживать. Предложения могут оказаться самоуверенными, но на практике это происходит в бизенесе за миллионы доларов.


TL;DR
Микросервисы это маленькие системы. Вы можете легко избавиться от MVC. Скажите нет ORM и пожалуйста не используйте все ваши знания о паттернах проектирования в микросервисах. Сконцентрируйтесь на производительности, читабельности кода и поддерживаемости, чего нет в старых правилах и паттернах. Паттерны были придуманы не для микросервисов.
Зачем писать микросервисы в первую очередь

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


Вам нужен MVC?

С паттерном Модель-Представление-Контроллер (MVC) я познакомился в 2007 или может чуть раньше. С тех пор я думал что это серебрянная пуля для любой архитектуры программного обеспечения. Но больше я не придерживаюсь такого мнения. Да вы привыкли работать с Java или PHP и там любой фреймворк построен на MVC. Но теперь вам не обязательно думать что иначе не может быть. Сфокусируйтесь на чистоте и том, что бы все работало.
Используйте контроллеры если вы хотите и это уместно в вашем случае. Думайте о задаче в духе: мое приложение получает HTTP запрос и после возвращает HTTP ответ. Не думайте о том, что у вас есть бэкенд с API и фронтенд, который его использует. Посмотрите на этот код, это точно не MVC:
  async function get(params) {

  const today = new Date().toISOString().split('T')[0];
  const {fromCurrency='AUD', toCurrency='USD', onDate=today} = params;

  let exchangeRates = await db.query(
    `SELECT rate, created_at FROM exchange_rates WHERE from_currency = ? AND to_currency = ? AND on_date = ?`,
    [fromCurrency, toCurrency, onDate]
  );
   
  if (exchangeRates.length) {
    const rate = Number(exchangeRates[0].rate);
    console.log(`Found exchange rate of ${rate} for ${fromCurrency} to ${toCurrency} of ${onDate} in the db`);
    return {fromCurrency, toCurrency, onDate, rate};
  }
 
  return getExternal(fromCurrency, toCurrency, onDate);
}

module.exports = {
  get
}
Вы можете посмотреть полное приложение здесь, и обратите внимание, это точно не MVC.
Поэтому вместо того, что бы следовать каждой букве M-V-C, пишите тесты, реализуйте непрерывную интеграцию. Добавьте лог и прочие средства для мониторнига приложения. Пишите максимально простой код, который легко поддерживать.

Не переусердствуйте с ORM

Когда я впервые познакомился с ORM (Object Relation Mapping), я сказал сам себе что это самая крутая штука для программистов которую я видел. Спустя более чем 10 лет, я бы остерегался предлагать использовать ORM для любых случаев. Недавно я занимался рефакторингом и заменял реализацию полной ORM в чистыми вызовами SQL запросов. В результате я получил 20% прироста производительности. В дополнение к этому я начал непосредственно использовать транзакции и сделал код намного чище и понятней.
Маппер данных или Активная запись – каждая из них привностит свои особенности в реализации и тяжеловестноти решения. Это влияет не только на производительность, но также и на читабельность кода. Вот например возмем пре и пост хуки для Doctrine, они как то магически работают, и понять эту магию весьма не просто.
Вот просто попробуйте объяснить молодому специалисту как ORM добавляет данные и как данные добавляются с помощью INSERT SQL. Вы уже пожалели что используете ORM. И особенно в контексте микросервисов ORM выглядит чрезмерной. Микросервисы должны быть не более 10К строк кода, и использовать как максимум с десяток таблиц, поэтому не используйте ORM. Точка.

Паттерны проектирования могут быть обузой

Я ни в коем случае не говорю не изучать паттерны проектирования. Вы должы знать о SOLID, закона Деметры, паттерне фабрики, стратегии, синглтона, адаптера и прочих. Все это полезно если вы имеете дело с объектно –ориентированным программированием, верно? А что если вы пишете микросервис с помощью Node.js когда 1К сток кода разбиты на 7 файлов. Код просто решает некую бизнес задачу. Все эти паттерны для данного случая становятся не более чем полезной ерундой.
Паттерны проектирования полезны для кода, который уже большой и в ближайшие полгода станет еще больше, то есть нормальным таким монолитом. Паттерны подойдут для сервиса в 100 строк кода, которые в течение полгода превратятся в 1000 строк. Мы никогда не предполагаем, что размер кода будет больше, потому что для выполнения другой части у нас будет другой микросервис. Так что следите за тем, чтобы ваш код микросервиса был обезжиренным и хорошо проверенным.

Выводы

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