Thursday, August 16, 2012

Exploring Desktop Objects #1

Recently I played a little bit
with Pharo (which is a fork
of Squeak Smalltalk) and I was quite impressed with it. Since this was my
first connection with Smalltalk, the language simplicity and clarity
struck me hard, wondering why we are still living in dark ages of C++/Java
or whatever language that is daring to call itself Object Oriented.

A perfect companion for this language comes in form of it's own
environment: you have a full desktop under single executable which isn't
desktop in a normal sense: it is much more like environment of
objects, where everything you touch and move (window, button) is a true
object.

Of course, every sane GUI C++ program will use object notation for
buttons or windows, but at the end, they are compiled down to assembly
and you are done with it. To have a false sense of ability to change it,
you would modify some configuration files, reread them and load the
program again.

With Smalltalk is different: if you want to change how button looks in
certain window, you just get it's object and call whatever method you
can call (in Smalltalk parlance: you send a message). Or, if you, at some
point would like to see how this window is written, you simply query it's
source code.

If you are still not convinced,
check these
videos from Alan Kay's Etech Presentation. Remember that was
2003 and we still can't do many of those things with (insert your
favorite language here), no matter how fancy it is.

But, this article is not about how Smalltalk is glorious but what can
be done to improve current situation. And some things can be done indeed,
even if we are still living in stone age of modern languages
(sic).

Now lets go to the matter.

Today modern way to communicate between desktop components and
applications
is DBus
so situation here is very much status quo. DBus became stable,
everyone use it and everyone is happy.

DBus brings notation of object paths,
interfaces and methods; you can see object paths as instances living
in certain namespace, which is pretty neat since you will have a lot
objects floating around.

So DBus is very much object oriented, but why we are still have
stone age tools to handle it? I'm not counting here language bindings
(where btw. some of them are awesome), but the tools for exploring current
objects (or object paths) and their context. Let we see what we have:

standard tools shipped with dbus (dbus-monitor and dbus-send): well
unless you know how to manually encode the message with array of
strings or, for God sake, struct of arrays and dictionaries, you
have to look somewhere else

qdbusviewer and qdbus: much better, comes with Qt. Even
qdbusviewer will popup a dialog to fill method arguments when you
are going to call that method. However, services which do not have introspection data will make it
unresponsive (you will need to restart it). Setting complex
parameters (like arrays or dictionaries) is not possible.

DBus Explorer:
never tried it, but C#/Mono background decided for me to never try
it; I don't have mono installed and not planning to do so.

How about some tool with exploring ability and ability to write
and call custom code from the same place? Or maybe to have some IDE
capabilities like generating code or displaying documentation of selected methods? Unless
you are going to write it, there isn't one.

Why this matters when we have nice language bindings and even better
archaic tools like dbus-send?

Well, let suppose you are going to write
a client for PackageKit, but
your language doesn't have ability to
integrate packagekit-glib2 (or it was packagekit-glib
:P) or simply, you don't want to add another library as dependency?

In that case, the only solution is to
read reference
api where you will get lost in a matter of seconds. Who needs
examples when all methods are nicely documented and colored. What to
call in which order? Well, either read the code or use dbus-monitor.

With the same approach applied above, if you are going to write your console http client (for example), you would either have to consult firefox
source code or use wireshark to decipher http protocol. C'mon people, we
are not living in '90-ties any more; we are lazy today and we prefer to see examples
first.

Or, let put PackageKit aside (as we don't write package
management tools every day). How about to see what (DBus) services we
have on our system, which interfaces and objects they exposes? Or
simply, your program exposes services; how the hell you are going to
test it? Again, you will use either dbus-send or write some testing
code with python/ruby/etc. (before that make sure to download all
their dependencies as their developers like to depend on as much
libraries as possible).

So to make situation in this field less painful as possible, the last
couple of days I was working on edelib-dbus-explorer (it comes
with edelib from svn). With it, I was trying to address above issues
that itched me for some time.

edelib-dbus-explorer (as you can see from the shot) looks much like
qdbusviewer, in layout form, but adds scheme interpreter as the main
communication point (or better say edelib-script, which is
nicely packaged tinyscheme with a bunch of addons).

In a Smalltalk fashion, you explore services and objects, find some
method and hit 'Send to editor': you will get a code snippet ready for
evaluation. Then, you continue to write some more code, add another
method call and at the end, save everything. Could it be more
complicated?

edelib-dbus-explorer recognizes almost all DBus types (except
signatures and file descriptors); return values will be converted to
scheme objects (simple types to corresponding scheme values, like
DBUS_STRING to string and complex to lists, or list of lists like
dictionaries). For input types (those that serves as arguments to
method calls), explicit type designation must be appended as
DBus is picky if you use uint32 or int16 because signature is different.

But, explicit typing is not an issue: when is instructed to generate
code, all types will be correctly placed with added REPLACE_ME
placeholder, which must be replaced with appropriate values. Hitting Shift-TAB
will jump between those placeholders.

Is this better than previous solutions? I'm confident it is and can be
even better, which adds more room for improvements.