<div dir="ltr"><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div>Here are some thoughts off-hand. They are not too fleshed out.<br><br></div>* I'd definitely run things via Ranch if possible. Some of the subtler things in and around reconnect accept pools and so on happens to be solved well by Loic in Ranch.<br><br></div>* It may be possible to generalize buffer handling from the user. Consider a function handle(Data, BufferState) -> {Cmds, UpdatedBufferState}, where Cmds is a list of the commands the user entered.<br><br></div>* Most modules in a BBS probably runs in a Request -> Reply fashion. You send a command to the module and it replies with a new display state you send to the BBS client. Since each module will keep its own state, you can stuff that into a process.<br><br></div>* Modules may have their own state. They may also have BBS-global state which enables communication between clients. Say you have a forum module. It will have a forum_backend in which you store the actual posts in the forum. When a client requests forum access, you spawn a helper which runs the Request/Reply pattern proxying the data in the backend to the client.<br><br></div>* gen_statem is probably most useful in modules, and not so much in the client itself, unless the interactions are complex and there are certain things which can only happen in some limited states, etc.<br><br></div>* Be aggressive and link everything or use monitors. That way, you can easily handle errors in parts of the system without taking it all down. Also, you can probably handle a hangup by simply terminating the client process and then have modules handle a 'DOWN' message and clean up.<br><br></div>* Old BBS'es did not really have it that much, but you could write a general command parser and then supply parsed terms to modules. This becomes yet another state machine, but it often kept inside the client process:<br><br></div>-record(state, {<br></div>    buffer_state :: buffer_state(),<br></div>    parser_state :: parser_state(),<br></div>    socket :: inet:socket(),<br>    ...<br>}).<br><br></div>* A common beginners mistake is to want to process everything en masse. The rule of thumb is to create a process for each truly concurrent activity in the system. With that in mind, it may be that module state should not by in a proxy process, as above, but rather be embedded directly in the client. The forum_backend is truly concurrent however and warrants its own process.<br><br></div>* The counterpoint to the last remark: don't be afraid to use a process to isolate parts of your system and keep complexity down. Juggling many states in one process at the same time means you have to handle every complex cross-interaction between them. If you push something to its own process, then chances are there are less cross-talk and thus a system which is easier to understand and handle.<br><br></div>* Finally: rather than focusing on the "behaviour", focus on the interaction protocol. When you talk HTTP, you don't do that by inheriting a HTTP-class. You do that by speaking the protocol. This is powerful because you *don't* know the internal implementation of the HTTP server. REST was only possible in the first place because HTTP was a protocol. In a BBS, focus on the module interaction protocol. You don't care for the internal implementation, but rather how you talk to it. Once established, it may be that 80% of the modules can implemented via a generic callback framework, as is the case for the gen_server (where the protocol is OTP). But there are always 20% which are not fitting in, and you want that to be possible as well.<br><br></div>Feel free to follow up :)<br><br></div><br><div class="gmail_quote"><div dir="ltr">On Tue, Jan 24, 2017 at 6:02 AM Thom Cherryhomes <<a href="mailto:thom.cherryhomes@gmail.com">thom.cherryhomes@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class="gmail_msg">Would you, for example, build the ranch protocol as simple as possible, and link the other application servers, as needed, with a common protocol?</div><div dir="ltr" class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">-Thom</div></div><br class="gmail_msg"><div class="gmail_quote gmail_msg"><div dir="ltr" class="gmail_msg">On Sun, Jan 22, 2017 at 2:56 PM Thom Cherryhomes <<a href="mailto:thom.cherryhomes@gmail.com" class="gmail_msg" target="_blank">thom.cherryhomes@gmail.com</a>> wrote:<br class="gmail_msg"></div><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class="gmail_msg">
        
        


<p style="margin-bottom:0in;line-height:100%" class="gmail_msg">Hello, everyone.
This is my first post to the list. 
</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg"><br class="gmail_msg">

</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg">I’m a long time
swiss army knife of a software and hardware engineer who has started
to pick up Erlang, because I believe it and languages like it to be
the future of software development.</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg">With that said, I am
working on a personal project of mine that I have wanted to complete,
a 21<sup class="gmail_msg">st</sup> century version of a BBS system, and I believe
Erlang and OTP are a good language and toolkit to write it in.</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg"><br class="gmail_msg">

</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg">Code is being
dropped here: <a href="http://github.com/tschak909/nakbbs" class="gmail_msg" target="_blank">http://github.com/tschak909/nakbbs</a></p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg"><br class="gmail_msg">

</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg">I am experimenting
with both Ranch and just using gen_tcp with my own socket pools, but
I do have some design questions.</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg"><br class="gmail_msg">

</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg">The telnet ports
need to present a definite series of states, broken up into seperate
pieces:</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg"><br class="gmail_msg">

</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg">I have definite
common events that can be stretched across multiple use cases:</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg"><br class="gmail_msg">

</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg">* Display</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg">* Wait for line of
input</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg">* Wait for character
input</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg">* branch to another
menu</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg">* hang up</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg"><br class="gmail_msg">

</p>
<p style="margin-bottom:0in;border-top:none;border-bottom:1px solid rgb(0,0,0);border-left:none;border-right:none;padding:0in 0in 0.03in;line-height:100%" class="gmail_msg">
But there will also be definite sections of the system, which could
be thought of as states:</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg"><br class="gmail_msg">

</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg">* Authentication</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg">* Message Browser</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg">* Message Editor</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg">* Various Games</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg"><br class="gmail_msg">

</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg">etc.</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg"><br class="gmail_msg">

</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg">and I’m trying to
think of an appropriate architectural pattern that will avoid me
basically having to cram every conceivable state as a sort of
hierarchy of tuples into a single gen_statem module. How can I
approach this in a nice abstract and extensible manner, that I could
for example push into a Behaviour and subsequently utilize for
different terminal types? It would be nice to split up the different
parts of the system into applications that would essentially be
called from well defined APIs…</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg"><br class="gmail_msg">

</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg">I’m just trying to
figure this all out, and would love a semblence of direction so I can
do the proper research and deeply understand what I need to learn.</p></div><div dir="ltr" class="gmail_msg">
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg"><br class="gmail_msg">

</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg">-Thom</p>
<p style="margin-bottom:0in;line-height:100%" class="gmail_msg"><br class="gmail_msg">

</p></div></blockquote></div>
_______________________________________________<br class="gmail_msg">
erlang-questions mailing list<br class="gmail_msg">
<a href="mailto:erlang-questions@erlang.org" class="gmail_msg" target="_blank">erlang-questions@erlang.org</a><br class="gmail_msg">
<a href="http://erlang.org/mailman/listinfo/erlang-questions" rel="noreferrer" class="gmail_msg" target="_blank">http://erlang.org/mailman/listinfo/erlang-questions</a><br class="gmail_msg">
</blockquote></div>