Coding Best Practice

1        Terms & Acronyms

Term/Acronym
Description
REST
Representational State Transfer
SOAP
Simple Object Access Protocol
JSP
Java Server Pages
MVC
Model View Controller
CSS
Cascading Style Sheets
UI
User Interface
HTTP
Hypertext Transfer Protocol
DAO
Data Access Object
JSON
JavaScript Object Notation
IDP
Identity Provider
LDAP
Lightweight Directory Access Protocol
SAML
Security Assertion Markup Language
STS
Security Token Service
TLS
Transport Layer Security




2        Java Language Best Practices

2.1       SOLID Principles

<< Content to be added>>

2.2       Avoid or Minimize Synchronization

If only certain operations in the method must be synchronized, use a synchronized block with a mutex      instead of synchronizing the entire method. For example:
private Object mutex = new Object();
    ...
private void doSomething()
{
// perform tasks that do not require synchronicity
...
synchronized (mutex)
{
...
}
...
}

Use private fields:
Making fields private protects them from unsynchronized access. Controlling their access means these fields need to be synchronized only in the class's critical sections when they are being modified.

2.3       Always use a finally clause in each method to cleanup

In Java, it is impossible to leave the try or catch blocks (even with a throw or return statement) without executing the finally block. If for any reason the instance variables cannot be cleaned, throw a catch-all exception that should cause the caller to discard its object reference to this now corrupt object. If, for any reason the static variables cannot be cleaned, throw an InternalError or equivalent that will ultimately result in restarting the now corrupt JVM.

2.4       Discard objects that throw catch-all exceptions


Adopt a guilty unless proven innocent approach. For example, a SQLException thrown from an DB2 JDBC invocation could represent one of thousands of error conditions in the JDBC driver, the network, or the database server. Some of these errors (for example, subclass SQLWarning) are benign. Some SQLExceptions (for example, "ORA-3113: end of file on communication channel") definitely leave the JDBC object useless. Most SQLExceptions do not clearly specify what state the JDBC object is left in. The best approach is to use the gentle error codes that could occur frequently in your application and can definitely be retried, such as a unique key violation for user-supplied input data. If any other error code is found, discard the potentially corrupt object that threw the exception.
Discard all object references to the (potentially) corrupt object. Be sure to remove the corrupt object from all pools in order to prevent pools from being poisoned by corrupt objects. Do not invoke the corrupt object again - instantiate a brandnew object instead.
When you are sure that the corrupt objects have been discarded and that the catching object is not corrupt, throw a non catch-all exception so that the caller does not discard this object

2.5       Avoid common errors that can result in memory leaks

In Java, memory bugs often appear as performance problems, because memory leaks usually cause performance degradation. Because Java manages the memory automatically, developers do not control when and how garbage is collected. To avoid memory leaks, check your applications to make sure they:
·       Release JDBC ResultSet, Statement, or connection.
·       Release failures here are usually in error conditions. Use a finally block to make sure these objects are released appropriately.
·       Release instance or resource objects that are stored in static tables.
Perform clean up on serially reusable objects.

2.6       Replace hashtable and vector With hashmap, arrayList, or linkedList if possible

The Hashtable and Vector classes in Java are very powerful, because they provide rich functions. Unfortunately, they can also be easily misused. Since these classes are heavily synchronized even for read operations, they can present some challenging problems in performance tuning.
Any such usage must be considered for its consequences.

2.7       Use an array instead of an ArrayList if the size is fixed


If you can determine the number of elements, use an Array instead of an ArrayList, because it is much faster. An Array also provides type checking, so there is no need to cast the result when looking up an object.

2.8       Use an ArrayList or LinkedList to hold a list of objects in a particular sequence

A List holds a sequence of objects in a particular order based on some numerical indexes. It will be automatically resized. In general, use an ArrayList if there are many random accesses. Use a LinkedList if there are many insertions and deletions in the middle of the list.

2.9       Use HashMap or TreeMap to hold associated pairs of Objects

A Map is an associative array, which associates any one object with another object. Use a HashMap if the objects do not need to be stored in sorted order. Use TreeMap if the objects are to be in sorted order. Since a TreeMap has to keep the objects in order, it is usually slower than a HashMap.

2.10   Reuse objects instead of creating new ones if possible

