Webcam Chat QuickBooks Advice international calling cards international phone cards
JavaBeat Java Books Certifications Certifications Kits Articles Tutorials Tips QNA Book Store Interview Questions SCJP 1.5 SCJP 1.6 SCWCD 5.0 SCBCD 5.0 SCEA SCJA Feeds

Documenting our Application

Author : PacktPub
Topic : java books 
Pages :
Submit Your Blog Feedback Request Article Print Email

Title : Documenting our Application
Publisher : PacktPub
Topic : java
Related : Hibernate, Spring, Struts, ejb
Javabeat : Tips, Java / J2EE Tutorials, Certifications

Apache Struts 2 Web Application Development

Struts 2.1 is a modern, extensible, agile web application framework, which is suitable for both small- and large-scale web applications.

The book begins with a comprehensive look at the basics of Struts 2.1, interspersed with detours into more advanced development topics. You'll learn about configuring Struts 2.1 actions, results, and interceptors via both XML and Java annotations. You'll get an introduction to most of the Struts 2.1 custom tags, and also learn how they can assist in rapid application prototyping and development.

From there, you'll make your way into Struts 2.1's strong support for form validation and type conversion, which allows you to treat your form values as domain objects without cluttering your code. A look at Struts 2.1's interceptors is the final piece of the Struts 2.1 puzzle, which allows you to leverage the standard Struts 2 interceptors, as well as implement your own custom behavior.

After covering Struts 2.1, you'll journey into the world of JavaScript (a surprisingly capable language), the Document Object Model (DOM), and CSS, and learn how to create clean and concise client-side behavior. You'll leverage that knowledge as you move on to Struts 2 themes and templates, which give you a powerful way to encapsulate site-wide user interface behavior.

The book closes with a look at some tools that make the application development life cycle easier to manage, particularly in a team environment, and more automatic.

What This Book Covers

Chapter 1 gives us a bird's-eye view of Struts 2 and examines some useful techniques of lightweight, agile development.

Chapter 2 gives an introduction to Struts 2 application configuration, using both XML and annotations. It also covers the beginning of our sample application, RecipeBox.

Chapter 3 covers some of the functionality provided by Struts 2's ActionSupport class, including I18N, and a first look at form validation. It also covers some basic RecipeBox functionality after gathering some user stories.

Chapter 4 examines several common, standard Struts 2 result types. It also covers how to write our own custom result types.

Chapter 5 gives an in-depth look at the generic Struts 2 custom tags. These include tags for iteration, list generation, conditionals, and internationalization (I18N).

Chapter 6 continues our exploration of Struts 2 custom tags, focusing especially on its form tags.

Chapter 7 examines Struts 2 form validation, including both XML and annotation-driven validation. It also teaches more about how Struts 2 converts our form values into domain objects, and shows how to create our own type converters to handle custom data types.

Chapter 8 finishes our comprehensive introduction to Struts 2, by checking out the included Struts 2 interceptors. It also discusses how to write and configure our own interceptors.

Chapter 9 looks at how to handle errors in Struts 2, as well as discusses error and exception handling in general. It also covers some general Java logging topics, focusing on using Apache Commons Logging and Log4J.

Chapter 10 explores how to best leverage JavaScript and how to keep it modular.

Chapter 11 covers the client-side functionality, which depends on more than JavaScript. By using CSS and the DOM effectively, we can accomplish a lot with a minimal amount of code.

Chapter 12 covers Struts 2 themes and templates. The themes and templates in Struts 2 allow for application-wide functionality on the client side, keeping our JSP pages lightweight and adaptable. Rather than writing boilerplate HTML on our pages, we can separate it into themes and templates.

Chapter 13 takes a look at some of Struts 2's built-in support for Ajax using the Dojo tags. It also covers the Struts 2 REST plug-in that furthers our "convention over configuration" path.

Chapter 14 covers how to apply the TDD concepts to several testing aspects, including unit, functional, and acceptance tests.

Chapter 15 looks at many aspects of documentation, including "self-documenting" code, Javadocs, generators, methodologies, and so on, with a focus on automating as much documentation as possible.

Documenting our Application

Every developer's favorite task is documenting their application (or so I've heard). As irritating as documentation can be, delivering a complete solution implies comprehensive, usable documentation. This goes beyond (but includes) typical Javadocs. However, more is required in order to understand how a particular application works, how its parts fit together, where dependencies lie, and so on. Even us, the developers, benefit from having a wide variety of documentation available.

In this chapter, 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.

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. (Well, annotations, XDoclet, and so on, make that somewhat less true. You know what I mean.)

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 "fl ows" 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 fl uent 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 fl uent 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 "fl uent" 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 "fl uent" style, where method chaining is used to create criteria. Joshua Flanagan wrote a fl uent 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 fl uent 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).

Personally, I'm of the opinion that regular expressions are so incredibly important that it's worth learning them in their native form, as they can be used in many environments, including the IDEs so loved by Java developers. Large expressions can be broken down into components and created by concatenating strings. But the point here is more about the style of fl uent programming, rather than this specific example.

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 my personal favorite, Contract Oriented Programming (COP), which
	is how I'll refer to it from now on. I have a lot of respect for Eiffel and its
	creator, but this type of trademarking bothers me. Maybe I'll trademark
	"Singleton"?!

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);
	}

This seems simple enough. The information available to us is that we can push an object, whatever pushing means.

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 throws clause to the method declaration when throwing runtime exceptions. This means further information may be lost in both the code and the documentation.

As hinted, 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.

One aim of COP is to formalize the nature of contracts. Languages such as Eiffel have one solution to that problem, and having it built-in at the language level provides a consistent means of expressing contracts.

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

If most of this seems like a mystery, that's fine. 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.

Submit Your Blog Feedback Request Article Print Email

Related Articles


JavaBeat Website (2004-2011), India
javabeat | advertise | about us | contact | useful resources
Copyright (2004 - 2011), JavaBeat


Technology Blogs
Technology blogs Technology Blogs
blog log