Documenting our Application in Apache Struts 2 (part 1)

Exclusive offer: get 50% off this eBook here
Apache Struts 2 Web Application Development

Apache Struts 2 Web Application Development — Save 50%

A beginner’s guide for Java developers

$20.99    $10.50
by Dave Newton | June 2009 | Open Source

In this two-part article series by Dave Newton, we'll look at the ways in which we can document our applications, coding styles that can aid in understanding, tools and techniques for creating documentation from application artifacts, different types of documentation for different parties, and so on.

This part of the article deals with ways to document Javacode and how to self-document our code.

Documenting Java

Everybody knows the basics of documenting Java, so we won't go into much detail. We'll talk a bit about ways of writing code whose intention is clear, mention some Javadoc tricks we can use, and highlight some tools that can help keep our code clean. Clean code is one of the most important ways we can document our application. Anything we can do to increase readability will reduce confusion later (including our own).

Self-documenting code

We've all heard the myth of self-documenting code. In theory, code is always clear enough to be easily understood. In reality, this isn't always the case. However, we should try to write code that is as self-documenting as possible.

Keeping non-code artifacts in sync with the actual code is difficult. The only artifact that survives a project is the executable, which is created from code, not comments. This is one of the reasons for writing self-documenting code. (Annotations, XDoclet, and so on, make that somewhat less true.)

There are little things we can do throughout our code to make our code read as much like our intent as possible and make extraneous comments just that: extraneous.

Document why, not what

Over-commenting wastes everybody's time. Time is wasted in writing a comment, reading it, keeping that comment in sync with the code, and, most importantly, a lot of time is wasted when a comment is not accurate.

Ever seen this?

a += 1; // increment a

This is the most useless comment in the world.

Firstly, it's really obvious we're incrementing something, regardless of what that something is. If the person reading our code doesn't know what += is, then we have more serious problems than them not knowing that we're incrementing, say, an array index.

Secondly, if a is an array index, we should probably use either a more common array index or make it obvious that it's an array index. Using i and j is common for array indices, while idx or index is less common. It may make sense to be very explicit in variable naming under some circumstances. Generally, it's nice to avoid names such as indexOfOuterArrayOfFoobars. However, with a large loop body it might make sense to use something such as num or currentIndex, depending on the circumstances.

With Java 1.5 and its support for collection iteration, it's often possible to do away with the index altogether, but not always.

Make your code read like the problem

Buzzphrases like Domain Specific Languages (DSLs) and Fluent Interfaces are often heard when discussing how to make our code look like our problem. We don't necessarily hear about them as much in the Java world because other languages support their creation in more "literate" ways. The recent interest in Ruby, Groovy, Scala, and other dynamic languages have brought the concept back into the mainstream.

A DSL, in essence, is a computer language targeted at a very specific problem. Java is an example of a general-purpose language. YACC and regular expressions are examples of DSLs that are targeted at creating parsers and recognizing strings of interest respectively.

DSLs may be external, where the implementing language processes the DSL appropriately, as well as internal, where the DSL is written in the implementing language itself. An internal DSL can also be thought of as an API or library, but one that reads more like a "little language".

Fluent interfaces are slightly more difficult to define, but can be thought of as an internal DSL that "flows" when read aloud. This is a very informal definition, but will work for our purposes

Java can actually be downright hostile to some common DSL and fluent techniques for various reasons, including the expectations of the JavaBean specification. However, it's still possible to use some of the techniques to good effect. One typical practice of fluent API techniques is simply returning the object instance in object methods. For example, following the JavaBean specification, an object will have a setter for the object's properties. For example, a User class might include the following:

public class User {
private String fname;
private String lname;
public void setFname(String fname) { this.fname = fname; }
public void setLname(String lname) { this.lname = lname; }
}

Using the class is as simple as we'd expect it to be:

User u = new User();
u.setFname("James");
u.setLname("Gosling");

