
Sergey
08.05.2017
13:45:29
User берет, т.к. он знает че использовать, если бы было чем-то типа auth->authenticate в user, то ещё можно было бы глаза закрыть, т.к. usrr не знает что происходит, а так он знает и чтобы изменить поведение надо в него лезть (а не стандартные функции переписывать), а т.к. user уже за другое ответственен, то у него много ответствен гостей появляется, т.е. нарушение
public function changePassword(string $oldPassword, string $newPassword) {
if (!password_verify($this->password, $oldPassword) {
throw new IncorectPasswordError($this);
}
$this->password = password_hash($newPassword, PASSWORD_DEFAULT);
}

Andrey
08.05.2017
13:45:32
Смену пароля надо в user, т.к. это просто один из атрибутов user, но здесь только смена, отправка нотификаций и прочее - за пределами user

Sergey
08.05.2017
13:45:54
что до нотификаций

Google

Sergey
08.05.2017
13:46:20
$this->remember(new PasswordChanged($this));
и вешаем потом лисенер на доменные ивенты
итого допустим нам надо реализовать следующую логику:
- пользователь может сменить пароль только если ввел корректный старый
- новый пароль юзера не должен совпадать с 5-ю последними
куда бы ты чего пихал?

Andrey
08.05.2017
13:50:19
В пользователе только смена, ar мне не нравится, поэтому сохранение в репозиторий, а все проверки до фактической смены в отдельном сервисе

Sergey
08.05.2017
13:50:57

Andrey
08.05.2017
13:51:08
Надо сменить проверки - меняем только сервис, остальное без изменений

Sergey
08.05.2017
13:51:25
что бы собрать логику этого простого флоу надо попрыкать по классам

Andrey
08.05.2017
13:52:20
Давай начнём с самого начала - зачем нужны паттерны? Точнее для чего они?

Sergey
08.05.2017
13:52:55
которые нарушают O/C

Andrey
08.05.2017
13:53:14
Это кто сказал? ))) не верь ему )

Google

Sergey
08.05.2017
13:53:23
и потом расскажи как ты будешь покрывать юнит тестами все это дело

Andrey
08.05.2017
13:54:37
Паттерны - это решение какой-либо проблемы. If/else - это частный случай, т.к. они тоже являются проблемами

Алексей
08.05.2017
13:55:21

Andrey
08.05.2017
13:56:08
Юнит - легко, у меня может быть несколько аутентификации и каждая будет протестирована, каждую можно будет использовать и это легко поддерживать

Sergey
08.05.2017
13:57:24
мое любимое определение - паттерны это способы избавления от switch
"какие-то проблемы" это нарушение open/close принципа

Sergei
08.05.2017
13:58:14

Sergey
08.05.2017
13:58:32
симптомами нарушения OCP являются свитчи, ифы и new

?
08.05.2017
13:58:43

Sergey
08.05.2017
13:58:55
вывод, паттерны способ убрать switch/if/new и добиться соблюдения OCP
кроме юзера пароля никто не знает

Andrey
08.05.2017
13:59:45

Sergey
08.05.2017
13:59:47
предлагаешь инкапсуляцией пожертвовать?

Алексей
08.05.2017
14:00:04

Google

Sergei
08.05.2017
14:00:12

Andrey
08.05.2017
14:00:42

Sergey
08.05.2017
14:00:47

Sergei
08.05.2017
14:01:17

Sergey
08.05.2017
14:01:41
Д - делегирование ответственности

Алексей
08.05.2017
14:02:09

Sergei
08.05.2017
14:02:42

Andrey
08.05.2017
14:02:44
В примере её не было и я писал - если проверка отдельно - проблемы большой не вижу, но в примере она захардкожена была

Sergey
08.05.2017
14:03:06

Andrey
08.05.2017
14:03:08
Мы про пример говорим

Sergey
08.05.2017
14:03:12
но если подумать:
- поведенческие паттерны - избавляют нас от if/switch
- порождающие - от new
со структурными не все так просто но в конечном итоге всеравно от if избавляют и позволяют добиться OCP

?
08.05.2017
14:03:52
Но полностью от if'ов же не избавиться?
Это не реально

Sergey
08.05.2017
14:04:25
(ну и другие SOLID принципы тоже)

Andrey
08.05.2017
14:04:43
Если подумать - код только из if и состоит ))) но проблема не в них, а в поддержке этого кода

Google

Sergey
08.05.2017
14:05:22
https://gist.github.com/fesor/f5e2df605315f12eab3aaa01b80e7442
придумай мне кейсы при которых мне надо будет поменять этот код
раз уж мы про SRP начали

?
08.05.2017
14:05:58
Кто-то говорил, что static - это..
не круто)

Sergey
08.05.2017
14:06:28
мы же от сайд эффектов и глобального стэйта спрятаться хотим

?
08.05.2017
14:07:01
if (!password_verify($this->password, $oldPassword)) {
throw new IncorrectPasswordError();
}
повтор кода

Sergey
08.05.2017
14:07:17
и найди там повтор

Admin
ERROR: S client not available

Sergey
08.05.2017
14:07:32
и еще оцени профит от устранения такого дублирования
я профита не вижу
DRY не о том что бы маниакально убирать дублирование, он о том что бы логика не дублировалась

Andrey
08.05.2017
14:07:57

Sergey
08.05.2017
14:08:01
у тебя может быть два абсолютно одинаковых класса но использующихся в разных контекстах.

?
08.05.2017
14:08:26

Andrey
08.05.2017
14:08:34
В конфиге указано чем хэшировать ))

Sergey
08.05.2017
14:08:46
public function changePassword(string $oldPassword, string $newPassword, PasswordHasher $hasher);

Google

Andrey
08.05.2017
14:08:50
Или в другом классе

Sergey
08.05.2017
14:08:59

Andrey
08.05.2017
14:09:08
Раз уже изменили ))

Sergey
08.05.2017
14:09:10
но вот я выше дал тебе пример как делигировать это

Andrey
08.05.2017
14:10:41
Так вот для этого и rsp, чтобы не менять 100 классов, а просто добавить один и передать его там где он нужен. А мы уже на один больше изменили. Последний пример мне нравится больше

Sergey
08.05.2017
14:10:56

Andrey
08.05.2017
14:11:02

Sergey
08.05.2017
14:11:31
SRP о том что в ЗАВИСИМОСТИ от контекста и характера изменений мы должны делить объекты определенным образом с позиции того кто будет использовать нужное поведение
changePassword и authenticate имеют одни и те же причины для изменений
логика проверки хэша и валидации пароля может быть делигирована другим объектам
но главное
инкапсуляция не нарушена

Andrey
08.05.2017
14:12:43

Sergey
08.05.2017
14:12:54
и как бы положил новый?
и скажи как это будет выглядеть с точки зрения инкапсуляции?
еще одна проблема твоего подхода
будет у нас например еще пяток бизнес правил для логина
небольших каких
аля "если чувак 3 раза ввел пароль не правильно - надо залочить аккаунт"
и допустим у нас есть на все это отдельные сервисы, декораторы и прочее