The Pursuit of Perfection Should Never Destroy the Good Enough
If Java is truly to replace COBOL as an enterprise-wide standard, then it needs to be as easy to write as COBOL and as fast a C++ at runtime. In my experience with all of these implementations, I have found that Java at the command level is clearly easier to learn than C++, however, Java the platform is complicated. As far as runtime performance, only through a combination of application server clustering and application construct performance tuning can Java expect to approach the runtime performance of C++.
This article attempts to address the latter issue by developing criteria for assembling applications. Part of that criterion is to promote as a project norm that simply identifying a design pattern or framework that satisfies a requirement is not good enough. The candidate pattern should also address non-functional requirements, such as, performance, protocol independence, etc.
In my experience, object designers and programmers, typically, are more obsessed with elegance or adherence to good design principles, than ensuring that an application construct performs well. Sometimes professionals need to be reminded that they are only building business applications, and that the pursuit of perfection should never destroy the good enough, especially if a solution performs well and is robust.
Technical Architecture alignment with “The Business”
Over the years, I have tried to stay in touch with C-level executives regarding technology, as well as the developer community were I spend most of my time.
Recently, I did a stint with a cable shopping channel where I was responsible for helping move the organization from a mainframe-oriented IBM MVS COBOL shop to a modern zSeries, J2EE-based organization with aspirations of establishing a SOA.
In my minds eye, the new platform represented three distinct hurdles for this organization:
- Transition to object-oriented design, including UML, from a procedural approach.
- Administration and development of applications using WebSphere on the zSeries as opposed to an IBM MVS COBOL environment
- Moving from a client-server to service-oriented architecture (see Develop A Service-Oriented Architecture Methodology, WebSphere Advisor 2006 http://websphereadvisor.com/doc/17991)
Early on, I was debriefed by the chief architect and told that consultants, such as, the likes of where I had come from, come into an organization and make recommendations, based on J2EE best practice and frameworks. He indicated that the company had unique application performance requirements specifically regarding customer service reps “talk time.” Talk time is essentially managerial speak for the time spent by a CSR booking an order over the phone while interacting with an Enterprise Information System. Importantly, an increase in application performance and response time would reduce talk time and increase the ability to take orders. At the C-level, technology is really is all about performance and costs.
He further commented that J2EE reference architecture that may have worked in other organizations would not work here. Over time, I realized that this assessment was based on a finite amount of J2EE experience within the organization and a recent hapless attempt at converting COBOL application to SOA using SOAP on the zSeries. Still, there is a certain amount of truth, that for business applications performance and costs are paramount.
Performance, Scalability and Reliability
Although, the experienced architect knows that application performance does not just increase a users' satisfaction with their online experience or meet a Service Level Agreement (SLA). In reality, performance, scalability and reliability are all related. That is, reliability impacts performance statistics, and performance is directly related to scalability and throughput. For example, intermittent exception errors emanating from JDBC libraries must be handled or eliminated to improve overall Web performance. In many cases, the problems that cause poor performance can also cause a program to stop functioning. Thus, fixing badly behaving code constructs is part of enhancing performance. At the same time, architects know there are advantages to object reuse, either through design patterns or frameworks.
As I started to reflect on the task in front of me, it appeared that although daunting it made a lot of technical and business sense. The object was to select a particular design pattern or framework only when it was appropriate for a “processing style.” Gartner more or less defines processing styles as an application with distinct processing requirements. Essentially, the recommended reference architecture needed to be optimized for a particular processing style. More specifically, I was to specify, using UML, performance-oriented design patterns.
Reference Architecture Revisited
It is important to point out that a Reference Architecture is a set of design patterns proven for use in a particular business or technical context. In a mature organization, these artifacts are usually harvested from previous projects. The key to a well-defined Reference Architecture is well-defined patterns. Some architects might take umbrage in referring to Struts or Spring Workflow as a pattern, but a software pattern, by definition, is an abstract concept. A pattern should be fungible, amorphous and not implementation dependant. In reality, business applications are a combination of frameworks and patterns.
Design Patterns Revisited
Design Patterns represent recurring solutions to software development problems within a particular context. Patterns and frameworks both facilitate reuse by capturing successful software development strategies. The primary difference is that frameworks focus on reuse of concrete designs, algorithms, and implementations in a particular programming language. In contrast, patterns focus on reuse of abstract designs and software micro-architectures.
In the seminal book on patterns called simply Design Patterns, Gamma, Helm, Johnson and Vlissides' state that by using patterns in systems modeling helps keep the design standardized. For example, it is better to have a standard mechanism for say creating a JMS producer rather than one that appears more efficient than the other, but different. Hopefully over time the more efficient construct prevails. Again, the pursuit of perfection should never destroy the good enough. Typically, patterns are captured and documented in a sufficiently descriptive manner in UML, so that they can be referred to for future use. Documenting patterns is one way that you can reuse and possibly share the information that you have learned about how it is best to solve a specific program design problem.
Design Patterns and Frameworks by Processing Style
The matrix identifies appropriate design patterns and frameworks contained within a logical tier for a particular processing style. For example, the command pattern was selected as the appropriate controller pattern for the Enterprise-wide OLTP application, since the application was designed to integrate with XML/XSLT clients and not rely on just JSP for view behavior, as is the case with Struts. Struts, is, essentially, an MVC pattern that implements the JSP Model 2 Architecture. The matrix was an attempt at identifying some of the major processing styles in the organization, but it is in no way conclusive at the enterprise-level.
One of the main differences in these “architectures” is related to using Spring versus EJB for constructing services. Spring is an implementation and or framework, while EJB 3.0 is an implementation and architecture, which requires an EJB container. EJB specifically addresses the development of distributed components; Spring does not really emphasize this feature.
Large Grained Object Reference Architecture
The enterprise-wide intranet OLTP application processing can be depicted as an MVC implementation. Choice of the command pattern over an implementation, such as, Struts had to do with the need to serve ubiquitous clients.
The fundamental choice between being a Spring-based organization and one that relies on EJB as the matrix implies is not mutually exclusive. There are ways of to integrate both technologies to take advantage of their relative strengths. Many organizations that support application servers that include EJB containers (i.e. WebSphere, WebLogic) view EJB as a complex, heavyweight solution and do not rely on them. These organizations prefer using more lightweight frameworks like Spring (i.e. Prototype, Singleton or Session) beans in conjunction with Hibernate. In some cases, though, they might want to rely on Message Driven Beans, which require an EJB container, for asynchronous messaging, because they may already be using IBM MQSeries for there underlying messaging service.
In the final analysis, a solid architecture, one that is worth reusing, needs to perform well, be robust and be scalable, based on the service level requirements. The objective of the (application) architect is to assemble the patterns and frameworks that accomplish that goal. In general, though, consistence is more important than adherence to best practices and standards. Although, adopting best practices and following standards as a strategy will eventually lead to consistence.
Other related articles by the author:
Develop A Service-Oriented Architecture Methodology, WebSphere Advisor 2006
Design for EJB Message-Driven Beans with UML Use Cases, Enterprise Architect, Winter 2003
Designing Performance Testing Metrics into Highly Distributed J2EE Applications, TheServerSide.com, 2/04
Frank Teti is an industry analyst and principal architect. He can be reached at email@example.com.