...
- 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 svngit)
- 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) - 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
...
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.)
Configure your Integrated Development Environment to assist you in following the style guidelines: Coding Standards - IDE Settings
Class Structure
For the most part, classes should be laid out in the following order:
LOG
fields
constructors
overridden methods (public)
protected/private methods
getters and setters with logic
- getters/setters with no logic
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.
...
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.)
...
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.)
...
Examples of Constant Classes:
Constant Type | Global KFS Class | Module-Specific class example | Description/Usage |
---|---|---|---|
Constants | org.kuali.kfs.sys.KFSConstants | org.kuali.kfs.module.purap.PurapConstants | Used to define general constants (don't fit in one of the categories below) for the system or module. |
KeyConstants | org.kuali.kfs.sys.KFSKeyConstants | org.kuali.kfs.module.purap.PurapKeyConstants | Holds error key constants that are global or module-specific. |
PropertyConstants | org.kuali.kfs.sys.KFSPropertyConstants | org.kuali.kfs.module.purap.PurapPropertyConstants | Holds property name constants that are global or module-specific. |
ParameterConstants | org.kuali.kfs.sys.KFSParameterKeyConstants | org.kuali.kfs.module.purap.PurapParameterConstants | Has names of parameters associated globally or with a module (inner classes can be used to organize those parameters which don’t fit with the big four components of All, Batch, Document, and Lookup). |
WorkflowConstants |
org.kuali.kfs.module.purap.PurapWorkflowConstants | Has node names and application document statuses (inner classes can be used here to differentiate between nodes and statuses used on different documents, like what PurapWorkflowConstants does). | ||
AuthorizationConstants | org.kuali.kfs.sys.KfsAuthorizationConstants | org.kuali.kfs.module.purap.PurapAuthorizationConstants | Contains names of edit modes (again, inner classes to separate by document type is fine) and special permission names which need to be called...and in very very rare cases, role names. |
KimAttributes | org.kuali.kfs.sys.identity.KfsKimAttributes | org.kuali.kfs.module.purap.identity.PurapKimAttributes | Special case that holdes constants for KIM attributes as well as instance variables, setters and getters for those attributes. |
KFS Naming Standards
These are examples of naming convention for KFS documents.
BO or Transactional Document Class | BO DD Entry | Doc DD Entry | Workflow Doc Name | Doc Label / Workflow Doc Label / Portal Link |
---|---|---|---|---|
AssetAcquisitionType.java | AssetAcquisitionType.xml | AssetAcquisitionTypeMaintenanceDocument.xml | AssetAcquisitionTypeMaintenanceDocument | Asset Acquisition Type |
AssetDepreciationMethod.java | AssetDepreciationMethod.xml | AssetDepreciationMethodMaintenanceDocument.xml | AssetDepreciationMethodMaintenanceDocument | Asset Depreciation Method |
AssetObjectCode.java | AssetObjectCode.xml | AssetObjectCodeMaintenanceDocument.xml | AssetObjectCodeMaintenanceDocument | Asset Object Code |
Module Development Standards
...
A module service interface in the
org.kuali.module.integration.<your module code>
package that contains all methods that the core financial system and other optional modules need to call. This includes data access methods, business rules, document spawning etc. The implementation for this interface will live in theorg.kuali.module.<your module>.service.impl
. The corresponding bean should be defined in theorg.kuali.module.integration.SpringBeansModules.xml
file.Note Module service bean definitions that reside in
org.kuali.module.integration.SpringBeansModules.xml
cannot reference beans defined in optional module Spring files, e.g. withinLaborModuleServiceImpl
, other Labor services that are relied on need to be obtained fromSpringContext
NOT dependency injection.- Interfaces in the
org.kuali.module.integration<your module>.bo
package for business objects that the core financial system and other optional modules need to deal with as parameters or return values from your module service methods or reference from their lookups, documents, etc. See Externalizable Business Objects for documentation and the following examples: Account BO's references to ContractsAndGrantsCfda and ContractsAndGrantsAccountAwardInformation and the FP CAB data collection code - look for code references to CapitalAssetInformation and capitalAssetInfo.tag, e.g. refs to CapitalAssetManagementAsset. - Public and protected method signatures should not be changed in a non-impacting release. If a method signature change is required, the original method should be deprecated and a new method created. If possible, the original method should call the new method with sensible defaults.
...
Public services in KEW all return "DTO" objects which are capable of being sent over the Kuali Service Bus.
Useful KNS Services
Service | Purpose | Sample Methods |
---|---|---|
Standard KNS Services |
BusinessObjectService | General purpose service to retrieve and persist business objects. This service eliminates the need for custom DAOs and services for basic CRUD operations. |
| ||
LookupService | Service for performing more complex lookups of business objects. Criteria maps passed to this service can contain special characters in the lookup values which can perform and/or/between/greater than/less than operations. This also can be used to reduce the need for OJB-specific query code. |
| ||
MailService | Used to send email messages. |
| ||
DateTimeService | Use to obtain the current date/time and parse/format dates between String and Date objects. |
| ||
Data Dictionary Services |
DataDictionaryService | General purpose service to obtain information about business objects, documents, and their attributes from the data dictionary. These calls are lower level than either of the services below. Only use these calls if you can't get the information from one of the services below. |
BusinessObjectDictionaryService | Specialization of the above service to help answer more complex, but common, questions needed about business objects, mainly for implementing the KNS framework. |
MaintenanceDocumentDictionaryService | Same as the above, but for maintenance documents. |
| ||
Workflow Wrapper Services |
---|
DocumentService | Primary KNS service for interacting with documents. This service should be used whenever possible instead of accessing KEW services. |
| ||
Information Services |
ConfigurationService | Used to pull configuration properties (mostly from configuration.properties). |
| ||
ParameterService | Used to pull parameters from the KRNS_PARM_T table on the Rice server. |
|
Public KEW Services
In general, the services below should only be used if there is not a KNS "wrapper" service for the same operation. Often, the KNS services perform additional actions on the document before calling into the workflow engine.
Service | Purpose | Sample Methods |
---|---|---|
WorkflowUtility | main service for obtaining information about a document in routing |
|
WorkflowDocumentActions | allows most actions to be taken on an existing document in routing |
|
DocumentSearchService | Perform document lookups using the same APIs as the document search screen. For programmatic searches, DocumentSearchService has a number of problems - it's incredibly slow, and furthermore, it brings back a limited number of results. Because of this, it would be best to consider if you can find all of the information needed to successfully complete the search by doing a BusinessObjectService#findMatching on records of FinancialSystemDocumentHeader. |
|
Public KIM Services
Service | Purpose | Sample Methods |
---|---|---|
IdentityService | Service to access principal and entity information. | getPrincipalByEmployeeId() getPrincipalByPrincipalName() |
RoleService | Information about Roles | getRole() getRoleByNamespaceCodeAndName() |
PermissionService | Service which checks if a given principal has the permission to execute a certain kind of system event. | isAuthorizedByTemplate() findPermissionsByTemplate() |
PersonService | Full information about entities stored in KIM. IdentityService's getPrincipal*() methods are much faster and typically require all the information necessary to do, say, a permission check - for this reason, those methods are preferred to using PersonService. | getPersonByPrincipalName() |