Вводная
Добрый день всем, дорогие читатели!
Если вы хотя бы чуть-чуть имели неудачу пообщаться с Архитекторами, то знаете, что в их понимании не существует идеальной архитектуры ПО и вся их работа состоит во взвешивании плюсов и минусов того или иного Архитектурного стиля. И поскольку Архитектурных стилей много и каждый имеет свои преимущества (даже Монолит) и недостатки (даже Микросервисы) - работа архитектора состоит в попытках применения данных стилей на конкретный продукт и попыток предугадать, что из этого получит в итоге для бизнес-части.
Архитектурный стиль, иногда называемый архитектурным шаблоном – это набор принципов (высокоуровневая схема), обеспечивающая абстрактную инфраструктуру для семейства систем (StudFiles)
В данной статье предлагаю вам углубиться в достаточно нестандартный эксперимент по проверке Архитектурных стилей: не сидеть и теоризировать, а прямо соорудить некий эмулятор разработки ПО на игре Factorio в качестве движка.
Factorio - компьютерная игра в жанре симулятора строительства и управления (Wikipedia)
Как сказал мой добрый друг-программист про Factorio: "Эту игру создали программисты для программистов" и эти слова плотно въелись в мою память. И реально игра в эту игру очень сильно напоминает процесс разработки ПО: можно просто строить как попало и прийти к полностью запутанной и сложнообслуживаемой системе, а можно подойти к вопросу с умом изначально и в итоге получить производительную и легкую в обслуживании систему (Прям как в жизни!)
На начало написания статьи я только успел обдумать общие подходы и немного опробовать эту идею и понятия не знаю, чем это закончится. Она может оказаться полностью бесполезной тратой времени, может вообще не иметь возможности реализоваться, может получиться хорошим обучающим материалом для опытных программистов, а может и дорасти до научной работы и привнести новые идеи в запутанную профессию Архитектора ПО. Посмотрим, что получится: я не буду кардинально править уже написанные части статьи, чтобы сохранить эту атмосферу неизведанного.
Ложь/враньё
Со стечением времени уже пришлось вносить правки в эту статью т.к. иначе получались много сторонних переменных, которые вносили погрешность в исходные данные. А именно:
Сценарии "Scalability" - добавил информацию о необходимости установки генерации бесконечных ресурсов на места добычи руд/нефти; добавлены пояснения, как именно мы масштабируем (делаем везде "синие" конвейера, заводы типа 3 и ставим везде пакетные манипуляторы); плюс считаем ещё и производительность колб всех цветов.
Сценарии "Agility" - переформулировано условие: замерять время будем с самого начала игры и фиксированный набор производств (например, запуск производства синих колб или полный переход на АЭС).
Сценарии "Deployability" - добавлено, что можно открывать карту читами, чтобы быстрее найти подходящее место для эксперимента.
Сценарии "Configurability" - полностью переформулирован сценарий. Теперь вместо плавающих от архитектурного стиля к стилю событий я перешёл к более универсальному: будем проверять скорость перенаправления производства на колбы или на ракету без строительства/сноса. И замерять изменения производства, конечно же.
Сценарии "Perfomance" - в сценарий добавлена необходимость установки бесконечных ресурсов на места добычи руд/нефти. В разных архитектурных стилях получались разные потоки этих руд/нефти, что вносило ОЧЕНЬ большое искажение в итоговые цифры производительности. А теперь всё будет точнее в разы.
Сценарии "Cost" - выяснилось, что пользоваться разными онлайн-инструментами для подсчёта площади сложных фигур даёт разные результаты. Поэтому я фиксирую только один инструмент и будем с ним всё считать.
Сценарии "Testability" - полностью переработана и теперь производится тестирование на основании Tier'ов.
На все сценарии даны краткие примеры того, как бы выглядела плохая и хорошая архитектура в описываемом сценарии с точки зрения эксперимента. Просто для примера и понимания.
Естественно, все сценарии, где как-либо поменялся способ измерения я переобмерил. Исходные данные сохранены, но поправлен метод подсчёта и переподведены итоги.
Переработано правило, разрешающее уничтожать улеи - теперь это можно делать, если на месте стройки улей виден на миникарте. Раньше было правило "виден на экране", но выяснилось, что экраны бывают разные и получаются разные условия.
Переписано условие по использованию "синих" конвейеров. Технически правило осталось прежним, просто дано более понятное пояснение правила.
Добавлена возможность открывать карту читами после завершения игры. Ни на что не влияет, но просто экономит моё время между замерами.
Статья "Пробуем Микросервисы" перенесены на 4-ую часть. Просто потому-что он хорошо стыкуется с 3-ей частью, а с моими темпами я все 7 частей допишу ближе к 50-му году. Не хотелось бы так далеко уводить достаточно популярный сегодня Архитектурный стиль - лучше обработать его побыстрее.
Ну и по мелочи поправил объяснения и ошибки в тексте.
Что мы будем делать?
Статья поделится на 7 частей:
(эта) Вводная. Пробуем Монолит
Пробуем Сервисо-ориентированную архитектуру
Пробуем Основанную на сервисах архитектуру
Пробуем Микросервисы
Пробуем Основанную на пространствах архитектуру
Пробуем Событийно-управляемую архитектуру
Ищем новые Архитектурные стили
Мы будем брать какой-либо архитектурный стиль и будем попробовать реализовать её в игре Factorio, замерять и фиксировать различные параметры, а после будем сравнивать их. Собственно это всё: так мы сразу узнаем, какие Архитектурные стили хороши/плохи в сравнении друг с другом.
Сгеренированную карту игры, параметры игры и ряд правил берём как константу для того, чтобы сохранить идентичность лабораторной среды. Начинать будем с самого начала игры и будем иметь две задачи:
запустить ракету в космос со спутником на борту
перевести всё электрообеспечение на атомную энергетику и полностью отказаться от сжигания угля (оставить только для производства гранат, пластмасс и подобного сырья).
По ходу игры мы будем замерять время наиболее важных событий для возможности в будущем более детально сравнить Архитектурные стили между собой. Плюс к последнему я ещё буду стараться постить мои личные заметки по происходящему на экране, что будет отражать общее настроение продуктовой команды, которая разрабатывает данный продукт.
Далее у нас начнётся аналитика собранной информации: узнаем, как получается всё быстро, просто, понятно и дёшево. Тут мы сравним графики, различные аспекты производства и общие впечатления от работы с определённым стилем.
Ну и в конце, набравшись опыта и знаний, мы приступим к завершающей части: попробуем развернуть задание наизнанку и попробуем на основании уже сохранённых файлов игры Factorio найти концептуально новые Архитектурные стили.
Что ж, работы много, так что приступим!
Что у нас со стороны Архитектуры?
Начнём с того, что мы хотим привнести со стороны Архитектуры ПО в данный эксперимент.
Конкретно здесь мы будем использовать уже устоявшиеся в тот или иной промежуток времени Архитектурный стили - так мы получим проверенную временем информацию, что поможет нам в будущем развитии эксперимента. Иными словами мы проверим, действительно ли наш эксперимент наказывает те же самые плюсы/минусы, что широко известны в профессии.
Кратко опишем основные Архитектурные стили для освежения памяти или ввода в контекст.
Архитектурные стили
Монолит (Monolithic)
Собственно, начнём мы с оклемённым всеми Монолитом. Причина его включения в данный список проста: он всё ещё актуален и он всё ещё имеет свои преимущества.
Если кратко, то логика работы Монолита заключается в отсутствии логики как таковой - он просто получается сам собой, если просто сесть писать код без предварительной проработки Архитектурной части. Может быть это сильно некорректно-критическое описание работы Монолита, но нам сейчас в нашей статье более и не надо.
Особенность его заключается в том, что мы запихиваем всю логику работы приложения в один исполняемый процесс и в итоге у нас получается простое в написании, но сложное в доработке приложение.

