Есть ещё один очень популярный язык программирование в котором всё время приходится учитывать троичную логику (и даже в каком-то смысле четверичную) — это JavaScript со своими undefined и null
Скрытый текст
var a = {};
console.log(a.b); // undefined
console.log(Object.keys(a)); // []
a.b = undefined;
console.log(a.b); // undefined
console.log(Object.keys(a)); // ["b"]
Забавно, в свое время самостоятельно дошел до идеи «Closure Table», а это оказывается уже известный паттерн )
Могу лишь добавить, что если данных в основной таблице с деревом не очень много, а возиться с обновлением «Closure Table» не охота, то в принципе, можно обойтись и «view» c рекурсивной CTE, позже заменив её на реальную таблицу (в случае проблем с производительностью).
Пример CTE
;WITH CTE_Recursive AS (
SELECT
Id,
ParentId
FROM dbo.TreeData
UNION ALL
SELECT
[PREVIOUS].Id,
[CURRENT].ParentId
FROM dbo.TreeData
[CURRENT]
INNER JOIN CTE_Recursive
[PREVIOUS] ON
[PREVIOUS].ParentId = [CURRENT].Id
)
,CTE_TreeRelation AS
(
SELECT
Id,
ParentId
FROM CTE_Recursive
UNION ALL
SELECT
Id, Id as ParentId
FROM dbo.TreeData
)
SELECT * FROM CTE_TreeRelation
Хм... а сталкивался на практике с прямо противоположной ситуацией, когда JSON выпиливался и внедрялся EAV как раз из-за проблем с производительностью - с EAV всё стало в тысячи раз быстрее (в буквальном смысле).
Мне кажется, что данные, в предложенной вами структуре таблиц, будет сложнее обновлять т.к. всегда придется работать с двумя таблицами.
filter без вложенных селектов
Идея в том, что фильтр приходит "извне", где не знают о структуре хранения данных, и предикат по полю "списку" (например [Protocol] IN ('4G', '5G')) может быть вложен внутрь сложного булевского выражения. Замена такого предиката на EXISTS(SELECT ...) позволит сохранить логику исходного фильтра.
Как при этом сделать сквозную сортировку и пагинацию, если фильтрация идет одновременно по нескольким полям и фильтр может включать любые логические операции (как в примере из статьи)?
Нормально с JSON могут работать далеко не все SQL базы данных, и не понятно, что с производительностью (если делать индексы на JSON, то теряется динамичность).
Для .Net в свое время создал SqExpress. Работает с MS SQL, Postgresql и MySql. Заточен в первую очередь на T-SQL, но для остальных диалектов создает полифилы некоторых возможностей (например MERGE).
Ещё блок finally в C# можно пропустить вообще без каких-либо исключений, достаточно намудрить с асинхронной стейт машиной. Когда-то приводил пример того, как это можно сделать.
В основном для удобства. Не надо прокидывать порты (8 для Moonlight и 1 для Wake Up On LAN) и есть доступ к настройкам роутера. Кроме того, тамошний провайдер не блокирует официально заблокированные в РФ сайты, что весьма удобно, поскольку подключившись к домашнему роутеру через VPN, можно из любой точки легко попасть на заблокированные сайты.
Спасибо за статьи!
Поделюсь своим конфигом стриминга:
1) На одной квартире стоит игровой ноутбук с карточкой NVIDIA.
2) Ноутбук подключен к роутеру, который может поднимать OPEN VPN (есть белый IP)
3) На смартфоне стоит Moonlight и Open VPN клиент.
4) Когда я хочу поиграть, НЕ находясь в квартире с ноутбуком, я подключаю VPN, бужу компьютер через “Wake up on LAN” и запускаю стриминг через Moonlight.
5) На телефоне играть не всегда удобно. т. к. меленький экран, но на другой квартире стоит большой телевизор, к которому я и подключил свой смартфон (Samsung Note 10+) используя USB Hub
Как всё это выглядит можно посмотреть на картинке:
К плюсам C# я бы отнес тот факт, что и язык, и платформу развивает одна компания, и как следствие у C# гораздо больше возможностей для развития, поскольку в случае необходимости можно и стандартную библиотеку расширить (например, Task, ValueTuple и т.д.) и рантайм поправить (Generics, dynamic)
“Вырождающееся человечество” (которого сейчас 7миллиардов) стало зависеть от технологий с того момента, как стало осколками камней стало разделывать туши животных, а после начала приготовления пищи на огне, изменения в нашем строении закрепили эту зависимость навсегда.
Это я к тому, что при наличии советующих технологий, ранее негативные признаки переходят в статус нейтральных.
Преимущество перед RxJ здесь в том, что тут гораздо меньше сущностей и как результат — это проще освоить, и по опыту – проще использовать в каких-то базовых сценариях, которые и составляют 90% всех случаев. Хотя может это именно у меня не заладилось с rxJs и всё время какой-то "write only" код выходит.
На самом деле создавать, альтернативу rxJs планов не было, а основным мотивом к созданию этой библиотеки был поиск простого способа реакции на изменения входных параметров компонента так, чтобы поведение компонента всегда им соответствовало например:
Здесь greeting=f(userName, template), и приветствие надо переделывать каждый раз, когда меняется один или несколько входных параметров.
Когда количество параметров растет, то такие зависимости ускользают из вида и получаются баги.
Конечно, можно было бы и rxJs здесь использовать, но это бы неоправданно усложнило код.
По поводу OnPush, явный changeDetection, нужен только если в компоненте есть асинхронное поведение, в синхронных компонентах все будет работать и с OnPush без явного detectChanges если включить immediateEvaluation.
Я так и не придумал способа того, как можно было бы получить доступ к changeDetector из библиотеки, что конечно бы упростило ситуацию.
Зато change detection вообще можно теперь отключить (.detach()) и всегда явно детектить изменения.
Победить эффект "зловещий долины" у нейронок пока не выходит. Чувствуется, что что-то с этими картинками не так.
Могу лишь добавить, что если данных в основной таблице с деревом не очень много, а возиться с обновлением «Closure Table» не охота, то в принципе, можно обойтись и «view» c рекурсивной CTE, позже заменив её на реальную таблицу (в случае проблем с производительностью).
Хм... а сталкивался на практике с прямо противоположной ситуацией, когда JSON выпиливался и внедрялся EAV как раз из-за проблем с производительностью - с EAV всё стало в тысячи раз быстрее (в буквальном смысле).
Мне кажется, что данные, в предложенной вами структуре таблиц, будет сложнее обновлять т.к. всегда придется работать с двумя таблицами.
Идея в том, что фильтр приходит "извне", где не знают о структуре хранения данных, и предикат по полю "списку" (например [Protocol] IN ('4G', '5G')) может быть вложен внутрь сложного булевского выражения. Замена такого предиката на EXISTS(SELECT ...) позволит сохранить логику исходного фильтра.
Как при этом сделать сквозную сортировку и пагинацию, если фильтрация идет одновременно по нескольким полям и фильтр может включать любые логические операции (как в примере из статьи)?
Нормально с JSON могут работать далеко не все SQL базы данных, и не понятно, что с производительностью (если делать индексы на JSON, то теряется динамичность).
Можно просто привязать атрибуты к категории товара. Это, собственно, и сделано в демонстрационном приложении SqGoods:
Спасибо! Поправил. Это сработала авто-замена. Должно быть " 05/29/2022, 2022–05–22, 29.05.2022 " (MM/dd/yyyy, yyyy-MM-dd, dd.MM.yyyy)
Для .Net в свое время создал SqExpress. Работает с MS SQL, Postgresql и MySql. Заточен в первую очередь на T-SQL, но для остальных диалектов создает полифилы некоторых возможностей (например MERGE).
Ещё блок finally в C# можно пропустить вообще без каких-либо исключений, достаточно намудрить с асинхронной стейт машиной. Когда-то приводил пример того, как это можно сделать.
В Option/Maybe работа цепочки вызовов (при обнаружении ошибки) как раз прерывается и происходит ранний выход.
В основном для удобства. Не надо прокидывать порты (8 для Moonlight и 1 для Wake Up On LAN) и есть доступ к настройкам роутера. Кроме того, тамошний провайдер не блокирует официально заблокированные в РФ сайты, что весьма удобно, поскольку подключившись к домашнему роутеру через VPN, можно из любой точки легко попасть на заблокированные сайты.
Спасибо за статьи!
Поделюсь своим конфигом стриминга:
1) На одной квартире стоит игровой ноутбук с карточкой NVIDIA.
2) Ноутбук подключен к роутеру, который может поднимать OPEN VPN (есть белый IP)
3) На смартфоне стоит Moonlight и Open VPN клиент.
4) Когда я хочу поиграть, НЕ находясь в квартире с ноутбуком, я подключаю VPN, бужу компьютер через “Wake up on LAN” и запускаю стриминг через Moonlight.
5) На телефоне играть не всегда удобно. т. к. меленький экран, но на другой квартире стоит большой телевизор, к которому я и подключил свой смартфон (Samsung Note 10+) используя USB Hub
Как всё это выглядит можно посмотреть на картинке:
К плюсам C# я бы отнес тот факт, что и язык, и платформу развивает одна компания, и как следствие у C# гораздо больше возможностей для развития, поскольку в случае необходимости можно и стандартную библиотеку расширить (например, Task, ValueTuple и т.д.) и рантайм поправить (Generics, dynamic)
“Вырождающееся человечество” (которого сейчас 7миллиардов) стало зависеть от технологий с того момента, как стало осколками камней стало разделывать туши животных, а после начала приготовления пищи на огне, изменения в нашем строении закрепили эту зависимость навсегда.
Это я к тому, что при наличии советующих технологий, ранее негативные признаки переходят в статус нейтральных.
Можно заморочиться и сделать криптографическую временную метку.
Я обычно "скриптингом" на C# занимаюсь через Powershell. Очень удобно, когда нужен простенький GUI, например:
Преимущество перед RxJ здесь в том, что тут гораздо меньше сущностей и как результат — это проще освоить, и по опыту – проще использовать в каких-то базовых сценариях, которые и составляют 90% всех случаев. Хотя может это именно у меня не заладилось с rxJs и всё время какой-то "write only" код выходит.
На самом деле создавать, альтернативу rxJs планов не было, а основным мотивом к созданию этой библиотеки был поиск простого способа реакции на изменения входных параметров компонента так, чтобы поведение компонента всегда им соответствовало например:
Здесь
greeting=f(userName, template)
, и приветствие надо переделывать каждый раз, когда меняется один или несколько входных параметров.Когда количество параметров растет, то такие зависимости ускользают из вида и получаются баги.
Конечно, можно было бы и rxJs здесь использовать, но это бы неоправданно усложнило код.
По поводу OnPush, явный changeDetection, нужен только если в компоненте есть асинхронное поведение, в синхронных компонентах все будет работать и с OnPush без явного detectChanges если включить immediateEvaluation.
Я так и не придумал способа того, как можно было бы получить доступ к changeDetector из библиотеки, что конечно бы упростило ситуацию.
Зато change detection вообще можно теперь отключить (.detach()) и всегда явно детектить изменения.
Значок "Тролль" — это тоже, своего рода, достижение, требующие не самых малых усилий.