ch
Feedback
Unity Architect: архитектура unity проектов

Unity Architect: архитектура unity проектов

前往频道在 Telegram

Пишу о том, что нельзя нагуглить про архитектуру, разработку и пр. Мой курс по архитектуре: https://course.uniarchitect.dev/y/9b8ec0c Иногда выкладываю видео и веду стримы: youtube.com/@vangogih По всем вопросам: @vangogih

显示更多
5 244
订阅者
无数据24 小时
-47
-430
帖子存档
UNITY BUILD PIPELINE ПО КИРПИЧИКАМ Полгода назад я решил попробовать активность в блоге, где я сначала долго и кропотливо соб
UNITY BUILD PIPELINE ПО КИРПИЧИКАМ Полгода назад я решил попробовать активность в блоге, где я сначала долго и кропотливо собираю информацию по какой-то технической теме, а после этого рассказываю ее в онлайн формате. В прошлый раз мы разбирали детали устройства Asset Bundles, где от участников я получил максимально положительные отзывы:
Самый большой вау-эффект был именно от осознания того, что работа с любыми ассетами в Unity устроена похожим образом и AssetBundle не исключение а дополнение для этого. Плюс само по себе разбор формата файлов раскрывает уйму возможностей: можно писать свои патчеры или шифраторы/дешифраторы.
Занятие было записано и выложено в закрытую группу вместе со всеми материалами: исходники, текстовые разборы — всё, что было нарыто в процессе подготовки. Всегда под рукой, чтобы в любой момент вернуться и вспомнить детали. Потому я решил повторить формат и провести занятие по теме сборки и компиляции проекта в Unity — то, что отнимает у нас, разработчиков, времени в разы больше, чем любая работа AI-агента 😬 🔸Что внутри: ▫️Asset Pipeline — через какие ключевые шаги проходит ассет перед тем как попасть в сборку ▫️Bee Frontend и Bee Backend — как пошагово компилируются сотни сборок в проекте без csproj и sln файлов ▫️Tundra и Directed Acyclic Graph — за счет чего обеспечивается быстрая incremental сборка ▫️Domain Reload — из каких шагов состоит и в деталях разберемся почему отнимает так много времени Я уже проводил занятие на эту тему для участников курса в начале этого года. Тогда я успел сделать компиляцию editor скриптов без Unity. 🔻В это раз я подготовил проект на dotnet, который собирает проект под windows асинхронно 🤯 Т.е. он не блокирует редактор: обновил класс -> запустил скрипт -> билд делается на заднем фоне не блокируя работу в редакторе 🔸Формат11 июля, 14:00 МСКОнлайн в Zoom — После занятия в закрытую Telegram группу будут выложены: запись, текстовые материалы и исходный код программ-примеров — Доступ к группе и материалам остаётся навсегда — Вопросы можно задать в любой момент в приватном чате 🔻Это не пересказ документации. Это разбор того, что происходит под капотом — на уровне, который не найти в гайдах и туториалах. 📎Ссылка на сайт с подробным описанием, отзывами, ценами и ответами на частые вопросы. До встречи 👋 #курс@UniArchitect

ПРОКЛЯТИЕ ПЕРЕИСПОЛЬЗУЕМОСТИ Делюсь болью. Я последние 5 лет на разных уровнях у разработчиков, лидов и техдиректоров, активн
ПРОКЛЯТИЕ ПЕРЕИСПОЛЬЗУЕМОСТИ Делюсь болью. Я последние 5 лет на разных уровнях у разработчиков, лидов и техдиректоров, активно встречаю такой паттерн:
Ну давай просто выделим общее и переиспользуем это в другой системе/проекте.
Мы ведь уже написали систему перемещения для ботов, давайте для игрока её тоже переиспользуем. У нас ведь уже есть backend-сервис по обработке match-3 логики, давайте его же тупо используем в другой игре 😵 Может казаться, что нужно просто скопировать/вставить решения из одного места или создать общий класс. И черт, это не работает нормально в большинстве случаев. 🔸 Если вы делаете что-то общее, то сначала нужно понять, какие зависимости это общее в себя принимает и отдаёт Если вы сделаете прямой copy/paste, придётся писать кучу обёрток, чтобы подружить новую систему с текущей. Поэтому чтобы действительно такое было возможно, нужно заранее проектировать не только саму систему абстрактно, но и её зависимости 🤯 А это значит, что нужно изначально планировать проектирование ключевых абстракций проекта. Например: 🔹 Весь cross-cutting context. Логирование, конфиги, аналитика, обработка ошибок. Либо придётся кучу мест рефакторить, либо заранее согласовывать единое API для переиспользования между проектами. 🔹 Коммуникация с сервером — пример посложнее. Но суть простая: вы не хотите при переносе дублировать логику обработки ошибок, контрактов взаимодействия и тянуть лишние транзитивные зависимости (другой HTTP-плагин, например). И это важно тупо потому, что это заставляет поддерживать задублированные решения по проекту 🤢 🔹 Изменился формат логирования или когда логи пишутся, а когда нет 🔹 Добавился новый обработчик исключений, формат контракта или обработка краевого случая Вот иди свищи по проекту 10 копий и вкостыливай фикс и туда. При этом ладно этот фикс в коде, ха, это ещё изи, а если ты решил общий микросервис такой выделить… 🔻Чем больше расстояние между зависимостями — тем сложнее и дороже в них вносить изменения. 🔸 Не всё, что кажется общим, таковым является Избитый троп:
Ну тут сделаем абстрактно, чтобы другие системы, вдруг, взяли и переиспользовали эту логику.
Ну нет, это не работает. Если заранее не понимать, как именно система будет переиспользоваться, и не переиспользовать сразу — оно не будет работать. Это происходит из одного простого факта: 🔹 Скорость изменения требований разная для каждой из систем. То, что вчера виделось как общее, сегодня жёстко заточено под что-то конкретное, т.к. переиспользуемость стоит времени, сил, денег и тщательного планирования. Или по другому: То что вчера казалось легко можно переиспользовать, сегодня требует узкого и конкретного решения. Так что всё, пожалуйста, я снимаю со всех, кто читает этот пост, «проклятие переиспользуемости» 😘 С этого момента вы можете не писать системы так, чтобы вдруг когда-то их кто-то использовал и сократил себе время. 🔻 Наконец-то можно писать системы, которые заточены на выполнение своей задачи и не раздувают сложность проекта на ровном месте. Но если переживаете, вот правило трёх:
Пока система или её часть не переиспользуется как минимум в трёх независимых местах — ничего общего выделять не нужно.
А если есть требование — выровняйте уровень знаний, покажите цену такого решения, сделайте #проектирование@UniArchitect, внедрите и пользуйтесь на здоровье, все только спасибо скажут. Ставь 👍 если тебе заходит такого рода контент! Ты знаешь кому переслать эту статью 💪 #проект_в_разработке@UniArchitect

