Si el proyecto es "Teatro", use actores ...

Este art铆culo contar谩 sobre la experiencia de usar el enfoque del actor en un proyecto interesante de un sistema de control automatizado para un teatro. Esta es exactamente la impresi贸n de uso, nada m谩s.


Recientemente, pude participar en una tarea muy interesante: la modernizaci贸n, pero de hecho, el desarrollo de un nuevo sistema de control automatizado para levantar bastidores para uno de los teatros.


Un teatro moderno (si es grande) es una organizaci贸n bastante compleja. Mucha gente, equipos y diversos sistemas est谩n involucrados en ello. Uno de esos sistemas es el sistema de control para "subir y bajar" el escenario en el escenario. Las actuaciones modernas, y m谩s 贸peras y ballets, se est谩n saturando cada vez m谩s de medios t茅cnicos cada a帽o. Utiliza muchos escenarios complejos y su movimiento durante la acci贸n. El escenario se usa activamente en los planes de direcci贸n, ampliando el significado de lo que est谩 sucediendo e incluso "desempe帽ando su propio papel de apoyo"). En general, fue muy interesante familiarizarse con la vida detr谩s del escenario del teatro y descubrir qu茅 sucede all铆 durante las actuaciones. Despu茅s de todo, los espectadores comunes solo ven lo que sucede en el escenario.


Pero este art铆culo sigue siendo t茅cnico y en 茅l quer铆a compartir la experiencia de usar el enfoque de actor para implementar la gesti贸n. Y tambi茅n comparta la experiencia de usar uno de los pocos marcos de actores de C ++: sobjectizer .


驴Por qu茅 exactamente 茅l? Lo hemos estado observando por mucho tiempo. Hay art铆culos sobre un habr, tiene excelente documentaci贸n detallada con ejemplos. El proyecto es bastante maduro. Un vistazo r谩pido a los ejemplos mostr贸 que los desarrolladores operan con conceptos "familiares" (estados, temporizadores, eventos), es decir. No se esperaban grandes problemas con la comprensi贸n y el dominio para su uso en nuestro proyecto. Y s铆, lo m谩s importante, los desarrolladores son adecuados y amigables, listos para ayudar con consejos (en ruso) . Entonces decidimos probar ...


Que estamos haciendo


Entonces, 驴c贸mo es nuestro "objeto de control"? El sistema de ascensores shtanketovy - esto es 62 mantas (tubos de metal) en todo el ancho del escenario que cuelga sobre esta misma escena, aproximadamente cada 30 - 40 cm desde el borde del escenario en profundidad. Las mangas est谩n suspendidas en cuerdas y pueden elevarse o descender al escenario (movimiento vertical). En cada actuaci贸n (u 贸pera o ballet), una parte de las estrofas se utiliza para la decoraci贸n. El escenario se cuelga de ellos y se mueve (si el gui贸n lo requiere) durante la acci贸n. El movimiento en s铆 se lleva a cabo bajo la orden de los operadores (tienen paneles de control especiales) utilizando el sistema "motor - cable - contrapeso" (casi lo mismo que los ascensores en las casas). Los motores est谩n ubicados en los bordes del escenario (en varios niveles), de modo que no son visibles para el espectador. Todos los motores est谩n divididos en 8 grupos y cada grupo tiene tres convertidores de frecuencia (IF). En cada grupo, se pueden activar simult谩neamente tres motores, cada uno conectado a su propio inversor. En total, tenemos un sistema de 62 motores y 24 inversores, que debemos controlar.


Nuestra tarea consist铆a en desarrollar una interfaz de operador para gestionar esta econom铆a, as铆 como implementar algoritmos de gesti贸n. El sistema incluye tres puestos de control. Dos postes de control est谩n ubicados directamente sobre el escenario y un poste est谩 ubicado en la sala de m谩quinas (donde se encuentran los gabinetes de control) y est谩 dise帽ado para monitorear el trabajo de un electricista de servicio. En los gabinetes de control hay controladores que ejecutan comandos, controlan PWM, suministran energ铆a a los motores y rastrean la posici贸n de los v谩stagos. En los dos controles remotos superiores hay monitores, una unidad del sistema donde los algoritmos de control y la bola de seguimiento giran como un "mouse". Se utiliza una red Ethernet entre los paneles de control. Cada gabinete de control tiene un canal RS485 (es decir, 8 canales) de cada uno de los dos paneles de control. La gesti贸n puede llevarse a cabo simult谩neamente desde ambos controles remotos (que est谩n por encima del escenario), pero al mismo tiempo solo uno de los controles remotos (designado por el operador como operador principal) est谩 intercambiando con los gabinetes, la segunda consola en este momento se considera una copia de seguridad y el intercambio est谩 desactivado en ella.


