You are on page 1of 23

Code Maintenance:

Specification Standards for Class Design


Specification Standards for Class Design

• 4 suggested standards which taken together can make


your code:

• readable

• maintainable

• robust

• and can help you with the code design


1. Use Full Javadoc Standards in Code Comments

• javadoc can automatically generate API documentation from


documentation comments within your code

• you can add special comments to your code delimited by /** … */

• those comments are processed by the javadoc tool to generate


the API docs

• can access javadoc program from command line or within


Eclipse

• the comments should contain 2 parts, in order:

• description

• block tags
Example
/**
* Returns an Image object that can then be painted on the screen.
* The url argument must specify an absolute {@link URL}. The name
* argument is a specifier that is relative to the url argument.
getImage
* <p> public Image getImage(URL url,
description * This method always returns immediately, whether or not the String name)
Returns an Image object that can then be painted on the
* image exists. When this applet attempts to draw the image on
screen. The url argument must specify an absolute URL. The
* the screen, the data will be loaded. The graphics primitives name argument is a specifier that is relative to the url
* that draw the image will incrementally paint on the screen. argument.

* This method always returns immediately, whether or not the


image exists. When this applet attempts to draw the image on
* @param url an absolute URL giving the base location of the image
the screen, the data will be loaded. The graphics primitives that
* @param name the location of the image, relative to the url argument draw the image will incrementally paint on the screen.
block tags * @return the image at the specified URL
Parameters:
* @see Image url - an absolute URL giving the base location of the image.
name - the location of the image, relative to the url argument.
*/
Returns:
public Image getImage(URL url, String name) { the image at the specified URL.
try { See Also:
Image
return getImage(new URL(url, name));
} catch (MalformedURLException e) {
return null;
}
}

from http://www.oracle.com/technetwork/java/javase/documentation/index-137868.html
Quick Guide to Style

• can use phrases instead of complete sentences for brevity

• use 3rd rather than 2nd person:

• avoid 'get the label'

• prefer 'gets the label'

• begin method descriptions with a verb phrase:

• avoid 'this method gets the label of this button'

• prefer 'gets the label of this button'


Quick Guide to Style

• for class/interface/field descriptions omit the object and just state subject:

• avoid 'this field is a button label'

• prefer 'a button label'

• use this instead of the:

• avoid 'gets the id of the object'

• prefer 'gets the id of this object'

• avoid Latin:

• avoid 'i.e', 'e.g', 'viz'

• prefer 'to be specific', 'for example', 'in other words'


Quick Guide to the Block Tags

• most useful:

• @author classes and interfaces only

• @version classes and interfaces only

• @param methods & constructors only

• @return methods only

• @throws methods only


Quick Guide to the Block Tags

• @author not required but useful for teamwork

• @author jimmyNail

• @version of java for which this was written

• @version 1.6

• @param for each data type give the name (not type) and description

• @param height the height of the door, measured in


millimetres

• @return just like @param, can omit for constructors and void returns

• @throws include for checked exceptions (declared in the throws clause)

• @throws FileNotFoundException if the filename passed


cannot be resolved to a valid file path
2. Use Total Procedures in Class Design

• problem:

• often the legal set of inputs for a method is smaller than the
possible set of inputs that a client can pass to it

• for example: a squareRoot( double value) method requires


an input value ≥ 0

• solution:

• we can specify total procedures (or from now on methods)


which specify each type of valid and non-valid input and how
it is handled
@requires

• for each input parameter (@param) in the javadoc we can add a


@requires clause

• this specifies the validity of the input from the method's perspective

• for squareRoot():
@param value the number whose square root will be returned
@requires value ≥ 0

• this lets the reader know that they should not pass a negative value
to this method

• and we can go through every parameter of every method and


identify what the method requires as valid input
Minimising the use of @requires

• @requires tells us what the legal input is for a method, but it doesn't tell us what will
happen if illegal input is passed

• for example, if we attempt squareRoot( -1)

• it's also not part of javadoc

• so our aim is not to fill classes with lines of @requires specifications

• but instead to minimise the need for @requires in the first place

• "prevention is better than cure"

• we can minimise the need in 2 ways:

