Form should follow function - or: Why RPC really is bad for your mental health

What is a subroutine call like the following?

int r = Calc(a, b);

It is an abstraction and a promise!

It is an abstraction of something like this

push a
push b
call 1234
pop r

The 3GL syntax hides all the low level details like allocating a stack frame, pushing actual parameters on the stack, jumping to the subroutines address, and later retrieving its result from the stack. Maybe even no stack is used at all. Maybe the parameters are passed in registers. In order to solve your customers problem you don´t want to be concerned with all this nitty gritty detail and any machine dependencies.

In addition the subroutine is a promise to return a result pretty fast. It says, "Hey, you´ll get the requested result in just a moment. I´ll be back in a hurry. It´s worthwhile to wait right here." This promise is implicit, though. The usual notation like above does not contain this promise. Rather it stems from your practice with such kind of subroutines. And you become aware of it whenever a subroutine takes an overly long time to return and thus hampers the performance of your program.

Form follows function promise

Now, let´s look at a couple of other well known abstractions and promises:

What are the abstractions? Instead of doing the switching of lines you use a telephone and dial a number. Instead of growing vegetables and milking cows yourself, you go to the supermarket. Instead of going going to a theater play or produce a movie yourself you switch on the TV. (Yeah, I know, maybe the "abstractions" are not 100% correct. But in any case, these tokens of civilization hide uncomfortable details, don´t they? They make life easier for you, don´t they? Since making something easier is the purpose of abstraction, I´d say they are abstraction. Ok?)

And what are the promises? The phone promises a direct link and fluent conversation with your beloved ones. With today´s mobile phones even "... whereever and whenever you like!" is appended to it. The super market promises fresh food and a huge choice almost 24x7. And the TV promises at least moving pictures - sometimes even matching your current mood.

This all great, I´d say. We love these abstractions and promises. And we are very used to their form. Maybe we even love their form, because it´s so easy to use. Their form therefore is a representation of their services and promises we are very familiar with. Or to turn it around: Whenever we encouter the form, we immeditately associtate a certain promise with it.

Now, what happens, if the promise is not fullfilled? We are disappointed. If you want to talk to your friend on the phone to impart some exicting news and keep hearing just her answering machine, you are frustrated. If you go to the super market and they don´t carry the type of bread or beer, you are frustraed. If you switched on the TV and all you could see were interviews or stills of an exciting event, you´d be frustrated.

If some technical gadget or service does not keep its promise... you´d rather like to know so you can switch to an alternative that´s better suited to what you want or what is available.

If communication via phone degrades to leaving messages on answering machines, you probably will resort to letters, faxes or emails as means for asynchronous communication. If a super market does not provide fresh food next to beer and next to magazines you probably prefer to get really fresh vegetables at a local farmers´ market with the added chance to actually bargain your price. And if a TV program deteriorates to pretty pictures, why not look at them in a nice book at any time and at any place and as often as you want?

Letters, farmers´ markets,  and books hold different promises than phones, super markets, and TVs. So their form is different, it´s optimized for their kind of services.

Why am I talking about phones, letters, books in a posting on software? Because I believe in "form follows function" - and I guess, you do so too. What strikes me odd, then, is how little we care about form when it comes to communication in today´s distributed software.

To say it bluntly: If a subroutine call is the accepted form for fullfilling the promise of swift and synchronous execution of a request, then, why would anyone use the same form, if this promise cannot be kept?

I have to admit, for a long time I liked the programming model of .NET Remoting and RPC-style Web services, or even the former DCOM. But just recently I came to the conclusion that using the syntax of subroutine calls is fundamentally wrong whenever the promise that´s tied to it cannot be kept, i.e. when what happens under the hood is completely different.

I´m not just talking about switching to message oriented "thinking" when designing distributed software. I´m talking about the need for actually seek appropriate manifestations for communication.

If you look at a phone or book you immediately know what kind of service you can expect from it. Also you have a pretty clear idea of the quality of the service.

RPC is the wrong form

When you look at a subroutine call, though, you might have an idea of the service, the subroutine´s function - but nowadays you cannot really know anything about the non-functional aspects of the service. Will it keep the promise of the subroutine call syntax and return fast? Will the service execute synchronously or asynchronously? Will the service run in the same address space, on the same thread, or on a different machine in a far away country? Can I be sure the request reaches the service worker at all? Is the service worker available? Can I be sure to receive the result?

By looking at

int r = myservice.Calc(a, b);

you can´t answer any of these questions. That´s what I find fundamentally wrong with today´s communication offerings - even with WCF. Because it does not really make a difference if I write the above or the following:

RequestMessage req = new RequestMessage(a, b);
ResponseMessage resp = myservice.Calc(req);
int r = resp.result;