AI КАК РЕДАКТОР, А НЕ АВТОР Это вторая статья из серии про AI. Первая тут. Когда я запускал блог, одной из самых неприятных з
AI КАК РЕДАКТОР, А НЕ АВТОР Это вторая статья из серии про AI. Первая тут. Когда я запускал блог, одной из самых неприятных задач было не “придумать тему”. Тем обычно много. Сложнее было разложить мысль компактно, без каши в предложениях, и так, чтобы опытному читателю не хотелось закрыть пост на третьей строке со словами “господи, что я читаю” 😅 И первое место, где AI меня реально вытащил — это не код. Это текст. 🔸Блог Почти каждая статья проходила через ChatGPT: — проверить стилистику — поправить грамматику — найти кривые формулировки — предложить другой способ сказать ту же мысль И вот последнее оказалось важнее, чем кажется. Потому что иногда мысль вроде нормальная, но звучит так, будто её три раза уронили по дороге. У каждого автора есть набор любимых речевых конструкций. Одни и те же связки, одни и те же обороты, один и тот же способ подводить к выводу. С одной стороны — это стиль. С другой — если не обновлять этот пул, текст начинает звучать как пережёванная версия самого себя. У меня это особенно заметно, потому что я довольно быстро нахожу первичную формулировку мысли, но намного хуже умею посмотреть на неё под другим углом. Я уже писал про это в статье Проклятие знаний: когда мысль у тебя в голове собрана, очень легко забыть, что то, что очевидно для тебя может быть не очевидно для читателя. 🔹Курс Вторая большая область — подготовка курса. Первые 3 месяца я собирал материал руками. Ночью, когда жена уходила спать, я садился за комп, шёл в Google, читал научные статьи, разбирался, что там вообще написано, и складывал всё в Notion. Не просто “ссылка на источник”, а: — какая мысль откуда взята — где её нужно использовать — в каком порядке она должна идти — что нельзя исказить при пересказе Так была сделана почти половина курса. А потом появились reasoning-модели, которым можно скормить большой промпт, файлы и дать 40 минут подумать. И здесь AI стал не автором, а независимым валидатором: правильно ли я понял источник, не перепутал ли причинность, не натянул ли вывод на свою картину мира, потому что очень хочется, выдать желаемое за действительное 😅 Вот это оказалось прям ценно. Потому что найти источник — не самая сложная часть. Сложная часть — прочитать, правильно понять, а потом донести мысль так, чтобы не исказить исходный смысл. 🔸И это хорошо ложится на исследования В SAP/HPI исследовании про опыт разработчиков с GenAI есть важный практический вывод:
когда человек использует один режим работы с AI — только chat или только in-code — нагрузка падает. Когда начинает метаться между режимами, выигрыш пропадает.
А ещё точнее в ту же точку попадает свежий RCT Anthropic про формирование навыков. Исследование про код, но механизм универсальный:
когда человек полностью отдаёт задачу AI, у него растёт ощущение продуктивности, но проседает понимание, чтение и отладка — причём без реального выигрыша по скорости. А те, кто работает с AI вовлеченно, спрашивая объяснения, а не готовый ответ, понимание сохраняют.
С текстом у меня работает так же. AI полезен, когда у него понятная роль: редактор, переформулировщик, валидатор или исследователь. А промпт формируется несколькими итерациями, где я подробно рассказываю куда нужно капнуть, что взять и как преобразовать. Но если прописать “давай классную статью по архитектуре”, на выходе очень быстро получается стерильный AI-slop/мусор 🤢 🔻 AI хорошо снижает стоимость итерации мысли. Но мысль всё равно должна быть твоя. Иначе вместо авторского текста/кода получится гладкая, правильная и абсолютно мёртвая жвачка. Понимаю, тема уже успела обрасти мхом и противоречивыми заявлениями, но я стараюсь, прагматично исследовать эту тему. Дайте знать в комментах что вы думаете 🫡 Ставь 👍 если тебе заходит такого рода контент! #ai@UniArchitect

Запись: архитектура проекта уровня Gardenscapes На 4 часа вчера засиделся чтобы выдать и показать весь материал что я подготовил 😬 В следующий раз буду значительно сокращать, та же БД и зарисовки вручную я думаю были лишними. Но мне просто хотелось показать как с диграммами можно удобно работать самому и что это не сложно 😊 Я сам кайфанул, очень много рассказал, почти каждый важный момент прокомментировал и дал прям подробную картину как архитектура таких проектов может выглядеть 🤓 Так что рекомендую посмотреть в записи, на х2 очень даже комфортно 🫡 Ссылка на запись Спасибо так же за активность в чате, вопросы были крутые, а атмосфера ламповая 🍻 Пишите тут как вам стрим и что нужно ещё улучшить? Ставь 👍 если тебе по кайфу такая движуха @UniArchitect

Проектируем проект уровня Gardenscapes Я не просто так задавал в канале вопросы про стрим 🤓 В эту Субботу, 13.06.2026 в 14:00 МСК не планируйте ничего. Потому что в это время в режиме реального времени будем пытаться запроектировать проект масштаба Gardenscapes 🤯 Формат будет примерно такой: 🔸Начало и предисловие 🔸Задание ограничений (иначе в 2 часа не уложимся) 🔸Проектирование уровня систем, контейнеров и компонентов по C4 Стрим будет на youtube 😊 Я прислушался к результатам опросов и составил материал так, чтобы примерно 60% мы проектировали, 10% я показывал слайды и 30% уделял примерам в коде. Я носил идею этого стрима еще с момента когда вел курс, это была одна из рекомендаций одного из учеников 🫡 🔻Так что: Если тебе по кайфу такая движуха, кликай по кнопке ниже и бот отправит тебе напоминание и ссылку на стрим за 10 минут до его начала 🛞 До встречи! @UniArchitect

Если бы вы смотрели стрим на youtube по проектированию архитектуры, какой уровень детализации вы хотели бы видеть?
Anonymous voting

Если бы вы смотрели стрим по архитектуре ПО, какой теме вы бы хотели чтобы было уделено больше внимания?
Anonymous voting

