How should one document an interface?

O

Oliver Wong

Does anyone have any best-practices advice on document interfaces? I'm
writing JavaDocs for some interfaces in my project, and I realized that this
documentation will be read by two distinct types of audiences, with
completely different interests. Namely, people who are going to use objects
that are instances of the interface (the clients), and people who wish to
implement the functionality that the interface requires (the implementors).

Now I know that in theory, I should just be able to say what it is each
method in the interface is supposed to do, but in practice, it may be
helpful for the client to understand typical usage scenarios of the methods
and under what circumstances they may be useful (something the implementor
probably doesn't care about); and it may be helpful for the implementor to
know about tricky, behind the scenes requirement for objects implementing
this interface to work well with the rest of the code base (which the client
probably doesn't care about). As an example of the latter, implementation
for part of the interface can be generated by one of our code generators, so
I'd like to point this out to the implementor, rather than having him
re-implement the method from scratch.

Sometimes pieces of information overlap both these areas, so the
simplistic solution of having a "FOR CLIENTS" and "FOR IMPLEMENTORS" section
seems slightly too naive.

As a concrete example, here's the interface for IScopeNode, which is
part of a generic framework for compiler construction. "Node" here refers to
a Node in the Abstract Syntax Tree for a parsed program, and a ScopeNode is
a node which defines a new scoping context.

<code>
public interface IScopeNode {

/**
* <p>
* Returns the scope of this node. Clients should note that this method
will
* only return the correct information after the Symbol Table building
phase
* is complete.
* </p>
* <p>
* A typical implementation is to just return whatever was passed in from
* setScope().
* </p>
*
* @return the scope of this node.
*/
public IScope getScope();

/**
* <p>
* Sets the scope of this node. This method should only be called by the
* symbol table builder.
* </p>
*
* @param scope
* the scope to associate with this node.
*/
public void setScope(IScope scope);

/**
* <p>
* Returns a list of strings representing a hierarchical name for this
node.
* For example, in Java, a class "Foo" in the package "com.castortech"
might
* have the identifier ("com.castortech", "Foo").
* </p>
* <p>
* Clients should be free to do anything they want with the list returned,
so
* implementors should probably generate a new, mutable list, each time.
* </p>
* <p>
* A typical implementation is just to call getIdentifier() on the
* corresponding helper.
* </p>
*
* @return a list of strings representing a hierarchical name for the node
* passed in.
*/
public List<String> getIdentifier();
}
</code>

Our code generator can usually analyze the grammar that describes the
programming language whose compiler we wish to generate, and so most of the
time, it can also generate the code for getIdentifier(), though occasionally
it may fail and thus leave a TODO in the body of that method, and a human
developer has to implement it. I'd like to notify the human developer of a
shortcut utility method that can be called instead of implementing this
method from scratch, but occasionally, to address certain quirks of the
language we're writing a compiler for, the human may wish to use a
completely different algorithm.

The other two methods (setScope and getScope), our code generator can
pretty much generate the code every time (in the obvious way). Furthermore,
setScope() will probably never get called by human-written code. Should I
simply not document the setScope() method at all, since it is only used and
implemented by the machines?

Human-written code will typically be interested in getScope() and
getIdentifier(), usually to do language-specific data flow analysis.
However, because of the way that getScope() is implemented, it will only
return a valid value after the symbol table building phase is complete (that
is, after our generated code has called setScope()). How can I warn the
client about this, without mentioning setScope() and/or without getting into
implementation details?

- Oliver
 
I

Ian Pilcher

Oliver said:
Sometimes pieces of information overlap both these areas, so the
simplistic solution of having a "FOR CLIENTS" and "FOR IMPLEMENTORS" section
seems slightly too naive.

Put the common stuff first, follwed by a "Usage Notes:" section and an
"Implementation Notes:" section.
 
S

Stefan Ram

Oliver Wong said:
* <p>
* A typical implementation is to just return whatever was passed in from
* setScope().
* </p>

"As much as possible, write doc comments as an
implementation-independent API specification."

http://java.sun.com/j2se/javadoc/writingdoccomments/index.html
* <p>
* Clients should be free to do anything they want with the list returned,
so
* implementors should probably generate a new, mutable list, each time.
* </p>

This whole sentence might be redundant. It is already known,
that a defining property of an object in OOP is that it
protects its invariants. If a change to the result of an
operation by a client would modify an invariant, that would be
violated.

Possibly, the JavaDoc could only contain a minimal
documentation, while two separate documents are added: A
tutorial for client authors and guidelines for implementators.

After all, Sun Microsystems also publishes a Java tutorial in
addition to the JLS and the API-doc.
 
O

Oliver Wong

Stefan Ram said:
This whole sentence might be redundant. It is already known,
that a defining property of an object in OOP is that it
protects its invariants. If a change to the result of an
operation by a client would modify an invariant, that would be
violated.

I assume the only way to "protect the invariants" in the case of
returning a List, is to create a new copy of the List each time the method
is called. I thought it was somewhat common, when one wishes to avoid the
overhead of lots of object creation, to politely ask, in the JavaDocs, for
the client not to modify the list they get (and to warn of undefined
behaviour otherwise).

Since I *know* the client is eventually going to modify this list, I
wanted to put a warning to implementors about this.

I guess you could argue that if it isn't specified either way, one
should assume that it's safe to modify the list; but I'm taking the stance
that if it isn't specified either way, one cannot know whether or not it is
safe to modify the list (e.g perhaps the API designer didn't even consider
whether or not list modification would have side effects elsewhere), and so
it's better to state it explicitly.

- Oliver
 
S

Stefan Ram

Oliver Wong said:
I guess you could argue that if it isn't specified either way, one
should assume that it's safe to modify the list; but I'm taking the stance
that if it isn't specified either way, one cannot know whether or not it is
safe to modify the list

This is not so easy indeed.

After all, here an object A returns an object B.

The interface of A and B is specified by the corresponding
JavaDocs of the types of A and B, respectively.

Now, when it is described nowhere, whether a change to B also
modifies A, what assumptions should be made about this?

Often one uses a "closed world" assumption, that
behavior not mentioned does not occur, for example.

/** This will print the text "a" to java.lang.System.out. */
final public static void printa(){ java.lang.System.out.print( "a" ); }

Here the documentation does not write whether this method will
also place some orders at eBay and then format the
harddrives. The usual assumption is that it will /not/ do any
such behavior /not/ being described.

However, sometimes it is difficult to tell between what
is behavior and what is "not-behavior".

The question is: If neither the documentation of the
types of A nor that of the types of B mentiones that
a change to an instance of B affects an instance of A,
can one rely on the assumption that this does not happen?
 
C

Chris Uppal

Oliver said:
Does anyone have any best-practices advice on document interfaces? I'm
writing JavaDocs for some interfaces in my project, and I realized that
this documentation will be read by two distinct types of audiences, with
completely different interests.

An interface represents [the compiler-checkable part of] the contract between
the user of an object and its implementation. Since when have contracts only
been visible or interesting to one party in an agreement ?

I'd say that if /any/ part of the design of an interface (whether documented or
not, and however expressed) is only interesting to one of the parties, then
there is something /very/ badly wrong with your design. Or, more likely, that
the design is fine, but you are underestimating the amount of information that
is needed by one or the other party.

-- chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top