WYSIWYG semantics

New Dec2011, here Jan2014 (updated 12Feb2014)
This page is in group Technology

Intro

This note is about programming language source code’s syntax and semantics. (Some implicit references are at Wiki-refs)

I will try to explain WYSIWYG semantics and discuss whether the new term stuttering semantics is of any value. It’s new here and meant to cover an aspect where the system probably still has WYSIWYG semantics, but it is substantially more complex than it would be if compared to some other programming paradigms. If you don’t think the name is anything, please suggest another. Or maybe it isn’t needed; provided I may have failed to understand that WYSIWYG perhaps also covers “not stuttering”? To be honest, I’m not entirely happy with it myself – but matters seem to be more or less WYSIWYG. And stuttering semantics; I have nothing formal for you. So be it. I am not a computer scientist, but someone between a spectator and a player.

I will start with a historical note and then do a brief explanation of both terms. But the bulk of the theme is covered in the seminal referenced papers (see below). They are not written by me.

These historical references will show that traditional Object-oriented programming languages do not have WYSIWYG semantics (in the relevant scope). They will also describe that a (particular?) language for Process-oriented programming does in fact have WYSIWYG semantics. I will also show that buffering and asynchronous systems easily introduce stuttering.

History and seminal references

I think it started at one of the last WoTUG (now CPA, (*1)) conferences in the ninenties. Peter H. Welch of University of Kent at Canterbury initiated a comment letter to the editor of IEEE Computer [01]. I was in the WoTUG committee and had the opportunity to sign it. After this I have heard Welch present the theme from several angles, but mostly quite informally [02]. In the light of occam-Pi (occam-π) he presented an official paper about it in 2013 [03] – but the term WYSIWYG semantics isn’t used. About all I have heard about the theme has been from his lectures. There is a mail sequence between Welch and myself below.

You should now read the three references above. But first some teasers from the “We Need to Talk About Objects” chapter in [03]:

(2.1) ..”An alarming postscript to the above scenario is that the side-effect on B can happen even if B is held in a (supposedly) private field of A, was constructed by A and has never had its reference given away by A!”..
(2.2) ..”The conclusion is that local fields of objects must be regarded as global, regardless of any notions of privacy declared for them.”..
(2.3) ..”This need for non-local analysis is a serious trap”..
(2.4) ..”The implementor has to work harder to ensure that invariants are maintained. The problem, again, is callback. Any callout from a method to another object has the potential for callback. Discovering if this is so for a particular system requires non-local analysis.”..

Now, I suggest you read it!

Not having WYSIWYG semantics or having too much stuttering make programs harder to code, read and understand – also for some code analysis tools. Even if the results may be catastrophic it may be one of those bugs that need to be fixed. You had tested the previous version and had modified at a completely different place. And you must admit that you were surprised that none of the tests in the suite caught it. But then, you may be right to state that it wasn’t your fault.

The basic summary from the IEEE Computer letter [01] is here:

One crucial benefit of CSP is that its thread semantics are compositional (i.e. WYSIWYG), whereas monitor thread semantics are context-sensitive (i.e. non-WYSIWYG and that’s why they hurt!). Example: to write and understand one synchronized method in a (Java) class, we need to write and understand all the synchronized methods in that class at the same time — we can’t knock them off one-by-one! This does not scale!! We have a combinatorial explosion of complexity!!!

With CSP, threads can refuse individual events if they are not in a state to accept them. They do not wait on shared condition variables and do not rely on other methods to fix things up for them. Each method has its own contract and looks after itself. This type of logic does scale.

My earlier notes

I have described some of this in some earlier notes. I have called it WYSIWYG, but in hindsight I see that I might have stuttered. But the taxonomy is not as important as the facts, therefore I will only modify if necessary. Oldest on top:

Stuttering semantics

Peeking into the documents above and searching for WYSIWYG will take you into most of this. But here’s a summary from [04] – in new words.

079 fig2
Here are 5 processes which communicate asynchronously, seen by the sloping message arrows (for flow of time downwards). The center process P almost simultaneously sends to the left and to the right. For some reason it wants to receive one of the replies before the other. Every process has a single input queue, and the oldest message is delivered upon scheduling. There usually is no scheme available to pick out the next expected message from a concrete sender first, and lock out the others. This is just one example of stuttering semantics.

Not stuttering semantics

079_fig3

This figure is from an earlier version of [04]. There are 4 processes and communication is on synchronous channels with no buffering. The processes in this example build a buffer. The first on the channel is descheduled (blocked) until the second arrives; therefore the horizontal non-sloping message lines (time stands “still”). When IsLeft is not able to take any more message because IsRight hasn’t sent acknowledge then IsLeft just don’t listen on message. Then IsUp could try to send message, but it would in case be descheduled while IsLeft is Full. When it’s Empty then IsUp may send. The response is at application level and not necessary for next message to come through. No data is lost, and IsLeft is able to “close the door” from IsUp or IsRight when it needs to. This is one example of WYSIWYG semantics, and it’s also not stuttering semantics (if one can say it like that!)

It’s about either not listening on a channel or having conditional guards in selective choice (occam). Or sending over a pair of extra channels to use just for the session, and then keep the others out by not listening on their channels (Google’s Go (golang)).

Questions

Here is a mail sequence between me and Peter Welch. He allowed me to blog this. I have made some of his sentences italic. Pages 31-36 in [02] (“occam obviously”) are reused as the same pages in [03] presentation (“Life of occam-Pi”). Starting with me:

I assume that page 36 is a situation as shown in page 33?

Yes. Slides 31-34 use the example code:

count := 42;
thing.f ();

Slides 25-30 and 36 use the code:

count++;
logger.log (count);

They are used to make the same point: that the value of ‘count’ may change following the method call on a foreign object. I should have used the same example throughout – slides 31-34 were reused from a much earlier talk.

So the problem with “n++; logger.log(n);” is that we don’t know if Logger class and logger object has a private instance on Counter that calls counter.increment?

Strictly, it’s the logger object that might have a reference to the ‘Counter’ object whose ‘increment’ method has been called. But, as indicated in slide 36, the problem may be more obscure than that: the logger may have a reference to another object that has a reference to another object that has … a reference to another object that has a reference to the ‘Counter’ object whose ‘increment’ method has been called.

If this is so we would have had a recursive call forever? This would in case be detected at run-time immediately, just like a deadlock?

No – not necessarily. It depends on the logic in logger (or one of the chain of objects being invoked) that triggers the eventual call-back on the ‘Counter’ object. I’ll say more about this below.

Would “n++; logger.log();” without any param have the same problem? I think so?

Yes. The problem arises with *any* call on a method of *any* object (other than the object making the call). We can never know, without analysis of the object references in the system at the time of a call, whether a call-back may occur. That analysis is clearly impossible just from the source code of the object making the call. Now, whatever the class invariant (and there will be one whether the programmer knows it or not), unless that invariant is re-established before *every* call-out to another object, any call-back will be to a corrupt object (i.e. one whose invariant is false). So, the semantics of such an object cannot be WYSIWYG … its semantics depend on the system in which it is placed.

Is this just a cycle in a class diagram that’s easy to spot so that not WYSIWYG semantics isn’t any more deal than other problems with (any) language?

It’s not a cycle in the *class* diagrams that’s the problem. I would bet money that most OO systems, for non-trivial applications, have cycles in class relationship diagrams. The problem is:

  • at any time, is there a cycle of references between the *objects* in the system (bearing in mind that the number and variety of objects can be continually changing)?
    [I’m not expert on all the varieties of UML diagram, but I don’t know of one that illustrates such *object* relationships … discovering the dynamically changing object references requires good understanding of the whole system … which means the source code of everything.]
  • if there is such a cycle at any time, will the state of the objects cause a cyclic invocation of methods via the references in that cycle?

That’s the analysis needed to keep out of trouble. Good OO designers will design their system so that such analysis is tractable and, if the answer to both questions is yes, that the call-back is intended and the classes involved are programmed (by re-establishment of invariants) to cope with it.

The ‘Counter’ example shows that even very simple classes, following proper principles of OO design, have semantics that are not determined just by its source code (i.e. non-WYSIWYG) and can land you in trouble. The need for care in design and programming to overcome this problem seems, to me, evidence for significant engineering weakness underlying the whole concept of OO.

I think you have a lecture where you outline this more. If so, could you place that on the internet or send it to me?

This is written up better in the paper for my talk ([03]) – in particular, Section 2 (“We Need to Talk About Objects”). Although it doesn’t use the term WYSIWYG, that’s what the whole section is about. Section 2.1 illustrates an even wider non-WYSIWYG problem with OO – hidden side-effects by design! Section 2.2 shows this side-effect can apply even on private integer fields. Section 2.3 does the ‘Counter’ example, showing how the call:

counter.increment ();

can result in the ‘count’ field in ‘counter’ being increased by a random number! Note: there is no infinite recursion arising from the call-back; the above call-out completes normally but has had an unexpected effect on the state of ‘counter’. This is very dangerous … 🙁

Section 3.3 shows that we don’t have this problem with PO (process oriented) design. (End of letter sequence).

Practical example: A server having a session with one of several clients

There are five clients, named A-E and one server S. Helper process for S is called H

Server process S (easy case)

  1. Client A send a message service request to S
  2. S needs services from H, so this will take a while
  3. S waits for response from H in a select
  4. S receives response from H (from nowhere else)
  5. S sends reply back to client A
  6. S listens in a fair way on client channels (pipes etc.), and receives a request from client B

This is WYSIWYG semantics (easy case).

A possible architecture could be one point-to-point channel (or p-p pipes) between each client and the server, and two p-p channels between S and H (request and response).

Server A could have done something else in the meantime, it didn’t have to just wait for reply from S. This could have been more or less easy, see later.

Server process S (difficult case)

  1. Client A send a message service request to S
  2. S needs services from H, so this will take a while
  3. S waits for response from H in a select
  4. S receives instead of response from H, another service request from client B
  5. S pushes this request away (luckily this was the only request)
  6. S finally receives response from H
  7. S sends reply back to client A
  8. S pops request from client B and processes it

In this case, server S needs to be its own “scheduler”, by pushing and popping requests. Lucky that it was in a state where this was ok. It didn’t need to. This architecture is difficult to program. Maybe the programmer “knew” that the other clients would not be active, so it needed only push one request. When a new programmer sees this standard client / server model, it does not “know” that the client only has a one position stack. This is discovered by inspecting a log after having installed the system at 1000 sites. The server had crashed, and a service man had managed to get a log.

For a long time I believed this was not WYSIWYG semantics. But Peter Welch writes in a mail that “I don’t quite agree that your example “Server process S (difficult case)” is non-WYSIWYG. All the extra scheduling logic is contained in the ‘S’ class; so I think it’s still WYSIWYG … but the what-you-see is rather complicated, so you might not get it! The example shows a different benefit from Process Orientation: the ability of a process to refuse communication (compared with an object’s inability to refuse being called).”

This is an example that I have now started to say has stuttering semantics.

An architecture that could cause this to happen is a common message queue that the run-time system uses to pick new messages from, to the server. At any time, any client could send requests into this common queue.

Client processes

So far we have not said anything about the client processes. Does it make any difference if they block or send and forget the request into (an infinite) queue?

A WYSIWYG scenario: If the first request blocks immediately (zero buffered channel), and the server not at this channel yet or in fact is at this channel, then the request – reply sequence will be “atomic” as seen from the outside. If several clients all try to send a request at the same time: still as “atomic”. We can knock them off one-by-one! This scales!

