Method Malleability Language Support and Evidence for its

Software Structures Group Report #107
18 May 2007
Method Malleability
Language Support and Evidence for its Applicability
Tim Walsh, Paul Biggar, William Harrison
Department of Computer Science
Trinity College
Dublin 2, Ireland*
(+353) 1-896 8556
{tim.walsh | pbiggar | bill.harrison}@cs.tcd.ie
*
This research is supported by a grant from the Science Foundation Ireland.
© Tim Walsh, Paul Biggar, William Harrison, 2007. Permission to make digital or
hard copies of all or part of this work for personal use is granted provided that that
copies bear this notice and the full citation on the first page.
2
Tim Walsh, Paul Biggar, William Harrison
Method Malleability
Language Support and Evidence for its Applicability
3
Method Malleability
Language Support and Evidence for its Applicability
Tim Walsh, Paul Biggar, William Harrison
Dept. of Computer Science
Trinity College Dublin
Ireland
{tim.walsh | pbiggar | bill.harrison}@cs.tcd.ie
Abstract. The asymmetric method call mechanism is common in most popular
languages. Symmetric methods improve the flexibility of a program since no
single object is designated as a target object. We have designed a new
language, Continuum, to improve program flexibility by, amongst other things,
hiding from the client the fact of which parameter object provides assurance
that an implementation of a method is provided. To maximize the number of
potential sources for implementations, we require knowledge of which
reference parameter can not be null. Knowing that several parameters can not
be null will give more choice for assurance. We investigate evidence from
current usage that the use of required parameters occurs often enough in
practice to be beneficial.
1. Introduction
The object oriented paradigm, now over a quarter-century old, has not changed in the
same manner that the communication infrastructure has. Software developed in
existing object-oriented languages is often too fragile for rapid deployment in
different contexts. Although object-oriented languages encourage reuse, the dispatch
model usually requires that the client know, at compile time, which of the service
provider’s objects implement the method. An object’s location and type assurances
are encapsulated using a single object reference or pointer.
We are exploring the implications of programming language features that enable
rapid redeployment using an experimental language called Continuum that shifts
clients’ orientation to services rather than to objects. This language enables objectoriented software to be much less dependent on the class hierarchy structure of the
implementation of the services they call. Fundamental to improving the flexibility of
software written using Continuum is the concept of symmetric method call.
Symmetric method call removes the dominance of one object in the call by allowing
any one or more of the method parameters to complete the contract supporting the
method. Whether written with a symmetric syntax, or in the usual asymmetric style as
obj.method(obj2, obj3,..,), the declaration of method can be
provided by obj as usual, or from obj2 or obj3. To allow this flexibility, at least
4
Tim Walsh, Paul Biggar, William Harrison
one of the method parameters must be non-null and provide the assurance that the
method can be called safely. To know whether a parameter may provide this
assurance we must introduce a required keyword for, amongst other things, method
parameters. Continuum also introduces the notion of recombinance. This allows the
assurances, traditionally associated with types, to be recombined in a manner that
increases the potential pool of where a suitable implementation for the method can be
found.
The paper examines the required keyword. We describe its significance and
importance in the context of the Continuum programming language. To demonstrate
its utility we also analysed an existing software framework to demonstrate that even
in existing systems, safety could be increased by indicating to the type system that a
particular variable must not be null.
The remainder of this paper is arranged as follows: Section 2 introduces the reader
to Continuum including symmetric method call, classifiers, servicesfaces and finally
recombinance. Section 4 explores the usefulness the required keyword would have in
the SPECJVM framework. Section 5 presents the conclusions of the experiments.
2. Continuum
Continuum is a programming language that extends conventional object-oriented
languages in a manner that allows it to exploit the modern computing infrastructure
that has emerged and matured over the past quarter century. An important
requirement of modern software is the ability to rapidly adapt to changing
organisational and operating environments. The most common invocation model for
object-oriented software is that in which a specific ‘target’ object provides the
implementation and is sent the method call. The emergence of software variations
such as aspect-oriented, service-oriented, event-driven and ‘Grid’ software have
resulted in the development of specialised dispatch mechanisms between the message
sending client and the message handling servicer. In a similar vein, the commercial
software world has J2EE / Enterprise JavaBeans and .net to separate business logic
from application development. However these solutions have proven to be more
complex than expected partly because of the need to explicitly find and manipulate
the objects representing the rewrapped business logic.
Many object-oriented approaches to software dispatch require a particular target
object to be specified, with the result that clients remain strongly dependent on the
implementation structure of the service providers. The need to phrase method-calls in
terms of a target object that must be known to hold the method’s implementation
interferes with the modularity and reusability of software. Continuum extends existing
object-oriented programming languages by introducing, among others, symmetric
methods, classifiers and servicefaces, and ‘recombinance’.
Symmetric Method Calls
Most programmers are familiar with object oriented method calls of the form
obj.method(obj2, …). This form is asymmetric; not all the objects involved are
Method Malleability
Language Support and Evidence for its Applicability
5
treated equally. This can become more problematic when there is an underlying
symmetry among objects. For example, store.registerSale (item,
customer) shows that at some stage in the development process a decision was
made to place the registerSale method in store’s type. Making the choice among the
three possible homes for registerSale’s implementation dictates more than
simply the syntactic choice of the target object in the call’s syntax. Somewhere before
this code is executed there will be some form of lookup for store. Attempting to move
the registerSale method to the item type will require the preceding code to be
changed also.
There are two different symmetries involved in method call –syntactic symmetry
and semantic symmetry. The syntactically symmetric method call gives no syntactic
dominance to any particular object; e.g. all parameters are written the same way in
registerSale (store, item, customer). In semantically symmetric
method calls, all objects can have equal significance with respect to providing
assurance that there exists a registerSale implementation. Syntactically symmetric
method call is not new. It was common in pre-object oriented languages from Fortran
through Ada but has fallen out of fashion in object-oriented software in favour of the
asymmetric form, which offers advantages of encapsulation and conditional-binding.
To satisfy the type, a reference must usually denote an object that implements all of
the methods indicated, but a null reference value satisfies even though none of the
methods are implemented. Hence the declaration of methods associated with a
reference is conditional on the value being non-null.
Classifiers and Servicefaces
In Java, reference types are defined with classes or interfaces. The type allows the
developer to classify according to operations implemented for the object. In
Continuum this is broken up into the abstract ‘type’ of object it is, called the
classifier, and the assurances, as defined by the set of legal operations, called
servicefaces. All objects with the same classifier have the same behaviour. But the
behaviour known to be available for a particular object can vary depending on the
client’s knowledge. A particular object can be interpreted differently depending on
the viewpoint. For instance, something classified as a Person may have one set of
assurances when seen as an Employer and a completely different set when seen as a
Parent. We can transfer from one declaration to another the knowledge about
operations that can be safely performed on something of a particular classification.
This is what we call recombinance and is explained further below.
Continuum’s serviceface construct is similar to Java’s interface. Servicefaces have
a unique name and contain symmetric method signatures. When declaring a variable
in Continuum you must associate it with both a serviceface and a classifier.
Classifiers can form similar hierarchies to conventional types defined by interfaces.
In Java an object reference is represented as a pointer to a particular memory
location where an implementation for the object resides. Continuum’s classifier and
serviceface pair does not hold any such information. Instead, Continuum adds further
facilities to allow the developer to specify how the reference is represented. A
dispatcher, separate from the language is tasked with the responsibility of finding
6
Tim Walsh, Paul Biggar, William Harrison
implementations. An implementation is known to exist from assurances of the
serviceface. However as this is beyond the scope of this paper further information is
available from [1].
Recombinance
Recombinance is one of the keys to software malleability in Continuum. The basic
idea, as alluded to above, is that as references are used in different contexts they
‘acquire’ assurances that operations are assured to have implementations. A very
simplistic example, once again using the Person classifier example above, is that a
Hospital could acquire assurances about new operations applicable to hospitals
and people from assurances known about a Person.
Consider a method implemented as treatment (Hospital, Person)
where Hospital assures scheduleAppointment (Hospital, Person)
and Person assures payBill (Hospital, Person). This implementation of
treatment calls scheduleAppointment and payBill and uses the fact that
implementations for both of these exist. The caller of treatment must supply both
assurances, but in the caller’s program these methods might be associated with the
parameters differently. There are four different ways to associate two methods with
two parameters.
It is important to note here that recombinance can only take place in the presence
of guaranteed reference variables; that is, parameters, fields, or local variables that are
never null, because null references are considered to fit all classifications, but provide
no real assurance about the existence of method implementations. Generally, at least
one parameter must be have a required (section 3) attribute for a method to be
invoked, however more required parameters gives greater opportunities for
recombination.
3. Required Method Parameters
The previous section discussed the use of symmetric call to hide the source of method
implementations from clients. But the ability to do strong type-checking requires that
we be able to show that some implementation will always be available. With
conventional object-oriented languages, this proof falls out trivially from the fact that
the target reference is always required to be present and not null. Greater flexibility
can be derived if other parameters are also known to be required. In Continuum,
parameters, fields, and local variables are all declared to be required or optional.
Information, like assurance about what methods may be called, is known
conditionally - on the basis of whether a variable’s value is null. In practice, several
parameters to a method may all be required. When the fact that a parameter is
required is actually declared, the information can be used to perform the necessary
strong type-checking, but still allow flexibility in the actual run-time situation.
Although we can hypothesize that methods may have several required parameters,
the usefulness of the flexibility we introduce in Continuum depends on how often
methods do so in practice. For this reason we analysed the SPECJVM98 system [2] to
Method Malleability
Language Support and Evidence for its Applicability
7
search for evidence that indicates that use of required parameters occurs often enough
in practice to be beneficial. In other words, are parameters required for execution
despite not being flagged as so.
4. SPECJVM98 Analysis
In Java, only the this parameter is actually required for instance methods. The
compiler ensures that it is automatically included on a method’s parameter list, and
the dispatcher insists it is not null when a method call is made. Looking at Java from a
Continuum recombinance perspective, only the this parameters can be viewed as a
possible source for assuring a method’s implementation. All other parameters are
irrelevant for the purposes of assuring an implementation. Continuum allows any
required parameters to be viewed as potential sources of assurance. But the question
arises whether the malleability of existing frameworks would benefit from
Continuum’s capability for recombinance. In other words, does existing software
already have method parameter lists that could, were the infrastructure in place, take
advantage of recombination. Because Java has no mechanism for flagging required
parameters these can be considered lost opportunities to potentially perform
recombination.
SPECJVM98 [2] is a collection of programs used to benchmark Java Virtual
Machines. It is comprised of over 500 Java classes. We chose it as a sufficiently large,
well known framework on which to conduct tests. We analysed its classes in order to
determine how many methods had parameters that could be classed as required. That
is, which parameters could not be null if the program is to execute properly.
While most discussion of software malleability focuses on promoting software
reuse by interposing adapters that may do argument conversion, casting, or
reordering, none of those transformations permit the method recombinance that can
occur in Continuum. Method recombinance allows the conditional assurance that
methods are available to migrate among reference declarations, while traditional
object-oriented languages insist that the assurance remain with the reference to which
it is initially bound. In Continuum, the method can be called passing references that
assure support for these methods in any of the 4 possible forms of combination.
The difference represents a loss in malleability of the underlying software inherent
in the lack of recombinance. We can define a measure of the per-method malleability
with respect to the recombination of assurances across its parameters. Consider a
method with n required parameters which among them assure m methods. The
number of different ways of apportioning those assurances among the parameters
without duplication is nm. Java allows only 1/nm of the possible client configurations.
We will call this the malleability ratio Enm. For Continuum, with recombinance,
Enm=1.
If we conservatively estimate 3 or 4 different methods per interface, we can
compute the weighted average malleability ratio for Java to be .00085. The relative
malleability of Continuum compared to Java is 1180.
Although the relative malleability is quite high for methods with one or more
reference parameter in addition to this, those methods are, after all, the ones for which
8
Tim Walsh, Paul Biggar, William Harrison
developers are most likely to misguess the source of their implementation. There is a
considerably less dramatic relative malleability if we include them. In that case, the
malleability for the common object model used by Java is .90. Even though 90% of
the methods SPECJVM98 have a hidden this as their only reference parameter, the
relative malleability of Continuum compared to Java is still 1.11. A fuller presentation
of the measurements and the analysis leading to these results can be provided.
5. Conclusions
Recombinance might be an important characteristic of programming languages
intended to support more malleable software. It permits clients and service providers
to interoperate even though they may differ about which methods are implemented by
which kinds of objects. Effective use of recombinance uses knowledge of which
parameters or fields can never be null. Continuum is a Java-like language designed to
support recombinance. But recombinance can be exploited only when several
variables, e.g. method parameters, are used jointly and required to be non-null. To
explore whether this circumstance already occurs and the effectiveness of exploiting it
to increase malleability, we have measured a sizeable, well-known collection of
classes. Analysis of the measurements indicates that about 20-25% of methods with
more than one reference parameter in addition to the target have one or more required
reference parameter in addition to the target. Furthermore, the expression of this
software in common object-oriented languages like Java rather than in ones like
Continuum that provides recombinance allows exploitation of under .1% of the
possible client/service configurations of expectation about which methods are
implemented by which kinds objects for methods that refer to more than one object,.
Acknowledgements
The authors wish to acknowledge the assistance of David Gregg in the design of the
analysis software.
References
[1]
[2]
Continuum Language Specification,
https://www.cs.tcd.ie/research_groups/ssg/Continuum Language Specification.htm
Standard Performance Evaluation Corporation (SPEC), http://www.spec.org