Re[58]: Haskell нужен! (в Standard Chartered Bank)
От: Sinclair Россия https://github.com/evilguest/
Дата: 26.02.15 14:20
Оценка: 72 (2) +2
Здравствуйте, jazzer, Вы писали:

J>да нету никакого кода в load_order, самый обычный код, возвращающий самый обычный order безо всяких свойств.

J>Все интересное начинается потом, когда ты собираешься что-то с ордером делать — а функции, которые ты собираешься звать, требуют те или иные установленные свойства.
И, простите, чем это отличается от нашего нынешнего кода, где изо всех типов есть только самый обычный ордер, безо всяких "свойств"?

У меня весь workflow состоит из вот таких шагов:
— поднять ордер из базы
— попытаться двинуться на шаг вперёд
— сохранить ордер в базу (не нужно, если transition failed).

J>Как именно проверяются свойства — см. PROP_IF в моем большом посте. И пример (там же) тела функции try_to_change_amount, которая пытается вызвать функцию increase_amount, но та требует наличия свойств HasRisk:false и Shipped:false и не дает себя звать без предварительной проверки оных.


J>Если что-то непонятно — спрашивай.

Непонятно, в чём бенефит статической типизации. Я могу описать функцию increase_amount вот так:
public void Order increase_amount(Order order, Money newAmount)
{
  Contracts.Assert(order, (o)=> !o.HasRisk); // выбросим исключение!
  Contracts.Assert(order, (o)=> !o.Shipped); // выбросим исключение!

  Contracts.Assert(order, (o)=> newAmount <= 1.20 * o.CurrentAmount) // выбросим исключение!

  return order.Clone().SetAmount(newAmount);
}

А могу — вот так:
public void Order<Risk.None, Shipped.None> increase_amount(Order<Risk.None, Shipped.None> order, Money newAmount)
{
  Contracts.Assert(order, (o)=> newAmount <= 1.20 * o.CurrentAmount) // выбросим исключение!
  return order.Clone().SetAmount(newAmount);
}


Вся разница — в том, что теперь в try_increase_amount мне придётся провести корректное приведение типов:
public void Order try_increase_amount(Order order, Money newAmount)
{
  var o = checkNoRisk(order); // выбросим исключение, если есть риск, вернём Order<Risk.None, S> иначе
  var o2 = checkNotShipped(o); // выбросим исключение, если зашиплен, вернём Order<Risk.None, Shipped.None> иначе

  return increase_amount(order // не компилируется
                         o // не компилируется
                         o2, newAmount); // ура, компилируется!!!
}

Но мы наблюдаем те же яйца, вид сбоку. Всё, try_increase_amount — это наш верхний уровень, мы не можем ничего доказать за её пределами.
У нас совершенно нормально иметь workflow, в котором мы пытаемся увеличить amount у уже отправленного ордера. Потому что компилятор видит ровно один шаг этого workflow.
В итоге, мы написали кучу кода, напрягли компилятор, но никак не улучшили поведение системы. У нас уже и так increase_amount была вполне локальна — все бизнес-правила выписаны в начале, шансы напортачить в них минимальны. Ну вынесли мы требования к флагам из тела в сигнатуру — так ведь нам это никак не помогло!



J>ЗЫ Серьезно, складывается впечатление, что ты читаешь мои ответы через раз и по диагонали. Очень неприятно.

А у меня наоборот — складывается впечатление, что ты отвечаешь не на те вопросы, которые я задаю.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.