Как ни крути, нам будет полезно сравнить остальные Архитектурные стили с Монолитом и ответить на вопрос: а действительно он так плох, как о нём говорят.
Сервисо-ориентированная архитектура (Service-Oriented Architecture или SOA)
Среди всех остальных Архитектурных стилей Сервисо-ориентированная самая непопулярная из-за её множества проблем, но именно она помогла отойти от концепции Монолита и тихо-мерно прийти к концепции Микросервисов.
Суть SOA заключается в попытке разбиения сервисов по логическим задачам и связывании их через некую "Сервисную шину". Сама шина занимается только тем, что забирает ответы от одних сервисов и передаёт этот ответ на выполнения другим, а потом забирает ответ и передаёт третьим и так далее до достижения некого финала (возврат ответа пользователю или занос результата в некое хранилище).

Как и Монолит, SOA так же имеет смысл внести в наш список для того, чтобы был предмет для сравнения.
Основанная на сервисах архитектура (Service-Based Architecture или SeBA)
Хоть от SOA от отказались как "неудачный опыт", найти что-либо в Гугле по нему было значительно легче, чем по Service-Based Architecture. Но сложно не невозможно, так что приступим.
Данный Архитектурный стиль является логическим развитием SOA и, относительно её, заключается в двух ключевых изменениях: первое, переход от Сервисной шины к API; второе, перевод логики определения передачи результатов сервиса на сам сервис (то есть теперь не шина решает, куда передать результат дальше на вычисление, а сам сервис). Если говорить проще, то SeBA является попытка сделать SOA проще для дальнейшей разработки за счёт упразднения шины и переносы её задачи равномерно на все сервисы. То есть каждый сервис сам знает, что/куда ему слать дальше по цепочке, а для самой передачи запроса использует сеть.
Ну и да: именно где-то тут начали пихать всё не в один исполняемый процесс, а переходить на мультипроцессное исполнение и ковайный API. А если ещё для каждого сервиса сделать свою БД и вынести Web-часть - уже получится знаменитая Микросервисная архитектура.

Эти изменения дали свои плюсы, но полностью ощутить мы их сможем только уже в ходе эксперимента.
Микросервисный (Microservices)
У нас будет самый распиаренный Архитектурный стиль из всех актуальных - Его Превосходительство Миркосервисный Архитектурный стиль.
Если кратко, то его особенностью является разделение приложения на множество независимых друг от друга миниприложений (собственно, микросервисы), каждый из которых занимает только одной, вселенной ему частью логики. Общение между ними происходит по API. Логика передачи запроса тоже устанавливается каждым микросервисом самостоятельно. В общем и всё - ничего лишнего.

Если попробовать мысленно переместить эту концепцию на Factorio, то уже начинает приходить понимания, что за внешней простотой кроется много железных орехов... (но это не мои проблемы...)
Основанная на пространствах архитектура (Space-Based Architecture или SpBA)
Это тоже ответвление от SОА, которые пошёл в другую сторону.
В попытках отойти проблемы SOA есть данный Архитектурный стиль некоторые архитекторы сконцентрировались на попытках решить проблемы с масштабированием приложения для принятия больших нагрузок и так изобрели SpBA. Ну и тот факт, что информации в Гугле по SpBA значительно больше, чем по SeBA недвусмысленно говорит нам о том, что в мире ПО более важна именно работа под большой нагрузкой, чем обилие различных фич (но это не точно)
Кратно разберём данный Архитектурный стиль. В попытках принять большую нагрузку на своё приложение SOA ушло в чуть другую плоскость - использовать реплицированную In-Memory для хранения обрабатываемой информации, а так же небольшой модуль для управления всем этим процессом. Это даёт хороший буст в плане масштабировании, но и привносит ряд сложностей.

С продумыванием концепции In-Memory в Factorio у меня явно будут определённые сложности, но как-нибудь решим их.
Событийно-управляемая архитектура (Event-Driven Architecrute или EDA)
В данном Архитектурном стиле мы впервые начинаем использовать концепцию очередей - именно ими хотели во всём том же SOA закрыть проблему масштабирования и сложности разработки одновременно.
Если кратко разобрать принцип работы EDA, то можно сказать так: в SOA разбили Сервисную шину на очереди и управление очередью (т.н. "Брокер/Медиатор"). Теперь программистам достаточно кодить сами сервисы и просто задавать логику работы медиатра, а эксплуатации просто подключать к очередям столько экземпляров сервисов, сколько надо.

