Class, state, and representation

Many applications can be decomposed into the processing done by servers and by clients. A single server will exchange data with multiple remote clients. In a hybrid situation, an application can be both a client of other remote computers, and a server to remote clients. There is an intentional asymmetry that is used to simplify the definition of the protocol: a client makes a request to the server, and the server responds to the client. The client initiates each request and waits for the response.

Separating clients and servers means that objects must be transmitted between the two processes. We can decompose the larger problem into two smaller problems. The inter-networking protocols define a way to transmit bytes from a process on one host to a process on another host. Serialization techniques transform our objects into bytes and then reconstruct the bytes from the objects. It helps, when designing classes, to focus on object state as the content exchanged between processes.

Unlike the object state, we transmit class definitions through an entirely separate method. Class definitions change relatively slowly, so we exchange the class definitions by the definition of the class in the form of the Python source. If we need to supply a class definition to a remote host, we can install the Python source code on that host.

When a client is written in a language other than Python, then an equivalent class definition must be provided. A JavaScript client, for example, will construct an object from the serialized JSON state of the Python object on the server. Two objects will have a similar state by sharing a common representation.

We're making a firm distinction between the entire, working object in Python's working memory, and the representation of the object's state that is transmitted. The whole Python object includes the class, superclasses, and other relationships in the Python runtime environment. The object's state may be represented by a simple string. Consider the following:

>>> from dataclasses import dataclass, asdict
>>> import json

>>> @dataclass
... class Greeting:
... message: str

>>> g = Greeting("Hello World")
>>> text = json.dumps(asdict(g))
>>> text
'{"message": "Hello World"}'
>>> text.encode('utf-8')
b'{"message": "Hello World"}'

This example shows a simple class definition, Greeting, where the state is characterized by a single attribute value, message. The asdict() function, applied to an instance of a dataclass, creates a dictionary that we can serialize in JSON notation. Because the networks transmit bytes, the use of text.encode() creates a stream of bytes. This tiny example shows how the data class definition is entirely separate from the representation of the state of this example instance of the class.

Let's see how we can use HTTP and REST to transmit objects.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset