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