Обнаружилась интересная штука с типизированными свойствами
If a typed property does not have a default value, no implicit null default value is implied (even if the property is nullable). Instead, the property is considered to be uninitialized. Reads from uninitialized properties will generate a TypeError (unless __get() is defined, see next section).
То есть, получается, что у нас меняется привычное поведение
class A
{
/**
* @var string|null
*/
public $a;
public ?string $b;
}
$a = new A();
var_dump($a->a); // NULL
var_dump($a->b); // Fatal error: Uncaught Error: Typed property A::$b must not be accessed before initialization
Согласен. Многословность доставляет некоторые неудобства, но преимущества в композиции, реиспользовании и единой точке объявления бизнес-правил, что упрощает сопровождение и рефакторинг.
RulerZ позволяет более компактно описывать бизнес-првила, но он лишён многих преимуществ Happyr Doctrine Specification.
На мой взгляд, статья не облегчает и не упорядочивает восприятие принципов SOLID. Только ещё больше запутывает.
Зачем это мудрёное усложнение? Там же всё просто. Из всех 5 принципов, только LSP сложен для восприятия, и то вы как-то коряво его объяснили.
Проблема не в том, что квадрат как то не так наследуется от прямоугольника. Проблема в том, что квадрат, прямоугольник, ромб и параллелограммом является абсолютно разными фигурами не смотря на ряд сходст. И ни кто из них не является подтипом другого о чем и говорит LSP.
И зачем вы объединили ISP и DIP? Это разные принципы. У них из общего только то, что они входят в SOLID. К слову, SOLID это про зависимости.
Спасибо за статью. Интересная мысль высказана, но мне кажется, что всё несколько иначе.
Есть замечательный анекдот на эту тему
Приходит сын к папе программисту.
Папа, как всегда, трое суток не вылазя из-за компьютера что-то хачит…
– Папа, почему Солнце всходит на востоке, а заходит на Западе?
Папа — ноль эмоций…
– Папа, ну почему Солнце каждый день всходит на востоке,
а заходит на Западе?
Папа — опять ноль эмоций…
Сын, нетрпеливо дергая папу за рукав:
– Папа, папа, ну почему Солнце
каждый день всходит на востоке, а заходит на Западе?
Папа, оторвавшись от Клавы и глядя мутным взором на сына:
– Солнце…
– Да
– Всходит на востоке…
– Да
– Заходит на западе…
– Да, папа
– Каждый день?!
– Да…
– И давно так?
– Ну, я не знаю… Всегда…
– Тогда сынок, ради бога, ничего не трогай и ничего не меняй!
Людей из компании просто так не увольняют и особенно ключевых сотрудников. Я вижу только 3 причины увольнения ключевого сотрудника.
А) Попытка сэкономить. Как было уже сказано, проект вышел на плато и есть возможность/необходимость сэкономить средства на рабочей силе.
Зарплаты сотрудников это одна из самых больших статей расходов компании и когда встаёт вопрос финансов, первыми летят головы сотрудников. А кого увольнять, дешёвых джунов или дорогостоящих ключевиков, уже на усмотрение бизнеса.
Если на вас решили сэкономить, то лучше за эту компанию не держаться. Ни к чему хорошему это не приведет. А если в компании реально финансовые трудности, то и обижаться тут не на что. (Я бывал в такой ситуации)
Б) Мешает развитию бизнеса. Не прислушивается к авторитетным мнениям, отказывается реализовывать нужные бизнесу фичи, пилит свои, никому не нужные, фичи, требует долю в бизнесе, диктует как вести бизнес и т.д.
Не важно как, но если ключевой сотрудник мешает развитию компании, то от него нужно избавляться и это нормально.
Если от вас решили избавиться, то может стоит поработать над собой?
С) Возможно вы не такой уж и ценный сотрудник. Бывают случаи когда бизнес списывает какие-то свои провалы на не особо ценных сотрудников и просто избавиться от них.
Тут нет четких критериев выбора козла отпущения. Это просто бизнес.
В любом случае, я бы рекомендовал становиться ценным сотрудником для бизнеса, а не ключевым сотрудником и морально готовится перейти на руководящие роли отдав программирование другим.
Каждый раз когда заходит разговор о фингерпринте, все тут же вспоминают таргетированную рекламу, но почему-то забывают о том, что для этого используются банальные куки, а не фингерпринт.
На всех сайтах установлен Google Analytics и/или Яндекс.Метрика. Куки ставятся на домены Гугла и Яндекса. И не важно, что вы посещаете разные сайты, Гугл с Яндексом могут точно идентифицировать вас по своим кукам.
Фингерпринт хоть и даёт высокий процент точности идентификации пользователей, но не 100% в отличии от кук.
Значительно чаще я встречаю кейсы в которых фингерпринтинг используют для борьбы с теми, кто злоупотребляет анонимностью. Цитата с сайта из комментария выше:
я играю в браузерную онлайн стратегию… при создании второго аккаунта меня система распознаёт как уже зарегистрированного… повторную регистрацию удается повторить при очистке истории (куки) и смене айпи… но если пробовать регать новый ак по реферальной ссылке реферал получается не рабочий ( то-есть ак вроде есть и играет но польза от него хозяину реферальной ссылки ни какой) Эффективно только регистрация на новом не засвеченном компьютере… но где взять столько машин если надо много рефералов?.. МАК-адрес менял не помогает… может криво с руками что… ПОМОГИТЕ обмануть меркантильных хозяев онлайн стратегий и иметь возможность на халявный плюсик.
Делали подобные штуки лет 5 назад, в самописе, и кажется использовали Go!, только аспекты накладывали через аннотации.
Пример в статье не очень удобен, потому, что он моментально сломается если метод переименуется или изменится список аргументов. А отслеживать такие вещи сложно ибо разработчик меняющий метод может быть не в курсе, что на него кто-то налажал аспект. И IDE такую связь не увидит. Особенно весело, если проблема вылезет на этапе слияния с другими фичами.
Аннотации дают более четкую связь метода и аспекта и не такую жёсткую связь как явное использование в методе.
Я вот не понимаю этого шума вокруг знака $. Не припомню чтобы мне когда либо мешал этот символ.
Скажу даже больше. Некоторым не хватает $ в других языках. Довольно часто встречаю случаи когда JavaScript разработчики используют $ в имени переменных (сам так не делаю). Поначалу мне думалось, что это php программисты переносят свои привычки в js, но сейчас так пишут код даже чистые фронтендеры, которые php в глаза не видели. Возможно это просто последствия.
Хотя есть свой смысл в использовании $ в контексте js. Например, в следующем примере без контекста невозможно понять, bar это переменные с некоторым значением или название функции, а foo это название функции или ссылка на функцию.
foo(bar);
Следующие примеры более очевидны
foo($bar);
$foo(bar);
$foo($bar);
И не подумайте. Я не поддерживаю идею использования $ в js.
Сейчас набегут хейтеры и скажут, что это недостатки самого языка и писать надо на питоне)))
Вообще это была шутка. В плане стадий отрицания, с руби и питоном я дальше первой не ушел. Покапал немного, написал несколько простеньких програмулин, но не зашло. А вот php зашёл с самых первых строк. Так зашёл, что до сих пор не отпускает)))
То есть, доступ к данным имеет их владелец или пользователь техподдержки. Получается это тоже бизнес правило, которое также можно закладывать в условия.
Кроме того этот случай решается «супер-пользователем»
На мой взгляд, "супер-пользователь" это серьезный удар по безопасности.
В своей практике я не припомню случаев необходимости в таких пользователях.
Персональный пользователь с правами администратора – Да
Временный пользователь для функциональных тестов – Да
Пользователь с ограниченными правами для ботов – Да
Но не супер-пользователь.
Да, но если эти данные вообще не предназначены для данного пользователя зачем ему вообще иметь возможность их видеть?
Моё предложение в том, что бы использовать базовую спецификацию проверяющую права и расширять её при необходимости. В этом случае вы в явном виде запрашиваете данные конкретного пользователя. То есть, это не спецификация проверчющая права доступа, а спецификация возвращающая пользовательские данные, которая инкапсулирует проверку прав доступа. Это немного другой взгляд.
Конечно можно применять фильтры и на глобальном уровне в неявном виде. Иногда я тоже так делаю, но лично я все равно придерживаюсь мнения, что явное лучше неявного.
Короткий ответ — отлично. Если хотите длинный ответ, то вот он.
Вообще, ограничения доступа которые вы описали в статье, это больше похоже на бизнесовые правила и им место скорее в спецификациях, а не на глобальном уровне. Применяя их на глобальном уровне вы можете столкнутся с ситуацией когда вам нужно получить данные не применяя эти правила.
А что бы не забывать применить спецификации, давайте им понятные названия и объединяйте их в большие. Например, в вашем случае, можно создать спецификации ClientOrganizationsSpec и StaffingAgencyOrganizationsSpec и объединить в общую UserOrganizationsSpec.
Остальные правила которые вы описываете в Where, так же можно описать через спецификации и в результате в контроллере вы будете передавать 1-3 спецификации.
На мой взгляд, проще ориентироваться в наборе спецификаций имеющих четкое название и четкое назначение чем в куче условий в Where. Тем более что со спецификациями вы уже имели дело. Кстати говоря, как ваше впечатление от них спустя год?
Когда пользователь перемещается между страницами его явно интересуют не последние записи
И вернувшись на первую страницу он не увидит новых записей.
на момент запроса тут было сообщение, но к тому моменту как вы до него добрались оно уже было удалено, поэтому мы не можем показать вам его содержимое
Вот вы не видите проблемы в НЛО, но видите проблему в дублях. Другие же разработчики и пользователи не видят проблемы в дублях, а вот НЛО раздражает.
Снепшот создаётся клиентом целенаправленно, чтобы с ним потом работать независимо от изменений в исходных данных.
Из вашей статьи я делаю вывод, что вы запрашиваете с сервера список id записей соответствующих поисковому запросу и кешируете результат на клиенте. Далее, реализуете пагинацию на клиенте по списку закешированных записей.
Вы список закешированных записей называете снепшотом, но механика явно кеширующая.
Так что, нет. В вашем случае кеш и снепшот это синонимы.
А ограничение на число элементов есть всегда
И снова нет. Ограничений почти никогда нет. Вам уже привели 2 примера и можно привести ещё миллион.
Да, некоторые искусственно ограничивают число элементом в силу своих каких-то технических ограничений и Google Search тому яркий пример. Выдавать в поисковой выдаче результаты до которых пользователей не долистает для них скорей всего экономически не выгодно. А вот для каталогов (1, 2, 3) это не корректно. Тоже с архивом новостей. А обрезание комментариев на форуме или сообщений в личке или списка конкурсантов в онлайн конкурсе или ленты в соцсетях это вообще нарушение целостности данных и пользователи вас за это по головке не погладят.
Подитожу. Как я, так и другие комментаторы я полагаю, критикуем не сам ваш метод, давно известный, но не слишком популярный. Мы критикуем ваше отношение к нему. Вы преподносить классическую пагинацию как антипаттерн, а ваш метод как серебряную пулю и универсальное решение хотя это не так.
Но это конечно ваше право иметь собственное мнение и не принимать истину.
При удалении записей которые есть в снепшоте вы получите НЛО или дырки. Если удаленных материалов много, то вы можете получить вообще дырку от бублика пустую страницу.
Вы ограничиваете результат до 1000 записей, но это не всегда корректно. Это корректно для поисковой выдаче, но не корректно для каталогов и архивов. Вспоминаем Бездну.
Реализация без паджинации, но с разделением поиска и выборки решает их все. Было бы не плохо предлагать альтернативы, которые как минимум не хуже.
Serious? Ваше решение решает только проблему дублей на странице, но оно не решает остальные поставленные вами проблемы, о чем вам уже не однократно написали в комментариях.
Относительная паджинация, предложенная maximw, решает как проблему дублей, так и проблему удаленных записей.
Обнаружилась интересная штука с типизированными свойствами
То есть, получается, что у нас меняется привычное поведение
Я что-то не уверен, что это правильно.
Не совсем так, но общий смысл тот же
Конечный запрос всего в несколько строчек которые легко читаются:
На более сложных бизнес-правилах профит будет больше.
Согласен. Многословность доставляет некоторые неудобства, но преимущества в композиции, реиспользовании и единой точке объявления бизнес-правил, что упрощает сопровождение и рефакторинг.
RulerZ позволяет более компактно описывать бизнес-првила, но он лишён многих преимуществ Happyr Doctrine Specification.
Сколько всего интересного))) И ковариантность/контравариантность это супер. Давно не хватало.
На мой взгляд, статья не облегчает и не упорядочивает восприятие принципов SOLID. Только ещё больше запутывает.
Зачем это мудрёное усложнение? Там же всё просто. Из всех 5 принципов, только LSP сложен для восприятия, и то вы как-то коряво его объяснили.
Проблема не в том, что квадрат как то не так наследуется от прямоугольника. Проблема в том, что квадрат, прямоугольник, ромб и параллелограммом является абсолютно разными фигурами не смотря на ряд сходст. И ни кто из них не является подтипом другого о чем и говорит LSP.
И зачем вы объединили ISP и DIP? Это разные принципы. У них из общего только то, что они входят в SOLID. К слову, SOLID это про зависимости.
Рекомендую к прочтению https://github.com/jupeter/clean-code-php или форк на русском https://github.com/peter-gribanov/clean-code-php
А ещё есть такая штука как подзаголовки. Рекомендую
Спасибо за статью. Интересная мысль высказана, но мне кажется, что всё несколько иначе.
Приходит сын к папе программисту.
Папа, как всегда, трое суток не вылазя из-за компьютера что-то хачит…
– Папа, почему Солнце всходит на востоке, а заходит на Западе?
Папа — ноль эмоций…
– Папа, ну почему Солнце каждый день всходит на востоке,
а заходит на Западе?
Папа — опять ноль эмоций…
Сын, нетрпеливо дергая папу за рукав:
– Папа, папа, ну почему Солнце
каждый день всходит на востоке, а заходит на Западе?
Папа, оторвавшись от Клавы и глядя мутным взором на сына:
– Солнце…
– Да
– Всходит на востоке…
– Да
– Заходит на западе…
– Да, папа
– Каждый день?!
– Да…
– И давно так?
– Ну, я не знаю… Всегда…
– Тогда сынок, ради бога, ничего не трогай и ничего не меняй!
Людей из компании просто так не увольняют и особенно ключевых сотрудников. Я вижу только 3 причины увольнения ключевого сотрудника.
А) Попытка сэкономить. Как было уже сказано, проект вышел на плато и есть возможность/необходимость сэкономить средства на рабочей силе.
Зарплаты сотрудников это одна из самых больших статей расходов компании и когда встаёт вопрос финансов, первыми летят головы сотрудников. А кого увольнять, дешёвых джунов или дорогостоящих ключевиков, уже на усмотрение бизнеса.
Если на вас решили сэкономить, то лучше за эту компанию не держаться. Ни к чему хорошему это не приведет. А если в компании реально финансовые трудности, то и обижаться тут не на что. (Я бывал в такой ситуации)
Б) Мешает развитию бизнеса. Не прислушивается к авторитетным мнениям, отказывается реализовывать нужные бизнесу фичи, пилит свои, никому не нужные, фичи, требует долю в бизнесе, диктует как вести бизнес и т.д.
Не важно как, но если ключевой сотрудник мешает развитию компании, то от него нужно избавляться и это нормально.
Если от вас решили избавиться, то может стоит поработать над собой?
С) Возможно вы не такой уж и ценный сотрудник. Бывают случаи когда бизнес списывает какие-то свои провалы на не особо ценных сотрудников и просто избавиться от них.
Тут нет четких критериев выбора козла отпущения. Это просто бизнес.
В любом случае, я бы рекомендовал становиться ценным сотрудником для бизнеса, а не ключевым сотрудником и морально готовится перейти на руководящие роли отдав программирование другим.
Каждый раз когда заходит разговор о фингерпринте, все тут же вспоминают таргетированную рекламу, но почему-то забывают о том, что для этого используются банальные куки, а не фингерпринт.
На всех сайтах установлен Google Analytics и/или Яндекс.Метрика. Куки ставятся на домены Гугла и Яндекса. И не важно, что вы посещаете разные сайты, Гугл с Яндексом могут точно идентифицировать вас по своим кукам.
Фингерпринт хоть и даёт высокий процент точности идентификации пользователей, но не 100% в отличии от кук.
Значительно чаще я встречаю кейсы в которых фингерпринтинг используют для борьбы с теми, кто злоупотребляет анонимностью. Цитата с сайта из комментария выше:
Делали подобные штуки лет 5 назад, в самописе, и кажется использовали Go!, только аспекты накладывали через аннотации.
Пример в статье не очень удобен, потому, что он моментально сломается если метод переименуется или изменится список аргументов. А отслеживать такие вещи сложно ибо разработчик меняющий метод может быть не в курсе, что на него кто-то налажал аспект. И IDE такую связь не увидит. Особенно весело, если проблема вылезет на этапе слияния с другими фичами.
Аннотации дают более четкую связь метода и аспекта и не такую жёсткую связь как явное использование в методе.
Сейчас, в Symfony, подобные задачи можно решить через Doctrine Annotation.
Я вот не понимаю этого шума вокруг знака $. Не припомню чтобы мне когда либо мешал этот символ.
Скажу даже больше. Некоторым не хватает $ в других языках. Довольно часто встречаю случаи когда JavaScript разработчики используют $ в имени переменных (сам так не делаю). Поначалу мне думалось, что это php программисты переносят свои привычки в js, но сейчас так пишут код даже чистые фронтендеры, которые php в глаза не видели. Возможно это просто последствия.
Хотя есть свой смысл в использовании $ в контексте js. Например, в следующем примере без контекста невозможно понять,
barэто переменные с некоторым значением или название функции, аfooэто название функции или ссылка на функцию.Следующие примеры более очевидны
И не подумайте. Я не поддерживаю идею использования $ в js.
Сейчас набегут хейтеры и скажут, что это недостатки самого языка и писать надо на питоне)))
А с autoconfigure и конфиг писать не надо. Просто говорим в конструкторе какие зависимости нам нужны.
Вообще это была шутка. В плане стадий отрицания, с руби и питоном я дальше первой не ушел. Покапал немного, написал несколько простеньких програмулин, но не зашло. А вот php зашёл с самых первых строк. Так зашёл, что до сих пор не отпускает)))
14 лет пишу на php. Пробовал питон и руби – и меня никто, ни за какие деньги не заставит писать на них)))
То есть, доступ к данным имеет их владелец или пользователь техподдержки. Получается это тоже бизнес правило, которое также можно закладывать в условия.
На мой взгляд, "супер-пользователь" это серьезный удар по безопасности.
В своей практике я не припомню случаев необходимости в таких пользователях.
Но не супер-пользователь.
Моё предложение в том, что бы использовать базовую спецификацию проверяющую права и расширять её при необходимости. В этом случае вы в явном виде запрашиваете данные конкретного пользователя. То есть, это не спецификация проверчющая права доступа, а спецификация возвращающая пользовательские данные, которая инкапсулирует проверку прав доступа. Это немного другой взгляд.
Конечно можно применять фильтры и на глобальном уровне в неявном виде. Иногда я тоже так делаю, но лично я все равно придерживаюсь мнения, что явное лучше неявного.
Спасибо за доклад. Было интересно послушать.
Вообще, ограничения доступа которые вы описали в статье, это больше похоже на бизнесовые правила и им место скорее в спецификациях, а не на глобальном уровне. Применяя их на глобальном уровне вы можете столкнутся с ситуацией когда вам нужно получить данные не применяя эти правила.
А что бы не забывать применить спецификации, давайте им понятные названия и объединяйте их в большие. Например, в вашем случае, можно создать спецификации
ClientOrganizationsSpecиStaffingAgencyOrganizationsSpecи объединить в общуюUserOrganizationsSpec.Остальные правила которые вы описываете в
Where, так же можно описать через спецификации и в результате в контроллере вы будете передавать 1-3 спецификации.На мой взгляд, проще ориентироваться в наборе спецификаций имеющих четкое название и четкое назначение чем в куче условий в
Where. Тем более что со спецификациями вы уже имели дело. Кстати говоря, как ваше впечатление от них спустя год?Я в подобных случаях использую спецификации
И вернувшись на первую страницу он не увидит новых записей.
Вот вы не видите проблемы в НЛО, но видите проблему в дублях. Другие же разработчики и пользователи не видят проблемы в дублях, а вот НЛО раздражает.
Из вашей статьи я делаю вывод, что вы запрашиваете с сервера список id записей соответствующих поисковому запросу и кешируете результат на клиенте. Далее, реализуете пагинацию на клиенте по списку закешированных записей.
Вы список закешированных записей называете снепшотом, но механика явно кеширующая.
Так что, нет. В вашем случае кеш и снепшот это синонимы.
И снова нет. Ограничений почти никогда нет. Вам уже привели 2 примера и можно привести ещё миллион.
Да, некоторые искусственно ограничивают число элементом в силу своих каких-то технических ограничений и Google Search тому яркий пример. Выдавать в поисковой выдаче результаты до которых пользователей не долистает для них скорей всего экономически не выгодно. А вот для каталогов (1, 2, 3) это не корректно. Тоже с архивом новостей. А обрезание комментариев на форуме или сообщений в личке или списка конкурсантов в онлайн конкурсе или ленты в соцсетях это вообще нарушение целостности данных и пользователи вас за это по головке не погладят.
Подитожу. Как я, так и другие комментаторы я полагаю, критикуем не сам ваш метод, давно известный, но не слишком популярный. Мы критикуем ваше отношение к нему. Вы преподносить классическую пагинацию как антипаттерн, а ваш метод как серебряную пулю и универсальное решение хотя это не так.
Но это конечно ваше право иметь собственное мнение и не принимать истину.
Это такой тонкий троллинг?
Вам же уже написали:
дырку от бубликапустую страницу.Serious? Ваше решение решает только проблему дублей на странице, но оно не решает остальные поставленные вами проблемы, о чем вам уже не однократно написали в комментариях.
Относительная паджинация, предложенная maximw, решает как проблему дублей, так и проблему удаленных записей.