Back to index

10 Summary & Conclusions

This last chapter summarises what has been achieved and outlines areas for further research, both in the fields of composable message semantics and distributed computing.

10.1 Summary

We've discussed the semantics of method invocation both for systems with a fixed number of semantics and systems offering the means to add an arbitrary number of new semantics. A fixed set of semantics restricts the flexibility of the programmer in structuring his/her application and inhibits the introduction of additional transparencies, e.g. replication and transaction transparency. Existing systems, which offer the flexibility of an arbitrary number of semantics, either require reduced transparency or degrade the overall performance.
We introduced a framework for the construction and composition of arbitrary new message semantics. The framework is based on the Decorator and the Strategy design patterns. We used an object-centric view, which allows us to define the semantics not at the class level but at the object level. We even extended this notion and allow for every object to have several different semantics simultaneously. We used this facility to offer different views of an object.
Our framework supports the definition of pre- and post-actions for method invocations. Additionally we strictly distinguish between caller-side and server-side semantics. This distinction enables the programmer to define the environment (address space) in which the semantic is executed.
To increase the performance without losing neither flexibility nor transparency, we introduced the notion of just-in-time stub generation. Using the class definition and the semantics supplied by the application programmer, we generate and compile the necessary stub and skeleton snippets only at run-time. The additionally available information, which is gained by delaying the generation process, allows for late adaptations and optimisations.
Another goal while implementing our prototype was to make it as small as possible. We omitted all features not vital for our purposes. This results in an extremely small implementation (see Figure 10.1).

10.2 Future Work

There are several major directions for future research based on the work presented in this thesis. The development of further invocation abstractions, invocation filters, optimisations, a more flexible transport mechanism and a more flexible field update technique.
The set of semantics implemented in the prototype is quite small. We implemented only a few filters and abstractions in order to proove the feasibility of our concepts. However, the range of possible semantics seems to be infinite. Here are some examples:
  • Filters enforcing QoS (quality of service) restraints, e.g. at-most-once execution, execution within 10 minutes É
  • Time independent invocation used for mobile computing.
  • Transaction filters. Using our composable message semantics, it is possible to transparently join invocations of different methods on different receivers within one transaction.
  • A filter that redirects invocations to other receivers, e.g. depending on the current network or processor load.
Another interesting area for future research is the adaptable update semantic for stub fields. Our current prototype implements only two choices. Either the fields of stub objects are ignored by the invocations or, the server object sends back all its fields packed together with the invocation results. Aspects of interest are the partial update [HaPM93] and the research into bi-directional update mechanisms for object fields.
The transport layer of the prototype of our distributed objects system is fixed. This is an implementation restriction and by implementing more flexible client-side abstractions, one could achieve a highly flexible transport layer.
Marshalling turned out to be the main obstacle for an efficient implementation. One way to achieve better performance would be to move our composable invocation semantics or at least the necessary marshalling mechanisms, into the object model of an object-oriented operating system. By making this move, we would gain increased flexibility on the level of the operating system. We think that the necessary prerequisites, such as dynamic adaptation or code generation, will have to be met by every competitive object-oriented operating system. Examples of systems that fulfil all these requirements are the Java VM or the JavaOS.

10.3 Implications on Language and Application Design

Composable message semantics are only concerned with the message passing facility of the host language. In order to be activated, they need dynamically bound procedures, i.e. methods. The more invocations that occur, the more possibilities we have for the customised semantics to change the behaviour of the application. This results in some guidelines for language designers and for application programmers that wish for run-time flexibility:
  • Enforce dynamic dispatch. Statically determined access cannot (easily) be decorated at run-time. Thus, we consider procedure calls and direct access to class fields as potential obstacles for extensibility.
  • Prohibit direct access to class fields. Statically bound access inhibits not only the introduction of access semantics, but also complicates the semantics of stub objects. Statically bound access leads to ambiguities between the fields of the real object and the fields of the stub object. This problem does not occur, if field access is only possible through accessor functions. We try to offer a solution by offering adaptable field update semantics during method invocations. Similarly, Spring [HaPM93] offers objects, which are not server based and objects where the state of the object is split between the client and the server. However, the usefulness of our adaptable field updates remains to be verified in future research.
  • Refrain from compile-time optimisations. The Oberon compiler optimises some kinds of method invocations at compile-time. Invocations on private methods are resolved by the compiler and the generated code performs no dynamic dispatch, but the system invokes the method using a static invocation (procedure call). In these cases, the assigned semantics are not activated, even though the dynamic dispatch table is patched accordingly. Even worse is the use of procedure in-lining. Some compilers in-line methods, whenever they are small enough and are statically seen as being unambiguous. Typical examples for such candidates are accessor functions for class fields. However, in a distributed environment, inlining probably will not be the case.
We can conclude by noting that one should not restrict possible run-time choices by applying automatic or manual optimisations at design or compile-time.

10.4 Conclusions

It is tempting to assume that all object interactions can be performed using just one (synchronous) method invocation semantic. Adding synchronous remote method invocation does not really resolve this restriction. In practice, this uniformity usually turns out to be restricting and penalising and the myth of "distribution transparency" is very misleading. It is now relatively well accepted that the "one size fits all" principle does not apply in the context of distributed object interactions. Most uniform approaches to object-oriented distributed programming have recently considered to extend their original model in order to offer a more flexible choice of interaction modes. For example, the OMG is in the process of standardising the messaging service that complements the original CORBA model with various asynchronous modes of interaction [OMGc].
The overall conclusion of this thesis is, that the removal of the fixed invocation semantic and the introduction of a flexible framework for invocation semantics, increases the flexibility with which a programmer can structure an application. This flexibility can be offered without a massive decrease in performance. We believe that the modes used for distributed interaction should, like many other programming aspects, be represented by an extensible class library instead of being hardcoded into the language. In other words, we advocate an approach where invocations are promoted to the rank of first class abstractions. For the demanding tasks of future software systems, composable message semantics seem to be a promising technique. The presented applications show the usefulness of our approach. However, we do not want to hold back a problem that is introduced by our composable message semantics: The calling site of a method says nothing about the semantics that are actually used for the invocation, i.e. possible side effects are not visible.
Even though the actual framework can also be used in a non-distributed environment, we see the main application area within this domain. Distribution, apart from many benefits, introduces new challenges for professional software development. We see our composable message semantics as one possibility to tackle these challenges.
The very same approach could be applied to other languages and environments. The actual requirements are easily fulfilled. The basic requirements are: (1) Run-time access to a compiler; (2) Dynamic code loading; and (3) Meta information. The only problematic implementation part is the run-time type generation for stub objects. We solve this problem by patching the corresponding type descriptors. However, this may be impossible in other environments, e.g. Java [GoJS96, LiYe99]. The actual solution to this problem depends heavily on the actually environment used, i.e. on how the run-time type of an object is determined and on how a method is dispatched. It may well be that the Java VM would have to be changed to supply correct run-time types. However, Java remote method invocations (RMI) had a similar problem. They solve it by demanding that only interfaces are distributed. A similar solution could be applied to our proposal. Another problem that may occur in other systems, could be the compiler that is just too slow to generate code at run-time, e.g. the standard Java compiler. One may have to resolve this problem by using another approach suitable for this specific environment, e.g. in the case of Java, one could use a customised class loader that generates the needed class files by instrumenting the original files at load-time [KeHö98].
Composable message semantics promote the separation of concerns and offer programmers the possibilty to easily adapt their programs to new circumstances. Thereby we reduce the overall complexity which has a positive impact on the quality of our programs, so we can expect more reliable applications in the future.

Back to index