Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 24.08.15 14:05
Оценка: 46 (5)
Речь идет разумеется не о том, что концепция акторов сама по себе является антипаттерном только потому, что это акторы, а о случаях их неправильного использования или чрезмерного использования. Проблема однако в том, что по моим наблюдениям 90 процентов случаев их реального применения на практике являются чрезмерными или неправильными. На волне популярности эрланга и всевозможных фреймворков навроде akka, концепция акторов сама по себе переоценена и выглядит в глазах некоторых как серебряная пуля, хотя и близко таковой не является. Приведу некоторые примеры, с которыми столкнулся за последние два года.

1. Использование акторов для parallel execution.

actor = new Actor();
actor.sendMessage(new CalculateSomething(1, 2, 3));
//Все, здесь ничего больше не делается, и если даже этот код
//является частью другого актора, в 99 процентах случаях он либо не
//получает других сообщений кроме CalculationResult,
//а если и получает, то ничего не может с ними сделать без CalculationResult


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

actor = new Actor();
actor.sendMessage(new CalculateSomething(1, 2, 3));
someHardCalculation();


это все равно останется антипаттерном, потому что потом кто-нибудь может добавить еще одно вычисление

actor = new Actor();
actor.sendMessage(new CalculateSomething(1, 2, 3));
actor.sendMessage(new CalculateSomething(4, 5, 6));
calc = someHardCalculation();


которое выполнится последовательно с первым вычислением (используется один актор). Потом приходится переписывать такой код с помощью Conditions или Future:

calc = new Calculator();
calc1Future = calc.calculate(1, 2, 3);
calc2Future = calc.calculate(4, 5, 6);
calc = someHardCalculation();
result = resultCalculation(calc, calc1Future.get(), calc2Future.get());


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

2. В предыдущем примере речь шла о явно ошибочном использовании акторов. Однако даже в тех случаях, когда использование акторов, казалось бы, оправдано, я бы 10 раз подумал, прежде чем их использовать. Приведу типичный пример — сервер, работающий по TCP, большое количество параллельных сессий, но время обработки запроса незначительное. Казалось бы, что может быть проще

sessionLock.lock();
try {
    commonDataLock.lock();
    try {
        //Непродолжительная обработка
        executeLogic(message, session, commonData);
    } finally {
      commonDataLock.unlock();
    }
} {
  sessionLock.unlock();
}


или на худой конец использовать актор, но только ОДИН (в смысле класс один, в котором будет вся обработка, а не instance). Однако, и здесь может найтись умник, который разнесет обработку запроса по двум, трем а то и более акторам — "так более масштабируемо"... В результате в системе порождается огромное количество сообщений между акторами, отлик падает, потому что 90 процентов тактов уходит на переключение контекста, вращение в спинлоках, чтение-копирование данных. Читаемость и поддерживаемость кода уже с тремя акторами с богатыми состояниеми и нетривиальными взаймодействиями радикально осложняется, об этом речь пойдет дальше.

3. Асинхронный код сложнее в поддержке, это все знают. Однако асинхронность асинхронности рознь. Одно дело, когда это асинхронный вызов с callback-ом, сохраняющий контекст вызова. И другое дело — актор, который каждый раз в момент прихода сообщения должен понять, в каком он состоянии находится. Городить на каждый чих FSM — удовольствие не из приятных. При добавлении одной дополнительной коммуникации или одного дополнительного контекста количество состояний способно комбинаторно взорваться. Бизнес-логика размазывается по всему коду актора на маленькие порции. Вместо одного сервисного метода вы ползаете по функциям перехода, проклиная автора за то, что тот не оставил excel-таблицу с описанием автомата. Это в том случае, если автор удосужился оформить актор именно в виде автомата с именованным признаком состояния, а не определяет контекст из лапши условий — последнее встречается чаще, тогда приходится брать бумагу и карандаш и рисовать граф с переходами, чтобы составить хотя бы приблизительное представление о том, что же делает эта мешанина кода. Спору нет, в некоторых случаях такой подход может быть эффективным с точки зрения производительности — в случае с TCP-сервером из предыдущего примера применение нескольких типов акторов может быть оправданным в случае достаточно тяжелых запросов. Однако в любом случае, прежде чем браться за акторы, я бы посмотрел на другие способы решения задачи. Например, shared memory что бы про него не говорили при соблюдении простейших правил и правильного проектирования совершенно безопасен, а код ясен и читаем. Акторы же, даже в тех случаях, когда их применение технически оправдано, принципиально тяжелы для восприятия — это их фунадментальная особенность в силу того, что каждый актор является машиной состояний.

