Hello Fabrizio

Thanks for your questions. Sorry it's taken so long to reply. I was
off-line for most of the weekend.  This gave me plenty of time to
compose the reply so I guess I should offer a second apology for its
length.

(Some might wonder why I bring up museum pieces like Oberon and
HyperTalk on what is after all the *Java* posse. What can I say? I'm a
generalist at heart. In our business, ideas seem to resurface
periodically under new names because the problems we deal with
resurface periodically in new guises. I think there are insights to be
had by looking back at previous generations tackled these issues.)

# HyperCard

Ben Smith-Mannschott wrote:

> Generally, one module would implement the Model and define some
> kind of UpdateMessage. Another module would impelement a
> view. Each view instance would inspect all UpdateMessages that
> passed by to see if they pretained to the particular model
> instance it was displaying.

Fabrizio Giudici wrote:

> Again, I don't understand somethinng - what made a Model different
> than a View, if everything was in a hierarchy?

You're assuming HyperCard distinguishes between model and view. It
doesn't. The view is the model. What you see is what you get.  For
serious. A typical way of storing data that the user was not expected
to see or manipulate directly was in a text field which was set to
'hidden'. And when I say "text field" I'm talking about a GUI
control. Pretty slick^H^H^H^H^H sick, no?

I love my source control and my repeatable builds and I don't
think I'd like to go back to HyperCard where programming meant
performing successive mutations directly on a
binary-blob-of-a-document-that-IS-your-application. On the other hand,
the very directness of this approach was a real productivity win when
I was still young and naive.

# Oberon

B Smith-Mannschott wrote:

> "Sending a message" was understood very literally. Messages were
> instances of some extension of a base record type. You filled them
> out and sent them off at which point they were *broadcast to all
> viewers in the view hierarchy*, which reacted to the ones they
> were interested in possibly by forwarding them on to their
> children (contained widgets) and ignored the rest.
>
> There was no registration and there was no dangling objects due to
> forgetting to unregister listeners. Every component was was in the
> visual hierarchy and was thus in on all message broadcasts. You
> didn't have to do anything, except react to messages that
> interested you when they came. Closing a window automatically
> removed it from the view hiearchy.

Fabrizio Giudici wrote:

> And what about performance? This sounds _exactly_ as the original
> design in AWT for Java 1.0, that was dropped in Swing for 1.1 - it
> was a performance hell. Not to say it sounds as a poor design to use
> a containment hierarchy as a way to deliver events (no separation of
> concerns, no MVC - unless I didn't understand it correctly, that
> might be of course). Was Oberon ever used in a production systems?
> It's quite common to sketch a clean and simple OO design, just to
> find later that it can't deal with the real world. If instead the
> answer to my question is that Oberon is being used in production and
> it's performant, the interesting point is discussing how it manages
> to do that.

## "In Production"?

Well, it was used as an operating system for student workstations at
ETH/Zurich for many years. (The Ceres-1, -2 and -3 workstations were
designed and built at ETH.) I also know that it was used as part of an
embedded system for controlling mixing of granulates plastic
production. (Presented during JMLC 2000). But let's be honest: Oberon
has't seen anything like the kind of wide-spread use we're used to
seeing in the Java world.

## MVC in Oberon

Oberon most certainly does follow the MVC pattern.  This is not a
coincidence as Oberon was inspired at least in part by Niklaus Wirth's
exposure to PARC's Mesa & Cedar systems which shared ideas with
SmallTalk. Oberon was Wirth & Gutknecht's effort to reduce these
systems to their essence.

I've included, at the end of this message, two sections 5.5 and 5.6 of
_The Oberon Companion_. This is as good a summary as I could find of
Oberon's take on MVC. A few notes:

### 5.5 Display Space

- The discussion around figure 5.4 touches on Oberon's principle of
 "parental control", in particular: "Each parent frame is completely
 responsible for its direct descendant frames and thus indirectly
 responsible for its indirect descendants."

