1. Introduction
The
major objective of this document is to provide standards and guidelines for
application developers and designers to develop systems that are maintainable,
testable, readable and adaptable to changes in the infrastructure. A
system depends on its maintenance instead of development, so it becomes
mandatory to write code clean and well packaged. Following are some importance
reasons to convey the coding standards during coding phase of project life
cycle…
1. 80% of
the lifetime cost of a piece of software goes to maintenance
2. Hardly
any software is maintained for its whole life by the original author.
3. Code
conventions improve the readability of the software, allowing engineers to
understand new code more quickly and thoroughly.
4. If you
ship your source code as a product, you need to make sure it is as well
packaged and clean as any other product you create.
This
white paper describes a collection of standards, conventions, and guidelines
for writing solid Java code. They are based on sound, proven software
engineering principles that lead to code that is easy to understand, to
maintain, and to enhance. Furthermore, by following these coding standards our
productivity as a Java developer should increase remarkably – Experience shows
that by taking the time to write high-quality code right from the start we will
have a much easier time modifying it during the development process. Finally,
following a common set of coding standards leads to greater consistency, making
teams of developers significantly more productive.
Coding
standards for Java are important because they lead to greater consistency
within our code and the code of our teammates. It increases code robustness. Greater consistency leads to
code that is easier to understand, which in turn means it is easier to develop
and to maintain. This reduces the overall cost of the applications that you
create.
We
have to remember that our Java code will exist for a long time, long after we
have moved on to other projects. An important goal during development is to
ensure that we can transition our work to another developer, or to another team
of developers, so that they can continue to maintain and enhance our work
without having to invest an unreasonable effort to understand our code. Code
that is difficult to understand runs the risk of being scrapped and rewritten –
We wouldn’t be proud of the fact that our code needed to be rewritten? If
everyone is doing their own thing then it makes it very difficult to share code
between developers, raising the cost of development and maintenance.
New
developers, and cowboys who do not know any better, will often fight having to
follow standards. They claim they can code faster if they do it their own way.
They MIGHT be able to get code out the door faster, but I doubt it. Cowboy
programmers get hung up during testing when several difficult-to-find bugs crop
up, and when their code needs to be enhanced it often leads to a major rewrite
by them because they’re the only ones who understand their code. Is this the
way that we want to operate? I think I certainly do not.
No
standard is perfect and no standard is applicable to all situations: sometimes we
find ourselves in a situation where one or more standards do not apply. This
leads me to introduce what I consider to be the prime directive of standards:
When we go against a standard, we
must document it. All standards, except for this
one, can be broken. If we do so, we must document why we broke the standard,
the potential implications of breaking the standard, and any conditions that
may/must occur before the standard can be applied to this situation.
The
bottom line is that we need to understand each standard, understand when to
apply them, and just as importantly when not to apply them.
Most
ordinary comments within Java code explain the implementation details of that
code. In contrast, the Java language specification defines a special type of
comment known as a doc comment that serves to document the API of your code. A
doc comment is an ordinary multiline comment that begins with /** (instead of the
usual /*) and ends with */. A doc comment appears immediately before a class,
interface, method, or field definition and contains documentation for that class,
interface, method, or field. The documentation can include simple HTML
formatting tags and other special keywords that provide additional information.
Doc comments are ignored by the compiler, but they can be extracted and
automatically turned into online HTML documentation by the javadoc
program.
We
ensure that our code should follow some basics facts about good documentations,
these basics facts are –
1.
Comments should add to the clarity
of the code.
2.
If the program isn’t worth documenting,
it probably isn’t worth running.
3.
Take care about comments - Avoid
decoration, i.e. do not use banner-like comments.
4.
Comments must be simple.
5.
Always prefer to write the
documentation before you write the code.
6.
Document why something is being done,
not just what.
Java
programs can have two kinds of comments: implementation comments and documentation
comments. Implementation comments are those found in C++, which are
delimited by /*...*/, and //. Documentation comments (known as "doc
comments") are Java-only, and are delimited by /**...*/. Doc comments can
be extracted to HTML files using the javadoc tool.
2.2.1 Implantation
Comment
Program can have
following type of implementation comments –
1.
Block
2.
Single
line
3.
Trailing
4.
End-of-line
2.2.1.1 Block
Comments:-
Block comments are used to provide
descriptions of files, methods, data structures and algorithms. Block comments
may be used at the beginning of each file and before each method. They can also
be used in other places, such as within methods. Block comments inside a
function or method should be indented to the same level as the code they
describe.
/*
* Here is a block comment.
*/
Block
comments can start with /*-, which is recognized by indent(1)
as the beginning of a block comment that should not be reformatted. Example:
/*-
* Here is a block comment with some very
special
* formatting that I want indent(1) to ignore.
*
* one
*
two
*
three
*/
Note: If we don't use indent(1), we don't have to use /*- in our code or make any other
concessions to the possibility that someone else might run indent(1) on
our code.
2.2.1.2 Single-Line
Comments:-
Short
comments can appear on a single line indented to the level of the code that
follows. If a comment can't be written in a single line, it should follow the
block comment format. A single-line comment should be preceded by a blank line.
Here's an example of a single-line comment in Java code:
if (condition) {
/* Handle the condition. */
...
}
2.2.1.3 Trailing
Comments:-
Very short comments can appear on
the same line as the code they describe, but should be shifted far enough to
separate them from the statements. If more than one short comment appears in a
chunk of code, they should all be indented to the same tab setting.
if (a == 2) {
return TRUE; /* special
case */
} else {
return isPrime(a); /* works only for odd a */
}
2.2.1.4 End-Of-Line Comments:-
The // comment
delimiter can comment out a complete line or only a partial line. It shouldn't
be used on consecutive multiple lines for text comments; however, it can be used
in consecutive multiple lines for commenting out sections of code. Examples of
all three styles follow:
if (foo > 1) {
// Do a double-flip.
...
}
else {
return false; // Explain
why here.
}
//if (bar > 1) {
//
//
// Do a triple-flip.
//
...
//}
//else {
//
return false;
//}
Doc comments describe Java classes,
interfaces, constructors, methods, and fields. Each doc comment is set inside
the comment delimiters /**...*/, with one comment per class,
interface, or member. This comment should appear just before the declaration:
/**
* The Example class provides ...
*/
public class Example { ...
Notice that top-level classes and
interfaces are not indented, while their members are. The first line of doc
comment (/**) for classes and interfaces is not indented; subsequent doc
comment lines each have 1 space of indentation (to vertically align the
asterisks). Members, including constructors, have 4 spaces for the first doc
comment line and 5 spaces thereafter.
If
you need to give information about a class, interface, variable, or method that
isn't appropriate for documentation, use an implementation block comment or
single-line comment immediately after the declaration. For example,
details about the implementation of a class should go in such an implementation
block comment following the class statement, not in the class doc
comment.
Doc comments should not be
positioned inside a method or constructor definition block, because Java
associates documentation comments with the first declaration after
the comment.
Included
in Sun’s Java Development Kit (JDK) is a program called javadoc that
processes Java code files and produces external documentation, in the form of
HTML files, for your Java programs. I think that javadoc is a great
utility, but at the time of this writing it does have its limitations. First,
it supports a limited number of tags, reserved words that mark the beginning of
a documentation section. The existing tags are a very good start but I feel are
not sufficient for adequately documenting your code. I’ll expand upon this
statement later. For now, I present a brief overview of the current javadoc tags
in the chart below, and will refer you to the JDK javadoc documentation
for further details.
Tag
|
Used for
|
Purpose
|
@author name
|
Interfaces,
Classes
|
Indicates the author(s) of a
given piece of code. One tag per author should be used.
|
@deprecated
|
Interfaces,
Classes,
Member Functions.
|
Indicates that the API for
class… has been deprecated and therefore should not be used any more.
|
@exception name description
|
Member Functions
|
Describe the exceptions that a
member function throws. We should use one tag per exception and give the full
class name for the exception.
|
@param name description
|
Member Functions
|
Used to describe a parameter
passed to a member function, including its type/class and its usage. Should
use one tag per parameter.
|
@return description
|
Member Functions
|
Describe the return value, if
any, of a member function. We should indicate the type/class and the
potential use(s) of the return value.
|
@since
|
Interfaces,
Classes,
Member Functions
|
Indicates how long the item
existed, i.e. since Java Development Kit (JDK) 1.1
|
@see ClassName
|
Interfaces,
Classes,
Member Functions, Fields
|
Generate a Hypertext link in
the documentation to the specified class. We can and probably should use a
fully qualified class name.
|
@see
ClassName#memberFunctionName
|
Interfaces,
Classes,
Member Functions, Fields
|
Generate a hypertext link in
the documentation to the specified member function. We can, and should
probably use a fully qualified class name.
|
@version text
|
Interfaces,
Classes
|
Indicates the version
information for a given piece of code.
|
The way that we
document our code has a huge impact both on our own productivity and on the
productivity of everyone else that later maintains and enhances it. By
documenting our code early in the development process we become more productive
because it forces we to think through our logic before we commit it to code.
Furthermore, when we revisit code that we wrote days or weeks earlier we can
easily determine what we were thinking when we wrote it – it is documented for
we already.
I’m
a firm believer in maximizing the productivity of systems professionals.
Because I also recognize that an application spends the majority of its
existence being maintained, not developed, I am very interested in anything
that can help to make my code easier to maintain and to enhance, as well as to
develop. Never forget that the code that we write today may still be in use
many years from now and will likely be maintained and enhanced by somebody
other than I. We must strive to make our code as “clean” and understandable as
possible, because these factors make it easier to maintain and to enhance. We
will understand naming convention step-by-step in following pattern (this is
not mandatory for all sub-heading) …
v Naming
conventions
v Visibility
v Documentation
conventions
v Techniques
for writing clean Java code
Member
Functions should be named using a full English description, using mixed case
with the first letter of any non-initial word capitalized. It is good practice
to name a method according to its work. It is also common practice for the
first word of a member function name to be a strong, active verb. For instance
Ø openMail();
Ø closeMail();
Ø saveMail();
Ø deleteMail();
This
convention results in member functions whose purpose can often be determined
just by looking at its name. Although this convention results in a little extra
typing by the developer, because it often results in longer names, this is more
than made up for by the increased understandability of our code.
We will discuss
accessors, member functions that get and set the values of fields
(fields/properties). The naming conventions for accessors, however, are
summarized below.
3.1.1.1 Getter:-
Getters
are member functions that return the value of a field. We should prefix the
word ‘get’ to the name of the field, unless it is a boolean field and then we
prefix ‘is’ to the name of the field instead of ‘get.’ For Example –
Ø getFirstName();
Ø getAccountNumber();
Ø isPersistent();
By
following this naming convention we make it obvious that a member function
returns a field of an object, and for boolean getters we make it obvious that
it returns true or false. Another advantage of this standard is that it follows
the naming conventions used by the beans development kit (BDK) for getter
member functions. The main disadvantage is that ‘get’ is superfluous, requiring
extra typing.
Alternative Naming Convention for
Getters – Has and Can
A
viable alternative, based on proper English conventions, is to use the prefix
‘has’ or ‘can’ instead of ‘is’ for boolean getters. For example, getter names
such as hasDependents() and canPrint() make a lot of sense when we are reading
the code. The problem with this approach is that the BDK will not pick up on
this naming strategy (yet).
3.1.1.2 Setters:-
Setters,
also known as mutators, are member functions that modify the values of a field.
We should prefix the word ‘set’ to the name of the field, regardless of the
field type. For example
Ø setFirstName(String
name);
Ø setAccount(int
accountNumber);
Ø setPersistent(boolean
persist);
Following
this naming convention we make it obvious that a member function sets the value
of a field of an object. Another advantage of this standard is that it follows
the naming conventions used by the beans development kit (BDK) for setter
member functions. The main disadvantage is that ‘set’ is superfluous, requiring
extra typing.
3.1.2 Naming
Constructor
Constructors
are member functions that perform any necessary initialization when an object
is first created. Constructors are always given the same name as their class.
For example, a constructor for the class Customer would be Customer(). Note
that the same case is used. For instance –
Ø Customer();
Ø Account();
This
naming convention is set by Sun and must be strictly adhered to.
For a good
design where we minimize the coupling between classes, the general rule of
thumb is to be as restrictive as possible when setting the visibility of a
member function. If member function doesn’t have to be public then make it
protected, and if it doesn’t have to be protected then make it private.
Visibility
|
Description
|
Proper Usage
|
public
|
A public
member function can be invoked by any other member function in any other
object or class.
|
When the
member function must be accessible by objects and classes outside of the
class hierarchy in which the member function is defined.
|
protected
|
A protected
member function can be invoked by any member function in the class in which
it is defined or any subclasses of that class.
|
When the
member function provides behavior that is needed internally within the class
hierarchy but not externally.
|
private
|
A private
member function can only be invoked by other member functions in the class in
which it is defined, but not in the subclasses.
|
When the
member function provides behavior that is specific to the class. Private member
functions are often the result of refactoring, also known as reorganizing,
the behavior of other member functions within the class to encapsulate one
specific behavior.
|
No visibility
is indicated. This is called default or package visibility, and is sometimes
referred to as friendly visibility. The member function is effectively public
to all other classes within the same package, but private to classes external
to the package.
|
This is an
interesting feature, but be careful with its use. I use it when I’m building
domain components, collections of classes that implement a cohesive business
concept such as “Customer”, to restrict access to only the classes within the
component/package.
|
Throughout this
white paper I will use the term field to refer to an attribute, which
the Beans Development Kit (BDK) calls a property. A field is a piece of data
that describes an object or class. Fields may be a base data type like a string
or a float, or may be an object such as a customer or bank account. To adhere
following important lines when declaring fields –
1.
Use
a full English descriptor for field names: - we should use a full English
descriptor to name fields to make it obvious what the field represents. Fields
that are collections, such as arrays or vector, should be given names that are
plural to indicate that they represents multiple values. For example
Ø employeeName;
Ø employeeId;
2.
Acronym
should be lower case – if the name of the field begins with an acronym, such as
sqlDatabase, then the acronym should be lowercase. For example – sqlDatabase
should not write this sQLDatabase.
3. All fields name
should be meaningful, and shows that what type of value it will hold.
4. Always avoid
abbreviation format for naming a field.
5. Always avoid
using java key words as field name.
6. Naming Constant - In Java,
constants, values that do not change, are typically implemented as static final
fields of classes. The recognized convention is to use full English words, all
in uppercase, with underscores between the words. Examples are -
Ø MINIMUM_BALANCE
Ø MAX_VALUE
Ø DEFAULT_START_DATE
The
main advantage of this convention is that it helps to distinguish constants
from variables. We will see later in the document that we can greatly increase
the flexibility and maintainability of our code by not defining constants,
instead we should define getter member functions that return the value of
constants.
7. Familiar Names –
we should use the words that exist in the terminology of the target domain. If
our users refer to their clients as customer, then use the name “Customer” for
the class not “Client”.
8. Avoid
excessively long names – name should be meaningful and descriptive but not
excessively long. Max size for this should be up to 25 characters
9. Use descriptive
name and do not attempt to shorten names by removing vowels.
10. Don’t use name
that differ only in case.
11. Naming
Collection
– A collection, such as an array or a vector, should be given a pluralized name
representing the types of objects stored by an array. The name should be a full
English descriptor with the first letter of all non-initial words capitalized.
For example –
Ø customers;
Ø orderItems;
The main advantage of this convention is
that it helps to distinguish fields that represent multiple values (collections)
from those that represent single values (non-collections).
A local variable
is an object or data item that is defined within the scope of a block, often a
member function. The scope of a local variable is the block in which it is
defined. The important coding standards for local variables focus on:
Ø Naming
conventions
In general,
local variables are named following the same conventions as used for fields, in
other words use full English descriptors with the first letter of any
non-initial word in uppercase. For the sake of convenience, however, this
naming convention is relaxed for several specific types of local variable:
Ø Streams
Ø Loop counters
Ø Exceptions
3.3.1 Naming
Streams
When there is a
single input and/or output stream being opened, used, and then closed within a
member function the common convention is to use in and out for
the names of these streams, respectively. For a stream used for both input and
output, the implication is to use the name inOut. A common alternative
to this naming convention is to use the names inputStream, outputStream,
and ioStream instead of in, out, and inOut respectively.
To tell you the truth I like this alternative better, but the fact remains that
the names in and out are what Sun suggests, so that’s what you
should probably stick with.
3.3.2 Naming
Loop Counters
Because loop
counters are a very common use for local variables, and because it was
acceptable in C/C++, in Java programming the use of i, j, or k,
is acceptable for loop counters. If we use these names for loop counters, use
them consistently. A common alternative is to use names like loopCounter or
simply counter, but the problem with this approach is that we often find names
like counter1 and counter2 in member functions that require more
than one counter. The bottom line is that i, j, k work as
counters, they’re quick to type in, and they’re generally accepted.
A major
disadvantage of using single letter names for counters, or for anything, is
that when we try to search for its use within a code file we will obtain many
false hits – consider the ease of searching for loopCounter over the
letter i.
3.3.3 Naming
Exception Objects
Because
exception handling is also very common in Java coding the use of the letter e
for a generic exception is considered acceptable.
The standards
that are important for parameters/arguments to member functions focus on how
they are named and how they are documented. Throughout this white paper I will
use the term parameter to refer to a member function argument.
Parameters
should be named following the exact same conventions as for local variables. As
with local variables, name hiding is an issue (if you aren’t using accessors).
Some examples are –
Ø customer
Ø inventoryItem
Ø in
Ø e
3.4.1 Name Parameters the Same as their
Corresponding Fields (if any)
An alternative
is to name parameters that align to an existing field with the same name as the
existing field. For example, if Account has an attribute called balance
and we needed to pass a parameter representing a new value for it the
parameter would be called balance. The field would be referred to as this.balance
in the code and the parameter would be referred to as balance (we
could also invoke the appropriate accessor method). The disadvantage of this approach is name
hiding problem and it is easy to forget to use “this” object. But I my view it is good approach, if developer
shows own maturity.
This unit
concentrates on standards and guidelines for classes, interfaces, packages, and
compilation units. A class is a template from which objects are instantiated
(created). Classes contain the declaration of fields and member functions.
Interfaces are the definition of a common signature, including both member
functions and fields, which a class that implements an interface must support.
A package is a collection of related classes. Finally, a compilation unit is a
source code file in which classes and interfaces are declared. Because Java
allows compilation units to be stored in a database, an individual compilation
unit may not directly relate to a physical source code file.
3.5.1 Standards
for Classes
The standards
that are important for classes are based on:
3.5.1.1 Naming
convention: –
The standard
Java convention is to use a full English descriptor starting with the first
letter capitalized using mixed case for the rest of the name. It is good
practice to use noun when naming a class.
Examples are –
Ø AddressDetails;
Ø Customer
Ø String
3.5.1.2 Class
visibility: –
Classes may have
one of two visibilities: public or package (default). Public visibility is
indicated with the keyword public and package visibility is not indicated
(there is no keyword). Public classes are visible to all other classes whereas
classes with package visibility are visible only to classes within the same
package.
1. Use package visibility for classes
internal to a component. With package visibility you hide classes within
the package, effectively encapsulating them within our component.
2. Use public visibility for the
facades of components. Components are encapsulated by façade classes,
classes that implement the interface of the component and that route messages
to classes internal to the component.
3.5.1.3 Documentation
Convention: –
The following
information should appear in the documentation comments immediately preceding
the definition of a class:
Ø The purpose of
the class. Developers
need to know the general purpose of a class so they can determine whether or
not it meets their needs. I also make it a habit to document any good things to
know about a class, for example is it part of a pattern or are there any
interesting limitations to using it.
Ø Known bugs8. If there are any
outstanding problems with a class they should be documented so that other
developers understand the weaknesses/difficulties with the class. Furthermore,
the reason for not fixing the bug should also be documented. Note that if a bug
is specific to a single member function then it should be directly associated
with the member function instead.
Ø The
development/maintenance history of the class. It is common
practice to include a history table listing dates, authors, and summaries of
changes made to a class. The purpose of this is to provide maintenance
programmers insight into the modifications made to a class in the past, as well
as to document who has done what to a class. As with member functions, this
information is better contained in a configuration management system, not the
source files itself.
Ø Document
applicable invariants. An invariant is a set of assertions about an
instance or class that must be true at all "stable" times, where a
stable time is defined as the period before a member function is invoked on the
object/class and immediately after a member function is invoked. By documenting
the invariants of a class you provide valuable insight to other developers as
to how a class can be used.
Ø The concurrency
strategy.
Any class that implements the interface Runnable should have its
concurrency strategy fully described. Concurrent programming is a complex topic
that is new for many programmers; therefore you need to invest the extra time
to ensure that people can understand your work. It is important to document
your concurrency strategy and why you chose that strategy over others. Common
concurrency strategies include the following: Synchronized objects, balking
objects, guarded objects, versioned objects, concurrency policy controllers,
and acceptors.
3.5.1.4 Declaration
convention: –
There are two
things that must be considering during the declaration of a class
1.
Apply
the “final” key words sensibly.
2.
Always
maintain the order among the member function and fields. The order of member of
a class differs from architecture to architecture. But, according to my
opinion,
Ø Static fields
(private, protected, public)
Ø Private fields
Ø Protected fields
Ø Public fields
Ø Constructor()
Ø Finalize()
Ø Static or
instance block{}
Ø Static function
(private, protected, public)()
Ø Private
function()
Ø Protected
function()
Ø Public
function()
Note – once the
sequence decided, then all members should stick on that format.
3.5.2 Standards
for Interfaces
The standards
that are important for interfaces are based on:
3.5.2.1 Naming
Interfaces: -
The Java
convention is to name interfaces using mixed case with the first letter of each
word capitalized. The preferred Java convention for the name of an interface is
to use a descriptive adjective, such as Runnable or Cloneable,
although descriptive nouns, such as Singleton or DataInput, are
also common.
3.5.2.2 Documenting
Interfaces
The following
information should appear in the documentation comments immediately preceding
the definition of an interface:
1.
The purpose. Before other developers will use an
interface, they need to understand the concept that it encapsulates. In other
words, they need to know its purpose. A really good test of whether or not you
need to define an interface is whether or not you can easily describe its
purpose. If you have difficulties describing it, then chances are pretty good
you do not need the interface to begin with. Because the concept of interfaces
is new to Java, people are not yet experienced in their appropriate use and
they are likely to overuse them because they are new. Just like the concept of
inheritance, and in particular multiple inheritance, was greatly abused by
developers new to object-orientation, I suspect that interfaces will also be
greatly abused at first by programmers new to Java.
How it should
and shouldn’t be used. Developers need to know both how an interface is to
be used, as well as how it shouldn’t be used. Because the signature for member
functions is defined in an interface, for each member function signature you should
follow the member function documentation conventions discussed in section 3.1.1.
3.5.3 Standards
for Packages
The standards
that are important for packages are based on:
3.5.3.1 Naming
Packages
There are
several rules associated with the naming of packages. In order, these rules
are:
1.
Identifiers are separated by periods. To make package
names more readable, Sun suggests that the identifiers in package names be
separated by periods. For example, the package name java.awt is
comprised of two identifiers, java and awt.
2. The standard java distribution packages
from Sun begin with the identifier ‘java’ or ‘javax’. Sun has reserved this
right so that the standard java packages are named in a consistent manner
regardless of the vendor of your Java development environment.
3. Local package
names begin with an identifier that is not all upper case. Local packages
are ones that are used internally within your organization and that will not be
distributed to other organizations. Examples of these package names include persistence.mapping.relational
and interface.screen.
4. Global package
names begin with the reversed Internet domain name for your organization. A package that
is to be distributed to multiple organizations should include the name of the
originating organization’s domain name, with the top-level domain type in lower
case. For example, to distribute the previous packages, I would name them com.greensoft.persistence.mapping.relational
and com.greensoft.interface.screens. The prefix (.com) should be
lower case and should be one of the standard Internet top-level domain names
(currently com, edu, gov, mil, net, org).
5. Package names
should be singular.
The common convention is to use singular names for package names, such as interface.screen,
and not a plural, such as interface.screens.
3.5.3.2 Documenting
a Package
We should
maintain one or more external documents that describe the purpose of the
packages developed by our organization. For each package we should document:
1. The rationale for the package. Other
developers need to know what a package is all about so that they can determine
whether or not they want to use it, and if it is a shared package whether or
not they want to enhance or extend it.
2. The classes in
the package. Include
a list of the classes and interfaces in the package with a brief, online
description of each so that other developers know what the package contains.
Oracle-Sun suggests creating an HTML file called index.html for each
package, putting the file into the appropriate directory for the package. A
better name would be the fully qualified name of the package, postfixed with .html,
so that we do not have to worry about accidentally overwriting one package
documentation file with another.
The standards
and guidelines for compilation units are based on:
3.5.4.1 Naming a Compilation Unit:-
A compilation
unit, in this case a source code file, should be given the name of the primary
class or interface that is declared within it. Use the same name for the
package/class for the file name, using the same case. The extension .java should
be postfixed to the file name. Examples are –
Ø Customer.java
Ø Singleton.java
Ø AddressDetails.java
3.5.4.2
Documenting a Compilation Unit
Although we
should strive to have only one class or interface declaration per file, it
sometimes makes sense to define several classes (or interfaces) in the same
file. My general rule of thumb is that if the sole purpose of class B is to
encapsulate functionality that is needed only by class A then it makes sense
that class B appear in the same source code file as class A. As a result, I
have separated the following documentation conventions that apply to a source
code file, and not specifically to a class:
1.
For files with several classes, list each class. If a file
contains more than one class we should provide a list of the classes and a
brief description for each.
2.
[OPTIONAL] The file name and/or identifying
information. The
name of the file should be included at the top of it. The advantage is that if
the code is printed we know what the source file for the code is. The
disadvantage is that if we change the source file name we also need to update
our documentation, therefore if we have a sophisticated source control system
(and if we don’t then get one) we might want to not include the source file
name.
3.
Copyright information. If applicable we
should indicate any copyright information for the file. It is common to
indicate the year of the copyright and the name of the individual/organization
that holds the copyright. Note that the code author may not be the holder of
the copyright.
In this section
we will cover several techniques that help to separate the professional
developers from the hack coders. These techniques are:
1.
Document
the code.
2.
Paragraph
the code.
3.
Paragraph
and punctuate multiline statements.
4.
Use
whitespace.
5.
Specify
the order of message sends.
6.
Write
short, single command lines.
7.
Organize
Code Sensibly.
8.
Always
place Constants on the Left Side of Comparisons.
The Sun
Microsystems suggests that fields not be declared public for reasons of
encapsulation, but I would go further to state that all fields should be
declared private. When fields are declared protected there is the
possibility of member functions in subclasses to directly access them,
effectively increasing the coupling within a class hierarchy. This makes our
classes more difficult to maintain and to enhance, therefore it should be
avoided. Fields should never be accessed directly; instead accessor member
functions (see below) should be used.
Visibility
|
Description
|
Proper
Usage
|
public
|
A public field
can be accessed by any other member function in any other object or class.
|
Do not make fields
public.
|
protected
|
A protected
field can be accessed by any member function in the class in which it is
declared or by any member functions defined in subclasses of that class.
|
Do not make
fields protected.
|
private
|
A private
field can only be accessed by member functions in the class in which it is
declared, but not in the subclasses.
|
All fields
should be private and be accessed by getter and setter member functions
(accessors).
|
For fields that
are not persistent (they will not be saved to permanent storage) you should
mark them as either static or transient. This makes them conform
to the conventions of the BDK.
I’d like to
share several techniques with all developers from Building Object
Applications That Work that, in addition to following standards, lead to
greater productivity:
1.
Program for people, not the machine. The primary goal
of our development efforts should be that our code is easy for other people to
understand. If no one else can figure it out, then it isn’t any good. We should
always obey to naming conventions, documentation of our code, to paragraph it.
2.
Design first, then code. Have we ever
been in a situation where some of the code that program relies on needs to be
changed? Perhaps a new parameter needs to be passed to a member function, or perhaps
a class needs to be broken up into several classes. How much extra work did we
have to do to make sure that our code works with the reconfigured version of
the modified code? Did we ask ourselves why somebody didn’t stop and think
about it first when he or she originally wrote the code so that this didn’t
need to happen? That they should have DESIGNED it first? Of course we did. If we
take the time to figure out how we are going to write our code before we actually
start coding we’ll probably spend less time writing it. Furthermore, we’ll
potentially reduce the impact of future changes on our code simply by thinking
about them up front.
3.
Develop in small steps. I have always
found that developing in small steps, writing a few member functions, testing
them, and then writing a few more member functions is often far more effective
than writing a whole bunch of code all at once and then trying to fix it. It is
much easier to test and fix ten lines of code than 100, in fact, I would safely
say that you could program, test, and fix 100 lines of code in ten 10-line
increments in less than half the time than you could write a single one-hundred
line block of code that did the same work. The reason for this is simple.
Whenever you are testing your code and you find a bug you almost always find
the bug in the new code that you just wrote, assuming of course that the rest
of the code was pretty solid to begin with. You can hunt down a bug a lot
faster in a small section of code than in a big one. By developing in small
incremental steps you reduce the average time that it takes to find a bug,
which in turn reduces your overall development time.
4.
Read, read, read. This industry moves far too
quickly for anyone to sit on their laurels. In fact, friends of mine within Sun
estimate that it’s a full time job for two to three people just to keep up with
what’s happening with Java, let alone what’s happening in the object-orientation
field or even development in general. That says to me that you need to invest
at least some time trying to keep up. To make things easier for you, I’ve
created an online reading list indicating what I consider to be the key
development books that you should consider reading.
5.
Work closely with your users. Good developers
work closely with their users. Users know the business. Users are the reason
why developers create systems, to support the work of users. Users pay the
bills, including the salaries of developers. You simply can’t develop a
successful system if you do not understand the needs of your users, and the
only way that you can understand their needs is if you work closely with them.
6.
Keep your code simple. Complex code
might be intellectually satisfying to write but if other people can’t
understand it then it isn’t any good. The first time that someone, perhaps even
you, is asked to modify a piece of complex code to either fix a bug or to
enhance it chances are pretty good that the code will get rewritten. In fact,
you’ve probably even had to rewrite somebody else’s code because it was too
hard to understand. What did you think of the original developer when you
rewrote their code, did you think that person was a genius or a jerk? Writing
code that needs to be rewritten later is nothing to be proud of, so follow the
KISS rule: Keep it simple, stupid.
7. Learn common
patterns, antipatterns, and idioms. There is a wealth of analysis, design,
and process patterns and antipatterns, as well as programming idioms, available
to guide you in increasing your development productivity. My experience is that
patterns provide the opportunity for very high levels of reuse within your
software development projects.
very good blog!
ReplyDeleteThank you
ReplyDelete