activateState1();
actor1.sendMessage(new Request1(data1));
actor2.sendMessage(new Request2(data2));
state = STATE1_WAIT_FOR_RESPONSE1_RESPONSE2;


void response1Handler(Response1 resp) {
     this.resp1 = resp;
     if (state == STATE1_WAIT_FOR_RESPONSE1_RESPONSE2) {
         state = STATE1_WAIT_FOR_RESPONSE2;
     } else if (state == STATE1_WAIT_FOR_RESPONSE1){
       process(this.resp1, this.resp2);
       someCommonForState1State2Processing();
       state = STATE1_PROCESSED;
     } else if (state == STATE2_WAIT_FOR_RESPONSE1) {
       //Здесь другой контекст (STATE2) и совершенно другое вычисление
       doAnotherProcessing(this.resp1);
       someCommonForState1State2Processing();
       state = STATE2_PROCESSED;
     } else if (...){}//Обработка других комбинаций
}

void response2Handler(Response2 resp) {
     this.resp2 = resp;
     if (state == STATE1_WAIT_FOR_RESPONSE1_RESPONSE2) {
         state = STATE1_WAIT_FOR_RESPONSE1;
     } else if (state == STATE1_WAIT_RESPONSE2) {
       process(this.resp1, this.resp2);
       someCommonForState1State2Processing();
       state = STATE1_PROCESSED;
     }
}