- Figure 5.5 illustrates that non-visual ("model gadgets") also
 participate in the display space DAG by virtue of being a model for
 one or more "visual gadgets".

### 5.6 Messages and Broadcasting

- "Model-view consistency" describes the core of Oberon's MVC with an
 example.

- "Types of broadcast" again discusses "parental control".

## Performance

One might think the performance of message broadcasting would be
terrible. The work required to broadcast a message should grow
linearly with the complexity of the view graph.  In practice, however,
performance is not generally a problem.

With 30 documents open (or applications running -- the distinction is
not very meaningful in Oberon), I found that I could broadcast 3300
messages a second into the display space. [Dell Mini 9 (Atom @
1.66GHz); Linux/x86 port of Oberon System 3] In practice this is
plenty fast enough.

I can provide a counter example as well. I wrote an implementation of
SameGame once on a 90 MHz Pentium I. Initially, the model broadcast a
separate update event for every change in board state. In SameGame
large numbers of individual changes can result from a single move.
The performance was not spectacular. At the time, I just had the model
buffer and merge all the update messages resulting from a single move
and then broadcast that merged update as a single message. Performance
was excellent.

The real performance problem in Oberon is of a different sort. Recall
that there is no multitasking. There is one process. One thread. Not
even coroutines. The procedure call is the indivisible unit of
computation.

This means that applications have to be quick about reacting to the
messages. Even drawing the mouse cursor is delegated to the view over
which the mouse happens to be located. Since you want fluid mouse
movement, you can't hog the machine when reacting to messages.

Oberon software was written with these limitations in mind, so they
were rarely a problem in practice.  For the user the experience
was almost always one of a very repsonsive system. (Notable exception:
when you downloaded software from the central file server to a Ceres-3
workstation, the entire gui would freeze for the duration of the file
transfer -- thankfully the files were small.)

The best solutions are ones that clearly define their goals and cut
away everything that's not necessary to achieve those goals.  With
luck, such simplicity will later bring benefits not originally
anticipated. (Misidentify your goals and things won't turn out so
well.)

## Conclusion: Events/Messages

Approaches like Swing rquire a lot of glue because:

- You are required to *know* which senders you are interested in listening to.
- You must know where to find these senders.
- You are required to register for every Message x Sender combination that
 you might be interested in.
- You must uregister yourself from all your Message x Sender
 subscriptions when you're closed so that you don't hang in memory
 forever just because you're on someone's listener list.

The final point is particularly ugly because it defeats automatic
resource management (garbage collection).  Listeners effectively
become unmanged resources for which must be explicitly closed(). This
is just another form of the malloc/free problem. It is difficult, in
an extensible system to determine who is responsible for disposing of
such a resource and when it should occur.

It's much more pleasant when objects can just take a ubiquitous
message feed for granted, react to what interests them and ignore the
rest. This won't be an acceptable solution in all cases. (I wouldn't
advocate it over a network.) It sure is nice when it *is* a suitable
approach.

// Ben Smith-Mannschott

----

# Excerpts from *The Oberon Companion*

*The Oberon Companion*

**Copyright 1997-1998 by André Fischer and Johannes L. Marais**

## 5.5 The Display Space

In earlier chapters, the display space was introduced. In essence, the
display space is a data structure containing visual and non-visual
objects. The visual objects, called frames, are the gadgets such as
documents, Buttons, Scrollbars, etc. you see on the display. The
non-visual objects are the model gadgets linked to these gadgets. We
should emphasize here the abstract nature of the display space we are
referring to. The display space should not be confused with the
geometrical space of the display screen. To understand the display
space, we have to discuss the nature of the single elements of the
display space, and the nature of the connections between them.

### The type hierarchy.

Before going into detail about the structure of the display space, we
first investigate the type hierarchy of the visual and non-visual
objects. All visual objects are extensions of the type
Display.Frame. In turn, each frame is an extension of a more basic
type called Objects.Object. The non-visual objects are also extensions
of Objects.Object, but not of Display.Frame.

![Figure 5.2 The Object type hierarchy](Fig5.2.png)

