Pull to refresh
1
0

Пользователь

Send message
И это проблема — сложно тестировать поведение (например, двигателей) — нужно писать отдельный функционал для тестов. Другая проблема — inputController который жёстко зашит внутри ракеты. Что если мы хотим управлять ракетой через тесты? Что если через сеть? Что если через обучающий сценарий, что если хотим записать её полёт и повторить потом? Если бы у ракеты было просто SetTrust(float trust) то всех этих проблем не было бы — делай с ней, что хочешь.


В данном контексте тестирование супер изи, ибо есть конфиг в котором зашит параметр скорость — запихиваем разный конфиг, можно через инъекцию как раз агрегатором. Далее даём отмашку старт, далее присылаем ивенты добавления модификаторов. Тест занял бы от 2х с плюсом строчек строчек. Это легко делается тестовыми методами/классами, и можно проверить самые сложные сценарии типа применения одновременно нескольких модификаторов с разной силой влияния.

На самом деле я думаю уже можно закругляться, я понял вашу точку зрения. Я придерживаюсь другой и признаю большинство парадигм, и на мой взгляд всему своё место, COOP, OOP, AOP, Reactive, Event based, DDD.

И вопрос с подвохом — DDD придумали не сегодня, почему он не занял доминирующую позицию в программировании?
Только что был по лекции про DOTS, не везде он зайдет, и там очень много писанины, далее:

1) Компоненты у Unity слабый элемент, поэтому я в большинстве случаев за наследование и композицию. Композиция если брать абстрактно и есть парадигма COOP. Просто либо мы пользуемся обертками Unity со всеми вытекающими, либо сами пишем и дробим функционал как нам хочется. И скажем так — текущие компоненты это для удобства инди разработчика, понавесил какой то функционал, запихал в публичные поля объекты, и оно взлетело.

2)
И про этот event не должна знать
Не согласен, вполне себе в рамках событийной модели решение. Как еще ракете узнать что пора? Вешать более верхнюю сущность и хендлить там? Что еще будет делать эта сущность? Зачем она? Откуда ракета в принципе узнает что пора? В данный момент есть условный поток данных — старт ракеты, где может быть весь необходимый контекст. Всем кому интересны эти данные — реагируют.

3) Насчёт DOTS/ECS — ну это попытка пропихнуть DDD в более качественной обертке с волшебными штуками, но по факту у неё есть те же слабые места что и у DDD. Другой вопрос что при определенных задачах профит от DOTS очень крут. А вот то что писанины становится в разы больше и она не всегда оправдана — это факт. Порой для описания простой сущности нужны десятки объектов. Поэтому для простого прототипа казуалки я бы избегал нативного ECS.
Вдогонку к пункту 7 и 4, я вообще за разумную композицию и агрегацию
Спасибо за ответ и код ревью ) Особенно за начинающего программиста. Долго отвечал — был в кино, советую кстати Джонни Уика.

Итак:
1)
Зачем понадобилось усложнять и делать родительский класс, если почти наверняка будет всего один тип ракет в игре
Мы рассматривали возможность нескольких вариантов ракет, одна из которых может смещаться в полёте.

2)
Класс Rocket не должен знать про кнопку старта
Ну он и не знает, ракета только знает что ей прилетает ивент на старт

3)
Код под каждым case должен быть вынесен в отдельный метод.
Согласен, я просто придерживаюсь правила — если кода не очень много, можно оставить в кейсе. Но в отдельный метод будет правильнее.

4)
Но, вообще, класс Rocket ничего не должен знать про inputController. У Rocket должен быть отдельный компонент Driver или Engine, который должен иметь что-то типа SetTrust(float trust);
В любом деле главное без фанатизма, инпут контроллер в данном ракурсе не верхняя сущность, а всего лишь источник данных для принятия решений, да, в нём есть лишние данные для ракеты, более расово правильно это было всё связать через интерфейс с конкретными штуками, но снаружи мы не можем менять данные, поэтому если торчат пара лишних для ракеты полей — ничего страшного. Всё равно эти данные будут необходимы, если не ракете, так более верхней сущности/объекту.

