Re[54]: [C++] о паттернах (доп.)
От: Sharad-Waador  
Дата: 08.06.11 21:04
Оценка:
Здравствуйте, samius, Вы писали:

SW>>Это твоя логика, а не моя и похоже, с тобой вообще не о чем говорить, т.к. про автоматы Мура ты только слышал. При получении сигнала Open реакцией будет смена состояния, а не выходной сигнал Close !!!

S>Ты же утверждал что реакция будет зависеть от состояния? Это ведь не я утверждал.

Не нужно передёргивать. "По твоей логике реакцией на входной сигнал Open будет тоже Close" это твои слова и я этого не говорил.

P.S. Можно закругляться, поскольку очевидно, что ты начал спорить со своими передёргиваниями.
Re[55]: [C++] о паттернах (доп.)
От: samius Япония http://sams-tricks.blogspot.com
Дата: 08.06.11 22:15
Оценка:
Здравствуйте, Sharad-Waador, Вы писали:

SW>Здравствуйте, samius, Вы писали:


SW>Ты использовал пустое по смыслу сообщение как аргумент да еще хватило наглости заявлять что оно фальсифицируемо

Я его использовал в ответ на твое пустое, да еще и не имеющее отношеие к IoC.

SW>>>Последняя разница — в конкретной реализации State входные сигналы могут быть совмещены с выходными.

SW>>>То есть,
SW>>>в состоянии открыто
SW>>> Open даёт исключение,
SW>>> Close закрывает и переключает состояние на закрыто,
SW>>> Send отсылает
SW>>>в состоянии закрыто
SW>>> Open открывает и переключает в состояние открыто,
SW>>> Close дает исключение,
SW>>> Send дает исключение
SW>>>- классика Мили с учетом особенности State.

SW>я ошибся "классика Мура" а не Мили, т.к. речь про Муа.

Ты еще и в этом ошибся, а я не заметил.
SW>По ссылке :"В State в классической реализации выходной сигнал зависит только от состояния."
SW>С этим сообщением все в порядке — каждый из выходных сигналов зависит только от состояния и ничего больше. Если состояние открыто, то сигнал Close всегда будет функцией закрытия, сигнал Open всегда будет функцией которая бросает исключение и тд. И ни от чего более эти сигналы не зависят — ни от чего, кроме как от состояния.
А теперь совсем для детского сада: я выделил выходные сигналы курсивом, а то от чего они зависят — жирным.

SW>P.S. Похоже ты и вправду не понимаешь, что такое автомат Мура. Если тебе понятно написаное здесь, считай что ты понял автомат Мура. Это снова диагноз.

Симптомы в карточку: пациент описывает автомат Мили и утверждает что это автомат Мура. Ставит диагнозы.
Re[55]: [C++] о паттернах (доп.)
От: samius Япония http://sams-tricks.blogspot.com
Дата: 08.06.11 22:15
Оценка:
Здравствуйте, Sharad-Waador, Вы писали:

SW>Здравствуйте, samius, Вы писали:


SW>>>Это твоя логика, а не моя и похоже, с тобой вообще не о чем говорить, т.к. про автоматы Мура ты только слышал. При получении сигнала Open реакцией будет смена состояния, а не выходной сигнал Close !!!

S>>Ты же утверждал что реакция будет зависеть от состояния? Это ведь не я утверждал.

SW>Не нужно передёргивать. "По твоей логике реакцией на входной сигнал Open будет тоже Close" это твои слова и я этого не говорил.

Сказанное мной является следствием из твоего отрицания зависимости выхода от чего либо, кроме состояния. И не является истиной.

SW>P.S. Можно закругляться, поскольку очевидно, что ты начал спорить со своими передёргиваниями.

Очевидно, что понятия 'импликация' и 'логика высказываний' тебе чужды.
Re[35]: [C++] о паттернах
От: vdimas Россия  
Дата: 08.06.11 22:29
Оценка: +1
Здравствуйте, Sharad-Waador, Вы писали:

SW>Определяйся, я ж только за.


Да просто не с той стороны зашли. Попробуй еще раз. Только надо держать в памяти, что всегда есть однозначное взаимное преобразование модели Мили в Мура и наоборот. Эквивалентные автоматы Мили и Мура со стороны наблюдателя ведут себя одинаково. Разница только в способе исполнения внутри. Т.е. состояние тут вторично, суть подробность реализации. Автомат отличается от обычного функционального преобразователя лишь тем, что его ф-ия зависит не только от входного сигнала, но и от истории предыдущих входных сигналов... Но!!! Особенностью Мили является то, что в его классическом абстрактном представлении, сигнал на выходе появляется лишь когда есть сигнал на входе. Это логично для функционального преобразователя (наоборот, автомат Мура всегда "помнит" текущий выходной сигнал, это как бы побочный эффект). Это единственное важное отличие имеющее отношение к обсуждаемому. Двигаемся далее. В ООП аналог сигнала — это вызовы методов. Абстрактные методы State — это способы подать сигнал на автомат, т.е. его входной алфавит. Происходящая полезная логика внутри, т.е. вызовы других полезных методов других объектов — всё это можно принять как выходные сигналы нашего автомата. Мне представляется, что в этой схеме выходные сигналы появляются в те моменты, когда есть входные. Не? Более того, даже не меняя текущего состояния State, разные входные сигналы в общем случае генерят разные выходные сигналы. Такая подробность реализации и есть классическая автоматная модель. Т.е. та которая Мили. Ибо Мура — это упрощенная модель от исходной, со своими недостатками, например, в общем случае на X входных сигналов и Y состояний Мили, после преобразования можем получить X*Y состояний Мура.