The lines of Figure 5.2 show the type extension relationship between
objects. To simplify the programming of gadgets, two further base
types form the basis of the visual and model gadgets. These two types,
Gadgets.Frame and Gadgets.Object are extensions of Display.Frame and
Objects.Object respectively. Thus when programming gadgets, we are
faced with the type hierarchy depicted in Figure 5.3.

![Figure 5.3 Base system / Gadgets system relationship](Fig5.3.png)

The double horizontal line of Figure 5.3 signifies a split between the
base system and the Gadgets system. There is a good reason for
emphasizing this split. The base system provides the mininum for
implementing a framework of components. The Gadgets system "fills in"
part of the functionality in this framework, that is, it adds rules
and user interface conventions. Theoretically, we can imagine yet
another type of user interface system built on the same base but
implementing a different type of user interface framework. In fact,
the textual user interface of the Oberon system is such a framework
which existed before the development of the Gadgets system. This also
illustrates that such a dichotomy turns out useful for guaranteeing
compatibility with older applications, as both gadgets-enabled and
older applications are different aspects of the same underlying object
model.

Before continuing with the display space structure, it is informative
to show the type definitions of Objects.Object and Display.Frame,
although the meaning of several of the RECORD fields is not obvious
yet, and thus partially hidden:

   Handler = PROCEDURE (obj: Object; VAR M: ObjMsg);

   Object = POINTER TO ObjDesc;
   ObjDesc = RECORD
       ... some more fields ...
       handle: Handler    (* Message handler. *)
   END;

   Frame = POINTER TO FrameDesc;
   FrameDesc = RECORD (Objects.ObjDesc )
       next, dsc: Frame;
       X, Y, W, H: INTEGER
   END;

The definition of Object reveals that each object has a message
handler, which is responsible for interpreting the messages that are
sent to it. Furthermore, we see that frames are type extensions of
objects with the additional fields next, dsc, X, Y, W and H, which are
described in the next paragraph.

### The Display space structure.

Frames have a location and a size: the record fields F.X and F.Y
contain the position of the frame F, and the record fields F.W and F.H
its width and height. When a frame is located in the display space, it
is always nested in another frame. The situation can be clarified in
the following way, but for the sake of simplicity we shall confine the
description to the tiled display space model used by the textual
interface. The display itself is a large (imaginary) frame that covers
the whole display surface. It has the location (0, 0) and size
(Display.Width and Display.Height). (By the way, the origin of the
Oberon display is in the bottom left corner, in contrast to many other
systems.) This "root" frame is divided into two tracks, the user and
the system tracks. Each track is a frame nested or contained in the
root frame. The tracks are further divided into viewers, which are
frames too (nested in their respective tracks). Each viewer is divided
into two further frames, the menu bar frame and the main frame. The
main frame might for instance contain a text editor frame. Inside this
text editor frame we have the text itself, and possibly further frames
signifying the visual objects that "float" in the text. These frames
might contain further frames, and so on to any nesting depth.

![Figure 5.4 Example structure of the display space](Fig5.4.png)

The nested nature of the display space is extremely important in the
system and should be well understood. Figure 5.4 gives a diagrammatic
view of the situation. Frames containing other frames as children are
called container gadgets. Frames not containing any further frames are
elementary gadgets. Each parent frame is completely responsible for
its direct descendant frames and thus indirectly responsible for its
indirect descendants. By convention, the "nested" structure of the
display space is defined by the two fields dsc and next of
Display.Frame. The dsc field of a container points to the first child
of that container, and is the start of a list of direct descendants
linked by the next field. The following code fragment shows how the
children of a container F are traversed:

   PROCEDURE Traverse (F: Display.Frame);
   VAR f: Display.Frame;
   BEGIN
       f := F.dsc;
       WHILE f # NIL DO
           ... do something with f ...
           f := f.next
       END
   END Traverse;

