[Twisted-Python] Clean pb solution for two-way object sync?

Daniel Sank sank.daniel at gmail.com
Thu Sep 26 00:05:38 MDT 2013


(Apologies for double send but I forgot the subject line)

Dear Twisted users,

I recently found myself implementing a design pattern that I think
twisted.pb was specifically designed to address. I think I'm not using pb
correctly so I'd like advice. This is a somewhat longish post because I
need to describe the problem I'm trying to solve.

I have done internet searches on Stack Overflow and this list but have not
found the answer to my question. If I've missed something kindly direct me
to the appropriate reference.

I want to implement something functionally equivalent to a network chess
game. I first consider how I would do this on a single computer with no
network (maybe this is bad thinking). Each piece in the game is represented
by an instance of class Agent. Each agent has a .graphics attribute which
is an instance of a class from a GUI toolkit library or equivalent.
Whenever an agent in the game needs to do something there will be business
logic executed by the game objects proper (ie the agents) which will invoke
methods on the .graphics objects to update the screen. This sort of
structure seems natural as it allows easy integration of drag/drop, mouse
click detection etc. It also nicely separates the real business logic from
the GUI.

Now I want to run over the network. The question is how should I set up
references between the client and server objects?

Surely the server will maintain a set of objects representing the pieces in
the game. It seems reasonable that each user's program will have a
corresponding set of objects (with .graphics attributes). The issue is,
what do we mean by "corresponding" and how do these objects talk to one
another? Following is my idea so far:

Each instance of AgentClient has a .server attribute which is a remote
reference to an instance of AgentServer, and each instance of AgentServer
has a .clients attribute which is a list of remote references to instances
of AgentClient.

class AgentServer(pb.referenceable):

    def remote_move(self, targetSquare):
        """Handle move request from client"""
        if self.thisMoveIsLegal(targetSquare):
            self.position = targetSquare
            for client in self.clients:
                client.callRemote("move", targetSquare)

    def thisMoveIsLegal(self, targetSquare):
        <check that this is a legal move>

class AgentClient(pb.referenceable):

    def requestMove(self, targetSquare):
        """Tell server we'd like to move"""
        self.server.callRemote("move", targetSquare)

    def remote_move(self, targetSquare):
        """Server told us we moved"""
        self.position = targetSquare
        self.graphics.setNewPosition(targetSquare)

This isn't THAT bad. The client's requestMove is thin and unecessary (I put
it there for illustration). Still I need to have two separate classes with
corresponding methods to handle moving the piece. This seems like the kind
of thing I could twisted.pb to solve more cleanly if I only would look in
the right place.

This problem gets even worse when I think about how to birth new in-game
objects. It would have to look like this:

class PlayerServer(pb.referenceable):

    def newAgent(self, asker):
        """Client told us it wants a new Agent"""
        if self.thisIsLegal():
            a = AgentServer()
            self.agents.append(a)
            for client in self.clients:
                d = client.callRemote("newAgent", a)
                d.addCallback(lambda obj: a.clients.append(obj))

class PlayerClient(bp.referenceable):

    def requestNewAgent(self):
        """Tell the server we want to spawn a new Agent"""
        self.server.callRemote("newAgent", self)

    def newAgent(self, serverObj):
        a = AgentClient()
        self.agents.append(a)
        a.server = serverObj
        return a

This just looks wrong. Any advice?

Thank you in advance for your help.

Regards,
Daniel Sank
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://twistedmatrix.com/pipermail/twisted-python/attachments/20130925/5fa99ba8/attachment-0001.html>


More information about the Twisted-Python mailing list