Поэтому, если делаем Мура и видим, что у нас много входных сигналов и и очень ветвистый граф переходов по ним (т.е. много уникальных вычислений выходного сигнала), стоит подумать о Мили. И паттерне State как программной реализации.
Re[36]: [C++] о паттернах
От: samius Япония http://sams-tricks.blogspot.com
Дата: 08.06.11 23:59
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, Sharad-Waador, Вы писали:


SW>>Определяйся, я ж только за.


V>Особенностью Мили является то, что в его классическом абстрактном представлении, сигнал на выходе появляется лишь когда есть сигнал на входе. Это логично для функционального преобразователя (наоборот, автомат Мура всегда "помнит" текущий выходной сигнал, это как бы побочный эффект). Это единственное важное отличие имеющее отношение к обсуждаемому.

Можно сформулировать иначе: у Мили выходной сигнал приписывается к переходу (возможно к петле), а у Мура к вершине(состоянию).

V>Поэтому, если делаем Мура и видим, что у нас много входных сигналов и и очень ветвистый граф переходов по ним (т.е. много уникальных вычислений выходного сигнала), стоит подумать о Мили. И паттерне State как программной реализации.

Можно поднять вопрос, что именно считать классической реализацией State?
а) Мур
Если мы хотим получить Send на выходе, у нас должно быть спецсостояние, помнящее выходной сигнал Send.
б) Мили
Выходной сигнал Send получается при проходе по ребру 'Send', которое ведет из состояние Open в него же.
В GoF реализован именно Мили по следующим признакам
* нет состояния для выходного сигнала Send.
* выходные сигналы Close и Send могут быть получены при получении соответствующих сигналов на входе, находясь в состоянии Open.
* выходные сигналы подаются из методов входящих сигналов. Например, в моей русской книге есть такой фрагмент кода:
void TCPClosed::ActiveOpern (TCPConnection* t) {
   // послать SYN, получить SYN, ACK и т.д.

   ChangeState(t, TCPEstablished::Instance());
}

По всей видимости комментарий отвечает за полезный выходной сигнал.

Считать ли GoF классикой? Склоняюсь к тому что да.
Видел ли кто-либо реализацию State на автомате Мура в книгах? Не исключаю, хотя сам лично не видел.
Re[37]: [C++] о паттернах
От: vdimas Россия  
Дата: 09.06.11 01:29
Оценка:
Здравствуйте, samius, Вы писали:

V>>Особенностью Мили является то, что в его классическом абстрактном представлении, сигнал на выходе появляется лишь когда есть сигнал на входе. Это логично для функционального преобразователя (наоборот, автомат Мура всегда "помнит" текущий выходной сигнал, это как бы побочный эффект). Это единственное важное отличие имеющее отношение к обсуждаемому.

S>Можно сформулировать иначе: у Мили выходной сигнал приписывается к переходу (возможно к петле), а у Мура к вершине(состоянию).

Можно, но это формулировка с обратной стороны, со стороны подробностей реализации. Со стороны же постановки задачи, автомат — это ф-ия, значение выхода которой зависит от входного значения и от истории предыдущих входных значений. При таком взгляде на вещи естественно ожидать, что выход у ф-ии наблюдается только при возбуждении входа.

S>Можно поднять вопрос, что именно считать классической реализацией State?

S>а) Мур
S>Если мы хотим получить Send на выходе, у нас должно быть спецсостояние, помнящее выходной сигнал Send.
S>б) Мили
S>Выходной сигнал Send получается при проходе по ребру 'Send', которое ведет из состояние Open в него же.

Паттерн удачно обходит эти подробности, сосредотачиваясь на собственно трюке диспетчеризации входа через vtable. Паттерн избавляет от вложенных switch/case.

В реальном коде вряд ли строго выделяют входные и выходные сигналы. И это иногда ведет к проблемам, например к сложности тестирования. Что делать я уже писал чуть выше — это вводить сурогатные сигналы, по которым работает внешняя схема, устанавливающая конкретный экземляр State. Эта внешняя схема может быть выполнена как угодно. Например как автомат Мура. Или опять как Мили. Главное, что логику смены состояний можно отладить без воссоздания сложного окружения, которое дергается "полезными" сигналами.

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

S>В GoF реализован именно Мили по следующим признакам


