
Sergey
14.10.2018
12:33:36
более того - в случае если бронь зафэйлилась пытаться применить промокод уже не нужно.

Дмитрий
14.10.2018
12:34:53
Пытаться применить нет, но сообщить о его просрочке можно

Sergey
14.10.2018
12:35:08
так что можно опять же сначала проверить все прекондишены а уже потом сраждаться с инвариантами. И получить список ошибок для прекондишенов (это просто) а с инвариантами просто фэйлить по одной ошибке. Поскольку у тебя применение промокода все же зависит от брони

Google

Дмитрий
14.10.2018
12:35:50
Я это и предложил, вынести проверки прекондишенов в отдельный метод

Sergey
14.10.2018
12:36:12
еще раз - прекондишены и инварианты - разные вещи
ой все короч

Дмитрий
14.10.2018
12:36:37
))
Ты почти понял меня)

Sergey
14.10.2018
12:37:09
прикол инвариантов в том что у тебя врядли в одной бизнес операции будут независимые инварианты. Как следствие - говорить о получении "списка" нарушений инвариантов глупо
инварианты - они как бы инварианты системы
и изначально дискуссия была только про инварианты, в следствии чего я начал подозревать что человек смешивает понятие прекондишенов и инвариантов

Дмитрий
14.10.2018
12:40:27
Ты согласен с тем что для атомарного перехода от одного состояния к другому с соблюдением всех инвариантов может потребоваться проверка 2 и более независимых условий?

Sergey
14.10.2018
12:41:59
независимых - нет. Потому что переход от одной проверки к другой требует изменения состояния.

Дмитрий
14.10.2018
12:42:06
Например человек может сделать шаг и изменить состояние, только если у него будет обе ноги
Чтобы проверить наличие одной ноги не нужно менять состояние

Sergey
14.10.2018
12:46:59
еще раз...
1. конфликт в промокодах (один промокод остался) и нет конфликта по местам - если проверки "независимы" то фэйл с промокодами не должен влиять на бронь.
2. конфликт с местами, промокодов всем хватает - бронь не будет произведена
3. конфликт и с местами и с промокодом - ты не сможешь забронировать а стало быть не сможешь применить промокод. Как следствие зафэйлится всегда только одна операция (нету конфликта). Что делает эти проверки зависимыми

Google

Дмитрий
14.10.2018
12:55:37
Проверки зависимы если возможность выполнить одну проверку появляется после совершения другой проверки. Например, 1. Ввел ли пользователь купон, 2. Существует ли купон. 3. Просрочен ли купон.
В нашем случае чтобы проверить купон, не обязательно бронить место, значит результат проверки можно показать сразу независимо от того, свободно ли место


Sergey
14.10.2018
12:59:13
все это - прекондишены а не инварианты.
их можно проверять отдельно
опять же - ситуация (раз уж ты за конверсию топишь) - я ошибся с промокодом и выбрал места. Нажал "забронировать", и система мне такая "сорян дружок, ты ввел невалидный промокод, но ты еще мог забронить" и пока я читаю это сообщение бронирует кто-то другой
а это были последние места которые я считаю удобными для себя и вообще в пень твой сервис - посмотрю в онлайн кинотеатре дома
короч, еще раз - ты решаешь проблему, которая появилась у тебя из того, как ты организовал UI и работу с оным. Внезапно у тебя реализация клиента влияет на бизнес
при этом мои варианты ты называешь негибкими - и в этом я вижу проблему

Maksim
14.10.2018
13:03:14
проблеме при этом не первый день и её давно уже решили

Aleh
14.10.2018
13:03:58
другое дело, что обычно это не нужно или даже нужно не это)

Дмитрий
14.10.2018
13:12:34

Aleh
14.10.2018
13:31:21

Sergey
14.10.2018
13:34:05
сначала была протокурица, потом курирое яйцо и потом уже курица.

First
14.10.2018
13:34:11
Пхпшники, вас можно поздравить?
Rfc с типами на свойство приняли

Sergey
14.10.2018
13:34:42
ты осоздал, мы уже неделю назад это дело обмывали

First
14.10.2018
13:34:51
А де мои одинарные кавычки?

Sergey
14.10.2018
13:35:19
всеравно с типами в пыхе все плохо и будет плохо и ничего не поменяется

First
14.10.2018
13:35:49

Google

First
14.10.2018
13:36:08
Это те, которые встроенны в ядро и не умеют ничего?

Sergey
14.10.2018
13:36:37
типа всеравно придется писать что-то типа
/**
* @var Post[]
*/
private array $posts;

First
14.10.2018
13:36:52
А ты снова про дженерики)
Меня больше угнетает то, что у типов нету объектов

Sergey
14.10.2018
13:37:14
ну просто возможность задать тип для проперти у меня и так была - а возможность проверять в рантайме мне нах не нужна

First
14.10.2018
13:37:25

Sergey
14.10.2018
13:38:38
а не просто синтаксис

First
14.10.2018
13:39:08
Мне вот недавно пришлось снова на пхп пописать денек, как же я горел ?