Naturally, we might also supply a constructor that accepts the same parameters. However, it's easy to think of a class that has many properties making a full constructor impractical. It also seems like the code is a bit wordy, but we're used to this in Java. Another way of creating the same functionality is to include setter methods that return the current instance. If we want to maintain JavaBean compatibility, and there are reasons to do so, we would still need to include normal setters, but can still include "fluent" setters as shown here:

public User fname(String fname) {
this.fname = fname;
return this;
}
public User lname(String lname) {
this.lname = lname;
return this;
}

This creates (what some people believe is) more readable code. It's certainly shorter:

User u = new User().fname("James").lname("Gosling");

There is one potential "gotcha" with this technique. Moving initialization into methods has the potential to create an object in an invalid state. Depending on the object this may not always be a usable solution for object initialization.

Users of Hibernate will recognize the "fluent" style, where method chaining is used to create criteria. Joshua Flanagan wrote a fluent regular expression interface, turning regular expressions (already a domain-specific language) into a series of chained method calls:

Regex socialSecurityNumberCheck =
new Regex(Pattern.With.AtBeginning
.Digit.Repeat.Exactly(3)
.Literal("-").Repeat.Optional
.Digit.Repeat.Exactly(2)
.Literal("-").Repeat.Optional
.Digit.Repeat.Exactly(4)
.AtEnd);

Whether or not this particular usage is an improvement is debatable, but it's certainly easier to read for the non-regex folks.

Ultimately, the use of fluent interfaces can increase readability (by quite a bit in most cases), may introduce some extra work (or completely duplicate work, like in the case of setters, but code generation and/or IDE support can help mitigate that), and may occasionally be more verbose (but with the benefit of enhanced clarity and IDE completion support).

Contract-oriented programming

Aspect-oriented programming (AOP) is a way of encapsulating cross-cutting functionality outside of the mainline code. That's a mouthful, but essentially it means is that we can remove common code that is found across our application and consolidate it in one place. The canonical examples are logging and transactions, but AOP can be used in other ways as well.

Design by Contract (DbC) is a software methodology that states our interfaces should define and enforce precise specifications regarding operation.

"Design by Contract" is a registered trademark of Interactive Software Engineering Inc. Other terms include Programming by Contract (PbC) or Contract Oriented Programming (COP).

How does COP help create self-documenting code? Consider the following portion of a stack implementation:

public void push(final Object o) {
stack.add(o);
}

What happens if we attempt to push a null? Let's assume that for this implementation, we don't want to allow pushing a null onto the stack.

/**
* Pushes non-null objects on to stack.
*/
public void push(final Object o) {
if (o == null) return;
stack.add(o);
}

Once again, this is simple enough. We'll add the comment to the Javadocs stating that null objects will not be pushed (and that the call will fail/return silently). This will become the "contract" of the push method—captured in code and documented in Javadocs.

The contract is specified twice—once in the code (the ultimate arbiter) and again in the documentation. However, the user of the class does not have proof that the underlying implementation actually honors that contract. There's no guarantee that if we pass in a null, it will return silently without pushing anything.

The implied contract can change. We might decide to allow pushing nulls. We might throw an IllegalArgumentException or a NullPointerException on a null argument. We're not required to add a throwsclause to the method declaration when throwing runtime exceptions. This means further information may be lost in both the code and the documentation.

Eiffel has language-level support for COP with the require/do/ensure/end construct. It goes beyond the simple null check in the above code. It actively encourages detailed pre- and post-condition contracts. An implementation's push() method might check the remaining stack capacity before pushing. It might throw exceptions for specific conditions. In pseudo-Eiffel, we'd represent the push() method in the following way:

push (o: Object)
require
o /= null
do
-- push
end

A stack also has an implied contract. We assume (sometimes naively) that once we call the push method, the stack will contain whatever we pushed. The size of the stack will have increased by one, or whatever other conditions our stack implementation requires.