If the client sends into a buffered channel, it’s still WYSIWYG, since the channel pipe disregarding size is process to process. Not shared. Even the Any2OneChannel of JCSP [05] will be fine, since:

Any2OneChannel is an interface for a channel which is safe for use by many writing processes but only one reader. Writing processes compete with each other to use the channel. Only the reader and one writer will actually be using the channel at any one time. This is managed by the channel – user processes just read from or write to it.

Please note that this is a safely shared channel and not a message gatherer. Currently, gathering has to be managed by writing an active process.

What WYSIWYG does not cover

I don’t think that this term would cover problems like race conditions, hazards, deadlock, livelock, starvation, pointer errors or anything causing “segment fault”. Even if one do get something else than you see, to me the term What You See Is What You Get semantics would not cover these matters.

They belong to different “error spaces” (and would have nothing to do with stuttering).

“Nonstop technobabbel” blog

When some of these words were at my now removed 036 blog note I wrote a comment to Svein Arne Ackenhausen’s blog note “Parallel takes you half the way.” He responded by making a new note to discuss my comment, see “2 cups of messaging, 1 tablespoon of async and a whole lot of context”. I then responded with a rather large reply to this, here. Very interesting, indeed! Thank you!

Real example?

I would not be surprised if this error in Apple OS X Maverics 10.9.1 is such an error, see here.

Go language discussion

I did start a thread in golang-nuts about the theme. It’s called “Cycle of references in Go?” and can be read here: https://groups.google.com/forum/#!topic/golang-nuts/eGivkkf47nA.

It seems like Go does not have WYGIWYG semantics, but at the time of writing I am not sure. Read the latest update in the thread.

However, what I did not know is that the immutability of functional languages will ensure WYSIWYG semantics! So, even if occam-Pi is not a functional languge and has mutability, it still has this property of a functional language. Hmm. So immutability then is not a condition for WYSIWYG semantics?

References

Wiki-refs: Object-oriented programming, occam-π, Process-orientated programming, Software testing, Stuttering (but I’m giving it an additional meaning).

  1. Letter to Edward A. Parrish, The Editor, IEEE Computer. Peter Welch (University of Kent, UK) et al. (Dead url: http://www.cs.bris.ac.uk/~alan/Java/ieeelet.html (1997)). Internet archive at http://web.archive.org/web/19991013044050/http://www.cs.bris.ac.uk/~alan/Java/ieeelet.html (1999)
  2. occam obviously” Peter H. WELCH, School of Computing, University of Kent, UK at Communicating Process Architectures 2012 (CPA-2012)
    http://www.wotug.org/papers/CPA-2012/Welch12c/Welch12c-slides.pdf – Presentation only
  3. Life of occam-Pi” by Peter H. WELCH, School of Computing, University of Kent, UK at Communicating Process Architectures 2013 (CPA-2013)
    http://www.wotug.org/papers/CPA-2013/Welch13a/Welch13a.pdf – Paper
    http://www.wotug.org/papers/CPA-2013/Welch13a/Welch13a-slides.pdf – Presentation
  4. High Cohesion and Low Coupling: the Office Mapping Factor“. CPA-2007. Read at http://www.teigfam.net/oyvind/pub/pub_details.html#TheOfficeMappingFactor
  5. org.jcsp.lang Interface Any2OneChannel, see http://www.cs.kent.ac.uk/projects/ofa/jcsp/jcsp-1.1-rc4/jcsp-doc/org/jcsp/lang/Any2OneChannel.html (part of Communicating Sequential Processes for JavaTM (JCSP) at http://www.cs.kent.ac.uk/projects/ofa/jcsp/)

(*1) The only that’s left from WoTUG now is the still present web site’s url and proceedings and a series of twenty-two WoTUG conferences. CPA-2000 was the first in a new series to replace it. WoTUG = World occam Transputer User Group. CPA = Communicating Process Architecture, or “WoTUG – The Place for Communication Processes”

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.