...
- Each layer has a unique responsibility. Avoid responsibility leaking among layers;
Thread Safety
All web applications are multi-threaded applications. This means that a particular section of code may be accessed at the exact same time by multiple users. As such, you must never store an operation's state in a variable which could be accessed from multiple threads. In the best case, an error will occur when the user's sessions collide. In the worst case, there would be silent data corruption as one user's data is saved over the other's.
...
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.
...
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.
...
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 |
...
- Javadoc everything no matter what the scope.
- Always use the "/**, hit return" command above each method
- Never leave "TODO" in the code
...
Java 8 Streams
Java 8 introduced the concept of a stream that can be filtered, manipulated and collected into a new data type. These features make code shorter and more readable. When working with collections, streams should be used when possible in place of code that loops through each element. Information on Java 8 Streams can be found here: Processing Data with Java SE 8 Streams.
Javadoc/Comment Standards
Info |
---|
Taken from Coding Standards |
Javadoc Standards
The Javadoc standard is a way of writing comments in code that can be used when generating documentation web pages. These forms of comments should be used for classes and methods when the code warrants a comment. Comments should be provided to explain why a class exists or why a method is needed. It should also explain something that is non-obvious in the code. A comment should not state the obvious (examples "This is the default constructor" or "getter for accountName").
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 |
General Comments about 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 if a comment is warranted
- 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-commented deviations can
be considered a mistake) - When refactoring code, any existing comments should be refactored also so the comment matches the current code
- SQL scripts should follow the same comment guidance
Info |
---|
Taken from Javadoc Standards |
Examples
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 ClassNameExceptionClassName This is thrown when... */ public ClassName doMethod(ClassNameOne classNameOneparamOne, ClassNameTwo classNameTwoparamTwo) throws ClassNameExceptionClassName { ... |
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? method? * * @see org.kuali.service.SomeInterfaceClass#doMethod(ClassNameOne classNameOne, ClassNameTwo classNameTwo) */ public ClassName doMethod(ClassNameOne classNameOne, ClassNameTwo classNameTwo) throws ClassName { ... |
...
Constructor Javadocs
Code Block |
---|
/** * This constructor sets up empty instances for the dependent objects... */ public ClassName() { ... |
...
Code Block |
---|
// this variable is private to ensure that subclasses only use the getter private static DataDictionaryService dataDictionaryService; // This method is protected. Nothing but this class and subclasses should ever obtain the service reference from here. protected DataDictionaryService getDataDictionaryService() { if ( dataDictionaryService == null ) { dataDictionaryService = SpringContext.getBean(DataDictionaryService.class); } return dataDictionaryService; } |
...
OJB proxies are sadly resistant to null checks. This is because a proxy itself may not be null, but until it actually goes to the database to look for a value, it hasn't replaced itself with null yet. This leads to code examples like this:
Code Block language java if (document.getItem() != null) { // document.item is a proxy - it passes the null check because the proxy isn't null return document.getItem().getQuantity() * 2; // but this blows up because when ojb tries to retrieve the item in in // getItem() so it can call getAmount(), it finds there is no itemitem in the db and then throws // in the db and then //throws a very strange NullPointerException }
To help avoid these situations, Rice provides a class org.kuali.rice.krad.util.ObjectUtils (not to be confused with Spring's ObjectUtils or Apache Commons' ObjectUtils) with two methods: isNull() and isNotNull(). These methods force the ORM to check if a proxy is in place and if so, to figure out at that point if the proxy will resolve to null:
Code Block language java if (!ObjectUtils.isNull(document.getItem()) { return document.getItem().getQuantity() * 2; // now, if document.getItem() isn't in the database, this whole block of code will be skipped }
Because of the utility of this method, as well as the fact that it is sometimes difficult to know whether you are dealing with a proxy or not, the KFS product team suggests that you use ObjectUtils.isNull() or ObjectUtils.isNotNull() to perform all null checks.
...