Самое плохое в данном Архитектурном стиле, что медиатор может работать в двух режимах: собственно, режим Брокера (тупая, заданная последовательность) и режим Медиатора (на основании внутренней логики). Как мы будем реализовывать это в Factorio и как нам реализовать два этих режима - ещё не понятней, чем с In-Memory (но это проблемы не мои... это проблемы будущего меня... так что... иди к чёрту будущий Я).
Что там со стороны Factorio?
Игра позиционирует себя больше как симулятор программиста, а не симулятор продукта, а значит нам придётся искать аналогии для сравнения их с реальным процессом производства ИТ-продукта. Так мы сможем чуть изменить понимание и правила игры для большей достоверности. В общем нужно, первое, провести аналогии каких-либо элементов и процессов игры с реальной разработкой; второе, подкорректировать правила игры (где-то облегчить, где-то усложнить и под.).
Итак, начнём с проведения аналогий и будем двигаться от общего к точечному
Организационные аналогии
Игра==Компания/Бизнес.
Тут всё просто: мы туда приходим, что-то строим, генерируем единицу пользы и жаждим получить со всего этого единицу выгоды
Планета==Проект.
По сюжету игры наш персонаж терпит крушение на чужой планете и всё что у него есть: это немного стартовых инструментов/предметов и локальный Гугл для изучения методов производства различных технологических штук. В общем Планета является аналогией нашего продуктового проекта.
Жуки==Бюджет.
В Мире/Проекте есть ограничивающий фактор, который ограничивает наш бесконечный рост. В компании это продуктовый бюджет, в Factorio - жуки. Если мы начнём разрастаться так, что бизнес уже начинает нервничать в виду возросших расходов на всё это добро - оно начнёт пихать в палки в колёса (например, вместо выполнения основной работы начинать просить стоить планы со сроками в 4-х эксельках и часами их обсуждать); если мы в ходе строительство своих зданий начнём загрязнением задевать территорию жуков - они начнут волноваться и нападать. Так или иначе, аналогия похожа: если мы переходим какие-либо пределы - начинается сопротивление. И чем дальше заходим, тем сопротивление больше. В игре жуки хорошо ещё тем, что чем больше вы хотите захватить территорий - тем сложнее эту территорию зачищать и оборонять (если кто не знает - чем дальше он спавна, тем сильнее охрана улий Жуков и тем их больше по количеству). Всё это просто идеально похоже на запрос дополнительного бюджета: чем больше/чаще мы его запрашиваем, тем больше/чаще ловим вопросы вида "Обоснуйте затраты".
Так же Жуки, при определённых обстоятельствах переквалифицируются в хакеров, но это мы рассмотрим ниже
Площадь==Расходы
Вытекающий из предыдущего пункта Жуков/Бюджета: если мы будем занимать малую площадь под свои заводы или обходиться компании малыми расходами - Бизнес нам слова не скажут. Соответственно, чем меньше у нас в итоге наши строения будут занимать площади, тем лучше мы справимся в плане расходов, но и тем больше проблем мы испытывает с ограниченным пространством (иначе говоря, можно сразу делать запас площади под постройки и сразу же наткнуться на Жуков/Бизнес, а можно экономить пространство, но зато лишний раз испытывать сложности с "втулением" вон той трубы через ровный строй заводов).
Исследования/Ракета==Доходы.
Что приносит Бизнесу доходы? Пользователи. Что хотят пользователи? Много фич. Что нужно сделать в Factorio? Добиться цели постройки ракеты. Что нужно, чтобы создать ракету? Провести тонны исследований и реализаций этих исследований.
В обоих случаях у нас работает правило "Чем быстрее, тем лучше", а значит тут мы попали в аналогию на 100%. В итоге у нас получается хорошая картина: чем быстрее мы сможем достичь конечной цели, тем лучше.
Единственное, тут есть пару оговорок:
Во-первых, просто поставить себе одну цель и измерить время её достижения не сильно поможет нам в аналитике, поэтому к замеру времени достижения общей цели мы будем ещё замерять время исследования различных технологий - таким образом у нас получится более детальный график.
Во-вторых, к одной общей цели я поставил ещё и обязательную вторую - перевести всё энергообеспечение на атомную энергетику и отказ от сжигания угля. Относительно Компании это естественно - она хочет, чтобы продукт требовал как можно меньше затрат на этапе эксплуатации. Относительно Игры сложнее - это просто среднеудачная попытка избавится от вечных атак жуков. Так или иначе аналогия очень удачная - фиксируем.
Персонаж==Команда.
В игре в распоряжении у нас один человек и на него придётся взвалить все аспекты команды: он и придумывает, он и реализует, он и занимается тактикой и стратегией, он и воюет с жуками. В общем ДиректороАналитикоПрожектоАрхитектороПродуктоПрограммист в одном лице. Единственное отличие, что он всё это не может делать одновременно, но поскольку эти ограничения выступают константой - на наше исследование они погрешности не даст.
Месторождения==Пользователи.
Они приходят и просто вливают в наш продукт кучу запросов. Но Бизнес этому только рад и просит освоить ещё и ещё новых месторождений.
Организационные аналогии достаточно поверхностны: я не могу придумать аналогию конкуренции, смены приоритетов потребительского рынка и прочее. Но видится, что для наших целей этого вполне хватит
Технические аналогии
Далее перейдём на более низкий уровень - в техническую плоскость. Тут уже будет больше всего, так что проходим быстро и кратно.
Конвейер/Трубы==Переменная.
Мы туда что-то положили, куда-то переместили и использовали где-то в другом месте. Идеально.
Предметы/Жидкости==Данные.
Они хранятся либо в переменных (Конвейеры/Трубы типа ОЗУ), либо на долговременной памяти (Ящики/Резервуары типа ПЗУ). Соответственно, чем их больше, тем больше затрат на ту или иную ЗУ.
Завод/Фабрики/Печи==Вычисления.
Берём значение из переменных/конвейеров и как-то ими манипулируем в попытке добиться некого промежуточного итога.
Буры/Скважины==Браузер.
По сути это просто способ доставки запросов пользователей в наше приложение. Просто и тупо.
ЖД==Сеть.
Те же переменные с некой полезной информацией, но перемещаемой на большие расстояния. Ну и она не мгновенная и не резиновая - всё как в жизни.
Электроэнергия==Стенды.
Чем больше объёмов мы захотим, тем больше всего настроем и тем больше оно будет потреблять энергии. Большой проект будет требовать больше стендов как по количеству, так и по качеству, а затраты электроэнергии позволят это отследить в сумме. Так же это позволит нам ещё проверить соотношение площади застроек к потреблению электроэнергии и точно убедиться, что мы считаем Расходы верно.
Манипуляторы/Насосы==Программная логика.
Что-куда сунуть определяют именно всякие манипуляторы разных сортов и размеров (а для жидкостей - насосы). Они потребляют немного энергоресурсов, но их очень много.
Загрязнения==Перерасход.
Идеального кода/автоматики/стендов не бывает и по любому будет что-то неоптимизированно/криво/косо. Когда мы достигнем определённого Загрязнения/Перерасхода, то сразу же взбудоражутся Жуки/Бизнес и придётся иметь с ними дело. Именно поэтому я поставил переход на Атомную энергетику как основную цель. Именно поэтому у нас идёт настоящий пункт.
Стены/Турели==Отчёты/ИБ.
Жуки/Бизнес с определённого этапа развития продукта начнёт банально мешать производству: Бизнес будет требовать различные отчёты, объяснения, корректировки и прочее; Жуки - просто приходить и крушить. Постройка и обслуживание Стен и Турелей как раз является хорошим примером "отвлечения" на все эти мешающие аспекты.
Так же у Стен/Турелей есть и другой аспект отвлечения - это вопросы ИБ. Достаточно нередко бывает так, что команда просто пилит себе крутой продукт, а тут приходят ИБ и просят вне плана срочно закрыть какую-то уязвимость. И это будет таким же "мешающим" фактором, как и Отчёты для Бизнеса. В общем, у нас два в одном, и с учётом необходимости расширения затраты на оборону будут только расти.
Радары==Мониторинг.
Тут всё просто: затраты сравнительно малые, но позволяют следить за тем, что как работает.
Лаборатории==Бизнес-логика.
Вроде бы простая на словах вещь, за которой скрывается тонны сложных манипуляций с заводами/вычислениями, конвейерами/переменными и подобным. Но именно исследования в Лабораториях являются единственным путём достижения наших целей (игры и бизнеса)
Ну и в целом всё. Всякие мелкий штуки вроде "Оружие", "Автомобиль", "ЛЭП" и прочее я классифицировать не буду т.к. они незначительные и больше запутают.
Соединяем Архитектуру и Игру
Начинаем соединять Архитектурный стиль и игру: берём определённый стиль, переводим её в игру по вышеуказанным аналогиями и пробуем строить. Ну и фиксируем полученную в ходе информацию для будущего анализа.
Например, если мы сравним игру с Монолитом и Микросервисами, то подход к постройку заводов будет кардинально разный:

Пока это план, а там в игре уже посмотрим как всё будет получаться.
Дальше, нам нужно будет сравнить все эти стили по ряду параметров и вот они:
Параметры
Evolvability - возможность развития. Показывает, как быстро продукт может обрастать различными фичами. Относительно игры, это скорость проведения исследований и скорость достижения двух, основных целей: запустить ракету и перейти на атомную энергетику. Плохая Evolvability - это ког��а фичи выходят редко (условно, раз в несколько часов игры). Хорошая - когда быстро (условно, раз в 10 минут).
Сценарий:
Замерять будем по ходу игры;
Если выполнилось исследование или частично/полностью выполнилась цель игры - фиксируем время игры;
Повторять до победы.
Perfomance - производительность. Показывает, сколько пользователей сможет потянуть приложение. Относительно игры мы организуем поступление бесконечного количества сырья в точку входа Завода и посмотрим, какое количество ракет, спутников и колб сможет выдать наш завод. Это значение назовём «Базовым производством» и будем сравнивать его с другими показателями в других экспериментах. Плохой Perfomance - это когда за игровой час мы еле-еле сможем собрать несколько ракетных модулей и произвести пару сотен колб. Хорошая - когда за тот же час ракетных модулей производится сотни, а колб - десятки тысяч.
Сценарий:
Замерять будем после финала;
Убиваем всех жуков;
Организовываем очередь исследований (при необходимости - бесконечных исследований);
Ставим бесконечные сундуки на места приёмки руд/нефти в приложении (т.е. ЖД-станции);
Очищаем все хранилище жидкостей (чтобы не переполнилось);
Замеряем производство частей ракет, спутников и колб за 1 час.
Deployability - разворачивание. Насколько быстро можно развернуть второй и последующие экземпляры продукта. Опять же просто применим вертикальное масштабирование и замерим время. Плохой Deployability - это когда второй экземпляр приложения разворачивается (перенос/настройки/отладка/запуск) несколько часов. Хороший - когда примерно час и приложение готово к работе.
Сценарий:
Замерять будем после финала;
Убиваем жуков;
Открываем карту, для выбора места для копии завода (при необходимости);
Изучаем скорость (10) и грузоподъёмность (3) дронов до 6;
Копируем основной завод на свободное место;
Засекаем время;
Строим второй завод из собственных запасов построек;
Подключаем столько же месторождений (только железо и медь);
Подключаем поставку воды;
Подключаем ЖД сеть.
Scalability - масштабирование. Оно показывает, насколько безболезненно приложение сможет вырасти горизонтально или вертикально. Под горизонтальным ростом у нас будет идти попытки увеличить производительность за счёт увеличения числа заводов в существующей цепочке; вертикальное - создание второй цепочки (за одно и проверим Deployability). Плохое Scalability - когда сам процесс масштабирование делается долго и/или прирост производительности при этом далёк от коэффициента масштабирования (например, сделали 2 реплики приложения, а прирост всего x1.2). Хорошее - когда смасштабировались мы быстро, а прирост близок к коэффициенту.
Сценарий:
Замерять будем после финала;
Замеряем производство при вертикальном масштабировании:
Меняем все конвейера на синие;
Меняем все манипуляторы на пакетные;
Меняем все заводы на тип 3;
Ставим бесконечные сундуки на места добычи руд/нефти;
Строим дополнительные фабрики на территории текущего завода (сколько получится физически вместить);
Замеряем производство колб, частей ракет и спутников за 1 час.
Замеряем производительность при горизонтальном масштабировании:
Строим вторую копию завода по чертежам (то, что делали в Deployability);
Подключаем новую ЖД-сеть к старой;
Удваиваемым количество поездов;
Ставим бесконечные сундуки на места добычи руд/нефти;
Замеряем производство колб, частей ракет и спутников за 1 час.
Сравниваем полученный прирост после обоих типов масштабирования с тем, что мы получили Perfomance.
Agility - гибкость. Сколько времени требуется, чтобы разработать новую фичу. Относительно игры это сколько потребуется времени, чтобы открыть новое производство чего-либо. Плохая Agility - это когда внедрение нового производства занимает больше времени, чем у других Архитектурных стилей. Хорошая - соответственно, быстрее.
Сценарий:
Замерять будем по ходу игры;
Когда мы запускаем новое производство чего-либо - фиксируем время;
Повторяем до победы.
Fault Tolerance - отказоустойчивость. Насколько приложение хорошо переживает разные сбоя. В игре будем пробовать "ломать" различные участки завода и смотреть, что из этого получится. Так как поломать систему можно двумя способами (кривыми руками и чрезмерной нагрузкой), то и реализуем мы два сценария. Плохое Fault Tolerance и быстро упадёт под возросшей нагрузкой, и быстро сломается просто от наличия хабов (одного участка завода, от которого зависит много других заводов). Хорошее - когда завод упорно продолжает работать, даже когда входных запросов стало в несколько раз больше, а жуки поели половину строений.
Сценарий 1:
Замерять будем после финала;
Отключаем подачу патронов в турели;
Засекаем время;
Убегаем в безопасное место;
Ждём, когда прекратится производство частей ракеты;
Фиксируем время.
Сценарий 2:
Замерять будем после финала;
Фиксируем текущее количество поездов;
Спавним локомотивы, вагоны и топливо;
Засекаем время;
Равномерно заполняем ЖД поездами под разные маршруты. До упора. С паузами ~5 минут;
Ждём, когда прекратится производство частей ракеты;
Фиксируем время;
Фиксируем общее количество поездов
Configurability - возможность конфигурации. Как гибко можно управлять приложением для подстройки его под текущие приоритеты. Замерять будем путём перенаправления всех ресурсов отдельно на ракеты и отдельно на колбы, игнорируя другие производства. В хороших архитектурах это можно быстро делать путём нескольких действий и это сразу даст заметный прирост, а в плохих архитектурах мы будем вручную отключать каждый заводик, что сильно растянется по времени. А ещё и прирост может быть мизерным.
Сценарии:
Замерять будем после финала;
Перенаправляем ресурсы на ракеты:
Убиваем всех жуков;
Ставим бесконечные ящики на сырьё;
Фиксируем время старта процесса реконфигурирования завода;
Перенаправляем разветвители конвейеров, манипуляторы и поезда на производство ракет и спутников. Остальные производства максимально изолируются, но без сноса и доп. строительства;
Фиксируем время окончания реконфигурирования;
Замеряем увеличение целевого производства ракетных частей и спутников за 1 час;
Перенаправляем ресурсы на колбы:
Убиваем всех жуков;
Запускаем очередь исследований без белых колб;
Ставим бесконечные ящики на сырьё;
Фиксируем время старта процесса реконфигурирования завода;
Перенаправляем разветвители конвейеров, манипуляторы и поезда на производство колб и доставки их в лаборатории. Остальные производства максимально изолируются, но без сноса и доп. строительства;
Фиксируем время окончания реконфигурирования;
Замеряем увеличение целевого производства ракетных частей и спутников за 1 час;
Сравниваем получившиеся цифры с Базовой производительностью и оцениваем затраченое на реконфигурирование время. Вычисляем показатель эффективности (KPI) по формуле "((Коэффициент прироста - 1 ) + ())/время" - чем он выше, тем лучше.
Domain Partitioning - разделение обязанностей частей завода. Если к карте завода можно быстро понять назначение определённого производства и его связь с другими производствами - это хорошая Domain Partitioning. А если у нас появляется множество мелких, хаотичных и плотно расположенных производств - значит это плохо.
Сценарий:
Замерять будем после финала;
Делаем скриншот карты без отметок;
Цветами разделяем различные производства;
Считаем количество мелких, плотноприлегающих друг к другу зон.
Abstraction Level - абстрагирование. Показывает, насколько хорошо определённые компоненты приложения выполняют какую-то глобальную задачу (бизнес-логика, оркестрация, хранение и прочее). В игре мы поделим всю нашу карту на зоны "пользователи", "сырьё", "хранение" и прочее и попробуем связать всё это стрелками друг с другом. Плохая Abstraction Level - это если у нас нельзя взять группу рядомрасположенных производств и сказать "эта группа отвечает за то-то". Хорошая - если всё это отлично группируется и может быть названо назначение этой группы без исключений.
Сценарий:
Будем замерять после финала;
Делаем скриншот карты без отметок;
Цветами разделяем следующие зоны:
Ресурсы - добыча их aka "Пользователи";
Переработка ресурсов - переработка сырья aka "Frontend";
Основной завод - центральное производство конечной продукты aka "Backend";
Элетро - электростанция aka "ЦОД";
Ж/Д - точка поставки ресурсов aka "API/HTTP(S)";
Хранилище - место складирования чего-либо aka "БД";
Шина - место логического управления производством ака "Оркестрация"
Замеряем, сколько зон пересекаются друг с другом и сколько из них дублируется.
Elacticity - эластичность. Как приложение может самоподстраиваться под текущую нагрузку. Тут уже отдельно замерять ничего не надо, а просто сложим показатели Scalability и Deployability.
Сценарий:
Замерять будем после финала.
Получаем от горизонтального Scalability процент прироста производства;
Получаем от Deployability время разворачивания экземпляра завода;
Получаем контрольный показатель эффективности (KPI) по формуле "(Коэффициент прироста - 1 )/время" для каждого из трёх ключевых ресурсов. И будем его использовать как сравнительный параметр для других Архитектурных стилей
Testability - тестирование. Насколько хорошо приложение поддаётся тестированию. И не просто протестировать входные точки сервиса (типа API), а необходимо именно подключаться автотестами в середине логики приложения. Плохое Testability - это когда мы тратим много времени, чтобы настроить тест-кейсы какой-то отдельной бизнес-логики. Хорошее - когда это занимает буквально несколько минут.
Для того, чтобы правильно и единообразно воспроизвести этот сценарий, мною установлены тиры (Tier) - это как далеко нужно подать автотесты от производства колб и ракет, чтобы тестировать различные части производства. То есть Tier 3 - это максимально близкие расходники к колбам/ракете, а Tier 1 - расходники колб/ракет за 2 цикла производства. Ну и Base - это всегда исходные руды и жидкости.

Таким хитрым образом мы даже сможем увидеть, на каком этапе производства насколько сильная просадка по производительности у нас получается.
Сценарий:
Будем замерять после финала;
Тестируем Tier1 (бесконечная Медь, сталь, железо, пластмассы, сера и дизель):
Убиваем всех жуков;
Засекаем время старта процесса навешивания автотестов;
Подключаем максимально возможное количество бесконечных сундуков с ресурсами для Tier1;
Очищаем все хранилище жидкостей (чтобы не переполнилось);
Фиксируем время окончания реализации тестов;
Замеряем производство частей колб ракеты и спутников за 1 час;
Тестируем Tier2 (бесконечные зелёные/красные/синие платы, медь, сталь, железо, ракетное топливо, аккумуляторы, солнечные панели и радары)
Убиваем всех жуков;
Засекаем время старта процесса навешивания автотестов;
Подключаем максимально возможное количество бесконечных сундуков с ресурсами для Tier2;
Очищаем все хранилище жидкостей (чтобы не переполнилось);
Фиксируем время окончания реализации тестов;
Замеряем производство колб, частей ракеты и спутников ��а 1 час;
Тестируем Tier3 (бесконечные Блоки управления ракетами, ракетное топлива, спутники и конструкций малой плотности)
Убиваем всех жуков;
Засекаем время старта процесса навешивания автотестов;
Подключаем максимально возможное количество бесконечных сундуков с ресурсами для Tier3;
Очищаем все хранилище жидкостей (чтобы не переполнилось);
Фиксируем время окончания реализации тестов;
Замеряем производство колб, частей ракеты и спутников за 1 час;
Тестируем Base (бесконечная генерация руд/нефти в местах их добычи)
Убиваем всех жуков;
Засекаем время старта процесса навешивания автотестов;
Подключаем максимально возможное количество бесконечных сундуков с рудами/нефть в местах их добычи;
Очищаем все хранилище жидкостей (чтобы не переполнилось);
Фиксируем время окончания реализации тестов;
Замеряем производство колб, частей ракеты и спутников за 1 час;
Полученные цифры от каждого Tier'а сравниваем с Максимальной производительностью (из Perfomance).
Cost - стоимость. Насколько дорого обходится разработка и обслуживание продукта. По сути мы просто в игре замеряем площадь, занимаемой нашим заводом, общую площадь построек и, отдельно, сравним его с энергопотреблением. Плохая (большая) Cost мы получим, если наше приложение разрослось на огромную площадь карты. Хорошее - если получилось всё уместить в относительно легковестный завод.
Сценарий:
Замерять будем после финала.
Делаем скриншот карты без отметок;
Узнаём координаты угловых частей общих построек;
Узнаём координаты угловых частей общего производства;
Высчитываем площадь двух получившихся фигур;
Накладываем фигуру на карту и помечаем вычисленную площадь
В общем, работы предстоит много. Самое главное тут не выбрать прямо точный к реальности регламент проведения эксперимента для замера того или иного параметра, а делать каждый эксперимент с одинаковым подходом и единым итогом - в конце концов нам важно именно сравнить Архитектурные стили друг с другом в относительных величинах.
Правила игры
Далее, давайте обговорим, что мы можем делать по ходу игры, а что нельзя - это поможет нам максимально точно воссоздать среду эксперимента. Начинаем.
Правила игры
Версия игры - 1.1.42;
Режим игры - стандартный;
Всегда берём одну и ту же сгенерированную карту
Зерно - 2426146951
Ресурсы - стандартные;
Вода - максимальный масштаб, покрытие 50%;
Деревья - всё минимум
Скалы - отключены;
Тип местности - стандартный;
Враги:
Вражеские базы - стандартные
Размер начальной области без жуков - максимальная;
Экспансия - отключена;
Эволюция - отключена;
Сложность:
Стоимость рецептов - стандартная;
Загрязнение - стандартная;
Во время основной игры - можно использовать:
Команду на замер времени жизни карты - для фиксации времени важных событий;
Команду на вывод координат;
Чит на перемотку времени. Стоять без дела придётся часто - пожалейте моё время;
Чит на спавн стартового комплекта вещей (об этом ниже) для идентичности лабораторных условий;
Если часть стартового комплекта потеряется во время игры (кроме тех, что с меткой "невосполнимый") - можно заспавнить новый взамен;
После финала - можно:
Всё вышеуказанное;
Чит на удаление врагов;
Чит на удаление дронов;
Чит на открытие карты;
Искусственные ограничения:
Нельзя производить предметы руками - исключительно в зданиях. Причина проста - чтобы не сбивать ручным производство итоговую статистику;
Нельзя использовать "синие" типы конвейеров во время основной игры. То есть до финала игры можно максимум можно построить Красные конвейера, а Синие будут использоваться только при замере вертикального масштабирования;
Нельзя уничтожать улей, кроме случаев, когда на месте стройки на миникарте видно улей. Ограничивающее меня правило, чтобы не было желания перебить всех жуков в округе и избавится от аспекта бизнеса и безопасности;
Нельзя наполнять заводы вручную - только выкладывать на конвейер (вручную или через манипулятор). Исключение - добавление твердотельного топлива. Сделано это, чтобы не возникал соблазн перетаскивать сырьё вручную в разные части базы и тем самым вручную увеличивать производительность (реально, выглядит так, как будто если посадить программиста на Прод, то он будет производить расчёты вместе с компьютером... бред);
Нельзя использовать транспортные или строительные дроны (кроме стартовых строительных на персональной дронстанции). Дроны дают хороший буст в производстве под конец игры, но при этом сводят архитектурный аспект к минимуму - поэтому на это накладывается запрет;
Нельзя использовать логические сети до финала игры. Логические сети сильно скажутся на времени постройки завода: они имеют непредсказуемое время реализации и непредсказуемое окупаемость. И то и то будет паразитно в сравнении;
Нельзя ставить игру на паузу для продумывания дальнейших действий - пауза только для перерывов и естественных потребностей. Это позволит учитывать и время обдумывания какого-то решения, которое всегда присутствует в работе команды разработки. В общем, берём это в учёт;
Нельзя пользоваться чертежами, скачанными из Интернета или из предыдущих игр. Конечно, странно придумать программиста, не пользующемся StackOverflow, но помощь уже готовых чертежей выгладит сильно читерным (это как найти на StackOverflow не кусок полезного кода, а сразу идеально работающую программу). В общем, лучше просто это забанить и придумывать всё с нуля методом проб и ошибок;
Никаких модов. Только стандартный геймплей.
Искусственные привилегии:
Стартовый набор вещей:
Силовая броня МК2 х1
Портативный термоядерный реактор х2
Экзоскелет х4
ПНВ х1
Устройство игнорирования конвейров х1
Персональная дронстанция МК2 х4 (игра без дронов всё ровно что написание кода без копипаста)
Малый блок аккумуляторов х7
Строительные дроны х100
Автомобиль х1
Пистолет-пулемёт х1
Патроны х210 (невосп)
Деревянный ящик х100 (невосп)
Желтый конвейер х5000 (невосп)
Подземный желтый конвейер х100 (невосп)
Разделительный желтый конвейер х100 (невосп)
Желтый манипулятор х200 (невосп)
Красный манипулятор х100 (невосп)
Деревянный ЛЭП х1000 (невосп)
Труба х5 (невосп)
Бойлер х5 (невосп)
Паровой генератор х5 (невосп)
Бур х50 (невосп)
Насос х1 (невосп)
Твердотельный бур х31 (невосп)
Каменная печь х51 (невосп)
Серая фабрика х50 (невосп)
Разбитый корабль х1 (невосп)
Древесина х1 (невосп)
Пистолет х1 (невосп)
Железная плита х8 (невосп)
Всё это добро мы сделаем в виде сценария: разложим всё по коробкам рядом с кораблём, а часть появится вместе с персонажем. Потребуется чуть больше минуты на то, чтобы всё это собрать и скомплектовать на себе, но ничего страшного.
В общем, всё это выглядит вот так:






