210 likes | 384 Views
Tool support for crosscutting concerns of API documentation. Michihiro Horie, Shigeru Chiba Tokyo Institute of Technology, Japan. API (Application Programming Interface) documentation. A good library or framework has a good API documentation Documentation in a program source file
E N D
Tool support for crosscutting concerns of API documentation Michihiro Horie, Shigeru Chiba Tokyo Institute of Technology, Japan
API (Application Programming Interface) documentation • A good library or framework has a good API documentation • Documentation in a program source file • In Lisp, a function definition can include the description • In Java, documentation is written as doc comment • Documentation tools API documentation (.html) Doc comment (.java) /** Tests if this stack is empty * @return true if and only if … */ public boolean empty() { … } Javadoc
Difficulty of modular description (copy & paste) /** Writes a class file … on a local disk. * Once this method is called, further * modification are not possible any * more. */ void writeFile(String directoryName) { : DataOutputStream out = …; toBytecode(out); : } (@see tag) /** Writes a class file … on a local disk. * @see toBytecode(DataOutputStream) */ /** Converts this class to a class file. * Once this method is called, further * modification are not possible any * more. * … */ ü ü ü ü
Another kind of crosscutting concern • Modular description for user programmers is incompatible with modular description for developers • Due to a mismatch between the two kinds of decompositions for • Programming • Classes, methods, etc. • API documentation • The behavior of publicly exposed members
CommentWeaver :a new documentation system • Allows programmers to modularize crosscutting concerns of API documentation • Across procedure abstractions • Along an inheritance hierarchy • Caused by an aspect • An extended tool of Javadoc • Provides special tags to control modularized text • Supports Java and AspectJ
Crosscutting across procedure abstractions /** Writes a class file … in the current directory. * Once this method is called, further modification * are not possible any more. */ writeFile() /** Writes a class file … on a local disk. * Once this method is called, further modification * are not possible any more. */ writeFile(String) /** Converts this class to a class file. * Once this method is called, further modification * are not possible any more. */ toBytecode( DataOutputStream) • Methods with the same name but different parameters • Descriptions of them have some overlaps • Function about red comment is implemented in toBytecode
@quote tag /** Writes a class file … in the current directory. * @quote(writeFile(String)) */ writeFile() /** Writes a class file … on a local disk. * @export { * @quote(toBytecode(DataOutputStream)) } */ writeFile(String) /** Converts this class to a class file. * @export { *Once this method is called, further modification * are not possible any more. }*/ toBytecode( DataOutputStream) • Refers to the doc comment of other methods • @export tag is used to select which text should be referred to • For maintainability, text is only shared among methods in the call chain.
Multiple @export tags /**@quote(toClass(CtClass,ClassLoader)).conversion * This is only for backward compatibility. * @quote(toClass(CtClass, ClassLoader)).warning */ toClass(ClassLoader) /**@export : conversion { * Converts the class to a * <code>java.lang.Class</code> object. } * Do not override this method any more at … * @export : warning { *<p><b>Warning:</b> A Class object * returned by this method may not work …} */ toClass(CtClass, ClassLoader) • @export with a name • @quote tag refers to the name of @export
Crosscutting caused by aspects /** Creates a new public class… * @throws RuntimeException * if the existing class is frozen. */ ClassPool + makeClass() + makeInterface() : /** Creates a new public interface… * @throws RuntimeException * if the existing class is frozen. */ <<aspect>> FrozenChecking before(ClassPool, String) : execution(* makeClass()) || execution(* makeInterface()) /** @throws RuntimeException * if the existing class is frozen. */ • Duplicated description • makeClass and makeInterface never throws RuntimeException
@weave tag ClassPool + makeClass() + makeInterface() : /** Creates a new public class… */ /** Creates a new public interface… */ /**@weave(exec(* makeClass(..)) * || exec(*makeInterface(..))) { *@throws RuntimeException * if the existing class is frozen } */ <<aspect>> FrozenChecking before(ClassPool, String) : execution(* makeClass()) || execution(* makeInterface(*)) • Used to append the following text to methods selected by the argument • Its argument is AspectJ-like pointcuts • call, exec, etc.
Special values for @weave exec(* makeClass(..)) || exec(* makeInterface(..)) • JP • Avoids the repetition of the AspectJ pointcut • Represents join point shadow • cflow and if pointcuts are ignored • (ex.) @weave(JP) {@throws RuntimeException …} • JP_CALLER and JP_CALLEE • Appends text to the caller / callee methods • (ex.) @weave(JP || JP_CALLER) {…}
Crosscutting along an inheritance hierarchy /** Defrosts the class so that the class can * be modified again. * If defrost will be called later, pruning * must be disallowed in advance. */ /** Defrosts the class so that the class can * be modified again. * If defrost will be called later, pruning * must be disallowed in advance. */ CtClass + defrost() : /** (none) */ CtClassType + defrost() : • Public interfaces (or abstract classes) • Actual implementations given by non-public classes • If non-public classes show implementation-dependent behavior,the description should be written in them, instead of public ones.
@weave tag for methods /** Defrosts the class so that the class can * be modified again. */ CtClass + defrost() : @liftup = /** @weave(exec(void CtClass.defrost()) { * If defrost will be called later, pruning * must be disallowed in advance. } */ CtClassType + defrost() : • Also available in the doc comment of methods • @liftup tag can be used instead of @weave • Takes no argument
Case studies • We found many crosscutting concerns in real API documentation • Javassist • version 3.6 • Java standard library • Java 6 • Eclipse • Release 3.3 • An AspectJ version of Javassist • based on Javassist 3.6
Javassist crosscutting doc comments number LOC • 9% violatesprocedure abstractions • 22% reduction (LOC) • All modularized
Crosscutting along inheritance hierarchies in Javassist • Requires @liftup / @weave tag
The standard library of Java 6 number LOC • 20% violates procedure abstractions • 21% reduction (LOC) • All modularized • We selected only the packages that contain more than 100 public methods and 1,000 LOC of doc comments • Nothing violates inheritance hierarchies
Eclipse number LOC • 4% violates procedure abstractions • 10% reduction (LOC) • All modularized • 107 violates inheritance hierarchies
An AspectJ version of Javassist If an aspect implements a functional concern, that concern must be described in the API documentation of the advised classes.
Related work • Javadoc, Ajdoc • The documentation of the CLOS Metaobject protocol [Kiczales et.al. ’92] • Verifying specification of class libraries • Design by contract [Meyer ’92] • Typestate checking [Bierhoff et.al. ’07] • FUSION [Jaspan et.al. ’09] • Literate programming [Knuth ’83] • Approaches to understand crosscutting structures • Aspect-Aware Interface [Kiczales et.al. ‘05] • Open Module [Aldrich ’05] • XPI [Griswold et.al. ’06] • Active model [Coelho et.al. ’06]
Concluding remarks • CommentWeaver • Aspect-oriented simple extension to Javadoc • Modular description of doc comments • Crosscutting concerns of API documentation • Procedures, inheritances, and aspects • We found real examples • Javassist • Java standard library • Eclipse framework • AspectJ version of Javassist