Search
Write a publication
Pull to refresh
9
0.3
Send message

Эти "люди" в лице полутора местных землекопов, очевидно, не умеют готовить ООП.

ООП, как и любая парадигма, действительно требует мыслить в её рамках. Без этого - непонимание и отторжение

если моделируют бизнес требования через FSM, что приводит к комбинаторному взрыву при попытке реализовать все реальные варианты переходов.

FSM очень мощный инструмент, позволяющий решить задачу организации сложного взаимодействия, но да, это не серебряная пуля, не стоит её применять везде, где ни попадя.

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

Ну если люди говорят, тогда да. Не ожидал именно от Вас услышать такой аргумент

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

Чёт в реальном энтерпрайзе, если и есть некоторое количество систем на Haskell, то чисто следовое. Все мучаются с ООП.

Вон даже FSM с гарантиями не построить, как мы видим по примерам выше.

Какие гарантии должны быть у FSM? Отсутствие тупиковых/недостижимых стейтов? Не надо решать несуществующую проблему

Сам концепт ООП нужен для инкапсулирования сложности. Вероятно, есть и другие методы, но ООП выглядит вполне удачным

Подождите, я не понимаю. Как вы разделяете, что идёт в enter «следующего» состояния, а что — в exit «предыдущего»?

Кроме переопределения реакции на внешние стимулы, у каждого стейта есть возможность переопределить действия по переходу в этот стейт и выходу из него вне зависимости от стейта, куда идёт переход (Полезно для управления стейто-контекстными счётчиками итп). В общем случае есть ещё и набор действий, осуществляемых при переходе между конкретными стейтами.

Вот у меня есть, опять же, пусть простой случай — заказ в состоянии Finalized. При переходе в состояние Paid надо проверить, что платёжные реквизиты норм, и выслать письмо покупателю. Что тут куда идёт?

Вызываем у FSM соответствующий метод. FSM вызывает аналогичный у текущего стейта. Если логика предметной части (проверка реквизитов) прошла - стейт инициирует переход в Paid. если не прошла - в Error

Кто такой fsm? Это какой-то класс-менеджер? Инстанс конкретной стейтмашины, построенной по данным бизнес-правилам?

Это инстанс конкретной fsm, с которым собственно и осуществляется взаимодействие. Стейты - приватные классы и видны исключительно внутри fsm

И когда нам захотелось перед done воткнуть стейт saving, придется поменять все классы, которые умели переходить в done, так?

Когда нам захотелось добавить новый стейт, мы:

  • наследуем его, переопределяем, если надо для него enter() и exit() - то что будет обрабатываться при переходе в стейт и покидании его.

  • дополняем fsm методом gotoSaving()

  • реализуем логику перехода в новый стейт, там, где это надо по задаче. Например, в некоторых местах где gotoDone() теперь будет gotoSaving()

Всё.
З.Ы. Мне кажется, что наша беседа имеет некоторый привкус вкусовщины. Безусловно, на любом языке можно реализовать что угодно, и на вкус и цвет все фломастеры ...
Предлагаю сойтись на тезисе, что FSM решает множество проблем и их применение в подавляющем большинстве случаев оправдано. Отдельно хочу отметить необходимость следования парадигме языка, который используется.

На каждый стейт по классу?

Именно так. Мы же хотим переопределять поведение в зависимости от стейта. Фактически заводим объекту FSM вторую VTable

Человек прекрасно использует fsm с ООП, не беспокойтесь. Просто представьте, что поведение fsm определяется методами стейтов, которые за счёт полиморфизма наследования меняют свою реакцию на евенты. Никакого прямого изменения стейтов нет. Состояние скрыто. Конструкция банальна.

Можно набросать соответствующую стейтмашину на чистом ООП?

Я не знаю haskell и поэтому не приведу Вам аналогичный пример. Но да, очевидно можно, если приведённый код делает что-либо осмысленное

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

И никакого здравствуй. Новое состояние описывает только реакцию объекта, которое fsm в этом состоянии осуществляет.
Напоминаю, что стейты наследуются - у нас же ООП и силами полиморфизма определяется поведение fsm в данном стейте

Ну значит, вам придется защищаться от рефлексии, от аспектов, а еще нарисовать не поддающегося никакому когнитивному анализу макаронного монстра в setStatus.

Ничего из перечисленного мне не встречалось. А вместо setStatus(Status newStatus_) вполне уместны условные setError(), setIdle() и подобные. (Это если совсем примитивизировать - а на практике ещё и наборы для enter, exit определённые у классов иерархии state и transit у самой fsm)
Уж чего чего, а Его Макаронность, ООП как раз отлично структурирует в отличие от

Мой опыт подсказывает, что если вы думаете, то вам нужен конечный автомат, то скорее всего вам не нужен конечный автомат. 

Мой опыт подсказывает обратное - везде где встречается сколь угодно отличная от нуля сложность - конечный автомат или их композиция делает систему прогнозируемой и отлаживаемой

Иначе это просто поле status из базы, которое может поменять как угодно кто угодно.

Хорошо, пусть будет status (правда не пойму причём здесь база). И как кто угодно собирается поменять его значение, если оно private? Инкапсуляцию никто не отменял

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

Реализовывал и реализовываю. Подвоха не заметил. Поясните плз, может я чёго-то упускаю?

Может я чего-то и упустил, но тогда Вы говорите о состоянии заказа а не о самом заказе. ООП как раз исходит из сокрытия состояния.

Order1 = pay(Order)

и в функции pay() мы скопируем всё, начиная с австро-прусской войны, включая состав заказа, плательщика-получателя, менеджеров, которые его ведут и прочие погоды на Марсе, важные для прикладной задачи.

Обычно это делают с помощью конечных автоматов.

fsm и ООП никоим образом не противоречат друг другу, а наоборот, очень гармонично взаимно дополняют. А что с хранением истории заказа?

Потому что новый заказ и оплаченный заказ — это две абсолютно разные сущности

Ага, как и ЧастичноОплаченныйЧастичноСобранныйЧастичноОтгруженныйЧастичноВозвращённыйЧастичноОтменённыйИтпИтд заказ.
Статус оплаты - один из атрибутов заказа, коих может быть очень много в реальной системе.
Сколько видов сущностей надо завести под все возможные сочетания состояний заказа? Как установить между ними всеми связи?

Так вроде снижение ментальной нагрузки - это как раз плюс. Вон у brainfuck ментальная нагрузка о-го-го какая, но чёт на нём никто особо крупных систем не замечено ))

А кто ж тогда живёт в methodDictionary ? ))

Можно было бы также обсудить и сам вызов методов через точку, появившийся еще в Smalltalk в 1970-ых годах, откуда он и перекочевал в большинство современных языков.

В Smalltalk никакого вызова метода через точку нет.

Хотя в смоллтоковском ООП, (не использующем наследования)

Как это Smalltalk без наследования? Там всё на этом построено!

Могу только посоветовать аффвтору ознакомиться с "Серебряной пули нет" Брукса

Information

Rating
3,856-th
Registered
Activity