...
A related goal is to design the documentation so that it is easy to maintain, so that it remains tends to remain internally consistent with the framework itself.
Change Happens
Anyone who has worked with databases knows the value of normalizing the schema. Ideally, we want to store each fact exactly once, and then use query system to retrieve that fact whereever it is needed. If we store a fact once, we only need to update it once, and we avoid inconsistencies in our data set.
Do it now. Do it once. Do it well.
Overall, there are three goals for the documentation system.
- Say it all
- Say it once
- Say it well
FirstTo the extent possible, we want to "normalize" our technical documentation. Like a database, all technical documentation is subject to change. When change happens, we want the documentation to be as easy to update complete as possible. One way to do that is to try and minimize redudency (without sacrificing ease of use).
Single sourcing with snippets
The "holy grail" of technical documentation is single sourcing. One way we try to single-source documentation is to pull content directly from the Javadocs and source code into the documentation.
Using a snippet macro, we are able to tag portions of the Javadocs and source code for reuse. The macro fetches those snippets from the repository and merges the conntent into the documentation.
Tip | ||
---|---|---|
| ||
Before writing any new content, ask yourself if we could place the content in the repository in either one of the example applications or the Javadocs. Rather than contrive an example, can you pull a snippet from one of the applications? Rather than reiterate Javadoc, could we update the Javadoc and make it a snippet? |
Here are some examples of the snippet macro in action:
{snippet:id=description|javadoc=true|url=com.opensymphony.xwork.interceptor.LoggingInterceptor}
or
{snippet:id=example|javadoc=true|lang=xml|url=com.opensymphony.xwork.interceptor.LoggingInterceptor}
or
{snippet:id=sitegraph-usage|lang=none|url=webwork/src/java/com/opensymphony/webwork/sitegraph/sitegraph-usage.txt}
or
{snippet:id=ajax-validation-example|lang=xml|url=webwork/webapps/ajax/src/webapp/lesson1/example.jsp}
Legend:
id | The name of the snippet (required). |
---|---|
url | The URL where the snippet can be found (required). |
lang | The language that the code block. If this snippet is simply text, don't include this parameter and the content will be printed outside of a code block. |
javadoc | If true, the content is within a Javadoc block. If this is set to true, then the preceeding "* " (asterisk-space) characters will be stripped before merging the content. Also, the content is assumed to be already HTML escaped and won't be escaped again. |
All snippets are marked off by the pattern START SNIPPET: XXX
and END SNIPPET: XXX
where XXX
is the name
of the snippet that is assigned in the id
attribute of the macro. The URL is typically a location that points to the project's source control contents.
About URLs
As you probably noticed in the examples, there are several formats for URL patterns. A fully-qualified URL is always allowed, though that is often not practical. We've customized the macro to be a bit more intelligent with the URL attribute.
- If the URL appears to be a class, we assume it lives in
src/java
, convert all the dots to slashes, and then append.java
to it. - If the URL doesn't start with "http", then it is assumed to start with _https://opensymphony.dev.java.net/source/browse/*checkout*/_, as you saw in the third example.
About snippet markers
When possible, all snippet markers should be in comment blocks. How they are commented depends on where the snippet is being embedded.
Code Block | ||||
---|---|---|---|---|
| ||||
<!-- START SNIPPET: xxx -->
...
<!-- END SNIPPET: xxx -->
|
Code Block | ||||
---|---|---|---|---|
| ||||
if (true != false) {
// START SNIPPET: xxx
System.out.println("This is some silly code!");
// END SNIPPET: xxx
}
|
If the snippet is embedded in Javadocs, use HTML comments as they won't render in the Javadocs. For XML examples in Javadocs can be tricky. (See Timer Interceptor for an example.). Javadocs want to use the <pre>
tag, but you don't want that tag in the snipped content.
One technique is to embed the snippet markers inside the <pre>
tag.
This is job one! The documentation should be a repository of all the tips and tricks we use in our own applications, and it should also be a quick but comprehensive introduction to the framework, so newcomers can get started as easily as possible.
Second, the documentation should be easy to maintain. Ideally, we should cover the detail of each topic once, and draw as much detail from the source code and examples as possible (using the snippet macro).
Third, the documentation should be text-book quality; if not in the first draft, then in the next. Don't hesitate to hack in a new page. Better that we have the page than we don't. (See Job One!) But, as time allows, we should try to make each page the best that it can be. A lot of people access the documentation, and it's worth the effort to make the "documentation experience" productive and enjoyable.
Capitalization of common terms
- Java
- Javadoc
- HTML
- XML
General Punctuation and Grammar
Good online resources for punctuation, grammar, and text style include
In print, two excellent (and inexpensive!) resources are
Quick Tips
- Use as few words as possible. Instead of "but there are some quirks about it" try "but there are quirks".
- If a list of items includes both a term and an explanation, consider using a table instead of bullets.
- Avoid using "This" by itself. Instead of "This lets us" try "This strategy lets us".
- Ask yourself: "This what?"
- References to other wiki pages can be unqualified. Instead of "See Style Guide page", try "See Style Guide."
Don't be smurfy!
A lot of API members use the term "action". We have
- action extensions on pages,
- action attributes in forms,
- action elements in configuration files, and
- Action Java classes, some of which may implement the
- Action interface, and, of course, we're now calling the framework "Action" too!
Here are some terms that can be used to help clarify which action is which.
- Use "the framework" or "SAF2" to refer to Struts Action 2 as a whole, including any frameworks we use internally, like XWork and OGNL.
- Use "Action class" to refer to the Java class incorporated by the action element.
- Use "action mapping" to refer to the object created by the action element.
...
lang | none |
---|---|
title | Snipping XML examples from Javadoc content |
...
About Headings
This section refers to: Notation Guide >> Headings.
...
Warning | ||
---|---|---|
| ||
This segment an example of overusing headings. This whole "Headings" section has suo so few paragraphs that it really should have been written in just one section. The "advantages" and "disadvantages" would be just as easy to render as a table. |
...
Tip | ||
---|---|---|
| ||
If you find yourself writting too many |
General Punctuation and Grammar
Good online resources for punctuation, grammar, and text style include
In print, two excellent (and inexpensive!) resources are
...
More on Text Effects
This section refers to: Notation Guide >> Text Effects.
...
Always observe copyright issues. Do not annex images unless it an orginal or public domain work, or the author has donated the image to the foundation.
Example:
Icons
Use , , , and to bullet important one-liners. Use to highlight cross references.
Used carefully, icons such as , , or can make the content easier to read and understand.
...
Code Block | ||
---|---|---|
| ||
$ javac HelloWorld.java
$ java HelloWorld
Hello, World!
|
Change Happens
Anyone who has worked with databases knows the value of normalizing the schema. Ideally, we want to store each fact exactly once, and then use query system to retrieve that fact whereever it is needed. If we store a fact once, we only need to update it once, and we avoid inconsistencies in our data set.
To the extent possible, we want to "normalize" our technical documentation. Like a database, all technical documentation is subject to change. When change happens, we want the documentation to be as easy to update as possible. One way to do that is to try and minimize redudency (without sacrificing ease of use).
Single sourcing with snippets
The "holy grail" of technical documentation is single sourcing. One way we try to single-source documentation is to pull content directly from the Javadocs and source code into the documentation.
Using a snippet macro, we are able to tag portions of the Javadocs and source code for reuse. The macro fetches those snippets from the repository and merges the conntent into the documentation.
Tip | ||
---|---|---|
| ||
Before writing any new content, ask yourself if we could place the content in the repository in either one of the example applications or the Javadocs. Rather than contrive an example, can you pull a snippet from one of the applications? Rather than reiterate Javadoc, could we update the Javadoc and make it a snippet? |
Here are some examples of the snippet macro in action:
{snippet:id=description|javadoc=true|url=com.opensymphony.xwork.interceptor.LoggingInterceptor}
or
{snippet:id=example|javadoc=true|lang=xml|url=com.opensymphony.xwork.interceptor.LoggingInterceptor}
or
{snippet:id=sitegraph-usage|lang=none|url=webwork/src/java/com/opensymphony/webwork/sitegraph/sitegraph-usage.txt}
or
{snippet:id=ajax-validation-example|lang=xml|url=webwork/webapps/ajax/src/webapp/lesson1/example.jsp}
Legend:
id | The name of the snippet (required). |
---|---|
url | The URL where the snippet can be found (required). |
lang | The language that the code block. If this snippet is simply text, don't include this parameter and the content will be printed outside of a code block. |
javadoc | If true, the content is within a Javadoc block. If this is set to true, then the preceeding "* " (asterisk-space) characters will be stripped before merging the content. Also, the content is assumed to be already HTML escaped and won't be escaped again. |
All snippets are marked off by the pattern START SNIPPET: XXX
and END SNIPPET: XXX
where XXX
is the name
of the snippet that is assigned in the id
attribute of the macro. The URL is typically a location that points to the project's source control contents.
About URLs
As you probably noticed in the examples, there are several formats for URL patterns. A fully-qualified URL is always allowed, though that is often not practical. We've customized the macro to be a bit more intelligent with the URL attribute.
- If the URL appears to be a class, we assume it lives in
src/java
, convert all the dots to slashes, and then append.java
to it. - If the URL doesn't start with "http", then it is assumed to start with _https://opensymphony.dev.java.net/source/browse/*checkout*/_, as you saw in the third example.
About snippet markers
When possible, all snippet markers should be in comment blocks. How they are commented depends on where the snippet is being embedded.
Code Block | ||||
---|---|---|---|---|
| ||||
<!-- START SNIPPET: xxx --> ... <!-- END SNIPPET: xxx --> |
Code Block | ||||
---|---|---|---|---|
| ||||
if (true != false) {
// START SNIPPET: xxx
System.out.println("This is some silly code!");
// END SNIPPET: xxx
}
|
If the snippet is embedded in Javadocs, use HTML comments as they won't render in the Javadocs. For XML examples in Javadocs can be tricky. (See Timer Interceptor for an example.). Javadocs want to use the <pre>
tag, but you don't want that tag in the snipped content.
One technique is to embed the snippet markers inside the <pre>
tag.
Code Block | ||||
---|---|---|---|---|
| ||||
* <pre>
* <!-- START SNIPPET: example -->
* <!-- records only the action's execution time -->
* <action name="someAction" class="com.examples.SomeAction">
* <interceptor-ref name="completeStack"/>
* <interceptor-ref name="timer"/>
* <result name="success">good_result.ftl</result>
* </action>
* <!-- END SNIPPET: example -->
|