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:
{
{
...
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 failures here are usually in error conditions. Use a finally
block to make sure these objects are released appropriately.
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
or if the
object is needed only under some specific condition.
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.
·
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"
·
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:
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)
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
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:
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