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