ВЫЗВАЛ И ЗАБЫЛ В прошлой статье я разобрал что такое cross-cutting concerns — системы, которые пересекают всю кодовую базу, но не являются бизнес-логикой. Сегодня — как с ними работать на практике. 🔸Что такое "call and forget" Cross-cutting concerns — общепринятый термин. "Call and forget" — то, как я называю эти системы на практике. Название описывает паттерн использования: — Вызывающий код не ожидает возвращаемого значения — Внутреннее состояние системы не влияет на бизнес-логику вызывающего Примеры из каждого проекта: ▫️ Логирование — записал событие, пошел дальше ▫️ Аналитика — отправил трек, не ждешь ответа ▫️ Звуковая система — запустил звук, геймплей не зависит от результата ▫️ Вибрации — тактильная обратная связь, fire and forget в чистом виде ▫️ Toast'ы / Hint'ы — показал уведомление, логика продолжается Ключевое свойство: убери любую из этих систем — и геймплей не изменится. Они ортогональны бизнес-логике. 🔸Почему singleton Обслуживающий код занимает большую часть систем и "размывает" логику, которую мы хотим править. Архитектурно я хочу чтобы на это тратилось как можно меньше места в рабочих классах. Потому надо выбрать самый компактный способ связать классы друг с другом. И таковым является singleton. Т.е. часть систем в каждом проекте можно спокойно сделать как SomeSystem.Instance.DoSmth — и проект от этого только выиграет. Но с правилами. 🔸Когда singleton — проблема Проблема не в подходе, а ЧТО через него делают. Возможность вызвать бизнес-логику через глобальный доступ создает хаос связей. Любой скрипт — визуальный эффект, UI-элемент — может напрямую командовать Game, Player, Economy. Дочерние элементы обращаются к головным, образуя неконтролируемый граф зависимостей. Но "call and forget" системы по определению не возвращают управление в бизнес-логику. Связь — однонаправленная. А значит и проблем не будет, если правильно "готовить" работу с такими системами. 🔸Рецепт приготовления signleton 🔹Ингредиент 1: Явный lifecycle Singleton создается и уничтожается в выделенных фазах — там же где регистрируются зависимости в DI-контейнере. Никаких get { _instance = new Class(); return _instance; } Рядом с diContainer.Register<IMyService>().AsSingle() ты так же явно прописываешь AudioService.Instance = new AudioService(). Один файл, одно место, полный контроль. Я подробно разбирал Composition Root и фазы RRR в статье про DI, а проблемы с порядком инициализации — в статье про точку входа. 🔹Ингредиент 2: Доступ через интерфейс Singleton отдает не конкретный класс, а интерфейс. Т.е. публичное свойство IAudioService, а не AudioService. Первая причина — тестируемость. Можешь подставить заглушку в тестах. Вторая — подмена по окружению. Для dev-окружения аналитику заменяешь на логирование, звук в тестах — на NullAudioService, вибрации на десктопе — на StubHaptic. 🔻 Архитектурные решения — это всегда компромисс. А если тебе кажется что компромисса нет, значит ты его ещё не нашел. Вот так использование не самого любимого и проблемного паттерна может помочь замедлить рост сложности проекта. Ставь 👍 если тебе заходит такого рода контент! Ты знаешь кому переслать эту статью 💪 #решения@UniArchitect

АРХИТЕКТУРА БЛОГА Чем дольше ты в разработке, тем отчётливее чувствуешь — уровень материала в интернете не растёт вместе с тобой. "Рекомендации", "лайфхаки", "советы" по C# и Unity — это цикл самодублирующейся информации, который просто ходит по кругу. И что ещё хуже — почти всё что можно найти публично, плохо проверяется авторами или намеренно искажается. Приходится постоянно перепроверять. Я Лёша. 11 лет в Unity, 7 из них коммерческих. Самоучка без наставников — всё из книг, научных статей и анализа реального опыта. Вот не многие из проектов, где довелось работать: ▫️ Hero Wars: Alliance ▫️ WSOP ▫️ Cut The Rope: Daily ▫️ Combat Quest ▫️ А так же делал свою игровую студию Silverfox Games (вся история в статьях: раз, два, три) Сейчас на вольных хлебах, полностью сосредоточен на блоге и подготовке онлайн-версии курса по архитектуре. 🔸Зачем этот блог Мне захотелось создать место, где подача материала сконцентрирована на проверяемости источников и высоком качестве. С фокусом на разработчиков, кто уже несколько лет создаёт и работает проекты на Unity. Не пересказ документации и "10 советов для новичка". А выстроенная цепочка, где каждая статья — один маленький пазл в общую картину мира разработки. Прежде чем раскрыть объёмную тему, я стараюсь выровнять кривые обучаемости между мной и читателем. Чтобы итоговый материал не казался придумкой автора, а лаконично являлся следствием из ранее прочитанного. 🔸Что почитать Чтобы лучше понять о чем я пишу и в каком стиле, я постарался собрать все статьи в один список и разбил их по категориям. Чем ниже статья в списке, тем лучше она раскроется, если вы прочитали предыдущие статьи 🥄 🔹Фундамент — почему всё устроено так, как устроено ▫️ Мы инженеры, не художники ▫️ Второй закон инженерной разработки ▫️ Когнитивная сложность ч.1 и ч.2 ▫️ Невыразительность ▫️ Продуктивность ▫️ Проклятие знаний ▫️ Полиморфизм системы ▫️ Инкапсуляция ▫️ Причина и следствие 🔹Архитектура — от определения к проектированию ▫️ (А|a)рхитектура ▫️ Когда задумываться об архитектуре ▫️ Проектирование: система ▫️ Проектирование: контейнеры ▫️ Причина провала проектов ▫️ Требования 🔹Практика — код и инструменты ▫️ SOLID и KISS, DRY, YAGNY — критика ▫️ DI ▫️ Точка входа и инициализация ▫️ Конфиги ч.1 и ч.2 ▫️ Порты и адаптеры ▫️ Кодогенерация ▫️ MV* 🔹Под капотом Unity ▫️ UnityEngine.Object == null ▫️ Reverse Engineering ▫️ Качаем файлы быстрее и HTTP/2 ▫️ CoreCLR: основы, CoreCLR vs Mono, CoreCLR vs IL2CPP 🔸Видео на YouTube ▫️ Архитектура конфигов ▫️ Многослойная архитектура ▫️ Dzmitry Bazyleu: Архитектура Open Source Проектов ▫️ Ярослав Шабанец: Клиентская архитектура корпораций 🔸Open Source ▫️ Unity Empty Project Template — шаблон пустого Unity проекта с готовой структурой папок ▫️ FastMigrations.Json.Net — миграция json файлов, в 5-7 раз быстрее аналога 🔻 Этот блог — не набор случайных статей. Это выстроенная цепочка причин и следствий. Регулярно читая статьи — ты получаешь полную картину, основанную не на чьих-то мнениях, а на проверяемых источниках и реальном опыте. 🔸Ваш последний курс по архитектуре Мой образовательный продукт, над которым я работал последние 2.5 года: — 9 месяцев собирал материал — 11 месяцев вел занятия для middle/senior/lead разработчиков — 6 месяцев монтировал и загружал на платформу И все это чтобы: 🔹Полностью закрыть фундамент по архитектуре приложений на Unity. Сейчас он находится в состоянии soft launch, но если хочется узнать подробнее, кликай по кнопке ниже, забирай полезный материал со ссылкой на сайт, где ты сможешь узнать подробнее. Спасибо большое что читаете 😊 Ставь 👍 если тебе заходит такой подход! @UniArchitect