Что может произойти с кодом выше при добавлении нового контекста STATE3 знает любой, кто хоть немного знаком с конечными автоматами — произойдет взрыв состояний — STATE12_WAIT_RESPONSE1_RESPONSE2, STATE23_WAIT_FOR_RESPONSE1_RESPONSE2 и т.д. Ситуацию может облегчить использование иерархических автоматов — тогда вместо подобной комбинации состояний будет дерево и состояния WAIT_FOR_RESPONSE1_RESPONSE2 будут дочерними по отношению к контекстам STATE1, STATE2, STATE3... Но иерархические автоматы никто в подобных случаях не использует (уже спасибо, если удосужились оформить машину состояний в виде обычного автомата), потому что для этого требуются либо дополнительные телодвижения, либо дополнительная библиотека. Также количество состояний можно сократить с использованием coroutines (в С# — yield return), но они не в каждом языке есть и не каждому разработчику знакомы. А акторы, черт возьми, знакомы уже многим (к сожалению).

Что касается технической стороны кода, приведенного выше, то он может быть оправдан в тех случаях, когда помимо Response1 и Response2 актор ожидает например еще SomeMessage, обработкой которого он потенциально может заняться, ожидая ответа на Request1 и Request2. Но анализ встретившихся мне случаев опять-таки говорит о том, что в большинстве случае никаких других сообщений кроме Response1 и Response2 актор не принимает (а если и принимает, то не может ничего сделать с ними без Response1 и Response2), и висит в спинлоке или мьютексе точно также, как висел бы в случае явной блокировки:

ProcessingResult process(data1, data2) {
      future1 = performer1.request(new Request1(data1));
      future2 = performer2.request(new Request2(data2));
      return process(future1.get(), future2.get());
}

ProcessingResult2 processAnother(data) {
      return performer1.request(new Request1(data));
}


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

Если заменить 95 процентов всех случаев использования акторов на shared memory/future/stm/однопоточный код, получится технически как минимум эквивалентное (а с учетом первого пункта о неправильным использовании — зачастую и превосходящее) решение, к тому же значительно выигрывающее по ясности и поддерживаемости. Из этого не следует, что акторы не нужны, но рядовому программисту они почти не нужны, объективно. Само собой, я не затрагиваю тех, кто пишет ПО для кластеров — в этой области это де-факто стандарт коммуникации.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re: Об очередном антипаттерне. Модель акторов.
От: Alex912  
Дата: 24.08.15 14:46
Оценка: 6 (1)
Здравствуйте, LaPerouse, Вы писали:

Этож старо как мир.
https://www.chrisstucchio.com/blog/2013/actors_vs_futures.html

Actors are awesome. But they aren't the only abstraction we have. Futures are another great abstraction which work very well with purely functional code. Actors are great for maintaining state, futures are great for everything else.

Re[2]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 24.08.15 14:58
Оценка:
Здравствуйте, Alex912, Вы писали:

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


A>Этож старо как мир.

A>https://www.chrisstucchio.com/blog/2013/actors_vs_futures.html

A>

A>Actors are awesome. But they aren't the only abstraction we have. Futures are another great abstraction which work very well with purely functional code. Actors are great for maintaining state, futures are great for everything else.


За ссылку спасибо. Но хоть и старо, но судя по тому что я видел, их начали использовать совершенно бездумно, прямо как синглтон пятнадцать лет назад.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re: Об очередном антипаттерне. Модель акторов.
От: -MyXa- Россия  
Дата: 24.08.15 18:10
Оценка:
Здравствуйте, LaPerouse, Вы писали:

LP>3. Асинхронный код сложнее в поддержке, это все знают.


Я предлагаю отказаться от выражения "асинхронный код", разделив его на два — "лапшеобразный код" и "асинхронная логика".

Так вот, лапшеобразный код, тут я согласен, сложнее в поддержке. Однако, выразить "асинхронную логику" с помощью обычного (без колбэков и монад) можно с помощью стековых корутин. Вот пример. Если он понятен и присутствие yield не смущает, то дальше можно не читать.

Если код использует полиморфизм (например, как в iostreams, IStream (это из COM) или даже С-шный minizip), то его логика может выполняться асинхронно. Например, двадцать лет назад был написан и скомпилирован, а после компиляции безвозвратно потерян вот этот блокирующий (псевдо)код:

result read_from_stream(stream s)
{
    while(s.is_good())
    {
        s.read();
    };
    return result(...);
}


Понятное дело, что пока не прочитается весь поток (а это может занять хоть неделю), мы не сможем обрабатывать другие запросы. Правда? Конечно нет! Достаточно запустить эту функцию внутри корутины, передав такой stream, который в своей функции read не будет дожидаться окончания чтения, а вместо этого только быстренько запустит чтение и сразу же yield-нется на корутине. Через неделю, когда чтение закончится, нужно не забыть переключиться обратно в корутину, чтобы продолжить выполнение с того места, где мы прервались в прошлый раз.

Теперь только остаётся отказаться от выражения "блокирующий код", т.к. оно вовсе лишено смысла (выше я применил его, чтобы было легче читать. Это помогло?).
Если не поможет, будем действовать током... 600 Вольт (C)
Re[2]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 24.08.15 18:18
Оценка:
Здравствуйте, -MyXa-, Вы писали:

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


MX>Теперь только остаётся отказаться от выражения "блокирующий код", т.к. оно вовсе лишено смысла (выше я применил его, чтобы было легче читать. Это помогло?).


Ты наверное невнимательно прочитал мое сообщение. Процитирую

Ситуацию может облегчить использование иерархических автоматов — тогда вместо подобной комбинации состояний будет дерево и состояния WAIT_FOR_RESPONSE1_RESPONSE2 будут дочерними по отношению к контекстам STATE1, STATE2, STATE3... Но иерархические автоматы никто в подобных случаях не использует (уже спасибо, если удосужились оформить машину состояний в виде обычного автомата), потому что для этого требуются либо дополнительные телодвижения, либо дополнительная библиотека. Также количество состояний можно сократить с использованием coroutines (в С# — yield return), но они не в каждом языке есть и не каждому разработчику знакомы. А акторы, черт возьми, знакомы уже многим (к сожалению).


Я пишу на java и С++, здесь нет никаких корутин и вообще мало кто из разработчиков даже представляет об этом концепте. Есть решения для java, основанные на потоках (тяжелы и не применимы в production), есть на модифицкации байткода, я даже использовал как-то одну такую библиотеку для написания одного сложного КА, но в мире java и С++ это именно что исключение.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[3]: Об очередном антипаттерне. Модель акторов.
От: alex_public  
Дата: 24.08.15 18:46
Оценка: +1
Здравствуйте, LaPerouse, Вы писали:

LP>Я пишу на java и С++, здесь нет никаких корутин и вообще мало кто из разработчиков даже представляет об этом концепте. Есть решения для java, основанные на потоках (тяжелы и не применимы в production), есть на модифицкации байткода, я даже использовал как-то одну такую библиотеку для написания одного сложного КА, но в мире java и С++ это именно что исключение.


В C++ сопрограммы есть уже давным давно. Уже даже в Boost включены не первый год. А сейчас обсуждается вообще добавление в стандарт языка. )))
Re[4]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 24.08.15 18:53
Оценка:
Здравствуйте, alex_public, Вы писали:

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