**Remark.** The property of parental control dictates which of these
fields a frame may modify when receiving a message. A frame F is
allowed to change its own F.dsc record field and the next fields of
its direct descendants. But a frame should never change its own next
field. This property also requires that you should never interfere
with the dsc-next list of a container; although visible to the outside
world, it is under complete control of the container itself. Later, we
explain how external influences can be applied to containers.

A further complication of the display space is the location of model
gadgets. We already know that frames can possibly have a model linked
to them. The visual gadgets, for example, reserve a field called obj
to refer to a model gadget. As many frames can refer to the same model
object, the use of these fields "close" the structure of the display
space at the bottom (Figure 5.5). The general structure of the display
space is that of a directed acyclic graph (DAG). In this Figure we
have a Panel floating in two TextGadgets: the Panel containing a
Button and a CheckBox both linked to a Boolean model.

![Figure 5.5 Display space with model objects](Fig5.5.png)

In our previous explanation, we mentioned that the location of a frame
F in the display space is determined by the record fields F.X and
F.Y. We have to specify exactly what this means in the context of the
display space. By convention, F.X and F.Y are the relative coordinates
of a frame in its parent (i.e. container) frame. As the Figure 5.6
illustrates, the X and Y fields of a frame measure the offset of its
bottom-left corner relative to the top-left corner of its parent
frame. Since the Oberon display origin is in the left bottom corner of
the display, the Y offset of a gadget is always a negative
number. This setup provides the best efficiency when calculating the
coordinates of a gadget.

![Figure 5.6 Frame coordinate system](Fig5.6.png)

We should mention that a parent frame clips away those parts of its
children which lie outside the rectangle of the parent. The relative
coordinates of a frame in a container allow us to move that container
and all its descendants directly by modifying only the relative
coordinates of the parent in its own container.

## 5.6 Messages and Broadcasting

Now that the structure of the display space has been presented in
detail, we can discuss how objects (everything extended from
Objects.Object) communicate with each other in the display
space. Recall that every object in the Oberon system has a message
handler, responsible for "handling" the messages sent to that
object. There exists a large number of message types. For example,
there are messages to request an object to make a copy of itself, to
store itself to a file, to display or print itself, and so
on. However, not every message is applicable to all objects. For
example, model gadgets, that is, non-visual objects, do not understand
a "display yourself" message.

Messages are divided into classes. For the moment, we mention two
important ones: object messages and frame messages. Object messages
are those messages that all objects must respond to. This class
consists of a very small collection of messages like "copy yourself",
"store yourself" and so on. Frame messages are those messages that
frames respond to. That class includes ones like "display yourself,
"print yourself" and "move your position".

Objects might not understand some of the messages sent to them. Why
would we send a message to an object if it does not understand it
anyway? The answer lies in the display space. Let us take the example
of multiple text documents showing the same text (evoked in
Example5). We already know that when we change the contents of a text
(using module Texts), each text document displaying it is magically
updated. Behind the scenes this is solved by a special message
protocol between the text document (a view) and the text object (a
model). This protocol is "special" in that only text documents and
text objects are aware of it; they are "insiders", so to say.

### Model-view consistency

Let us trace what happens when a character is inserted into a text or
more correctly from a programming standpoint, when a text buffer is
inserted into a text. The user of module Texts does this with a call
to Texts.Insert. Behind the scenes, Texts.Insert has to inform all the
text documents displaying the text that a change has taken place. Now,
by convention, texts do not know what text document(s) they are
attached to. The only possibility left open to the text is to
broadcast a "text T has changed" message to all objects in the display
space. Since text documents are listening to messages of the type
"text T has changed" (where T is the text they are linked to), they
can update themselves when this broadcast message is received. The
broadcast functions in the following manner. First, the message is
sent to the display root. As the root does not understand the message
(because it knows nothing about texts), the only logical thing it can
do is to forward the message to the tracks it contains, in the hope
that these can have something to do with the message. However, the
tracks are just as clueless, and are forced to forward the message to
the viewers they contain. The same thing happens again, so each viewer
forwards the message to its (two) sub-frames. The message thus travels
through the entire display space in a depth-first way. Luckily, the
text documents located in the display space understand the message,
and can update the display with the character typed (which is
specified in the message by indicating the part of the text that has
changed).