Object creation is an expensive operation in Java, with impact on both performance and memory consumption. The cost varies depending on the amount of initialization that needs to be performed when the object is to be created.

2.11   Use a Pool to Share resource objects

Examples of resource objects are threads, JDBC connections, sockets, and complex user-defined objects. They are expensive to create, and pooling them reduces the overhead of repetitively creating and destroying them.
Recycle Objects
The collection interfaces have the built-in clear() method that you can use. If you are building your object, you should remember to include a reset() or clear() method if necessary.

2.12   Use lazy initialization to defer creating object until you need it

Defer creating an object until it is needed if the initialization of the object is expensive
 or if the object is needed only under some specific condition.
public class myClass
{
 private mySpecialObject myObj;
  ...
  public mySpecialObject
  getSpecialObject()
  {
  if (myObj == null)
  myObj = new mySpecialObject();
  return myObj;
 }
 ...
}

2.13   Use Stringbuffer instead of string concatenation

StringBuffer is the mutable companion class of String; it allows you to modify the String. Therefore, StringBuffer is generally more efficient than String when concatenation is needed.

2.14   Code Annotations

·       Do proper indentation of code and xml files.
·       Use Object Oriented principles.
·       Use java docs. At the minimum, Javadoc is present for
o   allclasses including members of clases A Class shall as minimum have the description below:
§  Purpose & Responsibility
§  Description
§  Dependencies
§  Side-effects
§  In/out-put plus initiations
§  Special structures used
§  Treads
§  Revision log with version, description, date, author, requirement-/incident/call number including their short description
o   All non-trivial methods with functionality purpose, description, input/output parameters, preconditions for usage, side effects and special structures.
·       Class names are written in UpperCamelCase.
·       Package names are all lowercase, with consecutive words simply concatenated together (no underscores). The package names are prefixed with "com.kombit.ky.java"
For example, com.kombit.ky.java.deepspace, NOT com.kombit.ky.java.deepSpace orcom.example.deep_space.
·       Xsd, xml, wsdl namespaces are alle prefixed with "urn:oio:kontantydelse"
·       Method names are written in lowerCamelCase.
·       Constant name should use UPPERCASE letters
Example:
static final int NUMBER = 5;
enum SomeEnum { ENUM_CONSTANT }
·       Method names are typically verbs or verb phrases. For example, sendMessage or stop.
·       Always use finally clause to clean up the resource .Example db connection as well s I/O connection.
·       Don’t use wild card imports.
Ex: import sun.com.*; is not correct.
Import the specific class like import sun.com.xyzclass;
·       Don’t drop exceptions.
Dropping and ignoring an exception means that a user will not observe the occurrence of an error. This may result in errors not being detected when they appear the first time. Note that it is dangerous to catch exceptions of type Exception since this includes exceptions of type RuntimeException, and such exceptions should normally flow to the outermost level since they indicate non-recoverable error.
The following example illustrates a typical way in which exceptions can be dropped, by having an empty catch block:

try
{
throw new BadIdeaException();
} catch (BadIdeaException e)
{ // let's ignore it
}
·       All the java object should implement java.io.serializable interface.
All the java object which are stored in the session object must implement the java.io.serializable interface.When  one of the node in the cluster fails , all the session data will be migrated to another active node.This is mainly to address the failover mechanism
·       Use Generics wherever possible.
·       Example : Use List<User> users= new ArrayList<User>() instead of 
·       List  users= new ArrayList();  
·       Use Static import wherever possible.
Example: double r = Math.cos(Math.PI * theta);

Use the style below.
import static java.lang.Math.PI;
import static java.lang.Math.cos;
...
double r = cos(PI * theta);

2.15   Spring specific Best Practices

2.15.1   Add a header comment to each configuration file:

It is always very helpful to add a configuration file header, which summarizes the beans/properties defined in the configuration files. In spring configuration, we can add comments as adding xml comments or we can use the description element.

2.15.2   Use consistent naming conventions:

Using clear, descriptive, and consistent name conventions across the project increase the readability of configuration files and make it easy for other developers to avoid some accidental bugs.

2.15.3   Prefer setter injection over constructor injection:

Spring provides three types of dependency injection: Constructor Injection, Setter Injection, and Method Injection. Usually, we all use first two types only.
Constructor injection can provide the cheapest thread safety possible i.e. immutable object. Also it guarantees that object will not be handed over to other beans without complete initialization.
Setter injection provides much desired capability i.e. flexibility or maintainability. If there are multiple attributes to set in a bean, then creating a long list of parameters to constructor is not good idea.

2.15.4   Reuse bean definitions as much as possible:

Spring provides a very useful capability which we should use extensively in our project and i.e. bean definition re-usability.

2.15.5   Use ids as bean identifiers:

Spring allows two types of identifiers for a bean. Using attribute “id” or by “name”. We should always choose attribute id over name. Usually it does neither increase readability nor benefit any performance scenario.

2.15.6   Use classpath prefix:

When importing resources, XML config, properties, etc. Always use the classpath: or classpath*: prefix. This provides consistency and clarity to the location of the resource.

2.15.7   Always externalize properties:

Often there are multiple configuration parameters related to runtime of application. They are passed to bean definitions in bean configuration context file. Instead of hard code them in config file we can externalize them to some properties file(s). Better group them in separate files based on their usage or module.

2.15.8   Use dependency-check at the development phase:

We should mostly set the dependency-check attribute on a bean definition to simple, objects or all, so that the container can do explicit dependency validation for us. It is useful when all of the properties of a bean must be set explicitly, or via autowiring.

2.16   Logging

Errors should be logged (see logging section of D02). Log should contain:
1.     Origin of the error. If the error is an exception a full stacktrace must be added along with the exception message and code line (like log4j does)
2.     Input for the method where the error occurred
3.     Output if there is a partial output to report before the error occurred.
4.     User ID of the user that performed the action that caused the error (if available)

Integrations and services should log input, output and response times as info to enable monitoring of both unnecessary repeated calls and performance. The logging may need to be toggle-able, if the performance penalty of that logging is too high.

2.17   Layering

Layering should follow the agreed on (horizontal) layering model. In the UI especially the division of presentation and maintenance is important, such that no business logic is part of the UI.
Application should be broken up into logical components (vertical layering) which represent business areas or even areas within business areas. The horizontal layering model has precedence.

2.17.1   Server side state

UI may utilize but NOT require server side state (for performance, service side state may be used, but the UI should be able to work without). This will allow the browser-part of the UI to utilize any available server, thereby supporting a high up-time


3        RESTful services Best Practices

This section covers the best practices, when implementing RESTful services. Prior to the EG SD LØN project, these practices were also used in the Legacy salary system, albeit with many exceptions.

3.1       URL construction

As with other aspects of EG SD LØN, we apply the KISS principle here as well. URLs for RESTful services must be simple and intuitive. This section describes the elements.
Service URLs should in general follow this pattern:
<protocol>://<host>:<port>/<version>/<resource>/<identifier>[?<output specification>]
Some resources may contain other resources, which means that the pattern can extend to:
<protocol>://<host>:<port>/<version>/<resource>/<identifier>/<resource>[?<output specification>]
and:
<protocol>://<host>:<port>/<version>/<resource>/<identifier>/<resource> [?<output specification>]

<protocol> can be either http or https
<host> and <port> identify where the service is available
<identifier> is a unique key that identifies a specific resource object, the format and type of the identifier itself is defined by the resource. Identifiers are most often path parameters, and therefore they become part of the URL.
In the following sub sections, best practices of the remaining elements are explained.

3.1.1     Resource naming

A RESTful resource should be named using nouns as opposed to verbs, the HTTP-methods will specify the action you wish to perform on the resource, rather than the name. Furthermore, use plural. E.g. "cars" rather than "getCars" and "cars" rather than "car", respectively.
Each resource has its own URL where an identifier can be added to specify which particular resource object is of interest.
Examples:
Getting all countries:
https://myserver:1234/v1/countries
Getting a specific country (with ID "DK"):
https://myserver:1234/v1/countries/DK
Getting all cities in a specific country:
https://myserver:1234/v1/countries/DK/cities

3.1.2     Output specification