Y aqui los actores


Desde el punto de vista de los algoritmos, todo el sistema se basa en eventos. O estos son algunos cambios en los sensores, o las acciones del operador, o el inicio de alg煤n tiempo (temporizadores). Y tales algoritmos est谩n muy bien ubicados por el sistema de actores que procesan los eventos entrantes, forman alg煤n tipo de respuesta, y todo esto dependiendo de su estado. En el sobjectizer, todos estos mecanismos salen de la caja. Se pueden atribuir los principios principales en los que se basa dicho sistema: la interacci贸n entre los actores ocurre a trav茅s de mensajes, los actores pueden tener estados y moverse entre ellos, en cada estado el actor procesa solo aquellos mensajes que le interesan en este momento. Curiosamente, en un sobjectizer, trabajar con actores est谩 conceptualmente separado de trabajar con flujos de trabajo. Es decir Puede describir los actores que necesita, darse cuenta de su l贸gica, darse cuenta de su interacci贸n a trav茅s de mensajes. Pero luego resuelva por separado el problema de asignar hilos (recursos) para su trabajo. Esto est谩 garantizado por los llamados "despachadores" que son responsables de una pol铆tica particular de trabajar con hilos. Por ejemplo, hay un despachador que asigna un hilo separado para cada actor con el que trabajar, hay un despachador que proporciona un grupo de hilos (es decir, puede haber m谩s actores que hilos) con la capacidad de establecer el n煤mero m谩ximo de hilos, hay un despachador que asigna un hilo para todos. La presencia de despachadores proporciona un mecanismo muy flexible para configurar un sistema de actores que se ajuste a sus necesidades. Puede combinar grupos de actores para trabajar con uno de los despachadores, mientras cambia un tipo de despachador a otro, esto esencialmente cambia una l铆nea de c贸digo. Seg煤n los autores del marco, escribir su propio despachador 煤nico tampoco es dif铆cil. Esto no era necesario en nuestro proyecto, porque todo lo que necesit谩bamos ya estaba en el sobjectizer.


Otra caracter铆stica interesante es la presencia del concepto de "cooperaci贸n" de los actores. La cooperaci贸n es un grupo de actores que pueden existir o destruirse (o no lanzarse) si al menos un actor de la cooperaci贸n no pudo comenzar a trabajar o completarlo. Ni siquiera tengo miedo de dar semejante analog铆a ( a pesar de que es de otra "贸pera" ) que el concepto de "cooperaci贸n" es como el concepto de "hogares" en los Kubernetes ahora de moda, solo parece en el sobjetivo, surgi贸 antes ...


En el momento de la creaci贸n, cada actor est谩 incluido en la cooperaci贸n (la cooperaci贸n puede consistir en un actor), se une a uno u otro despachador y comienza a trabajar. Al mismo tiempo, los actores (y la cooperaci贸n) pueden (f谩cilmente) crearse din谩micamente en grandes cantidades, y como prometen los desarrolladores, no es costoso. Todos los actores intercambian entre ellos a trav茅s de " buzones " (mbox). Este tambi茅n es un concepto bastante interesante y fuerte en el sobjectizer. Proporciona un mecanismo muy flexible para procesar mensajes entrantes. En primer lugar, m谩s de un destinatario puede estar escondido detr谩s de una caja. Es realmente muy conveniente. Por ejemplo, se crea un cuadro en el que se reciben eventos de sensores externos y cada actor se suscribe a eventos que le interesan. Esto proporciona un estilo de operaci贸n de "publicaci贸n / suscripci贸n". En segundo lugar, los desarrolladores han brindado la oportunidad de crear con relativa facilidad su propia implementaci贸n de buzones de correo que pueden preprocesar los mensajes entrantes (por ejemplo, de alguna manera filtrarlos o distribuirlos de manera especial entre los consumidores). Adem谩s, cada actor tiene su propio buz贸n e incluso puede enviarle un "enlace" en mensajes a otros actores, por ejemplo, para que puedan enviar alg煤n tipo de notificaci贸n como respuesta de respuesta.