ИМХО, там просто дан иллюстративный пример, чтобы читатель понял, в чем суть трюка.

S>
S>void TCPClosed::ActiveOpern (TCPConnection* t) {
S>   // послать SYN, получить SYN, ACK и т.д.

S>   ChangeState(t, TCPEstablished::Instance());
S>}
S>

S>По всей видимости комментарий отвечает за полезный выходной сигнал.

Да, за полезный. У нас же пара выходных значений: это полезный сигнал + код следующего состояния. Но сам пример — образец того, как не надо делать в сложных случаях. Лучше не менять состояние самому, а сгенерировать некое событие Established. А текущий State пусть меняет некий внешний автомат. Это удобнее, потому как в сложных случаях довольно много получается идентичных State, отличающихся только кодом, отвечающим за переход в следующее состояние. Или даже вообще никакого полезного кода кроме перехода в следующее состояние. Брр... Такая схема гораздо неудобнее табличной, бо слишком много буков из-за ерунды. Вот для сравнения в табличном виде: http://www.rsdn.ru/forum/flame.comp/4134557.1.aspx
Автор: vdimas
Дата: 28.01.11
На шарпе тоже похожим образом переопределял операторы и тоже не хуже декларативность выходила.

Я бы декомпозировал схему на две части: это генерящую полезный сигнал (именно это мне почему-то и подразумевается под "поведением") и осуществляющую переходы по состояниям. Я уже замечал, что разным состояниям может соответствовать одинаковое полезное поведение. Зачем дублировать полезную логику и засорять ее подробностями перехода из состояние в состояние?

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

S>Считать ли GoF классикой? Склоняюсь к тому что да.

S>Видел ли кто-либо реализацию State на автомате Мура в книгах? Не исключаю, хотя сам лично не видел.

Дык, если в рассмотрении оставить только вычисление следующего State, то в примерах GoF — это автомат Мура.
Там пример неудачный, замыливает цимус паттерна. Нужно было просто нарисовать что-нить простое из 3-х состояний и 3-х выходов на switsh/case или ифах, и рядом для сравнения на State.
Re[56]: [C++] о паттернах (доп.)
От: Sharad-Waador  
Дата: 09.06.11 09:36
Оценка:
Здравствуйте, samius, Вы писали:

SW>>Не нужно передёргивать. "По твоей логике реакцией на входной сигнал Open будет тоже Close" это твои слова и я этого не говорил.

S>Сказанное мной является следствием из твоего отрицания зависимости выхода от чего либо, кроме состояния. И не является истиной.

Сказаное является твоим передёргиванием.

SW>>P.S. Можно закругляться, поскольку очевидно, что ты начал спорить со своими передёргиваниями.

S>Очевидно, что понятия 'импликация' и 'логика высказываний' тебе чужды.

Поменьше передёргивай и всё будет в порядке.
Re[38]: [C++] о паттернах
От: samius Япония http://sams-tricks.blogspot.com
Дата: 09.06.11 09:36
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, samius, Вы писали:


S>>Можно сформулировать иначе: у Мили выходной сигнал приписывается к переходу (возможно к петле), а у Мура к вершине(состоянию).


V>Можно, но это формулировка с обратной стороны, со стороны подробностей реализации. Со стороны же постановки задачи, автомат — это ф-ия, значение выхода которой зависит от входного значения и от истории предыдущих входных значений.

Формально речь идет не об истории предыдущих входных значений, а о функции , которая имеет те же аргументы, что и функция перехода
V>При таком взгляде на вещи естественно ожидать, что выход у ф-ии наблюдается только при возбуждении входа.
Верно, но так же верно считать что выход наблюдается при тех же условиях, при которых наблюдается переход.

S>>Можно поднять вопрос, что именно считать классической реализацией State?

S>>а) Мур
S>>Если мы хотим получить Send на выходе, у нас должно быть спецсостояние, помнящее выходной сигнал Send.
S>>б) Мили
S>>Выходной сигнал Send получается при проходе по ребру 'Send', которое ведет из состояние Open в него же.

V>Паттерн удачно обходит эти подробности, сосредотачиваясь на собственно трюке диспетчеризации входа через vtable. Паттерн избавляет от вложенных switch/case.

Эти особенности вне паттерна. Если представить некоторую black box реализацию (неважно, диспетчеризация ли через vtable, табличная, или на switch-ах) с событиями StateChanged(s) и Transited(e), то то, на какие события мы подпишемся, и будет определять модель автомата.

V>В реальном коде вряд ли строго выделяют входные и выходные сигналы. И это иногда ведет к проблемам, например к сложности тестирования. Что делать я уже писал чуть выше — это вводить сурогатные сигналы, по которым работает внешняя схема, устанавливающая конкретный экземляр State. Эта внешняя схема может быть выполнена как угодно. Например как автомат Мура. Или опять как Мили. Главное, что логику смены состояний можно отладить без воссоздания сложного окружения, которое дергается "полезными" сигналами.

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

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

да

