@symfony_php

Страница 233 из 1418
Sergey
15.06.2017
23:25:31
если это все в рамках одного контекста - я бы сделал сервис сверху который руководит процессом и декларирует "создай, пересчитай" или "удали, пересчитай"

Big_Shark
15.06.2017
23:26:19
если сущности принадлежат разным контекстам - то почему бы и нет
То есть получается ты подписываешься на postFlush, там находишь нужную сушьнось, и от туда кидаешь ивент на то что надо пересчитать?

Sergey
15.06.2017
23:26:21
у меня же в проекте подобная штука между "добавь, вот та статистика где-то вдалеке должна пересчитаться"

Google
Sergey
15.06.2017
23:26:45
и я тупо обхожу все сущности в UoW и собираю ивенты

а потом тригерю. Могу в очередь их запихнуть, могу там же обработать

но

это повторюсь - если у тебя между двумя модулями надо связь организовать. В пределах одного - чем явнее тем лучше

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

ну и смотреть с позиции open/close

Big_Shark
15.06.2017
23:28:42
там по факту 3 строки + public function updatePropertyRating() + { + $property = $this->getProperty(); + $property->calculateRating(); + $property->save(); + }

Хотя конечно calculateRating в модели не должен находится, это косяк

В любом случае пихать все в 1 сервис, не очень кошерно, а у меня есть один основной объект

по этому лучше делать через ивенты

Big_Shark
15.06.2017
23:32:32
@fes0r а разве в доктрине нет походего функционала который может кидать ивенты?

Google
Sergey
15.06.2017
23:32:55
ну то есть, это не от "в модели/в сервисе" зависит, а просто от того как ты на объекты дробишь и соблюдаешь ли ты принцип информационного эксперта

Big_Shark
15.06.2017
23:33:17
кто тебе такое сказал
Ты думаешь норм что модель достает все ревью который одобрены и считает рейтинг, а потом записывает у себя в переменную?

Sergey
15.06.2017
23:33:49
public function updateSomething() { // do something $this->remember(new SomethingHasBeenUpdated($this->id)); }

и тогда да - зашить в сервис

у меня к примеру есть логика - надо пересчитать лимиты продавцов

Big_Shark
15.06.2017
23:34:49
я бы это SQL запросом делал)
Ну там по большому счету ведь не важно как делать? ты же не будешь запрос вы ентите делать?

Sergey
15.06.2017
23:35:28
public function calculateLimits(LimitsCalculator $calculator) { $this->limit = $calculator->calculate($this->id, $this->registeredAt); $this->remember(new MerchantLimitsUpdated($this->id, $this->limit)); }

Big_Shark
15.06.2017
23:36:41
Ну тут если судить по принципу открытости закрытости, то проперти знает о своих ревью и их рейтингах, поэтому может это делать)

Sergey
15.06.2017
23:36:55
так... давай по другому... я использую ивенты потому что мне не хочется что бы "тригеры" знали что по ним происходит.

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

Big_Shark
15.06.2017
23:37:57
так... давай по другому... я использую ивенты потому что мне не хочется что бы "тригеры" знали что по ним происходит.
Для меня главное чтоб грубо говоря вызов функции пересчета не терялся, и как мне кажется лучший вариант

то запихнуть его в ивент, и ивент вызывать по событию из модели при сейве. или типа того

Sergey
15.06.2017
23:38:24
Для меня главное чтоб грубо говоря вызов функции пересчета не терялся, и как мне кажется лучший вариант
чем тебе не нравится к примеру дергать какой-то сервис после того как ты дернул модель, явно

// Add review // recalculate rating

две строчки кода, явно описывающие что происходит

Big_Shark
15.06.2017
23:39:32
чем тебе не нравится к примеру дергать какой-то сервис после того как ты дернул модель, явно
нет что у нас везде будет по 2 строчки, одна изменения, а вторая вызова сервиса, и если мы гжето сделаем одну строчку, то мы не пересчитаем рейтинг

Google
Sergey
15.06.2017
23:39:56
ну то есть лучше уж явно это сделать

так намного проще найти ошибку

и не надо прыгать по файлам

что бы отследить что происходит

Big_Shark
15.06.2017
23:40:44
если ты где-то не кинешь ивент или не подпишешься на него - ты не пересчитаешь рэйтинг
Вот это и произашло, я просто забыл про вызов функции пересчета, а хочется кудато поставить ее так, чтоб ее забыть было нельзя

Sergey
15.06.2017
23:40:53
то есть мое мнение - по дефолту надо делать именно так. Что бы у тебя на операцию, юзкейс, был файлик, который описывает полностью что происходит.

короч, если ты хочешь что бы я тебе сказал "сделать страшную волшебную хрень которая по каким-то стремным правилам мониторит изменения и тд." - нет. Это неявно, это потенциально баги, это сложно, это дорого суппортить, это сложнее объяснять новым челикам

у меня алгоритм "как сделать цепочку операций" простой: - Можно ли это сделать явно? Ну то есть описать "сценарий" который декларирует порядок действий в одном месте? Если можно - так и делаем. - Порядок действий хочет зависимости из разных мест и мне не очень хочется что бы зависимости знали друг о друге. Или не хочется делать циклические зависимости. Тогда доменные ивенты.