5)
Зачем нужен агрегатор событий ещё и видимый всеми?
Я на самом деле понимаю что у меня есть проблема с позиционированием агрегатора, ибо под капотом там ивенты, механика работы у него — по сути потоки данных, а основная фича — именно контейнеры данных. Видимость всеми — ну в этом и фича, подписка на нужный тебе тип данных. В третьей части будут модификаторы которые просто присылают данные о модификаторе, может будет более очевидно, не говоря уже о инъекциях.

6)
Неверное именование. События называют просто Change/Click/Update а методы подписчиков уже OnChange, OnClick, OnUpdate.
склонен согласиться.

7)
Вообще, начинающие разработчики Unity (я и сам когда-то был в их числе) долгое время не понимают идеологии Unity. Идеология такая — если это что-то визуальное (звуковое и т.д.) на сцене, то это gameObject (или entity) на котором нужные компоненты, которые помогают его «визуализировать» и ничего больше. Всё, что не относится к визуализации, лучше выносить отдельно. Т.е. это чем-то похоже на MVC (gameObject это View) но совсем не MVC.
Если посмотреть на MonoBehaviour то видно, что внутри всё помогает отображать, анимировать, двигать объект и так далее. Логика должна быть снаружи.


COOP люблю, хорошая штука, но надо взглянуть на вещи шире — компонент Unity, это по факту куча барахла который тащит с собой монобех. Выделять функционал в отдельный юнити компонент, лучше когда он действительно отдельный и прям либо ваще никак не связан с конкретным классами. Например компонент для дефолтной озвучки UI(клик, наведение и тд), он вообще может ни про кого не знать и действовать автономно. В случае с ракетой — у неё только поведение связанное с движением. Допустим у нас всё становится сложнее — появляется стрельба, защитные поля, хелс поинты и тд, и допустим появятся враги, у которых будет такой же функционал (чисто фантазии). То этот функционал лучше разнести по классам моделям. И будет модель движения, модель стрельбы и тд. Опять же если смотреть шире — класс модель, и есть компонент в каком то смысле, ничто не мешает внедрить этот класс любому заинтересованному лицу. Пример в этом коде — ForceModel forceModel, этот класс можно применить например к астериодам, и они тоже станут попадать под влияние модификаторов. Плюс не забываем про любимый ООП, и у наследников мы можем переопределить или расширить функционал. Я против изначального дробления на мифические компоненты, вот это как раз и есть нарушения KISS в чистом виде. Вместо простого класса с простым поведением, мы пытаемся заложиться в COOP, плодим классы, плодим монобехи, каждый крутит свой апдейт, складирует в памяти кучу гавна которое не используется и тд. Те же Unity поняли что COOP в Unity тупиковый для оптимизации, и поэтому активно пилят ECS для слабых мест, который как раз выигрывает в том числе за счёт того что не тащит с собой целый багаж ненужных штук, которые валяются в куче.
Можно развернуть? В каких же местах злобное нарушение.
Каждой парадигме своё место, ECS еще сырой и с физикой он плохо работает(а точнее не работает), также для него еще нет good practice. В субботу пойду в маил ру как раз слушать про ECS и как правильно его готовить.
Я там ниже написал, когда ты один, сложно сделать качественный проектом размером больше мелкого. Есть исключения конечно в инди индустрии, но они скорее подчеркивают правило.
Да ) хороший вариант, публичность разработки/проекта даёт необходимый драйв, но одному сложно сделать средний/большой проект. Один мой знакомый пилит 5 лет средний проект (стратежку), и даже прототип нормальный не сделал )
Да, это самый правильный выход) если работать на результат
Не всё так просто, часто бывает нужен целый пласт знаний/скиллов, например 3д моделер делает воксельную графику в MagikaVoxel, там теперь несколько пространств с модельками, у каждой модельки генерится своя точка отсчёта координат относительно пространства, для каждого пространства генерится своя текстура, если в пространстве несколько моделек — у них всех смещен центр, это надо исправлять в 3д редакторах, если пространств много — надо сделать общий атлас. Если возник общий атлас — надо править ювишки. Если в юнити используется HDRP или LWRP — надо переделать шейдеры. Чтобы посвятить человека в нюансы, придётся потратить много времени на его обучение, причем обучение подразумевает как работу в юнити так и в 3д редакторах. Поэтому я упомянул что под наработками я также понимаю учебные материалы. Опять же человек может не понимать по английски.
в чем неблагодарность? )
Мне сложно поддерживать разговор, так как в США знакомых программистов нет, в Канаде есть, мы считали что у них примерно такая же зп выходит. Про США только знаю про налоги и тд, и что там не всё так красиво как сумма годовой зарплаты.
ну у нас это чистые деньги(на руки), а в США обычно говорят до налогов. Там в целом может до половины зп уйти на всякие налоги. Стоимость жилья/еды выше. Я думаю в сухом остатке у хорошего программиста в Москве получается немногим меньше чем у программиста в США.