S>>В GoF реализован именно Мили по следующим признакам


V>ИМХО, там просто дан иллюстративный пример, чтобы читатель понял, в чем суть трюка.

да

S>>По всей видимости комментарий отвечает за полезный выходной сигнал.


V>Да, за полезный. У нас же пара выходных значений: это полезный сигнал + код следующего состояния.

Код следующего состояния является полезным только как внутреннее знание автомата. Полезным же выходом является либо в случае Мили, либо в случае Мура.
V>Но сам пример — образец того, как не надо делать в сложных случаях. Лучше не менять состояние самому, а сгенерировать некое событие Established. А текущий State пусть меняет некий внешний автомат. Это удобнее, потому как в сложных случаях довольно много получается идентичных State, отличающихся только кодом, отвечающим за переход в следующее состояние. Или даже вообще никакого полезного кода кроме перехода в следующее состояние. Брр... Такая схема гораздо неудобнее табличной, бо слишком много буков из-за ерунды. Вот для сравнения в табличном виде: http://www.rsdn.ru/forum/flame.comp/4134557.1.aspx
Автор: vdimas
Дата: 28.01.11
На шарпе тоже похожим образом переопределял операторы и тоже не хуже декларативность выходила.

Вижу что callback-и привязаны к состояниям, т.е. это Мур.
Я тоже ушел от State паттерна к табличным автоматам. Только мой код позволял юзать смешанные модели (генерить события по смене состояния и по переходу). Получалось менее лаконично, чем у тебя, но позволял добавлять подписчиков на события вне описания логики переходов. Смешанные модели не очень практичны в том смысле, что в них легко запутаться. Но довольно удобно иметь один фреймворк и для тех и для других моделей.
Представь вместо:
ServerState 
    init        = { onInit,       { success>wait_hello, other>closed } },
    wait_hello  = { NULL,         { hello>hello_reply, other>closing } },

Следующее:
ServerState 
    init        = { onInit,  { make_transition(success, wait_hello, onInitSuccess), other>closed } },
    wait_hello  = { NULL,    { make_transition(hello, hello_reply, onWaitHelloHello), other>closing } },

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

V>Я бы декомпозировал схему на две части: это генерящую полезный сигнал (именно это мне почему-то и подразумевается под "поведением") и осуществляющую переходы по состояниям. Я уже замечал, что разным состояниям может соответствовать одинаковое полезное поведение. Зачем дублировать полезную логику и засорять ее подробностями перехода из состояние в состояние?


V>Т.е. еще раз русским языком. В телах State удобно вычислять только полезный сигнал. Часть этого полезного сигнала может быть предназначена для схемы, управляющей самим паттерном State.

Согласен. Полезный сигнал часто удобно повесить сверху на события. Но иногда — нет. Предположим что сигнал Send имеет параметры, которые нужно передать вместе с выходным сигналом. Вариантов масса — можно навернуть иерархию наследования для сигналов (c ADT конечно проще), но изящнее будет добавить к методу Send параметр, который в теле будет перенаправлен на выход.

S>>Считать ли GoF классикой? Склоняюсь к тому что да.

S>>Видел ли кто-либо реализацию State на автомате Мура в книгах? Не исключаю, хотя сам лично не видел.

V>Дык, если в рассмотрении оставить только вычисление следующего State, то в примерах GoF — это автомат Мура.

Т.е. если оставить закомментированную часть закомментированной Ну дак а какая будет с него польза, если на физическое соединение не пойдет сигнал?
V>Там пример неудачный, замыливает цимус паттерна. Нужно было просто нарисовать что-нить простое из 3-х состояний и 3-х выходов на switsh/case или ифах, и рядом для сравнения на State.
Тогда бы они получили обвинение в том что паттерн хорош только для <= 3х состояний. А это, ИМХО, действительно так.
Re[56]: [C++] о паттернах (доп.)
От: Sharad-Waador  
Дата: 09.06.11 09:40
Оценка:
Здравствуйте, samius, Вы писали:

SW>>По ссылке :"В State в классической реализации выходной сигнал зависит только от состояния."

SW>>С этим сообщением все в порядке — каждый из выходных сигналов зависит только от состояния и ничего больше. Если состояние открыто, то сигнал Close всегда будет функцией закрытия, сигнал Open всегда будет функцией которая бросает исключение и тд. И ни от чего более эти сигналы не зависят — ни от чего, кроме как от состояния.
S>А теперь совсем для детского сада: я выделил выходные сигналы курсивом, а то от чего они зависят — жирным.

Ты снова передёргиваешь. Я понятно указал, где какие сигналы : "...то сигнал Close всегда будет функцией закрытия".

SW>>P.S. Похоже ты и вправду не понимаешь, что такое автомат Мура. Если тебе понятно написаное здесь, считай что ты понял автомат Мура. Это снова диагноз.

S>Симптомы в карточку: пациент описывает автомат Мили и утверждает что это автомат Мура. Ставит диагнозы.

