Pull to refresh
30
0
Пётр Грибанов @ghost404

Symfony professional developer

Send message

Если говорить о предметной области, то это DDD и класс обязан быть построен на свойствах объекта предметной области. И если предметная область говорит нам о том, что есть Напиток и Кофе, и наша предметная область в конкретном ограниченном контексте говорит, что Кофе это частный случай Напитка, то в коде мы обязаны отразить это наследование.

Лучше выделить более общий подтип для обеих фигур.


Несмотря на кажущееся сходство квадрата и прямоугольника, они разные. Квадрат имеет много общего с ромбом, а прямоугольник с параллелограммом, но они не являются подтипом. Квадрат, прямоугольник, ромб и параллелограмм — это отдельные фигуры со своими собственными свойствами, хотя и схожими.


Подробнее здесь.

Я об этом и говорю, что необходимость объявления свойства как nullable в явном виде при переходе на PHP 7.4 не очевидна.
Не смотря на то, что я изучал вопрос type hunting свойств класса, я упустил из виду эту особенность. Безусловно это полностью моя вина и невнимательность, но я не вижу, что бы кто либо делал акцент на этой особенности. И в RFC этот нюанс описан вскользь и при беглом осмотре его легко упустить. Отсюда я предполагаю, что с этой проблемой могу столкнуться не только я, а ещё очень многие разработчики которые не слишком внимательно следят за всеми фичами в PHP. Хотя возможно мои домыслы надуманы и ни какой проблемы нет. Время покажет.

Точнее нет. После отправки формы скорей можно схлопотать TypeError, а Fatal error скорей при рендере или валидации формы.

Тут скорее не "рассчитывает на дефолтный null без его явного задания", а "не рассчитывает на Fatal error без его явного задания".


Проблема не в том, что логика приложение может быть построена на том, что значение по умолчанию null. Проблема в том, что обращение к свойству может быть и не в биснес логике, а где-то на низкоуровневых слоях в сторонних библиотеках типа форм, движка БД, шаблонгизатора и т.д. где скорее важно есть ли значение у свойства или нет.


К примеру, ты можешь не ожидать, что этот шаблон может падать с Fatal error у некоторых пользователей:


Возраст пользователя {{ app.user.age }}

Или форма после отправки может падать с Fatal error если пользователь заполнил не все поля формы или подменил какие-то поля формы.

Тут согласен. Наверное так и правда правильней, но меня смутило то, что переход на type hinting в свойствах класса будет не так очевиден как хотелось бы. Боюсь многие наступят на эти грабли.

Ну, то есть понятно, что код мигрирует на PHP 7.4 по другому.


class A
{
    /**
     * @var string|null
     */
    public $a;

    public ?string $b = null;
}

Но мне кажется это как-то не так должно быть.

Обнаружилась интересная штука с типизированными свойствами


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

Я что-то не уверен, что это правильно.

Не совсем так, но общий смысл тот же


class Enabled extends BaseSpecification
{
    protected function getSpec()
    {
        return Spec::eq('enabled', true);
    }
}

class PublishedBroadcast extends BaseSpecification
{
    protected function getSpec()
    {
        return new Enabled();
    }

class PublishedSeries extends BaseSpecification
{
    private $broadcast_alias = '';

    public function __construct(
        string $broadcast_alias,
        ?string $dql_alias = null
    ) {
        $this->broadcast_alias = $broadcast_alias;
        parent::__construct($dql_alias);
    }

    protected function getSpec()
    {
        return Spec::andX(
            new PublishedBroadcast($this->broadcast_alias),
            new Enabled()
        );
    }

class SeriesOfBroadcast extends BaseSpecification
{
    private $broadcast;

    public function __construct(Broadcast $broadcast, ?string $dql_alias = null)
    {
        $this->broadcast = $broadcast;
        parent::__construct($dql_alias);
    }

    protected function getSpec()
    {
        return Spec::eq('broadcast', $this->broadcast->getId());
    }
}

Конечный запрос всего в несколько строчек которые легко читаются:


$series = $this->rep_series->match(Spec::andX(
    Spec::innerJoin('broadcast', 'b')
    new PublishedSeries('b'),
    new SeriesOfBroadcast($broadcast),
    Spec::slice($slice_size, $slice_number)
), Spec::cache(3600));

На более сложных бизнес-правилах профит будет больше.

Согласен. Многословность доставляет некоторые неудобства, но преимущества в композиции, реиспользовании и единой точке объявления бизнес-правил, что упрощает сопровождение и рефакторинг.
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 это название функции или ссылка на функцию.


foo(bar);

Следующие примеры более очевидны


foo($bar);
$foo(bar);
$foo($bar);

И не подумайте. Я не поддерживаю идею использования $ в js.


Сейчас набегут хейтеры и скажут, что это недостатки самого языка и писать надо на питоне)))

А с autoconfigure и конфиг писать не надо. Просто говорим в конструкторе какие зависимости нам нужны.

Вообще это была шутка. В плане стадий отрицания, с руби и питоном я дальше первой не ушел. Покапал немного, написал несколько простеньких програмулин, но не зашло. А вот php зашёл с самых первых строк. Так зашёл, что до сих пор не отпускает)))

14 лет пишу на php. Пробовал питон и руби – и меня никто, ни за какие деньги не заставит писать на них)))

Information

Rating
Does not participate
Location
Россия
Registered
Activity