Output specification using query parameters (as opposed to path parameters), are used to limit the output when accessing a resource. Limiting the output can take several forms and has multiple purposes. The three main purposes are filtering, pagination and limiting the attributes of the resource objects that are returned.
·      Filtering use attributes of the resource. Attributes of a country could be continent, population, language and land area size. Similarly attributes of a resource such as a car could be color, make, model and propulsion energy source.
·      Pagination is used to limit the amount of resource elements returned in one service invocation. This can be used in lazy loading scenarios, or to keep the response to a manageable size.
o   For pagination we use the parameter "limit" to denote the number of elements that the client wishes to get in one call, and "offset" to denote the first element (0-indexed) of the resource elements to return. The ordering is consistently enforced by the server, such that two subsequent calls using the same query parameters will always yield the same result.
·      Attribute limitation can be an advantage when the client does not need all information available about resource elements. It limits the size of the response and, depending on the server side implementation, it may also limit the resources necessary at the server side.

Examples:
Getting countries in Europe (filtering):
https://myserver:1234/v1/countries?continent=Europe
Getting cities in Denmark that has a population between 100.000 and 500.000 inhabitants (filtering)
https://myserver:1234/v1/countries/DK/cities?populationStart=100000&populationEnd=500000
Getting country no. [61-110] in the world (pagination):
https://myserver:1234/v1/countries?limit=50&offset=60
Getting the name and area size all cities in Denmark (attribute limitation):
https://myserver:1234/v1/countries/DK/citites?attributes=name,areaSize

3.1.3     Versioning

Since services are a layer that aids with decoupling, versioning should always refer to the interface. Such interfaces should be relatively static, in order not to disrupt its surroundings (the clients of the service), but in case it changes in a way that removes or alters input in an incompatible way, it will always be a major change. Therefore versioning of the RESTful services of EG SD LØN should be using a v and one number, e.g. V1:

Examples:
Getting the name and area size all cities in Denmark using V1 of the service:
https://myserver:1234/v1/countries/DK/citites?attributes=name,areaSize
Getting the name and area size all cities in Denmark using V2 of the service, using country identifier in the format of ISO ALPHA-3 country code instead of ISO ALPHA-2:
https://myserver:1234/v2/countries/DNK/citites?attributes=name,areaSize

3.2       HTTP Methods

HTTP methods are used to read and manipulate RESTful resources, leaving the URL's unchanged. Each method has its own functionality. Deviations are sometimes necessary, but must be thoroughly documented.

Also see DP-0009.

GET will be used to fetch response data from target resource
PUT will be used to update UI changes/data into the service to update target resource.
POST will be used to create set of data in the target resource. EX: Create Registration
DELETE will be used to remove data from the target resource. Ex: deleting rows from the list
OPTIONS will be used for server communication or handing header & CORS informations from the server.

3.3       Input header

<Work in progress, see DP-0025 in the ADP document>

In addition to the URL which contains the parameters to access resources, an input header containing a unique client id and/or log id, which will allow tracing the call through the backend is required.
The names of these header attributes are
egsdlonClientID and egsdlonLogID respectively.
This header is necessary when using all HTTP-methods.


.



3.4       Return codes

The decision diagram on this page shows which
HTTP return codes to use in which cases.
(Full size diagram in the appendix)





3.5       Error handling

When errors occur, in many cases HTTP return code 500 will be used. In addition to this we will return an HTTP-body along with the HTTP return code. This body will contain as a minimum a timestamp and log-id, that will allow the maintenance teams to trace the error to its source.
It is important that the body does not contain stack traces, class names, package names and other information that will give away our platform and technology to potential hackers.



4        Queues

4.1       MQ

Queues should be defined and "owned" by the areas that uses them or requires them. We call this "owner area". Queues are often used for asynchronous communication between two areas, one of the areas is the owner area and we call the other "secondary area".

4.1.1     Naming

Naming of MQ's should follow this pattern:
egsdlon.<owner area>[.<secondary area>].[<in>|<out>]

examples:
egsdlon.events.employment
egsdlon.events.organization
egsdlon.messages.sms.in
egsdlon.messages.email.in
egsdlon.organization.apos.in
egsdlon.organization.apos.out


5        AngularJS Best Practices

5.1       Single Responsibility

Defining a single component per file helps with code maintenance. Rather than defining a module (and its dependencies), a controller, and a factory all in the same file, separate each one into their own files.

5.2       Immediately Invoked Function Expressions

