Я не согласен с вашей аналогией. React, Angular, Vue, решают типовые инженерные задачи.
Управление командой — это не типовая инженерная задача и не наука, это soft skills. Каждый сотрнудник индивидуален, к каждому нужен свой подход. Кто-то умеет и хочет подстраиваться под команду, а кто-то наоборот, гораздо производительнее если его не трогают.
Поэтому любые попытки применить "фреймворк" к человеческим отношениям выглядят так же нелепо, как книги по пикапу с набором составленных фраз.
Во-первых, вы строите всю архитектуру на предположении о том, что у вас может одновременно показываться только одна менюшка и это требование никогда не изменится. Но завтра к вам приходит дизайнер / заказчик и просит сделать drag-and-drop между менюшками, и оказывается что во время перетаскивания надо показать обе одновременно. И в такой момент вы понимаете, что весь код придется для этого выкинуть / переписать с нуля, потому что само понятие машины состояний тут неприменимо (раз может быть несколько состояний одновременно).
Во-вторых, в самом switch-case, конечно, ничего страшного нет, но как только добавится логика, анимации переключения между меню итд, появятся классы типа State, StateTransition и прочих артефактов спагетти-стейт машин, и проблема #1 станет еще хуже.
Как по мне, так хорошо установленные паттерны вроде MVC отлично подойдут здесь. Каждое меню или подменю имеет свою пару Controller — View. Controller отвечает за логику и делает вызовы в сервисы, View — за представление (шаблон меню, анимации). За переключение подменю может отвечать одна функция, которая при разворачивании контент-меню закрывает остальные:
Это просто, понятно, читабельно, а главное, требование "одновременно может быть показано толко одно меню", запрограммировано ровно в одной функции на 12 строк кода и может быть в любой момент времени изменено.
Не стройте архитектуру на предположениях, которые могут оказаться неверны.
Каждый сервис FSA не сильно отличается от монолитных FSA. Разбивая логику на сервисы, не забывая о принципе единой ответственности и SOLID в целом, вы быстро обнаружите, что FSA вам не нужны.
Приведите конкретный пример функционала и я приведу вам пример как сделать его на обычном OOP, без всяких FSA.
Ну, я говорил об играх. Понятное дело, за пределами игр есть ряд узкоспециализированных задач и алгоритмов где FSA применимы. Но для геймплей логики их использовать — это зло.
IMO, Finite State Machines — это антипаттерн похуже синглотонов. Он имеет очень узкое применение — анимация и AI, использовать его где либо еще — моветон. За годы работы в геймдеве, я не видел ни одной нормальной реализации FSA которая бы не раздулась в неподдерживоемое спагетти.
Переписать толком можно легко, есть куча паттернов и подходов, начиная классическими вроде MVC / MVVM (которые отлично подходят для UI-driven и 2d игр, с теми или иными изменениями), и заканчиая Entity Component System и Data Oriented Design.
Я считаю, что в таких ситуацях гораздо уместнее писать Service-Centric код и Inversion of Control. Вместо монолитной машины состояний, состояние игры описывается набором сервисов. Каждый сервис имеет свое сосотояние отвечает за что-то одно и только одно, например: анимация, диалоги, инвентарь, квесты, прогресс игрока, сохранения, аутентификация итд.
Сервисы слабо связаны (через интерфейс) и общаются друг с другом по минимуму. Соответственно, ожидания каждого сервиса так же описываются через интерфейс / контракт, например, сервис диалогов может обращаться к сервису интвентаря что бы узнать, имеется ли в наличии предмет, требуемый для выполнения квеста, итд (InventoryService.HasItem(...)).
Логика каждого сервиса может быть протестирована Unit и Integration тестами.
Проверка целостности 7z.dll это очень смешно.
Помню еще в начале-середине 2000ых, так обходили кривые корейские античиты, которые преимущественно боролись с DLL Injection с помощью проверки целостности Import Address Table.
Обход: скачивались исходники соответствующей версии 7zip, пересобирались с нужными изменениями, и клались в папку с игрой :P
Собираю так проект на Unity. По сути — практически бесплатный аналог Unity Cloud Build (если иметь Unity Pro то можно и на бесплатных агентах MS и не понимать виртуалку, но тогда придется при каждом билде ставить движок)
Изменения крутые и полезные.
Очень хотелось бы что бы исправили концептуальные проблемы языка, даже если это означает python 4 и сломанную обратную совместимость.
Например те же импорты все ещё очень сложны для понимания новичками (особенно по сравнению с другими языками). При этом циркулярные импорты падают в рантайме с неадекватной ошибкой, а orm фреймворки вроде той же алхимии предлагают решать проблему просто — указывать название классов текстом *facepalm".
Вы путаете время реакции и время отклика на действие игрока.
Можете выставить здесь 100мс и покликать. Представьте, у вас 2d шутер, и что вам нужно попадать по быстро движущемся целям, и ваша игра станет невыносимой.
А теперь представьте, что данный лаг происходит всегда, в том числе при повороте камеры.
Не критикуя статью, покритикую подход.
Я считаю что глобальные аггрегаторы событий нарушают принципы SOLID.
За 6 лет работы с Unity я не видел ни одного проекта, в котором глобальные аггрегаторы событий оправдывали бы себя. В основном все заканчивается спагетти кодом с кучей неявных зависимостей.
Про re-usability кода можно вообще забыть — любой процесс переноса модуля в другой проект заканчивается жестким рефакторингом с поиском по всему проекту, где и что на что подписано.
Этим, кстати, на мой взгляд страдают JS фреймворки и дизайны вроде React / Redux. Все отлично работает, когда у вас TODO приложение с двумя событиями. А когда у вас команда на 50 человек, тысячи классов и событий, все это становится очень трудно поддерживать.
Человек не выбирает, в каком государстве ему рождаться.
Пользоваться или не пользоваться YouTube, каждый решает сам для себя.
Тем более что в данном примере, YouTube не банит видео (хотя следовало бы), а просто отказывается платить вам деньги. Я не считаю это цензурой.
apt-get install в Debian прекрасен ровно до тех пор, пока вам не понадобилось с его помощью поставить новый софт. apt-get install python3 в Debian устанавливает 3.5.3 (2015й год) apt-get install python3 в Ubuntu устанавливает 3.6.6 (2016й год)
Смотрим в календарь, видим что на дворе 2019й. Наливаем чай и идем собирать из исходников, подключать альтернативные репозитории или прикручивать pyenv.
DontBreakDebian говорит вам о том, что новый софт вам "не нужен" потому что он "не протестирован", ведь ребята из Debian лучше вас знают, что вам нужно а что нет. Ведь вам нужна надежность. Что довольно иронично, учитывая что некоторые пакеты там настолько старые, что они просто не работают.
Советую посмотреть на Dependency Injection и DI / IoC фреймворки вроде ZenJect (линк).
Знаю, что для новичка это не простая концепция, но она имеет большое количество преимуществ перед синглтонами/статик классами/DontDestroyOnLoad.
Данный подход позволит сделать единую точку входа в приложение, а для хранения данных пользователя вместо singleton объекта можно использовать сервис (который потом можно заинъектить в необходимые вам скрипты):
public interface IGameDataService
{
public int DifficultyLevel { get; set; }
}
public class EnemyInstaller : MonoInstaller
{
public override void InstallBindings()
{
// IGameDataService будет автоматически инъекцировано в зависимые классы
// включая другие сцены, если использован Scene Container Parenting
Container.Bind<IGameDataService>().To<GameDataService>().AsSingleton();
}
}
public class EnemyFactory : IEnemyFactory
{
private readonly IGameDataService _gameDataService;
// Зависимость будет добавлена в конструктор автоматически при резолвинге EnemyFactory
// Для инъекции в MonoBehavior, можно добавить специальный компонент ZenjectBinding и аттрибут [Inject]
public EnemyFactory(IGameDataService gameDataService)
{
_gameDataService = gameDataService;
}
public void SpawnEnemy(string enemyName)
{
var level = _gameDataService.DifficultyLevel;
...
var enemy = GameObject.Instantiate(...).GetComponent<IEnemy>();
enemy.SetLevel(level);
}
}
В идеале, GameObject'ы и MonoBehavior'ы — для объектов игрового мира. Для всего остального есть обычный C#.
Компанию переименовали из Tesla Motors, Inc в Tesla, Inc в начале 2017 года. В статье речь об авто, которую продали в 2017м (чек датирован декабрем 2017го, но в целом кому выписан чек это не так важно).
На прошлой неделе на Google Pixel 2 приехал апдейт с Google Call Screening, который на 100% решает проблему спам-звонков, которая заключается не в самих звонках, а в том, что людям приходится снимать трубку, если они ждут звонка от курьера/рекрутера/кого угодно.
Уже поймал таким образом пару спамеров и очень смешно смотреть как они пытаются поговорить с автоответчиком.
В западных компаниях НИКОГДА, повторю, НИКОГДА не будут звонить в вашу предыдущую компанию во время background check. Попросят список recommendations/references с телефонами/emailами, и уже из указанного случайно позвонят или (что скорее всего) отправят email с просьбой дать характеристику.
Если представить, что мы живем в симуляции, которую писали программисты, то я все жду когда физики обнаружат константу бога — единую константу, из которой элегантными формулами выведутся все остальные фундаментальные физические постоянные.
Я не согласен с вашей аналогией. React, Angular, Vue, решают типовые инженерные задачи.
Управление командой — это не типовая инженерная задача и не наука, это soft skills. Каждый сотрнудник индивидуален, к каждому нужен свой подход. Кто-то умеет и хочет подстраиваться под команду, а кто-то наоборот, гораздо производительнее если его не трогают.
Поэтому любые попытки применить "фреймворк" к человеческим отношениям выглядят так же нелепо, как книги по пикапу с набором составленных фраз.
Я считаю что вы делаете две потенциальные ошибки.
Во-первых, вы строите всю архитектуру на предположении о том, что у вас может одновременно показываться только одна менюшка и это требование никогда не изменится. Но завтра к вам приходит дизайнер / заказчик и просит сделать drag-and-drop между менюшками, и оказывается что во время перетаскивания надо показать обе одновременно. И в такой момент вы понимаете, что весь код придется для этого выкинуть / переписать с нуля, потому что само понятие машины состояний тут неприменимо (раз может быть несколько состояний одновременно).
Во-вторых, в самом switch-case, конечно, ничего страшного нет, но как только добавится логика, анимации переключения между меню итд, появятся классы типа State, StateTransition и прочих артефактов спагетти-стейт машин, и проблема #1 станет еще хуже.
Как по мне, так хорошо установленные паттерны вроде MVC отлично подойдут здесь. Каждое меню или подменю имеет свою пару Controller — View. Controller отвечает за логику и делает вызовы в сервисы, View — за представление (шаблон меню, анимации). За переключение подменю может отвечать одна функция, которая при разворачивании контент-меню закрывает остальные:
Это просто, понятно, читабельно, а главное, требование "одновременно может быть показано толко одно меню", запрограммировано ровно в одной функции на 12 строк кода и может быть в любой момент времени изменено.
Не стройте архитектуру на предположениях, которые могут оказаться неверны.
Каждый сервис FSA не сильно отличается от монолитных FSA. Разбивая логику на сервисы, не забывая о принципе единой ответственности и SOLID в целом, вы быстро обнаружите, что FSA вам не нужны.
Приведите конкретный пример функционала и я приведу вам пример как сделать его на обычном OOP, без всяких FSA.
Ну, я говорил об играх. Понятное дело, за пределами игр есть ряд узкоспециализированных задач и алгоритмов где FSA применимы. Но для геймплей логики их использовать — это зло.
IMO, Finite State Machines — это антипаттерн похуже синглотонов. Он имеет очень узкое применение — анимация и AI, использовать его где либо еще — моветон. За годы работы в геймдеве, я не видел ни одной нормальной реализации FSA которая бы не раздулась в неподдерживоемое спагетти.
Переписать толком можно легко, есть куча паттернов и подходов, начиная классическими вроде MVC / MVVM (которые отлично подходят для UI-driven и 2d игр, с теми или иными изменениями), и заканчиая Entity Component System и Data Oriented Design.
Я считаю, что в таких ситуацях гораздо уместнее писать Service-Centric код и Inversion of Control. Вместо монолитной машины состояний, состояние игры описывается набором сервисов. Каждый сервис имеет свое сосотояние отвечает за что-то одно и только одно, например: анимация, диалоги, инвентарь, квесты, прогресс игрока, сохранения, аутентификация итд.
Сервисы слабо связаны (через интерфейс) и общаются друг с другом по минимуму. Соответственно, ожидания каждого сервиса так же описываются через интерфейс / контракт, например, сервис диалогов может обращаться к сервису интвентаря что бы узнать, имеется ли в наличии предмет, требуемый для выполнения квеста, итд (InventoryService.HasItem(...)).
Логика каждого сервиса может быть протестирована Unit и Integration тестами.
Предполагаю, что если бэкенд программисты говнокодят, и доверяют клиенту без каких-либо проверок, то тут никакой античит не спасет.
Проверка целостности 7z.dll это очень смешно.
Помню еще в начале-середине 2000ых, так обходили кривые корейские античиты, которые преимущественно боролись с DLL Injection с помощью проверки целостности Import Address Table.
Обход: скачивались исходники соответствующей версии 7zip, пересобирались с нужными изменениями, и клались в папку с игрой :P
Собираю так проект на Unity. По сути — практически бесплатный аналог Unity Cloud Build (если иметь Unity Pro то можно и на бесплатных агентах MS и не понимать виртуалку, но тогда придется при каждом билде ставить движок)
Изменения крутые и полезные.
Очень хотелось бы что бы исправили концептуальные проблемы языка, даже если это означает python 4 и сломанную обратную совместимость.
Например те же импорты все ещё очень сложны для понимания новичками (особенно по сравнению с другими языками). При этом циркулярные импорты падают в рантайме с неадекватной ошибкой, а orm фреймворки вроде той же алхимии предлагают решать проблему просто — указывать название классов текстом *facepalm".
Вы путаете время реакции и время отклика на действие игрока.
Можете выставить здесь 100мс и покликать. Представьте, у вас 2d шутер, и что вам нужно попадать по быстро движущемся целям, и ваша игра станет невыносимой.
А теперь представьте, что данный лаг происходит всегда, в том числе при повороте камеры.
Мониторы и зарядки в сетевой фильтр, а его в розетку?
Можно сделать как в Valve, у которых все рабочие столы мобильные.
Не критикуя статью, покритикую подход.
Я считаю что глобальные аггрегаторы событий нарушают принципы SOLID.
За 6 лет работы с Unity я не видел ни одного проекта, в котором глобальные аггрегаторы событий оправдывали бы себя. В основном все заканчивается спагетти кодом с кучей неявных зависимостей.
Про re-usability кода можно вообще забыть — любой процесс переноса модуля в другой проект заканчивается жестким рефакторингом с поиском по всему проекту, где и что на что подписано.
Этим, кстати, на мой взгляд страдают JS фреймворки и дизайны вроде React / Redux. Все отлично работает, когда у вас TODO приложение с двумя событиями. А когда у вас команда на 50 человек, тысячи классов и событий, все это становится очень трудно поддерживать.
Человек не выбирает, в каком государстве ему рождаться.
Пользоваться или не пользоваться YouTube, каждый решает сам для себя.
Тем более что в данном примере, YouTube не банит видео (хотя следовало бы), а просто отказывается платить вам деньги. Я не считаю это цензурой.
apt-get install в Debian прекрасен ровно до тех пор, пока вам не понадобилось с его помощью поставить новый софт.
apt-get install python3в Debian устанавливает 3.5.3 (2015й год)apt-get install python3в Ubuntu устанавливает 3.6.6 (2016й год)Смотрим в календарь, видим что на дворе 2019й. Наливаем чай и идем собирать из исходников, подключать альтернативные репозитории или прикручивать pyenv.
DontBreakDebian говорит вам о том, что новый софт вам "не нужен" потому что он "не протестирован", ведь ребята из Debian лучше вас знают, что вам нужно а что нет. Ведь вам нужна надежность. Что довольно иронично, учитывая что некоторые пакеты там настолько старые, что они просто не работают.
Советую посмотреть на Dependency Injection и DI / IoC фреймворки вроде ZenJect (линк).
Знаю, что для новичка это не простая концепция, но она имеет большое количество преимуществ перед синглтонами/статик классами/DontDestroyOnLoad.
Данный подход позволит сделать единую точку входа в приложение, а для хранения данных пользователя вместо singleton объекта можно использовать сервис (который потом можно заинъектить в необходимые вам скрипты):
В идеале, GameObject'ы и MonoBehavior'ы — для объектов игрового мира. Для всего остального есть обычный C#.
Компанию переименовали из Tesla Motors, Inc в Tesla, Inc в начале 2017 года. В статье речь об авто, которую продали в 2017м (чек датирован декабрем 2017го, но в целом кому выписан чек это не так важно).
На прошлой неделе на Google Pixel 2 приехал апдейт с Google Call Screening, который на 100% решает проблему спам-звонков, которая заключается не в самих звонках, а в том, что людям приходится снимать трубку, если они ждут звонка от курьера/рекрутера/кого угодно.
Уже поймал таким образом пару спамеров и очень смешно смотреть как они пытаются поговорить с автоответчиком.
В западных компаниях НИКОГДА, повторю, НИКОГДА не будут звонить в вашу предыдущую компанию во время background check. Попросят список recommendations/references с телефонами/emailами, и уже из указанного случайно позвонят или (что скорее всего) отправят email с просьбой дать характеристику.
Если представить, что мы живем в симуляции, которую писали программисты, то я все жду когда физики обнаружат константу бога — единую константу, из которой элегантными формулами выведутся все остальные фундаментальные физические постоянные.