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