Personal info for AndreasRaab

This person is currently certified at Master level.

Name: Andreas Raab

No personal information is available.

This person is:

Recent diary entries for AndreasRaab:
RSS

18 Oct 2004  »

Jasmine is out. Yeah! I'm so glad it is and I'm even more glad to see the reactions of people. In our discussion on the day of the release the question was brought up whether anyone would notice but, oh boy, they did. As far as I can tell we have been on the front pages of slashdot, osnews, opengl.org, and (here in Germany) both Golem, and Heise.

What surprised me most is that apparently a lot more people grasped it this time than before (in the Croquet alpha drop a year ago). It went as far as people complaining about the (admittedly short) Heise article and claiming that the writer of the article (who actually knows what he's talking about and run the article by me, e.g., it was semi-officially approved) didn't know what he was talking about. After reading Julien's blog entry I even went so far as to read the Slashdot articles (something I hardly ever do since most of the time the signal-to-noise ratio is just unbelievably bad ;-)

By the way, this time being slash-dotted didn't hurt us one bit. The universities were able to set up bit-torrent to solve the inevitable download problem and the web-site itself withstood the (about two orders of magnitude) larger number of requests. Check out Julien's story on being slash-dotted.

28 Feb 2004  »

Gesh, haven't been very active in my diaries over the last two months. Oh well, there has been so much going on with Tweak, Croquet and all the other stuff that I've had hardly any time to write some notes up here. So this is going to be a more lengthy entry.

The two most important things that happened lately to me was that I finally had the breakthrough I needed for being able to deal with "complex costumes" and "ownership" relations.

Players and Costumes

In Tweak, each graphical object exists in a "dual" representation - as a "model" like object (called a "Player") and as "view" like object (called a "Costume"). The basic deal here is that "players direct costumes" (such as requesting them to appear at this or that position) and "costumes notify players" about certain events (such as a mouse down). What had been really bothersome was that there was only one kind of "primitive costume". While there are good reasons to have primitive costumes (basically, they encapsulate all of the uglyness of the framework internal stuff) it was problematic that players were always a mixture of "abstract and concrete" objects, not much different from morphs. Meaning that they contained certain state that the user is most definitely interested in but also some stuff which was essentially "implementation left-over".

For example, a ScrollBar had some state (such as its min, max, value etc) which the user would be modify but then also had state such as the forward and back button, the scroll area, its scroll knob etc. which really was very implementation specific. Meaning it is almost impossible to have "other kinds of scrollbars" which did not have any of these parts and just blitted a bitmap on the screen.

The breakthrough here was simply to realize that being a "player" or a "costume" are roles rather than types. In other words, the above definition of costume and player can be applied to any kind of object if it just fullfills the requirements. Changing a whole bunch of the implementation actually made this work - now every player can also act as a costume. Meaning that suddenly our scrollbar example breaks down to having a "scrollbar player" with the abstract state (min, max, value) and a "scrollbar costume" with the concrete state (forward, back button...) which is simply that scrollbar's costume.

One of the effect that I hadn't really anticipated here but which fell out for free, is that this scheme also gives us "viewing" for free - there is no reason that an object can only have "one costume"; there may be many costumes for the same object and it's simply the "primary one" which the player directs immediately. But other costumes can perfectly well "view" the state of the same player. So all that one has to do for the above scrollbar example to get "another view" is to create a new scrollbar costume and set its player to some other scrollbar - voila, they both show the same state, but appear in different places of the screen (as the player will only direct its "primary view" - the costume it knows about).

In addition, we can have various costumes for any kind of player - in fact we can change these interactively. So one of the things I'll probably be doing is to provide a number of "native costumes" which simply go straight to the OS and just use whatever it provides. The nice thing is that the application will never even be aware of this - all it deals with are the players and what kind of costumes these players wear is actually up to the user.

Also note that the players which "act as costumes" use other players as well - so for example, the "ScrollPane costume" I have defined can perfectly well use a "ScrollBar" which is carrying, say, an OSX-ScrollBar costume. It is really interesting to see how much most frameworks screw up in this regard. For example, take MVC - if I would implement the scroll pane I would have to refer to the scrollbar's view since it is the only object that provides graphical state (such as position, extent etc). So if the scroll pane needs to be able to re-arrange the scrollbars it cannot do that short of "poking around in the view". What Tweak provides here is a graphical model and its because of the ability to describe graphical models that you don't have to "look behind the curtain" to modify graphical aspects (to be precise it's a combination of delegating graphical state to the costume and keeping the "model" state in the players which achieves that).

Ownership of objects

The other really intriguing thing that happened lately is that I finally fully realized why "Tweak" is called that way. It turns out that it really is the ultimate user interface tweaking tool. Something that I hadn't even dreamt about when it started. So what does this mean?

One of the fundamental differences between Tweak and Squeak (or more appropriately: Morphic) is that there is a really strong notion of ownership. Most objects created are owned by others in a way which effectively means that they play an important role for their owner. For example, consider a window - it may have a close button, a collapse button, a label. These objects aren't random - they serve a well-defined purpose within that window and Tweak allows for very easy description of these roles.

As a completely random besides here, the term "owner" from Morphic is really wrong. The objects aren't owned they are contained within their "owner" (so "container" would be a much better term). Why is this problematic? Actually, it wouldn't be problematic at all if Morphic wouldn't allow us to change the composition of morphs. But since it does, treating the submorphs as parts of their container is really wrong. Formulated differently: Does a SystemWindow's closeButton change if I take it out of the window and put it on the desktop? No, it doesn't. It's still the SystemWindow's closeButton and acts like this window's closeButton.

The most profound implication for this is that when we interact with an object in Tweak graphically, we not only know about this object in its "primitive form" (such as: this is a button, or this is a label) but also about the role it plays in the entire construction. So if we interactively modify the close button in a window we can easily describe the modification in terms of "the user has changed the window's closeButton to have the color red". Since almost all objects are owned, it is trivial to pin-point precisely what modifications were done by a user, even if it gets lengthy such as "the user changed a ClassBrowser's systemCategoryList's listWidget's vScrollBar's backButton's color".

With a "tweak description" like this, we are able to take it and apply it to any object that "matches" (e.g., has the same type/properties) - so if we change that backButton, we can take any other browser and apply precisely the same changes.

What's more is that these tweak description are context-sensitive in the sense that we can describe local tweaks as part of an overall composition. For example, in the above we describe a change to a button but this change only applies to "the backButton of a vScrollBar of a listWidget of a systemCategoryList of a browser" (and not to all buttons in the world). So if we have a composite object, we can tweak it in any form or shape and have the tweaks apply only to that particular context. Practically, this means that while we can tweak "windows in general" (such as in the above) we can also tweak "a browser's window" to be different from "a text editor's window".

Finally, since we're exclusively dealing with "user tweaks", the application's behavior is not affected by it at all. If I am in the midst of using a browser and realize that I really don't like this or that graphical aspect, I can change it, and the system will save only the changes I have done interactively. Meaning that the next browser which comes up will carry the graphical changes but still work just like it did before.

What this really does is bring the "turnaround times" for user interface changes down to zero. There is simply no "programmer intervention" involved in changing any of the UI aspects and the changes are applied in a side-effect free way. In fact, the programmer may not have to provide any user interface at all - the browser could be build exclusively by applying "tweaks" in the graphical domain.

How so? It really goes together with the first part about players and costumes. If the programmer uses the appropriate "models" for the composition of some application, a user-interface designer can just choose "the right costumes" for the objects. So a Browser can just be defined as a set of lists, an editor and a UI designer can ask the system to hand it "a costume for the list", decide what kind of costume to use, bring it into the right place and save the composition as a "tweak" for the browser. The programmer doesn't have to be involved at all except from providing good and easy to use models.

And that's what good programmers are good at anyways: Building models.

5 Dec 2003  »

Okay, today I did it. I shipped my previously small experiment with positional arguments as an update in Croquet. The major reason being that after some discussion with DAS we both agreed that it's worthwhile to give people a way of using the "already documented APIs".

In this particular case we were talking about the OpenGL interface. Here, almost every book in existence will talk about (say) "glVertex3f(0.0, 0.0, 0.0)" and having to write "glVertex3f: 0.0 with: 0.0 with: 0.0" is really a pain. In particular because the extra keywords don't convey any additional information as is standard practice in Smalltalk. I actually used the non-descript keywords quite deliberately to begin with, since "inventing new names" for these methods would completely screw up any existing knowledge and be totally out of whack with the books.

If OpenGL were invented in Smalltalk the above may have been called glVertexX:y:z: or somesuch. But it wasn't. And since it's hard enough to write good documentation, and since the documentation has been written already, it seems better to go with the well-documented set of stuff and break the Smalltalk rules a little. Or at least that's what I think.

The only issue that concerns me a little is what's going to happen with the "standard style of programming". Will Croquet end up with half of the methods being keyword messages and another half being positional messages? I don't know but time will tell. And even if it does it's not clear to me if that mixture is really that much of a loss here.

21 Nov 2003  »

Another day, another bug. The recent discussion about performance of Seaside and Comanche got me looking really close at the VM-level socket interface. After digging around a lot and running a few profiling sessions with avi and spair via IRC I finally found a really ugly bug in the Windows VM.

Whenever Squeak has nothing to do we send it to sleep to minimize CPU usage. On Windows, this is done using a function which will wake up if "something interesting" happens (such as socket activity). Or so I thought. Turns out that the VM didn't awake from its nap when data was arriving on the socket. I had simply forgotten to signal the appropriate event for waking up the event. Oh, dude.

After fixing this problem my little benchmark for testing the socket interface showed dramatic improvements. So now on to building a 3.7alpha VM using Tim rowledge's new VMMaker package.

18 Nov 2003  »

Today I finally finished the "real" Tweak object storage mechanism. It uses a very simple serializer/deserializer interface which essentially looks like:

Point>>writeFieldsOn: aSerializer
  "Write my fields on the serializer"
  aSerializer writeField: #x value: x.
  aSerializer writeField: #y value: y.

Point>>readFieldsFrom: deSerializer "Read my fields from the deserializer" x := deSerializer readField: #x. y := deSerializer readField: #y.

Why naming the fields? Mostly two reasons; for one thing it makes the mechanism robust when the object changes shape. For example, let's say you renamed an instVar from #foo to #bar, this is what you would write:

  bar := deSerializer readField: #bar ifAbsent:[
     "Older versions of the object may have #foo"
     deSerializer readField: #foo.
  ].

Simple as that. The second reason is that the serializer may use the keys for additional reasons (such as exporting to a well-defined text format - i.e. XML - which is used by Tweak). And yes, the deserializer can play a few tricks to make reading more efficient (such as re-ordering all fields based on their "last usage" so that after the first instance of a class was read the next one(s) don't pay the lookup-overhead anymore). Not that I've found speed to be a problem so far but it's always good to know what can be done if that ever gets a problem.

It's interesting where one ends up after "all things were considered". Originally, I had a much more complex interface that tried to be "smart" about the object it is storing and made all sorts of guesses. It sure worked ... but when I thought that some poor guy would have to use that interface it just got too complicated. In the end, the simplest interface was the best. Primarily because you can always just store everything and if you need to do something specific, then having to understand a complex interface only gets into your way.

Now I have exactly two interface to explain. Namely #writeField:value: as well as #readField:[ifAbsent:] with very clear and obvious semantics. This should make it simple to use the object storage mechanism as well as implementing new clients. Unfortunately, there are still some restrictions on what you can do in #readFieldsFrom: (since the object you read may not be "fully loaded" yet due to cyclical references) but that really can't be helped.

And finally, once I get the component interfaces working, all of this will be incredibly fast and compact. As always, higher-level optimizations outperform lower-level optimizations, so why bother?!

3 older entries...

This person has certified others as follows:

Others have certified this person as follows:

[ Certification disabled because you're not logged in. ]

[ Home | Articles | Login/Account | People | Projects ]