Persistence Tutorial using Visual Zero

Index

Introduction

An example, a simple address book, will be discussed through this section in order to show the interactive capabilities of this visual environment, as presented previously. Follows an image of the environment running a simple HelloWorld object.

The VZero environment

The common traits of persons

Firstly, a new object will be created to deal with personal information in the address book. Once the environment is started, it is possible to press new, having object chosen in the list under the container explorer, in order to create this object. The environment will trigger the execution of the createChild() method of the Object object, asking for its parameters. Actually, the only parameter needed is the object's name, so the environment is thus asking for the name of the object. By entering “TraitsPerson(including quotes), the object representing all persons will be created. An object inspector will open, showing the properties of the new TraitsPerson object. The explorer is, as discussed before, divided in three sections, up to down: attributes, own methods and inherited methods. Although the object has been created successfully, it has no information to hold or behaviour to offer. It is possible to solve this by selecting the add attribute contextual menu option or by choosing addAttribute in the inherited methods section, pressing the right button of the mouse and selecting execute.

Adding an attribute

A new dialogue box will appear asking for the arguments the method will be invoked with. In this case, the name of the attribute must be provided, as well as the object it will point to. The name of this new attribute is “name”, which will be used in order to store the name of the person. So this is the value for the first box, always remembering that it is needed to enter it with double quotes, as it must be interpreted as a new String object. The contents of the attribute to be created is also a string, so for example "John Doe" can be an appropriate value. The environment automatically creates special values such as strings (enclosed in quotes), numbers (as themselves), and vectors (enclosed in braces), before invoking the method addAttribute with them. The last step is to press Accept, in order for the VM to execute the given method.

Adding an attribute

 When a method is executed, an object inspector with the properties of the object returned by the execution is displayed. In this case, it is not relevant, so its window can be closed, going back to the TraitsPerson object inspector. The new attribute appears now among the attributes of the object, the one that appears at the top of the explorer. It is possible to double-click it in order to see the object it is pointing to, a simple new String object.

The same steps taken for adding the name attribute to the TraitsPerson object, can be taken in order to create the attribute email, using this time the values "email" and "John@doe.com" as arguments. Again, the use double-quotes is needed here.

It would be useful to be able to change the name and the e.mail of the person. That behaviour must be accomplished by a method. In order to add a method to a given object, the contextual menu option add can be used, as well as executing directly the addMethod method inherited from Object.

Executing setData

A dialogue box similar to the one that was presented for the attributes will appear. This time, the name of the method, and a vector with the names of the attributes must be provided. The name of the method is “setData” (including the double quotes), and a vector {“aName”, “anEmail”} must be entered for its arguments. Once created (pressing the Ok button), the new method will appear in the methods section of the object inspector, the one in the middle of the window. Its source code must be entered, which corresponds with the following Zero assembler (instructions can be entered by double-clicking the the new method): SET aName, ASG name, SET anEmail, ASG anEmail, changing each comma by a carriage return.

Executing setData

This assembler code just assigns the object pointed by arguments and make the attributes point to them. If the Compile button is pressed, then that instructions will become the new body of the setInfo method. Once returned to the object inspector for TraitsPerson, it can be executed as any other method in order to verify its behaviour.

The Person prototype and a first instance

Now, using the controls below the container explorer of the main window, a new object, called Person, must be created in order to be able to create new persons by means of a copy operation. This new and empty object will appear described by an object inspector if it is double-clicked in the container explorer. In order to make it derive from TraitsPerson, the parent attribute must be selected, and clicking it with the right button of the mouse, the change option chosen from the contextual menu.

Changing the parent attribute

Of the scrollable list in the assign object dialog, the TraitsPerson should be chosen. In order to create new Person objects, it is just needed to press the copy button of the object inspector. After providing the name of the object, an exact copy of Person will be created (which is actually empty: the important concept right now is that it inherits from TraitsPerson). For an example of Person with one of the developers of Zero, the new name could be baltasar.

Once created, the object will appear in an object inspector. It is not linked to any container, so it will be lost as soon as the inspector is closed. Therefore it must be saved (using the appropriate button in the inspector) to be stored in the current container. As expected, the button Save on the top of the object inspector must be pressed. The object's name will now appear in the container explorer. Note that, as it happens in this example, the current container is Exe, the object will be lost when the VM finishes its execution.

