[erlang-questions] Re: A discussion in application design and event propagation

Fred Hebert mononcqc@REDACTED
Mon Apr 19 19:21:07 CEST 2010


On Mon, Apr 19, 2010 at 11:58 AM, Jay Nelson <jay@REDACTED> wrote:

> 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.
>
>
Without wanting to get too much into a design war (well, this is a design
discussion, after all), I usually find it useful to avoid making too many
assumptions about the system I'm designing and where it's going to be used,
whether it is from a browser, a direct socket connection, or even through
XMPP or emails being sent back and forth.

The point of view I usually take is "make the core of it work standalone,
and then plug it in whatever system I need". I find it gives some good
separation of concerns and helps modularity on its own. What happens if you
want to support players from more than one platform? This break also lets
you draw a line on where the user becomes a trusted entity or not. If you
decide to do all your validating on the outer layers (connection) of the
game server, you can write your application as if it were completely trusted
and you no longer need to deal with propagation of errors and whatnot.

I like to see connectivity and client calls as an implementation detail
around the core application. Of course this doesn't always remain true if
one app is for your friends and you and the other for 5 million people at
once -- some planning has to be kept in mind.

One approach seems to be a bit bottom-up while the other sounds like the
opposite.


> 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


The proxy for a user is a pattern I've found extremely useful when handling
connections from a browser -- I've designed chut (still a prototype,
http://bitbucket.org/ferd/chut/) with this idea in mind, and I found it to
be quite useful when I wanted to do things like handle more than N client
connections from a single user. I wouldn't go without it were I to expect my
real-time application to be used in a browser.


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


The observation of the game is interesting, but I'm wondering whether it has
any importance when considering if you'd want to use process groups or a
system like gen_event. In any case, the end result is equivalent, isn't it?

Now about the chat system, I'm thinking this should be part of a different
application still exposed to the user. Conflating chat and whatever
game/project/system you're building means bundling it with every part of it.
If you suddenly want to add Poker to your online casino, you've got to
re-write a new chat system for that one. A standalone chat system seems more
appropriate from my point of view, but I'm getting a bit off-topic here.

>
> 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.
>
> Agreed. Erlang and its lightweight processes/concurrency makes it much
easier to get an architectural viewpoint and to design software with
modularity in mind.


> 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.
>
> Hence this discussion :)

> jay
>
>
> ________________________________________________________________
> erlang-questions (at) erlang.org mailing list.
> See http://www.erlang.org/faq.html
> To unsubscribe; mailto:erlang-questions-unsubscribe@REDACTED
>
>


More information about the erlang-questions mailing list