Java, of course, doesn't have built-in contracts. However, it does contain a mechanism that can be used to get some of the benefits for a conceptually-simple price. The mechanism is not as complete, or as integrated, as Eiffel's version. However, it removes contract enforcement from the mainline code, and provides a way for both sides of the software to specify, accept, and document the contracts themselves.

Removing the contract information from the mainline code keeps the implementation clean and makes the implementation code easier to understand. Having programmatic access to the contract means that the contract could be documented automatically rather than having to maintain a disconnected chunk of Javadoc.

SpringContracts

SpringContracts is a beta-level Java COP implementation based on Spring's AOP facilities, using annotations to state pre- and post-contract conditions. It formalizes the nature of a contract, which can ease development.

Let's consider our VowelDecider that was developed through TDD. We can also use COP to express its contract (particularly the entry condition). This is a method that doesn't alter state, so post conditions don't apply here.

Our implementation of VowelDecider ended up looking (more or less) like this:

public boolean decide(final Object o) throws Exception {
if ((o == null) || (!(o instanceof String))) {
throw new IllegalArgumentException(
"Argument must be a non-null String.");
}
String s = (String) o;
return s.matches(".*[aeiouy]+.*");
}

Once we remove the original contract enforcement code, which was mixed with the mainline code, our SpringContracts @Precondition annotation looks like the following:

@Precondition(condition="arg1 != null && arg1.class.name == 'java.
lang.String'",
message="Argument must be a non-null String")
public boolean decide(Object o) throws Exception {
String s = (String) o;
return s.matches(".*[aeiouy]+.*");
}

The pre-condition is that the argument must not be null and must be (precisely) a string. (Because of SpringContracts' Expression Language, we can't just say instanceof String in case we want to allow string subclasses.)

We can unit-test this class in the same way we tested the TDD version. In fact, we can copy the tests directly. Running them should trigger test failures on the null and non-string argument tests, as we originally expected an IllegalArgumentException. We'll now get a contract violation exception from SpringContracts.

One difference here is that we need to initialize the Spring context in our test. One way to do this is with JUnit's @BeforeClass annotation, along with a method that loads the Spring configuration file from the classpath and instantiates the decider as a Spring bean. Our class setup now looks like this:

@BeforeClass public static void setup() {
appContext = new ClassPathXmlApplicationContext(
"/com/packt/s2wad/applicationContext.xml");
decider = (VowelDecider)
appContext.getBean("vowelDecider");
}

We also need to configure SpringContracts in our Spring configuration file. Those unfamiliar with Spring's (or AspectJ's) AOP will be a bit confused. However, in the end, it's reasonably straightforward, with a potential "gotcha" regarding how Spring does proxying.

<aop:aspectj-autoproxy proxy-target-class="true"/>
<aop:config>
<aop:aspect ref="contractValidationAspect">
<aop:pointcut id="contractValidatingMethods"
expression="execution(*
com.packt.s2wad.example.CopVowelDecider.*(..))"/>
<aop:around pointcut-ref="contractValidatingMethods"
method="validateMethodCall"/>
</aop:aspect>
</aop:config>
<bean id="contractValidationAspect"
class="org.springcontracts.dbc.interceptor.
ContractValidationInterceptor"/>
<bean id="vowelDecider"
class="com.packt.s2wad.example.CopVowelDecider" />

The SpringContracts documentation goes into it a bit more and the Spring documentation contains a wealth of information regarding how AOP works in Spring. The main difference between this and the simplest AOP setup is that our autoproxy target must be a class, which requires CGLib. This could also potentially affect operation.

The only other modification is to change the exception we're expecting to SpringContract's ContractViolationCollectionException, and our test starts passing. These pre- and post-condition annotations use the @Documented meta-annotation, so the SpringContracts COP annotations will appear in the Javadocs. It would also be possible to use various other means to extract and document contract information.

Getting into details