Please take into account that it is possible to avoid separating Person and TraitsPerson, having only one object, namely Persona. But each time an object was created, all methods and attributes would be copied at the same time, which would make the copy very expensive. With this separation, methods exist only in one, shared, object (more or less similar to a class), while the state would be copied only each time a new object was created [15].

The object baltasar has been created, though its attributes have not been set properly. In order to achieve this, the setData method should be called with the appropriate arguments, which are “Baltasar” and “jbgarcia@pleasenospam.uvigo.es" , respectively.

It should be noted that attributes name and email are now part of the object baltasar. This happens because while not modified they share the very same attributes with TraitsPerson, but as soon as they are modified a new instance of these attributes is created in the object. This technique is called copy-on-write, which means that the duplication is done only when necessary.

The address book

Now it is needed to introduce this Person instances in a data structure, allowing some kind of searching. The natural key would be the name of person, which makes a map (an association between strings and objects) the ideal structure. The standard library has a map, so it is possible to create the new data structure just by inheriting from the Map object in the IntStdLib container. In order to achieve this, a new object must be created (for example, addressbook) and its parent attribute must be changed (as explained above) to point to Map, just by introducing its reference: Map (library objects are always reachable). The map already provides an add() method that takes a string and an object as arguments.

The addressbook object

A more convenient add() method, automatically taking the name of the Person object as index for the map would be really useful. Thus, a new method, called “add”, taking only an object as parameter ({ “aPerson” }), must be created in addressbook, with a new body presenting the functionality pursued : SET aPerson.name, MSG __this ^add __acc aPerson, RET __acc. This method just takes the name of the object passed as argument and calls the add method in the parent object (that is the meaning of '^') with this name and the object itself. In order to store the object baltasar in the address book, the recently created method of this object must be executed, selecting baltasar from the drop-down list.

Making objects persistent

Although the main objects of the application have been created, they are stored in the Exe container. This container is always transient, which means that if we end the execution of the VM all the Person objects, the address book, etc., will be lost. In order to preserve these objects, they must be included in a persistent container. There are already some persistent containers available in the Zero persistent programming system. The root (psRoot), and the standard library container (psRoot.IntStdLib). None of these are appropriate for the needs of the exercise: the standard library should be only used to store objects like Map, String or Object, while storing objects of user applications in the root container is allowed but not correct: that behaviour would convert the persistent store in a mess of objects. The correct solution is to create a new container. In order to get to the root container, the parent container button must be pressed until the root container is reached (i.e., it is not possible to go up in the hierarchy any more, one click away from Exe). Then, “container” must be selected in the pull-down box and press new. A new container will be created under the root one, after entering its corresponding name which could be “Addressbook.

Once the container has been created, the recently created objects should be stored inside it. In order to achieve this: the Addressbook container must be entered with a double-click in the container explorer and, again in the contextual menu of the container explorer, add objects should be chosen. That will trigger the execution of the add() method of the container object. In the dialogue window, select addressbook from the pull-down menu. The addressbook object will appear now as part of the Addresbook container.

Inserting the addressbook object is enough to have all remaining objects (TraitsPerson and baltasarPerson) inserted as well, just because of the relations among them. The addressbook object stores a reference to baltasarPerson, while baltasarPerson stores a reference (through the parent attribute) to the TraitsPerson object. The VM will follow all these references to determine which objects must be made persistent as well inside the container (this means that the effect will not be seen until the environment is closed and reopened, though the objects can always be inserted manually). On the other hand, Person, the prototype object created as a factory of new persons, will have to be copied explicitly (although this is not mandatory for this example).

If the environment is shut down now, these persistent objects will be stored. When open up again, the Addressbook container will be available under the root container, with the previously created objects inside it. These objects are now also available through other programs created with the compilers or the assembler. This shows how easy is to make an object persistent: just making a persistent object point to it with one of its attributes does the job. From the point of view, there is nothing as simple as this, not needing to worry about any saving/restore mechanism.

If a user interface is provided (which can be built with this programming environment or by any other of the available means), then the addressbook application will also be available for execution just by using the command-line VM.