Другой вопрос что там рынок/спрос выше.
ради интереса глянул hh на предмет вакансий, если брать мидлов, то не заметил большой разницы в зп. У синьоров/лидов большой разброс, потому сложно оценить в среднем.
Однако навскидку вакансий по Java например больше чем по С#, С++ меньше, Swift/ObjectiveC/Ios еще меньше. Scala — вакансий мало, но ценник там 200к -300к.

Поэтому утверждение что С# программисты дешевые — довольно спорное. Ну это касательно России, на стаковерфлоу наверное США имеется ввиду, а там нет популярной базы вакансий насколько я знаю, и сложно проверить количество вакансий/заработки
Думаю дело в геймдеве, на шарпе большой кластер инди разработчиков и всякие стартапы, которые портят статистику. В корпоративной разработке/бэкэнде думаю зп примерно равны другим языкам.
Чем универсальнее и функциональнее решение, тем выше порог входа и сложнее кастомизировать некоторые чамти. Поэтому надо выбирать, что-то среднее.


очень согласен с этой частью )
Почему вы решили что тот кто кидает ивент должен что то знать о подписчиках?
Тут будет два ивента — потому что будут кейсы когда нужно подсвечивать интерфейсы, но не показывать тултип и наоборот. В обоих случаях будет компонент который отслеживает поведение курсора, и будет вызывать ивенты, например ShowToolTip. Ему абсолютно не важно кто подписчик. Подписчиком в архитектуре может быть фабрика тултипов, может быть вьюменеджер и тд. А в этом ивенте можно передать достаточно контекста, чтобы понять — нужен ли тултип с картинкой, или текстом, или анимированный и тд. В этом отличие от остальных агрегаторов, в которых сложно передавать контекст.

Рассмотрим реализацию без ивента — хорошая альтернатива это прослойка с контроллером тултипов и DI.

PS почему я считаю альтернативу с DI более слабой — у нас как раз появляется связанность и дополнительные сущности/интерфейсы/фабрики и тд.
В целом согласен, просто приведу ряд аргументов за конкретное решение:
1) ивенты тут это конкретные классы или структуры, всегда можно посмотреть кто на них подписан и что передаётся внутри. То есть это не какой то DoSomething().Invoke;
Вызов в моем решении это — Invoke(new DoSomething {data});
И всегда можно глянуть кто что делает с классом DoSomething;

2) Самое правильное использование агрегаторов — пробрасывание инфы до интерфейса и/или некая реактивность логики. В бизнес приложениях всё понятно — MVC, MVVM и тд, и там есть уже конкретные реализации. В играх же часто надо чтобы когда что то случилось, случилось что то еще, без дополнительныъ связей. Реальный пример из жизни — при наведении на игровой элемент, должны появиться тултипы(конкретные, с конкретной инфой) и подсветиться элементы интерфейса связанные с тем что под курсором. Это можно пробросить за 1-2 ивента(можно за один, но лучше логически разделить на подсветку определенной группы и вызов определенного тултипа с опред. инфой) и несколько строчек кода. Другие решения приведут к большему количеству кода/контролирующих сущностей.

Information

Rating
Does not participate
Registered
Activity