The latter form is only slightly different. It´s still a subroutine call promising at least guaranteed, synchronous and immediate processing of my request.

So what I want to say is:

Whenever the promise of a subroutine call syntax - guaranteed, synchronous and immediate processing - cannot be kept by a service, then don´t use subroutine call syntax for communication.

You´re asking why? Well, it´s bad for your mental health ;-) Mental health, I´d say, depends on trust. The less you can trust an environment, the more uneasy you feel - leading to paranoia in extreme cases. Trust is fundamental for your wellbeing. And trust starts with looking at something and immediately be able to categorize it, to infer its properties. But if you look at the above subroutine call you cannot infer its properties, which leads to a lack of trust. You don´t necessarily get what you see. And that´s bad - as you might also understand if you´re a proponent of WYSIWYG ;-)

Fundamental for productive and healthy communication is to be clear and outspoken. Say what you mean, make obviouse what you can do and cannot do. And I think that´s also true for any communication related with software. For example that´s the reason everybody likes understandable and informative subroutine names.

If you subscribe to that, then you should understand why I think RPC remote (or non-stack based) communication mostly (or maybe even always) is bad for your mental health. It violates the above basic requirements for any communication because it suggests non-functional properties it mostly does not have.

Comments

# re: Form should follow function - or: Why RPC really is bad for your mental health

Thursday, February 23, 2006 10:09 PM by David

What syntax do you suggest to replace the subroutine call syntax when performing RPC? And even if you have a nice syntax, how do you stop the developer from subverting your great syntax by doing things like...

int Calc( a, b )
{
RequestMessage req = new RequestMessage( a,b );
ResponseMessage resp = myserice.Calc(req);
return resp.result;
}

I don't believe it matters what syntax you use, because in the end the RPC starts when you make the call to the Calc(a,b) function; everything after that is part of the RPC.

I say the only thing you can do with RPC is have a big throws RemoteException or similar to make you paranoid. Because if you have to some information from a server under any circumstance, you should be paranoid.


# re: Form should follow function - or: Why RPC really is bad for your mental health

Friday, February 24, 2006 1:11 AM by Chris Sterling

I entirely agree. RPC, including that found in web services, is not future liking idea. Jini (http://www.jini.org/) has been around for a long time. It was interesting to read an article lately from Dan Creswell about Jini not being RPC, distributed computing, or distributed interfaces. It is distributed services with asynchronous and synchronous calls. This was from his post at http://jroller.com/page/dancres?entry=jini_interfaces_and_rpc.

I have a feeling that mobile code is the way of the future. This is where true intelligence can be put into your proxies and also full control of communication between your proxies and any end points they need to speak to. It is not Java RMI but the JERI implementation of RMI is extremely robust. I wish they had an equivilent in the Microsoft community. I am anxious to see a programming language which attempts to achieve full harmony with the eight fallacies of distributed computing (http://today.java.net/jag/Fallacies.html).

# re: Form should follow function - or: Why RPC really is bad for your mental health

Friday, February 24, 2006 6:33 PM by WalterCReel

"don´t use subroutine call syntax for communication." is a bit of a stretch.

How is this new-fangled idiom of "service oriented" calls any different in premise than a recv()?

A big hint to the client programmer that the contract of "guaranteed, synchronous and immediate processing" is going to be broken is that the type of call is explicit in the example. The 'myservice' portion of:

int r = myservice.Calc(a, b);

should be a clue.

As David said, it's up to the programmer of 'myservice' to know to 'raise' or 'throw' when things go awry so that the client programmer can just treat the service method as a regular funtion call unless an exceptional situation has occurred (like a timeout).

If we're worried about blocking then the programmer should know to use asynchronous facilities (when available).

When someone only has a hammer you can't blame them for making everything look like a nail.

# re: Form should follow function - or: Why RPC really is bad for your mental health

Monday, February 27, 2006 6:22 AM by Ralf

@Walter: I agree: When there is only a hammer, everything has to be treated as nails.

But I´d say: There is (or should be) more than one tool in the toolchest. VSM is one such additional tool.

But even without VSM I think calling a remote subroutine is the wrong abstraction for non-stack based communication. And it´s not enough to have the programmer of some subroutine take care of all that could go wrong. It´s not enough because under the hood things are so different.

If you steer a mars probe like Sojourner you don´t use the usual remote control joystick and controls. The (user) interface for communicating with a mars probe is fundamentally different from a user interface for controlling a toy car in front of you - because a signal roundtrip to/from Mars takes at least 6 minutes.

Such a fundamental difference in communication is represented by a difference in how you deal/interface with the things to be controlled. Why not do the same in software development?

Software development is so abstract, we should grab any chance to make it more tangible. One such chance is to let communication look differently when it is fundamentally different.

-Ralf

Leave a Comment

(required) 
(required) 
(optional)
(required)