• use crafted types for the input parameters which are always valid

• for example, instead of squareRoot( double value)

• use squareRoot( PositiveNumber value)

• use or create exceptions to handle non-valid input...


Using Exceptions

• if the client tries to pass a negative value to squareRoot() then an


IllegalArgumentException will be generated

• problem:

• unless the client catches and handles this exception, the


program will crash

• solution:

• place the call to squareRoot() in a try-catch block:


try { squareRoot( value); }
catch ( IllegalArgumentException iaEx )
{ // appropriate reaction goes here }
Creating Exceptions

• problem:

• using a try-catch block to handle a generic exception


is better than not handing it

• but handling the exception is still optional

• if we are lazy or forget to code for it, then the


exception can still cause a crash

• solution:

• extend the generic exception with a tailored exception


Example: NegativeNumberException
public class NegativeNumberException extends IllegalArgumentException
{
public NegativeNumberException( double value)
{
super( value);
}
}

public double SquareRoot( double value) throws NegativeNumberException


{
if ( value < 0 ) { throw new NegativeNumberException( value); }
...
}

• we have replaced IllegalArgumentException with a new NegativeNumberException

• the exception is explicitly thrown by the squareRoot() method

• so the client code is forced to explicitly handle it


3. List all exceptions

• list in the method’s documentation comments

• specify using the @throws tag, one for each checked exception and its cause

• if:

• the method is a worker method (private), or

• the input which generates the exception is extremely unlikely

• then consider skipping this activity

• example:
/**
* @throws NegativeNumberException if value < 0
*/
public double squareRoot( double value) {
// method body
}
4. Use Exceptions rather than Special Return Values

• sometimes the method cannot provide a valid return for the given input

• for example:

• suppose an ArrayList<String> of names

• a getIndex(String name) method which returns the position in the list for a
given name

• "Claire" is not in the list

• a client might call getIndex( "Claire");

• it's tempting to add code to getIndex() to return a special value when this happens:

• if ( !list.contains( name) ) { return -1 };

• and then let the client handle this special return value

• we've probably all done something like that before


4. Use Exceptions rather than Special Return Values

• problems with using special values:

• the client has to know about the special value(s)

• the client must contain code for handling special values

• the client code for handling special value(s) might not be obvious
as such, unless we add lots of code comments

• a change to the special value(s) will break the client code

• solution:

• use a tailored exception and throw it instead of returning a special


value
Example: getIndex()
Before After
method: method:
public int getIndex( String name) public int getIndex( String name) throws
{ NameNotInListException
… {
if ( !list.contains( name) ) { return -1 }; ...
} if ( !list.contains( name) ) { throw new
NameNotInListException( String name) };
}

client: client:
int index = getIndex( name); try { int index = getIndex( name); }
if ( index == -1 ) catch ( NameNotInListException nnilEx )
{ // appropriate reaction goes here } { // appropriate reaction goes here }

• the method and client code will need code • the code is now largely self explanatory
comments to explain the special value and its handling • the handling of the exception is enforced
• the handling will not be enforced in the specification •now and in future
• might get forgotten in future re-use
Benefits of Standards

• creating full javadoc specification:

• makes you think carefully about where responsibilities should lie

• increases the likelihood of correct implementation of design

• increases maintainability

• specifying total methods and listing all exceptions:

• reduces the chance of runtime errors

• bad input is handled by design

• increases system reliability

• assists in testing and debugging

• thrown exceptions will state where they originated


Benefits of Standards

• avoiding Special Return Values:

• ensures the client takes appropriate action when a


valid return cannot be made

• increases reliability

• reduces the likelihood of runtime errors

• increases the likelihood of compilation errors

• but this is good, because to fix the errors we have


to make our code meet the specification
To conclude
• implementing these standards in full adds a lot of time
and effort to a build

• so it's not worth it for every project, every class or


every method

• but where:

• a method is likely to be broken by bad input, or

• client code is likely to be broken by a bad return

• then consider this approach


References & Further Reading
• total procedures, special values:

• Program Development in Java, Liskov & Guttag, Chapters


3 to 6

• javadoc:

• http://www.oracle.com/technetwork/java/javase/
documentation/index-137868.html

You might also like