Usage of objects

As for now, our application was designed in a simplistic - but not realistic - way, in terms of object decomposition : all the resources bags were attached in bulk to one single object.

Here, we will expose a method to split our application into distinct objects. The relevance of this decomposition principle will become obvious in the following lessons as the application will get more complex and refined. Moreover, this decomposition into several objects is an essential requirement for managing distributed systems.

Initial application design

Initially, all our bags were in the same Test object, as reminded below:

 bag1 = data.BagDescription()
 bag1.name = "Customer"
 bag1.type = ("Multiset", "TupleSpace")
 bag1.fieldnames = ['name', 'location']
 bag1.params = {}

 bag2 = data.BagDescription()
 bag2.name = "Connection"
 bag2.type = ("Multiset", "TupleSpace")
 bag2.fieldnames = ['depature', 'arrival']
 bag2.params = {}

 bag3 = data.BagDescription()
 bag3.name = "Destination"
 bag3.type = ("Multiset", "TupleSpace")
 bag3.fieldnames = ['name', 'arrival']
 bag3.params = {}

 bag4 = data.BagDescription()
 bag4.name = "Travel"
 bag4.type = ("Multiset", "TupleSpace")
 bag4.fieldnames = ['departure', 'arrival', 'name']
 bag4.params = {}

 Object1 = data.ObjectDescription()
 Object1.name = "Test"
 Object1.type = "Coordinator"
 Object1.port = None
 Object1.host = H1
 Object1.application = A1
 Object1.nameserver = NameServer
 Object1.params = {param.OBJECT_TRACE_LEVEL:gTraceLevel}
 Object1.list_of_bags = [bag1, bag2, bag3, bag4]
 LIST_OF_OBJECTS.append(Object1)

Even if this decomposition - or absence of object decomposition - may seem OK for a toy application, this design is not suitable for a real-world application, intended to be scalable, maintainable and distributed.

Improved application design

A better practice would be to split the application into meaningful objects, according to logical matters, and to attach to each of them the appropriate bags and behaviors.

For instance, if we consider the same bags and resources as in our previous initial design, the following objects may be constituted:

People object

The People object manages the information related to the people willing to use the metro. With the same resources definitions as the initial design, this refers to the Customer and Destination bags.

The People object is implemented like this :

 bag1 = data.BagDescription()
 bag1.name = "Customer"
 bag1.type = ("Multiset", "TupleSpace")
 bag1.fieldnames = ['name', 'location']
 bag1.params = {}

 bag3 = data.BagDescription()
 bag3.name = "Destination"
 bag3.type = ("Multiset", "TupleSpace")
 bag3.fieldnames = ['name', 'arrival']
 bag3.params = {}

 PeopleObject = data.ObjectDescription()
 PeopleObject.name = "People"
 PeopleObject.type = "Coordinator"
 PeopleObject.port = None
 PeopleObject.host = H1
 PeopleObject.application = A1
 PeopleObject.nameserver = NAMESERVER
 PeopleObject.params = {param.OBJECT_TRACE_LEVEL:TRACE_LEVEL}
 PeopleObject.list_of_bags = [bag1, bag3]
 LIST_OF_OBJECTS.append(PeopleObject)

Metro object

The Metro object is responsible for the definition of the metropolitan network. Here, this involves the Connection bag.

 bag2 = data.BagDescription()
 bag2.name = "Connection"
 bag2.type = ("Multiset", "TupleSpace")
 bag2.fieldnames = ['departure', 'arrival']
 bag2.params = {param.ASPECT_BLOCKING : False, param.ASPECT_READONLY:True}

 MetroObject = data.ObjectDescription()
 MetroObject.name = "Metro"
 MetroObject.type = "Coordinator"
 MetroObject.port = None
 MetroObject.host = H1
 MetroObject.application = A1
 MetroObject.nameserver = NAMESERVER
 MetroObject.params = {param.OBJECT_TRACE_LEVEL:TRACE_LEVEL}
 MetroObject.list_of_bags = [bag2]
 LIST_OF_OBJECTS.append(MetroObject)

Supervision object

In addition, we add a new Supervision object, used to store/manage journeys made by the customers in a Travel bag :

 bag4 = data.BagDescription()
 bag4.name = "Travel"
 bag4.type = ("Multiset", "TupleSpace")
 bag4.fieldnames = ['departure', 'arrival', 'name']
 bag4.params = {}

 SupervisionObject = data.ObjectDescription()
 SupervisionObject.name = "Supervision"
 SupervisionObject.type = "Coordinator"
 SupervisionObject.port = None
 SupervisionObject.host = H1
 SupervisionObject.application = A1
 SupervisionObject.nameserver = NAMESERVER
 SupervisionObject.params = {param.OBJECT_TRACE_LEVEL:TRACE_LEVEL}
 SupervisionObject.list_of_bags = [bag4]
 LIST_OF_OBJECTS.append(SupervisionObject)

Adapted script

The application bags have moved on from being the initial global Test object to more focused objects. As a consequence, initialization and management scripts have to be adapted to reflect this evolution.

init.ls

The initialization script source becomes :

 ::
 {
 ["People","Customer"].put("alice","A") ;
 ["People","Customer"].put("bob","B") ;
 ["People","Customer"].put("charles","C") ;
 ["People","Customer"].put("denis","A")
 }.

 ::
 {
 ["People","Destination"].put("alice","D") ;
 ["People","Destination"].put("bob","D") ;
 ["People","Destination"].put("charles","D") ;
 ["People","Destination"].put("denis","D")
 }.

 ::
 {
 ["Metro","Connection"].put("A","B") ;
 ["Metro","Connection"].put("A","D") ;
 ["Metro","Connection"].put("B","D")
 ["Metro","Connection"].put("C","D")
 }.

Note : the Connection resource ('B', 'D') was integrated in the initialization script to avoid the requirement of having to insert it manually through the monitor.

The related script description in the quinoa.py is adapted as :

script1 = data.ScriptDescription()
script1.application = A1
script1.name = "init"
script1.list_of_objects = [PeopleObject]
script1.policy = "Automatic"
LIST_OF_SCRIPTS.append(script1)

trom.ls

In the same way the trom.ls script source is updated as :

 {*,!}["People","Customer"].rd(name,departure) &
 {*,!}["People","Destination"].rd(name,arrival) &
 {*,!}["Metro","Connection"].rd(departure,arrival)
 ::
 {
 ["People","Customer"].get(name,departure) ;
 ["People","Destination"].get(name,arrival) ;
 ["Metro","Connection"].rd(departure,arrival);
 ["People","Customer"].put(name,arrival) ;
 ["Supervision","Travel"].put(departure,arrival,name)
 }.

and its definition in the quinoa.py becomes :

 script2 = data.ScriptDescription()
 script2.application = A1
 script2.name = "trom"
 script2.list_of_objects = [SupervisionObject]
 script2.policy = "Manual"
 LIST_OF_SCRIPTS.append(script2)

Now, our application is split in multiple objects. Each object manages bags related to same logical aspect. Later, these objects will be refined and enhanced as the application becomes more realistic and precisely designed.

Visualization

You can use the monitor to visualize the application in its current state. By using to the following URL, you should witness that it is now split into the 3 new specific bags, in addition to the NameServer.

http://localhost:9999/NameServer/MONITOR