ПРО AI: ПОЧЕМУ Я МОЛЧАЛ 3 ГОДА Сегодня день рождение блога — 3 года 🥰 И вот что забавно: за все эти годы я ни разу нормально
ПРО AI: ПОЧЕМУ Я МОЛЧАЛ 3 ГОДА Сегодня день рождение блога — 3 года 🥰 И вот что забавно: за все эти годы я ни разу нормально не написал про AI. Хотя использую его уже примерно 2.5 года — с того самого момента, когда ChatGPT начал жёстко хайповать. Я, как и все остальные, не смог предвидеть никакую “новую эру”. Просто залетел в волну хайпа и начал проверять:
окей, а где это вообще может быть полезно в реальности?
Давайте на чистоту: тема AI в геймдеве заряжена не только технически. Есть художники, геймдизайнеры, писатели, контент-мейкеры. Есть право на свой труд, свой стиль, свои работы. И если люди не будут защищать эту границу, всё очень быстро скатится в эксплуатацию и “ну мы просто обучили модель, а вы тут при чём?”. Я это понимаю. И не собираюсь обесценивать ❤️‍🔥 Но у блога всегда была немного другая задача: смотреть на вещи прагматично. Не с позиции “AI всех заменит”, не с позиции “AI это зло”, а с позиции: где это реально помогает, где ломает голову, где создаёт иллюзию пользы, а где тихо меняет саму профессию. 🔸Почему я не писал раньше Потому что долго не было честной картины. Было много шума, много FOMO и много “вот эта модель лучше, вот эта хуже”. С одной стороны, AI очень быстро стал частью моей работы и блога: — помогал с текстами — проверял стилистику и пунктуацию — помогал готовить курс — ускорял мелкие скрипты, тулзы и прототипы С другой стороны, в больших production-проектах у меня всё это время оставался скепсис. Не теоретический, а вполне инженерный:
Код в продакшен пушит не модель. Его пушит человек. И отвечает потом тоже человек.
И вот между этими двумя состояниями очень сложно написать честный пост. Потому что каждый короткий вывод сразу врёт. Если сказать “AI бесполезен” — это неправда. Он уже несколько раз сэкономил мне недели работы. Если сказать “AI теперь пишет код за нас” — тоже неправда 😵‍💫 Особенно когда речь не про маленький плагин, а про большой проект, где половина смысла живёт не в файлах, а неписанных правилах работы в проекте и тонких материй. 🔹О чём будет серия Поэтому вместо одного психоделического поста, где всё смешано в кашу, я лучше разложу по частям: ▫️ где AI реально помог мне в блоге и курсе ▫️ почему я всё ещё не доверяю ему большие production-фичи ▫️ почему ощущение “с AI быстрее” часто врёт ▫️ почему главный навык разработчика смещается от написания кода к упаковке системы И да, это всё будет не только “мне кажется”. Под это уже начали появляться нормальные исследования. И результаты там, как не странно, не укладываются ни в лагерь фанатов, ни в лагерь скептиков. 🔻 AI стал слишком важной темой, чтобы говорить о нём лозунгами. Тут нужно разбирать не “за” или “против”, а конкретные границы применимости. Где он усиливает инженера, а где просто быстрее генерит хаос. Ставь 👍 если тебе заходит такого рода контент! #ai@UniArchitect

ПОЖАЛУЙ, САМЫЙ ВАЖНЫЙ РЕЛИЗ В ИСТОРИИ КАНАЛА 2.5 года: 🔸9 месяцев на сбор, вычитку, отбор и структуризацию 🔸11 месяцев на подачу 🔸 5 месяцев отдыха (почти выгорел) 🔸 4 месяца монтажа, улучшение бота, создание сайта и платформы В следующий раз когда решите что сделать свой курс это легко, перечитайте список выше 🤣 Но как итог: 🔹40 участников первого потока 🔹44 лекции и 20 ответов на вопросы 🔹~85 часов материала 🔹Более 50 научных источников в основе 🔹Средняя оценка 9.5/10 Я по настоящему вложил все силы и душу в то, чтобы в мире AI-слопа, короткого и простого контента сделать то, что действительно дает знания 🥰 Чтобы убедиться в этом, я: 🔸После каждого занятия создавал опрос с оценкой от 1 до 5 🔸Если оценка была не 5, я шел в личку к каждому ученику и спрашивал что нужно улучшить 🔸Прислушивался к каждому мнению и вносил изменения Потому с уверенностью могу заверить, материал обкатан и проверен на разработчиках: 🔹Middle+ уровня 🔹Часть из них не работают с Unity (работают в других сферах) 🔹Часть из них инди 🔹50% из них работают на проектах с 1М+ скачиваний 🔹Средний коммерческий опыт 4-8 лет По итогу которого получилися замечательный образовательный продукт "Ваш последний курс по архитектуре" 😊 Который доступен на удобной онлайн платформе: 🔸Смотри в любое время на любом устройстве (через браузер или приложение) 🔸Хост в РФ без проблем с доступом (вне РФ тоже) 🔸Плати как тебе удобно (рассрочки, карты РФ, не-РФ, а так же счета для компаний) Чуть более подробную историю я расскажу на стримах, которые планирую проводить раз в 2-3 недели. Анонс уже скоро 🛞 А пока, переходите в бота, там я оставил для вас полезную методичку с архитектурными решениями, которые важно принять при старте нового проекта. Там же вы получите детали истории о курсе и ссылку на сайт. Для тех кто давно ждал онлайн-релиза, промокод EARLYBIRD со скидкой 20%. Просто введи его на странице оплаты. Осталось всего 14 использований, не затягивай. Ты знаешь кому переслать этот пост 💪 Ставь 👍, если тебе заходит такая движуха! #курс@UniArchitect