This is the general scheme Oberon uses to inform views that a model
has changed. If no view is interested in the model that has changed,
the message travels through the whole display space without effect.

### Types of broadcast.

In reality, there are two types of broadcasts: true broadcast and
directed broadcast. True broadcasts reach all frames in the display
space. Directed broadcasts are addressed to a certain destination
frame in the display space. This might sound a little paradoxical. Why
do we need to broadcast a message into the display space if we know
the frame that should receive it? Why not simply send the message
directly to the intended frame (without going through the display
root, tracks, viewers etc)? Although several reasons exist (one of
them related to the Oberon display model), only one reason will be
mentioned here. As messages travel in the display space from the root
frame to track, to viewer, and so on, at any point a container frame
can make a decision if it wants to handle, ignore, change or forward a
message. Thus a frame can influence the messages its descendants
"see". This is again the all important property of parental
control. Should a parent frame not control the message a child frame
sees, the child might "misbehave". Parental control might force a
child frame to move itself only in a restricted way in a container; or
prevent a child frame from deleting itself.

### Terminating a broadcast.

Under certain circumstances, it is necessary to terminate a broadcast
early. This is typically the case when it is known that no further
frame could have an interest in the message. Thus, Oberon provides a
way to invalidate a message. An invalidated message is not forwarded
by containers, thus terminating the broadcast abruptly.

----

   END of Excerpt.

   The Oberon Companion
   Copyright 1997-1998 by André Fischer and Johannes L. Marais

----

# Some Additional Background on Oberon

But Oberon really is very different from something like Linux or
Windows. It's even far simpler than the classic SmallTalk and
Cedar/Mesa Systems from Xerox Parc. (The Mesa/Cedar work at Xerox PARC
was an influence in Wirth in his design of Oberon.)

Anyone with a Unix background would be hard-pressed to even
acknowledge Oberon as an *operating system*, but the fact is that it
performed well at it's primary task: a simple, cheap single-user
system for programming in small, clean, garbage collected, statically
typed language. It also is a pretty good environment for writing and
for simple graphics.

- In an Oberon system, there is only a single process with a single thread.
- This thread runs the procedure Oberon.Loop(), which broadcasts
 mouse, keyboard and other events to all windows.
- Sending a message is nothing more than a normal procedure call in
 which the message record itself is passed *by reference* to the
 called procedure. (The message itself is allocated on the stack, not
 the heap.)
- The handler procedure (in MVC this is the "controller") of each
 window (Display.Frame, actually) reacts to events it's interested
 in, generally by mutating the model it's displaying in some way.
- This generally causes the model to broadcast an update message,
 which viewers displaying that model will react to by updating their
 display.
- When these procedure calls have all returned, control is back in
 Loop()
- Loop periodically calls the garbage collector and calls background
 tasks, giving them a chance to do a little work and return.
- Views are responsible for forwarding (or not) events to their
 subviews. (In Oberon this is the 'principle of parental control' and
 is an important element in the design of the system.)

Thanks to Oberon's simplicity it was later ported to run on top of a
wide variety of more conventional operating systems. (I've used it on
top of Ultrix (MIPS), Solaris (SPARC), MacOS (68020+ and PPC), Mac OS
X (Intel) and Windows (3.1, NT, 2000, XP). I've also run it as the native
OS on a ThinkPad T20 and I have it a Linux hosted port on my Netbook
as I write this.

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "The 
Java Posse" group.
To post to this group, send email to javaposse@googlegroups.com
To unsubscribe from this group, send email to 
javaposse+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/javaposse?hl=en
-~----------~----~----~----~------~----~------~--~---

<<attachment: Fig5.2.png>>

<<attachment: Fig5.3.png>>

<<attachment: Fig5.4.png>>

<<attachment: Fig5.5.png>>

<<attachment: Fig5.6.png>>

Reply via email to