Pull to refresh
22
0
Слава @slavcopost

Пользователь

Send message
Ооо, похороны PHP. Опять.
Ну надо уточнить что не «все» а лишь родительский контекст. В моем предыдущем комментарии я как раз показал. То что одна инструкция на функцию это ограничивает юз кейсы для данной функции, толька на те где обычная анонимка слишком громозко выглядит. Например
$positiveNumbers = array_filter($numbers, fn($num) => $num > 0);
$objects = array_map($items, fn($item => new Foo($num));

Пока реальных примеров использования не так много в php, в отличии от других языков. Например я часто использую это в JS, и нахожу это очень удобным и неплохо читабильным. Хотя понимаю, что кто-то другой скажет что читабильность ухудшается.
> У меня опыта значительно меньше

Отдельно хочу уточнить по поводу упоминания мною моего опыта.
Я совсем не хотел тем самым показать мою крутость или авторитетность моего мнения.
Я лишь хотел сделать акцент что несмотря на одинаковый карьерный возраст, мнения у нас могут категорически не совпадатью. И это прекрасно.

Возможно я мог бы выразится лучше, но уже поздно.
Так и в чем же значительная разница? Стрелочные функции это синтаксический сахар для очень простых (с одним expression) анонимок где не нужно писать `use`. Да это новый синтаксис, да его надо один раз выучить. Говрить о сложностях понимания думаю неправильно. Через годик, когда фреймворки подтянутся и когда каждый программист встретит парочку раз такой синтаксис, он не будет уже казаться новым и страшным.

Привыкаем, прогрессируем и все будет хорошо не хуже.
$foo = 'foo';
$f = function() {
   $fn = fn() => $foo; // Тоже ошибка компиляции
   echo $fn();
}
$f(); 
Не сломается если свойства родительского класса с дефолтными значениями. А не с дефолтными и сейчас сломается. Хочу еще раз уточнить Сonstructor promotion не придносит ничего нового кроме как более короткий синтаксис того что сейчас требует повторять трижды (объявление совйства, аргумент, присваивание свойству значение аргумента).

Это явно указано в RFC и показан пример после слов
> Promoted properties follow a simple desugaring, where the following transformation is applied for all promoted parameters
> Вам будет неявно добавлен вызов parent::__construct()

Специально перечитал RFC. Можно ссылочку на это заявление?
Я не понимаю о чем речь. Без Сonstructor promotion это выглядит как
class A {
  public int $x;
  public int $y;
}
class B extends A {
  public string $z;
}

Т.е.
Да. Объекты типа B имеет свойства x & y. Не нужно, меняем видимость __construct(private int $x, private int $y).

Откуда они взялись, ясно откуда. Я думаю вы не до конца осознали что такое Сonstructor promotion. Это не значит что свойства класса будут объявлены только если вызвать конструктор.

Тайп-чек проходит на момент присвоения.
Позвольте мне не согласится с автором во всех пунктах данной статьи. И я тоже последние 16 лет ежедневно работаю с PHP.

1. Стрелочные функции.
Идея не меняется, они имеют тоже контекст. Контекст каждой функции заключет в фигурные скобки. Так и со стерлочными функциями.

2. Именные параметры.
С `$` начинается обявленная переменная в памяти, РФЦ вводит `:` как присваивание для будущей переменной. С этим РФЦ есть проблемы, но не одна из них не описанна в этой статье. Например РФЦ включает название переменных в АПИ, что ведет к услажнению рефакторинга, теперь изменить название аргумента функции будет сложнее. Но думаю любая ИДЕ эту проблему решит так что програмисты не особо будут с не сталкиваться.

3. Match
Да, код написанные новым синтаксисом можно уже сделать через switch. Но и switch код легко заменить на if, а while на for. Match всего лишь попытка облегчить код, аналогичный код другими средставми минимум в два-три раза больше, что теоритечески сложнее читать.

4. Сonstructor promotion
Осуждение в статье посторенно на «не возможно догадаться». Я сильно сомневаюсь что читающий код это повар, лесоруб или кто-нибудь другой который должен гадать о написанном. Програмист скорее всего один раз познакомившийся с синтаксимом будет узнавать и понимать читаемое легко. А если представить контекст данной операции, то приемущества видны еще более явно. Давайте просто сравним два аналогичных кода
class Point {
    public function __construct(
        public float $x = 0.0,
        public float $y = 0.0,
        public float $z = 0.0,
    ) {}
}

class Point {
    public float $x,
    public float $y,
    public float $z,
    public function __construct(
        float $x = 0.0,
        float $y = 0.0,
        float $z = 0.0,
    ) {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
    }
}

ИМХО первый вариант предпочтительнее.
> Догадайтесь, что после знаков "="? Начальные значения свойств? Или дефолтные значения аргументов конструктора?

А какая разница? В контексте конструктора? После "=" это и то и другое. А если что-то еще надо добавляем в тело конструктора.

5. Property write visibility
Хотя тут я соглашусь что синтаксис довольно сорный и не понятный, но не могу согласится что РФЦ и обсуждение проблемы плохо. Проблема в языке есть и это факт. Сеттеры и геттеры это просто язва PHP, который делает код безобразным. Хотя я надеюсь что этот РФЦ отклонят на голосовании, т.к. сегодня это решается статическими анализаторами более элегантно. Все же думаю что обсуждение пойдет на пользу PHP.

Итого
В статье упор делается на проблемы новичком, что довольно спорно, ИМХО.
Новички читают учебный материал, для них весь язык является чем-то новым, а не только новшества новых RFC. Это скорее пробелма более опытных програмистов, которые сопративляются изменениям. Главное чтоб преподователи и менторы этих новычков не преподносили материал вместе со своим субъективным мнением.
А я и не говорил что именно Order считает бонусы, это может делать и Customer и бонусы могут быть отдельным классом и много чего может быть, сложно дезайнить классы не знаю требования и домен. И да, ивентытоже могут быть использованы если они используются в архитектуре. Вы не уловили мысль, скорее всего это моя вина, я не правильно выразился. Идея в том что Order ответственен при своей смене запустить процесс начисления бонусов, будь то вызов поведения Customer либо записать ивент и сделать это асинхронно. Это не дело какого-то там «Application Service»? Это логика домена.

Я считаю смысл «Application Service» в настоящее время не отражает изначальный смысл этого термина. Например возьмем историческую работу Жефри Палермо jeffreypalermo.com/2008/07/the-onion-architecture-part-1
В ней если разобраться Application layer и Application services это что-то очень общее для кординирования приложения в целом: это SessionManager, AuthenticationManager, CommandBus. Это не сервисы которые содержат бизнес логику, знаний как реагировать на смену ордера, нужно ли начислать бонусы или нет, отправлять письмо по смене заказа или нет, и тд. Все эти классы с одним методом «handle», часто встречающиеся в настоящее время, даже ООП нельзя назвать, это обычные функции и от объектов там нет ничего.
Сходить во внешний сервис — это не бизнес-логика, это простейшая координация действий. Не происходит изменения стейта, нет риска нарушения инвариантов, это простое чтение данных. Этим может заниматься сервис, для этого нам не нужна наша сущность, и поэтому анемичной она не станет. Если результат из сервиса нужен для логики сущности — вызовите метод сущности передав туда результат который вернул сервис.


Мне кажется ответ базируется на удобном интерпретирование вопроса. Ходить во внешний сервис — нет это не бизнес-логика, поэтому и о HTTP клиенте сущность не будет знать. Но как быть если все таки существуют инварианты для подсчета времени доставки? Что если время доставки зависит от статуса заказа (на складе, запакован уже и тд)? Или от других данных состояния: тип, размер? Выносить все эти проверки в сервис, где считается время доставки и устанавливается в сущность? Сущность все такая же анемисная, и метод `delivery` все тот же «сеттер» устанавлиющий несколько свойств сущности (проверяет часть инвариантов, но не все связанные с поведением доставки).
Вроде рассуждаете много правильно, но в нескольких местах даёте вредные советы, по-моему. Тут нарушение слоистой архитектуры.
Книжка Эванса о DDD в основном о том, что такое ubiquitous language, как важно выделять бизнес сценарии, выделять границы доменов, события события, имеющие смысл для бизнеса и так далее.


В той же книги (или у Вернона, я уже не помню) приводится пример что репозиторий это доменный объект, но его имплементация это persistence. То же самое и с примером выше, с чего вы взяли что IPasswordGenerator это другой слой? Это объект домена User, котрый генерит свой пароль, именно User контролирует инварианты, когда его генерить и в каком сосотянии (например при регистрации). А уже имплементация IPasswordGenerator это уже не дело User, и он ничего об этом другом «слое» не знает, консумер `generateNewPassword` только знает и передает ту имплементацию какую хочет.
При $order->deliver() меняется внутреннее состояние самого $order, ему неважно что нужно юзеру смс отправить или баллы бонусные посчитать.


Почему не важно? Если домен Order требует чтоб при смене состояния заказа на «отправленный» дать знать клиенту или посчитать бонусные балы клиента?
Order вообще может не хранить email пользователя. Суть всей затеи в том чтобы инкапсулировать работу с состоянием.


Суть в том что Order имеет Customer и бизнес правило утвреждает что «при доставке Order нужно сообщить клиенту» или перефразировав «ордер при смене состоянии на доставленный должен сообщить клиенту».
> а часть на любом другом, потому что я спёр эти примеры из интернета

Можно было бы перевести примеры к одному языку, возможно бы это позволило понять лучше разницу между DI и SL.

> Легальное применение Контейнера

Оба примера используют принцип Dependency Injection и паттерн Service Locator. От того что get в конструкторе или дергается по запросу сути не мееняет.

> Чем же плох Service Locator?

Плох он ровным счетом тем же чем плохи глобальные переменные. Куча объектов зависят от одного и того же локаторы который возвращает всем один и те же сервисы. Тем самым меняя сервис для одного компонента, велика вероятность сломать что-то другое. Именно поэтому статический доступ к контейнеру, является ничем иным как Service Locator.

Разница DI и SL в том что один это принцип отвязывания объекта (функции) от зависимостей, а SL паттерн при котором зависимости объекта сводятся к одному единственному объекту, который ответственнен за другие зависимости. Хоть SL и считается антипатерном (см. аналогию с использованием глобальных переменных), в некоторых случаях является самым подходящим, например по причине упомянутой коментом выше — «ленивое» создание сервисов по запросу.
> Такое использование геттеров встречается достаточно часто и это плохо.

А почему плохо, я так и не понял. Я лично делаю геттер и вот почему: стэйт обычно нужен когда несколько компонентов работают с одними данными, и геттер лучше будет в одном месте а не в нескольких компонентах. Создаю его я даже если он только в одном уомпоненте используется, и отчасти не потому что «пусть будет, мало ли какой новый компонент его потребует», а потому что его сделал, добавил в юнит тест стораджа и забыл.
...mapGetter(['films']),

выглядит точно так же красиво как
...mapState(['films']),


Так что я не могу согласится с первыми 2 пунктами, по крайней мере пока не увижу реальный проблемы с ними.

По третеьему пункту соглашусь. Геттеры с параметрами это боль. Особенно тестирование.
О каких игроках речь? Речь ведь в том, что PIR единственный кто отвечает за .org. Убрав правила на установку цены, не отдав зону в ответственность нескольких компаний, странное решение. Зону сменить потому что цена не нравится — сложновато.
Сомневаюсь что они на это пойдут. Это ведь только подвердит проблему поднятую на этом сайте. И шум поднявшийся после как выяснится этот бан будет не на одном ресурсе, заблочить все будет сложно гуглу.
Про «старый» синтаксис в документации

Warning
This function has been DEPRECATED as of PHP 7.2.0. Relying on this function is highly discouraged.
Мелкое уточнение $x instanceof \Closure не проверяет является ли переменная функцией. Она проверяет является ли переменная анонимной функцией.

<?php
$x = function() {
};
$y = 'trim';

var_dump($x instanceof Closure); // true
var_dump($y instanceof Closure); // false
var_dump(is_callable($x)); // true
var_dump(is_callable($y)); // true

Information

Rating
Does not participate
Location
Испания
Date of birth
Registered
Activity