Team LiB   Previous Section   Next Section

What Are Horizontal Services?

For just about all enterprise applications, there are common components and services that you will find present. These services typically are lower level and are used by other components that make up the overall application. The terms component and service are being used interchangeably here, although there can be some slight distinctions made.

Generally speaking, you can conceptually split any application into a set of horizontal and vertical services. For smaller applications, this split may be just an abstract idea and not actually be separated in the source code. With larger applications, this might be the best way to structure the software because it allows for more reuse and parallel development.

The main difference between a horizontal and a vertical service is that a vertical service normally will have dependencies on one or more horizontal services, but a horizontal service should never have a dependency on a vertical. Figure 21.1 shows how a typical enterprise application can be split into vertical and horizontal components.

Figure 21.1. A typical application can be separated into horizontal and vertical components.

graphics/21fig01.gif

The vertical components usually encapsulate the business and application logic that is core to the software solution, while the horizontal services are designed to provide common services for the application. Table 21.1 describes some of the more common horizontal services for an enterprise application.

Table 21.1. Some of the More Common Horizontal Services

Name

Description

Note

Logging Service

Used to log local and distributed debugging, general information, warnings, and error messages.

There are some third-party solutions, but sometimes it's built by the development group within an organization.

Email Support

To allow an application to send and possibly receive e-mails.

Most EJB servers have support for e-mail through the JavaMail API.

Messaging

To send synchronous and asynchronous messages from one component or application to another.

Provided by all compliant EJB servers. You still might want to build an application API on top of it.

Naming Service

To locate resources or references to references for distributed components.

Provided by all compliant EJB servers.

Properties Service

To locate configuration information for components.

Some groups build a service that can provide configuration information for a component. Others will bundle the properties along with the components. JNDI can also be used for this service.

Persistence Service

To provide an underlying infrastructure for creating, querying, updating, and deleting (CRUD) your application's data.

If using BMP in entity beans, you might build a small framework to handle the database interaction. With CMP, this is normally handled through the EJB deployment descriptor. You might also use a third-party ORM such as TOPLink.

Security

To help control access to the application resources and to protect information that is passed between components from being intercepted by unauthorized entities. Some security service frameworks also can help prevent denial of service attacks, which have become popular recently.

Infrastructure is provided for by EJB, JAAS, and an SPI. You will still need to build on this framework for your particular needs. Each application may have different security needs. Never take security lightly.

Not all of these horizontal services will be used by every application. Some make sense for a particular application and others do not. Every application is somewhat unique and can have a different set of requirements and constraints. You don't need to build all of these just for the sake of building them. Make sure you build only what you need for the current iteration of your development cycle.

Why Are Horizontal Services Needed?

Whether you use the concept of horizontal services just for logical purposes during design, or whether you structure your software along these lines, you're able to assign responsibility more cohesively. A cohesive component is one that contains a set of interfaces that are grouped logically and make intuitive sense together. Together, the public interfaces for a component provide one or more related services for a client. There are no hard and fast rules to determine what makes the best component interface, although some interface operations make sense together and others don't.

So, the question still remains. What's the benefit that you gain by developing a set of horizontal services outside the application, rather than designing these services into the application directly? The following list describes some of the more obvious benefits:

  • Reduces redundancy in your application

  • Helps with maintenance

  • Allows for best of breed

Each of these benefits is an admirable goal in itself when building any software application, but when building an application as complex as a distributed enterprise application, you should strive for all of them.

By decoupling the horizontal services from the actual application logic, you achieve all three goals listed with just a little bit of up-front investment in proper design. We'll elaborate on each benefit briefly in the following sections.

Reduces Redundancy

How many times have you found yourself making a change to your application based on some new requirement and you realize that you need to make the change in more than one place? The answer for most of us is too often. Redundant code in your application is very inefficient. First you have to spend time writing the same code several times rather than in a single place and if anything changes, you have to make changes in every location. Most of the time, this can be a sign that an adequate design was not conducted. Having redundant code in your application should be avoided like the plague. It will come back to bite you every time.

Let's think about a simple example. Suppose we have several components that need to write out debugging information. In the interest of time, let's say that we use something like this in every component that needs to log some debugging information:

System.out.println( "Some debugging info" ); 

Later, we realize that we need to write log messages to a file instead. Every component that had a println method for printing the logging information would have to be modified. If the product had already been put through a quality assurance (QA) cycle, then all affected code would have to have regression testing. Now suppose that instead we took more time during the design and came up with a component called Logger. The Logger component could have a public method called logMessage that took a message string. Listing 21.1 shows a small example of what this component might look like.

Listing 21.1 Code Fragment Showing an Example Logger Component
public class Logger {

  public Logger() {
    super(); 
  } 

  public void logMessage( String msg ) {
    System.out.println( msg ); 
  } 
} 

Now, if every component that needed to print out log information used this component rather than calling the println directly, only the logMessage method would need to change if we had to log to a file instead. Notice that all the clients that used this component would not have to change. They can continue to call the logMessage method as before, and the Logger object would have the details of how the logging is performed.

By moving code that is repeated in several places out to a single component, you are able to prevent some redundancy that would normally rear its ugly head. The manner in which each vertical component invokes messages on a horizontal service is through its public interfaces. We'll see more about the public interfaces later in this chapter.

Helps with Maintenance

This benefit has much to do with the previous example. By isolating the location of where changes needed to be made, you help make the application more maintainable. This is pretty important because we all know that change is inevitable and when you are the developer that has to make the change, you will appreciate a more maintainable application. When doing software design for an application, it's extremely important that you ask yourself, "How is this design affected if this or that changes?". An application that isn't affected greatly by change is said to be resilient. You should always strive to build a resilient application, and this starts during the analysis and design phase, not during construction.

Allows for Best of Breed

By decoupling a horizontal service from the vertical components of an application, you increase the likelihood of being able to plug in commercially available components, thus decreasing development time and also possibly increasing performance and maintainability.

Think back to the Logger example. We might be able to find a logging component already built by a third party and not have to build our own. This saves on development time and decreases the likelihood of introducing defects. If the third-party product has problems or is too slow, you can just go find another compatible product and plug it in with little work.

There is still a need to write some code that integrates your horizontal services with a third-party solution. You often don't just want to hook the third-party product in directly without having an API layer of your own. Remember, we will always have some dependencies on third-party components or services. The goal should be to limit those to very isolated places and know what these places are so that you can be prepared when change happens. During design, you should always consider what might change on the next version and plan accordingly.

This benefit is also one of the goals of the EJB architecture. If you have the opportunity to select from different vendors for a component or set of components, you usually increase the flexibility and portability of the application.

    Team LiB   Previous Section   Next Section