F01134H
14.10.2018
18:22:38

First
14.10.2018
18:22:46

Aleh
14.10.2018
18:25:03


Yury
14.10.2018
20:39:13
все это - прекондишены а не инварианты.
Блин я все пропустил, но было интересно прочитать дискуссию. Уже поздно, но напишу сейчас.
Вот мой кейс:
Есть рестораны, у них менеджеры. Менеджеры заказывают курьеров. Курьер принимает заказ через телеграм бота. Но вот инвариаты, которые должны не должны провалиться перед действием:
1. Курьер должен быть в XXX минутах от места куда нужно прибыть, на момент когда он принимает заказ.
2. Он должен состоять в одной группе с рестораном (менеджер этого сервиса может исключить курьера из группы, уже после того как курьеру прилетело уведомление о заказе)
3. Банально проверить не взял ли уже другой курьер этот же заказ.
=> нужно, чтобы курьер мог понять все причины, из-за чего у него не получилось взять заказ. Возможно логично, что ему не нужно знать более одной причины. НО тут требование заказчика.
Или вот возможно более явный пример:
Человек оформляет перевод, нужно проверить что тот кому он переводит не заблокирован и разрешает переводы к себе а также проверить, что оставшегося после перевода баланса хватить чтобы погасить ежемесячные расходы(тут не буду углубляться, эта общая суть)
В целом идея, что проверка - это не инвариант - наверное правильная мысль. Типа по какому нибудь CQRS мы можем из команды ничего не возвращать, только прошла операция или нет. А уже потом делать запрос на предмет что именно не так.
.


Sergey
14.10.2018
20:41:25
Блин я все пропустил, но было интересно прочитать дискуссию. Уже поздно, но напишу сейчас.
Вот мой кейс:
Есть рестораны, у них менеджеры. Менеджеры заказывают курьеров. Курьер принимает заказ через телеграм бота. Но вот инвариаты, которые должны не должны провалиться перед действием:
1. Курьер должен быть в XXX минутах от места куда нужно прибыть, на момент когда он принимает заказ.
2. Он должен состоять в одной группе с рестораном (менеджер этого сервиса может исключить курьера из группы, уже после того как курьеру прилетело уведомление о заказе)
3. Банально проверить не взял ли уже другой курьер этот же заказ.
=> нужно, чтобы курьер мог понять все причины, из-за чего у него не получилось взять заказ. Возможно логично, что ему не нужно знать более одной причины. НО тут требование заказчика.
Или вот возможно более явный пример:
Человек оформляет перевод, нужно проверить что тот кому он переводит не заблокирован и разрешает переводы к себе а также проверить, что оставшегося после перевода баланса хватить чтобы погасить ежемесячные расходы(тут не буду углубляться, эта общая суть)
В целом идея, что проверка - это не инвариант - наверное правильная мысль. Типа по какому нибудь CQRS мы можем из команды ничего не возвращать, только прошла операция или нет. А уже потом делать запрос на предмет что именно не так.
1-ое и 2ое вроде как прекондишены а не инварианты. 3-ее - можно проверить но опять же будут ситуации с конкурентным доступом которые ты никак нормально не разрулишь.


Yury
14.10.2018
20:43:05
конкурентным доступом которые ты никак нормально не разрулишь. - блокировки?

Sergey
14.10.2018
20:46:26

Google

Sergey
14.10.2018
20:46:48
и можно ли говорить о инвариантах если состояние не меняется?

Yury
14.10.2018
20:47:44
вот у тебя есть пред условия, пост условия и инварианты. Что есть что?
Вообще множественные инварианты (инвариант как бы по сути не один, но проверок для его удовлетворения несколько) на мой взгляд таких случаев много оч много. Например вот у Вернона есть такие:
https://github.com/VaughnVernon/IDDD_Samples/blob/05d95572f2ad6b85357b216d7d617b27359a360d/iddd_collaboration/src/main/java/com/saasovation/collaboration/domain/model/forum/Forum.java#L79
Я пытаюсь понять, как ты отличаешь пред условия, пост условия и инварианты, на примерах, что есть что и почему? Для меня это все инварианты


