JaVa
   

Development Lifecycle

The development lifecycle of a component-based service, shown in Screenshot, is similar to the lifecycle of any software system. It goes through the following phases: requirements analysis, design, implementation, quality assurance, and maintenance.

Java Click To expand
Screenshot: Development lifecycle of a component-based service.

Requirements Analysis

During the requirements analysis phase of component-based service development, an entire system's functional and nonfunctional requirements are defined. The functional requirements relate to the way the component-based service will fulfill the business need. Credit-card validation is an example of a functional requirement. Nonfunctional requirements are technical in nature. A requirement that states that a response must be returned to the consumer within two seconds is an example of a nonfunctional requirement. Techniques such as looking at existing documentation and conducting user interviews are used to construct a set of artifacts that constitute the requirements for the system.

Functional Requirements

Developing the functional requirements for a service is different from developing functional requirements for a single app. Services support multiple apps. Therefore, services designed and developed for a single app are not likely to meet the needs of other apps that require the same or similar functions. How do we design services when we don't know what apps will use them? The answer is to develop a business architecture—a description of the business the organization performs—which consists of documents and models. To a service developer, the most valuable part of the business architecture is the functional decomposition of the business into different subject areas. Each subject area describes a single part of the organization and the functions the area contains. For example, a bank has checking-account, savings-account, and customer functions. Services are coarse-grained structures that should map not to a single app but to the functional areas of the business. This mapping increases the services' reusability, because a service that maps to the business rather than an app is more likely to support the requirements of multiple apps. When designing a service, it's tempting to map services to existing legacy systems. For instance, if a banking system performs both checking and savings-account functions, many service designers will implement a banking-system service. This is wrong for two reasons. First, the banking system performs two logical functions that should be split into two services, one each for checking and savings. Also, the service is named for a system, not for the functional area the service supports. The advantage of this is that each service uses the banking system as a resource for executing service requests, but if the banking system is ever replaced, service consumers may not have to be updated, because the services map to a function, not a system. Once the business architecture is created, a conceptual service model is derived from it. Designing services is usually not a green-field exercise. The conceptual service model contains areas of the business implemented in services. It also focuses more on implementation aspects of the services but does not assume a particular implementation technology. The conceptual service model provides the basis for designing service boundaries and interfaces. However, in true green-field development, a set of artifacts should be created to identify the functionality a service should support. Service development is usually performed within the context of an app, which drives the parts of the conceptual service model to be implemented. Some of the interfaces will be needed and others will not (yet). The app requirements drive the implementation of small pieces of the component service model within the enterprise vision of a services layer. To identify app requirements, the requirements analyst creates a set of artifacts from existing documentation and user interviews that describes the app to be built. As Screenshot shows, these artifacts include a feature list, use cases, quality scenarios, and an object model.

Java Click To expand
Screenshot: The requirements analyst creates a set of artifacts that describes the app.

The feature list contains all the features the system must support. The use cases define the ways users will exercise those features. The object model describes the structure of the business process. The techniques used to elicit the functional requirements for an app are necessary and are well documented elsewhere and thus are not detailed here.

Along with the functional requirements for a system, the nonfunctional aspects must also be defined, to determine the technical level of service the system will support.

Nonfunctional Requirements

A system's nonfunctional requirements are defined in the quality scenarios. Just as it is necessary to make the functional requirements concrete by developing use cases, it is necessary to make the quality requirements concrete. It is not sufficient for a quality scenario to state that the system should be "highly reusable." A specific reusability requirement would state that the "credit-card validation service will be reused by system X." Another example is when a performance requirement is stated in reference to an overall latency requirement but not in terms of usage patterns, scalability, or the impact on system usability (Clements and Northrop 2002).

Another term for the set of nonfunctional requirements a service supports at runtime is quality of service (QoS). Other nonfunctional requirements not evident at runtime, such as maintainability and reusability, are not part of QoS. Each component-based service in service-oriented architecture supports a specific quality of service (QoS) level. Simply defining the service's functional requirements may not make the service usable if it does not support the quality attributes necessary to deliver a fully functioning system. Although it can be difficult to estimate the a system's quality requirements, the exercise will greatly enhance the designer's knowledge of expectations for the system. Defining the quality requirements as rigorously as possible greatly reduces the risk that the system will not satisfy them (Clements and Northrop 2002). In modern component-based development, it is especially necessary to pay attention to nonfunctional requirements such as performance, security, modifiability, reusability, integrability, testability, availability, reliability, and portability.

Once the nonfunctional quality of service attributes have been identified, they can be described using Web Services Endpoint Language (WSEL). WSEL allows a service provider to describe things such as QoS and security characteristics.

Performance