CROSS-CUTTING CONCERNS Чем больше проект, тем заметнее одна вещь: В зрелых production проектах очень много обслуживающего код
CROSS-CUTTING CONCERNS Чем больше проект, тем заметнее одна вещь:
В зрелых production проектах очень много обслуживающего кода.
Логирование, аналитика, кэширование, обработка ошибок, мониторинг — эти системы не являются бизнес-логикой, но присутствуют в каждом компоненте. Они проникают повсюду. 🔸С чего все началось В 1997 году команда из Xerox PARC (Kiczales et al.) опубликовала работу Aspect-Oriented Programming, в которой ввела понятие aspect. Авторы разделили свойства системы на два класса: components — бизнес-логика, которая чисто декомпозируется в процедуры, и aspects — свойства, которые пересекают эту логику насквозь и которые не получается скрыть за абстракциями^
Aspects tend not to be units of the system's functional decomposition, but rather to be properties that affect the performance or semantics of the components in systemic ways.
Логирование, кэширование, управление памятью, обработка ошибок — всё это aspects. Они не являются частью бизнес-логики, но вынуждены присутствовать в каждом компоненте. Авторы показали это на системе оптического распознавания символов: чистая бизнес-логика занимала 768 строк. После добавления production-аспектов — оптимизация памяти, кэширование промежуточных результатов, loop fusion — код разросся до 35,213 строк. В 45 раз. И этот "tangled code", по словам авторов, стал "excessively difficult to develop and maintain". 🔸Другой пример посвежее В 2019 году исследователи из Nova Southeastern University опубликовали работу GAMESPECT, где изучали эту проблему в контексте игровых движков:
Video game programming is an area where code duplication is extremely prevalent. Similar types of tasks are performed in multiple places throughout a game engine codebase. For example: game balance, logging, and memory allocation are just a few of the areas which are located across disparate locations of the codebase.
При анализе production-игры Noise Paradox (какая-то рандомная игра на UE4 🥱) авторы обнаружили, что одна из самых часто дублируемых функций — PostAKEvent. Централизация таких вызовов в их исследовании дала сокращение кодовой базы от 9% до 40% в зависимости от системы. Не "чуть удобнее" — а измеримое уменьшение объема кода. 🔸Как это использовать Такой код, который не является частью бизнес-логики, но который нужен чтобы обслуживать, отлаживать, оптимизировать и улучшать пользовательский опыт — прозвали cross-cutting concerns (сквозная функциональность). В простонародье мы это называем обслуживающий код. И он есть в каждом проекте: ▫️Логирование и аналитика — дублируются в десятках систем ▫️Звук и вибрации — вызываются из любого места, от UI до геймплея ▫️Кэширование и конфиги — пронизывают всё, от загрузки до runtime'а ▫️Обработка ошибок — размазана по всей кодовой базе И по большей части — это основной объем кода, который мы пишем. Не бизнес-логика, а именно обслуживание. Он необходим, от него никуда не деться. И именно он делает систему сложнее для понимания — потому что тебе нужно продраться через десятки строк инфраструктуры, чтобы ответить на вопрос: "как это работает?". 🔻 Cross-cutting concerns — неотъемлемая часть любого приложения. Их нельзя убрать, но можно минимизировать их присутствие в коде: тратить как можно меньше строк и символов на обслуживание, оставляя максимум места для бизнес-логики. Чем меньше "обслуживающего" шума — тем легче читать, понимать и развивать систему. В следующей статье — как с ними работать на практике и почему можно сделать осознанный выбор в сторону singleton. Ставь 👍 если тебе заходит такого рода контент! Ты знаешь кому переслать эту статью 💪 #software_engineering@UniArchitect

ПРОЕКТИРОВАНИЕ: КОД В 2020 году я работал лидом в Chill Gaming на проекте Combat Quest — клон Archero. Первый проект, где я н
ПРОЕКТИРОВАНИЕ: КОД В 2020 году я работал лидом в Chill Gaming на проекте Combat Quest — клон Archero. Первый проект, где я набирал команду под своё видение. До этого я только читал важные и серьезные книги от Мартина Фаулера и Роберта Мартина и был на 100% уверен что обязательно разработка каждой фичи должна начинаться с ее проектирования кода и классов. Потому каждая новая фича сопровождалась документом с детальным описанием классов и их связей между друг другом. Не буду ходить вокруг, просто 3 факта из этого опыта: 1️⃣ Даже я сам читал документы по диагонали. Уровень детализации слишком высокий, а логики в диаграммах нет. Толку в это вникать, если кода еще нет ... 2️⃣ Поддержка диаграмм отнимала ~20% времени разработки. Код менялся быстрее, чем обновлялись схемы. 3️⃣ Побочный эффект: разработчики боялись лезть в задокументированные системы. Изменения в коде системы = внесение изменений в документацию. Это был первый прецедент, когда рекомендации из книг не сработали на практике. 🔸Что говорит C4 про уровень кода В серии про проектирование мы прошли три уровня: система, контейнеры, компоненты. Остался четвёртый — код. Сайт C4 model прямо говорит:
This is very much an optional level of detail... Ideally this diagram would be automatically generated using tooling.
Т.е. Simon Brown не рекомендует создавать диаграммы кода как долгоживущую документацию. 🔸Зачем тогда нужны диаграммы кода Умение составлять диаграммы — не обязательный навык для разработчика. Это инструмент коммуникации: 🔹С разработчиками на другом языке программирования 🔹Между разработчиками в команде — наглядное объяснение как подойти к реализации Т.е. диаграмма кода — это не документация, а средство общения. Как салфетка с рисунком на митинге: нарисовал, обсудил, выбросил. 🔸Почему ручное проектирование кода избыточно Уровни System, Container и Component описывают что система делает. Уровень Code описывает как это реализовано — классы, методы, связи. Проблема в том, что: ▫️Диаграммы кода не содержат логики — отражают только структуру, но не поведение ▫️ Очень сложно адекватно отразить все связи реального класса так, чтобы это было удобно воспринимать ▫️ Код — самый волатильный уровень. Рефакторинг, новые требования, баг-фиксы — каждое изменение делает ручную диаграмму неактуальной Документировать код вручную — фиксировать положение стрелки секундомера. 🔸Генерация вместо рисования Если диаграмма кода всё-таки нужна — генерируй, не рисуй: ▫️ Mermaid — AI отлично генерирует Mermaid-диаграммы, а они из коробки рендерятся в любом .md файле. Самый быстрый путь от вопроса до схемы ▫️ Structurizr DSL — описание архитектуры as code. Есть MCP сервер — можно подключить к AI и генерировать диаграммы прямо из контекста проекта ▫️ Rider — умеет в Type Dependency Diagram, но НЕ в полноценные UML Class Diagram. А то многие говорят что он научился, все еще нет. Когда диаграммы уровня кода оправданы: 🔹Объяснение разработчику как подойти к реализации новой системы 🔹Проверка топологии системы перед рефакторингом 🔹Регуляторные требования (финтех, медтех) И во всех случаях — генерируй, не надо их ручками рисовать. 🔻 Уровень кода не имеет смысла описывать формально — только для коммуникации. Как и уровень компонентов. Единственное, для чего он потенциально полезен — проверка топологии системы для рефакторинга. Верхние три уровня C4 формируют архитектуру. Четвёртый — нарисовал, обсудил, выбросил. Ставь 👍 если тебе заходит такого рода контент! Ты знаешь кому переслать эту статью 💪 #проектирование@UniArchitect

ЧЕРНОВИК: перестать писать душные статьи и начать постить мемы 😅

