Enhancing Modularity, continued
Provision for Explicit Interfaces
Another advantage of the "everything is a file" philosophy for modularity is that once you find your object in the common namespace, you can expect to communicate with that object using a read-write interface. The idea is that if all objects respond to a least common denominator interface, then tools written to that interface will work interchangeably with most objects.

However, we observe that given a least common denominator interface, one must implement more complicated interfaces over the basic one. So in reality, although most tools can access most objects (ioctl()s notwithstanding), every tool in fact assumes some higher-level interface, and only makes sense operating on objects that conform to that interface.

Examples include record-per-line files (on which grep operates), record-and-field databases, key-value databases, tree-structured files, rich-structured files (graphics or object file formats), and daemons which expect a read­write dialog based on a specific protocol.

We conclude that the result of a least common denominator interface is the proliferation of externally documented or even undocumented interfaces implemented over the basic read-write interface. Because higher-level interfaces are not machine readable, tools cannot detect whether objects implement the interface they require, and programmers spend effort parsing input and formatting output to implement ad-hoc interfaces.

How do we retain the modularity of a common interface while making higher-level interfaces explicit? We favor designing a system based on method invocation. The least common denominator is that any tool can query the interfaces supported by any object. However, objects can implement multiple interfaces, thereby allowing objects to work with common tools that use simple interfaces, while also offering more specific interfaces to tools which can manipulate them. Because the interfaces are explicitly declared, tools can detect whether they are operating on objects for which they make sense.


Pervasive read-write interfaces depend on libraries linked with tools for abstraction to higher interfaces. Object implementations are made rigid.

Explicit interface definition hides implementation behind interface, so that tools can detect which objects implement an interface, and so that implementation is free to evolve.

Given explicit interfaces, objects can implement multiple interfaces, providing for manipulation with the maximum number of tools which are appropriate for the object.