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
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