РЕГРЕСС: КОНТРОЛИРУЕМ ОБЪЕМ ИЗМЕНЕНИЙ Самый большой рефакторинг за всю карьеру включал систему примерно на 10к строк. Это был
РЕГРЕСС: КОНТРОЛИРУЕМ ОБЪЕМ ИЗМЕНЕНИЙ Самый большой рефакторинг за всю карьеру включал систему примерно на 10к строк. Это был симулятор бильярда — целый режим игры с огромными системами внутри. Задача — добавить новый режим. Но просто взять и начать писать было невозможно: ▫️ Режимом управлял один класс на 2000 строк. Методы вызывали друг друга, промежуточное состояние записывалось в приватные поля. ▫️ Сам класс хоть и был за интерфейсом, но оставался неразрывно связан с другими частями системы. Сеть, при изменении состояния, двигала игру дальше — и механизм требовал четкого порядка вызовов. Потому сеть сама сортировала события, которые отдавала, чтобы логика работала правильно. Это как раз пример content и control coupling'ов: ▫️Content coupling — один модуль напрямую обращается к внутренним данным другого или модифицирует их ▫️Control coupling — один модуль передает другому управляющую информацию (флаг, параметр), определяя что тот должен делать И прежде чем добавлять что-то новое — нужно снизить сложность старого.
Противовес локальной и глобальной сложности — модульность.
У этого решения есть отдельное большое обоснование, которому я на курсе посвятил лекцию на 3 часа. В текстовом формате не хватит и 5 постов, так что ждите анонса онлайн версии курса — уже в Мае 😎 🔸Мое решение: 1️⃣ Не меняя логику, разбить систему на части. Выносить куски кода в отдельные классы по функциональности — буквально ctrl+c, ctrl+v в новые файлы. 2️⃣ Ни при каких обстоятельствах не менять порядок вызовов. 🔹Почему п.2 критически важен: При внесении изменений всегда нужно стараться избегать увеличения регресса. Регресс — тип ошибки, при которой ранее работавшая функциональность перестаёт работать корректно после внесения изменений в код. Для себя я формулирую это так: ▫️Регресс — это дополнительный объем работы для QA, чтобы убедиться в работоспособности твоих изменений ▫️А если глубже — это изменение кол-ва вариантов выполнения кода, которые делают возможным исполнение старых, уже исправленных багов И самый надежный способ его контролировать — переносить куски кода в другие файлы без модификации. 🔸Звучит странно Да. Но у этого есть конкретное назначение:
Снижение сложности без увеличения количества багов — суть рефакторинга.
На домашних проектах это может показаться излишним. На больших — это реальность: ▫️Сроки поджимают, и неидеальный код внутри не так страшен, как неработающая версия ▫️Регресс может быть настолько огромным, что одно упоминание для QA и PO станет аргументом вообще не брать задачу в работу. Ее оценят в кучу дней, PM закинет в бэклог, а разработчик будет вкостыливать новый режим в сжатые сроки. 🔸Как рефакторить огромные системы 1️⃣ Разбиваем на части без изменения логики — снижвем сложность и контролируем регресс 2️⃣ Отдаем QA на проверку 3️⃣ Рефакторим разбитую систему по частям — меняем логику по кусочкам, проверяем что не тригернули старых багов 🔸Отдельная критическая ошибка Часто вижу как вместе с фиксом бага на ревью отправляют рефакторинг каких-то частей. Мысли разработчика: "Ну, заодно вот еще улучшил это место." Часто оно правда так. Но не менее часто — изменения могут потребовать регресса измененной части. А это время и риски для того, кто ответственен за релиз. 🔻 Всегда держи в голове не только благую мысль "я делаю проект лучше", но и ответственность за дополнительную работу, которую ты создаешь другим людям. Истина — в балансе. И объем регресса, который ты создаешь — отличная метрика этого баланса. Ставь 👍 если тебе заходит такого рода контент! Ты знаешь кому переслать эту статью 💪 #проект_в_разработке@UniArchitect

НЕ ТЕРЯЕМ .META ФАЙЛЫ Часто, особенно ребята, которые начинают или мало работают с Unity и Git, получают замечания: "Ты тут .meta файл забыл закоммитить. Из-за этого ссылки на объект в других компонентах потерялись." И это раздражающая проблема: 1️⃣ Её можно обнаружить только в runtime. Т.е. пока код, который использует объект с потерянным .meta, не будет вызван — в консоли тишина. Никаких ошибок, никаких предупреждений. 2️⃣ "А у меня локально всё работает" — самая раздражающая фраза, которую только можно услышать. Полное снятие с себя ответственности и перекладывание проблемы на другого. Благо, есть решение. 🔸unity-git-hooks unity-git-hooks — 3 простых .sh скрипта, которые копируются в .git/hooks и автоматически следят за консистентностью .meta файлов. Установка — копируешь pre-commit, post-checkout и post-merge из репозитория в .git/hooks своего проекта. Если хуки уже есть — дописываешь содержимое в конец. По умолчанию скрипты считают, что папка Assets лежит в корне репозитория. Если структура другая — указываешь путь через git config unity3d.assets-dir client/Assets. 🔸pre-commit — валидация перед коммитом Самый важный. Срабатывает при git commit и блокирует его, если .meta и ассеты рассинхронизированы. При добавлении файлов: — Добавляется .meta, но ассета нет в индексе — ошибка "Redundant meta file" — Добавляется ассет, но нет .meta для него или для родительских директорий — ошибка "Missing meta file" с подсказкой git add При удалении файлов: ▫️Удаляется .meta, но ассет остаётся — ошибка. Нельзя удалить .meta и оставить ассет ▫️Удаляется ассет, а .meta осиротевшей директории остаётся в индексе — ошибка с подсказкой git rm Скрипт проходит вверх по всем родительским директориям до Assets и проверяет каждый уровень. Т.е. гарантирует простое правило: каждый ассет имеет свой .meta, каждый .meta имеет свой ассет. Ни больше, ни меньше. 🔸post-checkout и post-merge — очистка мусора Оба делают одно и то же — удаляют пустые директории внутри Assets. Зачем? Git не отслеживает директории — только файлы. Когда ты переключаешь ветку или делаешь pull, git удаляет файлы из папки, но сама пустая директория остаётся на диске. Unity видит эту пустую папку, генерирует для неё .meta файл — и вот у тебя уже грязный git status сразу после checkout. Два хука решают это автоматически. 🔻Одно простое решение на проекте — и на всём протяжении разработки экономишь кучу времени лида и разработчиков на решении багов с потерянными ссылками. Поставь эти скрипты своим художникам и дизайнерам — уверен, работать станет проще. Только не забудь написать короткий How-to, чтобы потом не отвечать на "А почему мне git выдаёт ошибку?" 😵 Ставь 👍 если тебе заходит такого рода контент! Ты знаешь кому переслать эту статью 💪 #решения@UniArchitect