This mechanism, or its implementation, may not be a good fit for every situation. Runtime performance is a potential issue. As it's just some Spring magic, it can be turned off by a simple configuration change. However, if we do, we'll lose the value of the on-all-the-time contract management.

On the other hand, under certain circumstances, it may be enough to say that once the contracts are consistently honored under all of the test conditions, the system is correct enough to run without them. This view holds the contracts more as an acceptance test, rather than as run-time checking. Indeed, there is an overlap between COP and unit testing as the way to keep code honest. As unit tests aren't run all the time, it may be reasonable to use COP as a temporary runtime unit test or acceptance test.

Apache Struts 2 Web Application Development A beginner’s guide for Java developers
Published: June 2009
eBook Price: $20.99
Book Price: $34.99
See more
Select your format and quantity:

Javadocs

We'll cover only a few things regarding Javadocs. We're all very familiar with them, but there are a few tips that might be helpful occasionally.

Always write Javadocs!

The first bit of advice is to always write Javadocs, except when they're not really needed. Getters and setters that have no additional functionality really don't need them. However, as soon as a getter or setter does more than just get or set its value, it may deserve documentation. Even minor functionality that's trivial to understand when looking at the code may deserve Javadocs. We may not have access to the source or we may only want to look at the API documentation.

The first sentence

The first sentence of a Javadoc comment is used as the summary documentation. It isn't necessary to encapsulate every nuance of the member being documented in the first sentence, but it's important to give a very clear and concise overview of the member. By default, the first sentence is everything up to the first "." (period). Some tools will complain if the first sentence is not properly terminated.

The proper way to describe the grammar of the first sentence is something along the lines of: "use a verb phrase in the third person declarative form." What does that mean in real life?

/**
* Builds and returns the current list of ingredients.
*
* @return List of ingredients.
*/
public List<Ingredient> buildIngredientList() { ... }

In the case of methods, the Javadoc summary should answer the question: "What does this member do?" One answer could be: "buildIngredientList() builds and returns the list of ingredients." This is opposed to saying something such as "Build and return list of ingredients", which doesn't work as an answer to the question. This is the "verb phrase" part.

The "third person declarative" part (informally) means that we answer the question as directly as possible. Sentence fragments are okay here. Additional exposition harms clarity. For example, we probably would not want to write the following:

/**
* This method builds and returns the current list
* of ingredients.
*/

That's not a direct answer to the question "What does buildIngredientList() do?". Therefore, this probably is not the best style of documentation.

This method is simple enough. Therefore, we may not need the @return Javadoc tag. What it returns is already specified in the first sentence. However, some tools may complain about missing Javadoc tags.

For variables, a simple descriptive sentence such as the following is usually fine:

/** Pre-built recipe summary. */
private String summary;

Is it okay to have member variables without Javadocs? The answer is yes, if the purpose is self-evident from the name. However, if our build process includes a tool that enforces Javadoc requirements, we'll either get irritating warnings or we'll need to specify what to exclude from checking.

If there aren't any Javadoc requirements, then all bets are off. However, bear in mind that Javadocs are also used by the IDE to provide information in various forms such as roll-over Javadoc pop-ups. It often boils down to whether or not we are able to come up with a good variable or method name. If we can, then the benefits of essentially repeating the same information in a Javadoc comment are very low and are probably not worth it.

Add information beyond the API name

In our buildIngredientList() example seen earlier, our first sentence really doesn't tell us much more than the name of the method does. This is good because it means that our method name (the API name) is probably correct and sufficient. However, let's assume that the method actually does something interesting during the construction of the ingredient list. That information should then be added to the Javadocs.

The information does not (necessarily) belong in the summary. Therefore, we can simply continue with another sentence (this is a bit contrived, since it could be merged into the first sentence quite easily).

/**
* Builds and returns the current list of ingredients.
* Initializes ingredient information if necessary.
*/

The summary information will consist of only the first sentence, but both sentences will be in the complete Javadocs. Note that in this case, it might make more sense to use a single sentence similar to the following:

/**
* Builds and returns the current list of ingredients,
* initializing ingredient info when necessary.
*/

The trick is to consistently make good decisions regarding what the most essential information is, and communicating it cleanly and concisely.

Write for multiple formats

Javadocs should be written with the thought that they might be read in several formats. Some common ways of viewing Javadocs include embedded in source code, using an IDE or an IDE popup/hover, the results of a grep, and so on. They may also be viewed as HTML, such as after they've been processed with the Javadoc tool. Javadoc comments may even be included in a wiki, through some sort of snippet mechanism or by including it in various forms of documentation.

In our example above, we have two sentences in a row. Let's say that we need to highlight the fact that the ingredient information will be initialized if necessary. Our first attempt just adds a bold Note to the second sentence.

/**
* Builds and returns the current list of ingredients.
*
* <b>Note:</b> Initializes ingredient information if
* necessary.
*/

The word Note: will stand out in the HTML output, but will appear connected to the opening sentence. Javadoc doesn't honor text-based line breaks. We must use HTML to format our Javadocs. Creating separate paragraphs requires the use of paragraph tags.

By formatting our Javadoc as indented HTML, we can create documentation that reads reasonably well in both text and HTML formats. Additionally, with judicious use of HTML tags, we can use doclets that create printable PDF documentation (or other printable formats).

/**
* Builds and returns the current list of ingredients.
*
* <p>
* <b>Note:</b> Initializes ingredient information
* if necessary.
* </p>
*/

Generating targeted Javadocs

One reason people give for not writing Javadocs for a particular method is that the method isn't necessarily designed to be used by others, or that exposing even the documentation isn't a good idea. The Javadoc tool gives us a few ways to restrict what documentation is generated.

Visibility

The most obvious way to restrict what documentation is generated is based on visibility. By default, Javadoc will generate documentation for all of the public and protected classes. By using the -public, -protected, -package, and -private flags, we can control the level of visibility for which documentation will be generated. Note that we need to specify only one flag—any member with equal or greater visibility will have documentation generated for it.

For example, running Javadoc with the -public flag will generate documentation for only public members, creating Javadocs suitable for the users of an API. Running with the -private flag will generate documentation for all of the members, making the documentation suitable for the developers of the same API.

The -exclude argument

The -exclude argument allows us to supply package names that will be excluded from Javadoc generation. For example, if we want to create documentation that specifically excludes an "internal-use only" package (security through obscurity?), we can use the -exclude argument to provide a ":" (colon) separated list of packages for which no Javadocs will be generated.

javadoc -exclude com.packt.s2wad.internal {...}

No classes in the com.packt.s2wad.internal package will be documented.

The -use argument

The -use argument will generate a "Use" page for each class C being documented. The "Use" page will contain an entry for each package, class, method, and fields "using" class C. Uses include subclasses, methods that use the class as a parameter, and methods that return an instance of the class.

This page may not be as useful as a graphical representation of the class interdependencies, but it's an option that's available out of the box. Creating various diagrams is possible with add-on Javadoc doclets such as yDoc or UmlGraph, as well as with non-Javadoc-oriented tools.

Creating new Javadoc tags with the -tag argument

One Javadoc capability that's trivial to take advantage of is creating our own Javadoc tags. These tags are similar to the @param and @return tags that Javadoc recognizes by default. This capability may or may not fit into your organization or coding style, but it's simple enough to use that it's worth an introduction. Another potential issue is that our IDE or build process probably won't be capable of validating the information contained in the tag, unlike the default tags. For example, Eclipse can flag a warning if a method's parameters don't have corresponding @param tags.

We could document an action that puts a variable into session by creating a @session Javadoc tag. By telling the Javadoc tool to pay attention to that tag, we can create output for it just like the built-in @param tag. An action's Javadocs might look like this:

/**
* Retrieves recipe, creating session parameters as needed.
*
* @session CONSTANTS.LAST_RECIPE The last recipe accessed.
*
* @returns SUCCESS or ERROR if retrieval fails.
*/

We instruct the javadoc tool to pay attention to our new tag by giving it -tag arguments. The easiest method is to just add -tag session to the javadoc command. How this is done depends on your build environment. It can be done using an Ant script, via an IDE javadoc frontend, and so on.

Adding the -tag session argument instructs javadoc to create output for @session tags similar to @param and @returns tags. The generated output will appear after the standard tags. If we want to change the order in the HTML we must supply a complete list of -tag arguments including the built-in tags as well. Each tag's output is generated in the order specified on the command line. If we wanted to see the @session documentation before the @return tag's documentation, then we'd specify both documentations on the command line as follows:

-tag session -tag return

We can also specify the header for a custom Javadoc tag. To set a header for the session tag we use colon-separated values (ignoring the a for now):

-tag session:a:"Session attributes accessed:"

The "a" we snuck in there determines where in the source code we can use the tag, with "a" meaning anywhere we want. A complete list of determinants is found in the javadoc tool documentation, but includes "t" for types (classes and interfaces), "m" for methods, "f" for fields, and so on. These may be combined, so a tag to identify injected entities for both types and fields could be specified as follows:

-tag injected:tf:"Injected entities:"

If we now try to use our new @injected tag in a method declaration, the Javadoc tool will signal an error, as it's been specified as being valid only for types and fields.

Note that this functionality of javadoc may overlap some use of annotations. For example, assume we're using an interceptor that loads and saves an annotated variable from and to the JEE session. It would make more sense to use a doclet that included this information from the annotation, rather than writing (and worse, maintaining) the Javadoc manually—the more we can do automatically, the better.

Never write Javadocs!

There are many cases where it makes sense to write detailed Javadocs, describing a complicated or non-obvious algorithm being chief among them. However, it's arguable whether such documentation belongs in the application's non-code documentation or in a wiki.

Never write inline Java comments!

If we find ourselves writing chunks of comments inside methods to explain each section of a method, we might be better off refactoring the chunk into its own method. Of course, some code lends itself to this more readily than others, which might be impractical for a variety of reasons. There's always a trade-off. However, there is always a cost associated with non-code documentation, as it is ultimately maintained separately from the code itself.

Using UML

UML (Unified Markup Language) can handle a wide range of documentation duties, much more than will be covered here. Even UML-like diagrams can be of great assistance in many aspects of documentation. It's not necessary to follow all of the UML notation or diagrams completely, purchase an expensive enterprise UML tool, and so on. However, a basic understanding of UML is very handy when documenting our own application, or reading the documentation of other projects that use UML.

There are many ways to integrate UML into the development and documentation process. It might be used to generate source code, it can be included in both developer and end-user documentation (where appropriate), and so on. Two of the more common UML diagrams related directly to Java code are the package and class diagrams, which most of us are already familiar with.

Package diagrams

Package diagrams are similar to class diagrams, but provide a very high-level overview of an application's package and package dependencies.

Class diagrams

One of the most useful and commonplace UML diagrams is probably the class diagram. The class diagram is used to show the relationship between different classes in a system. Class diagrams can be created at various levels of detail to provide very high-level overviews or extremely detailed information, including all of a class's properties.

For example, a portion of our com.packt.s2wad.recipe package's class diagram can be represented by the following UML class diagram. Note that this is an incomplete diagram and doesn't show our implementation of RecipeService. It's also fairly high-level, and doesn't show any class properties or methods.

However, it's still useful because it's obvious that we have two classes that use a RecipeService, and two classes that have a relationship to the Recipe class. This type of high-level overview is particularly important when first learning an application, identifying high-level class-coupling issues, and so on.

Apache Struts 2 Web Application Development

A class diagram for an entire application can be a bit overwhelming, and isn't always useful due to the sheer amount of information. Restricting what is visible at both the class and package level can be very useful allowing usable documentation to be generated.

