l4-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: DogCows or Polymorphism in the Hurd


From: Jonathan S. Shapiro
Subject: Re: DogCows or Polymorphism in the Hurd
Date: Thu, 02 Feb 2006 21:28:45 -0500

Marcus is replaying a conversation that started at my house. Some ascii
art may help. I will try to respond to questions on this subject, but
poor Marcus is stuck on a plane for the next 18 hours, so he may need to
correct me later.


The term "dogcow" came about to describe the following interface
hierarchy:

      Animal
      /    \
     Dog   Cow
      \    /
      DogCow

That is: a holder of a DogCow capability can invoke either the "Dog"
methods or the "Cow" methods. If I remember, the original discussion
started with Plan-9, where directory and file operations are mingled in
the 9p protocol.

[At the time of the discussion, my dog Morgan was assisting us by
allowing us to scratch her back, and our cat, Snickers, was commenting
on how silly we all looked in front of the whiteboard with the stupid
dog when we should really be petting him instead.]

Consider the following DogCow interface:

     FsObject
      /   \
     File Dir
      \   /
     FileDir

Now suppose that a client performs the following operations on a FileDir
capability:

   readDir()
   write()
   readDir()

We haven't really got two facets here at all. What we have is two
interfaces that have been mingled on a *single* facet. In abstract,
there is nothing wrong with this mingling, but we must be able to give a
sane story for what happens when arbitrary sequences of operations
happen like the example above. To make matters worse, the senseless
sequence may be done by two independent callers that know nothing about
each other -- the theory that this was an application error is mistaken.

Marcus notes that this practice causes confusion for POSIX tools in
Hurd, because they cannot figure out whether they are looking at a
directory or a file. Hurd has been lucky. The problem is MUCH worse than
this.

Consider that there are cases where a translator might reasonably
implement two (or more) *file* facets, and in this case we *must* know
which facet is invoked in order to understand what each read() call
means! How about a single translator that simultaneously presents a ZIP
file view, a TAR file view, and a directory view. Notice that both the
ZIP view and the TAR view both want to "own" the operations exported by
the file interface. Multiple inheritance simply won't work here.

There is a fundamental semantics issue here:

  A method call in isolation has no meaning. It can only be interpreted
  in the context of a particular interface.

Because of this multi-file example, when Marcus writes:

> Either we convince ourselves that such erratic
> behaviour is isolated and can be fixed by proper defaults and making
> minor modifications to existing programs.  Or we find out that in
> general this problem is too hard to fix...

I respond: the problem is foundational, reflecting a fundamental misuse
of the semantics of interfaces. The file/directory confusion is actually
a benign example, because there are no common methods in the multiple
inheritance. The ZIP/TAR/DIR example demonstrates that the mix-in
(multiple inheritance) style of interface is a broken pattern.


The polytype pattern that Marcus proposes would yield the following
alternative interface hierarchy:

       PolyType
        /    \
      File   Dir
     /    \
 ZipFile TarFile

where PolyType provides methods

        getSupportedTypes()
        getFacet(type)

this still allows polymorphism, but without ambiguity. The specialized
interfaces ZipFile and TarFile don't provide any new methods. They exist
only to provide distinct interface type codes.

> What would this mean for our tar.gz example?  It would mean that a
> translator implementing a tar.gz feature would either be seen as a
> tar.gz file, _or_ as a directory to the root of the archive, but never
> both with the same object.  In particular, the tar.gz file and the tar
> root directory would get different names in the directory hierarchy.
> For example, the tar.gz node could be called "foo.tar.gz" and the
> archive root dir could be called "foo".

Here is a real-world illustration of the file/directory confusion.

Recent versions of Windows have the ability to stick a plug-in into the
file browser. You can explore foo.zip as if it were a directory. But
there are anomalies.

Many installers are distributed electronically as ZIP files. If you
attempt to run setup.exe from one of these ZIP files after browsing into
the ZIP in a directory view, the execution will fail because the setup
application sees installer.zip as a file even though the user sees it as
a directory. When the installer goes to open files in the installation
directory tree, it fails.

A better design would solve this by binding the new view to "foo.dir" or
just "foo", and really registering this as a directory. In this approach
the installer logic would all work just fine, and the view would even be
permanently bound in the namespace. At this point the user could even
unlink the .zip file without losing anything!

> It sounds a bit lame to leave the problem which facet is the right one
> to use in the context of POSIX applications to the user.

To me, it seems empowering. By allowing me to name the facets, I am
given control to determine which view of the object I want to see where.
This is exactly the type of control that I, as user, would like to have.

> * What are compelling use cases for hybrid types?

To first order, every example of a Windows Explorer plug-in is a
compelling example where somebody found this useful. Off the top of my
head, I know of plugins on Windows for tar, zip, cab files, and for
thumbnails of several hundred formats (yes, thumbnail is just another
facet!).

> * How severe are the confusions in the POSIX world introduced by hybrid
> types?

Pretty horrible. ZIP/TAR/DIR is obviously not the only useful example.

> * How complex is the problem how hybrid types should be perceived by
> legacy applications?  Is it multi-dimensional and/or context-sensitive?
> Are there reasonable default resolutions?

I think a better question is: why should the new architecture deprive
the user of control over which view they want? Let the user name the
view and let the application do what it is told.


Best regards,


shap





reply via email to

[Prev in Thread] Current Thread [Next in Thread]