Wrapping your AngularJS components in an Immediately Invoked Function Expression (IIFE). This helps to prevent variables and function declarations from living longer than expected in the global scope, which also helps avoid variable collisions.
This becomes even more important when your code is minified and bundled into a single file for deployment to a production server by providing variable scope for each file.

5.3       Manual Dependency Injection

To prevent parameters from being converted to mangled variables, avoid using the shortcut syntax of declaring dependencies without using a minification-safe approach.
Using $inject to manually identify your dependencies mirros the technique used by ng-annotate and safeguards your dependencies from being vulernable to minification issues when parameters may be mangled.

5.4       Exception Handling

To provide a consistent manner for customizing how exeptions are handled, use a decorator at configuration time using the $provide service on the $exceptionHandler service to perform custom actions when exceptions occur.

5.5       Angular Wrapper Services

Use $document and $window instead of document and window. They are more easily testable than using document and window. Use $timeout and $interval instead of setTimeout and setInterval. They are more easily testable and handle AngularJS's digest cycle, thereby keeping data binding in sync.

5.6       Minification and Annotation

Using ng-annotate for Gulp or Grunt by commenting functions that need automated dependency injection with /** @ngInject */ will safeguard your code from any dependencies that may not be using minification-safe practices.

5.7       Factories

Factories are singletons which should have a single responsibility that is encapsulated by its context. Declaring all of the callable members of the service at the top makes it easy to read and helps you instantly identify which members of the service can be called and must be unit tested (and/or mocked).

5.8       Limit DOM Manipulation

DOM manipulation can be difficult to test and debug. If you must manipulate the DOM directly, use a directive. However, if alternative ways can be used, such as using CSS to set styles or the animation services, Angular templating, ngShow or ngHide, use those instead.

5.9        Resolving Promises for A Controller

Controller Action Promises: Placing start-up logic in a consistent place in the controller makes it easier to locate, more consistent to test, and helps avoid spreading out the activation logic across the controller. Typically, this should be done in an activate function.
Route Resolve Promises: When a controller depends on a promise to be resolved, resolve those dependencies in the $routeProvider before the controller logic is executed. Using a route resolve allows the promise to resolve before the controller logic executes.

5.10   Defer Controller Logic

Placing logic in a service or a factory, rather than directly in the controller, can lead to better reuse across multiple controllers. It is also easier to isolate in a unit test and allows the calling logic in the controller to be easily mocked. It also helps remove dependencies and hides implementation details from the controller.

5.11   Documentation

AngularJS-code must be documented to aid maintainability. Extent and style must match the documentation requirements of the java-code.

6        Data Access (Hibernate) Best Practices

6.1       Datasources connections caching and handling

·       Connections and Hibernate Session objects must not be closed within finalize() methods.
·       All connections and Hibernate session objects must be explicitly closed by the application.
·       Do not declare connections as static objects.

6.2       Datasource initialization

It is a good practice to put the JNDI lookup of a DataSource as part of the application initialization code, since DataSources are simply connection factories.

6.3       Disable Auto-Commit mode for better performance

For better application performance, disable auto-commit mode and use the commit() or rollback() method of the connection object to manually commit or rollback your transaction.

6.4       Defining column types

·       Saves a roundtrip to the database server.
·       Defines the datatype for every column of the expected result set.
·       For VARCHAR, VARCHAR2, CHAR and CHAR2, specifies their maximum length.

6.5       Setting the cache connection inactivity timeout in data sources

The inactivity-timeout specifies the time, in seconds, to cache unused connections before closing them. This must be set in the hibernate configuration file.

6.6       Set the wait for free connection timeout in data sources

The wait-timeout specifies the number of seconds to wait for a free connection if the connection pool does not contain any available connection. This must be set in the hibernate configuration file.

6.7       Use JDBC connection pooling and connection caching

In JDBC 2.0, a connection-pooling API allows physical connections to be reused. A pooled connection represents a physical connection, which can be reused by multiple logical connections.

6.8       Use JDBC statement caching

Use JDBC statement caching to cache a JDBC PreparedStatement that is used repeatedly in the application to:
·       prevent repeated statement parsing and recreation
·       reduce the overhead of repeated cursor creation

6.9       Tune the database and SQL statements


Monitor frequently executed SQL statements. Consider alternative SQL syntax, use PL/SQL or bind variables, pre-fetch rows, and cache rowsets from the database to improve your SQL statements and database operations