Я описал автомат Мура и промахнулся в одном месте когда написал "мили". Именно в автомате Мура выходные сигналы зависят только от состояния и больше ни от чего.
Re[37]: [C++] о паттернах
От: Sharad-Waador  
Дата: 09.06.11 09:46
Оценка:
Здравствуйте, samius, Вы писали:

V>>Особенностью Мили является то, что в его классическом абстрактном представлении, сигнал на выходе появляется лишь когда есть сигнал на входе. Это логично для функционального преобразователя (наоборот, автомат Мура всегда "помнит" текущий выходной сигнал, это как бы побочный эффект). Это единственное важное отличие имеющее отношение к обсуждаемому.

S>Можно сформулировать иначе: у Мили выходной сигнал приписывается к переходу (возможно к петле), а у Мура к вершине(состоянию).

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

S>
S>void TCPClosed::ActiveOpern (TCPConnection* t) {
S>   // послать SYN, получить SYN, ACK и т.д.

S>   ChangeState(t, TCPEstablished::Instance());
S>}
S>

S>По всей видимости комментарий отвечает за полезный выходной сигнал.

Ты сам то думай — в состоянии TCPClosed Open всегда будет "послать SYN, получить SYN, ACK и т.д". И никогда ни при каком условии Open не станет Close или чем то другим.
Re[36]: [C++] о паттернах
От: Sharad-Waador  
Дата: 09.06.11 09:52
Оценка: -1
Здравствуйте, vdimas, Вы писали:

V>Особенностью Мили является то, что в его классическом абстрактном представлении, сигнал на выходе появляется лишь когда есть сигнал на входе. Это логично для функционального преобразователя (наоборот, автомат Мура всегда "помнит" текущий выходной сигнал, это как бы побочный эффект). Это единственное важное отличие имеющее отношение к обсуждаемому. Двигаемся далее. В ООП аналог сигнала — это вызовы методов.


Входной сигнал — это вызов метода и его параметры. Выходной — это сам метод. То есть, для кодирования выходных сигналов используется не 0 и 1, а n-бит — сам метод. Количество разных Close может быть сколько угодно, это можно рассматривать как разные уровни, не 0 и 1, а "throw ...", "performCloseInternal()" и так далее.
Re[38]: [C++] о паттернах
От: samius Япония http://sams-tricks.blogspot.com
Дата: 09.06.11 09:53
Оценка:
Здравствуйте, Sharad-Waador, Вы писали:

SW>Здравствуйте, samius, Вы писали:


V>>>Особенностью Мили является то, что в его классическом абстрактном представлении, сигнал на выходе появляется лишь когда есть сигнал на входе. Это логично для функционального преобразователя (наоборот, автомат Мура всегда "помнит" текущий выходной сигнал, это как бы побочный эффект). Это единственное важное отличие имеющее отношение к обсуждаемому.

S>>Можно сформулировать иначе: у Мили выходной сигнал приписывается к переходу (возможно к петле), а у Мура к вершине(состоянию).

SW>Вот, начинаешь понимать. Как только поймешь, что один из выходных сигналов это функция, тебе сразу станет ясно, что к чему.

Я даже не понял что ты написал.

SW>Ты сам то думай — в состоянии TCPClosed Open всегда будет "послать SYN, получить SYN, ACK и т.д". И никогда ни при каком условии Open не станет Close или чем

то другим.
В состоянии TCPClosed Open всегда будет посылать "SYN и т.п."
В состоянии TCPClosed Send всегда будет посылать throw

Ты не видишь зависимость выхода от входного сигнала? На всякий случай, я вижу такую зависимость.
Re[38]: [C++] о паттернах
От: Sharad-Waador  
Дата: 09.06.11 09:55
Оценка: -1
Здравствуйте, vdimas, Вы писали:

V>Да, за полезный. У нас же пара выходных значений: это полезный сигнал + код следующего состояния. Но сам пример — образец того, как не надо делать в сложных случаях. Лучше не менять состояние самому, а сгенерировать некое событие Established. А текущий State пусть меняет некий внешний автомат.


Вот тогда и получится автомат Мили.

V>Т.е. еще раз русским языком. В телах State удобно вычислять только полезный сигнал.


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

V>Дык, если в рассмотрении оставить только вычисление следующего State, то в примерах GoF — это автомат Мура.


Samius: "И ты, Брут !"
Re[39]: [C++] о паттернах
От: samius Япония http://sams-tricks.blogspot.com
Дата: 09.06.11 10:02
Оценка: +1
Здравствуйте, Sharad-Waador, Вы писали:

SW>Здравствуйте, vdimas, Вы писали:



V>>Дык, если в рассмотрении оставить только вычисление следующего State, то в примерах GoF — это автомат Мура.


SW>Samius: "И ты, Брут !"

Ты еще и за меня будешь тезисы вставлять? Если ты еще не понял, то твоя позиция относительно Мура противостоит тому, о чем пишет vdimas. Если убрать выходной сигнал, то различий между моделями не будет.
Re[39]: [C++] о паттернах
От: Sharad-Waador  
Дата: 09.06.11 10:13
Оценка: -1
Здравствуйте, samius, Вы писали:

SW>>Ты сам то думай — в состоянии TCPClosed Open всегда будет "послать SYN, получить SYN, ACK и т.д". И никогда ни при каком условии Open не станет Close или чем

S>то другим.
S>В состоянии TCPClosed Open всегда будет посылать "SYN и т.п."
S>В состоянии TCPClosed Send всегда будет посылать throw

S>Ты не видишь зависимость выхода от входного сигнала? На всякий случай, я вижу такую зависимость.


Выход автомата это не "посылать throw", а конкретный набор Open, Close, Send. Они не зависят от входа, а только от состояния.
Re[40]: [C++] о паттернах
От: Sharad-Waador  
Дата: 09.06.11 10:15
Оценка:
Здравствуйте, samius, Вы писали:

V>>>Дык, если в рассмотрении оставить только вычисление следующего State, то в примерах GoF — это автомат Мура.


SW>>Samius: "И ты, Брут !"

S>Ты еще и за меня будешь тезисы вставлять? Если ты еще не понял, то твоя позиция относительно Мура противостоит тому, о чем пишет vdimas. Если убрать выходной сигнал, то различий между моделями не будет.

Если убрать выходной сигнал, то автомат вообще не нужен, ни Мура, ни Мили ни любой другой.
Re[40]: [C++] о паттернах
От: samius Япония http://sams-tricks.blogspot.com
Дата: 09.06.11 10:33
Оценка:
Здравствуйте, Sharad-Waador, Вы писали:

SW>Здравствуйте, samius, Вы писали:


SW>>>Ты сам то думай — в состоянии TCPClosed Open всегда будет "послать SYN, получить SYN, ACK и т.д". И никогда ни при каком условии Open не станет Close или чем

S>>то другим.
S>>В состоянии TCPClosed Open всегда будет посылать "SYN и т.п."
S>>В состоянии TCPClosed Send всегда будет посылать throw

S>>Ты не видишь зависимость выхода от входного сигнала? На всякий случай, я вижу такую зависимость.


SW>Выход автомата это не "посылать throw", а конкретный набор Open, Close, Send. Они не зависят от входа, а только от состояния.

ладно, фиг с ним со throw.

Попрошу тебя набросать тело функции, которая только по состоянию формирует управляющие команды для System.Net.Sockets.TcpClient.

void Handle(TCPState state)
{
    ...
    ...
           this.tcpClient.Connect(/*неважно*/);
    ...
    ...
           this.tcpClient.GetStream().WriteByte(10);

    ...
    ...     
           this.tcpClient.Close();
}


Ты утверждаешь, что кроме состояния тебе ничего не нужно. Значит не составит труда без знания о входе набросать черновик такой функции.
Re[39]: [C++] о паттернах
От: vdimas Россия  
Дата: 09.06.11 10:42
Оценка:
Здравствуйте, samius, Вы писали:

V>>Можно, но это формулировка с обратной стороны, со стороны подробностей реализации. Со стороны же постановки задачи, автомат — это ф-ия, значение выхода которой зависит от входного значения и от истории предыдущих входных значений.

S>Формально речь идет не об истории предыдущих входных значений, а о функции , которая имеет те же аргументы, что и функция перехода

Это конкретная модель автомата, а их же несколько. Речь о том, что автомат во время постановки задачи — черный ящик. А его конкретная модель реализация — это уже из анализа требований/сценариев выходит, никак не раньше. Не факт, что получится запихнуть сценарий в КА, иногда приходится использовать магазинные автоматы. Иногда проще сделать комбинированный автомат, чем "монолитный".

V>>При таком взгляде на вещи естественно ожидать, что выход у ф-ии наблюдается только при возбуждении входа.

S>Верно, но так же верно считать что выход наблюдается при тех же условиях, при которых наблюдается переход.

Переход-то не всегда. Петля хоть и нарисована в графе, но это — математическая абстракция. Нет зачастую никакого перехода в реализации — пустая ячейка таблицы. Эффективности ради. В общем, мое ИМХО исключительно в том, что нельзя плясать от реализации. Внешнему коду всё-равно пофиг, что и как у нас там внутри.

V>>Паттерн удачно обходит эти подробности, сосредотачиваясь на собственно трюке диспетчеризации входа через vtable. Паттерн избавляет от вложенных switch/case.

S>Эти особенности вне паттерна. Если представить некоторую black box реализацию (неважно, диспетчеризация ли через vtable, табличная, или на switch-ах) с событиями StateChanged(s) и Transited(e), то то, на какие события мы подпишемся, и будет определять модель автомата.

Ниче не понял, насчет как это будет определять модель автомата. И почему это осообеность диспетчеризации входа через vtable — вне паттерна? Сам паттерн только об этом трюке и больше ни о чем, вообще-то. Остальное мы пририсовываем рядом и жестоко спорим.

