It is 2003. About fifteen years ago, I learned my first object-oriented language. In the last decade, the programming community in general was finally convinced that OOP is necessary for producing maintainable and reusable code.
However, most programmers, specially in the Free Software community, still use C - a non-object-oriented language developed in the 70s to solve the problems of that time with the techniques of that time. For some reason, everyone is writing their own conventions for writing object-oriented code in C - the most notably case is GObject, used by GTK and Gnome - instead of switching to object-oriented or at least object-supporting (like C++) languages.
Why is that? Perhaps, as aptly noted by the GNU coding standards, C is best supported, and more people know it. Or perhaps we're sentimental. Or perhaps most of these languages offer too many inconveniences. C++ is too complex, making it too easy to blow out your own feet, or to make your program too slow. Java requires its own virtual machine, separate from the underlying OS, which gives some people a bad feeling. ObjectiveC's syntax is strange, I always feel in an Alice-like dream where I have to code in C and Smalltalk at the same time. And the others are interpreted, which, we're told, impacts performance.
Whatever the reason, people continue to use C. Let's call that fact 1.
Apart from that, fact 2 is that the object-oriented metaphor hasn't crossed the boundaries of our programs. In 1988, I figured in a few years we wouldn't be writing "programs" anymore; instead, our OS would be a soup of objects, and we would only write classes and methods for them. This vision never came true. The systems of today are still very C-ish in nature, centered around the notion of monolithic "processes" that have to be initiated, then pointed to the data, and then closed.
This, in my opinion, severely cripples the Free Software community. We believe that it is good to modify software, bend it to our needs, and then if our changes are useful, share them with others. But with our application-centered systems, any program useful enough is also very complex; you usually have to study the source code of the whole package, to find the functionality you want to enhance, understand how it works, change it how you want, and then pay attention if you didn't break anything unrelated. This, in OOP jargon, is what we call "spaghetti code".
Another common requirement we find these days is extension; we want to make our software able to load pieces of code conditionally, without a recompile. We call these "modules", or "plugins". This is indirectly related to our half-hearted adoption of OOP, because OOP presumes extensibility and reusability; well-written objects can be used in contexts that their author didn't foresee, and still do their job.
Now it is 2003, and I finally got tired of seeing everyone writing their own object system in C, and writing their own clever way of loading modules (or plugins), and loading data from files, making it look like objects, using it, then dumping it to files again.
In the past few years, I accumulated a pretty good experience in data serialization and desserialization (or in human language, representing objects as streams of bytes, and restoring them from such streams). Then I figure, we already have a pretty good medium to store our objects - our filesystem! If only we walk back one step, and see things from a bigger distance, our "process" may become methods, and instead of writing colossal programs, we can go back to "the Unix way" and write many small methods that, together, form a class (or in other words, perform a job).
For an example of how this could work, let's imagine a Document class. It would be represented in the filesystem by a file, in some document format. Now, instead of opening a document processor to edit it, you tell Om to send it the "edit" message, something like:
$ om-send ~/mydocument edit
When you do this, the system first has to desserialize the object
represented by ~/mydocument. It opens the file, looks
for signature sequences ("magic numbers"), and determines it's in our
XYZ document format. Then it finds a desserializer component for this
format, by looking in a repository of such components (we call these
translators; usually a translator is both a serializer and
desserializer). Now we have a neat object in memory.
Next we find its "edit" method. We ask the translator what is the
class of the object; it returns, let's imagine,
"/usr/lib/om/Classes/Document". This object ID is also a filesystem
path; if you ls it, it could be a shared library, or a
directory (or anything you have a translator for). Let's imagine, in
our example, it is a directory. There is a translator for
directories; it loads the directory and builds an object in memory
representing it. Now we can query the class for the "edit" method,
which is represented in the filesystem by an executable.
You guessed it - we now load the method using the translator for binary executables. We then ask the translator to run the method, passing it the object representing "~/mydocument" as the "self" context. The method opens a window and performs the edition, perhaps calling other methods to help it out.
Now, as you probably imagined, this method could also have been a Guile, Python, Perl, or even shell script. Or you could go to that directory and replace one method; as long as you kept the interfaces right, everything would continue to work.
Instead of our imaginary "om-send" program (the shell interface, as I call it), we could also have a tool that graphically displays an object (your home directory, for example - remember, it's an object too) and allows you to send messages to them using a GUI - for example.
This is my vision for Om. To fulfill that vision, I'm writing a few components:
- libOm, a library against which methods written as binary executables will link; it provides APIs to find other objects, send messages to them, and set attributes on "self".
- A core collection of classes, translations and other objects, so that the system adds up to an usable object system capable of basic operations.
- The "shell interface",
om-send, to allow users to send messages to Om objects from a command line.
(And perhaps more I don't remember right now...)
If you want to know more, technical details are in our CVS: in the Todo database, and in some header files - but until a release, the header files are subject to change and not to be trusted. And, of course, comments are welcome.