samedi 12 août 2017

Advice on structuring a single-client server application

I am making an application which a user is meant to interact with in order to collect various data (compile data from several physical devices in various ways).

To do this, I decided on a web-based user interface, so most of the app is running on a "server" which controls the devices, and communicates with this Javascript UI using websockets. I have written this server in Python using Autobahn (among various other packages for dealing with the devices).

The application naturally has a lot of state: when to collect data, what data to collect, where to put it, etc.

Disregarding all of the code for the devices, the main server is laid out like:

.
├── handlers
│   ├── handler1.py
│   └── handler2.py
├── router.py
└── server.py

Right now I have the main server object (an Autobahn WebSocketServerFactory), which owns the state as an enum. It also owns a router, which it passes incoming messages from the client to. The router routes these messages to the correct handler, which reacts to the message and sends a response.

The handlers need to have access to the server's state, and also be able to change it. However giving a reference to the server object to each of the handlers feels like bad form (e.g. if I want to import the server in the handlers in order to do static type checking, then I get circular imports: server -> router -> handler1 -> server).

What is a well structured way to handle this with good form? Are there useful design patterns I should be trying to follow here that I am clearly ignoring?

Possibly of note: in order for the server to control the various devices I am using a publish/subscribe system. This makes it easy for the various handlers (and the classes I'm using to collect and store the data I want) to simply subscribe to a stream of data from a device.

Aucun commentaire:

Enregistrer un commentaire