Паттерны проектирования "команда" и "фасад" на примере Unreal Engine

Поделиться
HTML-код
  • Опубликовано: 2 окт 2024
  • Привет!
    В этом я расскажу про паттерны проектирования "команда" и "фасад". Покажу на примере, как их можно использовать!
    Приятного просмотра!
    Моя игра в Steam: store.steampow...
    Сервер дискорд: / discord
    Бусти: boosty.to/nata...
    #unrealengine #unrealengine5 #паттерны_преоктирования #паттерныпроектирования #command #facade

Комментарии • 13

  • @dominuspiritus
    @dominuspiritus Месяц назад

    "Снять константность в архитектуре вместо того, чтобы использовать 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. тебя никто не пытался унизить, тебе показали на проблемные места. изложенное мною не является каким-то запредельно большим усложнением кода.

  • @dominuspiritus
    @dominuspiritus Месяц назад

    Итого мы
    использовали mutable там, где можно было снять константность
    использовали map там, где можно было обойтись обычным static array (tarray с inline allocator)
    использовали shared pointer'ы там, где хватило бы локальных объектов
    продолжили вписывать input action'ы в класс персонажа, вместо вынесения этих сущностей в отдельную структуру
    добавили состояние в команду и не показали как на него влиять
    не сделали переключение команд, что является главным поведением в этом паттерне

    • @natatem0080
      @natatem0080  Месяц назад

      Снять константность в архитектуре вместо того, чтобы использовать mutable для данных, которые просто кэшируют состояние?
      Как ты с помощью Static Array в рантайме будешь команды добавлять и убирать? Да даже с обычным TArray, но чтоб без гемора?
      Как ты создашь локальный объект на базовый класс? Там указатель нужен и создание этого объекта
      Причем тут вообще Input Action‘ы ?
      Что ты имеешь ввиду под «влиянием на состояние команды»?
      «Переключение команд - главное в этом паттерне»? Ты сейчас серьезно? Ты команды можешь вообще другими паттернами проектирования переключать. Или по нажатию кнопки. Или любой другой логикой

    • @dominuspiritus
      @dominuspiritus Месяц назад

      ​@@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. и у тебя в видео этого нет.

    • @dominuspiritus
      @dominuspiritus Месяц назад

      ​@@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. тебя никто не пытался унизить, тебе показали на проблемные места. изложенное мною не является каким-то запредельно большим усложнением кода.

    • @dominuspiritus
      @dominuspiritus Месяц назад

      ​@@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. тебя никто не пытался унизить, тебе показали на проблемные места. изложенное мною не является каким-то запредельно большим усложнением кода.

    • @dominuspiritus
      @dominuspiritus Месяц назад

      ​@@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. тебя никто не пытался унизить, тебе показали на проблемные места. изложенное мною не является каким-то запредельно большим усложнением кода.

  • @k0c0u
    @k0c0u 3 месяца назад

    Благодарю за видео! В Red Rift в каких частях кода используют данные паттерны?

  • @Котвбезумнойшляпе
    @Котвбезумнойшляпе 3 месяца назад

    То, что доктор прописал))

  • @ProGuitarUA
    @ProGuitarUA 3 месяца назад

    Вопрос зачем глаза красить? Или без этого в ГЕЙмдев не пускают?))

    • @gt34m62
      @gt34m62 3 месяца назад +1

      🤡

    • @neopoznan1399
      @neopoznan1399 3 месяца назад

      он капитан Джек Воробей 😄

    • @dominuspiritus
      @dominuspiritus Месяц назад

      Если бы ты знал, какой это головняк...
      Я как-то проспал, в офис пришел не накрашенный и меня засмеяли коллеги. Такого позора в моей жизни никогда не было. Очень стыдно. Начальник отказался пересматривать зарплату. И не видать повышения до главы отдела.