The previous image was generated with ArgoUML, an open source UML tool from application source. It was then edited by hand to improve the layout, to remove class members and operations, and so on.

Java source can also be generated from UML models. Several IDEs and modeling tools supply this functionality. The direction of generation, whether generating UML from source or source from UML, is largely a matter of preference, culture, and how well the available tools work for our style (or the style of our client).

Sequence diagrams

Another popular and useful UML diagram, which is relatively lightweight, is the sequence diagram. These diagrams are used to document interactions between entities. These entities are normally classes. However, it's not unreasonable to extend the sequence diagram metaphor beyond the official definition when necessary, such as adding user interactions, browser functionality, and so on.

As a quick example, we can take a look at the typical Struts 2 form validation processing sequence, compressing the non-related interceptors into a single entity:

Apache Struts 2 Web Application Development

Here, we're representing the user action of submitting a form in the sequence diagram. This (in simplified form) causes the Struts 2 filter to instantiate the appropriate action class, indicated by the new() message. The rest is largely self-explanatory.

Sequence diagrams are often easier to comprehend than plain text and can be more convenient than the code itself, as they aggregate as many classes as needed. As usual, they can suffer from decay, as the code continues to be modified and the diagrams aren't being generated automatically or being actively maintained.

This diagram was created using the Quick Sequence Diagram Editor, which creates an exportable diagram using simple text-based input. The input for this diagram is relatively short.

#![Struts 2 Validation Processing]
user:Actor "User"
s2f: "Struts 2 Filter"
etc: "Interceptors..."
val: "Validation Interceptor"
workflow: "Workflow Interceptor"
/action: "An Action"
user:s2f.Submit form
s2f:action.new()
s2f:Result=etc.Invoke
etc:Result=val.Invoke
val:action.validate()
[c:cond Validation errors]
val:INPUT result=workflow.Invoke
--[No validation errors]
val:Action result=workflow.Invoke
workflow:Action result=action.Invoke
[/c]
s2f:user.Rendered Result

It's pretty easy to create our own DSL (for example, in Ruby) that corrects this error. It's also relatively straightforward to create a log format that could be parsed to create diagrams from actual code. Therefore, running unit tests could also be a part of the documentation process.

Summary

This part of the article started with the basics of how to document Java applications. It then moved on to self-documenting code, the use of Contract-oriented programming in documenting applications, and ways of generating targeted Javadocs. The next part of the article will focus on documenting web applications.

 


If you have read this article you may be interested to view :


Apache Struts 2 Web Application Development A beginner’s guide for Java developers
Published: June 2009
eBook Price: $20.99
Book Price: $34.99
See more
Select your format and quantity:

About the Author :


Dave Newton

Dave Newton, a Struts PMC member, has been a professional developer for over twenty years, getting his start in Lisp and Smalltalk development, moving on to a lengthy stint in embedded system, game, and device driver development, before (confusingly) finding himself writing Java-based web applications for a variety of clients.

He is a strong proponent of agile practices and tool creation and use, particularly in relationship to documentation generation and testing. He's a regular (if crabby) fixture on the Struts user mailing list, prodding people to read the documentation and think outside the box.

Contact Dave Newton

Books From Packt


Pentaho Reporting 1.0 for Java Developers
Pentaho Reporting 1.0 for Java Developers

Seam 2.x Web Development
Seam 2.x Web Development

Magento: Beginner's Guide
Magento: Beginner's Guide

Liferay Portal 5.2 Systems Development
Liferay Portal 5.2 Systems Development

Flash with Drupal
Flash with Drupal

DWR Java AJAX Applications
DWR Java AJAX Applications

JBoss Tools 3 Developers Guide
JBoss Tools 3 Developers Guide

eZ Publish 4: Enterprise Web Sites Step-by-Step
eZ Publish 4: Enterprise Web Sites Step-by-Step

 


No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
F
E
e
w
E
B
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software