In a large project, designing for performance often turns out to be a chicken or egg situation. In a J2EE project, this is even more evident. Typically when business and functional requirements are handed down to the technical team, the first step is to map the functional subsystems into software components, and then to hand out the design of those components to respective team leads for design and implementation. This is part of the responsibilities of the project architect. At this stage in development, the onus is on the architect to make decisions on identifying potential bottlenecks in the system and recommending alternatives based on standard architecture patterns and guidelines.
In an ideal project, the design of each module involves taking all the performance characteristics into consideration and building out the functionality. If a formal design and development cycle is followed, the team may be able, even enforced, to take care of performance issues early on in the project. However, the luxury of doing this is often not there. Typically, most projects are driven by an urgency to demonstrate the functionality of the system to the client. Although well-coordinated teams design and develop with performance criteria in mind, focusing on performance issues puts the team in danger of missing the boat.
One of the reasons such projects lead to disaster is that often a technical proof-of-concept initiative that's undertaken at the beginning of the project ends up creating the framework for the full solution. A common point of confusion between different stages of a project is the proof of concept (POC) and the prototype. A proof of concept is geared toward demonstrating functionality. A prototype should be an implementation of the full solution that tests minimal functionality. A proof of concept doesn't need to consider performance characteristics, while a prototype should tweak out performance characteristics before the full functionality is implemented.
In a J2EE project, the architecture of the full solution needs to deal with the issues of load balancing across different hardware machines: integration with legacy systems; decisions on using the best technology such as EJBs versus JDO, application server clustering, etc. On the other hand, a POC needs to primarily deal with deployment in a minimal environment to demonstrate maximum functionality.
The support provided by the J2EE platform to implement different stages and environments is quite good. Application servers allow the same code base to be deployed in different environments with well-defined migration paths. For example, you can deploy multiple applications in the same instance of the server, multiple servers on the same machine, or multiple servers on different machines. If you've designed the code base correctly, the migration from one to the other should be well defined. While a POC typically has "throwaway code," designing with migration in mind facilitates at least some degree of reuse.
My current client has opted to invest both capital and resources into a well-defined POC. I think this is a worthwhile investment. Our project team is well aware of the life cycle of the POC, and the compromises we are making in terms of performance, the different architectural configurations, and the different issues involved in migration. This becomes even more crucial when integrating new third-party tools into the architecture. In our case, this involves a J2EE-compliant business rules engine and a workflow engine.
Organizations that decide to invest in such initiatives early on in the project end up working smarter and not harder. J2EE offers the capability to achieve this from a platform perspective as well as in the form of well-documented guidelines and patterns.
Ajit Sagar is the J2EE editor of JDJ and the founding editor of XML-Journal. He is a senior technical architect with Infosys Technologies, a leading global consulting and IT services organization, and is well-versed in Java, Web, and XML technologies.