En nuestro proyecto, para garantizar la independencia de los grupos de motores entre ellos, as铆 como para garantizar el funcionamiento "as铆ncrono" de los motores dentro del grupo, todos los objetos de control se dividieron en 8 grupos (seg煤n el n煤mero de armarios de control), cada uno de los cuales ten铆a tres trabajadores flujo (ya que no pueden funcionar m谩s de tres motores en un grupo a la vez).
Tambi茅n debe decirse que el sobjectizer (en la versi贸n actual 5.5) no contiene mecanismos de interacci贸n entre redes y entre procesos y deja esta parte a los desarrolladores. Los autores hicieron esto de manera bastante deliberada , para que el marco sea m谩s "f谩cil". Adem谩s, los mecanismos de interacci贸n de red "una vez" existieron en versiones anteriores, pero fueron excluidos. Sin embargo, esto no causa ning煤n inconveniente, porque de hecho la interacci贸n de la red depende mucho de las tareas que se resuelven, los protocolos de intercambio utilizados, etc. Aqu铆, una implementaci贸n universal no puede ser 贸ptima para todos los casos.


En nuestro caso, para la red y la comunicaci贸n entre procesos, utilizamos uno de nuestros desarrollos de larga data: la biblioteca libuniset2 . Como resultado, la arquitectura de nuestro sistema se ve as铆:


  • libuniset proporciona comunicaci贸n de red y entre procesos (basada en sensores)
  • sobjectizer proporciona la creaci贸n de un sistema de actores que interact煤an entre s铆 (en el mismo espacio de direcciones) implementando algoritmos de control.

Entonces, d茅jame recordarte que tenemos 62 motores. Cada motor se puede conectar al inversor, al soporte correspondiente se le puede dar la coordenada a la que debe llegar y la velocidad con la que debe moverse. Adem谩s, el motor tiene las siguientes condiciones:


  • listo para ir
  • conectado
  • corriendo (girando)
  • accidente
  • conexi贸n (estado transitorio)
  • apagado (estado transitorio)

Como resultado, cada "motor" est谩 representado en el sistema por un actor que implementa la l贸gica de las transiciones entre estados, procesando eventos desde sensores y emitiendo comandos de control. En sobjectizer, los actores se crean f谩cilmente, simplemente herede su clase de la clase base so_5 :: agent_t. Al mismo tiempo, el constructor debe tomar el llamado contexto :: so_5 :: context_t como primer argumento, los argumentos restantes est谩n determinados por la necesidad del desarrollador.


class Drive_A: public so_5::agent_t { public: Drive_A( context_t ctx, ... ); ... } 

Porque Este art铆culo no es educativo, por lo que no proporcionar茅 aqu铆 los textos detallados de las descripciones de clases o m茅todos. El art铆culo solo quer铆a mostrar lo f谩cil que es (en pocas l铆neas) con la ayuda de sobjectizer todo esto est谩 implementado. Perm铆tame recordarle que el proyecto tiene una excelente documentaci贸n detallada, con muchos ejemplos diferentes.


驴Y cu谩les son los "estados" de estos actores? De que estas hablando


