Я правильно понимаю, что ваша организация наняла молодого программиста, не проверив его компетенции и технологии, которыми он владеет, как и его опыт?
Вы поставили перед ним таску, которую он сделал исходя из своих компетенций и технологий, которыми он владеет?
Потом вы попросили его сделать некоторый лоулевел, который ему не дан ибо для него нужен миддл.
Вопрос - а почему вы взяли вместо миддла или сеньора непонятно кого? Потому что он дешев?
Ну и кто тогда должен оправдываться?
Те ваша восточноевропейская эйчарка взяла неизвестно кого, вы его пустили к себе в стэк не проверив, а оправдываться надо только ему?
В ситуации виноваты все, через кого Василий к вам попал, при этом Василий виноват меньше всего - таску, которую ему озвучивали он закрыл, то что делать он не умеет - он честно про это вам сказал, а не стал гуглить и тянуть время - как обычно бывает. Так что далеко не все так однозначно.
О правильности я в конце первого комментария написал - нужно всеми силами избегать блокирующего кода везде, где только можно (не только в микропроцессорах) , и использовать его только тогда, когда это прямо реально нужно и кейсов таких от силы пол-процента наберется.
Задачу можно решить быстро и в лоб, а можно решить хорошо. Блокирующий - это всегда быстро и в лоб, что потом чревато проблемами и переделками.
Зачем все подряд упаковывать в конечные автоматы?!
Потому что это более универсальней и покрывает весь спектр задач, это можно сделать один раз, а потом лишь переиспльзовать будучи на 99% уверенным, что код этот может всегда расширить на бОльшее колво случаев и работать он будет предсказуемо и четко. При этом самого кода при таком подходе будет не сильно больше, нежели у решения в лоб.
Ну, надо начать просто - чем больше, тем лучше будет.
Например, появляется возможность использовать классы как скоп, чтобы не гадить в глобальную область видимости. (можно статический, если не предвидится несколько таких).
Использовать объекты, когда есть что-то повторяющиеся в системе (кнопки, например).
Использовать ссылки, вместо передачи по значению.
Ну и возможность выносить класс или набор классов, как отдельный файл с отдельным функционалом - это прямо киллерфича - глобал не загрязняется, а порождая тип, ну например OLED display( PORTA, PIN1) сразу понятно что куда почему + инициализация, если нужна.
Раньше C++ не использовался ввиду того, что давал оверхэд при компиляции для микропррцессоров, сейчас компиляторы его практически не дают - разница может составлять совсем не много около - 0.2-0.5%
И раньше я также писал только на C из-за этого, сейчас куда правильней писать на C++ и иметь все его плюшки - программы получаются проще и гораздо более гибкими.
Но понятно, что при использовании C++, надо и метрологию его использовать, а не процедуры + вкоряченный класс)
При этом может получиться очень интересная штука - программа, написанная на C++ с использованием C++ особенностей получится меньшей по размеру и более быстрой, чем делующая тоже на C. На небольших программах это практически не видно, а вот с увеличением размера начинает ощущаться.
Очень подробно и с диаграммами — круто.
Но — блокирующий опрос кнопок — это очень плохо, особенно, если проект сложный.
Вообще все блокирующее в микроконтроллерах — это всегда плохо, особенно, если их быстродействие не велико.
Гораздо правильней делать это с помощью чего-то похожего на конечный автомат.
И так и делают — одна из самых популярных (но не самых крутых) — это библиотека по работе с кнопками от AlexGyver.
Суть в том, что есть структура (или класс) кнопки, где хранится ее состояние, когда было это по времени (значение таймера отсчета), предыдущее состояние и тд.
И на основе этих данных можно и дабл- и трипл-клики обрабатывать, и удержание и клик+удержание и много чего еще, причем с помощью очень небольших изменений кода.
И для того, чтобы обновить состояние — нужно просто вызвать некую фю, передав туда отсчет времени. И делать это можно где-угодно — хочешь — в таймере, хочешь — по прерыванию, хочешь — в основном цикле. Лишь бы паузы между вызовами были не слишком большие — иначе реакция будет подтормаживать. А так — один раз тайминги настроил и забыл.
Это удобней и в разы универсальней.
При этом таких кнопок сколько угодно можно породить (хоть динамически), а в функции(ях) опроса можно эти кнопки либо последовательно перебирать, либо сразу все, либо по одной на вызов фии, либо вообще сделать одну фю на все кнопки. Все это отлично ложиться на классы в C++, да и вообще на ООП.
И самое главное — опрос не мешает выполнятся остальным частям кода.
Не используйте блокирующий код, пока вы четко не понимаете, что он действительно необходим. И это относится не только к кнопкам или микроконтроллерам.
а твои способы распределять данные или выносить логику начали вызывать сложные баги, и становится все больше костылей.
Я ещё в первой части просил вас дать реальный пример, в котором можно увидеть, почему описанная вами проблема происходит, и на 90% это будет скорее всего из-за неправильной архитектуры.
У нас огромное и сложное SPA с кучей бизнес-логики и ни разу не нужно было городить какие-то отдельные, внешние классы, да ещё и связывать их с компонентами. Если общее (данные, логика) - все лежит в сторе, если компонентное - в компоненте(ах).
Все ещё не понятно, почему вы класс с данными и какой-то логикой называете сервисом. Сервисом чего он является?
Если вам действительно необходим некий общий сервис с реактивностью, почему просто не импортировать его и вызывать его фии для получения или установки каких-то его состояний? Реактивность можно добавить, через computed/watch в самом компоненте, где это необходимо, причём будет чётко видно что за сервис и как вы его используете, без какой либо внутренней магии.
Вобщем, без реального примера понять зачем это все понадобилось конкретно вам - невозможно. Как и понять верность выбора и плюсы вашего решения.
P. S. Зачем используете proxy для readonly? Почему не обычный сеттер?
Общий родитель есть всегда - это рут. Чтобы его не загрязнять, можно то что провайдится, затащить внешним файлом js.
Про отслеживание событий я написал ниже.
А так вы затащили в проект ещё одну зависимость, которую, во-первых, нужно понимать всем, кто работает в проекте, а во-вторых - поддерживать. Вместо того, чтобы использовать сам vue и его парадигмы, которые понятны всем и доступны из коробки.
ИМХО, это пятая нога - вы облегчили одно и усложнили другое.
Но, вообще, чтобы понять что решали, было бы очень неплохо увидеть реальную задачу.
Если договориться о стандарте именования, например, сделать события вида [НазваниеКомпонента]_[Событие]_[ID], где ID - это идентификатор экземпляра компонента, если компонентов такого вида может быть несколько.
После такого соглашения понимать что за компонент райзнул событие очень просто, как и найти подписчиков на него. Можно для дебага перехватывать все события и кидать в консоль и тд.
Я бы не сказал, что это неочевидней provide/inject, а самое главное - никаких внешних зависимостей и парадигм тащить не надо - работает из коробки.
Плюсов масса - если компоненты каким-то образом подписаны на события друг-друга, например когда есть модальный лоадер, а другие компоненты при асинхронке кидают события типа Loader_On/Off, то, достаточно просто подключить компонент лоадера и любой другой компонент, вообще ничего не зная про связь - и они подружатся сами. А если вы не подключили лоадер - никакой ошибки не будет, тк событие будет уходить, но подписчиков у него нет.
Я не очень понял суть задачи — надо расшарить какие-то данные/события между какими-то иерархически несвязанными/связанными компонентами?
Если да, то максимально корректный в парадигме Vue — это provide/inject.
А если с этим не заморачиваться, то (имхо) самый удобный — event-bus на руте (либо внешний через mixin/globals). В нем можно как райзить события-данные, так и события-логику, получают их все подписанные на нужные события компоненты, что очень удобно. Расплата за это только одна — отследить типы событий и где они порождаются и где ловятся — сложно. Но, если именование событий стандартизировать, то ищется в проекте элементарно поиском по названию события.
Не увидел event-bus в статье, кстати — но может быть потому, что неверно задачу понял. Поясните, если не трудно, можно просто простым примером задачи.
Блог, да, но статьи в ленте появляются отдельными, и далеко не все зайдут почитать что-то про вас, кроме того, ваши статьи кочуют между блогами — сегодня, например, это блог TimeWebCloud.
Кстати, сигнал «стоп» на велосипеде — актуальней некуда, говорю вам как человек с опытом катания под 10 лет. И у меня стоит такая фара. Стоп распознается автоматически акселем.
А че не на ПЗУ-шке? Там как раз 8 выводов, анимацию разделить на чанки, генератор гоняет по кругу только один чанк, чанки — это динамические действия типа «поворот направо» или «стоп», в каждом чанке каждый байт — состояние полоски диодов, на ПЗУ на вывод битов прямо прилепить диоды — выходы там мощные достаточно, размер чанка фиксированный и кратен степени 2 — чтобы выбирать было проще.
Но вообще, в каждой такой статье я бы вверху давал дисклеймер — «не надо так делать в 2022», или «я так делаю, потому что хочу и могу, а не потому что это правильно» :)
Ибо данная штука делается на attiny за 70рэ (или на китайском за 15рэ) и 8 адресных диодах WSxxxx, при этом плюсом идет RGB, любые переливы и анимация и у вас еще останется 4 свободных линии из 6 (1-лента диодов, 1-ацп на кнопки выбора режима), по которым можно подключить аксель, например. И все это уложится в платку 10x10мм и жрать будет куда меньше за счет ШИМ.
Вот про решетку — отдельная тема — из чего ее делать и как, 3D врядли подойдет, так как при печати и такой толщине ее поведет. Фрезерование только, ИМХО.
Пример — дисплей 8x40 — вполне достаточно для проекта = 320 диодов, первый лот на али, который нашел: sk6805 300шт = 24$, 100шт = 9.5$
Мало того, они в наличии в JLCPCB и вам их еще и напаяют за копейки и возьмут со своих стоков.
Про SK6805 не знал, уже развел на EASYEDA матрицу, закажу, пожалуй ради интереса, единственный вопрос — как делать решетку с минимальной толщиной для него.
Я правильно понимаю, что ваша организация наняла молодого программиста, не проверив его компетенции и технологии, которыми он владеет, как и его опыт?
Вы поставили перед ним таску, которую он сделал исходя из своих компетенций и технологий, которыми он владеет?
Потом вы попросили его сделать некоторый лоулевел, который ему не дан ибо для него нужен миддл.
Вопрос - а почему вы взяли вместо миддла или сеньора непонятно кого? Потому что он дешев?
Ну и кто тогда должен оправдываться?
Те ваша восточноевропейская эйчарка взяла неизвестно кого, вы его пустили к себе в стэк не проверив, а оправдываться надо только ему?
В ситуации виноваты все, через кого Василий к вам попал, при этом Василий виноват меньше всего - таску, которую ему озвучивали он закрыл, то что делать он не умеет - он честно про это вам сказал, а не стал гуглить и тянуть время - как обычно бывает. Так что далеко не все так однозначно.
P. S. и причём здесь платный NestJS?
Понял, а если blur наложить - шум не уменьшится?
Если кубики - как получаются внешние поверхности как полу-сферы?
Вообще, очень круто было бы увидеть что-то такое же как в этой статье.
Ибо сейчас все юзают шейдеры и не парятся, а вот на чистом си не найти.
А исходники где-то можно посмотреть? Особенно дыма.
Вот и так считаю - куда проще заинклюдить проверенный файл и вообще больше на это время не тратить.
Переиспользование универсального кода как раз и даёт возможность снизить стоимость разработки.
Обычный антидребезг, схем много - простейшая кондер 100nf параллельно кнопке.
О правильности я в конце первого комментария написал - нужно всеми силами избегать блокирующего кода везде, где только можно (не только в микропроцессорах) , и использовать его только тогда, когда это прямо реально нужно и кейсов таких от силы пол-процента наберется.
Задачу можно решить быстро и в лоб, а можно решить хорошо. Блокирующий - это всегда быстро и в лоб, что потом чревато проблемами и переделками.
Потому что это более универсальней и покрывает весь спектр задач, это можно сделать один раз, а потом лишь переиспльзовать будучи на 99% уверенным, что код этот может всегда расширить на бОльшее колво случаев и работать он будет предсказуемо и четко. При этом самого кода при таком подходе будет не сильно больше, нежели у решения в лоб.
Ну, надо начать просто - чем больше, тем лучше будет.
Например, появляется возможность использовать классы как скоп, чтобы не гадить в глобальную область видимости. (можно статический, если не предвидится несколько таких).
Использовать объекты, когда есть что-то повторяющиеся в системе (кнопки, например).
Использовать ссылки, вместо передачи по значению.
Ну и возможность выносить класс или набор классов, как отдельный файл с отдельным функционалом - это прямо киллерфича - глобал не загрязняется, а порождая тип, ну например OLED display( PORTA, PIN1) сразу понятно что куда почему + инициализация, если нужна.
Это вот прямо самое базовое.
Раньше C++ не использовался ввиду того, что давал оверхэд при компиляции для микропррцессоров, сейчас компиляторы его практически не дают - разница может составлять совсем не много около - 0.2-0.5%
И раньше я также писал только на C из-за этого, сейчас куда правильней писать на C++ и иметь все его плюшки - программы получаются проще и гораздо более гибкими.
Но понятно, что при использовании C++, надо и метрологию его использовать, а не процедуры + вкоряченный класс)
При этом может получиться очень интересная штука - программа, написанная на C++ с использованием C++ особенностей получится меньшей по размеру и более быстрой, чем делующая тоже на C. На небольших программах это практически не видно, а вот с увеличением размера начинает ощущаться.
Но — блокирующий опрос кнопок — это очень плохо, особенно, если проект сложный.
Вообще все блокирующее в микроконтроллерах — это всегда плохо, особенно, если их быстродействие не велико.
Гораздо правильней делать это с помощью чего-то похожего на конечный автомат.
И так и делают — одна из самых популярных (но не самых крутых) — это библиотека по работе с кнопками от AlexGyver.
Суть в том, что есть структура (или класс) кнопки, где хранится ее состояние, когда было это по времени (значение таймера отсчета), предыдущее состояние и тд.
И на основе этих данных можно и дабл- и трипл-клики обрабатывать, и удержание и клик+удержание и много чего еще, причем с помощью очень небольших изменений кода.
И для того, чтобы обновить состояние — нужно просто вызвать некую фю, передав туда отсчет времени. И делать это можно где-угодно — хочешь — в таймере, хочешь — по прерыванию, хочешь — в основном цикле. Лишь бы паузы между вызовами были не слишком большие — иначе реакция будет подтормаживать. А так — один раз тайминги настроил и забыл.
Это удобней и в разы универсальней.
При этом таких кнопок сколько угодно можно породить (хоть динамически), а в функции(ях) опроса можно эти кнопки либо последовательно перебирать, либо сразу все, либо по одной на вызов фии, либо вообще сделать одну фю на все кнопки. Все это отлично ложиться на классы в C++, да и вообще на ООП.
И самое главное — опрос не мешает выполнятся остальным частям кода.
Не используйте блокирующий код, пока вы четко не понимаете, что он действительно необходим. И это относится не только к кнопкам или микроконтроллерам.
Я ещё в первой части просил вас дать реальный пример, в котором можно увидеть, почему описанная вами проблема происходит, и на 90% это будет скорее всего из-за неправильной архитектуры.
У нас огромное и сложное SPA с кучей бизнес-логики и ни разу не нужно было городить какие-то отдельные, внешние классы, да ещё и связывать их с компонентами. Если общее (данные, логика) - все лежит в сторе, если компонентное - в компоненте(ах).
Все ещё не понятно, почему вы класс с данными и какой-то логикой называете сервисом. Сервисом чего он является?
Если вам действительно необходим некий общий сервис с реактивностью, почему просто не импортировать его и вызывать его фии для получения или установки каких-то его состояний? Реактивность можно добавить, через computed/watch в самом компоненте, где это необходимо, причём будет чётко видно что за сервис и как вы его используете, без какой либо внутренней магии.
Вобщем, без реального примера понять зачем это все понадобилось конкретно вам - невозможно. Как и понять верность выбора и плюсы вашего решения.
P. S. Зачем используете proxy для readonly? Почему не обычный сеттер?
Но смешивать бы точно не стал.
Из документации по VUE.
VUE Composition API появилась только во VUE3.
Общий родитель есть всегда - это рут. Чтобы его не загрязнять, можно то что провайдится, затащить внешним файлом js.
Про отслеживание событий я написал ниже.
А так вы затащили в проект ещё одну зависимость, которую, во-первых, нужно понимать всем, кто работает в проекте, а во-вторых - поддерживать. Вместо того, чтобы использовать сам vue и его парадигмы, которые понятны всем и доступны из коробки.
ИМХО, это пятая нога - вы облегчили одно и усложнили другое.
Но, вообще, чтобы понять что решали, было бы очень неплохо увидеть реальную задачу.
Чем event-bus меганеочевиден?
Если договориться о стандарте именования, например, сделать события вида [НазваниеКомпонента]_[Событие]_[ID], где ID - это идентификатор экземпляра компонента, если компонентов такого вида может быть несколько.
После такого соглашения понимать что за компонент райзнул событие очень просто, как и найти подписчиков на него. Можно для дебага перехватывать все события и кидать в консоль и тд.
Я бы не сказал, что это неочевидней provide/inject, а самое главное - никаких внешних зависимостей и парадигм тащить не надо - работает из коробки.
Плюсов масса - если компоненты каким-то образом подписаны на события друг-друга, например когда есть модальный лоадер, а другие компоненты при асинхронке кидают события типа Loader_On/Off, то, достаточно просто подключить компонент лоадера и любой другой компонент, вообще ничего не зная про связь - и они подружатся сами. А если вы не подключили лоадер - никакой ошибки не будет, тк событие будет уходить, но подписчиков у него нет.
Если да, то максимально корректный в парадигме Vue — это provide/inject.
А если с этим не заморачиваться, то (имхо) самый удобный — event-bus на руте (либо внешний через mixin/globals). В нем можно как райзить события-данные, так и события-логику, получают их все подписанные на нужные события компоненты, что очень удобно. Расплата за это только одна — отследить типы событий и где они порождаются и где ловятся — сложно. Но, если именование событий стандартизировать, то ищется в проекте элементарно поиском по названию события.
Не увидел event-bus в статье, кстати — но может быть потому, что неверно задачу понял. Поясните, если не трудно, можно просто простым примером задачи.
Но это был просто совет и ничего более.
Но вообще, в каждой такой статье я бы вверху давал дисклеймер — «не надо так делать в 2022», или «я так делаю, потому что хочу и могу, а не потому что это правильно» :)
Ибо данная штука делается на attiny за 70рэ (или на китайском за 15рэ) и 8 адресных диодах WSxxxx, при этом плюсом идет RGB, любые переливы и анимация и у вас еще останется 4 свободных линии из 6 (1-лента диодов, 1-ацп на кнопки выбора режима), по которым можно подключить аксель, например. И все это уложится в платку 10x10мм и жрать будет куда меньше за счет ШИМ.
Пример — дисплей 8x40 — вполне достаточно для проекта = 320 диодов, первый лот на али, который нашел: sk6805 300шт = 24$, 100шт = 9.5$
Мало того, они в наличии в JLCPCB и вам их еще и напаяют за копейки и возьмут со своих стоков.
Про SK6805 не знал, уже развел на EASYEDA матрицу, закажу, пожалуй ради интереса, единственный вопрос — как делать решетку с минимальной толщиной для него.