ДОКУМЕНТЫ НИКТО НЕ ЧИТАЕТ 😭 За всё время удалось поработать на проектах с разным уровнем документации. От полного её отсутст
ДОКУМЕНТЫ НИКТО НЕ ЧИТАЕТ 😭 За всё время удалось поработать на проектах с разным уровнем документации. От полного её отсутствия до удушающего бесполезного объёма. И каждый раз, приходя на новый проект, задаёшься вопросом:
Какой объём минимально эффективен, чтобы давать максимальную пользу?
Правильного ответа я ещё не нашёл, но вот что удалось понять: 🔸Переизбыток и недостаток одинаково плохи Кажется очевидным, что мало документации — плохо. Но переизбыток — не менее разрушителен. В одном случае до 40% времени уходит на написание и поддержку. В другом — до 20% тратится на поиск информации, которую никто не зафиксировал. Оба варианта одинаково воруют время — просто с разных сторон. 🔸Детальная документация внутрянки чаще всего не нужна Хочется чтобы все понимали, как работает тот шедевр, что ты создал. Но... и как часто ты сам это читал второй раз? Отличное решение — максимально короткий Guide, который объяснит как пользоваться. В детали каждый погрузится сам — AI в этом отлично помогает. На последних местах работы отлично себя зарекомендовали зарисовки в paint с комментариями (смотри скрин). 🔸Чем дальше документы друг от друга — тем сложнее искать информацию Тут прямо как с cohesion и coupling. Для документации это тоже работает: держи документы, объединённые одной тематикой, рядом друг с другом. А связи с другими темами упоминай в головном файле. Головной документ я всегда использую для хранения полезных ссылок, которые важно держать рядом. Например, при проектировании сервиса чата, в головном файле "Чат" было оглавление и полезные ссылки:
Cтарые GDD-файлы Задачи Доски в Figma/Miro Ссылки на репозитории
В общем всё, до чего нужно часто и быстро дотянуться. 🔸Хочется написать красиво — пиши на Хабр А в документах ключевое — экономия ресурсов и времени читателя. У меня благо есть блог и любимая жена-филолог ❤️‍🔥, которые учат писать экономично. Но поначалу, читая только Хабр, книги и блоги, я старался копировать способ повествования в документацию. В итоге это только моё эго тешило — коллеги документ не читали, потому что на полстраницы воды приходилось одно полезное предложение. Документ — не статья. Здесь важна плотность информации: короткие предложения, списки, заголовки. Читатель пришёл за ответом, а не за историей. 🔸Навигация и разметка важны Это опять же про экономию времени другого человека. Текст без разметки ощущается громоздким — его тупо лень читать. Даже в статьях этого блога, где лимит 4096 символов, я использую emoji, цитаты, ссылки и выделения — иначе стена текста убивает внимание. В документации это ещё критичнее. Человек приходит не читать, а искать. Оглавление, заголовки, списки — это не украшение, а навигация. Без них даже полезный документ превращается в текст, который проще спросить у коллеги, чем найти в нём ответ. 🔹Что важно документировать Кропотливо собранный список важных разделов и документов:
|— Фича / система / модуль / домен
  |— Продуктовые требования — метрики, бизнес, влияние на аудиторию, сроки, список фичей
  |— GDD — описание фичей от дизайнеров
  |— Техническая документация:
     |— Архитектура: C4 system, container, sequence diagram, ADR
     |— Требования: из чего должны состоять container'ы и component'ы
     |— How to: короткие Guide'ы как быстро решить проблему
     |— Исследования: результаты поиска решений, используются для обоснования
Самым жирным, как правило, будет раздел How to. Документы в него рекомендую добавлять каждый раз, как кто-то задаёт вопрос. Для ориентира — пример документации в FastMigrations.Json. Не раз отмечалась опытными разработчиками как хороший пример. 🔻 Документация — это не про объём, а про доступность нужной информации в нужный момент. Минимум текста, максимум структуры — и команда перестаёт тратить время на поиск того, что уже кто-то знает. А что ещё из важного ты документируешь на своих проектах? Что из перечисленного тебе пригодилось или чего не хватает? Ты знаешь кому переслать эту статью 💪 #проект_в_разработке@UniArchitect

MENUITEM Из проекта в проект прихожу и вижу одну и ту же картину. Есть маленькие полезные скрипты, которые упрощают работу, н
MENUITEM Из проекта в проект прихожу и вижу одну и ту же картину. Есть маленькие полезные скрипты, которые упрощают работу, но все они запрятаны в глубине проекта. О чем речь: — Открыть Persistent Data Path в проводнике — Переключить сцену, чтобы не искать её в иерархии — Удалить закешированные данные — Переключить редактор из dev в prod или qa И прочие мелочи, которые нужно часто вызывать в редакторе. Обычно для этого создаётся скрипт с атрибутом [MenuItem("Tools/...")]. 🔸Проблема Почему-то этот полезный код очень любят разбрасывать по скриптам, папкам, сборкам. Сторонние плагины туда же — Odin, DoTween и прочие имеют свои секции в Tools. Поиск нужной кнопки начинает отнимать время. Помножь на количество рабочих дней — получишь кучу времени потраченного на поиск. При этом не все команды пишут логи, и найти откуда именно этот код вызывается — бесящий процесс. В момент поиска не делается ничего полезного, ты просто ищешь ответ на вопрос "где это лежит". Мелочь, но дико бесит 😵 🔸Решение Всего 3 пункта: 1️⃣ Далем Editor asmdef в проекте: GenshinImpact.Editor 2️⃣ Все пути кладутся в 1 файл с константами, который лежит в корне:
public static class ToolConstants {
    public const string Root = "Silverfox";
    public static class Build {
        public const string Prod = Root + "/Build/Prod";
    }
}
3️⃣ При создании tool'а в качестве корня — имя проекта или компании: [MenuItem("Silverfox/Clean local data")] Итого получаем в коде: [MenuItem(ToolConstants.Build.Prod)] Т.е. путь до нужного кода — два шага: поиск по имени компании, а до других элементов легко дотянуться через файл с константами. 🔸Почему это работает ▫️ Не нужно держать в голове иерархию сборок. Достаточно найти строку Silverfox" — и ты сразу в файле со всеми tool'зами ▫️ Можно быстро прикинуть иерархию и понять как добавить или поправить tool. Особенно это полезно для новичков в проекте. ▫️ Быстрее чем спрашивать AI — переключение контекста и формулировка вопроса медленнее чем Ctrl+Shift+F в IDE 🔻 Простое соглашение — один файл, один корень — убирает целый класс раздражающих пауз в работе. Это новая рубрика #решения@UniArchitect — короткие и простые решения, которые хотелось бы видеть чаще на проектах. Они нигде не зафиксированы и каждый делает что-то подобное у себя. Хочется чтобы такие мелочи были под рукой. Ставь 👍 если тебе по кайфу такая движуха! Ты знаешь кому переслать эту статью 💪 #решения@UniArchitect