V>>Да, за полезный. У нас же пара выходных значений: это полезный сигнал + код следующего состояния.

S>Код следующего состояния является полезным только как внутреннее знание автомата.

Это я прокомментировал приведенный тобой сниппет (отрывок из примера в GoF).

S>Полезным же выходом является либо в случае Мили, либо в случае Мура.


А в случае автономного? А магазинного? А обобщенного автомата? А составного?

V>>Но сам пример — образец того, как не надо делать в сложных случаях. Лучше не менять состояние самому, а сгенерировать некое событие Established. А текущий State пусть меняет некий внешний автомат. Это удобнее, потому как в сложных случаях довольно много получается идентичных State, отличающихся только кодом, отвечающим за переход в следующее состояние. Или даже вообще никакого полезного кода кроме перехода в следующее состояние. Брр... Такая схема гораздо неудобнее табличной, бо слишком много буков из-за ерунды. Вот для сравнения в табличном виде: http://www.rsdn.ru/forum/flame.comp/4134557.1.aspx
Автор: vdimas
Дата: 28.01.11
На шарпе тоже похожим образом переопределял операторы и тоже не хуже декларативность выходила.

S>Вижу что callback-и привязаны к состояниям, т.е. это Мур.

Дык, я и говорил, что схему, меняющую State, легче делать на Мура. Но ты же не видишь прикладного State, и автомат об этом не знает — это не его дело. Это уже чисто прикладная логика. Я привел как раз ту самую "внешнюю схему", управляющую целевым паттерном State. Просто показал, как задешево накидать логику переходов отдельно от прикладной части, выполнив в табличном виде, вместо того подхода, как дается в примере GoF. Прикладная часть здесь вырабатывает суррогатные сигналы: "success, hello, login, ..." и не показана, бо объемна и очень секретна.

S>Я тоже ушел от State паттерна к табличным автоматам.


Зачем??? Чистый табличный автомат хорош только для простых случаев или как автогенеренный по некоей автоматной грамматике.

S>Только мой код позволял юзать смешанные модели (генерить события по смене состояния и по переходу).


Дык, уже Мили. Все состояния у автомата могут выдавать выход, зависимый только от состояния (т.е. похожий на Мура), но в одном из состояний значение будет зависеть от входа — уже Мили. автомат Мура можно считать особым случаем Мили, наоборот — никак.

S>Представь вместо:

...
S>Следующее:
S>
S>ServerState 
S>    init        = { onInit,  { make_transition(success, wait_hello, onInitSuccess), other>closed } },
S>    wait_hello  = { NULL,    { make_transition(hello, hello_reply, onWaitHelloHello), other>closing } },
S>


Дык, а зачем тогда мой onInit и NULL? Это и есть мой декларативный make_transitions, просто инициализация в стиле С. Ты лишь продублировал на методы с другими именами. У меня вместо onWaitHelloHello идет hello_reply.

В общем, ты уже пытаешься разнести часть полезной логики в различные состояния. Именно таким образом преобразуют Мили в Мура, в итоге получаем больше состояний.

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


Вот и сам же подтвердил.

V>>Там пример неудачный, замыливает цимус паттерна. Нужно было просто нарисовать что-нить простое из 3-х состояний и 3-х выходов на switsh/case или ифах, и рядом для сравнения на State.

S>Тогда бы они получили обвинение в том что паттерн хорош только для <= 3х состояний. А это, ИМХО, действительно так.

Наоборот, на >= 3-х состояний. На маленьком пространстве состояний/выходов он overdesign.
Re[40]: [C++] о паттернах
От: samius Япония http://sams-tricks.blogspot.com
Дата: 09.06.11 11:11
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, samius, Вы писали:


S>>Формально речь идет не об истории предыдущих входных значений, а о функции , которая имеет те же аргументы, что и функция перехода


V>Это конкретная модель автомата, а их же несколько. Речь о том, что автомат во время постановки задачи — черный ящик. А его конкретная модель реализация — это уже из анализа требований/сценариев выходит, никак не раньше. Не факт, что получится запихнуть сценарий в КА, иногда приходится использовать магазинные автоматы. Иногда проще сделать комбинированный автомат, чем "монолитный".

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

V>>>При таком взгляде на вещи естественно ожидать, что выход у ф-ии наблюдается только при возбуждении входа.

S>>Верно, но так же верно считать что выход наблюдается при тех же условиях, при которых наблюдается переход.

V>Переход-то не всегда. Петля хоть и нарисована в графе, но это — математическая абстракция. Нет зачастую никакого перехода в реализации — пустая ячейка таблицы. Эффективности ради. В общем, мое ИМХО исключительно в том, что нельзя плясать от реализации. Внешнему коду всё-равно пофиг, что и как у нас там внутри.

Верно. Но эффективности ради можно добавить петлю и убрать лишнее состояние.

V>Ниче не понял, насчет как это будет определять модель автомата. И почему это осообеность диспетчеризации входа через vtable — вне паттерна? Сам паттерн только об этом трюке и больше ни о чем, вообще-то. Остальное мы пририсовываем рядом и жестоко спорим.

