I'm not very sure it's the same idea I've talk about, I think it is. The idea is prevent business logic from being leaked into the view.
Yes, I think it’s precisely that same idea. Pete Heard talks a lot about separating out all business logic, so it is testable, and the UI being an afterthought (even one step further than what MobX does).
This is a very basic web app that uses the actor model. The actor model helps you to break your app’s core logic into small pieces that have to communicate with messages instead of using function calls. Adopting this model has multiple benefits on the web:
Yields to browser (it naturally leads to chunked code)
Helpers to build web applications based on the actor model.
These helpers are used in our examples, for which you can find our boilerplate here.
We encourage you to read through the boilerplate examples first and then read through the code in this repository.
actor.ts
actor.ts contains a base class implementation for an actor, as well as functions to hookup() and lookup() actors on the web page.
For more detailed examples, please check out the in-file documentation.
watchable-message-store.ts
This store is an implementation detail of the messaging system used by hookup() and lookup() to allow actors to communicate with one another. You shouldn't need to interact directly with the message store, but it's here all the same if you do.
What do you think about XState, which is actor model inspired state handling often used on the front-end?
Ideally, I imagine it would be nice with Niladic Components (no props), so React could be a dumb View layer, and simply handle all state separately in XState…
isn't pre-emptively scheduled. Typically a process is blocked at a receive() (or any other blocking call) waiting for the next message and even if it isn't the scheduler will suspend it after it consumes it's reductions.
None of this is feasible in single threaded/event loop based JavaScript but it points to the possibility of tying process scheduling to message delivery:
A "processing scope" (replacing "actor") only gets processing control when it receives a message (with some exceptions; the message would likely be arrive via a subscription). To be well behaved it has to break up large tasks into phases which it initiates by sending a message to itself at the end of the current phase.
To interact with other "processing scopes" is has to send a message. However there is no immediate response (the message goes to the end of the delivery queue). If there is a response it will be received later at which point in time it can be processed (so the processing scope state has to reflect this "in progress interaction" - the equivalent to a "function call (returning a value)" to a separate processing scope).
So the basic functionality needed for a processing scope is a way to receive messages so it has something to do, and a way to send messages so it can collaborate with other processing scopes. For that to work the message router/scheduler needs to support a few things:
The entire system is built around postMessage(). For the purpose of discussion lets call a Window or Worker a "processing node".
Each node
routes messages (i.e. has to manage routing data)
messages to the local processing scopes are put on the delivery queue
messages to processing scopes managed by another node are immediately posted to the nearest node.
schedules processing by
delivering a single message to the local processing scope from the head of the delivery queue provided there is enough time left in the current processing slice
returning control to the event loop when the current processing slice is exhausted.
when the delivery queue is empty use queueMicrotask() to start the next processing slice when a message is placed on the delivery queue arriving from another node or a general send (e.g. caused by an input event).
Now a system like this is inherently asynchronous—so in my judgement has little to no chance to be adopted by the JavaScript community given how relieved everybody was when async/await was introduced.
In terms of the PolymerLabs MessageStore I would be concerned that forcing messages through IndexedDB would slow things down unnecessarily.
props will be involved whenever you use a component more than once on the same page to represent separate business entities.
As I said before
I need to mention that the identity of Component is not always the same as the identity of Instance of Component. That's why in some framework you need to specify the key.
although there are no real key here but different update props are passed to identify different entities. In certain degree it's the mismatch between UI and application proved again.
and the solution is fairly simple... encapsulate High Order Component
although it's not necessary to involve any architecture decision, I'm placing the kairo's solution here
const[External,ExternalImpl]=createConcreteConcern('External',function*(){const[leftValue,setLeft]=yield*State(0);const[rightValue,setRight]=yield*State(0);return{leftValue,rightValue,setLeft,setRight}});// a shortcut of `createConcern` with a default implementationconstValue=UI(function*({value,setValue}:{value:Cell<number>,setValue:Setter<number>}){constonChange=e=>setValue(e.target.value);returnComponent((_,$)=>(<span><inputvalue={$(value)}onChange={onChange}/></span>));});constApp=UI(function*(){const{leftValue,rightValue,setLeft,setRight}=yield*External;constLeft=yield*Include(Value.withProps({value:leftValue,setValue:setLeft}));constRight=yield*Include(Value.withProps({value:rightValue,setValue:setRight}));returnComponent((_,$)=>(<divclassName="App"><h1>Totals</h1><Left/><Right/>
total is {$(leftValue)+$(rightValue)}</div>));});
notably I made Value fully controlled because it's unnecessary to have a local state as there is already a source of truth.
@peerreynders regarding Actor-Model you mentioned in this thread, you might be interested in this lib: reatom.dev/ (but it also relevant to the overall discussion)
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
Yes, I think it’s precisely that same idea. Pete Heard talks a lot about separating out all business logic, so it is testable, and the UI being an afterthought (even one step further than what MobX does).
In broad strokes he's mapping Clean Architecture to the front end.
I'm still partial to this 2018 "actor inspired" architecture for the front end.
It doesn't share anything and only runs when it has a message to process
“An Actor, a model and an architect walk onto the web...”
The 9am rush hour
Lights, Camera, Action!
Headless Web Development
When should you be using Web Workers?
PolymerLabs / actor-boilerplate
A starting point for web apps based on the actor model.
Actor Boilerplate
A starting point for web apps based on the actor model.
Chrome Dev Summit 2018 Talk
Architecting Web Apps - Lights, Camera, Action!
We also wrote a series of blog posts with more detail on web development with the actor model:
What is this repository that am I looking at?
This is a very basic web app that uses the actor model. The actor model helps you to break your app’s core logic into small pieces that have to communicate with messages instead of using function calls. Adopting this model has multiple benefits on the web:
What’s in here?
This boilerplate…
PolymerLabs / actor-helpers
actor-helpers
Helpers to build web applications based on the actor model. These helpers are used in our examples, for which you can find our boilerplate here. We encourage you to read through the boilerplate examples first and then read through the code in this repository.
actor.ts
actor.ts
contains a base class implementation for an actor, as well as functions tohookup()
andlookup()
actors on the web page. For more detailed examples, please check out the in-file documentation.watchable-message-store.ts
This store is an implementation detail of the messaging system used by
hookup()
andlookup()
to allow actors to communicate with one another. You shouldn't need to interact directly with the message store, but it's here all the same if you do.License BSD-3-clause
Please note: this is not a Google product.
Too bad it didn't go anywhere … but as usual I digress …
What do you think about XState, which is actor model inspired state handling often used on the front-end?
Ideally, I imagine it would be nice with Niladic Components (no props), so React could be a dumb View layer, and simply handle all state separately in XState…
See my comment here
Expressed roughly in JavaScript-like syntax an Erlang process is at its simplest
Of course JavaScript
receive()
(or any other blocking call) waiting for the next message and even if it isn't the scheduler will suspend it after it consumes it's reductions.None of this is feasible in single threaded/event loop based JavaScript but it points to the possibility of tying process scheduling to message delivery:
So the basic functionality needed for a processing scope is a way to receive messages so it has something to do, and a way to send messages so it can collaborate with other processing scopes. For that to work the message router/scheduler needs to support a few things:
Now a system like this is inherently asynchronous—so in my judgement has little to no chance to be adopted by the JavaScript community given how relieved everybody was when async/await was introduced.
In terms of the PolymerLabs MessageStore I would be concerned that forcing messages through IndexedDB would slow things down unnecessarily.
Is postMessage slow?
But thanks for asking …
Note what is going on in his niladic solution:
He is failing to extract the variation of two near identical components in order to preserve their "niladic" property
props
will be involved whenever you use a component more than once on the same page to represent separate business entities.As I said before
although there are no real
key
here but differentupdate
props are passed to identify different entities. In certain degree it's the mismatch between UI and application proved again.and the solution is fairly simple... encapsulate High Order Component
although it's not necessary to involve any architecture decision, I'm placing the
kairo
's solution herenotably I made
Value
fully controlled because it's unnecessary to have a local state as there is already a source of truth.@peerreynders regarding Actor-Model you mentioned in this thread, you might be interested in this lib: reatom.dev/ (but it also relevant to the overall discussion)