...
This is why all services in the application must be stateless, depending only on their passed parameters.
Getters and Setters
In general, any method in the form of "<some type> get{PropertyName}()" should be a real getter: it should not take any function parameters and it should do nothing more than return the value of a property. The same with setters - they should return void, take in one parameter, and set the value of the property to that parameter. If a getter is returning a primitive boolean, then it should be an "is-er" - ie, it should be in the form of "boolean is{PropertyName}()". These conventions, part of the original JavaBean spec, are well established. This implies that, for instance, setting the value a member variable in a getter or that a setter which reads from a database are probably preforming behavior which other developers would not expect. We'd like to try to avoid those kinds of situations.
There are, of course exceptions. For instance, KFS has a pattern of using a getter to return services in contexts where Spring cannot inject services - ie, where the service needs to be retrieved from SpringContext directly as there is no other choice about the service's retrieval. That pattern looks commonly like this:
Code Block | ||
---|---|---|
| ||
class ExampleDocument {
private static volatile BusinessObjectService businessObjectService;
public BusinessObjectService getBusinessObjectService() {
if (this.businessObjectService == null) {
businessObjectService = SpringContext.getBean(BusinessObjectService.class);
}
return businessObjectService;
}
} |
Here, we've got a document which wants to use a BusinessObjectService. Ideally, we'd like to cache that BusinessObjectService variable in such a way that all instances of the document live in memory can share it - hence we declare the property to be static. (We also want calls to getBusinessObjectService() running concurrently to not write over the businessObjectService property multiple times - that's why we declare the property to be volatile). If the businessObjectService property is null, we go ahead and set it from SpringContext, and then we return that property. This means we're possibly setting the value in the getter. In this case, though, we find the setting excusable since: a) we know that no other setting of businessObjectService will ever occur; b) we always use getBusinessObjectService(), never the property businessObjectService directly; and c) the setting will only ever occur once. These constraints make this an unusual case. In the vast majority of cases, though, getters and setters should truly be getters and setters.
Concrete methods on Interfaces
Java 8 comes with a lot of revolutionary language features. However, to enable those revolutionary language features, the Java team introduced one ugly feature: the ability to write concrete methods on Interfaces. The rationale behind this is that in some special cases, a method has a single, standard implementation which should always be used.
Hogwash! Malarkey! The real reason this feature was introduced was to make it easy to access Streams from Collections in a way that would retain Java's backwards compatibility, because if backwards compatibility wasn't there, Java programmers would grouse and pout. The Java designers did give us a fair number of revolutionary features, though, and therefore, we forgive them.
However, just because the Java language team used this doesn't mean any of the rest of us should. It's a really strange feature and it should be avoided if at all possible.
Javadoc Standards
Info |
---|
Taken from Coding Standards |
General Javadoc Standards
Anchor | ||||
---|---|---|---|---|
|
- Javadoc everything no matter what the scope.
- Always use the "/**, hit return" command above each method
- Never leave "TODO" in the code
Class Javadocs.
- Class javadocs should not have an author tag.
- Constructor javadocs should state anything unique about the constructor like unique build requirements or special setup.
Method Javadocs
- Description of what the method is doing unless it is a getter/setter; however, if getter/setter is doing something other than the standard execution, you should comment.
- Should have at least doclet tags for param, return, and throws.
Info |
---|
Taken from KC Coding Standards - Post Release 1.0 |
- Comments
- We need more comments explaining why things are done the way they are
- Include comments in the code on "why" in any case when "why" isn't readily apparent - for example, extra complexity
- Comment interfaces and abstract classes well as this forms basis for our Service APIs
- Comment interface and abstract class methods with JavaDoc, including a description of what the method does, why it does it and input parameters, return value, and anticipated exceptions that could be thrown (runtime or checked)
- Comment on the implementation anything interesting/special/complex about the way the interface is implemented
- JavaDoc comments should be included for all public, protected, and default visibility scopes
- Don't comment private with JavaDoc so we don't depend on interfaces that could be refactored
- Code should use descriptive names indicating what and how; comments should explain why
- If the method throws an unchecked exception, it should be manually added to the JavaDoc comments
- Internal method comments should be provided to explain necessary complexity, but not as crutch for poor names or overly complex code
- No "commented out" code should be committed
- If implementing a design pattern, say so in comments
- Bug Fixes
- Don't include JIRA #s in comments (relate JIRAs to commits via svn)
- Don't include specific bug fixes in comments, but keep comments up to date with any code changes
- Do not include @author tags
- No TODO comments in committed code
- Comment any deviation from our coding standards including an explanation for the deviation (non-commented deviations can
be considered a mistake) - SQL scripts should follow the same comment guidance
Info |
---|
Taken from Javadoc Standards |
General Javadoc Standards
- All methods - public, private, and protected will have the standard Javadoc header
- Any method that throws an Exception should declare a @throws directive and should explain what/why/when the exception is thrown.
- We do not need to comment our variable declarations
- The more complicated the code, the more extensive that the javadocs should be
- Comments should detail internal non-obvious code, if in doubt comment extensively
- Comments generally are intended to simplify maintenance
Class Headers
Code Block |
---|
/**
* This is a description of what this class does...
*/
public class ClassName { ... |
Javadocs for Methods
Code Block |
---|
/**
* A useful description of what this method does...
* @param paramOne This param...
* @param paramTwo This param...
* @return Returns the...
* @throws ClassName This is thrown when...
*/
public ClassName doMethod(ClassNameOne classNameOne, ClassNameTwo classNameTwo) throws ClassName { ...
|
If your method is in an implementation class, your Javadocs should follow this format:
Code Block |
---|
/**
* A useful description of what this method does... how does this implementation class
* implement the interface. What technology does it use? Is this the default impl? What's
* unique about this implementation of the method?
* @see org.kuali.service.SomeInterfaceClass#doMethod(ClassNameOne classNameOne, ClassNameTwo classNameTwo)
*/
public ClassName doMethod(ClassNameOne classNameOne, ClassNameTwo classNameTwo) throws ClassName { ...
|
If your method is in an interface, you Javadocs should follow the standard method format, describing what the method does without describing any implementation details.
Constructor Javadocs
Code Block |
---|
/**
* This constructor sets up empty instances for the dependent objects...
*/
public ClassName() { ...
|
Java Style Guidelines
In general, we are following the recommendations in the book: The Elements of Java Style. Please be familiar with the conventions in that book, as it will result in less reformatting of code later. (Such reformatting makes it harder to detect actual coding changes.)
Use of Braces
In almost all cases, braces should be used when creating blocks. It is too easy to introduce bugs into the system by omitting braces for single-line clauses, especially if-then-else setups. (This is one of those cases where indentation comes into play, if lines after the first are also indented, a developer reading the code might assume that those lines are part of the else clause.
The only exception would be simple one-line statements which are on the same line as the if statement. The statement and if cause must be simple so the line is not too long to easily read. E.g,:
Code Block |
---|
// return false if the passed in argument does not have a value
if ( StringUtils.isBlank( chartOfAccountsCode ) ) return false;
|
This helps save space and is still easy to read. Be sure to have a blank line after a statement like this so it is evident that there are no other statements within the if block.
Naming Conventions
General Java Naming Conventions
In the following table, the naming conventions for Java language entries are listed as well as corresponding examples:
Entity | Naming Conventions | Good Examples | Incorrect Examples |
---|---|---|---|
package |
| org.apache.log4j.logger | org.kuali.YearEnd |
class |
| LedgerPendingEntry | BalanceTyp |
interface |
| TransactionPoster | PostTransaction |
enum |
| Weekday |
|
enum values |
| MONDAY |
|
method |
| save() |
|
variable |
| documentTypeCode | findTypeCode |
constant |
| FISCAL_YEAR | FROM |
Suggestions:
- All names should be meaningful
- Do remember we are writing code read by not only compilers, but also future developers and implementors
- Keep the names consistent with the domain knowledge or business specifications
- Keep the names consistent across the project-level modules (E.g., name variables which contain a chart code: chartOfAccountsCode)
- Avoid abbrev. (Most IDEs include code completion, which takes away much of the reason for abbreviations.)
Note |
---|
This section is the Original Java Naming Conventions text. (the above was copied from the OLE site) |
General Naming Convention
Naming convention make programs more understandable by making them easier to read. They can also give information about the function of the identifier-for example, whether it's a constant, package,
or class-which can be helpful in understanding the code
Identifier Type | Rules for Naming | Examples |
---|---|---|
Packages | The prefix of a unique package name is always written in all-lowercase ASCII letters and should be one of the top-level domain name, org . Subsequent components of the package name vary according to modules, businessObject, document, service, dao etc. | org.kuali.kfs.pdp.businessobject |
| Class names should be nouns, in mixed case with the first letter of each internal word capitalized. Try to keep your class names simple and descriptive. Use whole words-avoid acronyms and abbreviations (unless the abbreviation is much more widely used than the long form, such as URL or HTML). | AdvanceDepositAccountingLineAuthorizer |
Interfaces | Interface names should be capitalized like class names | interface AccountingLineAuthorizer, FinancialSystemTransactionalDocumentPresentationController |
Methods | Methods should be verbs, in mixed case with the first letter lowercase, with the first letter of each internal word capitalized. The method names should be meaningful that succinctly describe the purpose of the method, making the code self-documenting and reducing the need for additional comments. | extractAccruals(),needsExpiredAccountOverride |
Variables | Except for variables, all instance, class, and class constants are in mixed case with a lowercase first letter. Internal words start with capital letters. Variable names should not start with underscore _ or dollar sign $ characters, even though both are allowed.Variable names should be short yet meaningful. The choice of a variable name should be mnemonic- that is, designed to indicate to the casual observer the intent of its use. One-character variable names should be avoided except for temporary "throwaway" variables. Common names for temporary variables are i, j, k, m, and n for integers; c, d, and e for characters. | String fullParameter,String boClassName |
Constants | The names of variables declared class constants and of ANSI constants should be all uppercase with words separated by underscores ("_"). (ANSI constants should be avoided, for ease of debugging.) | public static final Integer EXPIRED_ACCOUNT , List<String> REFRESH_FIELDS |
Logging
Kuali defaults logging to the INFO
level. This means that, in production, any messages at INFO level or higher will go into the application logs. Since this is the primary means of monitoring system operation, we need to be careful to not overload these logs with too much detail, as that tends to obscure any problems which may occur. (It may also cause critical troubleshooting information to be rotated out of the logs too soon.)
...