Под этими особенностями я подразумевал

S>Если мы хотим получить Send на выходе, у нас должно быть спецсостояние, помнящее выходной сигнал Send.
S>б) Мили
S>Выходной сигнал Send получается при проходе по ребру 'Send', которое ведет из состояние Open в него же

, а не особенность диспетчеризации. Именно они вне паттерна. А диспетчеризация через vtable — особенность паттерна State. Это верно.

S>>Полезным же выходом является либо в случае Мили, либо в случае Мура.


V>А в случае автономного? А магазинного? А обобщенного автомата? А составного?

нене, только в рамках абстрактного-Мили-Мура. Магазинные и т.п. — пусть опираются на историю. Ты прав. Я просто не думал обобщать до всех моделей.

S>>Вижу что callback-и привязаны к состояниям, т.е. это Мур.


V>Дык, я и говорил, что схему, меняющую State, легче делать на Мура. Но ты же не видишь прикладного State, и автомат об этом не знает — это не его дело. Это уже чисто прикладная логика. Я привел как раз ту самую "внешнюю схему", управляющую целевым паттерном State. Просто показал, как задешево накидать логику переходов отдельно от прикладной части, выполнив в табличном виде, вместо того подхода, как дается в примере GoF. Прикладная часть здесь вырабатывает суррогатные сигналы: "success, hello, login, ..." и не показана, бо объемна и очень секретна.

Это действительно дешево. Но дешев в этом стиле не только Мур, но и Мили.

S>>Я тоже ушел от State паттерна к табличным автоматам.


V>Зачем??? Чистый табличный автомат хорош только для простых случаев или как автогенеренный по некоей автоматной грамматике.

В сложных случаях обилие классов и их методов не позволяет охватывать поведение паттерна одним взглядом, приходится многое держать в голове, либо разбираться с бумажкой, бродя по возможным переходам. Табличный подход гораздо компактнее и позволяет реюзать код в разных задачах (как в твоем примере #include "Fsm.h"). State же вынуждает под каждый автомат заводить отдельную иерархию состояний.

S>>Только мой код позволял юзать смешанные модели (генерить события по смене состояния и по переходу).


V>Дык, уже Мили. Все состояния у автомата могут выдавать выход, зависимый только от состояния (т.е. похожий на Мура), но в одном из состояний значение будет зависеть от входа — уже Мили. автомат Мура можно считать особым случаем Мили, наоборот — никак.

Верно. Это и подразумеваю под смешанными.

S>>
S>>    init        = { onInit,  { make_transition(success, wait_hello, onInitSuccess), other>closed } },
S>>


V>Дык, а зачем тогда мой onInit и NULL? Это и есть мой декларативный make_transitions, просто инициализация в стиле С. Ты лишь продублировал на методы с другими именами. У меня вместо onWaitHelloHello идет hello_reply.

Твой onInit вызывается при входе в состояние init. А мой onInitSuccess вызовется при переходе из init по сигналу success. коллбэк входа дает нам Мура. Коллбэк перехода — Мили. Если юзать и то и другое — будет смешанный.

V>В общем, ты уже пытаешься разнести часть полезной логики в различные состояния. Именно таким образом преобразуют Мили в Мура, в итоге получаем больше состояний.

Да, я и говорю о смешивании моделей в одном исполнении. Только предостерегаю, что надо с этим аккуратнее. Проще использовать либо то, либо другое. Голова меньше болит.

V>>>Там пример неудачный, замыливает цимус паттерна. Нужно было просто нарисовать что-нить простое из 3-х состояний и 3-х выходов на switsh/case или ифах, и рядом для сравнения на State.

S>>Тогда бы они получили обвинение в том что паттерн хорош только для <= 3х состояний. А это, ИМХО, действительно так.

V>Наоборот, на >= 3-х состояний. На маленьком пространстве состояний/выходов он overdesign.

давай пофантазируем.
Ты представляешь себе диспетчеризацию S={1..50} X={1,10} на паттерне State, т.е. через vtable? Я представляю, и не испытываю никакого желания врубаться, почему она не работает как я хочу. 500 строк (максимум) в описании табличного автомата для меня будут проще, чем 50 классов, пусть и сгенерированных. Ну а если мы можем сгенерировать их, то можем и сгенерировать 500 строк табличного автомата. Потому я не наблюдаю серьезных преимуществ у State над табличным.
Re[37]: [C++] о паттернах
От: vdimas Россия  
Дата: 09.06.11 11:12
Оценка:
Здравствуйте, Sharad-Waador, Вы писали:

SW>Входной сигнал — это вызов метода и его параметры. Выходной — это сам метод.


Мимо. Сам метод — это вычисления, собсно полезная функция.

Если уж мы за входной сигнал принимаем в ООП вызов метода, то давай и за выходной принимать то же самое, бо для вызываемого нами объекта он будет точно таким же входным.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.