LP>>Я пишу на java и С++, здесь нет никаких корутин и вообще мало кто из разработчиков даже представляет об этом концепте. Есть решения для java, основанные на потоках (тяжелы и не применимы в production), есть на модифицкации байткода, я даже использовал как-то одну такую библиотеку для написания одного сложного КА, но в мире java и С++ это именно что исключение.


_>В C++ сопрограммы есть уже давным давно. Уже даже в Boost включены не первый год. А сейчас обсуждается вообще добавление в стандарт языка. )))


Неужели? К сожалению, программисты, которые на С++ пишут, не в курсе этого. Иначе я бы не смотрел сейчас на конечный автомат с over 2000 строк кода. Мне периодически приходится сталкиваться с С++ кодом, иногда даже приходится немного писать на нем, ни разу не сталкивался с этим концептом.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[3]: Об очередном антипаттерне. Модель акторов.
От: -MyXa- Россия  
Дата: 24.08.15 18:58
Оценка:
Здравствуйте, LaPerouse, Вы писали:

LP>Я пишу на java и С++, здесь нет никаких корутин и вообще мало кто из разработчиков даже представляет об этом концепте. Есть решения для java, основанные на потоках (тяжелы и не применимы в production), есть на модифицкации байткода, я даже использовал как-то одну такую библиотеку для написания одного сложного КА, но в мире java и С++ это именно что исключение.


Я старался про стратегию рассказать — чтобы было видно, так сказать, куда стремиться, а не про тактику. Вот в Java добавят корутины со стеком, а мы уже будем знать — зачем это. А в С# корутины не годятся (они без стека) — весь код придётся переписывать.
Если не поможет, будем действовать током... 600 Вольт (C)
Re[5]: Об очередном антипаттерне. Модель акторов.
От: alex_public  
Дата: 24.08.15 19:04
Оценка:
Здравствуйте, LaPerouse, Вы писали:

_>>В C++ сопрограммы есть уже давным давно. Уже даже в Boost включены не первый год. А сейчас обсуждается вообще добавление в стандарт языка. )))

LP>Неужели? К сожалению, программисты, которые на С++ пишут, не в курсе этого. Иначе я бы не смотрел сейчас на конечный автомат с over 2000 строк кода. Мне периодически приходится сталкиваться с С++ кодом, иногда даже приходится немного писать на нем, ни разу не сталкивался с этим концептом.

Более того, к примеру на этом форуме многие нюансы с работой сопрограмм в C++ разбирались, несколько лет назад. )