Ссылка на сценарий (Поместить в %USER%\AppData\Roaming\Factorio\scenarios)
Так же сценарий позволяет делать одну крутую вещь - записывать реплей.
В качестве замера времени мы будем использовать время жизни карты - она покажет точное время без всяких пауз/перерывов и прочее. Именно поэтому, когда мне нужно будут сесть и продумать свои дальнейшие действия ставить игру на паузу запрещается - так мы имитируем грумминги, работу архитектора и прочее.
Тактика/Стратегия
Как и любой проект, он начинает с пилота и каждый раз нам придётся начинать с постройки первых строений плюс-минус одинаково. Максимум, что мы сможем себе позволить тут - это представлять Архитектурный стиль нашего будущего завода и заранее стремиться строить под него. Именно поэтому прямо большой разницы в старте игры не будет, но как только будут изучены ЖД и грузовые поезда - с этого момента мы уже сможем сделать первую ЖД-сеть (подключить "пользователей") и дальше мы обязаны придерживаться выбранного Архитектурного стиля.
В итоге у нас должно получиться следующие жизненный циклы продукта:
Пилот - просто налаживаем базовое производство, но ровно до тех пор, пока не изучим и не внедрим ЖД;
Обрастание фичами - развиваем производства нашего завода, проводим большую часть исследований и плавно стремимся к конечным целям;
Рывок до конечной цели - когда ракета и АЭС уже будет близко, то стоит переключить все ресурсы на неё, чтобы выпустить её быстрее. В общем, это Киллер-фича;
Подведение итогов и эксплуатация - тут мы уже будем имитировать все трудности эксплуатации и замерим оставшиеся параметры Архитектурного стиля.
По ходу игры мы будем фиксировать следующие время:
Исследование завершилось;
Цель игры выполнена;
Новое производство чего-либо важного для цели игры запущено;
Другие важные события, например:
Подключение пользователей;
Первая атака жуков;
Жуки сломали что-то важное;
Кончилось электричество;
Остановка производства исследований.
Все вышеуказанные временные замеры помогут нам в сравнении архитектурных стилей между собой.
Ну и приступаем!
Монолит
Начинать будем с самым негативно-оценённым Архитектурным стилем. Относительно игры у нас будет простая идея: делать как приходится, даже если придётся сломать себе мозг в конце
Особенности у нас такие:
ЖД используется только для сырья (ака Пользователи), а весь завод работает исключительно на конвейерах и трубах;
Выходящее из последнего пункта - всё будет находится рядом т.е. со стороны завод будет представлять из себя огромный комплекс.
Пилот
Старт был достаточно лихой: имея свободу в действиях и легко сделав базовое производство (плиты, первые колбы, ЖД). Проблемы начались когда я попытался внедрить ЖД: во-первых, к этому моменту уже опустошилось месторождение железа; во-вторых, поскольку у меня не было никакого запаса - резко возникла проблема с желтыми конвейерами (красные вообще еле производятся). В итоге пришлось останавливать производство железных и стальных плит и, буквально, выковыривать все некритичные части конвейера. В итоге их хватило тютелька-в-тютельку.

Обрастание фичами
Внедрение ЖД решила проблему с железом - я сразу получил буст по производству его раза в 3, но со сталью это проблема решилась не сразу и чувствую, что мы эту проблему будем испытывать ещё часто.

Заражение уже подходит к жукам, но с обороной у нас всё в порядке: я понаставил турелей, доставляю им патроны поездом. В общем, рано или поздно начнётся первая атака.

После того, как ЖД разогналось, ресурсов стало хватать вдоволь. Единственное, что сказывается ряд неудачных решений с синими колбами - для них всё время не хватает ингредиентов (двигателей), а разместить больше заводов по производству двигателей простое не где. Собственно, в этом и фундаментальная проблема Monolith - всегда не будет хватать места.

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

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

Когда запустилось АЭС сразу возник большой профицит в электроэнергии, а значит, что можно переходить на электрические печи. Займусь этим как только будет время.

Рывок до конечной цели
К моменту постройки Ракетной шахты у меня оставалось 3 видимые цели: перевести переплавку на электропечи, собрать ракету. И с последним возникли проблемы.

Ракета собиралась медленно т.к. производилось очень мало Ракетных модулей, а производилось их очень мало из-за банального: не хватало "Зелёных" микросхем т.к. их перехватило производство "Синих" микросхем, а уже их перехватило производство "Жёлтых" колб. В итоге движение к двум конечным целям стали очень медленными. В итоге пришлось максимально искать "застойные" производства и перенаправлять их вышеуказанные цели. Это помогло, правда производство стало прямо ощутимо запутанней.

Итого:
Затрачено игрового времени 23:47:36
Затрачено реального времени 8 дней
Убито 32175 жуков

То есть мы с этой архитектурой справились меньше чем за сутки игрового времени. И это выглядит достойно, пока мы не начнём ставить эксперименты над этой архитектурой.
Видео реплея: YouTube и VK Видео
Итоговая карта:


Файл с сохранением (Поместить в %USER%\AppData\Roaming\Factorio\saves)
Подведение итогов и эксплуатация
Далее смотрим, какие характеристики приложения у нас получились по окончанию разработки.
Evolvability
По ощущениям, разработка шла вполне ожидаемо (сначала очень быстро, а потом очень медленно). Но тем не менее ощущается некоторое чувство сбалансированности - исследование часто завершается именно тогда, когда я готов его уже применять. Однако дальше продолжать играть с такой архитектурой желания нет.
Итого у нас получилось в формате таблицы

Если перевести это на диаграмму, то получим следующий график:

На графике видно ощутимый прирост при изучении Переработки Ядерного топлива и исследовании Космического пакета. Эти исследования самые ресурсоёмкие в рамках основной игры и Monolith справлялся с ними о-о-очень медленно. Ну и по ощущениям я скажу, что именно в этих двух исследованиях я очень простаивал - я тупо стоят и ждал, когда же они исследуются, чтобы я мог продолжить строительство.
Agility
Что у нас по старту производств покажет следующая таблица:

По таблице видно, что нам удалось вообще не конфликтовать с ульями жуков - то есть грубо говоря мы уложили все наши постройки в стартовую область. Ну и Monolith у нас не было временных построек перед началом строительства основной архитектуры: как мы построили первые здания в самом начале игры - так они и просуществовали до самого конца.
В целом график более плавный, чем с Исследованиями и прямо явный стопор был только когда запускали ЖД (ака Пользователей):