6.10   Bi-temporal data

Bi-temporal data access (CRUD) should be accomplished through the same framework (L5 Snodgrass engine) in all places (existing and new), except when requirements or legacy code dictates otherwise. Exceptions must be well documented.
Audit logging: All changes to data must be audited, such that information about who and when data was changed is available (Snodgrass engine has these data – some of the current SD JBoss application also contain that info through similar means, but often using hibernate audit logging).

6.11   Caching

Where caching is used, interfaces for viewing and clearing both single and multiple items must be provided. The interface should also provide a way to toggle caching on and off.



7        HTML Coding Standards:

7.1       Always declare a Doctype:

The doctype declaration should be the first thing in the HTML documents. The doctype declaration tells the browser about the XHTML standards that will be using and helps it read and render the markup correctly.

7.2       Use Divs to Divide Your Layout into Major Sections:

Consider dividing the web page into major sections as the first step in constructing a website design. Doing so from the start promotes clean and well-indented code.

7.3       Separate Content from Presentation:

We should not use inline styles in HTML. Always create a separate CSS file for styles. This will help us and future developers that might work on our code make changes to the design quicker and make your content more easily digestible for user agents.

7.4       Keep the Syntax Organized:

·       Use lowercase letters within element names, attributes, and values
·       Indent nested elements
·       Strictly use double quotes, not single or completely omitted quotes
·       Remove the forward slash at the end of self-closing elements
·       Omit the values on Boolean attributes

7.5       Use the Alternative Text Attribute on Images:

Images should always include the alt attribute. Screen readers and other accessibility software rely on the alt attribute to provide context for images. The alt attribute value should be very descriptive of what the image contains. If the image doesn’t contain anything of relevance, the alt attribute should still be included.

7.6       Make Use of Semantic Elements:

The library of elements in HTML is large, with well over 100 elements available for use. Deciding which elements to use to describe different content may be difficult, but these elements are the backbone of semantics. We need to research and double check our code to ensure we are using the proper semantic elements.

7.7       Use the Proper Document Structure:

We must always be sure to the use proper document structure, including the <!DOCTYPE html> doctype and the <html>, <head> and <body> elements. Doing so keeps our pages standards compliant and fully semantic.

7.8       Use Practical ID & Class Values:

Creating ID and class values can be one of the more difficult parts of writing HTML. These values need to be practical, relating to the content itself, not the style of the content.



8        CSS Coding Standards:


8.1       Make it Readable:

Great readability of CSS makes it much easier to maintain in the future, as we will be able to find elements quicker.

8.2       Keep it Consistent:

Along the lines of keeping the code readable is making sure that the CSS is consistent. We should start to develop our own "sub-language" of CSS that allows us to quickly name things.

8.3       Organize the Stylesheet with a Top-down Structure:

It always makes sense to lay the style sheet out in a way that allows us to quickly find parts of our code.

8.4       Understand the Difference Between Block vs. Inline Elements:

Block elements are elements that naturally clear each line after they're declared, spanning the whole width of the available space. Inline elements take only as much space as they need, and don't force a new line after they're used.

8.5       Make Use of Generic Classes:

There are certain styles that are applied over and over. Instead of adding that particular style to each ID, we can create generic classes and add them to the IDs or other CSS classes.

8.6       Use Absolute Positioning Sparingly:

Absolute positioning is a handy aspect of CSS that allows us to define where exactly an element should be positioned on a page to the exact pixel.

8.7       Use Multiple Stylesheets:

Depending on the complexity of the design and the size of the site, it's sometimes easier to make smaller, multiple style sheets instead of one large style sheet.

8.8       Reuse and customization

Make sure that generic style classes are used as much as possible on all levels, to ensure the same look and feel across all areas.
Custom styles should be clearly marked along with in-code comments that justified the customization. Included in this justification should be an argument why the customization is not general/generic solution. The naming for custom styles should contain "custom" and "<page/functionality/domain>" that identifies that the style is custom and where it is used.
Custom styles should have their own style sheet. Putting multiple custom styles into the same custom style sheet is allowed when they concern the same page/functionality/domain.

JAVA8 tutorial

https://howtodoinjava.com/java8/java-stream-distinct-examples/



No comments:

Post a Comment