Big_Shark
15.06.2017
23:43:27
пиши тесты)
Мне кажется достаточно странные стесты будут

Sergey
15.06.2017
23:43:40
Мне кажется достаточно странные стесты будут
смотря что ты хочешь проверить.

Sergey
15.06.2017
23:43:49
ты же запускаешь код когда работу ведешь?

Big_Shark
15.06.2017
23:44:07
смотря что ты хочешь проверить.
консольная команда которая удаляет допустим старые отзывы)

Sergey
15.06.2017
23:44:13
еще лайххак небольшой - когда планируешь работу - прописывай критерии приемки. Типа что и как должно работать.

консольная команда которая удаляет допустим старые отзывы)
ну ты то не команду будешь тестить, а какой-то сервис

обычный интеграционный тест по позитивному сценарию

и несколько юнитов которые проверят отдельные элементы

Big_Shark
15.06.2017
23:45:27
ну ты то не команду будешь тестить, а какой-то сервис
Ну вот получается удас должен быть ReviewServiсe c функцией удалить ревью, который уже помимо удаления будет вызывать и пересчет, верно?

Google
Sergey
15.06.2017
23:46:18
но да, как-то так

НО, рейтинг этот как к ревью относится?

Big_Shark
15.06.2017
23:46:32
я бы сделал по сервису на операцию. RemoveReviewHandler, AddReviewHandler
Этож сколько файлов в итоге получится, там же задача в 2 строки

Big_Shark
15.06.2017
23:46:56
НО, рейтинг этот как к ревью относится?
Есть дом, у него есть рейтинг который мы смотрим от отзывам с оценками

Sergey
15.06.2017
23:47:04
ты же понимаешь что вся соль не в том сколько кода надо написать, а в том как легко его потом читать

ну то есть сэкономишь ты 1 минуту

и потом потратишь лишние пол часа на то что бы разбираться с логикой

Big_Shark
15.06.2017
23:48:46
и потом потратишь лишние пол часа на то что бы разбираться с логикой
Ну хочется писать код и не думать что вроде бы как я тут должен вызвать еще какойто ивент, который гдето чтото будет менять, и я точно не помню где, что и как)

Sergey
15.06.2017
23:49:36
у меня есть проект где чел сделал "ядро" которое должно было ему позволить сделать CRUD не в 5 строчек а в 3. Делал он эту херню неделю. По итогу спустя год что бы разобраться в какой-то мелочи разработчик который после него сидел потратил день. Хотя если бы не эта желания "экономить на строчках" можно было бы логику прописать явно и в целом потратилось бы 5 минут на то что бы разобраться что куда и сделать фичу

Admin
ERROR: S client not available

Big_Shark
15.06.2017
23:50:27
так не юзай ивенты)
Ну если не ивент, то сервис, но в любом случае надо вызывать пресчет, вопрос где, когда и как)

Sergey
15.06.2017
23:51:26
$property->submitReview(Review::builder() ->withAuthor($author) ->withRating($rating) ->withMessage($message) ->build() );

а внутри

public function submitReview(Review $review) { $this->reviews->add($review); $this->remember(new ReviewSubmittedEvent($this->id)); }

а потом

public function onReviewSubmittedEvent(ReviewSubmittedEvent $event) { $propertyId = $event->property; $this->connection->exec('UPDATE properties SET rating = AVG(..)', ['id' => $propertyId]); }

если тебе вообще не надо разделять Updated или Submitted

Google
Big_Shark
15.06.2017
23:54:23
Ок, спасибо, идею понял

Sergey
15.06.2017
23:54:25
можно обобщить событие до ReviewsChangedEvent

профит

ты тригеры все можешь юнит тестами протестить, что ивент есть

ивенты отработают ТОЛЬКО если транзакция успешно зафлашится

ну и останется проверить простеньким интеграционным тестом что сама операция работает корректно

Big_Shark
15.06.2017
23:55:28
Ну это уже просто

Sergey
15.06.2017
23:55:38
у меня так например одна и та же операция требуется по 10-ти тригерам с весьма непростой логикой

Big_Shark
15.06.2017
23:55:39
слушай, а ты такие билдеры используешь?

Sergey
15.06.2017
23:55:45
причем тригеры разные

Big_Shark
15.06.2017
23:56:05
Review::builder() ->withAuthor($author) ->withRating($rating) ->withMessage($message) ->build()

или это просто пример из головы)

Sergey
15.06.2017
23:57:18
ну это просто класс ReviewBuilder. Что бы не делать сущность с сеттерами и при этом не делать сущность с миллионом аргументов в контрукторе. Можешь в better java почитать например.

Если лень писать руками - ну можно плагин к шторму написать например))))

Sergey
15.06.2017
23:58:17
да

Big_Shark
15.06.2017
23:58:34
У меня просто както так public static function createBlockout(Period $datePeriod, Property $property, String $description, User $user, $status): Booking {

Sergey
15.06.2017
23:58:37
все что имеет больше двух аргументов в контрусторе стараюсь для таких вещей делать билдеры

потому что где 3 там станет 4

а где 2 - далеко не всегда становится 3

Big_Shark
15.06.2017
23:59:11
Есть логика

Sergey
15.06.2017
23:59:22
больше кода приходится писать

Страница 233 из 1418