То есть, доступ к данным имеет их владелец или пользователь техподдержки. Получается это тоже бизнес правило, которое также можно закладывать в условия.
Кроме того этот случай решается «супер-пользователем»
На мой взгляд, "супер-пользователь" это серьезный удар по безопасности.
В своей практике я не припомню случаев необходимости в таких пользователях.
Персональный пользователь с правами администратора – Да
Временный пользователь для функциональных тестов – Да
Пользователь с ограниченными правами для ботов – Да
Но не супер-пользователь.
Да, но если эти данные вообще не предназначены для данного пользователя зачем ему вообще иметь возможность их видеть?
Моё предложение в том, что бы использовать базовую спецификацию проверяющую права и расширять её при необходимости. В этом случае вы в явном виде запрашиваете данные конкретного пользователя. То есть, это не спецификация проверчющая права доступа, а спецификация возвращающая пользовательские данные, которая инкапсулирует проверку прав доступа. Это немного другой взгляд.
Конечно можно применять фильтры и на глобальном уровне в неявном виде. Иногда я тоже так делаю, но лично я все равно придерживаюсь мнения, что явное лучше неявного.
Короткий ответ — отлично. Если хотите длинный ответ, то вот он.
Вообще, ограничения доступа которые вы описали в статье, это больше похоже на бизнесовые правила и им место скорее в спецификациях, а не на глобальном уровне. Применяя их на глобальном уровне вы можете столкнутся с ситуацией когда вам нужно получить данные не применяя эти правила.
А что бы не забывать применить спецификации, давайте им понятные названия и объединяйте их в большие. Например, в вашем случае, можно создать спецификации ClientOrganizationsSpec и StaffingAgencyOrganizationsSpec и объединить в общую UserOrganizationsSpec.
Остальные правила которые вы описываете в Where, так же можно описать через спецификации и в результате в контроллере вы будете передавать 1-3 спецификации.
На мой взгляд, проще ориентироваться в наборе спецификаций имеющих четкое название и четкое назначение чем в куче условий в Where. Тем более что со спецификациями вы уже имели дело. Кстати говоря, как ваше впечатление от них спустя год?
Когда пользователь перемещается между страницами его явно интересуют не последние записи
И вернувшись на первую страницу он не увидит новых записей.
на момент запроса тут было сообщение, но к тому моменту как вы до него добрались оно уже было удалено, поэтому мы не можем показать вам его содержимое
Вот вы не видите проблемы в НЛО, но видите проблему в дублях. Другие же разработчики и пользователи не видят проблемы в дублях, а вот НЛО раздражает.
Снепшот создаётся клиентом целенаправленно, чтобы с ним потом работать независимо от изменений в исходных данных.
Из вашей статьи я делаю вывод, что вы запрашиваете с сервера список id записей соответствующих поисковому запросу и кешируете результат на клиенте. Далее, реализуете пагинацию на клиенте по списку закешированных записей.
Вы список закешированных записей называете снепшотом, но механика явно кеширующая.
Так что, нет. В вашем случае кеш и снепшот это синонимы.
А ограничение на число элементов есть всегда
И снова нет. Ограничений почти никогда нет. Вам уже привели 2 примера и можно привести ещё миллион.
Да, некоторые искусственно ограничивают число элементом в силу своих каких-то технических ограничений и Google Search тому яркий пример. Выдавать в поисковой выдаче результаты до которых пользователей не долистает для них скорей всего экономически не выгодно. А вот для каталогов (1, 2, 3) это не корректно. Тоже с архивом новостей. А обрезание комментариев на форуме или сообщений в личке или списка конкурсантов в онлайн конкурсе или ленты в соцсетях это вообще нарушение целостности данных и пользователи вас за это по головке не погладят.
Подитожу. Как я, так и другие комментаторы я полагаю, критикуем не сам ваш метод, давно известный, но не слишком популярный. Мы критикуем ваше отношение к нему. Вы преподносить классическую пагинацию как антипаттерн, а ваш метод как серебряную пулю и универсальное решение хотя это не так.
Но это конечно ваше право иметь собственное мнение и не принимать истину.
При удалении записей которые есть в снепшоте вы получите НЛО или дырки. Если удаленных материалов много, то вы можете получить вообще дырку от бублика пустую страницу.
Вы ограничиваете результат до 1000 записей, но это не всегда корректно. Это корректно для поисковой выдаче, но не корректно для каталогов и архивов. Вспоминаем Бездну.
Реализация без паджинации, но с разделением поиска и выборки решает их все. Было бы не плохо предлагать альтернативы, которые как минимум не хуже.
Serious? Ваше решение решает только проблему дублей на странице, но оно не решает остальные поставленные вами проблемы, о чем вам уже не однократно написали в комментариях.
Относительная паджинация, предложенная maximw, решает как проблему дублей, так и проблему удаленных записей.
Операция – это всего лишь то, что находится во временном интервале: «с» и «по». Если точность наших измерений не позволяет различить «с» и «по», и они сливаются, то мы получаем событие с датой «когда».
Почему операция вдруг превращается в событие? Откуда вообще здесь взялись события если это "продолжительная операция" (с/по) и "одномоментная операция" (когда)?
Трансформатор для эксплуатации и трансформатор для учета материального учета – разные объекты. [...] То есть, один и тот же 4-Д объем может трактоваться как физический трансформатор или как функциональный трансформатор.
Таки разные или одинаковые?
Я бы сказал, что это разные объекты в разных Bounded Context и соответственно с разными 4-Д объемами.
Изменение – это сценарий, а не операция и не событие.
Разве? Мне всегда казалось, что — сценарий выполняет операциюизменения которая триггерит событие.
Но, уточняя модель, мы все равно наткнемся на событие, в котором свет и темнота существуют вместе.
Поясните пожалуйста, что вы имеете в виду под событием в данном случае?
Если это событие которое триггерится на изменение состояния, то я не вижу проблем в сосуществовании света и тени (красный и белый) в одном событии. Хотя в случае если состояний ограниченное количество, как в случае со светом, лучше подойдут типизированные события в духе: в помещении А включили свет.
Так я и не говорю "как взломать соседа". Я говорю, что последствия взлома сосед не проблема архитектуры SSL, а проблема самого взлома соседа.
Уже много раз встречал подобные заявления и каждый раз умиляюсь.
Почему-то все забывают, что если Почтальон взломает Бориса, то Почтальон станет Борисом со всеми вытекающими последствиями. И SSL здесь вообще не при делах.
каким-то образом (социальная инженерия, взлом с проникновением) прописать свой фейковый корневой центр сертификации в реестр Бориса.
В случае взлома, Почтальон уже имеет полный контроль над устройством и ему проще просто установить следящее ПО, майнинг Биткоино и тд, чем развлекаться с сертификатами. Он уже может больше чем просто слушать и изменять трафик.
Та же ситуация с социальной инженерией. Гараздо проще уговорить пользователя два раза кликнуть на exe, чем лезть в сертификационный центр. С этой задачей не каждый продвинутый пользователь справится, что уж говорить о бугалтерушечках.
Я говорю как раз о фактической безопасности сайта. Для пользователей будет все очевидно:
Красный — не безопасно. Не безопасно соединение и как следствие сам сайт.
Нет цвета — возможно безопасно, а может и нет. Соединение безопасно, а вот что с сайтом не известно.
Зелёный — безопасно. Зелёное только для EV сертификатов которые выдаются только юрлиццам и с кучей бумажной волокиты. Сайты под EV достаточно серьезно заботятся о своей безопасности и безопасности своих пользователей. Взломать конечно могут и сайт под EV сертификатом, но вероятность этого ниже. И если не доверять сайтам под EV, то вообще никому доверять нельзя.
Вот мы и получаем, что обозначение будет значительно лучше соответствовать фактической безопасности сайта. И для юзеров это будет нагляднее.
Хотя, пожалуй сайты под EV лучше все же сделать желтыми ибо безопасность не 100%
Я с вами полностью согласен, что "безопасный сайт" и "безопасное соединение с сайтом" это разные понятия. Я вам о другом говорю.
Посмотрите скрин в начале статьи с пометкой "В будущем". Скоро не будут писать ни каких "Защищено". Будут писать только "Не безопасно", что уже намного ближе к правде.
Если соединение с сайтом не защищено, то и сайт не защищен и пользователь не защищен. А если соединение с сайтом защищено, то нет гарантий, что сайт и пользователь защищены и значков говорящих об этом или обратном больше не будет.
Акцент меняется. Раньше было HTTPS это хорошо, а HTTP ну такое, а теперь будет HTTPS ну такое, а HTTP вообще ад. Если раньше Chrome говорил, что сайту с HTTPS можно доверять, то скоро этого не будет. И только избранные, с сертификатом EV, смогут говорить, что им можно доверять.
То есть, по факту, скоро обозначение безопасности сайта в Chrome будет на много ближе фактической безопасности сайта.
Получается как раз наоборот. Если на сайте есть HTTPS, то просто не выводится значек Not secure.
Если раньше Chrome говорил, что сайт с HTTPS безопасный и ему можно полностью доверять, то теперь этого не будет.
Как взаимодействуют друг с другом родительский и дочерние контексты, а так же дочерние друг с другом?
Моя практика показывает, что иерархическая структура контекстов хорошо работает когда есть множество небольших контекстов ни как не связанных между собой и другими контекстами, но имеющие общий контекст. Общий контекст, в этом случае, может быть пустым. Своего рода группа контекстов.
Порой, общий/родительский контекст имеет свою логику и дочерние контексты в этом случае имеют к нему доступ (дерево. Все связи направлены в низ, к основанию). Это может делаться для вынесения одинаковой бизнес логики, чтоб не дублировать её в каждом контексте. Не смотря на наличие схожих бизнес процессов, это все ещё разные контексты, которые ни как нельзя объединять в один большой контекст.
Моя практика показывает, что дублирование бизнес процессов в разных контекстах не самое лучшее решение, даже если это дублирование только формальное, на бумаге.
А вот выделение субконтекстов из основного контекста для их изоляции, как в примере с страницами и комментариями, дело довольно спорное, как вы уже подметили.
Если говорим о чём-то типа Хабра, то интеграция нужна.
И опять вы выносить домен в уровень представления. Сначало говорили, что аннотация в домене это протечка инфраструктуры, а теперь сами же вытаскиваете домен в представление.
А если серьезно, то посмотрите хотя бы на эту страницу. Только ли статья на ней и только ли комментарии? На странице есть как минимум сущности из контекста аунтификации, что значит, что сосуществование разных контекстов в одном запросе на уровне представления это норма. И к API это тоже относится.
Как минимум это заставит создавать отдельный модуль интгерации контекстов и страниц, не позволит выбирать комментарии со страницами одним SQL-запросом или хранить их в рамках одного документа в базах типа MongoDB.
Зачем модули интеграции если их не нужно интегрировать?
Один SQL запрос так и так нельзя использовать для извлечения одной страницы и всех её комментариев.
Документ в монге это конечно аргумент, но если использовать монгу как read хранилище, то можно. Структуру read хранилища определяет уровень представления, а не домен.
Я просто пытаюсь понять, какие плюсы в разделении контекстов страниц и комментариев.
Кажется я об этом уже говорил. Критерием для разделения контекстов их размер.
Учитывая сколько мы всего описали только для учёта просмотра страниц, не сложно прикинуть, что контекст получается ой как не маленький. Отсюда и вывод, что нужно делить контекст на контексты поменьше.
Надеюсь не нужно объяснять чем плохи больше контексты?
Я вам говорю о базовых принципах не однократно описанные множеством известных специалистов. Вы можете пренебрегать этими принципами. Это ваше право.
А как на фронте понять что нужно обновлять счётчик?..
Я разве говорил, что нужно понимать это на фронте? Нет. Я говорил, что вы можете отправлять на сервер сообщения о просмотре, по аналогии с GA и YM, а на сервере уже применять просмотры в соответствии с вашей бизнес логикой.
У Вас уже логика прямо на фронте получилась.
Нет. Хотя она там может быть. Вспоминаем SPA.
А на беке получается паутина из обработчиков событий. При этом это один use case.
Паутины нет. События только так где они действительно нужны.
Вы говорити, что Use case один, а так ли это?
Получить пост из хранилища;
Пометить пост как просмотренный;
Поставить бейдж популярному посту;
Обновить блок популярных постов;
Обновить топ на главной;
Обновить статистику просмотров поста у автора в профиле;
Обновить статистику просмотров в админке;
...
Вы собираетесь запихивать все это в один Use case, в один метод, в один GET запрос и пусть весь мир подождёт)))
То есть, доступ к данным имеет их владелец или пользователь техподдержки. Получается это тоже бизнес правило, которое также можно закладывать в условия.
На мой взгляд, "супер-пользователь" это серьезный удар по безопасности.
В своей практике я не припомню случаев необходимости в таких пользователях.
Но не супер-пользователь.
Моё предложение в том, что бы использовать базовую спецификацию проверяющую права и расширять её при необходимости. В этом случае вы в явном виде запрашиваете данные конкретного пользователя. То есть, это не спецификация проверчющая права доступа, а спецификация возвращающая пользовательские данные, которая инкапсулирует проверку прав доступа. Это немного другой взгляд.
Конечно можно применять фильтры и на глобальном уровне в неявном виде. Иногда я тоже так делаю, но лично я все равно придерживаюсь мнения, что явное лучше неявного.
Спасибо за доклад. Было интересно послушать.
Вообще, ограничения доступа которые вы описали в статье, это больше похоже на бизнесовые правила и им место скорее в спецификациях, а не на глобальном уровне. Применяя их на глобальном уровне вы можете столкнутся с ситуацией когда вам нужно получить данные не применяя эти правила.
А что бы не забывать применить спецификации, давайте им понятные названия и объединяйте их в большие. Например, в вашем случае, можно создать спецификации
ClientOrganizationsSpec
иStaffingAgencyOrganizationsSpec
и объединить в общуюUserOrganizationsSpec
.Остальные правила которые вы описываете в
Where
, так же можно описать через спецификации и в результате в контроллере вы будете передавать 1-3 спецификации.На мой взгляд, проще ориентироваться в наборе спецификаций имеющих четкое название и четкое назначение чем в куче условий в
Where
. Тем более что со спецификациями вы уже имели дело. Кстати говоря, как ваше впечатление от них спустя год?Я в подобных случаях использую спецификации
И вернувшись на первую страницу он не увидит новых записей.
Вот вы не видите проблемы в НЛО, но видите проблему в дублях. Другие же разработчики и пользователи не видят проблемы в дублях, а вот НЛО раздражает.
Из вашей статьи я делаю вывод, что вы запрашиваете с сервера список id записей соответствующих поисковому запросу и кешируете результат на клиенте. Далее, реализуете пагинацию на клиенте по списку закешированных записей.
Вы список закешированных записей называете снепшотом, но механика явно кеширующая.
Так что, нет. В вашем случае кеш и снепшот это синонимы.
И снова нет. Ограничений почти никогда нет. Вам уже привели 2 примера и можно привести ещё миллион.
Да, некоторые искусственно ограничивают число элементом в силу своих каких-то технических ограничений и Google Search тому яркий пример. Выдавать в поисковой выдаче результаты до которых пользователей не долистает для них скорей всего экономически не выгодно. А вот для каталогов (1, 2, 3) это не корректно. Тоже с архивом новостей. А обрезание комментариев на форуме или сообщений в личке или списка конкурсантов в онлайн конкурсе или ленты в соцсетях это вообще нарушение целостности данных и пользователи вас за это по головке не погладят.
Подитожу. Как я, так и другие комментаторы я полагаю, критикуем не сам ваш метод, давно известный, но не слишком популярный. Мы критикуем ваше отношение к нему. Вы преподносить классическую пагинацию как антипаттерн, а ваш метод как серебряную пулю и универсальное решение хотя это не так.
Но это конечно ваше право иметь собственное мнение и не принимать истину.
Это такой тонкий троллинг?
Вам же уже написали:
дырку от бубликапустую страницу.Serious? Ваше решение решает только проблему дублей на странице, но оно не решает остальные поставленные вами проблемы, о чем вам уже не однократно написали в комментариях.
Относительная паджинация, предложенная maximw, решает как проблему дублей, так и проблему удаленных записей.
Почему операция вдруг превращается в событие? Откуда вообще здесь взялись события если это "продолжительная операция" (с/по) и "одномоментная операция" (когда)?
Таки разные или одинаковые?
Я бы сказал, что это разные объекты в разных Bounded Context и соответственно с разными 4-Д объемами.
Разве? Мне всегда казалось, что — сценарий выполняет операцию изменения которая триггерит событие.
Поясните пожалуйста, что вы имеете в виду под событием в данном случае?
Если это событие которое триггерится на изменение состояния, то я не вижу проблем в сосуществовании света и тени (красный и белый) в одном событии. Хотя в случае если состояний ограниченное количество, как в случае со светом, лучше подойдут типизированные события в духе: в помещении А включили свет.
Так я и не говорю "как взломать соседа". Я говорю, что последствия взлома сосед не проблема архитектуры SSL, а проблема самого взлома соседа.
Уже много раз встречал подобные заявления и каждый раз умиляюсь.
Почему-то все забывают, что если Почтальон взломает Бориса, то Почтальон станет Борисом со всеми вытекающими последствиями. И SSL здесь вообще не при делах.
Как я люблю такие заявления:
В случае взлома, Почтальон уже имеет полный контроль над устройством и ему проще просто установить следящее ПО, майнинг Биткоино и тд, чем развлекаться с сертификатами. Он уже может больше чем просто слушать и изменять трафик.
Та же ситуация с социальной инженерией. Гараздо проще уговорить пользователя два раза кликнуть на exe, чем лезть в сертификационный центр. С этой задачей не каждый продвинутый пользователь справится, что уж говорить о бугалтерушечках.
Я говорю как раз о фактической безопасности сайта. Для пользователей будет все очевидно:
Вот мы и получаем, что обозначение будет значительно лучше соответствовать фактической безопасности сайта. И для юзеров это будет нагляднее.
Хотя, пожалуй сайты под EV лучше все же сделать желтыми ибо безопасность не 100%
Я с вами полностью согласен, что "безопасный сайт" и "безопасное соединение с сайтом" это разные понятия. Я вам о другом говорю.
Посмотрите скрин в начале статьи с пометкой "В будущем". Скоро не будут писать ни каких "Защищено". Будут писать только "Не безопасно", что уже намного ближе к правде.
Если соединение с сайтом не защищено, то и сайт не защищен и пользователь не защищен. А если соединение с сайтом защищено, то нет гарантий, что сайт и пользователь защищены и значков говорящих об этом или обратном больше не будет.
Акцент меняется. Раньше было HTTPS это хорошо, а HTTP ну такое, а теперь будет HTTPS ну такое, а HTTP вообще ад. Если раньше Chrome говорил, что сайту с HTTPS можно доверять, то скоро этого не будет. И только избранные, с сертификатом EV, смогут говорить, что им можно доверять.
То есть, по факту, скоро обозначение безопасности сайта в Chrome будет на много ближе фактической безопасности сайта.
Получается как раз наоборот. Если на сайте есть HTTPS, то просто не выводится значек Not secure.
Если раньше Chrome говорил, что сайт с HTTPS безопасный и ему можно полностью доверять, то теперь этого не будет.
Моя практика показывает, что иерархическая структура контекстов хорошо работает когда есть множество небольших контекстов ни как не связанных между собой и другими контекстами, но имеющие общий контекст. Общий контекст, в этом случае, может быть пустым. Своего рода группа контекстов.
Порой, общий/родительский контекст имеет свою логику и дочерние контексты в этом случае имеют к нему доступ (дерево. Все связи направлены в низ, к основанию). Это может делаться для вынесения одинаковой бизнес логики, чтоб не дублировать её в каждом контексте. Не смотря на наличие схожих бизнес процессов, это все ещё разные контексты, которые ни как нельзя объединять в один большой контекст.
Моя практика показывает, что дублирование бизнес процессов в разных контекстах не самое лучшее решение, даже если это дублирование только формальное, на бумаге.
А вот выделение субконтекстов из основного контекста для их изоляции, как в примере с страницами и комментариями, дело довольно спорное, как вы уже подметили.
Это как посмотреть на вопрос.
Если контекст единый, то при комментарии, в самом комментарии, мы должны убедиться, что статья опубликована и в противном случае выбросить исключение.
Если же контексты раздельные, то не опубликованных статей в контексте комментариев просто не будет существовать.
Вот вам и преимущество разделения.
И опять вы выносить домен в уровень представления. Сначало говорили, что аннотация в домене это протечка инфраструктуры, а теперь сами же вытаскиваете домен в представление.
А если серьезно, то посмотрите хотя бы на эту страницу. Только ли статья на ней и только ли комментарии? На странице есть как минимум сущности из контекста аунтификации, что значит, что сосуществование разных контекстов в одном запросе на уровне представления это норма. И к API это тоже относится.
Об том и спич
Кажется я об этом уже говорил. Критерием для разделения контекстов их размер.
Учитывая сколько мы всего описали только для учёта просмотра страниц, не сложно прикинуть, что контекст получается ой как не маленький. Отсюда и вывод, что нужно делить контекст на контексты поменьше.
Надеюсь не нужно объяснять чем плохи больше контексты?
Я вам говорю о базовых принципах не однократно описанные множеством известных специалистов. Вы можете пренебрегать этими принципами. Это ваше право.
Я разве говорил, что нужно понимать это на фронте? Нет. Я говорил, что вы можете отправлять на сервер сообщения о просмотре, по аналогии с GA и YM, а на сервере уже применять просмотры в соответствии с вашей бизнес логикой.
Нет. Хотя она там может быть. Вспоминаем SPA.
Паутины нет. События только так где они действительно нужны.
Вы говорити, что Use case один, а так ли это?
Вы собираетесь запихивать все это в один Use case, в один метод, в один GET запрос и пусть весь мир подождёт)))
Нет. Событие это сообщение возникающие в процессе выполнения программы. Само по себе событие ничего не меняет.