Historical Note: New-E was an intermediate step between Original-E and ELib. New-E has an outstanding design issue that needs to get sorted soon. This page describes the situation, the issues, and the potential strategies. We'll pick one once everyone's had a chance to review the situation. The SituationLet's assume the following new-E-ish code:
String myData; Argument(String data) { myData = data; } // warning: data better not be null! ...this becomes important later void doSomething () { data.print(); } } ... Argument arg = new Argument("yow"); E.send(someOtherProxy, "someMessage", arg); ... When the "someMessage" envelope gets received by the remote machine, the remote machine needs to create a proxy representing the "arg" object. The question is, what kind of proxy object does that remote machine create? And how does that interact with how the "someMessage" method needs to be declared? Generic ProxiesThe simplest sort of Proxy object is one which is strictly generic:
int mySwissNumber, myRemoteRegistrarID; public int swissNumber () { return mySwissNumber; } public int remoteRegistrarID() { return myRemoteRegistrarID; } Proxy (int id, int initialNumber) { myRemoteRegistrarID = id; mySwissNumber = number; } }
sendEnvelopeToProxy(sendTarget, messageName, arguments); } If the remote machine's "someOtherProxy" object went and did
HoweverThe question then is, what is the declaration of someMessage?One would think it would be:
void someMessage (Argument arg) { E.send(arg, "doSomething"); } } The problem is that this doesn't work with generic proxies! If the remote machine created an object of type Proxy (instead of an object of type Argument) to represent the incoming value of "arg", then the E runtime couldn't invoke someMessage, since the "arg" object would in fact not be of type Argument. You would wind up needing to say
* Some message or other. * @param arg The only argument (type Argument) */ void someMessage (Proxyable arg) { E.send(arg, "doSomething"); } If we captured this type info rigorously in the javadoc comments, we could then write a tool which could type-check all of our E sends, ensuring that the known types of the objects being sent matched the javadoc information. The other possibilityThe alternative way to do it is to create some kind of proxy object which has the correct type. You make the "arg" proxy object actually an instanceof Argument in some way or other. There are two ways to do it:El Cheapo (tm 1998 Arturo)We could make it a requirement of being Proxyable that you implement a special constructor:
protected Proxy myProxy = null; } class Argument extends Proxyable { String myData; Argument(String data) { myData = data; } Argument(Proxy proxy) { myProxy = proxy; } void doSomething () { if (ProxyChecking.ON && myProxy == null) { data.print(); }} }
Object newTypedProxy = new Argument(newProxy); You could then invoke someMessage passing in newTypedProxy, and it would work with the typed version of someMessage. The problem would be if you tried to call newTypedProxy.doSomething() directly; the newTypedProxy only has part of the state of the actual Argument object, so you could die horribly. This is why the doSomething() code above checks that myProxy == null before actually doing its thing; if myProxy != null, this Argument object is actually a proxy with mostly-null state, and would die if it actually tried to doSomething(). So if you do this, you wind up with lots of objects that have the proper Java type information for what they ought to be, but which are huge potential sources of null pointer exceptions if you forget to check whether they're really proxies. Stub generationThe way RMI and old-E and similar systems solved this issue was by stub generation. You basically ran a utility over all your Proxyable classes and it spat out new classes automatically:
Proxy myProxy; ArgumentProxy (Proxy underlyingProxy) { ... } void doSomething () { sendToProxy(myProxy, "doSomething"); } } The problem with this is that it results in class bloat, and that it requires an additional tool and an additional compile step. The Big PictureWhat this really boils down to is one fundamental choice, and then one sub-choice along each option:
If we do not, then we use Proxyable as the Java-declared type of all arguments-that-may-be-proxies. In this case the two subchoices are: If that were all the typechecking that our compile environment attempted to do, we would be paying no space cost and no time cost for our proxy strategy, but we would have some risk of passing badly typed arguments around; this could result in "bad type" errors down the line when you lose track of what type you thought an argument was. The compiler would be basically no help at all when tracking types of E message send arguments. Not only that, but we would have no place in the code to track what those arguments should be, and it would be hugely painful to reconstruct that information later. If we had a (religiously used) Javadoc convention for listing the type of a Java-typed-as-Object might-be-a-proxy argument, and if we had a static tool that could analyze that information and typecheck the actual arguments to E sends against it, it wouldn't matter that we didn't have the type information in the Java declaration; the checked Javadoc, with the typechecker, would do the job. (And in fact it would do an even better job, because it could type-check the sends themselves!--all the discussion we've done so far is just about the received arguments in the receiver, not about catching type problems in E.send itself!) However, we don't have such a tool, and it would take months to write one (the last estimate was six weeks, with no real investigation of that time estimate). They introduce a substantial risk of misbehavior at runtime, if you get sloppy and start doing things with objects that look like your everyday objects but are actually proxies. They also introduce some development overhead in that every "real" method needs to check (for safety) that it is not being invoked on a proxy by mistake. However, there is no tool cost to doing El Cheapo; we could start doing it immediately. This would start moving us back into the tools world, which we've already said we want to get out of. (It would be substantially simpler than a Javadoc-type-info-checking static typechecker, though!) One positive of this is that it is upwards compatible with El Cheapo; we could do El Cheapo now and build a stub generator later, and none of our (correct) code would care.
|
||||||||||||
Unless stated otherwise, all text on this page which is either unattributed or by Mark S. Miller is hereby placed in the public domain.
|