The performance-quality attribute requirement must be defined during the requirements analysis phase. Performance is the responsiveness of the system, measured in the time required to execute some function. Some of the questions that must be answered to design the system correctly include

A component-based system uses the network to communicate between components. Any performance requirement must be looked at closely to determine if the system can meet it. When a performance requirement cannot be met, the designer should consider several strategies:

If actual performance will not meet the requirement for a service request, it might be possible to make the request asynchronous. An asynchronous request returns control immediately to the service consumer after the consumer sends the request to the provider. The consumer continues processing and does not wait for the request to return. The consumer gets the results of the request in one of two ways: by checking periodically to see if the request has executed or by being notified when the results are ready. If a consumer needs to know immediately when the results are ready, the service provider will interrupt the consumer and give the consumer the results of the service request. Making a request asynchronous is appropriate especially if the service consumer does not require a response. For instance, a consumer who calls the AddCustomer method in a customer service might not require the add customer to happen immediately. The information could be passed in, and control could be immediately given back to the consumer. The add customer transaction would happen at a later time, and the consumer could optionally check the status of the transaction periodically to see if it has executed. In general, to improve consumer performance, any requests that do not return a response should execute asynchronously. Scalability is also related to the system's ability to respond to increasing load. All components execute in a component execution environment such as J2EE. The design should take full advantage of the component execution environment (CEE) (Herzum 1998), most of which support clustering. This allows the component execution environment to create components on multiple machines, to load-balance their requests across multiple component instances. As discussed in the previous chapter, a proxy can cache service data, such as reference tables. Robust proxy implementations can cache service results so that subsequent service requests to the proxy can return data cached in the proxy rather than making a network call. In addition, a proxy can execute methods that do not require the state of the service. Rather than incurring a network call, methods such as standard calculations can be made in a local proxy. This approach is problematic, because new proxies need to be redistributed every time the service changes. The best way to implement a proxy is to make it dynamically downloadable. In other words, when a consumer needs to access a service, it downloads a new proxy from a server. The proxy should also have a lease attached to it, such that when the lease expires, the service consumer must download another proxy from the server. This eliminates the problems that occur when services change and proxies are out of date.

When it comes to performance, the best strategy is "Make it run, make it right, make it fast, make it small" (Coplien and Beck 1996). The techniques outlined in this chapter and other performance-enhancing techniques should not cause the designer to sacrifice other quality attributes of the system in the name of improving performance.

Security

The security quality attribute must also be defined during this phase. Some of the questions that must be answered to design the system correctly as it relates to security include

If the system is highly critical, such as electronic control, security is of high concern. Even if the system is not critical but a security breach would cost a large amount of money, time, or resources, it is also of high concern. Creating or adopting specialized components for authorization, using secure transports, and implementing sound security policy can address security. For more on security, see .

Modifiability

A system's modifiability refers to its receptiveness to change. These questions will help identify how modifiable a system should be:

The cost of system development is not the only important factor. This cost is low compared to the cost of the system over its lifetime. In many organizations, the budget for app maintenance is larger than for software development. Unless the system has a short lifecycle, building modifiability into it should be a top priority, to reduce the cost of maintenance. Several factors determine modifiability:

Reusability

Reusability is the ability of a software asset to be used in a different app context without modification. A system's reusability must be determined, because a highly reusable system is more expensive to build and will necessarily be more generic and cover more functionality than necessary for the specific app. Some questions to ask in relation to the system's reusability:

An organization can take the following steps to increase reusability.

Establish a Product Line for Building Services

A product line (Clements and Northrop 2002) consists of a set of assets that supports the creation of a specific type of software artifact. Product lines within an organization consist of software assets, execution platforms, processes, and organizations centered on creating a particular class of software system. A product line for reusing component-based services should be considered, due to the large return on investment when multiple services use the same core assets. By establishing a product line, not only will the services themselves be reused, but core assets for building component-based services are reused as well. To build the services product line, the commonalities and variations between services must be identified. The product line assets are implemented based on the commonalities between services and must support all variations between services. In other words, they must be able to support all the functional and non-functional requirements of the services built using the product line's core assets. Creating of a product line involves mining, buying, and building assets for creating new services. The common core assets for creating component-based services are reused by each new service built using those assets, greatly improving overall reusability. For instance, if a product line's core assets consist of a persistence framework, an event framework, a set of project management templates, and a J2EE execution platform, those assets are reused by every component-based service built on that product line. Implementating new services on the product line will also identify requirements it does not support and must be upgraded to support. A downside to upgrading product lines is that it may be necessary to refactor older component-based services to run on the new product line. Not only will the product line share reusable core assets, it will support a common set of nonfunctional quality attributes for all services. Each service developed using the product line's core assets inherits its level of security, modifiability, and so on. By instituting a product line for services, an organization can realize many benefits, including better productivity, improved time to market, increased project predictability, better quality, and better return on investment. When initiating a product line for service development, the organization should identify common assets for inclusion in the product line. These common assets include

