#idisposable #управление_ресурсами
IDisposable продолжение 👇
Другим примером использования интерфейса IDisposable является реализация механизма отмены операции или транзакции.
Например, у вас есть сложная операция, которую нужно выполнить в несколько этапов, и необходима возможность отмены операции в любой момент времени.
Рассмотрим реализацию механизма отмены операции на примере:
В примере класс Operation представляет собой операцию, которая может быть выполнена и отменена.
В блоке using используется операция с возможностью отмены.
Если операция завершается успешно, то она просто выполняется, и интерфейс IDisposable не используется.
Если же происходит ошибка, то операция отменяется с помощью метода Cancel, который также вызывается при автоматическом освобождении ресурса благодаря интерфейсу IDisposable.
Использование интерфейс IDisposable в рассмотренном выше примере позволяет реализовать механизм отмены и гарантировать, что операция будет правильно завершена или отменена в любом случае.
✅ Итак, мы рассмотрели варианты использования интерфейса IDisposable для реализации:
- паттерна "ресурсы" для управления ресурсам и предотвращения утечек памяти
- паттерна "заимствования" (borrowing) для работы с потоками данных
- реализация механизма отмены операции или транзакции.
Всем хорошего дня 👋
Для тех, кто планирует более глубокое погружение, в следующем посте подборка тематической литературы 👇
IDisposable продолжение 👇
Другим примером использования интерфейса IDisposable является реализация механизма отмены операции или транзакции.
Например, у вас есть сложная операция, которую нужно выполнить в несколько этапов, и необходима возможность отмены операции в любой момент времени.
Рассмотрим реализацию механизма отмены операции на примере:
class Operation : IDisposable
{
private bool _isCompleted = false;
public void Execute()
{
// выполнение операции
_isCompleted = true;
}
public void Cancel()
{
if (!_isCompleted)
{
// отмена операции
_isCompleted = true;
}
}
public void Dispose()
{
if (!_isCompleted)
{
Cancel();
}
}
}
// Использование операции с возможностью отмены
using (var operation = new Operation())
{
try
{
operation.Execute();
// выполнение операции
}
catch (Exception ex)
{
// обработка ошибки
operation.Cancel();
}
}
В примере класс Operation представляет собой операцию, которая может быть выполнена и отменена.
В блоке using используется операция с возможностью отмены.
Если операция завершается успешно, то она просто выполняется, и интерфейс IDisposable не используется.
Если же происходит ошибка, то операция отменяется с помощью метода Cancel, который также вызывается при автоматическом освобождении ресурса благодаря интерфейсу IDisposable.
Использование интерфейс IDisposable в рассмотренном выше примере позволяет реализовать механизм отмены и гарантировать, что операция будет правильно завершена или отменена в любом случае.
✅ Итак, мы рассмотрели варианты использования интерфейса IDisposable для реализации:
- паттерна "ресурсы" для управления ресурсам и предотвращения утечек памяти
- паттерна "заимствования" (borrowing) для работы с потоками данных
- реализация механизма отмены операции или транзакции.
Всем хорошего дня 👋
Для тех, кто планирует более глубокое погружение, в следующем посте подборка тематической литературы 👇
#библиотека_программиста #геймдев #idisposable
Подборка литературы по использованию IDisposable.
📚
1. Де Смет, Барт. C# 5.0 Unleashed, глава 20, "Диспозиция и финализация".
2. Скит, Джон. C# in Depth, глава 6, "Размещение объектов и сборка мусора".
3. MSDN. "Использование using в C#", (https://docs.microsoft.com/ru-ru/dotnet/csharp/language-reference/keywords/using-statement).
4. CodeProject. "Implementing IDisposable and the Dispose Pattern Properly", (https://www.codeproject.com/Articles/15360/Implementing-IDisposable-and-the-Dispose-Pattern-P).
5. Albahari, Joseph and Albahari, Ben. C# 9.0 in a Nutshell: The Definitive Reference, глава 9, "Memory Management, Pointers, and Unsafe Code".
6. Nagel, Christian. Professional C# 7 and .NET Core 2.0, глава 21, "Unsafe Code and Pointers".
7. Скит, Джон. C# in Depth, глава 15, "Unsafe code and pointers".
8.Agafonov, Eugene. Mastering C# Concurrency: Write Flawless C# Code for Concurrent and Parallel Programming, глава 7, "Low-level Threading in C#".
9. Miles, Rob. C# Programming Yellow Book, глава 25, "Unsafe Code".
10. Официальная документация Microsoft по C#, раздел "Unsafe Code and Pointers".
11. C# Language Specification, раздел "28.1 Pointer types".
Приятного прочтения 🙂
Подборка литературы по использованию IDisposable.
📚
1. Де Смет, Барт. C# 5.0 Unleashed, глава 20, "Диспозиция и финализация".
2. Скит, Джон. C# in Depth, глава 6, "Размещение объектов и сборка мусора".
3. MSDN. "Использование using в C#", (https://docs.microsoft.com/ru-ru/dotnet/csharp/language-reference/keywords/using-statement).
4. CodeProject. "Implementing IDisposable and the Dispose Pattern Properly", (https://www.codeproject.com/Articles/15360/Implementing-IDisposable-and-the-Dispose-Pattern-P).
5. Albahari, Joseph and Albahari, Ben. C# 9.0 in a Nutshell: The Definitive Reference, глава 9, "Memory Management, Pointers, and Unsafe Code".
6. Nagel, Christian. Professional C# 7 and .NET Core 2.0, глава 21, "Unsafe Code and Pointers".
7. Скит, Джон. C# in Depth, глава 15, "Unsafe code and pointers".
8.Agafonov, Eugene. Mastering C# Concurrency: Write Flawless C# Code for Concurrent and Parallel Programming, глава 7, "Low-level Threading in C#".
9. Miles, Rob. C# Programming Yellow Book, глава 25, "Unsafe Code".
10. Официальная документация Microsoft по C#, раздел "Unsafe Code and Pointers".
11. C# Language Specification, раздел "28.1 Pointer types".
Приятного прочтения 🙂
Docs
оператор using — обеспечение правильного использования удаленных объектов - C# reference
Использование инструкции или объявления C# для обеспечения правильного использования удаленных объектов
GameDev: разработка на Unity3D pinned «Пост - приветствие 👋 Новый год - время новых начинаний, и к наступающему новому 2023 году мы подошли с решением и готовностью создать канал, посвященный разработке игр на Unity. Мы - это Сергей и Ирина Жильниковы. О Сергее: Более 15 лет в разработке…»
#monobehaviour #архитектура
Приветствую, друзья 👋
Сегодняшняя публикация посвящена роли MonoBehaviour в проекте.
MonoBehaviour - это базовый класс в Unity, который используется для написания скриптов, управляющих поведением игровых объектов.
Он предоставляет множество методов жизненного цикла, которые могут быть переопределены для реализации логики игровых объектов.
Некоторые из основных методов, используемые в жизненном цикле объекта, включают в себя:
- Awake(): вызывается при создании объекта после инициализации всех его компонентов, но до того, как он станет активным в иерархии сцены.
- Start(): вызывается после Awake() и до первого обновления фрейма.
✅ В методе можно инициализировать переменные и компоненты, которые зависят от других объектов в сцене.
- Update(): вызывается каждый кадр и используется для обновления поведения объекта.
✅ В методе можно изменять свойства объекта, перемещать его, обрабатывать ввод и т.д.
- FixedUpdate(): вызывается с фиксированной частотой и используется для обновления физики объекта.
✅ Метод должен использоваться всякий раз, когда вам нужно изменять физические свойства объекта, такие как скорость, позиция, силы и т.д.
- LateUpdate(): вызывается после того, как все объекты обновили свои позиции в текущем кадре.
✅ Метод полезен, когда необходимо обновить объект, исходя из его новой позиции после обновления других объектов.
- OnEnable(): вызывается, когда объект становится активным в иерархии сцены.
- OnDisable(): вызывается, когда объект становится неактивным в иерархии сцены.
- OnDestroy(): вызывается перед уничтожением объекта.
В дополнение к методам, MonoBehaviour имеет свойства, ниже некоторые из них:
- transform - для доступа к компоненту Transform объекта,
- gameObject - для доступа к объекту, на котором находится компонент
- и многие другие, которые позволяют получить доступ к различным свойствам и компонентам объекта.
С помощью MonoBehaviour можно реализовать множество функций, например:
- управление движением объектов,
- обработка столкновений,
- взаимодействие с пользователем и многое другое.
⛔На практике разработчики часто смешивают слои бизнес-логики, представления и контента в наследнике MonoBehaviour.
Такое смешение является плохой практикой по нескольким причинам:
1. Нарушение принципа единственной ответственности (SRP).
Каждый класс должен быть ответственным только за одну вещь, и смешение различных слоев функциональности в одном классе приводит к необходимости поддерживать несколько ответственностей одновременно.
Это усложняет код и его тестирование, увеличивает количество ошибок.
2. Сложность переноса и интеграции кода.
Когда вся функциональность приложения сосредоточена в наследнике MonoBehaviour, усложняется перенос в другую среду или интеграции с другими проектами.
Разделение функциональности на различные классы и слои позволяет легче переносить код и переиспользовать его.
3. Сложность тестирования.
Когда код приложения находится в одном монолитном классе, усложняется тестирование. Возникает необходимость создания сложных тестовых сценариев для проверки функциональности, что ведет к росту времени и увеличивает вероятность возниконовения ошибок.
4. Нарушение принципа разделения интерфейса и реализации (ISP).
Классы должны предоставлять только те методы и свойства, которые необходимы для работы с ними, а не всю функциональность приложения.
Смешение различных слоев функциональности в одном классе нарушает ISP и делает код менее гибким и модульным.
5. Усложнение поддержки кода.
Смешение различных слоев функциональности в одном классе делает код менее читабельным и понятным для других разработчиков.
Это усложняет поддержку и дальнейшее развитие приложения.
6. Трудности в отслеживании состояния объектов и их взаимодействия друг с другом.
Часто компоненты MonoBehaviour создаются и удаляются динамически в зависимости от событий в игре, подобное использование MonoBehaviour может сделать код менее гибким и менее управляемым.
Продолжение 👇
Приветствую, друзья 👋
Сегодняшняя публикация посвящена роли MonoBehaviour в проекте.
MonoBehaviour - это базовый класс в Unity, который используется для написания скриптов, управляющих поведением игровых объектов.
Он предоставляет множество методов жизненного цикла, которые могут быть переопределены для реализации логики игровых объектов.
Некоторые из основных методов, используемые в жизненном цикле объекта, включают в себя:
- Awake(): вызывается при создании объекта после инициализации всех его компонентов, но до того, как он станет активным в иерархии сцены.
- Start(): вызывается после Awake() и до первого обновления фрейма.
✅ В методе можно инициализировать переменные и компоненты, которые зависят от других объектов в сцене.
- Update(): вызывается каждый кадр и используется для обновления поведения объекта.
✅ В методе можно изменять свойства объекта, перемещать его, обрабатывать ввод и т.д.
- FixedUpdate(): вызывается с фиксированной частотой и используется для обновления физики объекта.
✅ Метод должен использоваться всякий раз, когда вам нужно изменять физические свойства объекта, такие как скорость, позиция, силы и т.д.
- LateUpdate(): вызывается после того, как все объекты обновили свои позиции в текущем кадре.
✅ Метод полезен, когда необходимо обновить объект, исходя из его новой позиции после обновления других объектов.
- OnEnable(): вызывается, когда объект становится активным в иерархии сцены.
- OnDisable(): вызывается, когда объект становится неактивным в иерархии сцены.
- OnDestroy(): вызывается перед уничтожением объекта.
В дополнение к методам, MonoBehaviour имеет свойства, ниже некоторые из них:
- transform - для доступа к компоненту Transform объекта,
- gameObject - для доступа к объекту, на котором находится компонент
- и многие другие, которые позволяют получить доступ к различным свойствам и компонентам объекта.
С помощью MonoBehaviour можно реализовать множество функций, например:
- управление движением объектов,
- обработка столкновений,
- взаимодействие с пользователем и многое другое.
⛔На практике разработчики часто смешивают слои бизнес-логики, представления и контента в наследнике MonoBehaviour.
Такое смешение является плохой практикой по нескольким причинам:
1. Нарушение принципа единственной ответственности (SRP).
Каждый класс должен быть ответственным только за одну вещь, и смешение различных слоев функциональности в одном классе приводит к необходимости поддерживать несколько ответственностей одновременно.
Это усложняет код и его тестирование, увеличивает количество ошибок.
2. Сложность переноса и интеграции кода.
Когда вся функциональность приложения сосредоточена в наследнике MonoBehaviour, усложняется перенос в другую среду или интеграции с другими проектами.
Разделение функциональности на различные классы и слои позволяет легче переносить код и переиспользовать его.
3. Сложность тестирования.
Когда код приложения находится в одном монолитном классе, усложняется тестирование. Возникает необходимость создания сложных тестовых сценариев для проверки функциональности, что ведет к росту времени и увеличивает вероятность возниконовения ошибок.
4. Нарушение принципа разделения интерфейса и реализации (ISP).
Классы должны предоставлять только те методы и свойства, которые необходимы для работы с ними, а не всю функциональность приложения.
Смешение различных слоев функциональности в одном классе нарушает ISP и делает код менее гибким и модульным.
5. Усложнение поддержки кода.
Смешение различных слоев функциональности в одном классе делает код менее читабельным и понятным для других разработчиков.
Это усложняет поддержку и дальнейшее развитие приложения.
6. Трудности в отслеживании состояния объектов и их взаимодействия друг с другом.
Часто компоненты MonoBehaviour создаются и удаляются динамически в зависимости от событий в игре, подобное использование MonoBehaviour может сделать код менее гибким и менее управляемым.
Продолжение 👇
#monobehaviour #архитектура
Продолжение Роль MonoBehaviour в проекте 👇
✅Что же является хорошей практикой?
Хорошей практикой является использование MonoBehaviour в качестве слоя View в Unity проекте.
Несколько правил, которые сделают использование данного класса эффективным:
1. Разделяйте логику и представление:
MonoBehaviour должен использоваться только для отображения объектов на сцене
2. Разделяйте игровые логики в отдельные классы:
Все игровые логики должны быть разделены в отдельных классах. Это обеспечит легкость понимания кода и возможность повторного использования
ℹ️ исключение может составлять логика, которая используется для работы самого представления.
Вопросы в комментариях приветствуются!
Лёгкой и продуктивной недели 💪
Продолжение Роль MonoBehaviour в проекте 👇
✅Что же является хорошей практикой?
Хорошей практикой является использование MonoBehaviour в качестве слоя View в Unity проекте.
Несколько правил, которые сделают использование данного класса эффективным:
1. Разделяйте логику и представление:
MonoBehaviour должен использоваться только для отображения объектов на сцене
2. Разделяйте игровые логики в отдельные классы:
Все игровые логики должны быть разделены в отдельных классах. Это обеспечит легкость понимания кода и возможность повторного использования
ℹ️ исключение может составлять логика, которая используется для работы самого представления.
Вопросы в комментариях приветствуются!
Лёгкой и продуктивной недели 💪
Приветствую, друзья 👋
По плану публикаций следующая тема должна быть посвящена организации префабов и роли слоя view в ней.
Но нам поступило несколько запросов на пост про CI/CD.
Поэтому предлагаем вам принять участие в опросе и выбрать тему следующей публикации 🙂
Поехали 👇
По плану публикаций следующая тема должна быть посвящена организации префабов и роли слоя view в ней.
Но нам поступило несколько запросов на пост про CI/CD.
Поэтому предлагаем вам принять участие в опросе и выбрать тему следующей публикации 🙂
Поехали 👇
Выбираем тему следующей публикации 👇
Final Results
57%
Организация префабов и роль слоя view в ней
43%
CI/CD в игровой разработке
#архитектура #prefab #view
Приветствую, друзья! 👋
По результатам голосования за выбор темы публикации между "Организацией префабов и роли слоя view в ней" и "CI/CD в игровой разработке" с результатом 57% победу одержали префабы.
Поэтому сегодня говорим про организацию префабов и роль слоя view в ней.
Начнем с организации.
Организация префабов в Unity - важный аспект процесса разработки игры.
Префаб - заранее созданный объект, который можно использовать в разных сценах игры.
Правильная организация позволит упростить процесс разработки, и организовать префабы таким образом, чтобы они были легко доступны и понятны для всей команды.
✅ Советы по организации префабов:
- Создание папок
Распределяйте префабы по папкам в соответствии с их функциональным назначением. Это упростит поиски нужного префаба. Например, разные папки для префабов игровых персонажей, окружения, звуков и т.д.
- Именование префабов
Имя префаба должно отражать его суть.
Ясные и понятные имена для каждого префаба позволяют легче его идентифицировать и искать.
- Использование тегов
Unity позволяет назначать теги для объектов, включая префабы.
Это упрощает поиск в больших проектах.
Назначение одного и того же тега нескольким префабам, позволит сгруппировать их вместе.
- Использование переменных
Используйте переменные для определения свойств префабов.
Например, переменная для определения здоровья игрового персонажа или скорости движения.
- Обновление префабов
При обновлении префаба, задействованного в сцене, убедитесь, что изменения не нарушит логику игры.
Например, если вы обновляете префаб игрового персонажа, убедитесь, что изменения не приведут к проблемам с анимацией или поведением персонажа.
- Переиспользование префабов
Будет полезно, если вы хотите создать множество однотипных объектов.
Например, при создании уровня, который включает множество блоков, можно создать префаб блока и использовать его для всех блоков в уровне.
Переиспользование префабов может значительно упростить процесс разработки игры в Unity, поскольку это позволяет использовать один раз созданный объект в разных частях игры.
✅ Советы по правильному переиспользованию префабов:
- Универсальность
Если планируется использование префаба в разных сценах игры, сделайте его универсальным для всех этих сцен.
Например, если вы создаете префаб здания, которое будет использоваться в разных уровнях игры, убедитесь, что он подходит для любого уровня, не только для текущего.
- Настраиваемость
Префабы могут быть настроены для изменения свойств в режиме редактирования Unity.
Например, вы можете создать префаб игрового персонажа и настроить его для разных типов персонажей, таких как главный герой, противники и т.д.
Это может упростить процесс создания игровых объектов в будущем.
- Версионнирование
Если вы обновляете префаб, который уже используется в игре, убедитесь, что новая версия не повлияет на уже созданные объекты.
Хорошей практикой является создание новых версий префаба с новым именем и обновление ссылок на них в игре.
- Документирование
Хорошей практикой является документирование использования префабов, чтобы другие члены команды знали как и могли легко использовать их в своей работе.
- Тестирование
Перед тем, как использовать префаб в игре, убедитесь, что он работает правильно.
Протестируйте его в разных условиях и убедитесь, что он работает корректно.
Продолжение 👇
Приветствую, друзья! 👋
По результатам голосования за выбор темы публикации между "Организацией префабов и роли слоя view в ней" и "CI/CD в игровой разработке" с результатом 57% победу одержали префабы.
Поэтому сегодня говорим про организацию префабов и роль слоя view в ней.
Начнем с организации.
Организация префабов в Unity - важный аспект процесса разработки игры.
Префаб - заранее созданный объект, который можно использовать в разных сценах игры.
Правильная организация позволит упростить процесс разработки, и организовать префабы таким образом, чтобы они были легко доступны и понятны для всей команды.
✅ Советы по организации префабов:
- Создание папок
Распределяйте префабы по папкам в соответствии с их функциональным назначением. Это упростит поиски нужного префаба. Например, разные папки для префабов игровых персонажей, окружения, звуков и т.д.
- Именование префабов
Имя префаба должно отражать его суть.
Ясные и понятные имена для каждого префаба позволяют легче его идентифицировать и искать.
- Использование тегов
Unity позволяет назначать теги для объектов, включая префабы.
Это упрощает поиск в больших проектах.
Назначение одного и того же тега нескольким префабам, позволит сгруппировать их вместе.
- Использование переменных
Используйте переменные для определения свойств префабов.
Например, переменная для определения здоровья игрового персонажа или скорости движения.
- Обновление префабов
При обновлении префаба, задействованного в сцене, убедитесь, что изменения не нарушит логику игры.
Например, если вы обновляете префаб игрового персонажа, убедитесь, что изменения не приведут к проблемам с анимацией или поведением персонажа.
- Переиспользование префабов
Будет полезно, если вы хотите создать множество однотипных объектов.
Например, при создании уровня, который включает множество блоков, можно создать префаб блока и использовать его для всех блоков в уровне.
Переиспользование префабов может значительно упростить процесс разработки игры в Unity, поскольку это позволяет использовать один раз созданный объект в разных частях игры.
✅ Советы по правильному переиспользованию префабов:
- Универсальность
Если планируется использование префаба в разных сценах игры, сделайте его универсальным для всех этих сцен.
Например, если вы создаете префаб здания, которое будет использоваться в разных уровнях игры, убедитесь, что он подходит для любого уровня, не только для текущего.
- Настраиваемость
Префабы могут быть настроены для изменения свойств в режиме редактирования Unity.
Например, вы можете создать префаб игрового персонажа и настроить его для разных типов персонажей, таких как главный герой, противники и т.д.
Это может упростить процесс создания игровых объектов в будущем.
- Версионнирование
Если вы обновляете префаб, который уже используется в игре, убедитесь, что новая версия не повлияет на уже созданные объекты.
Хорошей практикой является создание новых версий префаба с новым именем и обновление ссылок на них в игре.
- Документирование
Хорошей практикой является документирование использования префабов, чтобы другие члены команды знали как и могли легко использовать их в своей работе.
- Тестирование
Перед тем, как использовать префаб в игре, убедитесь, что он работает правильно.
Протестируйте его в разных условиях и убедитесь, что он работает корректно.
Продолжение 👇
#архитектура #prefab #view
Продолжение Роль слоя view в префабах 👇
View - наследник MonoBehaviour.
Его роль в организации префабов заключается в разделения ответственности между слоями представления и бизнес-логики.
Такой подход упрощает поддержку кода и делает его более гибким и масштабируемым.
View отвечает за отображение данных в игровом мире и может сообщать о них, также реагирует на изменение данных в pm.
Возможность реагировать на изменение данных в pm, отслеживать их и вызывать команды из слоя представления достигается через использование реактивных объектов, таких как ReactiveProperty или ReactiveCommand, помогает обеспечить правильное взаимодействие между слоями, упростить тестирование и отладку кода.
ReactiveProperty - это реактивный объект, который автоматически оповещает все подписанные на него объекты об изменении своего значения.
Он может использоваться для отслеживания изменений свойств.
Например, текущего здоровья игрока или его координат на карте.
ReactiveCommand - это реактивный объект, который представляет собой команду, которую можно вызвать.
Он позволяет разделять ответственность между слоем представления и pm, так как view не знает, что происходит за его пределами.
Например, при нажатии на кнопку "атаковать" в интерфейсе игрока, ReactiveCommand вызывает метод pm, который обрабатывает эту команду.
Кроме того, использование view позволяет легко настраивать префабы и создавать новые визуальные элементы, не затрагивая при этом pm.
Например, можно добавить новый элемент интерфейса, который будет отображать текущую скорость игрока, и при этом не вносить изменений в pm.
✅ Правила организации префабов с помощью View:
1. Каждый префаб должен иметь свой рутовый GameObject, на который необходимо повесить класс view.
2. В классе view необходимо явно прописать набор зависимостей
Набор зависимостей заполняем перетаскиванием. Они будут представлять собой другие GameObject'ы из иерархии префаба, необходимые для корректного отображения данных.
Например, у игрока может быть HpBar, который является дочерним объектом рутового GameObject'а, на котором также висит свой view класс.
Пример из Unity
3. В каждом классе view должен быть публичный метод SetCtx.
SetCtx вызывается при инициализации view через код в классе entity, после инстанцирования префаба.
Данный метод принимает контекст (обычно это структура) в виде зависимости.
Пример кода
Контекст должен содержать все необходимые зависимости для работы view.
Например, текущее здоровье игрока или его координаты на карте, реактивные объекты, контент.
Пример кода
‼️ Контекст view не должен содержать: context, entity, pm, view, content, state, так как в таком случае вы усилите зацепление.
Таким образом, использование view в организации префабов является важным элементом архитектуры Unity-проектов, который позволяет разделять ответственность между view и pm, упрощает поддержку и расширение кода и делает проект более гибким и масштабируемым.
Продолжение Роль слоя view в префабах 👇
View - наследник MonoBehaviour.
Его роль в организации префабов заключается в разделения ответственности между слоями представления и бизнес-логики.
Такой подход упрощает поддержку кода и делает его более гибким и масштабируемым.
View отвечает за отображение данных в игровом мире и может сообщать о них, также реагирует на изменение данных в pm.
Возможность реагировать на изменение данных в pm, отслеживать их и вызывать команды из слоя представления достигается через использование реактивных объектов, таких как ReactiveProperty или ReactiveCommand, помогает обеспечить правильное взаимодействие между слоями, упростить тестирование и отладку кода.
ReactiveProperty - это реактивный объект, который автоматически оповещает все подписанные на него объекты об изменении своего значения.
Он может использоваться для отслеживания изменений свойств.
Например, текущего здоровья игрока или его координат на карте.
ReactiveCommand - это реактивный объект, который представляет собой команду, которую можно вызвать.
Он позволяет разделять ответственность между слоем представления и pm, так как view не знает, что происходит за его пределами.
Например, при нажатии на кнопку "атаковать" в интерфейсе игрока, ReactiveCommand вызывает метод pm, который обрабатывает эту команду.
Кроме того, использование view позволяет легко настраивать префабы и создавать новые визуальные элементы, не затрагивая при этом pm.
Например, можно добавить новый элемент интерфейса, который будет отображать текущую скорость игрока, и при этом не вносить изменений в pm.
✅ Правила организации префабов с помощью View:
1. Каждый префаб должен иметь свой рутовый GameObject, на который необходимо повесить класс view.
2. В классе view необходимо явно прописать набор зависимостей
Набор зависимостей заполняем перетаскиванием. Они будут представлять собой другие GameObject'ы из иерархии префаба, необходимые для корректного отображения данных.
Например, у игрока может быть HpBar, который является дочерним объектом рутового GameObject'а, на котором также висит свой view класс.
Пример из Unity
3. В каждом классе view должен быть публичный метод SetCtx.
SetCtx вызывается при инициализации view через код в классе entity, после инстанцирования префаба.
Данный метод принимает контекст (обычно это структура) в виде зависимости.
Пример кода
Контекст должен содержать все необходимые зависимости для работы view.
Например, текущее здоровье игрока или его координаты на карте, реактивные объекты, контент.
Пример кода
‼️ Контекст view не должен содержать: context, entity, pm, view, content, state, так как в таком случае вы усилите зацепление.
Таким образом, использование view в организации префабов является важным элементом архитектуры Unity-проектов, который позволяет разделять ответственность между view и pm, упрощает поддержку и расширение кода и делает проект более гибким и масштабируемым.
View(ctx).png
99.3 KB
Контекст View - иллюстрация к статье
Prefab (view).png
99.5 KB
Prefab View - иллюстрация к статье
Entity (prefab+view).png
172.5 KB
Entity Prefab View - иллюстрация к статье
GameDev: разработка на Unity3D pinned «Привет, друзья 🙂 Ниже анонс тем для ближайших публикаций 👇 Все они вместе с затронутыми ранее темами являются важными составляющими разработки игр. UPD: для удобства навигации заголовок рассмотренных тем дополнен ссылкой на публикацию 1 Деление…»
#архитектура #разбор_кода
Приветствую, друзья 👋
Сегодняшняя публикация посвящена видеоразбору кода в рамках предлагаемого мной подхода к проектированию архитектуры.
Код написан мной на базе задания, которое давали ранее.
Т.к. на текущий момент по плану публикаций мы разобрали 4 темы, акцент при разборе сделан именно на них:
- Деление игры на слои абстракции.
- С чего должен начинаться Unity проект. Точка входа в код.
- MonoBehaviour.
- Организация префабов.
Видео получилось продолжительное и увесистое, доступно по ссылке
Приятного просмотра 📺
ПС: Приносим извинения за качество звука, проработаем данный вопрос к следующим записям!
Приветствую, друзья 👋
Сегодняшняя публикация посвящена видеоразбору кода в рамках предлагаемого мной подхода к проектированию архитектуры.
Код написан мной на базе задания, которое давали ранее.
Т.к. на текущий момент по плану публикаций мы разобрали 4 темы, акцент при разборе сделан именно на них:
- Деление игры на слои абстракции.
- С чего должен начинаться Unity проект. Точка входа в код.
- MonoBehaviour.
- Организация префабов.
Видео получилось продолжительное и увесистое, доступно по ссылке
Приятного просмотра 📺
ПС: Приносим извинения за качество звука, проработаем данный вопрос к следующим записям!
Telegram
GameDev: разработка на Unity3D
📌 UPD: группа желающих сделать тестовое задание для разбора сформирована 💪 всем спасибо за участие 👍
p/s если вы хотели, поучаствовать, но не успели, напишите, что-нибудь придумаем.
Приветствую, друзья 👋
С началом новой недели!
Пока мы готовим очередной…
p/s если вы хотели, поучаствовать, но не успели, напишите, что-нибудь придумаем.
Приветствую, друзья 👋
С началом новой недели!
Пока мы готовим очередной…
Приветствую! После публикации видео с разбором архитектурного подхода, от некоторых участников пришли комментарии, что объем слишком велик(. Что делаем?
Anonymous Poll
82%
оставьте на youtube, посмотрю там
18%
поделите на части и продублируйте здесь
#архитектура
Приветствую 👋
Сегодняшняя публикация посвящена жизненному циклу объектов (далее ЖЦ), в управлении которым важную роль играет класс Entity!
Роль Entity:
- создает и управляет объектами, в том числе ограничивает их жизненный цикл
- создает множество Entity, Pm, View
- создает реактивные объекты
- устанавливает связи через реактивные объекты
- создает и подготавливает ресурсы для объектов
- при завершении работы с объектами, освобождает ресурсы, занимаемые ими.
Каждая Entity может быть создана в подходящий момент в игре, например, когда игрок открывает сундук.
❗Созданные в Entity объекты являются частью ее жизненного цикла и могут использоваться только в рамках этого цикла.
Это означает, что после вызова метода Dispose у Entity, объекты, созданные ею, должны быть также освобождены и удалены из памяти, иначе могут возникнуть утечки.
❗Про освобождение памяти очень важно помнить, что при работе с Unity и другими движками, множество объектов создается и управляется автоматически.
Также контролировать ЖЦ и утечки помогает разделение слоя бизнес-логики и представления (о слоях говорили здесь).
Инстанцированные Entity создают дерево приложения - Composition Tree, которое определяет зависимости и взаимодействие объектов друг с другом (иллюстрация). Каждая Entity является вершиной этого дерева.
Подобный подход к управлению зависимостями похож на паттерн Composition Root, который рассматривается в различных статьях и книгах по проектированию приложений.
Подход предполагает, что в приложении существует единственная точка входа. В ней происходит инстанцирование и настройка всех объектов, затем они передаются в другие объекты через конструкторы или методы внедрения зависимостей.
Преимущества подхода
- гибкое и эффективное управление зависимостями
- обеспечение лучшей модульности
- упрощение поддержки и развития приложения, повышение его гибкости и надежности
- улучшение тестируемости кода.
Подобно Composition Root инстанцирование Entity в Composition Tree происходит в вершинах дерева.
Метод Framework'а DeferDispose, который существует в классах Entity, Pm и View, позволяет планировать вызов Dispose объекта, который будет передан в этом методе.
Метод DeferDispose(в классах Entity и Pm) вызывает Dispose как только в объекте, в котором вызывается этот метод, будет вызван Dispose.
Тогда как в классе MonoBehaviour(View) Dispose происходит при уничтожении GameObject, к которому этот MonoBehaviour прикреплен.
❗Использование метода DeferDispose наиболее рационально в конструкторе или в методе SetCtx (для MonoBehaviour), так как запланировать Dispose объекта можно в месте его создания.
Вне конструктора следует контролировать ЖЦ объекта самостоятельно, так как в некоторых случаях объект может быть создан чуть позже по требованию или не создан вовсе.
Внутри метода DeferDispose переданный объект добавляется в List. При вызове Dispose проход по List происходит в обратном порядке и вызывается Dispose для того объекта, который был передан в DeferDispose.
Проход в обратном порядке и Dispose всех объектов из списка связан с тем, что при выполнении Dispose некоторых объектов могут происходить различные операции, например, освобождение ресурсов, установка флагов или установка значений в реактивные объекты.
❌Dispose объектов в прямом порядке может привести к ошибкам, связанным с зависимостями между объектами, и некорректному освобождению ресурсов. Например, если один объект зависит от другого, то его Dispose должен произойти после Dispose зависимого объекта.
Подытожу: правильное управление ЖЦ объектов помогает избегать утечек памяти и строить более надежные и эффективные архитектуры приложений.
Жду ваши вопросы в комментариях👇
Приветствую 👋
Сегодняшняя публикация посвящена жизненному циклу объектов (далее ЖЦ), в управлении которым важную роль играет класс Entity!
Роль Entity:
- создает и управляет объектами, в том числе ограничивает их жизненный цикл
- создает множество Entity, Pm, View
- создает реактивные объекты
- устанавливает связи через реактивные объекты
- создает и подготавливает ресурсы для объектов
- при завершении работы с объектами, освобождает ресурсы, занимаемые ими.
Каждая Entity может быть создана в подходящий момент в игре, например, когда игрок открывает сундук.
❗Созданные в Entity объекты являются частью ее жизненного цикла и могут использоваться только в рамках этого цикла.
Это означает, что после вызова метода Dispose у Entity, объекты, созданные ею, должны быть также освобождены и удалены из памяти, иначе могут возникнуть утечки.
❗Про освобождение памяти очень важно помнить, что при работе с Unity и другими движками, множество объектов создается и управляется автоматически.
Также контролировать ЖЦ и утечки помогает разделение слоя бизнес-логики и представления (о слоях говорили здесь).
Инстанцированные Entity создают дерево приложения - Composition Tree, которое определяет зависимости и взаимодействие объектов друг с другом (иллюстрация). Каждая Entity является вершиной этого дерева.
Подобный подход к управлению зависимостями похож на паттерн Composition Root, который рассматривается в различных статьях и книгах по проектированию приложений.
Подход предполагает, что в приложении существует единственная точка входа. В ней происходит инстанцирование и настройка всех объектов, затем они передаются в другие объекты через конструкторы или методы внедрения зависимостей.
Преимущества подхода
- гибкое и эффективное управление зависимостями
- обеспечение лучшей модульности
- упрощение поддержки и развития приложения, повышение его гибкости и надежности
- улучшение тестируемости кода.
Подобно Composition Root инстанцирование Entity в Composition Tree происходит в вершинах дерева.
Метод Framework'а DeferDispose, который существует в классах Entity, Pm и View, позволяет планировать вызов Dispose объекта, который будет передан в этом методе.
Метод DeferDispose(в классах Entity и Pm) вызывает Dispose как только в объекте, в котором вызывается этот метод, будет вызван Dispose.
Тогда как в классе MonoBehaviour(View) Dispose происходит при уничтожении GameObject, к которому этот MonoBehaviour прикреплен.
❗Использование метода DeferDispose наиболее рационально в конструкторе или в методе SetCtx (для MonoBehaviour), так как запланировать Dispose объекта можно в месте его создания.
Вне конструктора следует контролировать ЖЦ объекта самостоятельно, так как в некоторых случаях объект может быть создан чуть позже по требованию или не создан вовсе.
Внутри метода DeferDispose переданный объект добавляется в List. При вызове Dispose проход по List происходит в обратном порядке и вызывается Dispose для того объекта, который был передан в DeferDispose.
Проход в обратном порядке и Dispose всех объектов из списка связан с тем, что при выполнении Dispose некоторых объектов могут происходить различные операции, например, освобождение ресурсов, установка флагов или установка значений в реактивные объекты.
❌Dispose объектов в прямом порядке может привести к ошибкам, связанным с зависимостями между объектами, и некорректному освобождению ресурсов. Например, если один объект зависит от другого, то его Dispose должен произойти после Dispose зависимого объекта.
Подытожу: правильное управление ЖЦ объектов помогает избегать утечек памяти и строить более надежные и эффективные архитектуры приложений.
Жду ваши вопросы в комментариях👇
#библиотека_программиста #composition_root
Приветствую 👋
Начнем неделю с подборки литературы, в которой рассматривается паттерн Composition Root:
📚
1. Книга, Mark Seemann, Dependency Injection in .NET, 2011
Краткий обзор: https://blog.ploeh.dk/2011/07/28/CompositionRoot/
2. Книга, Carl-Hugo Marcotte, Abdelhamid Zebdi, An Atypical "ASP.Net" Core 6 Design Patterns Guide, 2022
3. Книга, Gary Mclean, Adaptive Code via C#: Agile coding with design patterns and SOLID principles, 2014
4. Статья, Chris Fryer, Dependency Injection - Composition Root, 2018
https://medium.com/@cfryerdev/dependency-injection-composition-root-418a1bb19130
5. Статья, Jeremy, Dependency Injection Composition Root: Are We Just Moving the Coupling?, 2013
https://jeremybytes.blogspot.com/2013/03/dependency-injection-composition-root.html
Приятного чтения 🙂
И продуктивной недели 💪
Приветствую 👋
Начнем неделю с подборки литературы, в которой рассматривается паттерн Composition Root:
📚
1. Книга, Mark Seemann, Dependency Injection in .NET, 2011
Краткий обзор: https://blog.ploeh.dk/2011/07/28/CompositionRoot/
2. Книга, Carl-Hugo Marcotte, Abdelhamid Zebdi, An Atypical "ASP.Net" Core 6 Design Patterns Guide, 2022
3. Книга, Gary Mclean, Adaptive Code via C#: Agile coding with design patterns and SOLID principles, 2014
4. Статья, Chris Fryer, Dependency Injection - Composition Root, 2018
https://medium.com/@cfryerdev/dependency-injection-composition-root-418a1bb19130
5. Статья, Jeremy, Dependency Injection Composition Root: Are We Just Moving the Coupling?, 2013
https://jeremybytes.blogspot.com/2013/03/dependency-injection-composition-root.html
Приятного чтения 🙂
И продуктивной недели 💪
#архитектура #изолированность_классов
Приветствую 👋
Сегодня говорим про изолированность классов.
Изолированность классов - ситуация, в которой каждый класс:
- напрямую не зависит от другого
- не содержит публичные методы для обращения из другого места в приложении.
В данном контексте определение применимо к классам Entity, Pm (бизнес-логики) и View (представления).
Если вы пропустили публикацию про слои абстракции, ознакомиться можно тут.
Противоположный изолированности подход - наличие большого количества публичных методов и их вызов из разных мест в коде.
Большое количество публичных методов и их вызовы из разных мест в коде приводят к увеличению сложности кодовой базы и проблемам с сопровождением. Рано или поздно код превратится в “спагетти”.
"Спагетти код" - сложный в понимании и поддержке из-за большого количества взаимосвязанных частей и ветвлений логики код.
Для “спагетти” типична ситуация, когда изменения в одной части кода могут неожиданно привести к ошибкам а другой части кода.
Разберем зависимость между большим количеством публичных методов и качеством кода:
- нарушение принципа инкапсуляции и как следствие утечка абстракции.
Ситуация, при которой большое количество методов позволяет получить доступ к внутреннему состоянию объектов, приводит к тому, что в будущем изменение внутренней реализации класса потребует изменения всех методов, которые имеют доступ к этому состоянию.
- повышение сложности использования класса и усложнение интерфейса. Необходимость вызывать большое количество методов в определенном порядке и с определенными аргументами значительно усложнит использование данного класса в будущем.
- усложнение процесса отладки, тестирования и рефакторинга кода.
Ситуация, при которой есть возможность вызывать множество методов из разных мест в коде, усложняет локализацию ошибки, и увеличивает время ее исправление.
Избежать "спагетти кода" позволит:
- следование принципам SOLID и DRY
- разбиение приложения на слои абстракции
- сокращение количества публичных методов и удержание минимального количества связей между ними.
❗Изоляция классов друг от друга является важным принципом разработки, позволяет ослабить зацепление между классами, облегчить их тестирование и сопровождение.
Обеспечить изоляцию позволит использование минимального количества публичных методов и ограничение доступа к внутренней реализации класса.
Разберем, как организовать изоляцию классов👇
❗Итак изоляция классов обеспечивается через:
- для классов (не наследников MonoBehaviour) внедрения зависимостей через конструктор с использованием контекста
- для классов из слоя View (наследников MonoBehaviour) внедрение зависимостей также происходит через контекст, однако публичный метод SetCtx используется для передачи контекста в объект после его создания.
В идеальной ситуации SetCtx должен быть единственным публичным методом в классе, что позволит избежать проблем с неправильным использованием объекта.
💡Контекст должен содержать все необходимые зависимости, которые класс использует для своей работы, ❗ при этом класс не должен знать ничего о том, как и где создаются эти зависимости. Это позволяет легко заменять или изменять зависимости без изменения кода самого класса.
Важно, чтобы при передаче контекста все поля были инициализированы непустыми значениями. Это позволит избежать лишних проверок в коде (например на null).
❌ На практике распространена ситуация, когда до 20% кода класса состоит из проверок на пустые значения зависимостей, особенно когда речь идет про MonoBehaviour, где много логики написано в Update.
Таким образом, внедрение зависимостей через конструктор (или метод SetCtx для MonoBehaviour) и контекст позволит обеспечить изоляцию классов друг от друга, улучшит читаемость, тестируемость и сопровождаемость кода 💪
Прекрасного дня!
По традиции ждем вопросы в комментариях 👇
Приветствую 👋
Сегодня говорим про изолированность классов.
Изолированность классов - ситуация, в которой каждый класс:
- напрямую не зависит от другого
- не содержит публичные методы для обращения из другого места в приложении.
В данном контексте определение применимо к классам Entity, Pm (бизнес-логики) и View (представления).
Если вы пропустили публикацию про слои абстракции, ознакомиться можно тут.
Противоположный изолированности подход - наличие большого количества публичных методов и их вызов из разных мест в коде.
Большое количество публичных методов и их вызовы из разных мест в коде приводят к увеличению сложности кодовой базы и проблемам с сопровождением. Рано или поздно код превратится в “спагетти”.
"Спагетти код" - сложный в понимании и поддержке из-за большого количества взаимосвязанных частей и ветвлений логики код.
Для “спагетти” типична ситуация, когда изменения в одной части кода могут неожиданно привести к ошибкам а другой части кода.
Разберем зависимость между большим количеством публичных методов и качеством кода:
- нарушение принципа инкапсуляции и как следствие утечка абстракции.
Ситуация, при которой большое количество методов позволяет получить доступ к внутреннему состоянию объектов, приводит к тому, что в будущем изменение внутренней реализации класса потребует изменения всех методов, которые имеют доступ к этому состоянию.
- повышение сложности использования класса и усложнение интерфейса. Необходимость вызывать большое количество методов в определенном порядке и с определенными аргументами значительно усложнит использование данного класса в будущем.
- усложнение процесса отладки, тестирования и рефакторинга кода.
Ситуация, при которой есть возможность вызывать множество методов из разных мест в коде, усложняет локализацию ошибки, и увеличивает время ее исправление.
Избежать "спагетти кода" позволит:
- следование принципам SOLID и DRY
- разбиение приложения на слои абстракции
- сокращение количества публичных методов и удержание минимального количества связей между ними.
❗Изоляция классов друг от друга является важным принципом разработки, позволяет ослабить зацепление между классами, облегчить их тестирование и сопровождение.
Обеспечить изоляцию позволит использование минимального количества публичных методов и ограничение доступа к внутренней реализации класса.
Разберем, как организовать изоляцию классов👇
❗Итак изоляция классов обеспечивается через:
- для классов (не наследников MonoBehaviour) внедрения зависимостей через конструктор с использованием контекста
- для классов из слоя View (наследников MonoBehaviour) внедрение зависимостей также происходит через контекст, однако публичный метод SetCtx используется для передачи контекста в объект после его создания.
В идеальной ситуации SetCtx должен быть единственным публичным методом в классе, что позволит избежать проблем с неправильным использованием объекта.
💡Контекст должен содержать все необходимые зависимости, которые класс использует для своей работы, ❗ при этом класс не должен знать ничего о том, как и где создаются эти зависимости. Это позволяет легко заменять или изменять зависимости без изменения кода самого класса.
Важно, чтобы при передаче контекста все поля были инициализированы непустыми значениями. Это позволит избежать лишних проверок в коде (например на null).
❌ На практике распространена ситуация, когда до 20% кода класса состоит из проверок на пустые значения зависимостей, особенно когда речь идет про MonoBehaviour, где много логики написано в Update.
Таким образом, внедрение зависимостей через конструктор (или метод SetCtx для MonoBehaviour) и контекст позволит обеспечить изоляцию классов друг от друга, улучшит читаемость, тестируемость и сопровождаемость кода 💪
Прекрасного дня!
По традиции ждем вопросы в комментариях 👇
GameDev: разработка на Unity3D pinned «#архитектура #разбор_кода Приветствую, друзья 👋 Сегодняшняя публикация посвящена видеоразбору кода в рамках предлагаемого мной подхода к проектированию архитектуры. Код написан мной на базе задания, которое давали ранее. Т.к. на текущий момент по плану…»
Приветствую, друзья 👋
Вчера состоялось замечательное событие Yet Another Mobile Party или YAMP!
Было множество интересных докладчиков и докладов про мобильную разработку
В блоке, посвященном мобильному геймдеву (вы можете сразу перейти на него), где одним из приглашенных спикеров был я, обсудили текущее состояние индустрии, возможные тренды, стоит ли сейчас начинать свой путь в играх.
Полный выпуск по ссылке https://www.youtube.com/watch?v=dEKN4NYPs3M
Устраивайтесь поудобнее и приятного просмотра ☕
Вчера состоялось замечательное событие Yet Another Mobile Party или YAMP!
Было множество интересных докладчиков и докладов про мобильную разработку
В блоке, посвященном мобильному геймдеву (вы можете сразу перейти на него), где одним из приглашенных спикеров был я, обсудили текущее состояние индустрии, возможные тренды, стоит ли сейчас начинать свой путь в играх.
Полный выпуск по ссылке https://www.youtube.com/watch?v=dEKN4NYPs3M
Устраивайтесь поудобнее и приятного просмотра ☕
YouTube
Yet Another Mobile Party (YAMP) // 1 апреля 2023
Yet Another Mobile Party (YAMP) — это 5-ти часовой стрим в прямом эфире для iOS- и Android-разработчиков. Видеоподкаст без докладов и презентаций со спикерами из Яндекса и гостями из других компаний.
Вопросы можно задавать с хэштегом #вопрос в чате http…
Вопросы можно задавать с хэштегом #вопрос в чате http…