Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Object-oriented design forces software developers to think in terms of objects, rather than procedures. It is based on the following major techniques: inheritance, polymorphism, encapsulation, and modularity. A set of principles are derived from those techniques and can help us have better understanding about object-oriented design.

Single Responsibility Principle 

Panel

A class has a single responsibility: it does it all, does it well, and does it only.

...

  • Do not create omniscient classes that are all-knowing and all-powerful. (E.g., do not write classes which assume behavior of the implementations of other classes.)
  • Keep the maximum length of a method as one screen or one or two pages of program listing, no more than about 150 lines;
  • Each variable should have a single purpose.

Open Close Principle

Panel

Software entities (classes, modules, functions, and so forth) should be open for extension, but closed for modification.

...

Note
titleKuali Comment

Our take on this will be slightly different, as we are writing an application which we know that the implementors will want to customize. As such, we need to be careful not to lock them out of customizing pieces of the application. Where we can anticipate customization, we should add hook points to allow for easy overrides. But, private variables and methods interfere with their ability to override something which we did not anticipate.

Program to an Interface

Panel

Program to an interface, not an implementation

...

Java Programming Paradigms

Enumerated Type

An enumeration is new to Java 5. It is an object type with a finite set of possible values, which is called enum values or enum constants.

...

  • Avoid implementing enumerations with public static final int declarations;
  • Use enumerated types for readability, maintainability and type safety;
  • Use enumerated types as an alternative to boolean variables.

Annotations

Java annotations allow developers to add metadata to source code. The metadata can be utilized by tools at compile time and retained in the compiled Java classes for use at runtime. Annotations should never affect the way a Java program runs, but they may affect the behaviors of a compiler or auxiliary tools. For example, the annotation @SuppressWarnings instructs Java compiler to suppress the specified warning types while the annotation @Transactional in Spring is used to let the application put the calling class or method in a transactional context.

...

Java Language Specification requires annotations are not supposed to “directly affect the semantics of a program”. However, there are few standards that dictate what metadata should be used and carried by annotations, so developers are suggested to use annotations with restraint.

Annotation Examples

Java Generics

Generics were implemented by Java 5 or later. Generics make Java code easier to write and read through making the type of the objects an explicit parameter of the generic code.  Using Generics gives us:

...

  • Design methods and classes with generics whenever possible;
  • Specify the types of elements in a Java collection whenever it is used;
  • Use Enhanced for-loop whenever possible.

Method-Chaining

A few of programming languages and Java applications are promoting the use of method chaining since it is short and simple. The following code snippet is an example of Java method chaining:

...

Note
titleKuali Comment

The code above assumes normal Java objects. Care must be taken when working with objects retrieved from the database via OJB. If an object is automatically retrieved, as the Chart object from the getAccount().getChartOfAccounts() call will be, it will not be null. However, calling getAccount().getChartOfAccounts().getFinancialObject() will throw an error if the chart does not exist. The problem is that the system will return a proxy object created by OJB, which is not null, but also can not be used. OJB will attempt to load the object from the database upon use of the object. In any case where the object was retrieved from the database automatically, you must use a call like:

org.kuali.rice.kns.util.ObjectUtils.isNotNull( getAccount().getChartOfAccounts() )

which performs the proper checks knowing how to resolve the OJB proxy class.

 Scopes of Variables

Java has three kinds of variables:

...

  • Use a variable for a single purpose;
  • Keep the life time of variables as short as possible;
  • Declare local variables immediately before their use;
  • Avoid instance variables if the enclosing object can be accesses by multiple threads concurrently.

Configurability

Panel

Levy's Eighth Law: No amount of genius can overcome a preoccupation with detail.

...

  • All business logic should be placed in stateless services.
  • A client should use an aggregate of services, rather than re-implementing the related logic.
  • If an existing service is unable and the required functionalities are out of scope of the client, implement them with an additional service class which utilizes existing services.
  • A client should have certain liberties to determine what kinds of things would be included in the results of a service.

Application Architecture and Design Patterns

Component-based multi-tier application architectures have been invented and applied for a long time. Those architectures can greatly help us organizing the application components and promoting their reusability by defining layers of responsibilities.

...

Within each layer, there might be one or more design patterns applied to implement corresponding component. Four design patterns will be introduced here.

Business Object/Transfer Object

(Avoid complex business logics, rather than put them into business service)

A business process manages business data and business logic/rules. Business data usually Business Objects is used to separate business data and logic.

Application Service

(Avoid direct external resource access)

Data Access Object

(Database, file system and other external data sources)

Model-View-Controller

Suggestions:

  • 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.

...