Что касается конечного автомата, то у него есть отдельная ценность, никак не связная с задачами эмуляции сопрограмм. И ничего страшного в конечных автоматах тоже нет, особенно если пользоваться удобными готовыми реализациями (например как из того же boost'a).
Re[6]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 24.08.15 19:09
Оценка: -1
Здравствуйте, alex_public, Вы писали:

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


_>Что касается конечного автомата, то у него есть отдельная ценность, никак не связная с задачами эмуляции сопрограмм.


Сопрограмма — это обычный иерархический конечный автомат, в котором состояние автоматически управляется компилятором/рантаймом.

_>И ничего страшного в конечных автоматах тоже нет, особенно если пользоваться удобными готовыми реализациями (например как из того же boost'a).


Пример из исходного сообщени видел? Если их прудумывают на ровном месте, привнося совершенно ненужную сложность, ничего хорошего в них нет.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[4]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 24.08.15 19:16
Оценка:
Здравствуйте, -MyXa-, Вы писали:

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


LP>>Я пишу на java и С++, здесь нет никаких корутин и вообще мало кто из разработчиков даже представляет об этом концепте. Есть решения для java, основанные на потоках (тяжелы и не применимы в production), есть на модифицкации байткода, я даже использовал как-то одну такую библиотеку для написания одного сложного КА, но в мире java и С++ это именно что исключение.


MX>Я старался про стратегию рассказать — чтобы было видно, так сказать, куда стремиться, а не про тактику. Вот в Java добавят корутины со стеком, а мы уже будем знать — зачем это. А в С# корутины не годятся (они без стека) — весь код придётся переписывать.


А что, планируют добавить? Не слышал ни разу. Вообще говоря, мне их откровенно не хватает.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[4]: Корутины в C#
От: Qbit86 Кипр
Дата: 24.08.15 19:59
Оценка:
Здравствуйте, -MyXa-, Вы писали:

MX>А в С# корутины не годятся (они без стека) — весь код придётся переписывать.


Почему это не годятся? В C# есть и корутины через yield return, и async/await. Какого именно стека им не хватает?
Глаза у меня добрые, но рубашка — смирительная!
Re[5]: Об очередном антипаттерне. Модель акторов.
От: -MyXa- Россия  
Дата: 24.08.15 20:04
Оценка:
Здравствуйте, LaPerouse, Вы писали:

LP>А что, планируют добавить? Не слышал ни разу. Вообще говоря, мне их откровенно не хватает.


Я тоже не слышал. Но представьте, если правда добавят! Это будет революция в программировании!
Если не поможет, будем действовать током... 600 Вольт (C)
Re[7]: Об очередном антипаттерне. Модель акторов.
От: alex_public  
Дата: 24.08.15 20:22
Оценка:
Здравствуйте, LaPerouse, Вы писали:

_>>Что касается конечного автомата, то у него есть отдельная ценность, никак не связная с задачами эмуляции сопрограмм.

LP>Сопрограмма — это обычный иерархический конечный автомат, в котором состояние автоматически управляется компилятором/рантаймом.

Это безстековые) А у сопрограммы со стеком получается совсем другой расклад. Да, и кстати, скажем на той же винде они доступны давным давно для любых языков программирования (которые могут работать с win api). Но реализация в языке (пусть даже и в виде библиотеки, как в boost'e) конечно же удобнее, т.к. там всякие специфические нюансы (типа проброса исключений) можно учесть.

_>>И ничего страшного в конечных автоматах тоже нет, особенно если пользоваться удобными готовыми реализациями (например как из того же boost'a).

LP>Пример из исходного сообщени видел? Если их прудумывают на ровном месте, привнося совершенно ненужную сложность, ничего хорошего в них нет.

Ну естественно можно устроить говнокод и с помощью идеальных инструментов. Однако если применять конечные автоматы по делу, да ещё и в правильном виде (скажем таком http://www.boost.org/doc/libs/develop/libs/msm/doc/HTML/ch03s04.html#d0e1462), то они намного улучшают качество кода.
Re[5]: Корутины в C#
От: -MyXa- Россия  
Дата: 24.08.15 20:23
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Здравствуйте, -MyXa-, Вы писали:


MX>>А в С# корутины не годятся (они без стека) — весь код придётся переписывать.


Q>Почему это не годятся? В C# есть и корутины через yield return, и async/await. Какого именно стека им не хватает?


Ты-ж сам ответил на свой вопрос — потому, что надо расставить async и await в стратегических местах. А если Майкрософт её слово придумают — тоже будем его по всему коду расставлять? В предыдущем
Автор: -MyXa-
Дата: 24.08.15
сообщении я писал, что корутины со стеком не требуют модификации запускаемого кода (в т.ч. типа возвращаемого значения). На этом форуме про это был уже сра обсуждение.
Если не поможет, будем действовать током... 600 Вольт (C)
Re[5]: Корутины в C#
От: alex_public  
Дата: 24.08.15 20:27
Оценка:
Здравствуйте, Qbit86, Вы писали:

MX>>А в С# корутины не годятся (они без стека) — весь код придётся переписывать.

Q>Почему это не годятся? В C# есть и корутины через yield return, и async/await. Какого именно стека им не хватает?

Это не верная формулировка. Правильная такая: в C# генераторы (yield) и выпрямление (эмуляция синхронного вида) асинхронного кода (async/await) реализованы с помощью безстековых сопрограмм (которые по сути являются конечными автоматами, генерируемыми компилятором), не идущими ни в какое сравнение с нормальными сопрограммами со стеком (которые по сути являются полноценным аналогом потоков, только с кооперативной многозадачностью и мгновенным (без путешествий в ядро ОС) переключением).
Re: Об очередном антипаттерне. Модель акторов.
От: Mamut Швеция http://dmitriid.com
Дата: 24.08.15 20:27
Оценка: :)
Практически все описаные антипаттерны возникают из отсутсвия в языке и среде нативной поддержки собственно модели акторов. Отсюда все эти стенания о спинлоках, задержке сообщений и прочем и прочем. Это не говоря уже об отсутствии необходимой инфраструктуры, следящей за завершением исполнения процессов, изоляции процессов и многого другого. Откуда проистекают стенания о невозможности следить за акторами с «богатым состоянием» и т.п.


В том же Erlang'е практически все описанные «проблемы» давно, по сути, решены и описываются во первых же строках любой книги по Erlang'у. Курить те же деревья супервизоров.


dmitriid.comGitHubLinkedIn
Re[6]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 24.08.15 20:33
Оценка: 5 (1)
Здравствуйте, -MyXa-, Вы писали:

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


LP>>А что, планируют добавить? Не слышал ни разу. Вообще говоря, мне их откровенно не хватает.


MX>Я тоже не слышал. Но представьте, если правда добавят! Это будет революция в программировании!


Бросай этот балаган.
При помощи нормально реализованных сопрограмм можно сильно сократить код КА, избавившись от самой назойливой и мусорной части. Я как-то очень давно при помощи этой библиотеки урезал код автомата читающего с ком-порта раза эдак в три.
Опять же, в Unreal Engine и Unity сопрограммы уже давно используются для программирования логики. Надо думать, гейм-девелоперы, которым чаще других приходится работать с КА, не зря их используют.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[2]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 24.08.15 21:04
Оценка:
Здравствуйте, Mamut, Вы писали:

M>В том же Erlang'е практически все описанные «проблемы» давно, по сути, решены и описываются во первых же строках любой книги по Erlang'у. Курить те же деревья супервизоров.


Ну, начнем с того, что у меня не erlang, а jvm или c++. И как минимум там это действительно выглядит как антипаттерн. Про erlang ничего сказать не могу, не читал, не использовал, не сталкивался. Но с эрлангом или без, от конечного автомата все равно не убежите. Другое дело, он может быть замаскирован корутинами или продожениями. Но в любом случае будет интересно увидеть, что же так сказать эрланг животворящий делает. Как будет выглядеть на эрланге приведенный мной пример (с Response1 и Response2)?
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[8]: Об очередном антипаттерне. Модель акторов.
От: LaPerouse  
Дата: 24.08.15 21:34
Оценка:
Здравствуйте, alex_public, Вы писали:

_>>>И ничего страшного в конечных автоматах тоже нет, особенно если пользоваться удобными готовыми реализациями (например как из того же boost'a).

LP>>Пример из исходного сообщени видел? Если их прудумывают на ровном месте, привнося совершенно ненужную сложность, ничего хорошего в них нет.
_>Ну естественно можно устроить говнокод и с помощью идеальных инструментов. Однако если применять конечные автоматы по делу, да ещё и в правильном виде

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