[comp.object] Reflection In Object-Oriented Syste

foote@p.cs.uiuc.edu (10/14/89)

A reflective system is simply one that may dynamically operate upon
(inspect, modify, or customize) an explict representation of itself.

Any modifications a process might make to its representation must be reflected
instantaneously in the state of the process itself.  This is the "causal
connection" requirement.  This says, for instance, that a process which
modifies a disk copy of the metacircular interpreter that is running it is NOT
performing a reflective operation, since such a change does not affect
the invocation of the interpreter that is actually running the process itself.

The system must maintain the facade that a process, when it accesses
its self representation, is operating on the "real thing".  Depending
on the actual implementation, this may or may not be an easy thing to do.

To provide access to the state of a process, the system must be
capable of reifying, on demand, certain elements of a system's
self model.  For instance, in Smalltalk, Context objects provide a
process with causally connected access to certain aspects of the
the system's representation of that process.

Of course, the most interesting aspect of a process's self representation
is the part of it that determines how the behavior of the process
unfolds.  In a Lispish system, this can be some sort of glorified per object
eval hook.  In languages built using message passing execution models,
an object that can introduce localized customizations of the way in
which it handles message can make arbitrary modifications to its own
semantics.

The beauty of the marriage between object-oriented program and reflection
is that the self representation of an object's execution model need
not be embedded in a big case statement, as it is in most implementations
of eval, but can instead be distributed across a constellation of objects
that comprise a metalevel framework.  (If there is one thing object-
oriented techniques are good at, it is at converting type cases to
distributed message sends.)  Hence, all the power of reflecting upon
ones own execution model need not be concentrated in one spot (message
sending).  It can instead be distributed in such a way as to allow
selective modification to features such as instance representation,
message dispatching, and inheritance mechanisms.  These features
can be represented in such a way as to provide natural spots for programmer
supplied customizations and extenstions.  Such metalevel architectural
issues are one of the more interesting aspect of this line of investigation.

An almost incidental consequence of these approaches is that reflection
subumes existing sharing mechanisms, such as the various standard
inhertance schemes, and allows "smart" localized sharing mechanisms
to be constructed and applied when the problem warants them.

The most thorough formal treatments of reflection are in Brian Smith's
papers.  (Though the limitations on a system's ability to completely
represent itself can be traced all the way back to Kurt Goedel.)

Our interest in reflection was motivated by practial problems that
we found difficult to address in Smalltalk.  These include the construction
of monitor objects, futures, experimental inheritance and sharing
schemes, multiple views, and a host of others.  Reflection provides
an umbrella under which problems like these may be thought about, along
with issues like debugging, tracing, load balancing and the like.
It can legitimize (gentrify?) an interest in otherwise neglected
aspects of a system's architecture by providing a unifying framework
for considering them as instances of a related underlying problems.

An object, during the course of its existence, may enter into a number of
different relationships with other objects.  Some will be relatively static,
and some will be quite ephemeral.  Reflective facilities can help
a system cope with highly dynamic demands on its structure, as well
as adapt as it must evolve to address changing requirements.
I'm inclined to think that mechanisms which address the sort of
problems outlined above will be of considerable interest to
practicing software engineers, particularly if the performance
problems can be adequately addressed.  But that's another long story...

	Brian Foote 	foote@cs.uiuc.edu
	Dept. of Computer Science, University of Illinois @ Urbana-Champaign
	1304 W. Springfield, Urbana, IL  61801
	(217) 333-3411