El uso de estados y transiciones entre ellos para ACS es generalmente un tema nativo. Este "concepto" encaja muy bien en el manejo de eventos. En sobjectizer, este concepto es compatible a nivel API. En una clase de actor, los estados se declaran con bastante facilidad.


 class Drive_A final: public so_5::agent_t { public: Drive_A( context_t ctx, ... ); virtual ~Drive_A(); //  state_t st_base {this}; state_t st_disabled{ initial_substate_of{st_base}, "disabled" }; state_t st_preinit{ substate_of{st_base}, "preinit" }; state_t st_off{ substate_of{st_base}, "off" }; state_t st_connecting{ substate_of{st_base}, "connecting" }; state_t st_disconnecting{ substate_of{st_base}, "disconnecting" }; state_t st_connected{ substate_of{st_base}, "connected" }; ... } 

y adem谩s, para cada estado, el desarrollador determina los controladores necesarios. A menudo, se requieren algunas acciones al ingresar a un estado y al salir de 茅l. Esto tambi茅n se proporciona en el sobjectizer, usted define f谩cilmente sus controladores para estos eventos ("entrada de estado", "salida de estado"). Se cree que los desarrolladores en el pasado tienen una amplia experiencia ACS-shny ...


Controladores de eventos


Controladores de eventos, aqu铆 es donde se implementa la l贸gica de su aplicaci贸n. Como se mencion贸 anteriormente, se realiza una suscripci贸n a un buz贸n espec铆fico y para un determinado estado del actor. Si un actor no tiene estados declarados expl铆citamente en el c贸digo, entonces est谩 impl铆citamente en el estado especial "default_state". En diferentes estados, puede definir diferentes controladores para los mismos eventos. Si no especific贸 el controlador de ning煤n evento en este buz贸n, simplemente se ignorar谩 (es decir, simplemente no existir谩 para el actor).


La sintaxis para definir manejadores es muy simple. Es suficiente para indicar su funci贸n. No se requieren tipos ni argumentos de plantilla. Todo se deduce autom谩ticamente de la definici贸n de la funci贸n. Por ejemplo:


 so_subscribe(drv->so_mbox()) .in(st_base) .event( &Drive_A::on_get_info ) .event( &Drive_A::on_control ) .event( &Drive_A::off_control ); 

Aqu铆 hay un ejemplo de suscripci贸n a eventos en un cuadro espec铆fico para el estado st_base. Curiosamente, en este ejemplo, st_base es el estado base para otros estados y, en consecuencia, esta suscripci贸n ser谩 v谩lida para todos los estados que se "hereden" de st_base. Este enfoque le permite deshacerse de "copiar y pegar" para determinar los mismos controladores para diferentes estados. Al mismo tiempo, en un estado espec铆fico, puede anular el controlador especificado o "deshabilitarlo" (suprimir).


Hay otra forma de definir manejadores. Esta es una definici贸n directa de funciones lambda. Esta es una forma muy conveniente, porque a menudo los controladores son funciones cortas en un par de acciones, enviar algo a alguien o cambiar el estado.


 so_subscribe(drv->so_mbox()) .in(st_disconnecting) .event([this](const msg_disconnected_t& m) { ... st_off.activate(); }) .event([this]( const msg_failure_t& m ) { ... st_protection.activate(); }); 

Al principio, esta sintaxis parece complicada. Pero en solo unos pocos d铆as de desarrollo activo, te acostumbras e incluso te comienza a gustar. Porque toda la l贸gica del trabajo del actor en un estado u otro puede caber en un c贸digo bastante corto y todo estar谩 frente a tus ojos. Por ejemplo, en el ejemplo que se muestra, en el estado desconectado (st_disconnecting), la transici贸n al estado desconectado (st_off.) O el estado de protecci贸n (st_protection) se produce si se produce un mensaje sobre alg煤n tipo de falla. Tal c贸digo es bastante f谩cil de leer.


Por cierto, para casos simples cuando un evento solo necesita entrar en alg煤n estado, hay una sintaxis a煤n m谩s corta:


 auto mbox = drv->so_mbox(); st_off .just_switch_to<msg_connected_t>(mbox, st_connected) .just_switch_to<msg_failure_t>(mbox, st_protection) .just_switch_to<msg_on_limit_t>(mbox, st_protection) .just_switch_to<msg_on_t>(mbox, st_on); 

Gesti贸n


驴C贸mo funciona la gesti贸n de toda esta econom铆a? Como se mencion贸 anteriormente, se proporcionan dos controles remotos para el control directo del movimiento de los shtankets. En cada control remoto hay un monitor, un manipulador (trackball) y un marcado r谩pido (adem谩s de la "computadora" oculta en el control remoto en el que todo gira y un mont贸n de todo tipo de convertidores). El sistema tiene varios modos de controlar el movimiento de los shtankets. Manual y "modo script". Sobre el "modo de escenario" se discutir谩 m谩s a fondo, y ahora un poco sobre el "modo manual". En este modo, el operador selecciona el v谩stago deseado, lo prepara para el movimiento (conecta el motor al inversor), establece la marca (posici贸n objetivo) para el v谩stago y tan pronto como establece la velocidad mayor que cero, los v谩stagos comienzan a moverse. Para establecer la velocidad, se usa un ajustador f铆sico especial, en forma de un "potenci贸metro con una perilla", pero tambi茅n hay un "ajustador de pantalla" de velocidad. Cuanto m谩s "convertido", el mas fuerte va m谩s r谩pido La velocidad m谩xima est谩 limitada a 1,5 m / s. Perilla de velocidad: una para todos. Es decir En modo manual, todas las bandejas conectadas por el operador se mueven a la misma velocidad establecida. Aunque pueden moverse en diferentes direcciones (depende de d贸nde los dirigi贸 el operador). Por supuesto, es dif铆cil para una persona hacer un seguimiento de m谩s de dos o tres canastas al mismo tiempo, por lo que generalmente no se mueven mucho en modo manual. Desde dos estaciones, los operadores pueden gestionar simult谩neamente cada uno de sus shtankets. Adem谩s, cada consola (operador) tiene su propio controlador de velocidad.


Desde el punto de vista de la implementaci贸n, el modo manual no contiene ninguna l贸gica especial. El comando para conectar el motor proviene de la interfaz gr谩fica, se convierte en un mensaje para el actor correspondiente, que trabaja en 茅l. Al pasar por los estados "apagado" -> "conexi贸n" -> "conectado". Lo mismo con establecer la posici贸n para el movimiento del stunket y establecer la velocidad. Todos estos eventos llegan al actor en forma de mensajes a los que reacciona. A menos que se pueda observar que la interfaz gr谩fica y el proceso de control en s铆 son procesos diferentes y entre ellos hay una interacci贸n "interproceso" a trav茅s de los "sensores" que usan libuniset2 .


Modo de ejecuci贸n de script (de nuevo, 驴estos actores?)


De hecho, el modo de control manual se usa principalmente para pasar el rato durante los ensayos o en casos simples. El modo principal en el que el control est谩 en progreso es "modo de ejecuci贸n de script" o, brevemente, "modo de script". En este modo, cada shtank se mueve a su punto con los par谩metros especificados en el script (velocidad y marca de objetivo). Para el operador, el control en este modo consta de dos comandos simples:


  • prep谩rate (el grupo correcto de motores est谩n conectados)
  • vamos (el grupo comienza a moverse a las posiciones de destino establecidas para cada uno).

Todo el escenario se divide en las llamadas "agendas". Una agenda es un movimiento de un grupo shtanket. Es decir cada agenda incluye un grupo de shtankets, con la velocidad objetivo y la marca a la que necesita llegar. De hecho, el gui贸n se divide en actos, los actos se dividen en pinturas, las pinturas se dividen en citaciones y las citaciones ya consisten en "objetivos" para tiendas espec铆ficas. Pero desde el punto de vista de la administraci贸n, esta divisi贸n no es importante, porque Es en la agenda que los par谩metros espec铆ficos de movimiento se indican al final.


Para implementar este r茅gimen, el sistema de actores volvi贸 a surgir lo mejor posible. Se desarroll贸 un "reproductor de guiones" que crea un grupo de actores especiales y los lanza. Hemos desarrollado dos tipos de actores: actores-actores, dise帽ados para realizar tareas para un shtanket espec铆fico, y un actor-coordinador, que distribuye las tareas entre los artistas. Adem谩s, los actores interpretativos se crean seg煤n sea necesario, si en el momento del pr贸ximo equipo no es gratuito. El actor coordinador es responsable de crear y mantener el grupo de actores esc茅nicos. Como resultado, la administraci贸n se ve as铆:


  • declaraci贸n carga el script
  • Lo "voltea" a la agenda deseada (generalmente solo va en una fila).
  • en el momento correcto, presiona el bot贸n "preparar", mediante el cual se env铆a un comando (mensaje) al actor coordinador para cada formulario incluido en la agenda actual con par谩metros de movimiento.
  • El coordinador de actores analiza su grupo de actores que act煤an libremente, toma uno libre (si no crea uno nuevo) y le asigna una tarea (n煤mero de mantillas y par谩metros de movimiento).
  • Cada actor-actor que ha recibido la tarea comienza a cumplir el comando "prepararse". Es decir conecta el motor y entra en el modo de espera del comando "ir".
  • cuando llega el momento, el operador da el comando "vamos"
  • el equipo "ir" viene al coordinador. Se lo env铆a a todos sus artistas actualmente activos y comienzan la "ejecuci贸n".

Vale la pena se帽alar que en la agenda hay par谩metros adicionales. Por ejemplo, inicie el movimiento con un retraso de N segundos o inicie el movimiento solo despu茅s de un comando de operador especial por separado. Por lo tanto, la lista de estados para cada actor es bastante grande: "listo para ejecutar el siguiente comando", "listo para moverse", "movimiento retrasado", "esperando el comando del operador", "movimiento", "ejecuci贸n completada", "mal funcionamiento" .


Despu茅s de que el v谩stago alcanz贸 con 茅xito (o no) la marca especificada, el actor-int茅rprete notifica al coordinador la tarea completada. El coordinador da la orden de apagar este motor (si ya no participa en la agenda actual) o emite nuevos par谩metros de movimiento. A su vez, el actor-int茅rprete recibi贸 una orden para apagar el motor, lo apaga y pasa a un estado de espera de nuevas 贸rdenes, o comienza a ejecutar una nueva orden.


Debido al hecho de que el sobjectizer tiene una API bien pensada y conveniente para trabajar con estados, el c贸digo de implementaci贸n es bastante conciso. Por ejemplo, el retraso en el movimiento se describe en una l铆nea:


 st_delay.time_limit( std::chrono::milliseconds{target->delay()}, st_moving ); st_delay.activate(); ... 

La funci贸n time_limit establece un l铆mite de tiempo sobre cu谩nto se puede gastar en un estado dado y qu茅 estado se debe pasar despu茅s de un tiempo espec铆fico (st_moving).


Actores de protecci贸n


Por supuesto, durante la operaci贸n, pueden ocurrir fallos de funcionamiento. Se requiere el sistema para manejar estas situaciones. Aqu铆, tambi茅n, hab铆a un lugar para el uso de actores. Considere varias de estas protecciones:


  • sobre la protecci贸n actual
  • protecci贸n de falla de medici贸n
  • protecci贸n contra el movimiento en la direcci贸n opuesta (y esto puede ser, si algo est谩 mal con el sensor o el medidor)
  • protecci贸n contra movimiento sin comando
  • control de la ejecuci贸n del equipo (control de que el shtanket comenz贸 a moverse)

Puede ver que todas estas protecciones son independientes (autosuficientes) desde el punto de vista de la implementaci贸n, y deber铆an funcionar "en paralelo". Es decir Cualquier condici贸n puede funcionar. Al mismo tiempo, la l贸gica de verificar las condiciones de activaci贸n para cada una de las protecciones tiene la suya, a veces se requiere un retraso (temporizador) para la activaci贸n, a veces se requiere un procesamiento preliminar de varias mediciones anteriores, etc. Por lo tanto, la implementaci贸n de cada tipo de protecci贸n como un peque帽o actor separado result贸 ser muy conveniente. Todos estos actores se lanzan adem谩s (en cooperaci贸n) del actor principal que implementa la l贸gica de control. Este enfoque hace que sea f谩cil agregar tipos adicionales de defensas simplemente agregando otro actor al grupo. Al mismo tiempo, la implementaci贸n de tal actor sigue siendo bastante f谩cil y comprensible, porque Implementa solo una funci贸n.


Los actores de protecci贸n tambi茅n tienen varios estados. B谩sicamente se encienden (entran en el estado "encendido") solo cuando el motor est谩 conectado o el v谩stago est谩 en movimiento. Cuando se activan las condiciones de protecci贸n, publican una notificaci贸n sobre la protecci贸n que se est谩 activando (con un c贸digo de seguridad y algunos detalles para el registro), el actor principal ya responde a esta notificaci贸n, que, si es necesario, apaga el motor y cambia al modo de protecci贸n.


Como conclusi贸n ...


... por supuesto, este art铆culo no es una especie de "descubrimiento". El enfoque del actor se ha utilizado con 茅xito en muchos sistemas. Pero para m铆 fue la primera experiencia de usar conscientemente el enfoque del actor para construir algoritmos de sistemas de control en un proyecto relativamente peque帽o. Y la experiencia fue bastante exitosa. Espero haber podido demostrar que los actores est谩n muy bien superpuestos a los algoritmos de control, encontraron un lugar literalmente en todas partes.


Seg煤n la experiencia de proyectos anteriores, estaba claro que de una forma u otra est谩bamos implementando "algo as铆" (estados, mensajes, control de flujo, etc.), pero este no era un enfoque unificado. Usando el sobjectizer obtuvimos una herramienta de desarrollo concisa y liviana que tiene muchos problemas. Ya no es necesario (expl铆cito) usar herramientas de sincronizaci贸n (mutexes, etc.), no hay trabajo expl铆cito con flujos, ni realizaciones de la m谩quina de estados. Todo esto est谩 en el marco, l贸gicamente interconectado y presentado como una API conveniente, adem谩s, sin perder el control sobre los detalles. Entonces la experiencia fue interesante. Para aquellos que a煤n dudan, recomiendo prestar atenci贸n al enfoque del actor y al marco del sobjectizer en particular. Deja emociones positivas.


隆Y el enfoque del actor realmente funciona! Especialmente en el teatro.

Source: https://habr.com/ru/post/438196/


All Articles