Паттерны проектирования "команда" и "фасад" на примере Unreal Engine
HTML-код
- Опубликовано: 2 окт 2024
- Привет!
В этом я расскажу про паттерны проектирования "команда" и "фасад". Покажу на примере, как их можно использовать!
Приятного просмотра!
Моя игра в Steam: store.steampow...
Сервер дискорд: / discord
Бусти: boosty.to/nata...
#unrealengine #unrealengine5 #паттерны_преоктирования #паттерныпроектирования #command #facade
"Снять константность в архитектуре вместо того, чтобы использовать mutable для данных, которые просто кэшируют состояние?" - если два потока используют твой "константный" метод, который ничего не должен менять внутри объекта, то всё ломается. хотя хрен с ней многопоточкой, у тебя ExecuteCommand в персонаже не const, но у самой команды execute таки const. смысл?
"Как ты с помощью Static Array в рантайме будешь команды добавлять и убирать?" - ок, если надо в runtime менять количество элементов в контейнере, то подойдёт TArray с TInlineAllocator.
"Да даже с обычным TArray, но чтоб без гемора?" - а в чём собственно гемор? ты уже сделал enum в котором на этапе компиляции жёстко ограничиваешь количество команд с непрерывными значениями от 0. добавь в него SIZE последним для удобства тогда и будет легко его использовать как шаблонный параметр
для TInlineAllocator. я бы понял, если бы у тебя была фабрика/билдер, которые могли бы из lambda выражений формировать новые команды или даже целое дерево вызовов команд, которые зависят не от конкретных классов, а как-то находу лепятся. но у тебя просто пара enum - класс команды. или ты хочешь в TMap хранить больше одного экземпляра одной и той же команды?))
"Как ты создашь локальный объект на базовый класс? Там указатель нужен и создание этого объекта" - я так понимаю это про SP на 11:50. я про 15:10. там элементарно делается хранение фасада локально в классе перса.
"Причем тут вообще Input Action‘ы ?" - мне не понравилось, что в персонаже хранится такое многообразие данных разрозненно, хотя можно легко сгруппировать их в структуру и настраивать так же через blueprints.
"Что ты имеешь ввиду под «влиянием на состояние команды»?" - это был очень толстый намёк, что не надо в команде хранить никакое состояние. такие вещи в реальных проектах отстреливают ногу в самый неожиданный и неудобный момент. искать такие ошибки крайне трудно. это что-то на уровне удалять таймер из лямбды, которая по нему вызвалась. я вообще не понимаю, зачем передавать в команду персонажа и потом хранить по weak_ptr, если ты вызываешь команду из того же перса и можешь передать this.
"«Переключение команд - главное в этом паттерне»? Ты сейчас серьезно? Ты команды можешь вообще другими паттернами проектирования переключать. Или по нажатию кнопки. Или любой другой логикой" - так а почему ты самый сок не показал? где переключалка в рантайме? я именно к этому и докопался. написать в коде execute(MyEnum::MyCommand) каждый может. а вот сделать так, чтобы в рамках одного запуска у тебя по кнопке отрабатывали разные функции, а ещё сделать это красиво, это уметь надо)
P.S. тебя никто не пытался унизить, тебе показали на проблемные места. изложенное мною не является каким-то запредельно большим усложнением кода.
Итого мы
использовали mutable там, где можно было снять константность
использовали map там, где можно было обойтись обычным static array (tarray с inline allocator)
использовали shared pointer'ы там, где хватило бы локальных объектов
продолжили вписывать input action'ы в класс персонажа, вместо вынесения этих сущностей в отдельную структуру
добавили состояние в команду и не показали как на него влиять
не сделали переключение команд, что является главным поведением в этом паттерне
Снять константность в архитектуре вместо того, чтобы использовать mutable для данных, которые просто кэшируют состояние?
Как ты с помощью Static Array в рантайме будешь команды добавлять и убирать? Да даже с обычным TArray, но чтоб без гемора?
Как ты создашь локальный объект на базовый класс? Там указатель нужен и создание этого объекта
Причем тут вообще Input Action‘ы ?
Что ты имеешь ввиду под «влиянием на состояние команды»?
«Переключение команд - главное в этом паттерне»? Ты сейчас серьезно? Ты команды можешь вообще другими паттернами проектирования переключать. Или по нажатию кнопки. Или любой другой логикой
@@natatem0080
"Снять константность в архитектуре вместо того, чтобы использовать mutable для данных, которые просто кэшируют состояние?" - если два потока используют твой "константный" метод, который ничего не должен менять внутри объекта, то всё ломается. да и в конце концов у тебя команда телепортирует персонажа. почему она константная? наверное есть разница между семантикой и синтаксисом языка?)
"Как ты с помощью Static Array в рантайме будешь команды добавлять и убирать?" - ок, если надо в runtime менять количество элементов в контейнере, то подойдёт TArray с TInlineAllocator.
"Да даже с обычным TArray, но чтоб без гемора?" - а в чём собственно гемор? ты уже сделал enum в котором на этапе компиляции жёстко ограничиваешь количество команд и элементы идут по возрастанию от 0. можно вписать последним элемент SIZE и использовать для передачи в шаблонный аргумент TInlineAllocator. я бы понял, если бы у тебя была фабрика/билдер, которые могли бы из lambda выражений формировать новые команды в runtime. но у тебя просто enum. или ты хочешь в TMap пихать больше одного экземпляра одной и той же команды?))
"Как ты создашь локальный объект на базовый класс? Там указатель нужен и создание этого объекта" - я так понимаю это про SP на 11:50. я про 15:10. там элементарно делается хранение фасада локально в классе перса.
"Причем тут вообще Input Action‘ы ?" - мне не понравилось, что в персонаже хранится такое многообразие данных разрозненно, хотя можно легко сгруппировать их в структуру и настраивать так же через blueprints.
"Что ты имеешь ввиду под «влиянием на состояние команды»?" - это был очень толстый намёк, что не надо так костыльно пихать никакие переменные в команду. в не учебном проекте такое отстреливает ногу в самый неожиданный момент и часто трудно находится ошибка. у тебя там хранится персонаж чтобы что? ты когда вызываешь команду можешь его передавать как аргумент функции. это к моменту про локальный фасад в персонаже.
"«Переключение команд - главное в этом паттерне»? Ты сейчас серьезно? Ты команды можешь вообще другими паттернами проектирования переключать. Или по нажатию кнопки. Или любой другой логикой" - ну так чего ж ты самый сок не показал? я тебе об этом и говорю. очень круто, что ты на этапе компиляции можешь написать execute(MyEnum::Command1), но ведь смысл паттерна команда в возможности выбирать вызываемый метод в runtime. и у тебя в видео этого нет.
@@natatem0080
"Снять константность в архитектуре вместо того, чтобы использовать mutable для данных, которые просто кэшируют состояние?" - если два потока используют твой "константный" метод, который ничего не должен менять внутри объекта, то всё ломается. хотя хрен с ней многопоточкой, у тебя ExecuteCommand в персонаже не const, но у самой команды execute таки const. смысл?
"Как ты с помощью Static Array в рантайме будешь команды добавлять и убирать?" - ок, если надо в runtime менять количество элементов в контейнере, то подойдёт TArray с TInlineAllocator.
"Да даже с обычным TArray, но чтоб без гемора?" - а в чём собственно гемор? ты уже сделал enum в котором на этапе компиляции жёстко ограничиваешь количество команд с непрерывными значениями от 0. добавь в него SIZE последним для удобства тогда и будет легко его использовать как шаблонный параметр
для TInlineAllocator. я бы понял, если бы у тебя была фабрика/билдер, которые могли бы из lambda выражений формировать новые команды или даже целое дерево вызовов команд, которые зависят не от конкретных классов, а как-то находу лепятся. но у тебя просто пара enum - класс команды. или ты хочешь в TMap хранить больше одного экземпляра одной и той же команды?))
"Как ты создашь локальный объект на базовый класс? Там указатель нужен и создание этого объекта" - я так понимаю это про SP на 11:50. я про 15:10. там элементарно делается хранение фасада локально в классе перса.
"Причем тут вообще Input Action‘ы ?" - мне не понравилось, что в персонаже хранится такое многообразие данных разрозненно, хотя можно легко сгруппировать их в структуру и настраивать так же через blueprints.
"Что ты имеешь ввиду под «влиянием на состояние команды»?" - это был очень толстый намёк, что не надо в команде хранить никакое состояние. такие вещи в реальных проектах отстреливают ногу в самый неожиданный и неудобный момент. искать такие ошибки крайне трудно. это что-то на уровне удалять таймер из лямбды, которая по нему вызвалась. я вообще не понимаю, зачем передавать в команду персонажа и потом хранить по weak_ptr, если ты вызываешь команду из того же перса и можешь передать this.
"«Переключение команд - главное в этом паттерне»? Ты сейчас серьезно? Ты команды можешь вообще другими паттернами проектирования переключать. Или по нажатию кнопки. Или любой другой логикой" - так а почему ты самый сок не показал? где переключалка в рантайме? я именно к этому и докопался. написать в коде execute(MyEnum::MyCommand) каждый может. а вот сделать так, чтобы в рамках одного запуска у тебя по кнопке отрабатывали разные функции, а ещё сделать это красиво, это уметь надо)
P.S. тебя никто не пытался унизить, тебе показали на проблемные места. изложенное мною не является каким-то запредельно большим усложнением кода.
@@natatem0080 "Снять константность в архитектуре вместо того, чтобы использовать mutable для данных, которые просто кэшируют состояние?" - если два потока используют твой "константный" метод, который ничего не должен менять внутри объекта, то всё ломается. хотя хрен с ней многопоточкой, у тебя ExecuteCommand в персонаже не const, но у самой команды execute таки const. смысл?
"Как ты с помощью Static Array в рантайме будешь команды добавлять и убирать?" - ок, если надо в runtime менять количество элементов в контейнере, то подойдёт TArray с TInlineAllocator.
"Да даже с обычным TArray, но чтоб без гемора?" - а в чём собственно гемор? ты уже сделал enum в котором на этапе компиляции жёстко ограничиваешь количество команд с непрерывными значениями от 0. добавь в него SIZE последним для удобства тогда и будет легко его использовать как шаблонный параметр
для TInlineAllocator. я бы понял, если бы у тебя была фабрика/билдер, которые могли бы из lambda выражений формировать новые команды или даже целое дерево вызовов команд, которые зависят не от конкретных классов, а как-то находу лепятся. но у тебя просто пара enum - класс команды. или ты хочешь в TMap хранить больше одного экземпляра одной и той же команды?))
"Как ты создашь локальный объект на базовый класс? Там указатель нужен и создание этого объекта" - я так понимаю это про SP на 11:50. я про 15:10. там элементарно делается хранение фасада локально в классе перса.
"Причем тут вообще Input Action‘ы ?" - мне не понравилось, что в персонаже хранится такое многообразие данных разрозненно, хотя можно легко сгруппировать их в структуру и настраивать так же через blueprints.
"Что ты имеешь ввиду под «влиянием на состояние команды»?" - это был очень толстый намёк, что не надо в команде хранить никакое состояние. такие вещи в реальных проектах отстреливают ногу в самый неожиданный и неудобный момент. искать такие ошибки крайне трудно. это что-то на уровне удалять таймер из лямбды, которая по нему вызвалась. я вообще не понимаю, зачем передавать в команду персонажа и потом хранить по weak_ptr, если ты вызываешь команду из того же перса и можешь передать this.
"«Переключение команд - главное в этом паттерне»? Ты сейчас серьезно? Ты команды можешь вообще другими паттернами проектирования переключать. Или по нажатию кнопки. Или любой другой логикой" - так а почему ты самый сок не показал? где переключалка в рантайме? я именно к этому и докопался. написать в коде execute(MyEnum::MyCommand) каждый может. а вот сделать так, чтобы в рамках одного запуска у тебя по кнопке отрабатывали разные функции, а ещё сделать это красиво, это уметь надо)
P.S. тебя никто не пытался унизить, тебе показали на проблемные места. изложенное мною не является каким-то запредельно большим усложнением кода.
@@natatem0080"Снять константность в архитектуре вместо того, чтобы использовать mutable для данных, которые просто кэшируют состояние?" - если два потока используют твой "константный" метод, который ничего не должен менять внутри объекта, то всё ломается. хотя хрен с ней многопоточкой, у тебя ExecuteCommand в персонаже не const, но у самой команды execute таки const. смысл?
"Как ты с помощью Static Array в рантайме будешь команды добавлять и убирать?" - ок, если надо в runtime менять количество элементов в контейнере, то подойдёт TArray с TInlineAllocator.
"Да даже с обычным TArray, но чтоб без гемора?" - а в чём собственно гемор? ты уже сделал enum в котором на этапе компиляции жёстко ограничиваешь количество команд с непрерывными значениями от 0. добавь в него SIZE последним для удобства тогда и будет легко его использовать как шаблонный параметр
для TInlineAllocator. я бы понял, если бы у тебя была фабрика/билдер, которые могли бы из lambda выражений формировать новые команды или даже целое дерево вызовов команд, которые зависят не от конкретных классов, а как-то находу лепятся. но у тебя просто пара enum - класс команды. или ты хочешь в TMap хранить больше одного экземпляра одной и той же команды?))
"Как ты создашь локальный объект на базовый класс? Там указатель нужен и создание этого объекта" - я так понимаю это про SP на 11:50. я про 15:10. там элементарно делается хранение фасада локально в классе перса.
"Причем тут вообще Input Action‘ы ?" - мне не понравилось, что в персонаже хранится такое многообразие данных разрозненно, хотя можно легко сгруппировать их в структуру и настраивать так же через blueprints.
"Что ты имеешь ввиду под «влиянием на состояние команды»?" - это был очень толстый намёк, что не надо в команде хранить никакое состояние. такие вещи в реальных проектах отстреливают ногу в самый неожиданный и неудобный момент. искать такие ошибки крайне трудно. это что-то на уровне удалять таймер из лямбды, которая по нему вызвалась. я вообще не понимаю, зачем передавать в команду персонажа и потом хранить по weak_ptr, если ты вызываешь команду из того же перса и можешь передать this.
"«Переключение команд - главное в этом паттерне»? Ты сейчас серьезно? Ты команды можешь вообще другими паттернами проектирования переключать. Или по нажатию кнопки. Или любой другой логикой" - так а почему ты самый сок не показал? где переключалка в рантайме? я именно к этому и докопался. написать в коде execute(MyEnum::MyCommand) каждый может. а вот сделать так, чтобы в рамках одного запуска у тебя по кнопке отрабатывали разные функции, а ещё сделать это красиво, это уметь надо)
P.S. тебя никто не пытался унизить, тебе показали на проблемные места. изложенное мною не является каким-то запредельно большим усложнением кода.
Благодарю за видео! В Red Rift в каких частях кода используют данные паттерны?
То, что доктор прописал))
Вопрос зачем глаза красить? Или без этого в ГЕЙмдев не пускают?))
🤡
он капитан Джек Воробей 😄
Если бы ты знал, какой это головняк...
Я как-то проспал, в офис пришел не накрашенный и меня засмеяли коллеги. Такого позора в моей жизни никогда не было. Очень стыдно. Начальник отказался пересматривать зарплату. И не видать повышения до главы отдела.