Здесь нужно задать два вопроса:
1. А в скольких процентах случаев фаза «ну я же говорил» в итоге так и не наступила после этих решений?
2. Если такой процент ничтожно мал, то не кажется ли вам, что у вас в команде нездоровая атмосфера и ее надо просто сменить?
Это реально, мы часть инфы для конфли генерили из кода. Но это работает только для тех мест, которые поддерживает разработка. Пустить в репозиторий аналитиков\бизнес\саппорт может быть немного геморно со всех сторон (для одних — тюнинг прав и больше нагрузка на ревью изменений в репе, для других — необходимость изучать гит и процессы по которым это попадает в финальную доку, как посмотреть промежуточный результат без коммита и т.ж.)
Чести ради и «все константы класса» тоже нельзя, только через рефлексию. Поправьте, если ошибаюсь. Но эту ветку мы обсуждаем исходя из того что контроль типов не нужен человеку, только группировка значений
Пойдем еще дальше и добавим контроль допустимых значений через массив, а не через наличие метода. После этого можно вынести все кроме static $values в базовый родительский класс и у нас получился неплохой переиспользуемый енам
/**
* @method static static SUMMER()
* @method static static AUTUMN()
* @method static static WINTER()
* @method static static SPRING()
*/
final class Seasons
{
private static array $mapping = [];
private static array $values = [
'SUMMER',
'AUTUMN',
'WINTER',
'SPRING',
];
private string $name;
private function __construct(string $name)
{
$this->name = $name;
}
public static function __callStatic(string $name, array $args): self
{
if (!in_array($name, self::$values, true)) {
throw new \BadMethodCallException("Value $name is not allowed");
}
if (!isset(self::$mapping[$name])) {
self::$mapping[$name] = new self($name);
}
return self::$mapping[$name];
}
}
понимаю, что пример наколеночный, но вижу два недостатка:
* Нет контроля типов (т.е если унести свитч в отедльный метод\набор методов, то там будет таки (string $action) в сигнатуре.
* Енам либо придется делать глобальным, либо инстанциировать в каждом месте, где его надо обработать, т.е. опять же если унести этот свитч в отдельный метод, то для проверки значений придется инстанциировать енам заново, что будет плодить этот набор значений по кодовой базе
Обращения к рефлексии кэшируются в памяти класса и повторно используется мемори кэш вместо рефлексии при обращении к инстансам.
В целом можно было бы сделать и без рефлексии (похожий пример ниже в коментах), но первая версия этой либы работала на текстовых константах (new MyEnum(MyEnum::NAME1) ) и было решено оставить работу со списком значений через константы, а не через массив допустимых значений
Весь проект переписать на другой ЯП в тот момент когда понадобились перечисления — такая себе затея. Давайте будем честны, иногда работаем с чем есть, проекты не только создают, но и развивают существующие.
Как раз попалось на глаза видео про zigbee direct binding youtu.be/xgtZazMZNto?t=202
Выглядит очень удобно — координатор жив — получаем полноценное взаимодействие, mqtt и прочее. Выключили координатор — связанные устройства все еще общаются напрямую, не нужен даже роутер.
При этом сопряжение идет через удобный UI. Кажется если научиться заливать в такие штуки сценарии подобные вашим, то будет совсем круто
Ручная прошивка и сопряжение не нужны, я такой дичи нигде не предлагал…
Неправильно выразился, да. под «каждый с каждым» я имел ввиду именно ручное распределение сценариев по устройствам
Вы кажется используете крайне примитивную прошивку, даже в моём прототипе есть протокол первоначального подключения к сети, по которому можно подключить устройство в новую сеть без перепрошивки — это стандарт для commodity устройств…
Я использую голые esp — на них ничего нет изначально, так что прошивать все равно приходится. Но вообще да, на них можно залить прошивку вообще без конфига и донастроить опосля, но если девайс воткнут у меня в сериал порт — мне проще сразу и конфиг залить
но кол-во устройств задействованных в одном сценарии не растет — сценарии задействующие десятки устройств — редкость.
Классический сценарий «погасить весь свет в доме по нажатию на кнопку» будет требовать манипуляций с перенастройкой при добавлении каждого устройства (или замены обычного светильника на умный).
— В клиент-серверной архитектуре та самая единица добавляемая к M — это убернода, выруб которой убивает всю систему — это еще снижает надежность. x Такой SkyNet сможет завалить любой Нео нашедший сервер HA/MQTT.
— Так-же есть фактор стоимости — нода под HA нередко окажется самой дорогой во всей сети
Как я уже сказал HA — вообще необязательный компонент сети, а MQTT можно развернуть на таких же esp. Выруб — да, валит всю систему. Но как уже не раз сказали вероятность такая же как вырубить роутер\центральный свитч или что у вас там за сеть отвечает, имхо
Я же в целом эту проблему решаю чуть проще (и в плане исполнения и в плане удобства). Все критические девайсы в случае отвала SPoF (mqtt\роутер) можно тыкать физически прямо через девайс. т.е. можно подойти и переключить умную розетку вручную (на них есть кнопка), подойти и выключить умный свет выключателем и т.д. Т.е я заранее строю UX так, чтобы все деградировало до обычного «неумного» дома в случае проблем с девайсами
Но я процитирую соседний ответ
Не сочтите за критику, Ваше решение мне очень понравилось.
Мне кажется вам надо попробовать применить эту концепцию в сторону зигби девайсов. Они умеют строить меш сети где аргумент про отвал роутера больше не будет валидным ) Если присыпать это дело UI, который будет уметь заливать скрипты в девайсы — и кажется будет крутой продукт
Сейчас вы выступаете в качестве «ручного» окрестратора устройств при их конфигурации. При наличии большого количества устройств если спаривать их все вручную друг с другом займет кучу времени. Вы по сути предлагаете каждому устройству рассказать про каждое физическое устройство. Если нужно будет внести изменения, то это тоже куча работы — например отправлять данные не на одно устройство, а на 10. имея MQTT вам вообще не придется ничего модифицировать — вы просто подписываете 10 девайсов на один и тот же топик (т.е. по факту имеете 10 одинаковых девайсов с идентичной прошивкой).
Во вторых MQTT это не только точка отказа, но и точка резервации данных для устройств. Если какой-то девайс ребутался и пропустил последний пакет со стейтом то он легко может вычитать его из топика сразу при загрузке. В вашем случае он будет ожидать следующего пакета.
Я конечно выражаю точку зрения бытового потребителя этого всего добра. Для частного случая и единичного применения наверное это прикольно, но заставлять массового потребителя вручную прошивать и сопрягать каждое устройство с каждым ради децентрализации — выглядит оверхедом. Я заливаю на все свои устройства одинаковую прошивку с одинаковым конфигом — они знают только про вайфай сеть и mqtt брокера.
Нигде вручную не зашиваются полтора десятка айпишников (у меня устройства вообще по dhcp получают адреса)
Более того благодаря проектам типа zigbee2mqtt в эту же экосистему легко интегрируются девайсы котороые вообще не умеют в tcp\ip. Как это можно сделать с вашим подходом?
У вас нет SPoF только до тех пор пока вы все девайсы настраивайте и спаривайте вручную. Когда девайсов станет несколько десятков, то SPoF станете вы сами.
У меня полтора десятка и я бы уже задолбался каждый настраивать вручную
Все так. По факту если брать какую-нибудь тасмоту в качестве базовой прошивки для девайсов, то на HA накладываются только несколько ролей
* Няшный интерфейс с хранением истории данных
* Интеграция более тупых сервисов в экосистему (условный смарт тв который не умеет в mqtt)
* Интеграция внешних систем в экосистему (например, подключение к google home\alexa\алисе или подключение других брендов IoT у которых нет нормальных локальных протоколов)
Все остальное успешно работает мимо HA, через mqtt и системы автоматизации типа node-red.
ну технически окружение у процесса есть всегда, а вот файл еще вычитать надо, потратив на это ресурс. во-вторых так проще запускать во всяких докерах. есть один и тот же образ с одной и той же фс без .env, а настройки задаются при запуске образа. да хоть через тот же --env-file=.env, но приложение про него не узнает — образ остается неизменным, что более гибко. можно конечно смаунтить .env в образ, но тоже не думаю что это удобно и производительно.
опять же в случае работы через переменные окружения не все фреймворки будут уязвимыми от утечки кэша. симфони например не кэширует env переменные при дампе кэша, насколько я знаю
Именно в этом примере ярко демонстрируется проблема: в названии поля meail сделана опечатка и чтобы это исправить вам придется так же сделать релевантную правку в вашем API (точней она была уже сделана, если этот код работает), который в предыдущем примере был абсолютно независимым.
Но скрестив два этих RFC вместе получаем двойную проблему — мало того что имена параметров — теперь часть API, так еще и при неудачном использовании даже приватные поля класса становятся частью API, т.к. описываются через именованные параметры.
Я не то чтобы против этих нововведений, но пример, на мой взгляд, совсем не демонстрирует их преимущества, а даже наоборот — выставляет в негативном свете.
Вопрос в том, зачем вам проверять айдишник? Важно ли что он именно 5? Будет ли проблема, если 6? Может важно лишь то, что по айдишнику, который в ответ был возвращен системой лежат данные, которые вы этим запросом отправили, а какой именно айдишник вам выдали — не важно?
Представьте себе, что вместо ваших тестов сидит тестировщик и у него есть какое — то состояние приложение — он не знает какие данные туда заливали раньше. Как он будет проверять этот запрос?
Позвольте узнать, а что именно вы проверяете такое, где нужна привязка к генерируемым автоинкрементом айдишникам? На моей практике такие вещи сигнализируют об очень хрупких тестах которые дорого обслуживать и от которых мало профита.
1. А в скольких процентах случаев фаза «ну я же говорил» в итоге так и не наступила после этих решений?
2. Если такой процент ничтожно мал, то не кажется ли вам, что у вас в команде нездоровая атмосфера и ее надо просто сменить?
habr.com/ru/post/517752/#comment_22041126
* Нет контроля типов (т.е если унести свитч в отедльный метод\набор методов, то там будет таки (string $action) в сигнатуре.
* Енам либо придется делать глобальным, либо инстанциировать в каждом месте, где его надо обработать, т.е. опять же если унести этот свитч в отдельный метод, то для проверки значений придется инстанциировать енам заново, что будет плодить этот набор значений по кодовой базе
www.php.net/manual/ru/class.ds-map.php
Работают строгие сравнения (===, in_array($value, [MyEnum::NAME1(), MyEnum::NAME2()], true) и пр.)
Косяка из комента ниже нет habr.com/ru/post/517752/#comment_22031208
Food::BEER() === Waste::BEER() не пройдет (это разные инстансы)
Обращения к рефлексии кэшируются в памяти класса и повторно используется мемори кэш вместо рефлексии при обращении к инстансам.
В целом можно было бы сделать и без рефлексии (похожий пример ниже в коментах), но первая версия этой либы работала на текстовых константах (new MyEnum(MyEnum::NAME1) ) и было решено оставить работу со списком значений через константы, а не через массив допустимых значений
youtu.be/xgtZazMZNto?t=202
Выглядит очень удобно — координатор жив — получаем полноценное взаимодействие, mqtt и прочее. Выключили координатор — связанные устройства все еще общаются напрямую, не нужен даже роутер.
При этом сопряжение идет через удобный UI. Кажется если научиться заливать в такие штуки сценарии подобные вашим, то будет совсем круто
Неправильно выразился, да. под «каждый с каждым» я имел ввиду именно ручное распределение сценариев по устройствам
Я использую голые esp — на них ничего нет изначально, так что прошивать все равно приходится. Но вообще да, на них можно залить прошивку вообще без конфига и донастроить опосля, но если девайс воткнут у меня в сериал порт — мне проще сразу и конфиг залить
Классический сценарий «погасить весь свет в доме по нажатию на кнопку» будет требовать манипуляций с перенастройкой при добавлении каждого устройства (или замены обычного светильника на умный).
Как я уже сказал HA — вообще необязательный компонент сети, а MQTT можно развернуть на таких же esp. Выруб — да, валит всю систему. Но как уже не раз сказали вероятность такая же как вырубить роутер\центральный свитч или что у вас там за сеть отвечает, имхо
Я же в целом эту проблему решаю чуть проще (и в плане исполнения и в плане удобства). Все критические девайсы в случае отвала SPoF (mqtt\роутер) можно тыкать физически прямо через девайс. т.е. можно подойти и переключить умную розетку вручную (на них есть кнопка), подойти и выключить умный свет выключателем и т.д. Т.е я заранее строю UX так, чтобы все деградировало до обычного «неумного» дома в случае проблем с девайсами
Но я процитирую соседний ответ
Мне кажется вам надо попробовать применить эту концепцию в сторону зигби девайсов. Они умеют строить меш сети где аргумент про отвал роутера больше не будет валидным ) Если присыпать это дело UI, который будет уметь заливать скрипты в девайсы — и кажется будет крутой продукт
Во вторых MQTT это не только точка отказа, но и точка резервации данных для устройств. Если какой-то девайс ребутался и пропустил последний пакет со стейтом то он легко может вычитать его из топика сразу при загрузке. В вашем случае он будет ожидать следующего пакета.
То что требует отдельного девайса — на той же esp можно поднять брокер
Я конечно выражаю точку зрения бытового потребителя этого всего добра. Для частного случая и единичного применения наверное это прикольно, но заставлять массового потребителя вручную прошивать и сопрягать каждое устройство с каждым ради децентрализации — выглядит оверхедом. Я заливаю на все свои устройства одинаковую прошивку с одинаковым конфигом — они знают только про вайфай сеть и mqtt брокера.
Нигде вручную не зашиваются полтора десятка айпишников (у меня устройства вообще по dhcp получают адреса)
Более того благодаря проектам типа zigbee2mqtt в эту же экосистему легко интегрируются девайсы котороые вообще не умеют в tcp\ip. Как это можно сделать с вашим подходом?
У меня полтора десятка и я бы уже задолбался каждый настраивать вручную
Но в целом та же тасмота умеет в device groups (udp multicast)
tasmota.github.io/docs/Device-Groups без mqtt если очень хочется.
* Няшный интерфейс с хранением истории данных
* Интеграция более тупых сервисов в экосистему (условный смарт тв который не умеет в mqtt)
* Интеграция внешних систем в экосистему (например, подключение к google home\alexa\алисе или подключение других брендов IoT у которых нет нормальных локальных протоколов)
Все остальное успешно работает мимо HA, через mqtt и системы автоматизации типа node-red.
опять же в случае работы через переменные окружения не все фреймворки будут уязвимыми от утечки кэша. симфони например не кэширует env переменные при дампе кэша, насколько я знаю
Именно в этом примере ярко демонстрируется проблема: в названии поля meail сделана опечатка и чтобы это исправить вам придется так же сделать релевантную правку в вашем API (точней она была уже сделана, если этот код работает), который в предыдущем примере был абсолютно независимым.
Но скрестив два этих RFC вместе получаем двойную проблему — мало того что имена параметров — теперь часть API, так еще и при неудачном использовании даже приватные поля класса становятся частью API, т.к. описываются через именованные параметры.
Я не то чтобы против этих нововведений, но пример, на мой взгляд, совсем не демонстрирует их преимущества, а даже наоборот — выставляет в негативном свете.
Представьте себе, что вместо ваших тестов сидит тестировщик и у него есть какое — то состояние приложение — он не знает какие данные туда заливали раньше. Как он будет проверять этот запрос?