То есть получилось очень даже ровно, а значит вполне прогнозируемо.
Эти события можно разделить на несколько групп и сравнить, насколько мы быстро организовали лаборатории и колбы, как быстро мы организовывали производство ключевых расходников, как дела у нас с жуками и энергетикой. Но поскольку пока что сравнивать не с чем - оставим это на вторую часть.
Perfomance
Далее мы хотели узнать, сколько в принципе можно вынести производительности из нашего завода. Для этого мы поставили бесконечные сундуки с рудами/нефтью на место приёма их в приложение (т.е. на ЖД-станции) и получили следующие цифры:
Производство ракетных модулей | 71 |
Производство спутников | 1 |
Производство колб | 5862 |
У нас явно виднеется хорошая новость - производство ракет очень близка к балансу т.к. по игре на каждые 100 ракетных модулей необходимо по 1 спутнику. То есть к моменту производство одного спутника у нас ракета будет готова на 71%. Это хороший (хоть и не идеальный результат).
А вот производство колб у нас не очень впечатляющее и я думаю, что в других архитектурах цифры будут больше. Посмотрим.
Эти цифры мы будем использовать как основу для сравнения с другими экспериментами - насколько у нас улучшится производство, когда мы будем масштабировать приложение или тестировать его части.
Deployability
Теперь попробуем узнать, сколько времени у нас займёт на то, чтобы развернуть полную копию всего нашего завода и подключить его к старому. Ну и будем описывать возникающие проблемы и замерять их время.

Подключить месторождения, ЖД, воду и прочее не составило труда. Ровно как и построить основные здания. Проблема, как и ожидалась, была с Желтыми и, особенно, с Красными конвейерами - они сожрали две трети всего времени разворачивания. В итоге на полное разворачивание у меня ушло 7.88 часа, при этом через 3.3 часа у меня всё было уже настроено, но не подключено конвейерами - я просто сидел и ждал, когда произведутся конвейера.
По итогу у нас получились следующие цифры:
Событие | Количество минут (со старта работ) |
Нехватка конвейеров | 200 минут |
Запущено второе производство конвейеров | 248 минут |
Полный запуск второго завода | 473 минут |
В целом, поскольку величина завода явно не очень большая, вышеуказанное время можно считать хорошим. Особенно, если улучшить приложение и генерировать достаточное число конвейеров. Или просто избрать чуть другую тактику - сначала всеми силами отстроить второе производство конвейеров, а потом уже весь остальной завод.
Configurability
Ну и начинаем наши эксперименты уже над завершённой реализацией. И первое у нас на очереди - это проверить, как наше приложение успешно конфигурируется. Наша задача тут будет перенаправить всё производство отдельно только на производство ракет и отдельно только на производство колб. При этом всё это делать без сноса или строительства - в нашем распряжении только управление конвейерами, манипуляторами и поездами.

Получились следующие данные:

На самом деле это было мерзко: в Monolith-архитектуре нет единой точки переключения потока расходников до определённого производства и мне приходилось пробегаться по всему приложению и поворачивать манипуляторы на каждом заводе, чтобы отключить его от не целевого потребления ресурсов. При этом всё приходилось лично делать персонажем - подходить к каждому заводу и править - то не никакого удалённого правления не получилось. И при этом шанс запутаться оставался достаточно высоким: нужно было тратить много времени на проверку/перепроверку того, чтобы не отключить что-то не то, а так же я до сих пор не уверен, что отключил всё необходимое. Поэтому это и заняло много времени. ч
Особенно много времени заняло именно с производством ракет/спутников т.к. отключать приходилось добрые две трети всего завода. Так что у нас тут имеется прямая зависимость времени настройки и объёма отключаемых производств.
Коэффициент прироста ракет при этом оказался хорошим - почти в 2 раза. Спутников поменьше - на 15%ю А вот производство колб от такой манипуляции стало хуже на 15%. А причина в том, что в Monilith нарушился тонкий баланс производства и потребления колб - часть колб просто не успевали производиться в нужном объёме и поэтому производства других колб просто быстро переполнялось и останавливалось. Ну и в сумме это дало больше понижение прироста колб.
По итогу мы получаем, что в случае приоритета на ракету мы за 27:02 получили 200% производства ракет и 115% производства спутников - то есть показатель эффективности будет ((200% -1) + (115% - 1))/27,033 ~ 0.042.
А вот колбы у нас покажут отрицательную эффективность: (85%-1)/9.76 ~ -0,015 . И это максимальный провал...
Testability
Далее переходим к тестированию приложения.
И тут есть отличие от замера Perfomance. Во-первых, мы будем тестировать приложение не с точки подключения Пользователей (ЖД), а будем врезаться автотестами в самую гущу приложения и пробовать нагружать его частично, чтобы находить самые уязвимые места. И наоборот - смотреть, как приложение работает от лица пользователей. Во-вторых, мы ещё будем замерять время, которое потратили на организацию автотес��ов - так мы поймём, какой объём работ требуется для организации подобного тестирования приложения.

Начнём с замеров производства. И у нас тут получились следующие цифры:

Если изучать результаты автотестов внутри самого приложение (Tier'ы) то видно, что наша архитектура максимально хорошо работает при генерации большого количества расходников напрямую в производство ракет (Tier3) - производство ракетных модулей и спутников повышается многократно и близко к максимальному. Но вот стоит только сделать шаг назад по ресурсам и прирост заметно падает: всего 17% для ракет в Tier2 и Tier1 и немного лучше со спутниками - там в 3 и в 2 раза. Так что автотесты ценность показали - мы знаем, что в какой части приложения у нас начинаются проблемы с ракетостроением.
С производство колб прирост уже не такой хороший и почему-то чем он ближе к производству, тем быстрее он падает. А причина тут всё так же балансе производства колб - если одна из колб еле-еле производится, то остальные уходят в перепроизводство и останавливают производство. Это проблема. И как её решить - вообще не понятно.
Ну и базовое производство у нас тут тоже тестировалось (грубо говоря от браузера пользователя) и это показало падения прироста производства ракетных модулей на ~16% и колб на ~3%. То есть немного производительности мы теряем на геораспределённых пользователях.
Теперь давайте поговорим про время организации автотестов. Выглядит оно вот так:

Из-за того, что в Monolith всё крайне плотно построено и организовать единый алгоритм тестирования не представляется возможным - буквально для каждого ресурса в автотестах приходилось тщательно выбирать место и ещё включать свою творческую составляющую, чтобы установить там достаточное количество бесконечных ящиков.
По итогу результат на лицо: если расставить на предназначенных для этого местах приложения (точки подключения пользователей или на местах самих пользователей), то вся работа занимает около 10 минут. А вот если лезть уже в глубь приложения - это работа на час и больше.
При этом тут наблюдается зависимость времени от количество подключаемых бесконечных ресурсов - в Tier 2 из больше всего, а значит на него потратилось больше всего времени.
В общем видится так, что в плане Testability наш Monolith проиграет абсолютно всем. Но пока закадывать не будем и посмотрим ещё.
Scalability
Далее пробуем сделать вертикальное и горизонтальное масштабирование нашего приложения и замерить его производительность. В идеале в обоих случаях было бы достичь увеличение производства в 2 раза, но получится ли это по факту - посмотрим.
Для горизонтального масштабирования мы просто возьмём тот завод, что мы построили в Deployability - мы построили полную копию завода, а значит ожидаем x2 увеличение продуктивности.
А для вертикального масштабирования мы будем максимально улучшать наш текущий завод: устанавливать синие конвейера, пакетные манипуляторы и впихивать столько заводов, сколько влезет. Если у нас получится впихнуть в 2 раза больше заводов и получить в 2 раза больше производства - считаем, что это идеал вертикального масштабирования.
Цифры на экран:

Горизонтально масштабирование увеличило производство, но дошло всего до ~45%. Кроме спутников, конечно - они как им как будто только этого не хватало. Насколько я могу судить, потери произошли тут на наполнении нового производства во втором экземпляре приложения - там оно массово начало тратить ресурсы не на ракеты, а, например, на наполнение ящика с желтыми и красными конвейерами. Может быть если подождать достаточно много цифра получится и больше, но явно не x2.
С вертикальным масштабированием всё сложнее т.к. во время работ я не особо нашёл места, где бы можно было бы добавить дополнительных заводов - всё было плотно и занято. А если и находил и увеличивал, то явно не от целевого производства. По итогу как такового масштабирования и не было. Но вот переход на синие конвейера взяли своё и мы получили прирост примерно в 70%. То есть у меня получился запас производительности по заводом ещё изначально и единственное, что не хватало ему для высокопроизводительной работы - быстрая доставка сырья в нужные части завода.
Хотя вот производство спутников под это утверждение не попало - там на это работает всего одна цепочка по одному заводу и на него переход на синие конвейера сильно роли не играют. То есть хоть мы и видим прирост в 2 раза, но это скорее всего связано с эффектом низкой базы. Ну а в горизонтальном масштабировании бы получили прирост в 3 раза просто потому-что таких цепочек по производству спутников стало две (хотя в идеале прирост тогда должен быть 4 раза).
Elacticity
Тут мы оцениваем опять же время, затраченное на горизонтальное масштабирование (Deployability), но уже смотрим на прирост производительности. Таким образом мы высчитываем KPI, который сам по себе ничего не показывает, но даёт возможность сравнения с другими Архитектурными стилями. Поэтому мы их просто высчитаем и оставим так. Главное понимание тут, что чем больше это число, тем лучше.
У нас получилось из двух прошлых экспериментов, что за 473 минут мы получаем прирост ракетных модулей на 44%, спутников на 200% и колб на 45%.
Итого, считаем KPI по нашей формуле:
Ракетные модули: (1.44-1)/473=0.00093
Спутники: (3-1)/473=0.00422
Колбы: (1.45-1)/473=0.00957
Cost
Тут мы высчитываем площадь нашего завода. При этом высчитываем общую площадь (т.е. любых построек) и полезную площадь (где у нас происходит основное производство). Логика тут проста: чем плотнее нам удалось уместить весь наш завод - тем меньше бюджета нужно для сооружения его. А значит он будет более дешёвым в написании.
Если ориентироваться по атакам жуков, то основные проблемы были только на юго-востоке, а значит с ценой производства монолит будет в топе. Замеряем:
Параметр | Значение |
Площадь общая (любые постройки) | 634489 m2 |
Площадь полезная (производственные здания) | 72545 m2 |
Энергопотребление | 125 МВт |

Fault Tolerance
Тут мы определяем, насколько наше приложение с нашим Архитектурным стилем способно сопротивляться сбоям и работать не смотря ни на что его частично погрызли жуки. Логика тут такая - чем меньше у приложения общих точек отказа, тем лучше. А найти точку отказа помогут жуки и время, за которое они разнесли приложение.
Тут всё просто: жуки прорвали оборону через 82 минуты. Будем использовать это число для сравнения.
Но это не единственный способ сломать приложение - ещё оно может сломаться от перегруза (типа DDoS-атака). К сожалению, Factorio имеет большую дефолтную защиту от подобных проблем, поэтому единственное, где я могу хоть как-то нагрузить приложение - это нагрузить точку входа приложения поездами. Будем увеличивать количество поездов до тех пор, пока приложения не "встанет".
На то, чтобы полностью застопорить работу завода путём посылания "паразитных" поездов (трафика), ушло 2:30:44 времени
По количеству поездов ситуация следующая:
Базовое количество поездов | Проблема стала видимой | Началось снижение производительности производства | Засорилась ЖД - стало сложно добавлять новые поезда | Полная остановка производства |
19 (100%) | 33 (173%) | 68 (357%) | 82 (431%) | 110 (578%) |
То есть в целом мы можем держать максимум 3-хкратную нагрузку. Примерно.
Domain Partitioning
Разделение карты на домены даёт спорные результаты: есть и большие зоны одного производства и мелкие, плотно стоящих рядом. И именно с мелкими будут возникать наибольшее количество проблем при расширении.

В целом видна попытка выноса всего либо в прямоугольники, либо в линии, но не всё пошло так просто.
Итого:
Хорошо разграниченных зон: 33
Плотно стоящих зон: 30
В целом баланс хороший, но в идеале Плотно стоящих зон быть вообще не должно
Abstraction Level
Если же анализировать зоны по типу, то тут всё замечательней: явных пересечений нет, а отдельно стоящих зон вообще всего две (не считая "ресурсы"). Это означает следующее: на высоком уровне приложение будет понятно даже тому, кто недавно начал вливаться в работу над Проектом. Другое дело, что если он начнёт углубляться в некоторые зоны - там может зависнуть надолго.

Общий вывод по Монолиту
Пока ещё вышеуказанные данные являются голыми т.к. нам не с чем их сравнивать. Но в следующих статьях мы будем делать другие Архитектурные стили и сравнивать именно с Монолитом.
По собственным ощущениям скажу, что я вижу в Монолите следующие преимущества:
Бюджет - жуков мы задевали мало и только с одной стороны, а ульи вообще не уничтожали. То есть мы смогли только чуть-чуть превысить бюджет. Энергопотребление так же выглядит низким.
Время - мы успели сделать всё почти за сутки, что является хорошим показателем. Всё потому-что мы следовали простому правилу "Нужно сделать - делаем"
Горизонтальное масштабирование - самих построек немного и они уже соединены конвейерами в нужном порядке. Просто скопировал, вставил, подождал и, считай, работает. Работа с ЖД вообще минимальна. Прирост производительности тоже близок к коэффициенту масштабирования.
Из ярких минусов можно выделить следующее:
Сложно расширяться - если впихнуть ещё ряд заводов кое-как можно, то вот сделать так, чтобы сырьё доходило до этих новых заводов, а не израсходовалось по пути - уже проблема.
Запутанное на низком уровне - я часто терялся на карте где какое производство у меня находится. И это ещё маленькие объёмы.
Ну и в целом первая часть закончена. Далее мы будем делать тоже самое, но с другим Архитектурным стилем - SOA.
Отступление "Жёсткий монолит"
Где-то уже при создании Ракетной шахты я заметил, что в текущей игре я начал внутри Монолита применять другие Архитектурные стили типо SOA для Модулей управления ракетами. Они малы (по сути пару-тройку производств в цепочке), но уже могут влиять на конечный результат. То есть с одной стороны я показал, что те же Программисты тоже рано или поздно невольно начнут отходить от концепции Монолита; но с другой, я мог исказить свои замеры в текущей статье.
Где-то там у меня и родилась концепция "Жесткого монолита" - то есть взять за правило ни в коем случае не применять наработки из других Архитектурных стилей. Это сильно затянет игру и у меня сейчас нет ответа на вопрос "Нужно ли оно?". В общем, пока мы продолжаем работать с тем, что получилось, но если будет очевидно, что без этого замеры получились неточными или просто возникнет интерес сравнить ещё и его - сделаем это отдельной статьёй. Повторюсь, что тут я пытаюсь воссоздать условия реальной разработки некого приложения и я не уверен, что где-то есть команды разработки, которым на организационном уровне говорят "Пишите Монолит и не что иное". В общем, посмотрим...