There are two additional ways to improve reusability in services: by improving modularity and modifiability.

Improve Modularity

In addition to the reusability of the assets for building services, the services themselves are obvious candidates for reuse. Therefore, the modularity and interface definitions of the component-based services are critical to their potential for reuse. In other words, the more modular a component-based services is, the more likely it will be reused.

In addition to reusing the service in its entirety, individual layers can be reused within other services. For instance, if a service uses a data access layer for accessing a legacy system, this can be designed for reuse in other services that access the same legacy system.

Improve Modifiability

A service's modifiability is also important to determine its reusability. If reusing a component requires it to undergo change, the magnitude of the effort to change the component must be small. The original service designer cannot fully predict all possible requirements for future apps. Therefore, the service will need to be updated from time to time. To reuse the service effectively, the effort involved in modifying the service must be less than the effort involved in writing a new service. The modifiability of the core assets themselves is also of critical importance. They will support the system's current set of functional and nonfunctional requirements. When those requirements change, the core assets are likely to change as well. Therefore, they must be highly modifiable. The downside is that when the core asset changes, the changes ripple through each service built using that asset. Therefore, core assets must be built such that changes and improvements to them do not have devastating consequences for other component-based services that use them.

Integrability

A component's integrability is its ability to communicate with other systems. By definition, service-oriented architecture consists of highly interoperable services. Some questions to ask during requirements analysis include

To improve integrability:

Testability

A service's testability relates directly to its overall quality. A service that is not easily tested will be a low-quality service. The requirements for testability are

The architecture should support a level of testability that allows the component-based service to be certified for use. This is especially difficult in service-oriented environments, because the organization that certifies the service may not have access to the service consumer. For instance, the consumer could be on the other side of the Internet and not part of the organization that developed the service. Therefore, the testability of the service contract, the objects that make up the service, and the testing of component interfaces are extremely important. Also, even though services are certified individually, they may require retesting when assembled into service federations that support some orchestrated business process.

One of the downsides of a reusable product line for service creation is that a change in a core asset, such as a framework, may require all the services built using that framework to be regression tested and recertified. The extent of reusable code can sometimes have a negative impact on the effort required to test the impact of this change. However, it is almost always preferable to leverage existing assets than to build new ones from scratch.

Availability

A system's availability must be established. Availability measures the time between failures and how quickly the system is able to resume operation after a failure (Bass 1998). In addition to system failures that produce downtime, we also include normal maintenance operations that require downtime. Some questions to ask about availability include

A system's batch cycles, upgrades, and configuration changes must support the availability expectation. If a batch cycle requires two hours to run but the system is expected to be available 23 hours per day, either the requirement must be changed or the batch process must perform better. If a configuration change is made to the service, does it require restarting the service? If the service is currently in the middle of an orchestrated process, how will the change affect processes that are running? A robust architecture will allow runtime configuration changes and mitigate the impact of those changes on processes currently being executed.

Another aspect to availability is the way service consumers are notified that the service is not available. Do your service consumers simply time out, or will you provide a "Not Available" message? In some implementations, an endpoint description can provide QoS information, such as availability. The QoS description of the endpoint provides a proactive way to inform consumers about the service's availability.

Reliability

The system's reliability must be established. Reliability has to do with the system's capability to maintain a level of performance for a stated period. Questions related to determining reliability include

Reliability is related to several factors that include the architecture, design, and implementation. Reliability can be enhanced through the configuration of component-based services for rollover in case of hardware failures. In the event of a software or hardware failure, can the system be easily recovered? Does a failure result in an incorrect system state? A highly reliable and correct system will not only guard against system failure but will be easily recoverable when a failure does occur.

Portability

A system's portability relates to its ability to run on multiple platforms. Several questions to ask related to how portable to make the system include

To enhance an app's portability, a separation layer can be developed to create an interface for the service to use, rather than making the interface a feature of the service platform. This is accomplished by creating an adapter that adapts the generic interface the service expects to the particular implementation of the feature the platform provides. For instance, consider the creation of a logging adapter that provides a generic interface for logging to the service and logs messages using the Log4J library. If the library of choice changes to a newer version or a completely different implementation, the service will not change—only the adapter must change.

Another factor affecting system portability is the component execution environment. Some commercial component-execution environments are built to be more portable than others. For instance, a component built for the Microsoft .NET platform can run only on a .NET platform provided by Microsoft. A component built using the J2EE platform can run on J2EE platforms provided by a large number of vendors.


JaVa
   
Comments