UNITEXT TextMeshPro — это покупка 2017 года, которую Unity встроила и с тех пор поддерживала на плаву, исправляя баги. Я не гуру нюансов отрисовки текста, но я никогда и не задумывался что TMP, по стандарту Unicode, не способен отобразить все многообразие символов правильно 😱 Я решил разобраться подробнее в различиях и фичах, чтобы понять в чем инновационность UniText. 🔸Эмодзи Чтобы показать эмодзи в TMP, тебе нужно: создать текстурный атлас со спрайтами, импортировать его, разметить каждый спрайт, привязать к компоненту. И всё равно ты получишь статичную картинку без поддержки Zero Width Joiner (семьи, флаги, тона кожи). В UniText ты просто пишешь "Привет! 👋🏽" — и оно работает. Эмодзи берутся нативно с каждой платформы: Segoe на Windows, Apple Color Emoji на iOS, NotoColorEmoji на Android/Linux. Мне смешно об этом писать, но теперь emoji просто есть и не нужно костылить fallback шрифт в новых версиях и свой атлас emoji в старых версиях TMP. 🔸RTL и смешанный текст Арабский, иврит, урду, фарси — ни одно решение в Unity не реализует Bidirectional алгоритм по спецификации Unicode. Костыль вроде RTLTMPro покрывает базовый кейс, но ломается на смешанном тексте — когда в одной строке арабский и английский. Правильное отображение смешанного текста — это не просто "перевернуть строку". В Unicode разработали для этого целую спецификацию UAX #9 с 861 тысячей тестов. Каждый тест — конкретная комбинация символов разных направлений и ожидаемый порядок отображения. Проходит все тесты — текст корректен в любой комбинации языков. UniText проходит их все: ▫️ Bidirectional (направление текста) ▫️ Line Breaking (где можно переносить строку) ▫️ Grapheme Clusters (что считать одним "символом" — важно для эмодзи и составных букв) TMP ничего из этого не проходит на 100% 🫠 Т.е. нет гарантий что чат в вашей игре будет правильно показывать что пользователь написал. 🔸Шрифты без боли 1️⃣ TMP растеризует глифы оффлайн в редакторе и сериализует атласы на диск. Отсюда грязные файлы в git, конфликты при мёрже, раздутый билд. UniText растеризует глифы в runtime — атласы не сериализуются, в проекте хранятся только байты шрифтов (UniTextFont.cs). Никаких грязных файлов, никаких конфликтов. Кто вдруг не понял:
В UniText не нужно постоянно отменять изменения в папке как Text Mesh Pro 🤯
2️⃣ В UniText один компонент рендерит текст на любом языке через стек шрифтов с fallback — первый шрифт основной, остальные подхватывают недостающие глифы (UniTextFontStack.cs). 3️⃣ А Font Subsetter позволяет вырезать из шрифта только нужные символы — полезно когда из 10МБ шрифта тебе нужны только символы валют. И это я лишь малая часть отличий. 🔸Итого 🔻UniText это координально другой подход при работе с текстом, который на голову выше TMP. Делаю ставку что это новый стандарт в Unity и скоро он будет на каждом проекте 🫡 Там сейчас 2 версии доступно: 1.0 — бесплатный и open-source. Всё что описано выше — доступно прямо сейчас. 2.0 — платная версия с, компрессией шрифтов, единым атласом с дефрагментацией, 3D-текстом и батчингом всего текста в 1 draw call 😍и полностью переработанной системой стилей (см. видео к посту). 🔸Рекомендация Если у тебя проект с поддержкой японского, китайского, хинди, индонезийских или арабских локализаций — импортируй UniText и сравни размер билда. Для больших проектов с десятком языков это может стать значительной победой. Так что бегите скорее выпрашивать лицензию у компании для теста. Чисто изян способ реально улучшить метрики проекта 🛞 Мне посчастливилось знать лично разработчика этого плагина, поэтому пишите комментарии с вопросами и обязательно накиньте ⭐️ на GitHub ❤️‍🔥 📱 UniText Open Source Документация 📱 Discord сообщество Ставь 👍 если тебе заходит такого рода контент! Ты знаешь кому переслать эту статью 💪 #будни@UniArchitect

ADR: ФИКСАЦИЯ АРХИТЕКТУРНЫХ РЕШЕНИЙ Достаточно часто находил у себя и видел у других огромное желание, при присоединении к но
ADR: ФИКСАЦИЯ АРХИТЕКТУРНЫХ РЕШЕНИЙ Достаточно часто находил у себя и видел у других огромное желание, при присоединении к новому проекту, предложить улучшение или постараться исправить уже имеющуюся систему. Это нормально, мы понимаем и видим как можно сделать лучше, наш глаз не замылен и мы стремимся поскорее с головой ворваться в новый проект. Вот только один момент мы не учиваем: "А почему это сделано именно так и почему это никто не спешит исправить?". Можно, конечно, все объяснить простым конформизмом и ленью, но чаще всего мы упускаем одну простую мысль.
Когда-то уже кто-то взял ответственность и принял решение. Не принимать решение - это тоже решение.
И получается что прежде чем предложить изменение, нужно понять контекст текущего решения. А чтобы потом кто-то такой же смелый не переписал уже твоё — этот контекст нужно зафиксировать. 🔸Проблема: устные договорённости Классический сценарий: обсуждаете с командой, как лучше встроить новый модуль. В чате или на созвоне находите оптимальное решение, все соглашаются — но ничто не фиксируется письменно. Через две недели часть команды уже не помнит деталей обсуждения, другие уверены, что договорились о другом, а новый участник не понимает причины выбора. В итоге любое устное или не зафиксированное решение будет пересматриваться и, скорее всего, переписываться заново — просто потому, что отсутствует общий ориентир. А как мы знаем, архитектура — это набор ключевых решений. Но решения без зафиксированного контекста — просто факты без объяснения. 🔸ADR: формат В 2011 Michael Nygard предложил формат Architecture Decision Records (ADR). Формат минимален:
▫️ Status — proposed, accepted, deprecated, superseded ▫️ Context — какая ситуация и ограничения привели к решению ▫️ Decision — что именно решили ▫️ Consequences — что из этого следует, включая негативные эффекты
🔹Ключевое: ADR фиксирует не "что мы сделали", а "почему мы так решили". 🔸Правила ведения ▫️Каждый документ включает только одно решение ▫️Информация из ADR при изменениях не удаляется — статус меняется на deprecated или superseded, создаётся новый ADR со ссылкой ▫️Файлы максимально атомарные и легковесные — пара параграфов ▫️Хранятся в системе контроля версий рядом с кодом, не в wiki Для Unity-проекта: папка ADR в корне репозитория. Пример формата из реального open-source проекта C4G — ADR прямо в корне репозитория. Таким образом у вас важная техническая документация всегда под рукой в близкой доступности к проекту. Не нужно время тратить на поиск в wiki. 🔸ADR и проектирование ADR дополняет C4: уровни System/Container/Component показывают что и как устроено, ADR объясняет почему именно так. Требования определяют что система должна делать. ADR фиксирует как мы решили это реализовать и какие альтернативы отвергли. При этом зафиксированные решения в ADR — это чаще всего ответы на сложные технические вопросы, которые удовлетворяют именно нефункциональным требованиям. И по моим наблюдениям, именно неучтённые нефункциональные требования чаще всего раздувают изначальные сроки. Если кто-то придёт и скажет "давайте использовать нативные okhttp и alamofire" — а у тебя ADR:
Status: accepted. Context: нужен кроссплатформенный HTTP на iOS/Android/WebGL. Decision: используем BestHTTP.
Хочешь менять — сделай исследование, обоснуй, создай новый ADR, примите решение, внесите изменения. 🔻 ADR — минимальная документация с максимальной отдачей. Контекст, решение, последствия — пара параграфов сейчас экономит часы обсуждений и обоснований через полгода. Для примера можете посмотреть: ▫️Как структурированы предложения фичей для языка C# ▫️Простой шаблон ADR, что я упомянул в статье ▫️Как мы описываем ADR'ы на проекте, который создан на курсе Ставь 👍 если тебе заходит такого рода контент! Ты знаешь кому переслать эту статью 💪 #проектирование@UniArchitect