Sergey
14.10.2018
21:01:29
инварианты - это когда у нашего объекта есть состояние. И эти самые инварианты - это некие предикаты (утверждения, условия) которые описывают непротиворечивый стэйт этого объекта.
Помимо инвариантов (которые относятся к всему объекту, или системе) есть еще прекондишены и пост кондишены (пред условие - на вход нам нужно подать айдишку юзера, который существует, не заблокирован и все такое. Пост условие - если все хорошо - состояние поменяется определенным образом).
То есть само по себе изменение состотяние - это уже пост условие. Главное что бы при изменении состояния все предикаты описывающие инварианты оставались истинными.
Давай теперь посмотрим на твой пример. У нас есть три предиката, которые должны быть истины на момент заказа курьера:
- курьер должен быть в XXX минутах от места
- курьер должен состоять в группе
- курьер должен быть свободен
Даже если мы каким-то образом проверим все три условия и выплюнем менеджеру ошибку что мол одно из условий нарушено - мы никак не сможем гарантировать что за тот промежуток времени состояние не поменяется еще раз и не произойдет еще ошибки.
Потому я считаю что глупо пытаться оптимизировать эту часть работы, ибо в целом никому от этого удобнее в реальности не будет. Одна ошибка или все три - результат для менеджера один и тот же - он не может передать заказ этому курьеру.
В целом мы всегда можем проверить все три условия отдельно, оставляя лишь пограничные ситуации:
- когда курьер вот-вот отъедит слишком далеко
- курьер вот-вот примет заказ
- курьера вот-вот исключат из группы (как по мне самый маловероятный сценарий из трех)
Что бы все три ивента произошли одновременно (или два из трех) - менеджеру твоему должно сильно Не повести. А если мы говорим о хэппи флоу - можно отдельно проверить все три условия и выплюнуть менеджеру состояние.
В целом, мы вообще не должны отображать ему варианты, которые приведут к нежелательному результату. Синхронизировать стэйт на клиенте у менеджера что бы тот видел сколько кому ехать, кто стал занятым и т.д. Все что бы уменьшить окно по времени когда могут возникать эти вот пограничные ситуации.


Yury
14.10.2018
21:07:50


Sergey
14.10.2018
21:07:53
то есть так же как ты бы делал непосредственно при изменении - ты можешь предоставить отдельные методы для проверки каждого из условий.
Давай теперь посмотрим на твой пример. У нас есть три предиката, которые должны быть истины на момент заказа курьера:
- курьер должен быть в XXX минутах от места
- курьер должен состоять в группе
- курьер должен быть свободен
Даже если мы каким-то образом проверим все три условия и выплюнем менеджеру ошибку что мол одно из условий нарушено - мы никак не сможем гарантировать что за тот промежуток времени состояние не поменяется еще раз и не произойдет еще ошибки.
Потому я считаю что глупо пытаться оптимизировать эту часть работы, ибо в целом никому от этого удобнее в реальности не будет. Одна ошибка или все три - результат для менеджера один и тот же - он не может передать заказ этому курьеру.
В целом мы всегда можем проверить все три условия отдельно, оставляя лишь пограничные ситуации:
- когда курьер вот-вот отъедит слишком далеко
- курьер вот-вот примет заказ
- курьера вот-вот исключат из группы (как по мне самый маловероятный сценарий из трех)
Что бы все три ивента произошли одновременно (или два из трех) - менеджеру твоему должно сильно Не повести. А если мы говорим о хэппи флоу - можно отдельно проверить все три условия и выплюнуть менеджеру состояние.
В целом, мы вообще не должны отображать ему варианты, которые приведут к нежелательному результату. Синхронизировать стэйт на клиенте у менеджера что бы тот видел сколько кому ехать, кто стал занятым и т.д. Все что бы уменьшить окно по времени когда могут возникать эти вот пограничные ситуации.
опять же - в случае чего ты даже блокировками не много чего сможешь добиться поскольку курьер может быть в пределах досигаемости а потом вжух так, все ок, транзакция завершена, вот только интернет у курьера лагнул и оказалось что он уже дальше чем нужно. Скорее всего в этой ситуации твоя система не будет ничего отменять пост фактум, да?


Yury
14.10.2018
21:11:53
Пока оставим что нужно уведомлять о результате всех трех проверок инварианта

Sergey
14.10.2018
21:12:37

Yury
14.10.2018
21:14:45

Sergey
14.10.2018
21:14:52
я выше описал почему считаю это бесполезной затеей. Но тебе никто не мешает сделать 3 проверки и если одна из них зафэйлилась кинуть общее исключение.
которое может уже включать в себя информацию о результатах всех трех ошибок

Yury
14.10.2018
21:15:34
Я только думал как это технически сделать, чтобы норм выглядело
res += isValidFirstCond()
res += isValidSecondCond()
res += isValidThirdCond()
if(res.hasError())
throw ArgException(res.errors)
Как то не оч наверное?

Sergey
14.10.2018
21:17:20
почему нет?
но в целом - я не сталкивался с такими потребностями

Google

Yury
14.10.2018
21:18:01
почему нет?
Когда кода больше с доменными понятиями - то как будто это усложняет понимание и читаемость самой предметной области
Но хотя жертвовать приходится чем то если это реально нужно в редких случаях
Спасибо
Еще последнее

Sergey
14.10.2018
21:19:57

Yury
14.10.2018
21:20:08
А потом создаем VO Name и тоже првоеряем при создании

Sergey
14.10.2018
21:20:26

Yury
14.10.2018
21:20:37

Sergey
14.10.2018
21:20:42
function foo(name: Name, email: Email)
хз) домен твой чистым абсолютно никогда не будет) сам понимаешь)

Yury
14.10.2018
21:21:45

Sergey
14.10.2018
21:21:53
вот если бы ты DSL писал свой - то можно было бы сделать чистый домен.
а так у тебя всегда будут технические штуки в коде

Yury
14.10.2018
21:22:35
нада учить Скалу)