A discussion in application design and event propagation

Jay Nelson jay@REDACTED
Mon Apr 19 17:58:59 CEST 2010


Fred Hebert wrote:

 > I'm starting this thread to spark a discussion about Erlang  
software design.

Just yesterday I wanted to start a similar thread on "concurrency  
patterns."  I will do that as a separate thread.

I've found that with other languages I think of "software design."   
With erlang, I find it more fruitful to think of "architectural  
design" because the language allows you to make system level choices  
and enforce them in the software structure.  Limiting your thinking  
to "software patterns" and "software design" may not get you thinking  
about the right elements of your problem.  It's just that other  
languages have no other elements to the problem than the software  
itself, so our tendency is to revert to what's available.


 > You'd have (I imagine) one process representing the dealer and the  
table
 > (D). Then you have 3 players, P1, P2 and P3, each represented as a  
process.

That's a good start using software as the principle.  Instead let's  
look at the architectural issues:

1) Where are users coming from?
         - I'll assume Internet connected.
2) What to do if a connection is lost?
         - Most game tables don't allow you to bail when you are losing.
         - A 'bot' finishes the game for you since money is on the line.
3) How many connections are you expecting?
         - One game table is easy inside erlang distribution.
         - Many tables is too much inter-node chatter.


Using distributed erlang you get node-to-node pings to detect node  
failures.  This can lead to too much data traffic.  If many users are  
expected, you probably want TCP connected users rather than erlang  
node connected users. Distributed erlang (using the OTP distribution  
techniques) tends to require predetermined node names and process  
configurations, as opposed to Distributed TCP which leads to dynamic  
connectivity without enumerating participants in configuration files.

pg also uses global names to manage the groups.  This introduces  
potential contention for the global name (no global resource goes  
unpunished in concurrent architectures -- Patrick Nyblom SF 2010).

If you consider the architecture, you are missing some elements in  
your sketch. You should include them before you evaluate the design  
choices:

1) User initiates a connection from a browser (assumption on my part)
2) TCP connects the user to some erlang server process
3) User needs to be represented by a proxy in case of connection loss
4) Current game should be able to finish if a user disconnects
5) New game may or may not be allowed to start if user missing

New requirements:

6) Can non-players observe the game?
7) Can non-players interact with game players (chat with them)?

I can see an approach that there is a gallery and the players at the  
table.  The gallery can chat amongst themselves, and the players can  
interact amongst themselves.  The gallery observes all, the players  
only see the table (for example).


Architecturally, I would determine the principles that define a good  
solution before choosing a software pattern:

1) How many users can be supported?
2) What happens in the common failure scenarios?
3) How do you enforce the game rules (audience vs players, etc)?
4) What kind of responsiveness is needed?
5) How much hardware are you willing to configure?
6) How dynamic is your configuration and user participation?


For this problem gen_event probably has the most opportunities for  
you as the central design element.  It allows multiple groups to  
observe events with differing functionality for the groups.  You  
could use pg for the players and for the gallery, and gen_event to  
distribute the messages.  But you are missing the connecting server  
and the proxying user process that automatically represents (and  
governs) the users actions.

With erlang, don't just look at software patterns, step back and look  
at architectural patterns.  You will find yourself architecting  
loosely coupled systems, with layers of connectivity, routing,  
application constraints and application logic.  Each of these  
elements can use different software patterns, but the way they  
interact should be flexible, dynamic and auto-healing.

Also remember, there is no "good" or "bad" solution.  Each solution  
has certain characteristics it exhibits such as speed, resilience,  
capacity, etc.  One solution may be better for one situation and  
worse for another, based on the measurement that matters in each  
case.  Don't be biased against an approach that was rejected in a  
previous problem application -- it may turn out useful in a different  
situation.

jay



More information about the erlang-questions mailing list