This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
visible to the software’s developers) include maintainability, flexibility, portability, reusability, readability, scalability, testability, and understandability. The ities that affect the software’s external quality (visible to the customer) include usability, reliability, adaptability, and integrity, as well as correctness, accuracy, efficiency, and robustness.4 Some of these characteristics overlap, but all have different shades of meaning that are desired more in some cases and less in others. The attempt to maximize certain characteristics invariably conflicts with the attempt to maximize others. Figure 1 presents a summary of the ways in which external quality characteristics affect each other. These characteristics will be prioritized differently on different projects, which means the software quality target is always changing. Finding an optimal solution from a set of competing, changing objectives is challenging, but that’s part of what makes software development a true engineering discipline. From product quality to project quality When software people refer to quality, we usually refer to the quality of the software product we are producing. From a management perspective, however, customers also have requirements for projects. I think it’s reasonable to draw an analogy from products to projects, conceiving project quality as conformance to requirements, both stated and implied. Customers’ functional requirements for projects draw from a small number of possible attributes, namely schedule, resources, cost, and quality of the product March/April 2002
IEEE SOFTWARE
5
Correctness
Construction: Andy Hunt and Dave Thomas, Pragmatic Programmers, {Andy, Dave}@pragmaticprogrammer.com
Pauline Hosillos Art Director Toni Van Buskirk Cover Illustration Dirk Hagner
Advertising Assistant Debbie Sims
■
■
■
■
CONTRIBUTING EDITORS
Greg Goth, Denise Hurst, Gil Shif, Keri Schreiner, and Margaret Weatherford
■ Editorial: All submissions are subject to editing for clarity, style, and space. Unless otherwise stated, bylined articles and departments, as well as product and service descriptions, reflect the author’s or firm’s opinion. Inclusion in IEEE Software does not necessarily constitute endorsement by the IEEE or the IEEE Computer Society. To Submit: Send 2 electronic versions (1 word-processed and 1 postscript or PDF) of articles to Magazine Assistant, IEEE Software, 10662 Los Vaqueros Circle, PO Box 3014, Los Alamitos, CA 90720-1314; [email protected]. Articles must be original and not exceed 5,400 words including figures and tables, which count for 200 words each.
6
IEEE SOFTWARE
March/April 2002
⇑
⇑
⇑
⇑ ⇓
⇑
Robustness
⇓
⇑
⇓
⇑
⇓
⇓
produced. In some cases, a customer might prioritize cost higher—in others, schedule or product quality. Additionally, project quality includes nonfunctional requirements such as
Publisher Angela Burgess
Membership/Circulation Marketing Manager Georgann Carter
⇓
⇓
⇓
⇑
⇑
⇓
⇓
⇓
⇑
⇓
⇑
⇑
⇓
⇑
⇓
⇑
⇓
⇑
⇓ Hurts
Figure 1. Interactions between product quality external characteristics.
Executive Director David Hennage
Assistant Publisher Dick Price
⇑
⇓
⇑ Helps
Technical Illustrator Alex Torres Production Artist Carmen Flores-Garvey
How focusing on the factor below affects the factor to the right
Co rre ctn es s Us ab ili ty
FROM THE EDITOR
■
Efficiency: Minimal use of schedule, budget, and staff to deliver a particular software product. Flexibility: The extent to which the project can be modified to deliver software other than that for which the project was originally intended or to respond to changes in project goals. Improvability: The degree to which project experiences can be fed back into the project to improve project performance. Predictability: The degree to which a project’s cost, schedule, and product quality outcomes can be forecast in advance. Repeatability: The degree to which the project after the current project can be conducted using practices similar to those used on the current project. Robustness: The degree to which the project will continue to function in the presence of stressful environmental conditions.
■
■
Sustainability: The duration for which a project can continue using its current practices. Visibility: The ability of a customer to accurately determine project status and progress.
These project characteristics interplay with each other just as the software quality attributes do. Figure 2 shows the interactions. In addition to the interactions shown in Figure 2, some of these project quality characteristics tend to support or undermine the various product characteristics summarized in Figure 1. Different projects have different priorities among efficiency, flexibility, improvability, and the other characteristics shown in Figure 2. An established business might place high values on efficiency, predictability, improvability, and repeatability. A start-up company might place a higher value on robustness and visibility; it might not value sustainability and repeatability at all. This suggests that there isn’t one best definition of project quality for all projects; the best definition depends on the project’s consumers and those consumers’ specific project requirements.
FROM THE EDITOR
Efficiency
Ef fic ie nc y Fl ex ib ili ty Im pr ov ab ili ty Pr ed ict ab ili ty Re pe at ab ili ty Ro bu stn es s Su sta in ab ili ty Vi sib ili ty
How focusing on the factor below affects the factor to the right
⇑
⇓
Flexibility
⇑
Improvability
⇑
Predictability
⇑
⇓
Repeatability
⇓
⇓
Robustness
⇓
⇑
⇓ ⇓ ⇑
⇑
⇑
⇑
⇑
⇑
⇑ Helps
⇑
⇓ ⇑
⇓ ⇑ ⇑
⇑
⇑
⇑
⇑
⇓
Sustainability Visibility
EDITOR IN CHIEF: Steve McConnell 10662 Los Vaqueros Circle Los Alamitos, CA 90720-1314 [email protected]
⇑
⇑
⇑
⇑
⇑ ⇑
⇑ ⇑ ⇑
⇑
⇓ Hurts
Figure 2. Interactions between project quality characteristics.
Real engineering One difference between a craftsman and an engineer is that a craftsman defines quality on his own terms, whereas an engineer defines quality through his customers’ eyes. The craftsman settles into a way of working that suits him personally, while the engineer adapts his approach on each project to best satisfy his customer’s requirements. Software engineering purists argue that software should always be produced to the highest level of quality, by which they mean the highest levels of product quality. End-user requirements certainly should be considered, but the organization that builds and sells the software is another consumer whose requirements must be taken into account. The product characteristics that constitute quality to the end user do not necessarily satisfy the software-developing organization’s project quality requirements. As Deming pointed out in Out of the Crisis, different consumers can have different definitions of quality for the same product, and this applies as much to project quality as it does to product quality. The project
A S S O C I AT E E D I T O R S I N C H I E F
Design: Maarten Boasson, Quaerendo Invenietis [email protected] Construction: Terry Bollinger, Mitre Corp. [email protected] Requirements: Christof Ebert, Alcatel Telecom [email protected] Management: Ann Miller, University of Missouri, Rolla [email protected] Quality: Jeffrey Voas, Cigital [email protected] Experience Reports: Wolfgang Strigel, Software Productivity Center; [email protected] EDITORIAL BOARD
⇑ ⇑
EDITOR IN CHIEF EMERITUS: Alan M. Davis, Omni-Vista
team, manager, and sponsoring organization can all be considered consumers of a project. A manager might consider a project to have high quality if it provides good visibility, robustness, and repeatability. The project team might value efficiency, improvability, and sustainability. The sponsoring organization might value predictability and flexibility. A manager who factors product quality into the project plans but ignores project goals takes an abridged view of software quality. One hallmark of engineering work is the constant balancing of trade-offs. With the extensive trade-off decisions required to balance both software product attributes and software project goals, software personnel have abundant opportunities to hone their engineering skills in this area.
Don Bagert, Texas Tech University Richard Fairley, Oregon Graduate Institute Martin Fowler, ThoughtWorks Robert Glass, Computing Trends Andy Hunt, Pragmatic Programmers Warren Keuffel, independent consultant Brian Lawrence, Coyote Valley Software Karen Mackey, Cisco Systems Deependra Moitra, Lucent Technologies, India Don Reifer, Reifer Consultants Suzanne Robertson, Atlantic Systems Guild Dave Thomas, Pragmatic Programmers INDUSTRY ADVISORY BOARD
Robert Cochran, Catalyst Software (chair) Annie Kuntzmann-Combelles, Q-Labs Enrique Draier, PSINet Eric Horvitz, Microsoft Research David Hsiao, Cisco Systems Takaya Ishida, Mitsubishi Electric Corp. Dehua Ju, ASTI Shanghai Donna Kasperson, Science Applications International Pavle Knaflic, Hermes SoftLab Günter Koch, Austrian Research Centers Wojtek Kozaczynski, Rational Software Corp. Tomoo Matsubara, Matsubara Consulting Masao Matsumoto, Univ. of Tsukuba Dorothy McKinney, Lockheed Martin Space Systems Nancy Mead, Software Engineering Institute Stephen Mellor, Project Technology Susan Mickel, AgileTV Dave Moore, Vulcan Northwest Melissa Murphy, Sandia National Laboratories Kiyoh Nakamura, Fujitsu Grant Rule, Software Measurement Services Girish Seshagiri, Advanced Information Services Chandra Shekaran, Microsoft Martyn Thomas, Praxis Rob Thomsett, The Thomsett Company John Vu, The Boeing Company Simon Wright, Integrated Chipware Tsuneo Yamaura, Hitachi Software Engineering M A G A Z I N E O P E R AT I O N S C O M M I T T E E
References 1. W. Edwards Deming, Out of the Crisis, MIT Press, Cambridge, Mass., 2000. 2. J.M. Juran, Juran’s Quality Handbook, McGraw-Hill, New York, 1998. 3. P.B. Crosby, Quality Is Free: The Art of Making Quality Certain, Mentor Books, Denver Colo., 1992. 4. S. McConnell, Code Complete, Microsoft Press, Redmond, Wash., 1993.
George Cybenko (chair), James H. Aylor, Thomas J. Bergin, Frank Ferrante, Forouzan Golshani, Rajesh Gupta, Steve McConnell, Ken Sakamura, M. Satyanarayanan, Nigel Shadbolt, Munindar P. Singh, Francis Sullivan, James J. Thomas P U B L I C AT I O N S B O A R D
Rangachar Kasturi (chair), Mark Christensen, George Cybenko, Gabriella Sannitti di Baja, Lee Giles, Thomas Keefe, Dick Kemmerer, Anand Tripathi
Ten Deadly Risks in Internet and Intranet Software Development Donald Reifer
W
hen I think of Internet development, I picture a handful of developers working frantically against the clock amid the litter of takeout food containers to churn out code for the Web. As you might expect, these developers tend to be recent graduates who use the latest technology to turn out applications that live for weeks but not years. Not that this is bad. Some of the best work I have seen in years has come about this way. The reason is simple. With their “We can do anything” attitude, these teams are willing to work on technology’s proverbial bleeding edge. They know what they produce is going to change, so they aren’t afraid to try something new. That’s because they know they can fix problems as they occur without suffering the severe penalties they might have faced in earlier development environments. This article contrasts the current Internet and intranet development climate with earlier releases (see Table 1) and identifies the 10 greatest risks facing today’s Young Internet/intranet Lions. Where’s the action on today’s Internet? With the world economy’s recent slowdown, you might easily think that the move to the Net has also slackened. Don’t believe it. As Table 2 shows, current trends in Internet and intranet project work indicate oth12
and technology volatility should strike you as new and important. Don’t get confused by Table 3. The mitigation strategies listed are aimed primarily at Internet/intranet developments. How do I mitigate these risks? Just identifying the risks is easy. Knowing how to reduce their deadly consequences is much harder. The third column of Table 3 lists my recommendations for dealing with primarily the Internet/intranet risks. Most of these mitigation strategies aren’t new, but some are innovative, I believe. That’s because, until recently, issues identified in Internet and intranet projects hadn’t surfaced or were deemed less important. For example, you need to specifically align Web development with your business goals. Else, why build them? As another example, concepts such as nightly builds, weekly releases to the field, and having the customer function as a member of the programming team are novel. If you’re interested in risk management, you’ll find many publications on the topic, many based on experience rather than theory. But, be warned. In most cases, you will have to extend this experience into the Internet/intranet world as you try to address the peculiarities of Web projects. That’s not so bad when you think about it. It’s easier to extend existing knowledge than to plow new ground.
T
he list of 10 deadly Internet and intranet risks won’t surprise many. But based on them, software engineers need to strike a balance between the technologies that many in the Internet world depend
RAPID
A game-changing, nonproprietary rapid and agile development project model for building business solutions of any size in short timeframes. It shortens the clock-speed (and time to market) for delivery of core business benefits. It is the only approach that can guarantee delivery on an exact day under tight, Internet-time deadlines.
WHAT IS DSDM?
DSDM (Dynamic Systems Development Method) is a framework that encompasses all aspects needed for successful delivery: people, process and technology - with emphasis on people; most projects fail as a result of people-based problems. DSDM is primarily nonprescriptive so it is synergistic with many AGILE Created using software development agile techniques and now methods such as XP, in version 4.0, it continues Scrum, Adaptive, Crystal, to be evolved using DSDM, DSDM etc. The framework the only Agile Method created provides underlying using an Agile Method. principles, processes, project NON-PROPRIETARY lifecycle, artifacts, key roles and The non-proprietary DSDM method responsibilities, and guidance on evolved collaboratively over the last management techniques and 6 years by an International nonprofit development techniques. It's a consortium. It's tool and technology tool to effectively: independent. No tools to purchase * Understand, or be hamstrung by. * Plan, * Communicate, BUSINESS CENTERED Built in * Control, and partnership with big business for * Deliver all projects. business. DSDM will scale from five to hundreds of developers. As the most business benefit focused LEARN MORE visit the DSDM method in the world, many of the Consortium web site at world's largest companies and http://www.dsdm.org or contact numerous government bodies have DSDM directly at established DSDM as their standard. 800-610-6776. DSDM is ISO 9000 certified.
Table 1 Traditional versus Internet/intranet development Characteristic
Traditional approaches
Internet/intranet development
Primary goal Typical project size Typical timeline Development approach employed
Build quality software products at minimum cost Medium to large (20 or more team members) 10 to 18 months Classical requirements-based paradigms; done phased or incrementally; document-driven with focus on getting the design right before coding Traditional methods; object-oriented approaches, procedural languages (C, C++); limited, multimedia, CASE tools; use cases; lots of modeling; and so on Software Capability Maturity Model, SPICE, ISO-based Code-based systems; mostly new; some reuse; lots of legacy involved; many external interfaces; lots of interactions; often complex applications Professional software engineers typically with 5+ years of experience in at least two pertinent application domains
Bring quality products to market as quickly as possible Small (3 to 7 team members) Several weeks to 6 months Rapid application or spiral development (Rational Unified Model, MBase, and so on)
Primary technologies used
Processes employed Products developed
People involved
Agile methods; component-based approaches; multimedia; new language environments (Java, XML, HTML, and so forth); visualization; and so on Generally ad hoc, pairwise programming; refactoring Object-based systems; many reusable building blocks; few external interfaces; little interaction; simple applications Less experienced programmers; users as developers; graphic designers; new hires right out of school
March/April 2002
IEEE SOFTWARE
13
MANAGER
upon, on the one hand, and the tried and true processes that promote risk management and help us achieve business goals, on the other. The “just do it” attitude of the past few years has done as much harm as good to the software engineering profession. While a few good
practices have emerged for Internet development, many time-tested software engineering practices were jettisoned based on the faulty belief that teams don’t have time to put these practices to work. By looking at the list of deadly risks, we can recognize our mistake. My message is that
“Good software engineering pays off on Internet applications, too.” Try them, they’ll make your job easier.
Don Reifer is president of Reifer Consultants and visiting associate of the Center for Software Engineering at the University of Southern California. Contact him at [email protected].
Table 2 Who’s Developing Internet/intranet Applications? Time Period
Who’s playing?
What’s their primary interest?
1980s Early 1990s Late 1990s Now
Researchers Internet service providers Internet startups Large firms as well as yet more startups
Technical issues (protocols, for example) Meeting the demand for performance (many subscribers) Content is king as everyone moves to the Net Save money, collaborate, and build an e-business infrastructure
Table 3 Traditional and Internet and intranet project risks and mitigation strategies Traditional risks
Ten deadly Internet and intranet project risks
Internet/intranet Risk mitigation strategies
Personnel shortfalls
Personnel shortfalls
Unrealistic budgets and schedules
Misalignment with business goals
Volatile requirements
Unrealistic customer and schedule expectations
Shortfalls in externally furnished components
Volatile technology, changing so rapidly that it is hard to keep up (SML, .NET, Persistence, J2EE, and so forth) Unstable software releases (although the software works, it performs poorly and crashes frequently)
Bring on a skilled core team. Have the team mentor new people. Make training and teamwork part of the culture. Hire top-notch personnel while the job market remains soft. Align developments with business goals and highlight importance of development. Make the customer part of the team. Set schedule goals around frequent deliveries of varying functionality. Introduce new technology slowly, according to a plan. Use technology because it supports business goals, not because it is the latest and greatest thing to do. Stabilize requirements and designs as much as practical. Plan to refactor releases from the start. Don’t deliver applications when quality is poor and system crashes (say “no”). Manage functionality using releases. Deliver working prototypes before you target new functionality. Introduce new methods and tools slowly, as justified by business cases, not merely because they are new and appealing. Make sure methods and tools are of production quality. Set clear expectations and measures of success. Make effort a learning exercise (to make staff feel they are learning, growing, and gaining valuable experience). Staff the team carefully with compatible workforce. Build team and provide it with leadership. Manage conflicts to ease friction. Acquire dedicated workspace for the team. Appropriate collaboration tools. Lots of space available for meetings and pizza.
Gold-plating
Released software has poor quality New methods and unstable tools (primarily causing schedule delays)
Constant changes in software functionality (shooting at a moving target) Even newer methods and more unstable tools (causes heartburn, headaches, and schedule delays)
High turnover (especially of skilled personnel)
High turnover (especially of those personnel skilled in the new technology)
Friction between developers and customers
Friction within the team (lack of leadership, overwork, unrealistic expectations, and so forth)
Managing Requirements for Business Value John Favaro Requirements engineers are often asked the question, “What will the investment in requirements give to our business?” John Favaro uses his experience in financial engineering to help us answer this question by providing some tools for quantifying the value of requirements. —Suzanne Robertson
where requirements simply arrived, if you were lucky, on a one-way street from the customer. An analyst who masters the requirements process can become an active participant in the strategic conception of a system or product. He or she can elicit and formulate requirements in such a way that the path from requirement to implemented system feature is illuminated in all of its consequences, both technical and economic. Of course, we already know that a robust requirements process is a key factor in resolving problems early in the life cycle, with all the familiar economic benefits. But an actively managed requirements process gives you much more than that. Requirements analysts and customers alike can discover a new flexibility. Although there are always a few nonnegotiable requirements (such as no loss of human life), the vast majority are suitable for examination, reformulation, negotiation, or adaptation. As unexpected consequences are uncovered (for example, the projected high cost of implementation), the analyst can cooperate with the customer to search for other, equally satisfactory requirements formulations. The economic tools of cost–benefit analysis for this process have been well understood for years. A full cost–benefit analysis of a requirement (or group of requirements) needs an investment in time and resources. Furthermore, assessing the cost–benefit of requireMarch/April 2002
IEEE SOFTWARE
15
REQUIREMENTS DEPT TITLE
ments is more difficult than design or implementation, because requirements are the furthest upstream in the development process. Consequently there are more unknown factors; it can take a full development cycle before the complete economic impact of a requirement is known. Perhaps you can now understand why requirements researchers are studying techniques for creating reusable requirements.1 The first time you conceive a system based on a requirement, estimating the costs and benefits might be difficult. But, after carrying through the system to implementation, you will have a much better idea of the costs and benefits triggered by that requirement. A wellformulated, measurable, reusable requirement—including a full cost– benefit analysis as part of its description—is every bit as valuable as a reusable software module.
system. Requirements that once were vague become crystal clear as uncertainty is resolved; a requirement once thought to be rigid could be negotiated and reformulated to permit several alternative features that could satisfy it. Such changing conditions provide opportunities for the strategist to increase the value of his process. However, the traditional tools of cost–benefit analysis that apply so well to the noniterative requirements process have proven less adequate to help the requirements analyst examine the economic value of his or her newfound strategic flexibility—and this brings me to the third important change in recent years. I’d like to draw now on my interaction with Kent Beck over the past few years to discuss some cuttingedge ideas about the relationship between strategy and finance and their effect on requirements management.
Agile requirements The second important change has been the emergence of strategies for confronting the bête noire of the requirements process: vague and changing requirements. These strategies are best reflected in a new generation of software life cycles known as agile processes (see www.agilealliance.org). Some prominent examples of agile processes include Alistair Cockburn’s Crystal Methods, Bob Charette’s Lean Development, and Jim Highsmith’s Adaptive Software Development. The common denominator of these agile processes is the iterative development paradigm, which breaks up the tradition of upfront requirements elicitation and analysis. No longer do you fire and forget requirements and then move on to the next phase. Requirements may be introduced, modified, or removed in successive iterations. As Kent Beck (chief evangelist of Extreme Programming, the most visible of the agile processes) exhorts us, requirements management should “embrace change.”2 Business conditions change, giving rise to new requirements; requirements thought to be critical turn out not to be as the customer sees the first versions of the
Contractual innovation Evaluating the financial impact of strategic decisions has been the subject of great debate since the dawn of economics as a discipline. In a list of the Top 10 Unsolved Problems in Corporate Finance first compiled by the legendary financial authors Richard Brealey and Stewart Myers in 1981 and unchanged in last year’s sixth edition of their classic textbook Principles of Corporate Finance, the financial impact was ranked Number 1.3 In recent years, people have placed hope in a new branch of financial theory known as contingent claims analysis— or more popularly, real options— made possible by the breakthroughs in the 1970s in option pricing theory. In this approach, the opportunities created by strategic flexibility are evaluated with the financial tools of option pricing theory. Let’s take an example from XP. Suppose the customer requires your application to provide access to an enterprise-wide knowledge management system that he or she is contemplating introducing in a few months. A simple cost–benefit analysis on the system features that would satisfy this requirement is positive,
16
IEEE SOFTWARE
March/April 2002
say, $10 implementation cost versus $15 in benefits. But, an enormously uncertain environment undermines the cost–benefit analysis. The customer admits that the uncertainty (“volatility”) of his estimate is as much as 100 percent. If the knowledge management system is never introduced, then it will have been a waste of time to provide the access capability. However, if it is introduced, the access capability could become far more valuable than originally envisioned. The customer says that the uncertainty will be resolved in a year. The XP process permits the strategy of waiting until a future iteration to take up the requirement. Is there any way to calculate the economics of this alternative strategy? The tools of option pricing theory can in fact calculate the value of waiting to be slightly less than $8—more than the $5 of benefit accrued by immediate development.4 The option to delay implementing a requirement is an example of the way that contingent claims analysis is making a profound impact on the requirements process in the form of contractual innovation, a result of the new discipline of financial engineering born with the advent of option pricing theory. Beck likes to say that unlike fixed-scope traditional contracts, XP contracts have optional scope: every iteration provides a formal decision point in which the customer can change direction, abandoning requirements, introducing new requirements, or selecting between alternative requirements. For example, you sign such contracts not for a fixed set of functionality, but for a team’s best effort for a fixed period at a fixed price. The precise scope to be implemented will be negotiated periodically over the life of the contract, much as professional services contracts are run today. Changes in the team’s actual velocity and the relative estimates attached to each feature are factored into these scope negotiations, as are changes in the perceived relative value of these features. Option pricing theory yields some surprising insights to the economic
REQUIREMENTS DEPT TITLE
value of such contracts. For instance, there is an exotic type of option known as a best-of or rainbow option. The owner possesses two options, of which only one can be exercised. The rainbow option has the most value when the alternatives are negatively correlated—that is, when the same conditions that increase one alternative’s value will decrease the other’s. This implies that a contract’s value is enhanced by contradictory requirements. For example, two requirements each specifying the application to run on a different platform is a rainbow option. If the choice can be delayed to some later time, it adds value for the customer, letting him hedge the ultimate platform choice in the contract. Similarly, a requirement whose utility is uncertain (estimated cost and value are close) gains value by inclusion in an optional scope clause, because the option to delay implementation has demonstrable economic value. Where contractual flexibility exists to select among alternative requirements, add requirements, or even to abandon requirements, economic value is added.
Adding value What does all this mean for you as a requirements analyst? As the requirements process evolves to embrace increased strategic flexibility, and the new financial tools of contingent claims analysis mature, requirements become an important currency in system characteristic negotiation. By learning to create reusable requirements with a companion cost–benefit analysis, you bring valuable material to the table from the very beginning. By studying the new generation of agile development processes, you become fluent in the strategic possibilities to add value to the requirements process over the entire product life cycle. By learning something about the new tools of financial analysis I’ve introduced, you can better understand how strategic flexibility in the requirements process adds value. For that is what the requirements process should be about. If you remember nothing else from this column, remember this—stamp it on your forehead if necessary: the purpose of the requirements process should not be to “cover all eventualities,” or to “limit the dam-
age,” or to “minimize risk,” or even to “satisfy the customer.” The purpose of the requirements process is to add business value. It is a subtle shift in perspective for the requirements analyst, but it makes all the difference because it puts you in the position of managing requirements to make the most of your strategic opportunities.
References 1. S. Robertson and J. Robertson, “Chapter 12: Reusing Requirements,” Mastering the Requirements Process, Addison-Wesley, Reading, Mass., 1999, pp. 218–234. 2. K. Beck, Extreme Programming Explained: Embrace Change, Addison-Wesley, Reading, Mass., 1999. 3. R. Brealey and S.C. Myers, Principles of Corporate Finance, McGraw-Hill, New York, 2000. 4. M. Amram and N. Kulatilaka, Real Options: Managing Strategic Investment in an Uncertain World, Harvard Business School Press, Cambridge, Mass., 1999.
John Favaro is an independent consultant based in Pisa, Italy. He is European co-chair of the IEEE Technical Subcommittee on Software Reuse and a founding member of the steering committee of the Society for Software Education. He has degrees in computer science from Berkeley and Yale. Contact him at Via Gamerra 21, 56123 Pisa, Italy; [email protected].
Get CSDP Certified Announcing IEEE Computer Society's new
Certified Software Development Professional Program Doing Software Right •
Demonstrate your level of ability in relation to your peers
•
Measure your professional knowledge and competence
The CSDP Program differentiates between you and others in a field that has every kind of credential, but only one that was developed by, for, and with software engineering professionals.
"The exam is valuable to me for two reasons: One, it validates my knowledge in various areas of expertise within the software field, without regard to specific knowledge of tools or commercial products... Two, my participation, along with others, in the exam and in continuing education sends a message that software development is a professional pursuit requiring advanced education and/or experience, and all the other requirements the IEEE Computer Society has established. I also believe in living by the Software Engineering code of ethics endorsed by the Computer Society. All of this will help to improve the overall quality of the products and services we provide to our customers..." — Karen Thurston, Base Two Solutions
Register Today Visit the CSDP web site at http://computer.org/certification or contact [email protected]
ne of the growing trends in software design is separating interface from implementation. The principle is about separating modules into public and private parts so that you can change the private part without coordinating with other modules. However, there is a further distinction—the one between public and published interfaces. This distinction is important because it affects how you work with the interface. Public versus published Let’s assume I’m writing an application in a modern modular language—to make things more concrete, let’s assume this language is Java. My application thus consists of several classes (and interfaces), each of which has a public interface. This public interface of a class defines a group of methods that any other class in the system can invoke. While I’m enhancing a public method, I realize that one of its parameters is redundant— I don’t need to use it in the method (maybe I can get that value through some other route or maybe I just don’t need it anymore). At this point, I can eliminate that value from the method signature, clarifying the method and potentially saving work for its callers. Because this method is public, any class in the system can call it. Should I remove the parameter? In this case, I would argue yes, because there are benefits and it isn’t difficult. Al18
Advice on publishing Recognizing the difference between public and published leads to an important set of consequences. Don’t treat interfaces as published unless they are If you need to change an interface and can find and change all users, then don’t bother going through all the forwarding and deprecation gambits. Just make the change and update the users. Don’t publish interfaces inside a team I once suggested to somebody that we change a public method, and he objected because of the problems caused by its being published. The real problem was that although there were only three people on the team, each developer treated his interfaces as published to the other two. This is because the team used a strong form of code ownership in which each module was assigned to a single programmer and only that programmer could change the module’s code. I’m sympathetic to code ownership—it encourages people to monitor their code’s quality—but a strong code ownership model such as this one causes problems by forcing you to treat interperson interfaces as published. I encourage a weaker ownership model in which one person is responsible for the module but other people can make changes when necessary. This lets other developers do things such as alter calls to changed methods. (You can also use collective code ownership—where anyone can change anything—to avoid internal publishing.) This kind of ownership usually requires a configuration management system that supports concurrent writers (such as CVS) rather than one that uses pessimistic locking. There is a limit to how big a team you can run without some form of internal publishing, but I would err on the side of too little publishing. In other words, assume you don’t need to publish interfaces, and then adjust if you find this causes problems.
Publish as little as you can as late as you can Because publishing locks you into the slower cycle of changes, limit how much you publish. This is where a language’s inability to distinguish between public and published becomes an issue. The best you can do is declare some modules to be the interface and then counsel your software users not to use the other modules, even if they can see them. Keep these interfaces as thin as you can. Publish as late as possible in the development cycle to give yourself time to refine the interfaces. One strategy is to work closely with one or two users of your components—users who are friendly enough to cope with sharp interface changes—before you publish to the masses. Try to make your changes additions In addition to distinguishing between published and public interfaces, we can also identify two types of interface changes. Generally, changes can alter any aspect of an interface. However, there are some changes that only cause additions to an interface, such as adding a method. Additions won’t break any of the interface’s clients—existing clients have no problem using the old methods. Consequently, when you make a change, it’s worth considering whether you can recast it into an addition. For example, if you need to remove a parame-
There’s something to be said for the public–published distinction being more important than the more common public–private distinction.
ter from a method, instead of changing the method, try adding a new method without the parameter. That way, you get an addition rather than a general alteration, and your clients remain compatible. Additions can still cause problems if outside groups have their own implementation of your interface. If that happens, even adding a method breaks the alternative implementation. Thus, some component technologies, such as COM, use immutable interfaces. With an immutable interface, once it’s published, you guarantee not to change it. If you want to change the interface, you must create a second interface, and components can then support this interface at their leisure. It’s not the ideal scheme, but it certainly has its merits.
I
would like to see the public– published distinction appear more in languages and platforms. It’s also interesting that environments don’t tend to provide the facilities to evolve interfaces. Some can deprecate a method that’s due to be removed: Eiffel does this as part of the language, and Java does it (but as part of the built-in documentation). I haven’t seen anyone add a marker to a method that warns implementers of something that’s going to be added or would let you add something to an interface in a provisional way. That’s part of a more general issue in software platforms. So far, platforms haven’t sufficiently understood that software is supposed to be soft and thus needs facilities that allow change. In recent years, we’ve taken more steps in this direction with component-packaging systems, but these are just the early steps.
Martin Fowler is the chief scientist for ThoughtWorks, an Internet systems delivery and consulting company. Contact him at [email protected]. March/April 2002
IEEE SOFTWARE
19
software construction Editors: Andy Hunt and Dave Thomas ■ The Pragmatic Programmers a n d y @ p r a g m a t i c p r o g r a m m e r. c o m ■ d a v e @ p r a g m a t i c p r o g r a m m e r. c o m
Software Archaeology Andy Hunt and Dave Thomas
T
his isn’t programming, this is archaeology!” the programmer complained, wading through the ancient rubble of some particularly crufty pieces of code. (One of our favorite jargon words: www. tuxedo.org/~esr/jargon/html/entry/crufty. html.) It’s a pretty good analogy, actually. In real archaeology, you’re investigating some
situation, trying to understand what you’re looking at and how it all fits together. To do this, you must be careful to preserve the artifacts you find and respect and understand the cultural forces that produced them. But we don’t have to wait a thousand years to try to comprehend unfathomable artifacts. Code becomes legacy code just about as soon as it’s written, and suddenly we have exactly the same issues as the archaeologists: What are we looking at? How does it fit in with the rest of the world? And what were they thinking? It seems we’re always in the position of reading someone else’s code: either as part of a code review, or trying to customize a piece of open source software, or fixing a bug in code that we’ve inherited. 20
code. (Remember playing “Colossal Cave?” You are in a maze of twisty little passages, all alike….) Keep detailed notes as you discover priceless artifacts and suspicious trapdoors. UML diagrams might be handy (on paper—don’t get distracted by a fancy CASE tool unless you’re already proficient), but so too are simple notes. If there are more than one of you on the project, consider using a Wiki or similar tool to share your notes (you can find the original Wiki at www.c2.com/cgi/wiki?WikiWikiWeb and a popular implementation at www.usemod.com/cgi-bin/wiki.pl. As you look for specific keywords, routine names, and such, use the search capabilities in your integrated development environment (IDE), the Tags feature in some editors, or tools, such as Grep, from the command line. For larger projects, you’ll need larger tools: you can use indexing engines such as Glimpse or SWISH++ (simple Web indexing system for humans) to index a large source code base for fast searching. The mummy’s curse Many ancient tombs were rumored to be cursed. In the software world, the incantation for many of these curses starts with “we’ll fix it later.” Later never comes for the original developers, and we’re left with the curse. (Of course, we never put things off, do we?) Another form of curse is found in misleading or incorrect names and comments that help us misunderstand the code we’re reading. It’s dangerous to assume that the code or comments are completely truthful. Just because a routine is named readSystem is no guarantee that it isn’t writing a megabyte of data to the disk. Programmers rarely use this sort of cognitive dissonance on purpose; it’s usually a result of historical accident. But that can also be a valuable clue: How did the code get this way, and why? Digging beneath these layers of gunk, cruft, and patch upon patch, you might still be able to see the original system’s shape and gain
insight into the changes that were required over the years. Of course, unless you can prove otherwise, there’s no guarantee that the routine you’re examining is even being called. How much of the source contains code put in for a future that never arrived? Static analysis of the code can prove whether a routine is being used in most languages. Some IDEs can help with this task, or you can write ad hoc tools in your favorite scripting language. As always, you should prove assumptions you make about the code. In this case, adding specific unit tests helps prove—and continue to prove—what a routine is doing (see www.junit.org for Java and www.xprogramming.org for other languages). By now, you’ve probably started to understand some of the terminology that the original developers used. Wouldn’t it be great to stumble across a Rosetta stone for your project that would help you translate its vocabulary? If there isn’t one, you can start a glossary yourself as part of your note-taking. One of the first things you might uncover is that there are discrepancies in the meaning of terms from different sources. Which version does the code use? Duck blinds and aerial views In some cases, you want to observe the dynamics of the running system without ravaging the source code. One excellent idea from the workshop was to use aspects to systematically introduce tracing statements into the code base without
Instead of hiding in a “duck blind” and getting the view on the ground, you might want to consider an aerial view of the site.
editing the code directly (AspectJ for Java is available at www.aspectj.org). For instance, suppose you want to generate a trace log of every database call in the system. Using something like AspectJ, you could specify what constitutes a database call (such as every method named “db*’” in a particular directory) and specify the code to insert. Be careful, though. Introducing any extra code this way might produce a “Heisenbug,” a bug introduced by the act of debugging. One solution to deal with this issue is to build in the instrumentation in the first place, when the original developers are first building and testing the software. Of course, this brings its own set of risks. One of the participants described an ancient but still-used mainframe program that only works if the tracing statements are left in. Whether diagnostic tracing and instrumentation are added originally or introduced later via aspects, you might want to pay attention to what you are adding, and where. For instance, say you want to add code that records the start of a transaction. If you find yourself doing that in 17 places, this might indicate a structural problem with the code—and a potential answer to the problem you’re trying to solve. Instead of hiding in a “duck blind” and getting the view on the ground, you might want to consider an aerial view of the site. Synoptic, plotting, and visualization tools provide quick, high-level summaries that might visually indicate an anomaly in the code’s static structure, in the dynamic trace of its execution, or in the data it handles. For instance, Ward Cunningham’s Signature Survey method (http://c2.com/doc/SignatureSurvey) reduces each source file to a single line of the punctuation. It’s a surprisingly powerful way of seeing a file’s structure. You can also use visualization tools to plot data from the volumes of tracing information languishing in text files. As with real archaeology, it pays to be meticulous. Maintain a deliberate March/April 2002
IEEE SOFTWARE
21
SOFTWARE CONSTRUCTION
Tools and Techniques
■
The workshop identified these analysis tools and techniques: ■ Scripting languages for
■ ■ ■ ■ ■ ■ ■ ■ ■
–ad hoc programs to build static reports (included by and so on) –filtering diagnostic output Ongoing documentation in basic HTML pages or Wikis Synoptic signature analysis, statistical analysis, and visualization tools Reverse-engineering tools such as Together’s ControlCenter Operating-system-level tracing via truss and strace Web search engines and tools to search for keywords in source files IDE file browsing to flatten out deep directory hierarchies of the source Test harnesses such as Junit and CPPUnit API documentation generation using Javadoc, doxygen, and so on Debuggers
■
■
Participants also identified these invasive tools: ■ ■ ■ ■
Hand-inserted trace statements Built-in diagnostic instrumentation (enabled in production code as well) Instrumentation to log history of data values at interface calls Use of AspectJ to introduce otherwise invasive changes safely
pace; and keep careful records. Even for a short-term, quick patch that doesn’t require you to understand the whole code base, keep careful records of what you’ve learned, what you’ve tried, what worked, and what didn’t. What were they thinking? Archaeologists generally don’t make wisecracks about how stupid a particular culture was. In our industry, we generally don’t show such restraint. But it’s important when reading code to realize that apparently bone-headed decisions that appear to be straight out of a “Dilbert” cartoon seemed perfectly reasonable to the developers at the time. Understanding “what they were thinking” is critical to understanding how and why they wrote the code the way they did. If you discover they misunderstood something, you’ll likely find that mistake in more than one place. But rather than simply “flipping the bozo bit” on the original authors, try to evaluate their strengths as well as weaknesses. You might find lost treasure—buried domain expertise that’s been forgotten. Also, consider to which “school of 22
IEEE SOFTWARE
March/April 2002
programming” the authors belonged. Regardless of implementation language, West-Coast Smalltalkers will write in a different style from European Modula programmers, for instance. In a way, this approach gets us back to the idea of treating code as literature. What was the house style? By understanding what the developers were thinking, what influenced them, what techniques they were fond of, and which ones they were unaware of, you will be much better positioned to fully understand the code they produced and take it on as your own. Leaving a legacy Given that today’s polished code will inevitably become the subject of some future developer’s archaeological dig, what can we do to help them? How can we help them comprehend “what we were thinking” and work with our code? ■
Ensure the site is secure when you leave. Every file related to the project should be under version control, releases should be appropriately identified, and the build
■
■
should be automatic and reliable. Leave a Rosetta stone. The project glossary was useful for you as you learned the domain jargon; it will be doubly useful for those who come after you. Make a simple, high-level treasure map. Honor the “DRY” principle: Don’t duplicate information that’s in the code in comments or in a design document. Comments in the code explain “why,” the code itself shows “how,” and the map shows where the landscape’s main features are located, how they relate to each other, and where to find more detailed information. Build in instrumentation, tracing, and visualization hooks where applicable. This could be as simple as tracing “got here” messages or as intricate as an embedded HTTP server that displays the application’s current status (our book, The Pragmatic Programmer [Addison-Wesley, 2000] discusses building testable code). Use consistent naming conventions to facilitate automatic static code analysis and search tools. It helps us humans, too. No evil spells. You know what the incantations sound like. Don’t let the mummy’s curse come back to haunt programmers later. The longer a curse festers and grows, the worse it is when it strikes— and curses often backfire against their creators first.
Acknowledgments Many thanks to the other workshop organizers, Brian Marick and Ward Cunningham, and to the attendees: Ken Anderson, Vladimir Degen, Chet Hendrickson, Michael Hewner, Kevin Johnson, Norm Kerth, Dominik Kuropka, Dragos Manolescu, John McIntosh, Walter Risi, Andy Schneider, Glenn Vanderburg, and Charles Weir. Andy Hunt and Dave Thomas are partners in The
Pragmatic Programmers, LLC. They feel that software consultants who can’t program shouldn’t be consulting, so they keep current by developing complex software systems for their clients. They also offer training in modern development techniques to programmers and their management. They are coauthors of The Pragmatic Programmer and Programming Ruby, both from Addison-Wesley. Contact them through www. pragmaticprogrammer.com.
focus
guest editors’ introduction
The Software Engineering of Internet Software Elisabeth Hendrickson, Quality Tree Software Martin Fowler, ThoughtWorks
hen we first started working with the Web, it was a publishing medium. The Web was essentially a poorly edited and rather erratic encyclopedia. Although much of the Web is still that, the Web is increasingly doing things that we’ve typically seen in enterprise applications. Rather than simply presenting static information, Web sites invite user interaction. The Web plays host to a new generation of systems following green screens and client-server GUIs.
applications add some new variations of familiar activities. None of these changes are necessarily massive, but they suffice to suggest some new directions. Quality, scalability, usability, maintainability Jeff Offutt’s article “Quality Attributes of Web Software Applications” is a good starting point for this discussion; he explores quality attributes for Web-based systems. Although the Web hasn’t necessarily introduced any new quality issues, Web applications often combine more quality challenges than previous generations of applications. Furthermore, the Web’s capabilities introduce new twists on traditional ideas of quality. The Web also brings the question of scalability to the fore. Whereas a system might have had a few thousand users a decade ago, today Web system designers must consider the possibility that hundreds of thousands of users might log in at once. Colleen March/April 2002
IEEE SOFTWARE
23
Roe and Sergio Gonik dig into the issue of scalability in “Server-Side Design Principles for Scalable Internet Systems.” Their article culls principles from their experiences with software that is both behaviorally complex and that needs that elusive scalability. Additionally, many Web users are end customers. Web applications have a greater need for usability than many enterprise applications previously demanded. Larry Constantine and Lucy Lockwood tackle this problem with techniques for designing user interfaces through user models, task models, and content models in their article, “Usage-Centered Engineering for Web Applications.” When we talk about user interfaces, we must remember that as well as designing them from the outside to be usable, we must also design them from the inside to be maintainable. Web applications need to change as business changes, and even the most usable site can become a problem if the interface’s internal design is difficult to change and fix. In their article, “Objects and the Web,” Alan Knight and Naci Dai peer inside a design to reveal that one of the oldest patterns for user interfaces, the Model-View-Controller, is a key part of maintainable Web systems. Indeed, MVC plays a bigger-than-ever part in the Web. Agile, international, testing, lessons learned Web applications must be up quickly to compete. In “Going Faster: Testing the Web Application,” Edward Hieatt and Robert Mee explore this dilemma and suggest that
About the Authors Elisabeth Hendrickson is an independent consultant who specializes in software quality assurance and management. She has 14 years of experience working with leading software companies and is the founder of Quality Tree Software. An award-winning author, she has published more than 20 articles and is a frequently invited speaker at major software quality and software management conferences. Contact her at [email protected].
Martin Fowler is the chief scientist for ThoughtWorks: an enterprise application development and integration company. He has spent many years applying object oriented technology to enterprise applications. He edits the Design column for IEEE Software and is the author of several books on software design. He is currently working on a book on enterprise application architecture, which you can find at www.martinfowler.com.
24
IEEE SOFTWARE
March/April 2002
high quality is not just compatible with high speed—quality enables speed. By writing the tests before the code, the authors discovered that they not only produced a more solid end product but also could do it more quickly. It’s hard to write an introduction this far without raising the spirit of another recent fad: agile methods such as Extreme Programming. Throughout many of these articles, you’ll see that theme. Web applications seem particularly suited to agile processes’ emphasis on quality and speed. One feature of agile methods is their de-emphasis on modeling. In “Lessons in Agility from Internet-Based Development,” Scott Ambler describes a case study of how a Web development team used modeling within an agile process. He concludes that there is less emphasis on documentation and tools but more emphasis on communication and quality. Modeling is there, it’s recognizable, but a little different. The Web’s wide reach plays particular havoc with those who like to think that world revolves around the English language. Native English speakers often run into Web pages they can’t read and get a taste of what it’s like for many in the world who don’t have a dominant grasp of English. This leads to a new challenge: enabling Web applications for international use. In “Software Localization for Internet Software: Issues and Methods,” Rosann Webb Collins focuses on the needs of internationalization, providing one step toward a checklist for Web applications that need a global reach. Eric Altendorf, Moses Hohman, and Roman Zabicki provide a nice summary of lessons learned from Web development in “Using J2EE on a Large, Web-Based Project.” This is a case study of a moderately large Web application using the popular enterprise Java technologies. The authors discuss the challenges they faced designing dynamic HTML user interfaces, tackling internationalization, and integrating third-party systems that were developed before the Web was around.
O
ur challenge as a profession, both in Web development and in wider software development, is to better understand and communicate these lessons. We hope this issue helps to do just that.
focus
engineering Internet software
Quality Attributes of Web Software Applications Jeff Offutt, George Mason University
he World Wide Web was originally designed to present information to Web surfers using simple sites that consisted primarily of hyperlinked text documents. Modern Web applications run large-scale software applications for e-commerce, information distribution, entertainment, collaborative working, surveys, and numerous other activities. They run on distributed hardware platforms and heterogeneous computer
systems. The software that powers Web applications is distributed, is implemented in multiple languages and styles, incorporates much reuse and third-party components, is built with cutting edge technologies, and must interface with users, other Web sites, and databases. Although the word “heterogeneous” is often used for Web software, it applies in so many ways that the synonymous term “diverse” is more general and familiar, and probably more appropriate. The software components are often distributed geographically both during development and deployment (diverse distribution), and communicate in numerous distinct and sometimes novel ways (diverse communication). Web applications consist of diverse components including traditional and nontraditional software, interpreted scripting languages, plain HTML files, mixtures of HTML and
programs, databases, graphical images, and complex user interfaces. As such, engineering an effective Web site requires large teams of people with very diverse skills and backgrounds. These teams include programmers, graphics designers, usability engineers, information layout specialists, data communications and network experts, and database administrators. This diversity has led to the notion of Web site engineering.1 The tremendous reach of Web applications into all areas of communication and commerce makes this one of the largest and most important parts of the software industry. Yet a recent National Research Council study2 found that the current base of science and technology is inadequate for building systems to control critical software infrastructure. The President’s commission on critical infrastructure protection reached March/April 2002
IEEE SOFTWARE
25
Instead of “sooner but worse,” it is often advantageous to deliver Web applications “later and better.”
26
IEEE SOFTWARE
this same conclusion in the President’s Information Technology Advisory Committee report.3 This inadequacy is particularly severe in the novel, high-risk area of Web application software. Although Web software development uses cutting-edge, diverse technologies, little is known about how to ensure quality attributes such as Web application reliability. Unique aspects of Web application software Several factors inherent to Web development contribute to the quality problem. Developers build Web-based software systems by integrating numerous diverse components from disparate sources, including custombuilt special-purpose applications, customized off-the-shelf software components, and third-party products. In such an environment, systems designers choose from potentially numerous components, and they need information about the various components’ suitability to make informed decisions about the software’s required quality attributes. Much of the new complexity found with Web-based applications also results from how the different software components are integrated. Not only is the source unavailable for most of the components, the executables might be hosted on computers at remote, even competing organizations. To ensure high quality for Web systems composed of very loosely coupled components, we need novel techniques to achieve and evaluate these components’ connections. Finally, Web-based software offers the significant advantage of allowing data to be transferred among completely different types of software components that reside and execute on different computers. However, using multiple programming languages and building complex business applications complicates the flow of data through the various Web software pieces. When combined with the requirements to keep data persistent through user sessions, persistent across sessions, and shared among sessions, the list of abilities unique to Web software begins to get very long. Thus, software developers and managers working on Web software have encountered many new challenges. Although it is obvious that we struggle to keep up with the technology, less obvious is our difficulty in understanding just how Web software de-
March/April 2002
velopment is different, and how to adapt existing processes and procedures to this new type of software. Economic changes We evaluate software by measuring the quality of attributes such as reliability, usability, and maintainability, yet academics often fail to acknowledge that the basic economics behind software production has a strong impact on the development process. Although the field of software engineering has spent years developing processes and technologies to improve software quality attributes, most software companies have had little financial motivation to improve their software’s quality. Software contractors receive payment regardless of the delivered software’s quality and, in fact, are often given additional resources to correct problems of their own making. So-called “shrink wrap” vendors are driven almost entirely by time to market; it is often more lucrative to deliver poor-quality products sooner than high-quality products later. They can deliver bug fixes as new releases that are sold to generate more revenue for the company. For most application types, commercial developers have traditionally had little motivation to produce high-quality software. Web-based software, however, raises new economic issues. When I recently surveyed a number of Web software development managers and practitioners, I found that companies that operate through the Web depend on customers using and, most importantly, returning to their sites. Thus, unlike many software contractors, Web application developers only see a return on their investment if their Web sites satisfy customer needs. And unlike many software vendors, if a new company puts up a competitive site of higher quality, customers will almost immediately shift their business to the new site once they discover it. Thus, instead of “sooner but worse,” it is often advantageous to be “later and better.” Despite discussions of “sticky Web sites” and development of mechanisms to encourage users to return,4 thus far the only mechanism that brings repeat users to Web sites has been high quality. This will likely remain true for the foreseeable future. In software development, a process driver is a factor that strongly influences the process used to develop the software. Thus, if soft-
ware must have very high reliability, the development process must be adapted to ensure that the software works well. When I surveyed the important quality process drivers for traditional software, developers always gave a single answer that stands far above the rest: time to market. But when I recently made the same survey of Web software development managers and practitioners, they claim that time to market, although still important, is no longer the dominant process driver. They see the three most important quality criteria for Web application success (and thus, the underlying software) as ■ ■ ■
Reliability Usability Security
Additional important criteria include ■ ■ ■ ■
Availability Scalability Maintainability Time to market
Of course, this is hardly a complete list of important or even relevant quality attributes, but it provides a solid basis for discussion. Certainly speed of execution is also important, but network factors influence this more than software does, and other important quality attributes such as customer service, product quality, price, and delivery stem from human and organizational rather than software factors. That said, the quality attributes I just listed track closely with those cited in other books and articles,1, 5–8 suggesting wide agreement that successful Web software development depends on satisfying these quality attributes. Reliability Extensive research literature and a collection of commercial tools have been devoted to testing, ensuring, assuring, and measuring software reliability. Safety-critical software applications such as telecommunications, aerospace, and medical devices demand highly reliable software, but although many researchers are reluctant to admit it, most software currently produced does not need to be highly reliable. I have been teaching software testing in various forms for 15 years yet have always felt like I was selling something that nobody wants.
Many businesses’ commercial success depends on Web software, however—if the software does not work reliably, the business will not succeed. The user base for Web software is very large and expects Web applications to work as reliably as if they were going to the grocery store or calling to order from a catalog. Moreover, if a Web application does not work well, the users do not have to drive further to reach another store; they can simply point their browser to a different URL. Web sites that depend on unreliable software will lose customers, and the businesses could lose much money. Companies that want to do business over the Web must spend resources to ensure high reliability. Indeed, they cannot afford not to.
Companies that want to do business over the Web must spend resources to ensure high reliability.
Usability Web application users have grown to expect easy Web transactions—as simple as buying a product at a store. Although much wisdom exists on how to develop usable software and Web sites (Jakob Nielsen’s text9 being a classic example), many Web sites still do not meet most customers’ usability expectations. This, coupled with the fact that customers exhibit little site loyalty, means unusable Web sites will not be used—customers will switch to more usable Web sites as soon as they come online. Security We have all heard about Web sites being cracked and private customer information distributed or held for ransom. This is only one example of the many potential security flaws in Web software applications. When the Web functioned primarily to distribute online brochures, security breaches had relatively small consequences. Today, however, the breach of a company’s Web site can cause significant revenue losses, large repair costs, legal consequences, and loss of credibility with customers. Web software applications must therefore handle customer data and other electronic information as securely as possible. Software security is one of the fastest growing research areas in computer science, but Web software developers currently face a huge shortfall in both available knowledge and skilled personnel. Availability In our grandparents’ time, if a shopkeeper March/April 2002
IEEE SOFTWARE
27
Designing and building Web software applications that scale well represents one of today’s most interesting and important software development challenges.
in a small town wanted to take a lunch break, he would simply put a sign on the front door that said “back at 1:00.” Although today’s customers expect to be able to shop during lunchtime, we do not expect stores to be open after midnight or on holidays. But that only works for “brick and mortar” stores. When customers can visit our stores online, 2:00 a.m. in North America is the middle of the afternoon in Asia, and national or religious holidays fall on different days in different countries. On the Web, customers not only expect availability 24 hours a day, seven days a week, they expect the Web site to be operational every day of the year—24/7/365. Even a 10-minute downtime can be damaging; I recently purchased $50 worth of books online but switched companies because the first Web site gave a “missing file” error message. Ten minutes later, that Web site was operational again but had lost my sale. Although this was only one sale, many customers would never come back. Availability means more than just being up and running 24/7/365; the Web software must also be accessible to diverse browsers. In the seemingly never-ending browser wars of the past few years, some software vendors actively sought to make sure their software would not work under competitors’ browsers. By using features only available for one browser or on one platform, Web software developers become foot soldiers in the browser wars, sometimes unwittingly. As an example, one major Web site at my organization uses Shockwave flash, which is only compatible with Microsoft IE and Netscape under Windows. Thus, the many Unix and Netscape users in my building cannot view their own Web site. To be available in this sense, Web sites must adapt their presentations to work with all browsers, which requires significantly more knowledge and effort on developers’ part. Scalability A recent television advertisement showed a small group of young men and women nervously launching their Web site. The celebration started when the site got its first hit, but their faces quickly turned gray when the number of hits went into the thousands, then millions. As with a small corner store, as few as three or four people can create a commercial Web site but, unfortunately (or fortunately
28
IEEE SOFTWARE
March/April 2002
for the profit margin), virtually an unlimited number of customers can visit the Web site. We must therefore engineer Web software applications to be able to grow quickly in terms of both how many users they can service and how many services they can offer. The need for scalability has driven many technology innovations of the past few years. The industry has developed new software languages, design strategies, and communication and data transfer protocols in large part to allow Web sites to grow as needed. Scalability also directly influences other attributes. Any programming teacher knows that any design will work for small classroom exercises, but large software applications require discipline and creativity. Likewise, as Web sites grow, small software weaknesses that had no initial noticeable effects can lead to failures (reliability problems), usability problems, and security breaches. Designing and building Web software applications that scale well represents one of today’s most interesting and important software development challenges. Maintainability One novel aspect of Web-based software systems is the frequency of new releases, or the update rate. Traditional software involves marketing, sales, and shipping or even personal installation at customers’ sites. Because this process is expensive, software manufacturers usually collect maintenance modifications over time and distribute them to customers simultaneously. For a software product released today, developers will start collecting a list of necessary changes. For a simple change (say, changing a button’s label), the modification might be made immediately. But the delay in releases means that customers won’t get more complex (and likely important) modifications for months, perhaps years. Web-based software, however, gives customers immediate access to maintenance updates—both small changes (such as changing the label on a button) and critical upgrades can be installed immediately. Instead of maintenance cycles of months or years, Web sites can have maintenance cycles of days or even hours. Although other software applications have high maintenance requirements, and some research has focused on “on the fly” maintenance10 for specialized applications, frequent maintenance has never before been necessary for such a quantity of commercial software.
Internet
Another ramification of the increased update rate has to do with compatibility. Users do not always upgrade their software; hence, software vendors must ensure compatibility between new and old versions. Companies can control the distribution of Web software to eliminate that need, although Web applications must still be able to run correctly on several Web browsers and multiple versions of each browser. Another possible consequence of the rapid update rate is that developers might not feel the same need to fix faults before release—they can always be fixed later. I have seen no data to indicate this is happening. Time to market This has always been a key business driver and remains important for Web software, but it now shares the spotlight with other quality attributes. Most of the software industry continues to give priority to first to market. Given the other factors discussed here, however, the requirement for patience can and must impact the process and management of Web software projects. Analysis Software researchers, practitioners, and educators have discussed these criteria for years. No type of application, however, has had to satisfy all of these quality attributes at the same time, and Web software components are coupling more loosely than any previous software applications. In fact, these criteria have until recently been important to only a small fraction of the software industry. They are now essential to the bottom line of a large and fast growing part of the industry, but we do not yet have the knowledge to satisfy or measure these criteria for the new technologies used in Web software applications. Technology changes The commercial use of the Internet and Web has grown explosively in the past five years. In that time, the Internet has evolved from primarily being a communications medium (email, files, newsgroups, and chat rooms) to a vehicle for distributing information to a full-fledged market channel for e-commerce. Web sites that once simply displayed information for visitors have become interactive, highly functional systems that
GIF images
HTTP server
Browser HTML forms
CGI programs
Helpers Audio Video
Database
Client side
Files
Server side
let many types of businesses interact with many types of users. These changes have had an enormous impact on software engineering. As the use of the Internet and Web has grown, the amount, type, and quality of software necessary for powering Web sites has also grown. Just a few years ago, Web sites were primarily composed of static HTML files, so-called “soft brochures,” usually created by a single Webmaster who used HTML, JavaScript, and simple CGI scripts to present information and obtain data from visitors with forms. Figure 1 illustrates the early Web, a typical client-server configuration in which the client is a Web browser that people use to visit Web sites that reside on different computers, the servers, and a software package called a Web server sends the HTML files to the client. HTML files contain JavaScripts, which are small pieces of code that are interpreted on the client side. HTML forms generate data that are sent back to the server to be processed by CGI programs. This very simple model of operation can support relatively small Web sites. It uses small-scale software, offers little security, usually cannot support much traffic, and offers limited functionality. This was called a two-tier system because two separate computers were involved. The Web’s function and structure have changed drastically, particularly in the past 24 months, yet most software engineering researchers, educators, and practitioners have not yet grasped how fully this change affects engineering principles and processes. Web sites are now fully functional software systems that provide business-to-customer e-commerce, business-to-business e-commerce, and many
Figure 1. Firstgeneration Web sites followed a client-server model that suffices to support simple page viewing and limited traffic but does not scale well.
March/April 2002
IEEE SOFTWARE
29
Network
Client
Web server
Figure 2. Modern Web sites generally follow an N-tier model that, by separating presentation from business logic, supports much greater application complexity, higher traffic, and stronger site security.
30
IEEE SOFTWARE
Middleware
Middleware
Application servers
services to many users. Instead of referring to visitors to Web sites, we now refer to users, implying much interaction. Instead of Webmasters, large Web sites must employ Web managers leading diverse teams of IT professionals that include programmers, database administrators, network administrators, usability engineers, graphics designers, security experts, marketers, and others. This team uses diverse technologies including several varieties of Java (Java, servlets, Enterprise JavaBeans, applets, and JavaServer Pages), HTML, JavaScript, XML, UML, and many others. The growing use of third-party software components and middleware represents one of the biggest changes. The technology has changed because the old two-tier model did not support the high quality requirements of Web software applications. It failed on security, being prone to crackers who only need to go through one layer of security on a computer that is, by definition, open to the world to provide access to all data files. It failed on scalability and maintainability because as Web sites grow, a twotier model cannot effectively separate presentation from business logic, and the applications thus become cumbersome and hard to modify. It failed on reliability: whereas previous Web software generations relied on CGI programs, usually written in Perl, many developers have found that large complex Perl programs can be hard to program correctly, understand, or modify. Finally, it failed on availability because hosting a site on one Web server imposes a bottleneck: any server problems will hinder user access to the Web site. Figure 2 illustrates current Web site software. Instead of a simple client-server model, the configuration has expanded first to a three-tier model and now more generally to an N-tier model. Clients still use a browser to visit Web sites, which are hosted and deliv-
March/April 2002
Database server
ered by Web servers. But to increase quality attributes such as security, reliability, availability, and scalability, as well as functionality, most of the software has been moved to a separate computer—the application server. Indeed, on large Web sites, a collection of application servers typically operates in parallel, and the application servers interact with one or more database servers that may run a commercial database. The client-server interaction, as before, uses the Internet, but middleware—software that handles communication, data translation, and process distribution—often connects the Web and application servers, and the application and database servers. New Web software languages such as Java are easier to modify and program correctly and permit more extensive reuse. These features enhance maintainability, reliability, and scalability. The N-tier model also permits additional security layers between potential crackers and the data and application business logic. The ability to separate presentation (typically on the Web server tier) from the business logic (on the application server tier) makes Web software easier to maintain and expand in terms of customers serviced and services offered. Distributed computing, particularly for the application servers, allows the Web application to tolerate failures and handle more customers, and allows developers to simplify the software design. Newer design models11,12 have extended these goals even further. JavaServer Pages (JSPs) and Enterprise JavaBeans (EJBs) let developers separate presentation from logic, which helps make software more maintainable. To further subdivide the work, developers can create a software dispatcher that accepts requests on the Web server tier, then forwards the request to an appropriate hardware or software component on the application tier. Such design strategies lead to more
reliable software and more scalable Web sites. Of course the technology keeps changing, with the latest major addition to the technology being Microsoft’s .NET. As of this writing, it is too early to say what type of effect .NET will have, although it does not seem to provide additional abilities beyond what is already available. Clearly, modern Web sites’ increased functionality creates a need for increasingly complex software, system integration and design strategies, and development processes. This leads to two exciting conclusions: ■
■
One of the largest and fastest-growing software industry segments finds itself in dire need of the high-end software engineering practices and processes that researchers and educators have been developing and teaching for years. The new models for Web-based software production and deployment require that we adapt or replace many of the research solutions available now.
These conclusions imply that we need significant research progress, education, and training in diverse software engineering areas. The software that drives the Web has become a critical part of the world’s infrastructure. Although Web software’s immaturity poses significant risk to both industry and government, it also represents an opportunity for software engineering researchers and educators. Planning for the future One more important issue remains: the lack of engineers skilled in Web software development. A recent study from the US National Research Council found that the current base of science and technology is inadequate for building systems to control critical software infrastructure.2 Much of Web software is built from existing systems and involves complicated analysis to effectively compose and integrate these components into systems. Yet the combination of a shortage of skilled IT engineers and the large number of IT jobs means companies often resort to hiring engineers who have less skills and education than desired. As a small example, US universities graduate approximately 25,000 bachelor degrees in computer science every year, but industry recently esti-
mated that it needs more than 200,000 IT professionals.2 Even with the current economic downturn, the university output is not enough. If universities could double the production of computer scientists, we still could not put a dent in the need. (Most economists and business leaders currently believe last year’s many layoffs and bankruptcies in the e-commerce sector resulted from temporary problems, and expect significant growth in the near future. I optimistically accept this prognosis; if it is wrong, then this article will be irrelevant anyway.) We can only meet this need by ■ ■
■
Retraining experienced engineers to work with the new technology Applying knowledge and technology to increase efficiency, thereby reducing the number of engineers needed Finding ways to let people with less education and skills contribute
Although Web software’s immaturity poses significant risk to both industry and government, it also represents an opportunity for software engineering researchers and educators.
We are already seeing some progress in all three of these directions: ■
■
■
Training classes and university courses in Web software engineering technologies are increasing and experiencing very high enrollment. The Web software engineering courses at George Mason University are oversubscribed every semester, with some students being nondegree professionals seeking to improve their marketability. New textbooks, tools, languages, and standards are emerging to make Web software engineering knowledge more accessible and easier to learn, use, and deploy. For example, several XML innovations in the past year have made it a more useful and accessible language, while new development tools and refinements in the standards for JSPs and EJBs allow more software to be created with less effort. Automated technologies have recently allowed nonprogrammers to contribute more to Web software development. When HTML was first introduced, an HTML writer needed to fully know the language and be proficient with a text editor to create Web pages. Recent tools provide point-and-click ability to create Web pages that can even be enhanced with dynamic HTML and JavaScripts March/April 2002
IEEE SOFTWARE
31
while requiring very little knowledge of HTML and programming. Achieving the high quality requirements of Web software represents a difficult challenge. Although other segments of the software industry have already mastered some of these, such as the need for reliability in telecommunications and network routing, aerospace, and medical devices, they have typically done so by hiring the very best developers on the market, using lots of resources (time, developers, and testing), or relying on old, stable software and technologies. Unfortunately, these solutions will not work for Web applications. There are simply not enough of the best developers to implement all the Web software needed today, and few but the largest companies can afford to invest extra resources in the form of time, developers, and testing. Finally, it should be obvious that old, stable software technologies will not suffice as a base for the Web—it relies on the latest cutting-edge software technology. Although the use of new technology involves some risk, it allows us to achieve otherwise unattainable levels of scalability and maintainability. Indeed, technological innovations in just the past three years have greatly advanced the field, both in breadth and depth. And research progresses: New conferences appear almost monthly, and traditional conferences feature more tracks and papers on Web software issues. Every new PhD student, it seems, wants to write a thesis on some aspect of Web software engineering, and more textbooks and classes teach Web software application material. When George Mason University offered a graduate course in Web software engineering in Fall 2000, the class immediately became popular, with a large waiting list.
About the Author Jeff Offutt is an associate professor of information and software engineering at George Mason
University. His current research interests include software testing, analysis and testing of Web applications, object-oriented program analysis, module and integration testing, formal methods, and software maintenance. He received a PhD in computer science from the Georgia Institute of Technology. He served as program chair for ICECCS 2001 and is on the editorial boards for IEEE Transactions on Software Engineering, Journal of Software Testing, Verification and Reliability, and Journal of Software and Systems Modeling. He is a member of the ACM and IEEE Computer Society. Contact him at the Dept. of Information and Software Eng., Software Eng. Research Lab, George Mason Univ., Fairfax, VA 22030-4444; [email protected]; www.ise.gmu.edu/faculty/ofut.
32
IEEE SOFTWARE
March/April 2002
W
eb software engineering presents challenging and unique research problems. We currently lack the knowledge to create Web software of sufficient complexity or quality and that can be updated quickly and reliably. Although Web software engineering has significant differences from traditional software engineering, we can adapt much of what we already know to understanding and resolving these differences. Not only are we making extraordinary progress, we are also bringing much research of the past 20 years to fruition. Indeed, this is an exciting time to be a software engineer.
Acknowledgments This work is supported in part by the US National Science Foundation under grant CCR-98-04111.
References 1. T.A. Powell, Web Site Engineering: Beyond Web Page Design, Prentice Hall, Upper Saddle River, N.J., 2000. 2. F.B. Schneider, Trust in Cyberspace, National Academy Press, Washington, D.C., 1999. 3. President’s Information Technology Advisory Committee, Information Technology Research: Investing in our Future, tech. report, Nat’l Coordination Office for Computing, Information, and Communications, Washington, D.C., 1999; www.ccic.gov/ac/report. 4. D.A. Menascé, Scaling for E-Business: Technologies, Models, Performance, and Capacity Planning, Prentice Hall, Upper Saddle River, N.J., 2000. 5. E. Dustin, J. Rashka, and D. McDiarmid, Quality Web Systems: Performance, Security, and Usability, AddisonWesley, Reading, Mass., 2001. 6. L.L. Constantine and L.A.D. Lockwood, Software for Use: A Practical Guide to the Models and Methods of Usage Centered Design, ACM Press, New York, 2000. 7. S. Murugesan and Y. Deshpande, “Web Engineering: A New Discipline for Development of Web-Based Systems,” Web Engineering 2000, Lecture Notes in Computer Science 2016, Springer-Verlag, Berlin, 2001, pp. 3–13. 8. N. Kassem and the Enterprise Team, Designing Enterprise Applications with the Java 2 Platform, Enterprise Edition, Sun Microsystems, Palo Alto, Calif., 2000. 9. J. Nielsen, Designing Web Usability, New Riders Publishing, Indianapolis, Ind., 2000. 10. M.E. Segal and O. Frieder, “On-the-Fly Program Modification: Systems for Dynamic Updating,” IEEE Software, vol. 10, no. 2, Mar. 1993, pp. 53–65. 11. Wrox Multi Team, Professional Java Server Programming, J2EE edition, Wrox Press, Chicago, 2000. 12. A. Scharl, Evolutionary Web Development, SpringerVerlag, Berlin, 2000.
For more information on this or any other computing topic, please visit our Digital Library at http://computer.org/publications/dlib.
focus
engineering Internet software
Server-Side Design Principles for Scalable Internet Systems Colleen Roe and Sergio Gonik, GemStone Systems
Today’s Internet systems face real challenges in trying to serve many concurrent users. n today’s Internet systems, nothing is constant but change. If you build a successful site they will come—and boy, will they come. Consequently, designers today are faced with building systems to serve an unknown number of concurrent users with an unknown hit rate and transactionsper-second requirement. The key to designing and maintaining such systems is to build in scalability features from the start, to create Internet systems whose capacity we can incrementally increase to satisfy ramping demand.
I
This article explores the design principles guiding the creation of scalable systems. Each principle is discussed and followed by examples of its application. 34
IEEE SOFTWARE
Any application can essentially be characterized by its consumption of four primary system resources: CPU, memory, file system bandwidth, and network bandwidth. Scalability is achieved by simultaneously optimizing the consumption of these resources and designing an architecture that can grow modularly by adding more resources. This article looks at the underlying principles needed to achieve such designs and discusses some specific strategies that exploit these principles. The principles of scalable architecture Relatively few design principles are required to design scalable systems. The list is limited to ■ ■
leverage multiple hardware platforms or simply separate processes or threads, thereby dispersing the load in the system and enabling various forms of load balancing and tuning. D&C varies slightly from the concept of modularization in that it addresses the partitioning of both code and data and could approach the problem from either side. One example is replicated systems. Many applications can, in fact, be broken into replicated instances of a system. Consider an insurance application that is deployed as five separate but identical systems, each serving some specific geography. If load increases, more instances are deployed, and all running instances now service a smaller geography. Another example is functional–physical partitioning. A system that processes orders is broken into two components: an ordertaking component and an order-satisfaction component. The order-taking component acquires order information and places it in a queue that is fed into the order-satisfaction component. If system load increases, the components might run on two or more separate machines. Asynchrony Asynchrony means that work can be carried out in the system on a resource-available basis. Synchronization constrains a system under load because application components cannot process work in random order, even if resources exist to do so. Asynchrony decouples functions and lets the system schedule resources more freely and thus potentially more completely. This lets us implement strategies that effectively deal with stress conditions such as peak load. Asynchrony comes at a price. Asynchronous communications are generally more difficult to design, debug, and manage. “Don’t block” is probably the most important advice a scalable-system designer can receive. Blocking = bottlenecks. Designing asynchronous communications between systems or even between objects is always preferable. Moreover, use background processing where feasible. Always question the need to do work online in real time. A little lateral thinking can sometimes result in a solution that moves some work into background processing. For example, order satisfaction can include a background process that
emails an appropriate notification to the user on completion. Encapsulation Encapsulation results in system components that are loosely coupled; ideally, there is little or no dependence among components. This principle often (but not always) correlates strongly with asynchrony. Highly asynchronous systems tend to have well-encapsulated components and vice versa. Loose coupling means that components can pursue work without waiting on work from others. Layers and partitions are an example of the application of encapsulation. Layers and partitions within layers are the original principles that drive software architecture. The concepts might be old, but they are still legitimate. Layers provide well-insulated boundaries between system parts, and they permit reimplementation of layers without perturbation to surrounding layers. Work can be carried out independently within layers.
The more concurrency an application exploits, the better the possibilities to expand by adding more hardware.
Concurrency Concurrency means that there are many moving parts in a system. Activities are split across hardware, processes, and threads and can exploit the physical concurrency of modern symmetric multiprocessors. Concurrency aids scalability by ensuring that the maximum possible work is active at all times and addresses system load by spawning new resources on demand (within predefined limits). One example is to exploit multithreading. Question the need to carry out work serially. Look for opportunities to spawn threads to carry out tasks asynchronously and concurrently. You can also accommodate expansion by adding more physical platforms. Concurrency also maps directly to the ability to scale by rolling in new hardware. The more concurrency an application exploits, the better the possibilities to expand by adding more hardware. Parsimony Parsimony means that a designer must be economical in what he or she designs. Each line of code and each piece of state information has a cost, and, collectively, the costs can increase exponentially. A developer must ensure that the implementation is as efficient and lightweight as possible. Paying attention to thousands of microdetails in March/April 2002
Application Handle exceptions Invoke services Maintain conversational state Mediation between presentation and service
Services Domain service Single behavior services External services Object distribution Transaction control Use case control
Domain Business behavior Semantic validation
Persistence Basic CRUD services OR mapping Transaction support Profiling
Figure 1. Layers and their responsibilities in a service-based architecture.
a design and implementation can eventually pay off at the macrolevel with improved system throughput. Parsimony also means that designers must carefully use scarce or expensive resources. Such resources might be cached or pooled and multiplexed whenever possible. This principle basically pervades all the others. No matter what design principle a developer applies, a parsimonious implementation is appropriate. Some examples include ■
■
■
■
Algorithms. Ensure that algorithms are optimal to the task at hand. Everyone knows that O(n) algorithms are preferable to, say, O(n2), but sometimes this is overlooked. Several small inefficiencies can add up and kill performance. Object models. Pare object models to the bone. Most large object models with many object-to-object relationships are expensive to instantiate, traverse, process, or distribute. We sometimes have to compromise a model’s purity for a simpler and more tractable model to aid system performance. I/O. Performing I/O, whether disk or network, is typically the most expensive operation in a system. Pare down I/O activities to the bare minimum. Consider buffering schemes that collect data and do a single I/O operation as opposed to many. Transactions. Transactions use costly resources. Applications should work outside of transactions whenever feasible and go into and out of each transaction in the shortest time possible.
Strategies for achieving scalability Strategies are high-level applications of one or more design principles. They are not design patterns but rather entities that encompass a class of patterns. Given a strat36
IEEE SOFTWARE
March/April 2002
egy, we can articulate multiple patterns that embody its semantics. Careful system partitioning A scalable system’s most notable characteristic is its ability to balance load. As the system scales up to meet demand, it should do so by optimally distributing resource utilization. For Java-based Internet systems, load balancing maps to a well-distributed virtual machine (VM) workload from Web client hits. For other systems, the workload is distributed among operating system processes. Partitioning breaks system software into domain components with well-bounded functionality and a clear interface. In object terms, a domain component is “a set of classes that collaborate among themselves to support a cohesive set of contracts that you can consider black boxes.”1 Each component defines part of the architectural conceptual model and a group of functional blocks and connectors.2 Ultimately, the goal is to partition the solution space into appropriate domain components that map onto the system topology in a scalable manner. Principles to apply in this strategy include D&C, asynchrony, encapsulation, and concurrency. Service-based layered architecture During design, a service-oriented perspective facilitates the definition of appropriate components and data-sharing strategies. A service encapsulates a subset of the application domain into a domain component and provides clients contractual access to it. By making services available to a client’s application layer, service-based architectures (see Figure 1) offer an opportunity to share a single component across many different systems. Having a services front end lets a component offer different access rights and visibility to different clients. In a sense, services do for components what interfaces do for objects. Domain
components are shared by different remote systems, each having its own contractual view of the component. This paradigm is helpful in Web-enabled enterprise application integration (EAI) solutions.3 A service-based architecture not only aids scalability by statically assisting in proper component design; it also offers dynamic benefits. For example, Enterprise JavaBeans’ stateless session beans help implement a service layer that supports dynamic scalability by enabling multiplexed access from different clients—through bean implementation sharing (see http://java.sun.com/products/ejb/ docs.html). We would gain further benefits if we pooled stateless session bean interfaces in the Web server tier. Each interface would be associated with a preactivated bean implementation living in a middle-tier VM. We could then use these interfaces to load balance across the VMs. Principles to apply in this strategy include D&C and encapsulation. Just-enough data distribution The primary principle for object distribution is parsimony: distribute out as little data as possible. For an object to be distributed outward, it must be serialized and passed through memory or over a network. This involves three system resources: ■
■
■
CPU utilization and memory in the server to serialize the object and possibly packetize it for travel across the network Network bandwidth or interprocess communication activity to actually transmit to the receiver CPU utilization and memory in the receiver to (possibly) unpacketize, deserialize, and reconstruct the object graph
Hence, an object’s movement from server to receiver comes at a fairly high cost. There are two benefits of just-enough data distribution: it diminishes the bandwidth needed to flow data through the system, and it lessens the amount of data a process contains at any particular point in time. Let’s step back and look at the big picture. Suppose a large e-commerce application services 10,000 concurrent users. Each user must receive data. Now suppose the amount of information sent to a client increases by 10 Kbytes per hit. The total
amount of additional information the system would thus have to send to service all its clients would increase by 100 Mbytes. Because large-scale systems serve many users, relatively small increases in the amount of data sent to an individual client are magnified thousands of times. Seemingly small increases can have a significant impact on total system throughput. There are quite a few guidelines for keeping just the right amount of data in the right place at the right time. The next several paragraphs describe some techniques. Use lazy initialization strategies to fetch only the frequently used fields when an object is first instantiated and initialized. Lazy initialization schemes can save significant database querying, but a designer must understand what fields are most commonly used in a class to devise a good scheme. Be forewarned that too much lazy initialization is a bad thing. A design must balance the costs of bringing more data over at object initialization time against the need to go back to the database again and again to fetch more fields. Use state holders to pass requested data from the back end to the presentation layer. State holders represent a flattening of the object graph into one object containing all the pertinent data for a particular business case. A service-based layered architecture supports this concept well because services tend to be associated with subsets of data from domain model graphs. In C and C++, data is commonly passed around by reference because having a shared memory view is easy. VMs have private memory, and Java does not offer pointer functionality directly, so application data tends to be passed by value. Current Java technologies offer a shared memory view across VMs, and some offer transactional access to shared data and even persistence in native object format. This kind of technology can help optimize performance. If direct reference is not possible, use a key system for passing data identity. Keys can, for example, define catalog data associated with a Web page. Instead of sending the whole catalog to the user’s browser, an initial view is sent and follow-up views are populated as necessary based on returned request keys. Sharing read-only data can significantly improve scalability by cutting down on database queries and subsequent I/O. In a Java 2
A servicebased architecture not only aids scalability by statically assisting in proper component design: it also offers dynamic benefits.
March/April 2002
IEEE SOFTWARE
37
The world is moving in the direction of alerting and notification, which are push-based paradigms. Consequently, even transactional requests are increasingly handled asynchronously.
Enterprise Edition application, many users might execute in the same VM. Each user can avoid acquiring its own copy of data by sharing read-only copies across all users. Do not underestimate the impact of object distribution. In our experience, it is often the primary determinant of system viability in distributed systems. Principles that apply in this strategy include parsimony and D&C. Pooling and multiplexing Pooling is an effective way to share and reuse resources, which can be expensive in terms of memory usage (for example, large object graphs) or overhead (such as object instantiation, remote object activation, and relational database [RDB] connections). Initialization for remotely accessed resources is especially expensive because various protocols at different layers come into play. Furthermore, these resources have hard limits (such as the availability of ports) and scalability constraints on the remote server software itself. Pooling in general and multiplexing connections in particular are solutions that optimize resource sharing and reuse. Some examples of resources that might be pooled include Java database connectivity (JDBC) connections, RDB connections, buffers, EJBs, and ports. Multiplexing lets many actors share one resource. The paradigm is especially valuable when accessing back-end systems using JDBC connections or the like. Here are some approaches to pooling: ■
■
Manage pool resources dynamically, creating resources on an as-needed basis and letting resources be reaped after a set time. One option is to use a background process to wake up at preset epochs and remove unused resources. The pool can then dynamically meet changing system load requirements throughout the day. Always test for resource validity before use when managing resources whose life cycle you do not fully control.
The main principle that applies in pooling is parsimony. Queuing work for background processes Queuing lets a foreground resource serv38
IEEE SOFTWARE
March/April 2002
ing an interactive user delegate work to a background process, which makes the foreground resource more responsive to the user. Queuing can also permit work prioritization. Data warehouse searches, object cache synchronization with a back-end RDB, and message-broker-based EAI integration are all examples of candidates for asynchronous decoupled interaction. If a designer uses a priority scheme, he or she can map it to various queues to increase throughput by using concurrent dispatching. Careful management of the number of queues and their relative priority can enhance scalability. Queue content dispatched to domain components in other processes, perhaps using a messaging subsystem, affords an opportunity for load balancing. Designers can accomplish load balancing by ■
■
■
Replicating functionality into various processes and apportioning the number of queued requests sent to each process, possibly with a weighting factor for each request based on its memory, I/O, and computational resource usage Partitioning functionality into various processes and apportioning according to type the queued requests sent to each process, again possibly with a weighting factor Combining these schemes to apportion requests according to type and number
The key here is to always try to tease apart a design issue so that it can be handled asynchronously. Resist the trap of assuming everything must be synchronous. Consider that even customer access from a Web browser does not necessarily require synchronous response (response at the application level, not the HTTP level). For example, an online customer need not necessarily wait for credit card approval. A designer could set up a merchandise payment use case so that an email message is sent with the purchase confirmation sometime after the purchase. The world is moving in the direction of alerting and notification, which are push-based paradigms. Consequently, even transactional requests are increasingly handled asynchronously. Often it makes sense to run queued jobs on a scheduled basis. In this kind of queuebased batching, a background process is
scheduled to wake up during nonpeak production system hours and service all outstanding requests. This enhances scalability by spreading system usage across time. Principles to apply in this strategy include D&C, asynchrony, and concurrency. Near real-time synchronization of data It is common for designers to assume that in Web applications transactional changes must be instantly reflected in all federated databases of record. The problem is that synchronous distributed transactions are costly. Solutions such as two-phase commits increase network load, create multiple points of failure, and generate multiple wait states where the transaction time is bounded by the slowest system. Transactions rarely have to be synchronously distributed across all involved systems. For example, a data warehouse update can typically withstand some transactional delay, because it is not part of a realtime business process. In this case, the delay could be on the order of a few seconds (or more), but even critical systems might be able to handle synchronization latencies of a few hundred milliseconds. Near real-time synchronization assists scalability by spreading the system’s transactional load across time. In converting real-time synchronous distributed transactions into near real-time asynchronous ones, the best recourse is to choose a single database as the primary database of record. This primary database serves as the synchronization resource for all others.4 Principles that apply in this strategy include D&C, asynchrony, and concurrency. Distributed session tracking Generally, session tracking is maintained on a Web server either through cookies or by server-specific internal mechanisms. This limits load balancing across servers because clients must always be routed back through the same server so that their session state is available. Routing users to any Web server on a request-by-request basis is preferable because HTTP is designed to optimize this kind of resource usage. One architectural solution, called distributed session tracking, places the shared view of session state in a persistent store visible to all Web servers. A client can be routed to any server, and the session state will still be available. Typically,
the persistent store is an RDB. Distributed session tracking results in better load balancing, but it comes at a cost. If a designer uses the same RDB system for session tracking and business-related transactions, the load on the RDB increases considerably. There is also the overhead of having to object-to-relational map session state. A better solution for implementing distributed session tracking is to use a secondary lightweight RDB, an object database (ODB), or, better yet, an object cache with shared visibility across VMs. Principles that apply in this strategy include D&C and concurrency.
End-user satisfaction with a site is highly correlated with the speed at which information is rendered.
Intelligent Web site load distribution Perhaps the prime characterization of an Internet application is the requirement to transport files of all kinds around the network in an efficient manner. End-user satisfaction with a site is highly correlated with the speed at which information is rendered. However, rendering covers a whole plethora of possibilities—simple HTML pages, pictures, streaming audio or video, and so on. A well-designed Web site can handle many concurrent requests for simple HTML files, but entities such as streaming video involve much larger demands. For a busy Web site, it could be literally impossible to handle peak loads in a reasonable manner. The solution is to replicate these static, highbandwidth resources to better manage the load. Incoming HTTP requests redirect to the mirrored facilities based on some combination of available server and network capacity. This can be accomplished internally or by subscribing to one of the commercial providers who specialize in this type of service. Principles that apply in this strategy include D&C, asynchrony, and concurrency. Keep it simple Donald A. Norman warns in the preface to The Design of Everyday Things, “Rule of thumb: if you think something is clever and sophisticated, beware—it is probably self-indulgence.”5 The software development cycle’s elaboration phase is an iterative endeavor, and customer requirements need constant reevaluation. Complicated solutions make refactoring harder. In accordance with Occam’s Razor, when faced with two design approaches, choose the simpler one. If the March/April 2002
IEEE SOFTWARE
39
ear: it is iterative, recursive, and sometimes anticipatory. Consequently, design does not progress through the following steps in a linear fashion. Rather it loops and cycles through them (see Figure 2).
Design conceptual view
Map basic topology
>
Define domain components
Scale domain components
Scale topology
Tune system
Figure 2. The scalability design process. To simplify the diagram, we chose stereotypes instead of branches. The stereotypes and should be clear from the main text. The > stereotype guarantees that new domain component functionality translates back to the conceptual view.
simpler solution proves inadequate to the purpose, consider the more complicated counterpart in the project’s later stages. Putting it all together Although the complete mapping of a problem domain into a solution space is beyond this article’s scope, this section offers up a process for system partitioning. Each step in the process uses strategies presented in the previous sections. The nature of design is decidedly nonlin40
IEEE SOFTWARE
March/April 2002
Design conceptual view Create a conceptual view of the architecture, defining appropriate domain-specific functional blocks and connectors that follow good responsibility-driven design principles.6 This breaks down a solution space into functional components with an encapsulated set of responsibilities, appropriate communications protocols, and connectors to manage those protocols. Map basic topology Map the conceptual view into an initial system topology. This exposes all system stakeholders in the architecture—legacy systems, data sources, server hardware, middleware, and so on. Identify the role each system plays in the overall design and its responsibilities, needs, and constraints. For legacy systems, identify usage patterns. In keeping with the KISS principle, start with a minimal setup, such as one VM or process per tier, one Web server, and so on. Identify systems that are candidates for using replication, pooling, data-partitioning schemes, and so forth. Define domain components For each system in your topology, group functional blocks into domain components. It is at this stage that a designer should consider existing layering paradigms to assist in the grouping. In particular, consider a service-based layered architecture.7 Also, at this point, third-party software components should be considered because they present previously defined interfaces and usage constraints. Domain components should also be designed to best use available standards, so match a domain component with a standard’s APIs. In terms of initial scalability concerns, group the functional blocks initially to minimize communication bandwidth and coupling. Check created domain component candidates for possible queued background processing or, possibly, batched processing. Identify transaction flow between domain components and, whenever possible, avoid distributed transactions.
About the Authors Scale domain components Now relax the single VM or process per tier constraint. Refactor the domain components to optimize for data distribution and resource use. This might mean redefining functional blocks or their grouping into new domain components, placing different domain components in different processes, or replicating domain components into two or more processes. Load-balance work among the processes, and benchmark and measure process memory, CPU usage, and I/O bandwidth to identify well-balanced configurations. Analyze where some I/O-bound or computationally intensive domain components should have their own processes. Balance refactoring metrics against communication bandwidth between processes. Interprocess communication should not cause a huge performance hit compared to the single process phase (at some point, the price of communication outweighs the advantages of domain component distribution). Identify candidates for multiplexed resources. Keep an eye on the back end and see how it plays transactionally across your processes. Are transactional deadlines being met? Are resources across processes participating correctly in each transactional use case? Scale topology Now move back to your initial system topology definition and double the number of systems that you qualified as good candidates in mapping a basic topology. At this point, it might be necessary to incorporate some hardware routing scheme or some new component such as a Java messaging system queue. Replicating systems such as those contained in Web servers most likely will lead to replication of associated processes. For Web server replication in particular, consider distributed session tracking as an option for load balancing. Tune system Finally, based on previous refactoring observations, increase the number of qualified systems (domain servers, content servers, Web servers, databases of record, and so forth) and domain components to meet your production load demand. Ask how the current system and domain component distribution should be refactored to handle future load demand increases. At this point, the application space is partitioned in a scal-
Colleen Roe is chief architect at GemStone Systems and has been designing and developing software systems since kindergarten (or at least that’s how it feels). She has experience in several industry sectors including telecommunications, oil, manufacturing, software, and pharmaceuticals, and has developed everything from embedded systems to expert systems. Her current research focus is scalable architectures for large e-commerce J2EE-based systems. Contact her at GemStone Systems, 1260 NW Waterhouse Ave., Ste. 200, Beaverton, OR 97006; [email protected].
Sergio Gonik is a lead architect at GemStone Systems, where he currently focuses on next-generation large-scale e-business distributed systems. He has 13 years of experience in the field and has designed diverse software architectures for scientific, embedded, medical, music, and J2EE e-commerce systems. He is also a professional composer and performer who has written and executed musical pieces for theater, dance, and film. Contact him at GemStone Systems, 1260 NW Waterhouse Ave., Ste. 200, Beaverton, OR 97006; [email protected].
able manner, so there should be a clear path to handling load increases. If no such clear path exists, restart the process by redefining the architectural functional blocks or their grouping into domain components.
T
his article addresses many strategies that are important when designing scalable architectures, but our list is not exhaustive. Rather, it represents what we believe to be the most critical strategies for server-side scalability. Unfortunately, space limitations made it impossible to include an actual example of a well-designed scalable system built on these principles. The principles are important guidelines, but they are not a substitute for measurement. Throughout a system’s design and implementation, testing and benchmarking what you’re building to ensure that desired scalability is achieved is important. Software projects should always follow a motto— “benchmark early and benchmark often.” Acknowledgments We thank Anita Osterhaug and John Cribbs for their insightful comments and suggestions. We never would have made it without them.
References 1. S.W. Ambler, “Distributed Object Design,” The Unified Process: Elaboration Phase, R&D Books, Lawrence, Kan., 2000. 2. C. Hofmeister, R. Nord, and D. Soni, Applied Software Architecture, Addison-Wesley, Reading, Mass., 2000. 3. D.S. Linthicum, Enterprise Application Integration, Addison-Wesley, Reading, Mass., 2000. 4. C. Britton, IT Architectures and Middleware: Strategies for Building Large Integrated Systems, Addison-Wesley, Reading, Mass., 2001. 5. D. Norman, The Design of Everyday Things, Doubleday, New York, 1988. 6. R. Wirfs-Brock, B. Wilkerson, and L. Wiener, Designing Object-Oriented Software, Prentice Hall, Englewood Cliffs, N.J., 1990. 7. GemStone A3Team, “I-Commerce Design Issues and Solutions,” GemStone Developer Guide, GemStone Systems, Beaverton, Ore., 2000.
March/April 2002
IEEE SOFTWARE
41
focus
engineering Internet software
Usage-Centered Engineering for Web Applications Larry L. Constantine and Lucy A.D. Lockwood, Constantine & Lockwood
espite breathless declarations that the Web represents a new paradigm defined by new rules, professional developers are realizing that lessons learned in the pre-Internet days of software development still apply. Web pages are user interfaces, HTML programming is programming, and browser-deployed applications are software systems that can benefit from basic software engineering principles.
D
This model-driven approach to software engineering, focusing on user interface design and usability, proves especially appropriate for Web applications. 42
IEEE SOFTWARE
Nevertheless, development for the Web faces difficulties that standard development does not. Three challenges come to the fore. First, the Web development process must be highly accelerated—“Web time” has become synonymous with headlong desperation and virtually impossible deadlines. Second, many Web projects are “green-field” applications, which means they have few if any standards or precedents. Finally, much more so than standard software, Web applications must focus on the user experience. Systematic, disciplined practices might help developers face these challenges, but traditional approaches proliferate documents and deliverables and emphasize analysis of established practices—a poor match for novel applications with Web-time delivery schedules. Furthermore, user interface design and usability are generally weak points in both the heavyweight software en-
Table 1 User-centered and usage-centered design: A comparison quire costly manual follow-up or lead to lost sales. Web-usability guru Jakob Nielsen estimates that billions of dollars in lost Web sales can be traced to usability problems. Technical and customer support costs in all areas of business are skyrocketing. Every time usability problems on a site or application prompt a telephone call or an email message to customer service, an inexpensive Web session becomes an expensive support incident. On corporate intranets, hard-touse applications require extensive training or go completely unused. Although this article focuses on Webbased applications—systems that deploy functional capability on the Web through a browser instance as a thin client—it is difficult to draw a hard and fast line separating Web-based applications from those Web sites that are intended for use, that is, for something more than entertainment, “branding,” or the like. The common thread is the delivery of useful services and capabilities over the Web. In addition to usability, aesthetic design aspects also figure in the user experience. Unfortunately, graphic design and aesthetic considerations are often established early and drive the entire development process at the expense of usability. For example, based on an “aesthetic brief” approved by a client’s CEO, a prominent graphic design house developed an innovative Web site for a major analyst group. Although the designers consulted extensively with the firm’s customers and conducted numerous marketoriented focus groups, the design proved a usability disaster, in no small part because of the aesthetic design. Last-ditch efforts to make improvements without modifying the basic graphic design enabled the site to go live but ultimately proved merely palliative and insufficient to satisfy customers. In the end, the firm redesigned the site completely, this time approaching the project with usage-centered design.4 Usage-centered design Usage-centered design uses abstract models to systematically design the smallest, simplest system that fully and directly supports all the tasks users need to accomplish. Developed in the early 1990s, the approach has been applied to systems ranging from industrial automation systems and consumer elec-
User-centered design
Usage-centered design
Focus is on users: User experience and user satisfaction Driven by user input Substantial user involvement • User studies • Participatory design • User feedback • User testing Design by iterative prototyping Highly varied, informal, or unspecified processes Design by trial and error, evolution
Focus is on usage: Improved tools supporting task accomplishment Driven by models and modeling Selective user involvement • Exploratory modeling • Model validation • Usability inspections Design by modeling Systematic, fully specified process Design by engineering
tronics to banking and insurance applications. The streamlined process, driven by simple models, scales readily; developers have used it on projects ranging from a few person-months to the five-designer, 19developer, 23-month project that produced Step7lite, a sophisticated integrated development environment from Siemens AG (see http://foruse.com/pcd). On the Web, groups have employed usage-centered design successfully for applications in fields including ecommerce, membership support, education, and medical informatics.5 User-centered or usage-centered? Usage-centered design evolved as a software engineering alternative to user-centered design. Table 1 summarizes some of the salient differences. User-centered design is a loose collection of human-factors techniques united under a philosophy of understanding users and involving them in design. It relies primarily on three techniques: user studies to identify users’ desires, rapid paper prototyping for user feedback on user interface design iterations, and usability testing to identify problems in working prototypes or systems. Although helpful, none of these techniques can replace good design. User studies can easily confuse what users want with what they truly need. Rapid iterative prototyping can often be a sloppy substitute for thoughtful and systematic design. Most importantly, usability testing is a relatively inefficient way to find problems you can avoid through proper design.4,6 Driving models. Role, task, and content models—simple, closely related abstract modMarch/April 2002
IEEE SOFTWARE
43
Withdraw Money The use case begins when the client inserts an ATM card. The system reads and validates the information on the card. 1. System prompts for PIN. The client enters PIN. The system validates the PIN. 2. System asks which operation the client wishes to perform. Client selects “Cash withdrawal.” 3. System requests amounts [sic]. Client enters amount. 4. System requests type. Client selects account type (checking, savings, credit). 5. The system communicates with the ATM network to validate account ID, PIN, and availability of the amount requested. 6. The system asks the client whether he or she wants a receipt. This step is performed only if there is paper left to print the receipt. 7. System asks the client to withdraw the card. Client withdraws card. (This is a security measure to ensure that Clients do not leave their cards in the machine.) 8. System dispenses the requested amount of cash. 9. System prints receipt. 10. The use case ends.
Figure 1. Conventional use case for getting cash from an ATM.9
Figure 2. Abstract use case in essential form—the “getting cash” task case.
els—drive usage-centered design. The role model captures the salient characteristics of the roles that users play in relation to a system. The task model represents the structure of the work users need to accomplish with the system. The content model represents the user interface’s contents and organization. A user role represents one kind of relationship users could have with a system. Among numerous possible aspects of this relationship are the purpose and frequency of interaction, the volume and direction of information exchange, and the attitude toward the system of users in the role. A task model comprises a set of task cases 44
IEEE SOFTWARE
March/April 2002
and a map of the interrelationships among those task cases. Task cases are a form of use cases,7 which conventionally are models of systems—namely, the “sequence of actions a system performs that yields an observable result to a particular actor.”1 As commonly written, use cases express the concrete actions and responses taken by the system and an actor with which it interacts. Figure 1, a published example of a conventional use case,1 tellingly omits the user’s single most important step: actually taking the cash. Task cases—also called essential use cases4—are essential models8 that are abstract, simplified, and technology-free—that is, they have no built-in assumptions about the user interface. For example, the task case of Figure 2, written in the style used in agile usage-centered design, is shorter, simpler, and closer to the essence of the user task than that of Figure 1. The advantages of essential use cases are widely recognized, and a consensus is building that this style is best for both user interface design and requirements modeling in general.9 The third model, the content model,4 is sometimes called an abstract prototype: It abstractly represents the user interface’s contents—independent of actual appearance or behavior—and how these are organized into the contexts within which users interact, called interaction contexts. Abstract prototypes can range from a simple inventory of a site’s or application’s accessible contents to a highly structured abstract model based on a canonical set of abstract components (see http://foruse.com/articles/ canonical.pdf). Regardless of the form, abstract prototypes are a bridge between task models and realistic or representational prototypes, such as conventional paper prototypes or design sketches. By adhering to a user perspective and leaving open the various implementation possibilities, abstraction encourages innovative visual and interaction designs.4,10 Process overview. Figure 3 shows a logical
overview of usage-centered design. The process separates system actors—other software and hardware systems—from human actors who are users. The role, task, and content models are developed in coordination with and interlinked with other models. These include a domain model (such as a
Task cases User roles Actors
Abstract prototypes Behavior Step1
Step2
Figure 3. Logical process of usage-centered design.
1. 1.Loquom Asdhf asdf ipso 2.Wertw rt bzc 3.Ouiaa ero
Visual and interaction design
System actors
glossary or another more elaborate data model), a business rules model that embodies the application’s underlying logic and constraints,11 and an operational model that captures salient aspects of the working environment or operational context.3 Conceptually, a straightforward and direct derivation links the final design back to task cases supporting user roles. Each page, form, or other interaction context corresponds to an abstract prototype supporting a cluster of interrelated task cases. The designer derives the actual buttons, links, tables, displays, and other features directly from abstract components that realize specific steps within supported task cases. These task cases, in turn, support the roles that users can perform. Usage-centered Web design Over successive Web projects, usagecentered design has evolved a lightweight form that takes certain modeling and design shortcuts (see http://foruse.com/articles/ agiledesign.pdf). Agile usage-centered design employs rapid-fire modeling techniques using ordinary index cards for brainstorming, sorting, and clustering,12 as in Extreme Programming.2 When practical, collaborative modeling with end users, application domain experts, and clients can save additional time. Figure 4 outlines an agile usagecentered design process. Essential purpose and preconception. Web
projects often suffer from vague objectives and unrealistic ambitions. Early clarification of objectives and exploration of fantasies can pay off enormously.13 We prefer
to kick off the process by involving managers, users, developers, and other stakeholders in framing the application’s purposes as external users and from a business perspective. The group can brainstorm onto cards and sort them to establish priorities. Similarly, we encourage participants to share their fantasies about the system’s features, functions, facilities, content, and capabilities, but we clearly label these ideas preconceptions and set them aside to be treated as negotiable fantasies rather than requirements. Exploratory modeling. Exploratory modeling jumpstarts the design process by identifying questions and areas of uncertainty or ambiguity in user requirements. The team does this by sketching out rough versions of the role and task models that it will develop in more refined form later. In this way, the team can identify needed, but missing, information. User interface architecture. Many agile processes3 abjure up-front design in favor of a more evolutionary approach—constructing a limited system and then elaborating it through successive iterations. Unfortunately, when code starts small and gradually grows with expanding requirements, the original architecture—the code’s underlying organization—often proves insufficient or inappropriate to support emerging needs. Refactoring,14 in which existing code is reorganized and rewritten to fit evolving and emerging requirements, is a key to successful evolution of complex software systems through iterative expansion. March/April 2002
IEEE SOFTWARE
45
Preliminary steps 1. Essential purpose and preconception—Clarify business and user purposes, then fantasize and set aside preconceptions of features, facilities, content, and capabilities. 2. Exploratory modeling—Identify questions, ambiguities, and areas of risk and uncertainty. First iteration 3. Role modeling—Inventory and prioritize all user roles and select initially targeted subset. 4. Task modeling—Inventory and prioritize all tasks and select initially targeted subset. 5. Task clustering—Group all tasks by affinity and draft overall navigation architecture. 6. Design—Draft visual and interaction scheme; review and revise aesthetic design. 7. Abstract prototyping—Develop content model for interaction contexts supporting selected subset of tasks. 8. Design—Develop detailed user interface design for selected interaction contexts. 9. Construction—Program designed portions of user interface. Successive iterations (similarly) 3a. Review role model and revise as needed, select next subset. 4a. Review task model and revise as needed, select next subset. 5a. Review navigation architecture and revise as needed. 6a. Review visual and interaction scheme and revise as needed. 7a. Develop content model for interaction contexts supporting next selected task subset. 8a. Design user interface for selected interaction contexts. 9a. Construct newly designed portions. Figure 4. Rough outline of steps in an agile usage-centered design process.
User interfaces are a different story. Late refinement of the user interface’s basic structure is not acceptable because it changes the system for users who have already learned or mastered an earlier version. Whereas refactored internal software components don’t necessarily affect users, a redesigned user interface architecture is unavoidably disruptive. For highly usable user interfaces, we design the overall organization, navigation, and look and feel to fit the full panoply of tasks to be covered. You don’t have to design every aspect of the user interface in advance, however. To avoid radical refactoring or inconsistency across design increments, you need to work out a well-conceived overall map of the site or application in advance.15 To insure that the basic visual style and be46
IEEE SOFTWARE
March/April 2002
havior are effective across the entire application, you must devise a comprehensive design scheme. Navigation architecture specifies how the overall user interface breaks down into interaction contexts, collections, and groups; how these are presented to users; and how users navigate them. Minimally, the navigation architecture identifies all the interaction contexts and their interconnections, but having more is advantageous. For example, the navigation architecture might organize parts of the user interface into tabbed notebooks—accessed through a set of command buttons on a central dispatch dialog—with sections within notebook pages reached through shortcuts in a menu-like bar across the top of each page. Another crucial facet of overall user interface design is the visual and interaction scheme, a sort of abstract style guide. It briefly describes the basic visual elements that will recur throughout the design as well as the common layouts, visual arrangements, or templates that apply to various interaction contexts.16 The scheme might, for example, specify a basic layout grid with a modified tree-view in the left-most column for primary navigation and a set of view controls across the top for secondary navigation. At a more detailed level, it might specify that a distinct color should identify all editable fields, which can be edited in place by double clicking. It might further spell out how certain collections of controls will be placed on slide-out tool panels that automatically open on mouse-over and close after use. Clearly, a sound navigation architecture and visual and interaction scheme requires a complete task model that includes all identified tasks, not just those to be tackled on the first or early iterations. Card-based modeling. The initial user role
model is a simple inventory of roles users can play in relation to the site or application. One of the quickest ways to develop such an inventory is to brainstorm it directly onto index cards. Once we’ve agreed on the initial inventory, we succinctly describe roles directly on their index cards using the characteristics most relevant to the design problem: the role’s context, characteristic patterns of interaction within the
role, and special support criteria. We then sort the completed cards to rank them by overall importance. After reviewing the roles in order of importance, we brainstorm an inventory of task cases, again onto index cards. As we review and refine this inventory—condensing, combining, eliminating, or adding tasks— we standardize the names to convey the basic purpose from a user’s perspective, such as “finding a replacement part for a specific product” or “adding an assessment to a lesson plan.” Once we’ve established the initial set of task cases, we sort the cards to rank them for expected frequency and for overall importance. Based on these two rankings, we deal them into three piles: required (do first), desired (do if there’s time), and deferred (do next time). At this point, we start to fill in the details, but not for all task cases. We skip task cases for which the interaction appears obvious or routine. For task cases that are critical, complex, unclear, or interesting, we write the interaction narrative on the index card. Working on small cards favors good modeling discipline. If the process narrative doesn’t fit on one card, either the narrative is not sufficiently abstract and simplified, or the card really covers multiple task cases that we must identify. Using all the knowledge built from creating, refining, and interacting with the task cases, we group the cards into affinity clusters on the basis of how strongly they seem to be related—particularly, how likely users in a role will perform tasks together. Each cluster represents a set of capabilities that the application must offer together—within the same page, form, or browser window, or at least within a set of closely connected interaction contexts. Each task cluster becomes the guide for designing a part of the user interface. We prefer to construct abstract prototypes but under pressure could move directly into sketching realistic paper prototypes. We then evaluate the paper prototypes, augmented by a description of how the various elements behave, to identify usability problems and areas for improvement. For speed and convenience, we prefer collaborative usability inspections,3 involving users and clients as well as designers and developers, but recognize the effectiveness of heuristic
inspections and other techniques. In practice The approach we took to designing a browser-resident classroom information management system illustrates the ad hoc accommodations an agile process often needs for development in Web time. A sophisticated performance-support system to empower K–12 classroom teachers, this system simplified key administrative, planning, and teaching tasks in an environment fully integrated with existing administrative systems and software and with Web-based learning resources. The application was deployed through a Web-based technology with the client-side user interface realized in HTML, XML, and Java JFC/Swing. Risk factors were numerous, including a new and unproven development team in a new company, an outside consulting team for user interface design, the need for technical breakthroughs in several areas, vague and ambiguous requirements exacerbated by frequent changes in scope, and management obsessed with early delivery, frequent demonstrations, and unpredictable changes of direction. The design team collaborated with a team of PhD-level educators with extensive classroom experience. This education team served as both domain experts and representative end users, while also functioning in what amounted to an XP-style customer role.2 Collaboratively with the education team, the design team developed the initial user role model and inventory of task cases. In total, we identified and prioritized 14 user roles. The initial inventory of 142 task cases included 35 task cases related to lesson planning, which emerged as a critical capability for the system. We wrote process narratives for only a handful of interesting task cases.1 We constructed a draft navigation map with just over 40 interaction contexts, based on task case clustering (see Figure 5). To resolve problems with the design and omissions, irregularities, and ambiguities in the requirements, we held frequent meetings and consulted continually with the education team—a pattern we now refer to as JITR, just-in-time requirements. One of the two designers concentrated on requirements and scope issues, while the other began working on the initial design.
Each task cluster becomes the guide for designing a part of the user interface.
March/April 2002
IEEE SOFTWARE
47
Figure 5. Webdeployed classroom information management system: Main portion of the navigation map.
48
IEEE SOFTWARE
The design team devised drafts of a navigation architecture, navigation map, and visual and interaction scheme, validated them with the education team, then revised them. Not entirely by plan, the design proceeded in two- to two-and-a-half-week cycles. Once full-time design work started, we completed an initial navigation architecture and visual and interaction scheme within the first cycle. We finished the first version of the complete visual and interaction design in the next cycle, after which we inspected it for usability defects, and we undertook a major design revision on the second iteration. In the third iteration, we continued to extend and refine the design, spread over the remainder of the project’s 17-week usage-centered design portion. Programming followed an agile, lightweight process that proceeded in parallel with visual and interaction design. We needed a design that would be immediately usable by ordinary teachers
March/April 2002
with little or no special training. It had to be flexible enough to accommodate a wide range of working styles and efficient to use, given that teachers may typically have less than 15 minutes a day to plan an entire day’s lessons. Technical goals that we identified based on the usability criteria included ■ ■ ■ ■
Minimize window management overhead. Minimize modal behavior. Allow simple and direct switching among contexts. Maximize available screen real estate for document and data display.
A discussion of the complete design is beyond this article’s scope (for details, see our design studies on the Web, www. foruse.com/articles/designstudy1.pdf, /designstudy2.pdf, and /designstudy3.pdf). However, the first design iteration’s results clearly illustrate the importance of early,
up-front consideration of the overall navigation architecture and the visual and interaction scheme based on a full understanding of user roles and tasks. Neither traditional software engineering practices nor the newer lightweight methods make this possible. Figure 5 shows the main portion of the navigation map, as finalized in the second iteration. The mock-up in Figure 6, adapted directly from actual design documents produced in the project’s first cycle, illustrates how we documented the overall navigation and visual and interaction design scheme. Together, these design documents specified much of the user interface’s overall architecture. Understanding the various roles classroom teachers play and thoroughly exploring their tasks revealed the importance of a fast, flexible, and easy-to-learn scheme for navigating the application’s various working contexts. Once we understood the task structure, we organized the various groups and interaction contexts for single-click switching among tasks within any given activity. Using simple visual metaphors based on thumb tabs, hanging folders, and file folders, we devised a three-level visible hierarchy that proved far easier to learn and
use than a conventional Windows-style tree view. Screen real estate, always a scarce resource, is particularly valuable in an application running within a browser instance on low- to moderate-resolution displays. To address this, the design scheme included components that would expand and contract or reveal and hide themselves automatically as needed. For example, the toplevel navigation panel (containing thumb tabs) contracts to provide more working space once the user selects a starting point. Figure 6 shows another example of screen space conservation in the dynamic workspace, which anticipated rather than mimicked the Apple OS-X dock. The workspace provides a compact holding bin that lets the user gather various documents or fragments from a variety of personal and public resources for assembly into a lesson plan or assignment. Any product design’s success is ultimately measured by its acceptance. Classroom teachers in a variety of settings made immediate use of this application with only minimal instruction. In fact, we were able to achieve the stringent design objective of enabling immediate, productive use of the system based on a single-page tutorial.
Figure 6. Navigation architecture and design scheme, classroom information management system.
March/April 2002
IEEE SOFTWARE
49
Further Reading L. Constantine, Constantine on Peopleware, Prentice Hall, Upper Saddle River, N.J., 2001. R. Jeffries, A. Anderson, and C. Hendrickson, Extreme Programming Installed, Addison-Wesley, Reading, Mass., 2001. J. Nielsen and R.L. Mack, eds., Usability Inspection Methods, John Wiley & Sons, New York, 1994.
O
ur experiences in agile usage-centered design have made clear that improved usability does not come without cost or risk, even when the methods are streamlined and the schedule is compressed. Special training and skills are necessary, and these may not be available to every development group, especially the lean teams typical in agile development. Moreover, the best design is easily corrupted by casual or even well-intentioned alterations and elaborations during coding. Close coordination between user interface designers and programmers is essential, and programmers must be fully committed to the process and convinced of the benefits even if they do not understand every design decision. A flexible and condensed usage-centered design process is a good starting point for collaboration, but for agile practices such as Extreme Programming, which abjures anything resembling BDUF (big design up front), some of the rules and philosophy can get in the way. Just which rules need to be
About the Authors Larry L. Constantine is an adjunct professor of information technology, University of Technology, Sydney, Australia, and director of research, Constantine & Lockwood, Ltd. A methodologist who pioneered fundamental concepts and techniques underlying modern software engineering theory and practice, he now focuses on methods for improving the usability of software and hardware. A consultant and designer with clients around the world, he shared the 2001 Performance-Centered Design award for his work with Siemens AG. He is a graduate of MIT’s Sloan School of Management, a member of the IEEE Computer Society and the ACM, and he has served on the boards of numerous professional journals, including IEEE Software. Contact him at [email protected]. Lucy A.D. Lockwood is president of Constantine & Lockwood, Ltd., the design, training, and consulting firm she cofounded. One of the developers of usage-centered design, she is the coauthor of a Jolt Award-winning book on the subject. With a passion for teaching and professional communication, she has chaired several professional conferences and is co-organizer of forUSE 2002, the first international conference on usage-centered, performance-centered, and task-oriented design. She is a graduate of Tufts University and a member of the IEEE and the ACM. Contact her at [email protected].
50
IEEE SOFTWARE
March/April 2002
bent or rewritten and what philosophy may need to be compromised is the subject of much current debate and experimentation. The outline presented here should be regarded more as a draft than as a definitive model.
References 1. P. Kruchten, The Rational Unified Process: An Introduction. Addison-Wesley, Reading, Mass., 1999. 2. K. Beck, Extreme Programming Explained, AddisonWesley, Reading, Mass., 2000. 3. M. Fowler, “Put Your Processes on a Diet,” Software Development, vol. 8, no. 12, Dec. 2000. Expanded version at www.martinfowler.com/articles/newMethodology.html. 4. L.L. Constantine and L.A.D. Lockwood, Software for Use: A Practical Guide to the Models and Methods of Usage-Centered Design, Addison-Wesley, Reading, Mass., 1999. 5. J. Anderson et al., “Integrating Usability Techniques into Software Development,” IEEE Software, vol. 18, no. 1, Jan./Feb. 2001, pp. 46–53. 6. A. Parush, “Usability Design and Testing,” ACM Interactions, vol. 8, no. 5, Sept./Oct. 2001. 7. I. Jacobson et al., Object-Oriented Software Engineering: A Use Case Driven Approach, Addison-Wesley, Reading, Mass., 1992. 8. S.M. McMenamin and J. Palmer, Essential Systems Analysis, Prentice Hall, Englewood Cliffs, N.J., 1984. 9. L.L. Constantine and L.A.D. Lockwood, “Structure and Style in Use Cases for User Interface Design.” M. van Harmelan, ed., Object Modeling an User Interface Design, Addison Wesley, Reading, Mass., 2001. 10. D. Corlett, “Innovating with OVID,” ACM Interactions, vol. 7, no. 4, July/Aug. 2000. 11. E. Gottesdiener, “Rules Rule: Business Rules as Requirements,” Software Development, vol. 7, no. 12, Dec. 1999. Reprinted in L.L. Constantine, ed., Beyond Chaos: The Expert Edge in Managing Software Development, Addison-Wesley, Reading, Mass., 2001. 12. R. Jeffries, “Card Magic for Managers: Low-Tech Techniques for Design and Decisions,” Software Development, vol. 8, no. 12, Dec. 2000. Reprinted in L.L. Constantine, ed., Beyond Chaos: The Expert Edge in Managing Software Development, Addison-Wesley, Reading, Mass., 2001. 13. L.A.D. Lockwood, “Taming the Wild Web: Business Alignment in Web Development,” Software Development, vol. 7, no. 4, Apr. 1999. Reprinted in L.L. Constantine, ed., Beyond Chaos: The Expert Edge in Managing Software Development, Addison-Wesley, Boston, 2001. 14. M. Fowler, Refactoring: Improving the Design of Existing Code, Addison-Wesley, Reading, Mass., 1999. 15. M.H. Cloyd, “Designing User-Centered Web Applications in Web Time,” IEEE Software, vol. 18, no. 1, Jan./Feb. 2001, pp. 62–69. 16. J. Pokorny, “Static Pages Are Dead: How a Modular Approach Is Changing Interaction Design,” ACM Interactions, vol. 8, no. 5, Sept./Oct. 2001.
For more information on this or any other computing topic, please visit our Digital Library at http://computer.org/publications/dlib.
focus
engineering Internet software
Objects and the Web Alan Knight, Cincom Systems Naci Dai, ObjectLearn
pplying software engineering principles, particularly object-oriented techniques, to the Web can be difficult. Many current Web technologies lend themselves to—or even encourage—bad practices. Scripting and server-page technologies can encourage cutand-paste reuse, direct-to-database coding, and poor factoring. Component models such as the Component Object Model (COM) and Enterprise JavaBeans (EJB) seek to construct building blocks for application assembly, but in doing so they sacrifice many of the advantages of objects. XML emphasizes
technology-independent reuse and sharing of content, data, and messaging but at the expense of encapsulation and the association of behavior with state, which is central to OO. Scripting languages, common on the Web, are often optimized for rapidly creating simple functionality rather than for modular construction of large programs. Also, such languages typically lack the rich development environments of general-purpose languages. Some Web developers even deliberately disregard software engineering principles. They argue that if we’re just writing scripts, they don’t merit the kind of engineering techniques—object or otherwise—we apply to “real” systems. However, software engineering and OO techniques are gaining importance in Web development as Web applications become more complex and integrated with traditional server-side applications. To motivate
the need for these techniques, we examine some representative Web technologies and the issues they present in naive use. We describe a layered, OO architecture, based on the Model-View-Controller (MVC) pattern, which can overcome these issues to produce large, well-structured systems. Motivations If we consider scripts from an OO and layering perspective, the most immediate problem is that a single script has responsibilities spanning several layers (see the “Definitions” sidebar for an explanation of our terminology). The script must ■ ■ ■ ■
This couples all the layers together, making March/April 2002
IEEE SOFTWARE
51
Definitions Here we define our terminology and goals. In the main text, we present a layered architecture, implemented using both scripts and server pages. Most of these techniques can be applied to any technology in these categories, but where the details of a specific technology are important, we use servlets and JavaServer Pages as representative technologies. Both, while nominally Java specifications, can easily be applied to other languages, and implementations in both Smalltalk and C++ are commercially available.
ing business functionality. This code should be entirely unaware of the presentation being used. We also refer to business objects, which implement the business logic. In a complex application, business logic is likely to be the largest component and can include code that accesses external systems such as databases, external components, and other services. In the ModelView-Controller framework, this corresponds to the model.
Presentation This layer contains code and noncode resources (such as HTML text and images) used to present the application. It typiLayered architecture cally contains little code—code concerned only with formatting A layered architecture is a system containing multiple, and presenting data. An example of this in a Web context is a strongly separated layers, with minimal dependencies and interactions between the layers. Such a system has good separa- server page’s code fragments that print values into a dynamition of concerns, meaning that we can deal with different areas cally generated Web page. In the Model-View-Controller of the application code in isolation, with minimal or no side ef- framework, this corresponds to the view. fects in different layers. By separating the system’s different pieces, we make the software adaptable so that we can easily Scripts Many basic Web technologies can be grouped together in change and enhance it as requirements change. The layers we are concerned with here include input, application logic, busi- the category of scripts—small programs that perform HTTP processing. This term encompasses, among others, compiled CGI ness logic, and presentation. programs, files of scripting language code (such as Perl, Python, Ruby, and VBScript), and Java servlets. While there are Input The input layer contains the code concerned with processing significant differences among these technologies, all of them have the fundamental characteristic of being programs that acand syntactically validating input. In a Web context, this procept an HTTP request and send back a response. In basic uscessing and syntactically validating input includes HTTP input parsing and extracting parameters from an HTTP request. In the age, each script is stateless and independent of all others. An Model-View-Controller framework, this corresponds to the input important distinction within this category is whether scripts can share memory with other scripts (for example, servlets) or are controller. entirely independent (for example, CGI programs). Shared memory allows more effective use of system resources through Application logic pooling, and a simpler programming model through persistent The application logic code is concerned with the applicastates at the cost of a more complex infrastructure. tion’s overall flow. We often refer to it as the glue layer, separating business logic from input and presentation logic and Server pages managing the interface between the two. This requires some An alternative mode of HTML scripting is that of an HTML knowledge of both layers. For example, this layer would be involved in converting between presentation-level inputs and out- page annotated with small amounts of code. Many scripting lanputs as strings and the corresponding business object messages guages support this kind of facility in addition to pure scripts, and or state. This layer might also manage a multipage Web inter- representative examples include JavaServer Pages (JSP), Microsoft’s Active Server Pages, PHP, and Zope. There are also variaction as a sequence of steps. In the Model-View-Controller ations on this approach in which the pages are annotated with framework, this corresponds to the application controller. application-specific HTML or XML tags, and developers can specify code to be run when these tags are encountered. Examples of Business logic The business logic code is concerned only with the underly- this include JSP bean and custom tags and Enhydra’s XMLC.
it harder to modify or test any particular aspect in isolation. In addition, there are significant issues related to handling these responsibilities, as described below. For server pages used alone, the same issues apply (because we can consider a server as a script with some additional embedded HTML), and mixing code with the HTML also presents code management and debugging issues. 52
IEEE SOFTWARE
March/April 2002
Accepting input When accepting input, a script receives either the raw HTTP input stream or a minimally parsed representation of it. HTTP supports several different mechanisms for passing parameters (encoding into the URL, query values, or form data), and all of these pass the data as simple strings. Each script must know or determine the parameter-passing mechanism, convert the parameters to
appropriate types, and validate them. This causes code duplication between scripts. Handling application logic Another issue, which affects both input and application logic, is the lack of information hiding when accessing request and session data. The script must retrieve input data from the request by name. HTTP is a stateless protocol, so data used in multiple scripts must be either stored in a session identified with the user or reread from an external data source in each script requiring the data. For example, if a script passes login information as form data, the code to store that information in the session might be password = request.getParameter (“passwordField”); decrypted = this.decode (password); request.getSession().putValue (“password”,decrypted);
Both storage in the session and storage in an external data source are effectively global in scope, and the application accesses them in dictionary-like fashion using strings as keys. Normal programming mechanisms for controlling variable access do not apply to this data, and any scripts or server pages that wish to use this data must be aware of the naming conventions. We cannot easily find all accesses to the variables using programming-language mechanisms, so modifications become more difficult. If the script does not encapsulate these conventions, knowledge of them and of the HTTP protocol’s details can spread throughout the application, greatly hindering adaptation to new uses. Furthermore, this is a potential source of errors because of both spelling errors and different scripts using the same name for different purposes. As the number of scripts or server pages increases, these problems become overwhelming. When using server pages for application logic, we are adding potentially significant amounts of code to the page. Code management techniques are not usually available for code inside server pages. With many technologies, debugging code inside the server pages is difficult. Features of modern development environments for code authoring and interactive debugging might not be available, and for compiled languages we might need to
debug inside complex generated code. For these reasons, it is a good idea to minimize the amount of code in server pages and to keep application logic out of the pages. Handling business logic Because all of the code is grouped together, it is difficult to isolate the business logic from the other layers, particularly application logic. Furthermore, unless we can run portions of the scripts separately, it is impossible to test the business logic (or any of the other layers) independently. With server pages, business logic presents the same issues that we discussed for application logic. We can very quickly have too much code in the pages, and even pages with minimal code are difficult to manage and debug.
It is a good idea to minimize the amount of code in server pages and to keep application logic out of the pages.
Generating output In producing output, simple scripts mix the HTML encoding of the result with the dynamic data. This couples the page’s look and feel with the other layers. Changing the Web site’s look or adapting the application to multiple output devices becomes extremely difficult. The latter is becoming increasingly important as the Web expands to include devices such as WAP (Wireless Application Protocol)-connected mobile phones and other small devices. Server pages help address this last issue by letting Web designers design and maintain the pages and by letting programmers provide annotations. This is generally considered the most appropriate use for server pages. Model-View-Controller To overcome these difficulties, we can use a combination of scripts, server pages, and application code. The approach we present here is part of a family of possible approaches we have used1,2 to properly partition responsibilities and overcome weaknesses in the underlying technologies (see the “A Related Approach” sidebar for a comparison). MVC strongly influences our approach, so we first examine its history. MVC concepts MVC originated in the Smalltalk-80 system to promote a layered approach when developing graphical user interfaces.3 It emerged in the late 1970s and early 1980s, long before such March/April 2002
IEEE SOFTWARE
53
A Related Approach There are many frameworks and design patterns influenced by layering, the Model-View-Controller pattern, and object principles. In general, using servlets and server pages together and keeping code out of the server pages as much as possible is referred to in Java circles as model 2 Web programming (see http://java.sun.com/j2ee). The most widely known framework using these principles is the open source Jakarta Struts (see http://jakarta.apache.org/struts). Struts is a controller framework for Java to build JavaServer Pages-based views that are linked to business models using a single controller servlet. Struts is very close to many of our concepts and also uses a single input controller servlet, but it differs in some significant areas. Most notably, it does not distinguish a separate application controller, distinguishing only
Model
Notifications
input, action, presentation, and model. Application controller responsibilities are assigned to actions, model objects, or declarative aspects of the framework. Actions are command objects, and Struts suggests that they should delegate as much behavior as possible to the model, but coding examples include application control or even model behavior in some actions. The transition to the next page after an action is controlled by the developer by editing configuration files. One other difference is that Struts classifies model objects into “bean forms” that have only state, and more normal objects with both function and behavior. These bean forms are used to store data for input or presentation processing. We have no corresponding layer and are unclear as to the role of pure state objects in an OO framework.
View
Display
Controller
Keyboard, mouse
(a)
Application Notifications controller Business objects
View
Notifications Input controller
Business logic layer
(b)
Problem space
Figure 1. (a) The original Smalltalk-80 Model-View-Controller pattern and (b) the revised Model-ViewController.
Tool layer
View layer
User interface
interfaces had become mainstream. It defined three different components (see Figure 1a): ■ ■ ■
The model handles application and business logic. The view handles presentation logic. The controller accepts and interprets keyboard and mouse input.
The intention was to separate the model (meaning nonGUI) code from its presentation. The model code didn’t contain any GUI information, but it broadcast notification of any 54
IEEE SOFTWARE
March/April 2002
state changes to dependents, which were typically views. This is similar to many current GUI component models, of which JavaBeans is perhaps the most widely known. This scheme provided a good separation between these three layers but suffered from two weaknesses. First, it had a simplistic view of the model and did not account for any difference between application logic (for example, flow of control and coordination of multiple widgets in a GUI) and business logic (for example, executing a share purchase). Second, most GUI libraries and windowing systems combined the view and controller functions in a single widget, making the logical separation into view and controller less useful. Later versions of Smalltalk with operating system widgets chose not to use a separate controller. All of the Smalltalk versions eventually introduced an additional layer to handle application logic, distinct from the business objects. Perhaps the most elegant of these is Presenter, as used in, for example, Taligent and Dolphin Smalltalk.4,5 Together, these revisions changed the common understanding of the framework, such that the term controller now refers to the object handling application logic and the term model is reserved for business objects (see Figure 1b). To distinguish these two interpretations of MVC, we use model to refer to business objects, and we use input controller and application controller to refer to the two types of controllers. MVC for the Web To apply MVC to the Web, we use a combination of scripts, server pages, and ordinary objects to implement the various components in a framework we call Web Actions. In this context, both versions of the
WAP
MVC are relevant, particularly the dual uses of the term controller. For HTTP applications, input and presentation are entirely separate, so an input controller distinct from the view is useful. For applications of any complexity, we also need an application controller to separate the details of application flow from the business logic. Figure 2 shows the framework’s basic object structure. Input controller. We implement the input controller as a script. One of the framework’s important features is that there is a single input controller for all pages in a Web application. The input controller parses input, determines the parameter-passing mechanisms, extracts any necessary information from the request, cooperates with the application controller to determine the next action, and invokes that action in the correct context. By having a single script as an input controller, we localize any knowledge of HTTP or naming conventions at the request level, reduce code duplication and the total number of scripts, and make it easier to modify any of the input processing, because there is a single point of modification. Note that the input controller class is shown as an abstract class, with one implementation for accessing the applications over HTTP with a regular Web browser and another implementation for accessing the applications using a WAP-enabled device. Application controller. We implement the application controller as a regular object—not as a script or server page. It coordinates logic related to the application flow, handles errors, maintains longer-term state (including references to the business objects), and determines which view to display. We store the application controller in the session using a key known to the input controller. This relies on a naming convention, with the disadvantages described earlier, but because this is the only thing stored directly in the session, the impact is minimized. A single application controller is responsible for multiple Web pages. In a simple application, it might be responsible for all pages; in a complex application, there are multiple application controllers for different areas of the application. By using a single, well-encapsulated ob-
WAP input controller Input controller
HTTP
HTTP input controller
Application controller
Finds and executes
Action
XML view
XML
JavaServer Page view
JavaServer Page
View
Figure 2. The Web
ject as the central point of reference for any Actions framework. persistent information, the application controller resolves the issues of information hiding and naming conventions. Rather than storing isolated pieces of information in the session, we store them in business objects and access them using messages from the application controller. Programminglanguage mechanisms let us track use of the application controller and business objects and more easily modify our code. If we are using a statically typed language, we also get static type checking as an additional validation of data usage. Action. The single input controller will invoke one of many possible actions on each request. One of its responsibilities is to determine which one. This depends on both the input from the user and on the application’s current state, so it must be determined in conjunction with the application controller. We represent the result of this determination as an Action object (an implementation of the Command pattern described elsewhere6). Business objects. We implement business objects as normal objects that contain only business logic, so they should have no knowledge of any other layers. The application controller is the only thing that manipulates the business objects, and for this reason they are not shown in Figure 2 but are inside the application controller. Both of these attributes make it much easier to develop and test the business logic in isolation from the Web infrastructure. Because the business objects March/April 2002
IEEE SOFTWARE
55
Figure 3. Java code for an input controller servlet.
might be isolated, we should be able to use the same implementation for a thin-client Web application, a more rich-client implementation, or even a traditional GUI. View. We implement views as server pages, which can access the application controller and business objects. Views should contain as little code as possible, delegating most functionality to the application controller or business objects. Only code directly related to presentation in the current page should be used in a page. If supported, we prefer to use a tag mechanism such as JavaServer Pages (JSP) custom tags to remove code from the pages altogether. Figure 2 shows two different view mechanisms. The first uses a server page implementation, appropriate for a Web browser or WAP device. The second generates the same information in an XML format, which could be sent to an applet, an ActiveX control, or a GUI application.
Web actions: Control flow By organizing the scripts, server pages, and regular objects as we’ve described, we’ve overcome many of the issues associated with simple Web development. We have minimized code duplication and reliance on the protocol’s details or naming conventions by using a single input script. We have also achieved good information hiding by maintaining the data in objects rather than as flat session data. We have confined our use of server pages to the view layer, maximizing the amount of code we can manage and debug using standard programming tools and methods. By keeping each layer separate, we can test each in isolation. Overall, our application remains well-factored and easy to maintain and extend. To see how this works in more detail, let’s examine the flow of control from a single Web request in an online banking appli56
IEEE SOFTWARE
March/April 2002
cation. First, we see how the input controller accepts input, finds and sets up for the action, executes the appropriate application controller code, and then delegates to the view. Figure 3 shows sample code for this, and here we examine each of the steps. Find the controller The input controller must determine which application controller is responsible for the current request. Active application controllers are stored in the session. We assume that we can determine the controller using a lookup based on the request’s path. For example, in our banking application, we might have an account maintenance application controller, which is used for any pages related to account maintenance. Accept input Once we have determined the application controller, we must extract the appropriate information from the request and transfer that information to the application controller. Most notably, we need to find any input parameters. These can be encoded as part of the URL, as query parameters listed after the URL, or as form data. Regardless of the transmission mechanism, this input consists entirely of strings and must be converted into the appropriate types and validated. The input controller extracts the information and, in cooperation with the application controller, performs basic syntactic validation and informs the application controller of the values. For example, we might have a user request to transfer funds such as https://objectbank.com/ InputController/transfer?from= 123&to=321&amt=$50.00
The string /transfer identifies the action to
the input controller. The remainder of the string holds query parameters for the two account numbers and the amount to transfer. On the other hand, a request to update account holder data might be submitted from an HTML form and would carry many pieces of data as form data, invisible in the URL: https://objectbank.com/ InputController/updateAccountData
Find the action The application controller can keep track of a set of acceptable sequences of operations and the previous steps the user has taken. On the basis of this and the information submitted in the request, we can determine which action to take and whether this action is legal in the current context. This logic is particularly important because Web users can use the Back button to throw off the sequence of operations in a way that is not possible in a GUI. In the simplest version, we might define actions for login, logout, transfer between accounts, account update, and bill payments. Any account activity is allowed once the user has logged in, but actions transferring money have a confirmation page. We only let the user confirm a request if the immediately previous operation was the request. We also detect the situation in which the user backs up and resubmits the same request or hits the Submit button repeatedly while waiting for the first submission to be processed. Perform the action Once we have determined which action to take, we must execute it. The exact procedure for this varies depending on which implementation we choose. We might choose to have heavyweight actions, implemented as objects inheriting from a class Action and implementing a trigger method. public void trigger(Controller controller){ BankController ctrlr= BankController)controller; Account acct=ctrlr.readAccount (context.getAccountNo()); ctrlr.setCurrentAccount(account); ctrlr.setNextPage(“account Summary”); }
This lets us separate the different actions, but it does not give us as much encapsulation in the application controller as we might like. Rather than the standard OO usage of multiple methods on a single object, we have many action objects that manipulate the controller’s state, providing little encapsulation. As an alternative, we can represent the action simply as an indicator of the application controller method to be performed. This is particularly easy in a system such as Smalltalk, with simple reflection techniques. Given a Smalltalk servlet and JSP framework,7 we can simply set the action action := #deposit.
and then execute controller perform: action.
Keeping code and data together in the application controller provides better encapsulation but raises potential team issues of having many people collaborating on a single object.
In this case, the action is simply the action method’s name, and we invoke it with the standard perform: method. No action class or trigger operation is necessary. Which of these choices is preferred depends on the situation. Keeping code and data together in the application controller provides better encapsulation but raises potential team issues of having many people collaborating on a single object. In a GUI presentation, it might also be desirable to use the full Command pattern to better support Undo functionality. Forward the request We use forwarding to divide responsibility among different components. Once the action is complete, we determine the URL of the next page to be displayed and forward the request. In a simple system, the actions can directly determine the next page. In a more complex system, the application controller might coordinate this using internal state management such as a state machine. Variations We have described one particular implementation of this type of framework. Many others are possible, and in our uses of this framework, we have made significant variations depending on the application’s precise needs. Complex views We have described views as mapping diMarch/April 2002
IEEE SOFTWARE
57
rectly to server pages, but in more complex applications, this can become more sophisticated. First, we can assemble larger views from multiple smaller views. So, we might have a main page with subsections in frames or with subsections determined by including the results of other Web requests. We could model this structure either by explicitly issuing new requests or by using an internal mechanism to forward the request to another partial page. We might also want to interpose another layer of objects at the view level. For example, if handling multiple possible forms of output, we might need an explicit View object that handles the output details on a particular device. For example, we might store a key that lets the View identify the appropriate output. This might delegate to different server pages for HTML and WAP presentation and to a screen identifier for a GUI. Using a View object helps isolate the presenta-
tion of an action’s results from the action itself. It is also an appropriate place to implement functionality such as internationalization of the result. Action context We have described an architecture with very lightweight actions in which state is associated directly with the application controller. In some situations, it might be useful to dissociate some of this state from the controller. In particular, if we do not have a simple mapping from the URL to the application controller, we might need to extract more of the request state to determine the correct controller. We can do this by introducing an ActionContext object, which stores the request state in a standardized form. In this case, we would create the context, use it to find the appropriate controller, and then apply actions to the combination of controller and context.
COMPUTER
PURPOSE The IEEE Computer Society is the world’s
MEMBERSHIP Members receive the monthly magazine COM PUTER , discounts, and opportunities to serve (all activities are led by volunteer members). Membership is open to all IEEE members, affiliate society members, and others interested in the computer field.
BOARD OF GOVERNORS Term Expiring 2002: Mark Grant, Gene F. Hoffnagle, Karl Reed, Kathleen M. Swigger, Ronald Waxman, Michael R. Williams, Akihiko Yamada Term Expiring 2003: Fiorenza C. AlbertHoward, Manfred Broy, Alan Clements, Richard A. Kemmerer, Susan A. Mengel, James W. Moore, Christina M. Schober Term Expiring 2004: Jean M. Bacon, Ricardo Baeza-Yates, Deborah M. Cooper, George V. Cybenko, Wolfgang K. Giloi, Haruhisha Ichikawa, Thomas W. Williams Next Board Meeting: 10 May 02, Portland OR
IEEE
OFFICERS
President: RAYMOND D. FINDLAY
President-Elect: STEPHEN L. DIAMOND* Past President: BENJAMIN W. WAH* VP, Educational Activities: CARL K. CHANG * VP, Conferences and Tutorials: GERALD L. ENGEL* VP, Chapters Activities: JAMES H. CROSS VP, Publications: RANGACHAR KASTURI VP, Standards Activities: LOWELL G. JOHNSON †
†
(2ND VP)*
VP, Technical Activities:
DEBORAH K. SCHER-
RER(1ST VP)*
Past President: JOEL B. SYNDER
Secretary: DEBORAH M. COOPER* Treasurer: WOLFGANG K. GILOI* 2001–2002 IEEE Division VIII Director:
Secretary: HUGO M. FERNANDEZ VERSTAGEN Treasurer: DALE C. CASTON VP, Educational Activities: LYLE D. FEISEL VP, Publications Activities: JAMES M. TIEN VP, Regional Activities: W. CLEON ANDERSON VP, Standards Association: BEN C. JOHNSON VP, Technical Activities: MICHAEL R. LIGHTNER President, IEEE-USA: LeEARL A. BRYANT
WEB
SITE
COMPUTER SOCIETY O F F I C E S EXECUTIVE COMMITTEE President: WILLIS K. KING* University of Houston Dept. of Comp. Science 501 PGH Houston, TX 77204-3010 Phone: +1 713 743 3349 Fax: +1 713 743 3335 [email protected]
President-Elect: MICHAEL S. ADLER Executive Director: DANIEL J. SENESE
SOCIETY
The IEEE Computer Society’s Web site, at http://computer.org, offers information and samples from the society’s publications and conferences, as well as a broad range of information about technical committees, standards, student activities, and more.
largest association of computing professionals, and is the leading provider of technical information in the field.
THOMAS W. WILLIAMS
2002–2003 IEEE Division V Director: GUYLAINE M. POLLOCK†
Executive Director:
DAVID W. HENNAGE†
*voting member of the Board of Governors
Headquarters Office 1730 Massachusetts Ave. NW Washington, DC 20036-1992 Phone: +1 202 371 0101 • Fax: +1 202 728 9614 E-mail: [email protected] Publications Office 10662 Los Vaqueros Cir., PO Box 3014 Los Alamitos, CA 90720-1314 Phone: +1 714 821 8380 E-mail: [email protected] Membership and Publication Orders: Phone: +1 800 272 6657 Fax: +1 714 821 4641 E-mail: [email protected] European Office 13, Ave. de L’Aquilon B-1200 Brussels, Belgium Phone: +32 2 770 21 98 • Fax: +32 2 770 85 05 E-mail: [email protected] Asia/Pacific Office Watanabe Building 1-4-2 Minami-Aoyama, Minato-ku, Tokyo 107-0062, Japan Phone: +81 3 3408 3118 • Fax: +81 3 3408 3553 E-mail: [email protected]
EXECUTIVE
STAFF
Executive Director: DAVID W. HENNAGE Publisher: ANGELA BURGESS Assistant Publisher: DICK PRICE Director, Volunteer Services: ANNE MARIE KELLY Chief Financial Officer: VIOLET S. DOAN Director, Information Technology & Services: ROBERT CARE Manager, Research & Planning: JOHN C. KEATON 11-FEB-2002
58
IEEE SOFTWARE
March/April 2002
Business logic and components We have not devoted a great deal of discussion to the business logic layer, because we consider it to be a normal OO program. However, it can be quite complex and involve any number of other technologies. One that frequently comes up is the relationship between this layer and components, particularly Enterprise JavaBeans. Some frameworks (when using Java) use entity EJBs as a standards-based solution for the business object layer. We do not generally consider this to be a good solution. Although the business logic layer might have good reasons for accessing components—most notably session beans encapsulating access to transactional or legacy systems—using entity beans to represent the business logic seems ill-advised. Entity beans offer some automation potential for issues such as transactions, security, and persistence, but they impose serious limits on our design and have significant performance constraints, even relative to normal Java performance. In particular, the absence of inheritance is a burden, and other frameworks exist to deal with transactions, security, and performance in the context of normal business objects. Finally, it is harder to test EJBs in isolation because they require a container to run; this imposes increased overhead on development. Using session beans to wrap business objects or forgoing EJBs altogether are both reasonable alternatives.
U
sing our framework, developers primarily focus on writing application code rather than dealing with servlets, requests, or session variables. We have used this in a variety of different Web applications, using both Smalltalk and Java. In this, we have achieved better software quality because good OO principles were not dictated but followed naturally from the structure of the framework. Paradoxically, it also allowed developers inexperienced with OO techniques to produce high-quality code without knowing the details of the framework too well. These frameworks could be extended in several different areas, including customization to particular domains, conversion into a full-fledged framework rather than a set of patterns, and more detailed adaptation to particular technologies.
Acknowledgments The authors thank Michael Ellis and Martin Fowler for their contributions to the ideas expressed here.
References 1. M. Ellis and N. Dai, “Best Practices for Developing Web Applications Using Java Servlets,” OOPSLA 2000 tutorial; www.smalltakchronicles.net/papers/Practices. pdf. 2. N. Dai and A. Knight, “Objects versus the Web,” OOPSLA 2001 tutorial; www.smalltalkchronicles.net/papers/ objectsXweb10152001.pdf. 3. E. Gamma et al., Design Patterns, Addison-Wesley, Reading, Mass., 1994. 4. G.E. Krasner and S.T. Pope, “A Description of the Model-View-Controller User Interface Paradigm in the Smalltalk-80 System,” J. Object-Oriented Programming, vol. 1, no. 3, Aug. 1988, pp. 26–49. 5. M. Potel, MVP: Model-Viewer-Presenter, tech. report, IBM, 1996; www-106.ibm.com/developerworks/ library/mvp.html. 6. A. Bower and B. MacGlashan, “Model-View-Presenter Framework,” 2001, www.object-arts.com/EducationCentre/Overviews/ModelViewPresenter.htm. 7. VisualWave Application Developer’s Guide, tech. report, Cincom Systems, 2001.
For more information on this or any other computing topic, please visit our Digital Library at http://computer.org/publications/dlib.
About the Authors Alan Knight is a senior software developer at Cincom Systems, where he works on Smalltalk Web tools. He was also recently the technical lead on a high-performance Smalltalk Web application server supporting full implementations of ASP, JSP, and servlets. His research interests include Web development, object-relational mapping, and team programming systems. He received his BS and MS in computer science from Carleton University in Ottawa, Canada. He is a member of the ACM. He coauthored Mastering ENVY/Developer (Cambridge Univ. Press, 2001). Contact him at 594 Blanchard Cr., Ottawa, Ontario, Canada K1V 7B8; [email protected]. Naci Dai is an independent mentor and an educator. He teaches object technology, Java, design patterns, and distributed computing. He leads and mentors Web development projects. He has a background in applied engineering and computational physics. He has received his PhD in mechanical engineering from Carleton University. He is a member of the ACM. Contact him at Acarkent C75, 81610 Beykoz, Istanbul, Turkey; [email protected].
March/April 2002
IEEE SOFTWARE
59
focus
engineering Internet software
Going Faster: Testing The Web Application Edward Hieatt and Robert Mee, Evant
esting is a fundamental aspect of software engineering, but it is a practice that too often falls by the wayside in today’s fast-paced Web application development culture. Often, valuable software engineering principles are discarded, simply because they are perceived as being too time-consuming and lacking a significant payoff, and testing is a common casualty. Testing is often last in developers’ minds when pressured to deliver something, anything, before the competition jumps on
T This article documents test-first design and the creation of testable code for Web applications. The authors explain how testing has been critical to building Evant’s application at speed while maintaining a high degree of quality. 60
IEEE SOFTWARE
it, the market changes, or the money runs out. Despite developers’ hard work, the resulting code is often precisely the opposite of what is desired: unstable and fragile, profoundly slowing development. Furthermore, adapting to new requirements is difficult because existing functionality must be manually retested whenever a change is made. We know that testing is the answer, but is there a way to adhere to doing it while still developing at a fast pace? We have found that a radical approach centered on testing proves highly effective in achieving rapid development. We have spent the last two years using the Extreme Programming methodology to develop e-commerce software at Evant, a Web-based ASP company. Focusing on testing and testability results in a code base that can be built on quickly and that is malleable to the extent that it can easily be changed to accommodate new customer re-
Though it might seem a tautology, practicing test-first programming leads to a pervasive quality of testability throughout the code base. By having tests in place, the overall code design is positively affected. More tests, and more features, can easily be added to designs and beneficial characteristics arise as a natural consequence of its testability. One such beneficial characteristic is reusable code. Code that is developed for a single purpose usually services a single client (meaning client code); a test provides a second client for the interface. Thus we force reuse by testing. This secondary interface exercise, and its resultant refactoring, tends to flush out design flaws that might exist in single-use code. For instance, a class B written to support class A might make inappropriate assumptions. Writing unit tests specifically for B, independent of its relationship with A, removes these assumptions, which leaves classes A and B more loosely coupled and therefore more reusable. Testable code tends to have a cleaner interface, and classes tend to be defined at a more appropriate granularity than they might otherwise be. Writing tests simply makes it more apparent when a single class’s scope is too ambitious or too reliant on the workings of another. Testing the servlet Unit testing has beneficial effects on removing dependence on a particular technology. Often software teams are directed to minimize their reliance on a single tool, technology, or vendor in an effort to maintain long-term flexibility. This is easier said than done. Take the ubiquitous Java servlet as an example. The instructions are simple: override the “service()” method and have it do what you want. Several outcomes are possible as the complexity of request processing grows or the types of different requests increase. The “service()” method might become long or break up into several methods in the class, there might be many utility methods added to the servlet subclass, or a whole hierarchy of different subclasses might arise in an attempt to specialize and still reuse code. The problem is that servlets are extremely awkward to test, primarily because they are used as a component in a specific environment—the servlet container. Creating instances of servlets and testing individual methods is quite difficult. The test-first approach leads to a different implementation. When it comes to servlets, it
is quite apparent that the easiest way to test the code that handles requests is to remove it from the servlet entirely, and put it into its own class. In fact, not only is that the easiest thing to do with respect to the tests, but the resulting design itself is then more flexible and quite independent of the servlet technology. Our code in “service()” is three lines long. It has just one responsibility: create another object that will do the work and then hand control to it. In our case, we call this object a dispatcher. Its job is to decide what kind of request is being submitted and create yet another object (an instance of a command pattern) to handle the request. The dispatcher and each command object have their own unit tests, in which creating the needed fixture is trivial. Now we not only have a testable design, we have one with a more appropriate division of labor and one that is more technology-independent.
Though it might seem a tautology, practicing test-first programming leads to a pervasive quality of testability throughout the code base.
Aggressive refactoring: Swapping technologies With the support of extensive unit tests it is possible to radically change code without breaking existing functionality. This gives the developer the ability to make major changes, even in integral frameworks, very quickly. For example, it allowed us to refactor our persistence code just weeks before we went live with our first client. We used Enterprise JavaBeans, specifically Entity beans, to manage our database persistence. We wanted to remove the entire EJB layer because of poor performance and difficulties in testing the internals of the Beans, among other reasons. Without tests, we would not have attempted to remove the Beans, but given that our unit test suite included extensive coverage for testing persistence, and that we had experience in performing this kind of major change, none of us was too concerned. In fact, we would be getting a performance improvement, more testable code, and the removal of an expensive technology. We executed the refactoring in less than a week, and performance did increase markedly. We saved money by removing the EJB technology and ended up with more testable code because we had removed a part of our system that was essentially a black box. Bugs Testing has radically changed the way we March/April 2002
IEEE SOFTWARE
61
The existing tests might not be extensive enough, in which case the programmers would add more tests.
deal with controlling bugs. We think of bugs differently from the traditional view—we use our bug count to help pinpoint areas that need more testing. That is, we consider bugs as feedback about how we are doing with our testing. When a bug is found, we write a test that “catches” the bug—a test in the area where the bug was found that asserts what should be the case and fails. We then change the code until the test runs successfully, thus fixing the bug. In this way, we fill in holes in our suite of tests. We do not stop there, though. We look for the case where several bugs in a related area entered our bug tracking system during a short time period. This information tells us that something more seriously wrong exists with our tests—perhaps the testing framework in that area needs some work. For example, perhaps three bugs are found one day all in the area of logging out of the application. Rather than trying to “pinpoint fix” each bug—that is, assign each bug to a different developer, thinking of each as an independent problem— we assign the group of bugs to a single pair of programmers. This pair looks at existing tests for that area, which clearly did not do their job well. The existing tests might not be extensive enough, in which case the programmers would add more tests. Or they might refactor the testing framework in that area to allow better, more accurate support for the kinds of tests that we can then proceed to write. The result is a suite of tests that constantly grows and changes to cover as much of the application as possible. The tests are run whenever code is changed, catching problems before the changes are even deemed worthy of being added to the main code base. Armed with such a weapon, as little time as possible is spent maintaining existing functionality. In short, development occurs faster. Tests as documentation Our methodology does not encourage writing documentation for code or even writing comments in the code. Instead, we rely on tests to document the system. This might seem strange, but because tests are written first, they completely define what the code should do. (In fact, the definition of the code being in working order is that the tests all run.) We write our tests with readability in mind. The best way to learn what the code is supposed to do is to read
62
IEEE SOFTWARE
March/April 2002
the tests. New developers, or developers who are inexperienced in a particular area, can get up to speed far quicker this way than by trying to wade through requirement and design documents. It is more effective to learn by reading a short, simple test than to try and decipher code that might contain problems or is very complex. This method of learning through reading tests is especially important in our company as the development team grows. As new developers come on, they are paired with existing developers to gain knowledge, but a large part of their learning comes from reading tests. New team members come up to speed quickly because of well-factored, readable tests. Acceptance tests and their extensions In addition to writing unit tests, our process has a mechanism called acceptance tests that allow product managers to express tests at the scenario level. We began by writing a testing tool that expressed operations in the system and the expected results as XML. Product managers, with the assistance of programmers and quality assurance team members, wrote extensive acceptance tests that, along with our suite of unit tests, are run at every integration. The acceptance tests provided a clear value, but it was soon apparent that the supporting frameworks for the XML had several other benefits. As we neared deployment for our first customer, the need arose to integrate with other e-commerce systems and with the client’s legacy mainframes. We employed an industry-standard EAI (Enterprise Application Integration) tool configured to generate XML as an adaptor to transform data from these external systems to our own. The XML test framework required little modification to act as the interface to this integration tool. We even used the framework assertion capabilities to verify incoming transactions. As our need for acceptance tests grew, writing them more quickly and making them easily maintainable became important. XML, though workable, is awkward for a human to write, especially for nontechnical staff. To solve this, we implemented a domain-specific language, called Evant Script Programming (ESP), which is more compact and readable than XML. Once ESP was available, we recognized uses beyond acceptance tests and
For More Information
data loading, including an easy way to configure system parameters, and that we could use a suite of ESP scripts to create a tailored demo environment. Testing challenges and solutions In the Web environment, the client and the server are very different beasts. The user’s machine runs a Web browser, which understands HTML and JavaScript (we will not discuss the extra complications of applets, plug-ins, or other client-side technologies here). The only ability this browser has is to send information through a map of strings over a stateless protocol to a Web server, which deals with the submission by passing it off to an engine running application code (for example a servlet container running Java code or a Perl program). We would typically like to test the client and the application server part of this set up, but it would be difficult to come up with a testing framework that could do both at once—to test JavaScript and DHTML on the client and Java on the application server. However, splitting tests into two distinct parts is not a good idea because we need to test how the two sides interact. This is the classic Web application testing problem. We recommend the following remedy. First, test those parts of the server-side code that are not directly concerned with being part of a Web application, without involving the Web peculiarities. For example, if one were testing the manipulation of a tree object, one would test manipulating the object directly, ignoring the fact that the visual representation of the tree is collapsed and expanded by the user through the UI. Test the business logic with such low-granularity unit tests. That is, of course, the goal no matter what the UI, but it becomes particularly important to be strict about it when working with a Web application. Second, test those parts of the client-side code that have no server interaction. This is typically code that contains little or no business logic. Examples of such code, typically written in JavaScript, might include functions to pop up error messages, perform simple field validations, and so on. The immediate problem we faced in writing tests for this sort of code was that no testing framework existed for JavaScript inside the browser. In fact, we had already heard from
Books Extreme Programming Explained, Kent Beck, especially Chapter 18 (”The introduction to Extreme Programming“); a good place to start. Extreme Programming Installed, Ron Jeffries et al., Chapters 13, 14, 29, and 34; contains a lot of information addressing common problems and questions about unit testing. Web sites Testing frameworks: www.xprogramming.com/software.htm www.junit.org Extreme Programming sites: www.xprogramming.com www.extremeprogramming.org
other developers that testing JavaScript was too hard, and that JavaScript itself should therefore be avoided entirely. Undeterred, we wrote a testing framework for JavaScript called JsUnit, now a member of the XUnit family of unit testing frameworks (www. jsunit.net). JavaScript is notoriously difficult to write and debug, but using JsUnit has greatly helped our rapid development of client-side code. Third, write functional tests of a low grain in the server-side language (for example, Java or C++) that simulate the request/response Web environment. We wrote a framework for such tests that extends our usual unit-testing framework to allow the test author to think of himself or herself as being in the Web browser position, putting keys and values into a Map object (which corresponds to in an HTML document). The framework simulates a submission of the Map to the server by invoking the server code, passing in the Map as a parameter. This invocation is coded in such a way as to follow as closely as possible the path a request would take were it submitted through the true UI. (We take advantage here of the refactoring of our servlet discussed above: We cannot “invoke” the servlet from a test, but we can easily talk to the objects that the servlet spins off.) The server’s response can then be inspected and verified by the test (see the next section for more on this). Because the test code explicitly invokes the server-side code, the test can inspect the state of the code, rather than just the HTML output resulting from the submission. It is for this reason especially that this method of testing is more useful than a framework such as HTTPUnit, which views the situation purely from the client’s viewpoint. March/April 2002
IEEE SOFTWARE
63
How to test output from the server is another classic problem because of the nature of Web applications.
Using this framework, you can write walkthrough tests that simulate the user moving through the UI. For example, we have methods available in the test framework with names such as “clickSaveButton().” A test case might call that method and then perform assertions about the domain object that should have been persisted as a result of the call. Thus, we have the ability to perform an action that the user might execute and then to test specifics about the domain. Walkthrough tests are particularly useful when writing tests to reproduce bugs that manual testing has exposed. In fact, there has not yet been a case when we could not write a walkthrough test that catches a bug found by a member of the quality assurance team. Testing server output How to test output from the server is another classic problem because of the nature of Web applications. How do you test HTML? Certainly we don’t want tests that assert that the output is some long string of HTML. The test would be almost unreadable. Imagine tracking down a mistake in such a test, or changing it when new functionality is required. Testing the Web page look is not usually the goal; testing the data in the output is. Any slight change to the output—for example, a cosmetic change such as making a word appear in red—should not break an output test. We came to understand these issues as we progressed through several technologies used to generate our HTML output. In fact, this progression and the choice on which we finally settled were influenced in large part by what was most easily testable. At the outset we worked with JavaServer Pages (JSPs). We found that although we got up and running quickly using them, testing them was hard. They are another Web technology that runs in a container environment that is difficult to reproduce in a test. In addition, it was challenging for our UI designers to work with JSPs because of the amount of Java code interspersed among the HTML. Soon we were spinning off testable objects to which the JSPs delegated that did the HTML generation. When we arrived at the point where the JSPs were literally one line long, we dispensed with them altogether and produced our HTML purely using Java. With that arrangement we could easily test the state of objects that produced the HTML—for exam-
64
IEEE SOFTWARE
March/April 2002
ple, that the object knew to make a button disabled. We could also test the process of producing pieces of HTML—for example, the production of an HTML
element. However, we were still not testing the output. The same question dogged us: How do you test the data in the HTML without getting confused with the cosmetics? Furthermore, our designers were even less interested in delving into Java code to change text color than they had been with JSPs. A further change of technology solved both these problems. We generated our UI by outputting XML—pure data—from our domain objects. Then we transformed the XML into HTML for the client using Extensible Stylesheet Language Transformation (XSLT) pages, written and maintained by our developers and UI designers. XML is easily testable. In our walkthrough tests, we can ask for the current XML output at any time and then make assertions about its structure and contents using the standard XPath syntax. The XML consists strictly of data from the domain; there is no knowledge even that it will be used in the UI. Our XSLT contains only information about how the UI should look and how to use the data in the XML. Thus we achieved an extremely clean separation of testable business data from HTML generation that helped us develop the UI much faster than the other methods we tried. We could test that part of the output that contained data without getting it confused with the HTML. Conversely, our UI designers were happier because their work was not confused by Java among the HTML. Again we found a way to separate the untestable Web technology, in this case HTML, from the data. A first test A question we are often asked is how we started promoting testing and testability at the beginning of our development. The first step in making our Web application testable was to establish a culture of testing among the developers. Following the methodology of writing tests first, our first task as a team was to write the first test. Most team members were new to the concept of test-first programming, so it was not obvious to them how to go about this. It seems almost comical thinking back on it, but it was appropriate at the time: We pro-
About the Authors
grammed in a group for the first couple of days. Having the entire team of eight huddled around a monitor, achieving consensus on every line of code, let us iron out right from the start what a typical test looked like, how we write a little bit of test code and then some code to make the test run, when to go back and add another test case, and so on. We also quickly settled other issues that often plague development teams: we agreed on coding standards, established a way to perform integrations, and settled on a standard workstation configuration.
T
hus testing has been an integral part of our development process since the first day, and remains so now. Of course, our testing frameworks and practices change and grow daily, and we are by no means finished with their evolution. For example, we feel that we have a long way to go in finding more appropriate ways to expose testing to
Edward Hieatt is a lead developer at Evant, a software vendor in San Francisco that observes a strict practice of XP. He became involved with Extreme Programming in 1999. His research interests include the rapid development and testing of Web-enabled software. He is also the author of JsUnit (www.jsunit.net), a unit-testing framework for JavaScript, which is one of the XUnit testing frameworks. Contact him at [email protected].
Robert Mee is a software programming and process consultant in a variety of indus-
tries, helping companies apply the practices of Extreme Programming. He regularly gives lectures on XP for corporations, their investors, and others. During 2000 and 2001, he was director of engineering at Evant, where he helped introduce XP. His research interests include human and computer languages, and the application of domain-specific languages to the automated testing of software. He has a BA in oriental languages from the University of California at Berkeley. Contact him at robmee@ hotmail.com.
our business users. We would also like to extend our walkthrough test framework to simulate even more closely what happens in real situations. Our company supports us when we ask for time to develop such abilities because they have seen the benefits of testing. They agree that our focus on tests and testability has helped us go faster than any project they have worked on in the past. For more information on this or any other computing topic, please visit our Digital Library at http://computer.org/publications/dlib.
What do software engineering professionals need to know, according to those who hire and manage them? They must be able to produce secure and high-quality systems in a timely, predictable, and cost-effective manner. This special issue will focus on the methods and techniques for enhancing software education programs worldwide—academic, re-education, alternative—to give graduates the knowledge and skills they need for an industrial software career.
For more information about the focus, contact the guest editors; for author guidelines and submission details, contact the magazine assistant at [email protected] or go to http:// computer.org/software/author.htm. Submissions are due at [email protected] on or before 1 April 2002. If you would like advance editorial comment on a proposed topic, send the guest editors an extended abstract by 1 February; they will return comments by 15 February.
Potential topics include
• • • • • • • • • • • •
balancing theory, technology, and practice experience reports with professional education software processes in the curriculum teaching software engineering practices (project management, requirements, design, construction, …) quality and security practices team building software engineering in beginning courses computer science education vs. SE education undergraduate vs. graduate SE education nontraditional education (distance education, asynchronous learning, laboratory teaching, …) innovative SE courses or curricula training for the workplace
Manuscripts must not exceed 5,400 words including figures and tables, which count for 200 words each. Submissions in excess of these limits may be rejected without refereeing. The articles we deem within the theme's scope will be peer-reviewed and are subject to editing for magazine style, clarity, organization, and space. We reserve the right to edit the title of all submissions. Be sure to include the name of the theme for which you are submitting an article. Guest Editors:
Watts S. Humphrey, Software Engineering Institute Carnegie Mellon University, [email protected] Thomas B. Hilburn, Dept. of Computing and Mathematics Embry-Riddle Aeronautical University [email protected]
March/April 2002
IEEE SOFTWARE
65
focus
engineering Internet software
Lessons in Agility from Internet-Based Development Scott W. Ambler, Ronin International
t the peak of the Internet revolution hype, we were inundated by claims that the fundamental rules of business had changed. To support this new business paradigm, new companies sprang up virtually overnight, often delivering very good software very quickly. I wondered whether the rules of software development had also changed. Were we witnessing a paradigm shift in the way we develop software? Was there something to the concept of “development in Internet time”?
A The author describes two Internet startup companies that adopted effective and efficient modeling and documentation practices, one taking a communal, teambased approach and the other a chiefarchitect approach. They found a “sweet spot” where modeling efforts can provide significant benefit without incurring the costs of onerous documentation. 66
IEEE SOFTWARE
In April 2000, the Internet bubble burst and the business world was brought back to reality, discovering that business fundamentals hadn’t changed. However, it isn’t so clear whether the fundamental rules of software development have changed. I worked as a software process consultant to two Internet startups during the boom— let’s call them XYZ.net and PQR.com to protect their identities, as both are still in business. XYZ.net focused on fundamental infrastructure services for Internet users and, when I joined them, was about to start work on its third generation of software to support its upcoming initial public offering. PQR.com was an online electronic retailer in the process of re-architecting its system to support its projected growth and to position itself for a future IPO. The two common factors between the companies were my involvement and the fact that both organizations were facing phe-
unnecessary bureaucracy to slow them down. Both organizations needed to improve their modeling practices; senior management felt that although they had bright, talented developers, they weren’t as effective as they could be. The developers at the two organizations had mixed feelings about this, with attitudes ranging from “it’s about time” to “modeling is a waste of time; all I need is source code.” The tailored version of the RUP needed to include an enterprise architecture modeling process that would define their technical and application infrastructures. This enterprise architecture effort was beyond the RUP’s scope, which focused on the software process for a single project instead of a portfolio of projects. Furthermore, both organizations needed effective approaches to their modeling and documentation on individual projects. Although the RUP clearly included sophisticated modeling processes, each organization felt the RUP approach to modeling was too cumbersome for Internet-based development and wanted to find a better way to work. Communal architecture To architect the new generation of XYZ.net’s software, the company introduced an architecture team comprising the technical leads from each development team, the vice president of systems, the chief technology officer, the quality assurance and testing manager, and several senior developers. The first week the team met for several afternoons to identify where they were going, what their fundamental requirements were, and then to propose an initial architecture to support these needs. When they weren’t modeling the new architecture, everyone worked on their normal day-today jobs. XYZ.net was a round-the-clock operation: no one could simply stop evolving the existing software. This had the side benefit of giving people time to reflect on the proposed architecture as well as to discuss ideas with co-workers. During the architecture modeling sessions, they drew diagrams on whiteboards. At first, the team tried to use a CASE tool connected to a projector but found this to be insufficient—the person operating the tool could not keep up with the conversation, and the tool wasn’t flexible enough to meet our needs (they needed more than the Unified Modeling Language4 diagrams that it supported).
The whiteboard also required little training to work with and allowed them to swiftly switch back and forth between modelers. As the team modeled, people would provide input and insights, question assumptions, share past experiences, and even talk about potential implementation strategies. The simpler tool enabled them to work together as a team. Whenever they needed permanent documentation, they would simply draw the models on paper and then scan them to produce electronic copies. Occasionally the team would capture the model in a CASE tool, but the scanner approach was more common because few developers had access to the CASE tool due to platform incompatibilities. The team drew UML diagrams but found they needed a much wider range of techniques—some of the software was written in procedural languages, so they needed nonobject diagrams such as structure charts. They also drew dataflow diagrams to depict workflow issues and free-form diagrams to depict the system’s technical architecture. Once the initial architecture model was in place, they continued to meet almost weekly (only when they needed to). The meetings were typically one or two hours long and always included an informal agenda that identified one or more issues to be addressed. The owner of each issue was responsible for explaining it, what he or she saw as the likely solution, and potential repercussions of this approach. Often, someone would come to an architecture session with the issue mostly solved; the group would simply review it and provide appropriate feedback. Presentations were typically done in a “chalk talk” manner, in which the owner would describe an issue by drawing on the whiteboard. This worked well because many people would already be familiar with the issue, having been involved in earlier discussions with the owner outside of the architecture modeling sessions.
Both organizations needed effective approaches to their modeling and documentation on individual projects.
Introducing a chief architect Taking a different approach, PQR.com decided to hire an experienced senior developer as a chief architect, an “old guy” in his early 30s who had built scalable systems before. He spent his initial week with the company learning about the business and the current status of the systems, mostly through discussions with senior IT and operations staff. He then ran small modeling March/April 2002
IEEE SOFTWARE
67
The main difference in their approaches was how architectural documentation was updated over time.
sessions to identify architectural requirements as well as potential architectural solutions. His approach was to hold one-hour “chalk talk” sessions involving two or three other people, followed by several hours of modeling privately with a diagramming tool and a word processor to explore and document what he had learned. He then posted his models as HTML pages on the internal network where everyone, developers and business people alike, could view them and potentially provide feedback. It was quite common for people to schedule an impromptu meeting with him to discuss his work or to simply send him an email. Documenting the architecture Both organizations chose to document their architecture to make it available to all their software developers. Their approaches had several interesting similarities: ■
■
■
68
IEEE SOFTWARE
Official documentation was HTML based. Both companies chose HTML (and JPEG or GIF pictures) to support the wide range of operating systems the developers used, thus making the documentation accessible to everyone. Furthermore, the developers were intimately familiar with HTML and had existing tools to view and edit the documents. They created only overview documentation. To remain effective, both companies documented only overview information pertaining to the architecture, recording the critical information that developers needed to know to understand how it worked. The documentation was primarily focused around an architecture diagram showing major software services deployed within the technical environment, with overview descriptions for each software service or system and appropriate links to the documentation pages maintained by individual project teams. A printout of the architectural documentation would have been no more than 15 pages. The information architecture wasn’t special. The databases and file storage systems appeared on the system architecture diagram along with applications and software services. The data team was treated the same as any other project team: all the teams provided func-
March/April 2002
■
tionality that other teams needed, and each team in effect was the customer of several other teams. This required everyone to work together to resolve any configuration and release management issues. This was unlike many organizations where the data team is considered a corporate infrastructure team that supports application development teams. At both companies, every team was an infrastructure team. Modeling and documentation were separate efforts. Both companies realized that the act of modeling and the act of writing documentation are two distinct efforts. In the past, most developers did not have significant experience modeling, so they equated it to using sophisticated CASE tools that generated detailed documentation. After experiencing several modeling sessions using simple tools such as whiteboards, after which someone wrote up the appropriate summary documentation (if any), they learned they could achieve the benefits of modeling without incurring the costs of writing and maintaining cumbersome documentation.
The main difference in their approaches was how architectural documentation was updated over time. PQR.com had a designated owner of the documentation, the chief architect, whereas XYZ.net took a more communal approach and allowed anyone to update the documentation. At PQR.com, people were required to first discuss their suggestions with the chief architect, who then acted accordingly. At XYZ.net, people would first talk with the perceived owner of a part of the documentation, typically the person initially assigned to that aspect of the architecture, and then update it accordingly. No one seemed to abuse this privilege by changing the architectural documentation to further their own political goals. One reason was that the XYZ.net developers were a closely knit team. Second, because all HTML pages were managed under their version control system, there was a record of who changed each page. Comparing the two modeling approaches Let’s compare the two approaches to enterprise architectural modeling with regard to several critical factors:
■
■
■
■
■
■
Calendar time. XYZ.net’s architecture team required less calendar time to develop their initial architecture and then to evolve it over time, because several people worked on it in parallel. Acceptance. The communal approach taken by XYZ.net clearly resulted in quicker acceptance by the developers for two reasons. First, representatives of each development team participated in the architectural team, and they effectively “sold” the architecture to their teammates, often simply by asking for their help when they were working on portions of the architecture. Second, everyone could update the architecture documentation as they required, thus promoting a sense of ownership. Cost. PQR.com’s approach required less overall effort because the chief architect performed most of the architectural modeling, enabling his co-workers to focus on other tasks. Control. The chief architect at PQR.com provided a single source of control, albeit one that became a bottleneck at times. The team approach provided several sets of eyes working on any given aspect of the architecture, although its shared ownership of documentation provided opportunities for mischief (although to my knowledge none ever occurred). Correctness. Both approaches resulted in scalable architectures that met the needs of their respective organizations. Process compatibility. Both approaches worked well within a RUP environment, although the chief-architect approach seemed to be better attuned to the RUP than the communal-architecture approach.
Project-specific modeling The project process was similar at both organizations: systems were developed in a highly iterative manner and released incrementally in short cycles ranging from six to 12 weeks, depending on the project. The marketing department wrote the initial requirements documents, typically high-level needs statements. The IT department heads and the project leads did a reality check on these documents to rework unrealistic ideas before presenting them to the teams. Mod-
eling sessions occurred as each project team required, with some team members meeting with appropriate project stakeholders to work through an issue in detail. These modeling efforts were similar to those performed by the XYZ.net architecture team: people met and worked on the models as a team around a whiteboard. Often, they would develop several models at once—perhaps several use cases along with some screen sketches, some sequence diagrams, and a class diagram. They did not have “use case modeling sessions” or “class modeling sessions”—just modeling sessions. At XYZ.net, the development teams had one to eight members, each of whom focused on one part of the overall infrastructure. At any given time, each team would be at a different place in the project life cycle. Sometimes two or more teams would need to schedule their releases simultaneously to enable various subsystem dependencies. The individual teams knew of those dependencies because they worked closely with the developers from other teams, often walking across the floor or up the stairs to sit down and talk with them. These modeling sessions differed from traditional ones. First, they iteratively did the minimal amount required that let them start coding, with most modeling sessions lasting from 10 minutes to an hour. Second, each modeling session’s goal was to explore one or more issues to determine a strategy for moving forward; the goal wasn’t simply to produce an artifact. Their goal was to model, not to produce models. Developers worked with technical writers to produce the release notes, installation procedures, and user documentation. The release notes were the formal documentation for the subsystems, written as HTML pages and posted online so that all internal developers could see them. The release notes typically summarized the newly implemented requirements, the design (diagrams were typically scans of their primary sketches and were posted as JPEG files), and a listing of the files making up the subsystem. Luckily, XYZ.net developers were already producing release notes following this process in their premodeling days, so the only change they needed to implement was to add the design diagrams that presented an overview of their work. At first, some developers included de-
The project process was similar at both organizations: systems were developed in a highly iterative manner.
March/April 2002
IEEE SOFTWARE
69
An interesting similarity between the two companies was their approach to data.
70
IEEE SOFTWARE
tailed diagrams in their release notes, but they quickly found that they provided little value. When the developers wanted detailed information, they went straight to the source code, which they knew was up to date. Developers also worked closely with test engineers. The developers needed help unittesting their software, and the test engineers needed help learning the software to develop acceptance tests for it. Before software could be put into production, the quality assurance department first had to test it to ensure that it fulfilled its requirements, it was adequately documented, and it integrated with the other subsystems. The development process worked similarly at PQR.com, with teams of three to six people. Developers from the various teams worked closely together, helping one another where necessary. PQR.com developers took a more formalized approach to documentation, writing requirements documents, design documents, and technical release notes. The requirements documents were based on the initial marketing requirements documents and the requirements models produced from them. The requirements document was written in parallel with development of the design document and source code and was typically finalized during the last week of an iteration: the teams worked iteratively, not serially, so they could react to new and changing requirements as needed. A requirements document included a use case diagram and detailed use cases for the release as well as related business rules, technical (nonfunctional) requirements, and constraints as required. Design documents included screen specifications when applicable (typically just a JPEG picture of an HTML page) and applicable overview diagrams; also, the developers preferred source code to detailed design diagrams. An interesting similarity between the two companies was their approach to data: their data efforts were treated just like development projects. However, the data teams worked differently than the other project teams, investing more time in detailed modeling. At both companies, the data groups used a CASE tool to create physical data models of their relational database schemas. The tool generated and reverse-engineered data definition language (DDL) code, including database triggers, thereby making the additional detailed modeling effort worthwhile.
March/April 2002
Dissension within the ranks Several individuals at XYZ.net didn’t appreciate the need for an increased effort in modeling and documentation. This was due to one or more factors: they perceived themselves as hard-core programmers, they preferred to work alone or with others of similar mindsets, or their people skills needed improvement. Moreover, they typically didn’t have good modeling and documentation skills, nor did most of their co-workers. For all but one person, a combination of peer pressure and the ability to see “which way the winds were blowing” motivated them to go along with adopting a tailored version of the RUP, albeit with a little grumbling. The lone holdout required minor disciplinary action: the head of development had a few personal chats with him, he wasn’t allowed to move on from his current project until he had written the documentation and the quality assurance department had accepted it, and his promotion to team lead was put on hold for a few months. There were few problems at PQR.com, likely because its staff was more aware of modeling’s benefits to begin with. People had various levels of modeling skills, so they received training, but nobody was actively antagonistic toward increased levels of modeling as long as they received training. Comparison with traditional project development How was this different from traditional development practices, particularly of typical RUP instantiations? From the 50,000-foot level, it wasn’t different at all. Both companies identified requirements and then architected, designed, coded, tested, and deployed their software. However, at ground level, there were some interesting differences. First, development started with the enterprise architecture model. To fit in with and exploit other systems, all project teams started with the existing enterprise architecture model because it showed how their efforts fit into the overall whole. When the project teams delved into the details, they sometimes discovered the need to update the architecture, which they did following their organization’s chosen practices, described earlier. Development was also highly iterative. Project teams did a little modeling, coding, and testing and then repeated as necessary.
Table 1 The principles of agile modeling They did not take the serial approach of completely developing and accepting the requirements model, then completely developing and accepting an analysis model, and so on. This let them react swiftly to changes in their highly competitive markets and rapidly deliver software to their end users. Also, modeling was streamlined. They modeled just enough and then got on with implementation, avoiding analysis paralysis while at the same time showing that their models actually worked (or didn’t) by writing code based on them. Moreover, both organizations used simple modeling tools. With the exception of the two data teams, the projects preferred simple sketches on whiteboards over diagrams created using sophisticated CASE tools. This sped up the modeling process, although it might have slowed development when developers could not automatically generate code from their models—a feature of many modern tools—or reverse-engineer existing code to create diagrams to help them understand it. Finally, documentation in the two projects was minimal. Both companies improved the quality of their system documentation and managed to find the “sweet spot” where it was just barely enough to meet their needs and no more. Many traditional projects produce far more documentation than they need, reducing their ability to implement new features and sometimes even causing the project to fail completely.5 Setting the foundation for agile modeling My experiences on these two projects provided significant insights for what was to become the Agile Modeling methodology.6 AM is a practice-based methodology for effective modeling and documentation of software-based systems. Principles and values guide the AM practices, intended for daily application by software professionals. AM is not hard and fast, nor is it a prescriptive process—in other words, it does not define detailed procedures for how to create a given type of model. Instead, it provides advice for how to be effective as a modeler. This is different from modeling methodologies such as Iconix7 or Catalysis8 that suggest a specific collection of modeling artifacts and describe how to create those artifacts. Where
Core principles
Supplementary principles
Assume simplicity
Content is more important than representation Everyone can learn from everyone else Know your models Know your tools Local adaptation Maximize stakeholder investment Open and honest communication Work with people’s instincts
Embrace change Incremental change Model with a purpose Multiple models Quality work Rapid feedback Software is your primary goal Enabling the next effort is your secondary goal Travel light
Table 2 Agile modeling practices Core practices
Supplementary practices
Active stakeholder participation Apply the right artifacts Collective ownership Consider testability Create several models in parallel Create simple content Depict models simply Display models publicly Iterate to another artifact Model in small increments Model with others Prove it with code
Update only when it hurts Use the simplest tools Apply modeling standards Apply patterns gently Discard temporary models Formalize contract models Model to communicate Model to understand Reuse existing resources
Iconix promotes applying use case models, robustness diagrams, UML sequence diagrams, and UML class diagrams, AM suggests that you apply multiple models on your projects and the right artifacts for the situation. AM is complementary to most traditional modeling methodologies—it does not replace Iconix and Catalysis but instead provides complementary advice for improving your effectiveness with them. AM’s scope is simply modeling and documentation. It is meant to be used in conjunction with other agile software processes9,10 such as Extreme Programming,11 Scrum,12 and the Dynamic System Development Method,13 as well as “near-agile” instantiations of the Unified Process. AM adopts the values of XP—simplicity, feedback, communication, and courage—and extends it with humility. These values are used to derive a collection of principles (see Table 1) that in turn drive AM’s practices (see Table 2). Nothing about it is truly new. It is a reformulation of concepts that many software professionals have been following for years. March/April 2002
IEEE SOFTWARE
71
XYZ.net and PQR.com were successful because they followed a collection of commonsense approaches.
Lessons learned XYZ.net and PQR.com were successful because they followed a collection of commonsense approaches. Let’s explore the lessons learned at XYZ.net and PQR.com and see how they relate to AM. ■
■
■
72
IEEE SOFTWARE
People matter. Everyone worked together to make the effort succeed—it was as simple as that. We operated under a philosophy along the lines of the Agile Alliance’s “value of individuals and interactions over processes and tools”9 and Alan M. Davis’s 131st principle, “People are the key to success.”14 You don’t need nearly as many documents as you think. Both companies built mission-critical software very quickly, software that is still in operation several years later and that has been modified significantly since—and we did so without creating mounds of documentation. Fred Brooks provides similar advice with what he calls the documentary hypothesis: “Amid a wash of paper, a small number of documents become the critical pivots around which every project’s management evolves.”15 In short, the teams followed the principle “Travel light,” producing just enough documentation and updating it only when they needed to, much along the lines of AM’s practice “Update only when it hurts.” Communication is critical. The amount of required documentation was reduced because both organizations had a highcommunication environment. Developers worked closely together, face-to-face with their co-workers and customers (either marketing and sales staff or the chief technology officer). Models were left on the walls so that everyone could see them, as AM suggests with its practice “Display models publicly.” By doing this, developers could refer to the models when explaining their strategies to others and often received valuable feedback, often simply in the form of questions, from people who had taken the time to look over the models. We had rediscovered Davis’s 136th principle, “Communication skills are essential” and his 8th principle “Communicate with customers/users.”14
March/April 2002
■
■
■
Modeling tools aren’t nearly as useful as you think. Although we honestly tried to use the leading UML modeling tool at the time, as well as an open source software offering, the tools simply didn’t offer a lot of value. We weren’t interested in creating a lot of documentation, and the tools didn’t generate code for our deployment environment. The only useful CASE tools were the data-modeling tools from which diagrams were printed and DDL code generated. We did, however, take advantage of some simple tools, whiteboards and flip charts, and were very effective doing so. This experience reflects the findings and techniques of the user-centered design community in the late 1980s16 and is captured in AM’s practice “Use the simplest tools.” You need a wide variety of modeling techniques in your intellectual toolkit. The techniques of the UML, although useful, were not sufficient—both companies needed to perform process, user interface, and data modeling. Furthermore, each developer understood some but not all of the modeling techniques that we were using, resulting in the teams stumbling at times because someone would try to model something using an ill-suited technique. These concepts are captured in AM’s principle “Multiple models” and its practice “Apply the right artifact(s)”—advice similar to what everyone’s grandfather has likely said at some point, “Use the right tool for the job.” The concept of requiring multiple modeling techniques is nothing new; in the 1970s, structured methods such as those promoted by Chris Gane and Trish Sarson17 supported this concept. As the teams modeled, they would often work on two or three diagrams in parallel, each of which offered a different view on what they were discussing, and would move back and forth between the diagrams as appropriate, similar to AM’s practices “Create several models in parallel” and “Iterate to another artifact,” respectively. Big up-front design isn’t required. Although XYZ.net spent a few afternoons formulating their initial enterprise architectural strategy, they quickly got
About the Author
■
down to work. Similarly, the chief architect at PQR.com also created an initial high-level model. Then he started to work with individual teams to implement portions of it, updating his model as required. Both companies discovered that they didn’t need weeks or months of detailed modeling and documentation to get it right, that hours were sufficient. Instead, they worked along the lines of AM’s practice “Model in small increments,” modeling the architecture a little and then either exploring strategies by proving them with code or simply starting work on the actual software itself. In his essay “Passing the Word,”15 Brooks provides similar advice—that architects must be able to show an implementation of their ideas, that they must be able to prove that their architecture works in practice. Reuse the wheel, don’t reinvent it. At XYZ.net, we took advantage of open source software whenever we could, building mission-critical systems quickly and effectively as a result. Through open source we had rediscovered Davis’s 84th principle: “You can reuse without a big investment.” We reused more than just open source software; we also adopted industry standards wherever possible, existing architectural strategies wherever possible, and applied design patterns when applicable. We discovered there was a wealth of material available to us when we chose to reuse it, supporting AM’s practice “Reuse existing resources.”
A
gile approaches to software development worked for these two Internetbased companies. Both XYZ.net and PQR.com applied existing, proven principles of software development in new ways to deliver complex, mission-critical software in a highly iterative and incremental manner. The lessons they learned apply beyond Internet development: most organizations can benefit from a shared architecture across projects as well as more effective and efficient modeling and documentation practices. Many of the “modern day” principles and practices of
Scott W. Ambler is president of and a principal consultant for Ronin International, Inc. (www.ronin-intl.com) and author of several software development books, including The Object Primer 2/e (Cambridge Univ. Press, 2001) and Agile Modeling (John Wiley & Sons, 2002). His professional interests focus on identifying and exploring techniques to improve software developers’ effectiveness. He received a masters in information science and a BSc in computer science, both from the University of Toronto. He is a member of the IEEE and ACM. Contact him at [email protected].
leading-edge development processes are the same (or slightly modified) principles and practices of yesteryear. Although the fundamentals are still the fundamentals, the way in which the fundamentals are applied has changed—agilely, not prescriptively. For more information on this or any other computing topic, please visit our Digital Library at http://computer.org/publications/dlib.
References 1. P. Kruchten, The Rational Unified Process: An Introduction, 2nd ed., Addison Wesley Longman, Reading, Mass., 2000. 2. S.W. Ambler, “Enterprise Unified Process,” 2001, www.ronin-intl.com/publications/unifiedProcess.htm. 3. S.W. Ambler, Process Patterns—Building Large-Scale Systems Using Object Technology, Cambridge Univ. Press, New York, 1998. 4. Object Management Group, “The Unified Modeling Language (UML), Version 1.4,” 2001, www.omg.org/ technology/documents/formal/uml.htm. 5. J.A. Highsmith III, Adaptive Software Development: A Collaborative Approach to Managing Complex Systems, Dorset House, New York, 2000. 6. S.W. Ambler, Agile Modeling, John Wiley & Sons, New York, 2002. 7. D. Rosenberg and K. Scott, Use Case Driven Object Modeling with UML: A Practical Approach, Addison Wesley Longman, Reading, Mass., 1999. 8. D.F. D’Souza and A.C. Wills, Objects, Components, and Frameworks with UML: The Catalysis Approach, Addison Wesley Longman, Reading, Mass., 1999. 9. K. Beck et al., “Manifesto for Agile Software Development,” 2001, www.agilealliance.org. 10. A. Cockburn, Agile Software Development, Addison Wesley Longman, Reading, Mass., 2002. 11. K. Beck, Extreme Programming Explained—Embrace Change, Addison Wesley Longman, Reading, Mass., 2000. 12. M. Beedle and K. Schwaber, Agile Software Development with SCRUM, Prentice Hall, Upper Saddle River, N.J., 2001. 13. J. Stapleton, DSDM, Dynamic Systems Development Method: The Method in Practice, Addison-Wesley, Reading, Mass., 1997. 14. A.M. Davis, 201 Principles of Software Development, McGraw Hill, New York, 1995. 15. F.P. Brooks, The Mythical Man Month: Essays on Software Engineering, Anniversary Edition, 2nd ed., Addison-Wesley, Reading, Mass., 1995. 16. J. Greenbaum and M. Kyng, eds., Design at Work: Cooperative Design of Computer Systems, Lawrence Erlbaum Assoc., Hillsdale, N.J., 1991. 17. C. Gane and T. Sarson, Structured Systems Analysis: Tools and Techniques, Prentice Hall, Upper Saddle River, N.J., 1979.
March/April 2002
IEEE SOFTWARE
73
focus
engineering Internet software
Software Localization for Internet Software: Issues and Methods Rosann Webb Collins, University of South Florida
Web sites must adapt to many local requirements to be usable for a global audience. This article examines key localization issues and presents an approach for analyzing and Web ost US corporations have a Web presence, but less than 15 percent offer non-English content.1 This is surprising, considering that in 2001, 57 percent of online users were non-English speakers, and by 2003 that percentage is estimated to increase to 65 percent of the Web’s one billion users worldwide.2 Moreover, studies have shown that retail customers are as much as three times more likely to purchase products from Web sites that use their native language.3 However,
M Web sites must adapt to many local requirements to be usable for a global audience. This article examines key localization issues and presents an approach for analyzing and documenting localization projects. Examples from a global “telehealth” company illustrate the main issues and their possible outcomes or solutions. 74
IEEE SOFTWARE
few US sites serve foreign customers well, with 46 percent of orders placed by individuals from outside the US unfilled.4 Clearly, Web sites that are usable in only one country cannot exploit the Internet’s global reach. Software localization is the process by which computer applications, such as Web sites, are analyzed and adapted to the requirements of other countries, making the software more usable for customers in those countries. Although translating Web site content is a major aspect of localization, it also involves changing many other aspects of the Web application, such as color, graphics, and structure. Localization can occur after the software application has been successfully used or marketed in one country and its owner wants to make the necessary changes for a new market. Although this produces software that is tailored to that specific market, the application is still not ready for easy
it is also important to recognize that cultures are difficult to describe and measure, and many individuals are multilingual or culturally heterogeneous. Developers of design rules for localization should avoid stereotypical views that do not adequately represent the richness and variation in cultural meaning in any single group.7 Increases in international travel for education, work, and leisure as well as transnational media and corporations are likely to create transnationals—individuals who are comfortable in multicultural and multilingual settings. This article identifies the key technical issues in Web site interface localization and describes an approach for analyzing and documenting a localization project. The article is based on a review of relevant literature, meetings with localization industry representatives, and an ongoing observation of participants in a global “telehealth” company (GTC). This company provides health care information, services, and products to health care professionals and patients in several countries. I will use examples from this company to illustrate the issues and their possible outcomes or solutions. Technical issues Software localization is based on research on each country as well as on input from usability testing in the target country. Testing global software in-country leverages developers’ knowledge of the locale, and such well-defined tasks with little interdependence are easily distributed.8 Many of the aspects of the country knowledge are obvious and immutable characteristics, such as language; other aspects are subtler and subject to cultural shifts, such as the meaning of colors. Such small changes in meaning make it particularly important to use individuals in the target country who have current knowledge rather than individuals who once lived or worked there, whose knowledge might be dated. A country’s technology infrastructure presents a particular design challenge, as that infrastructure will change and might be controlled by individual governments or companies. Therefore, the local technologydriven parts of a design must be revisited regularly. This means that the reuse possibilities and maintenance demands of the
localized software solutions differ by type and country. The following discussion is an expanded version of the guide prepared for GTC’s developers. Shirley Becker and Florence Mottay provide a more general list of usability factors for Web sites.9 I have organized the factors critical to localization into four categories identified by Becker and Mottay: information content, page layout, navigation, and performance. Information content In some cases, local differences are easily identified, fairly stable, and easy to implement in a Web site—for instance, time and date formatting, measurements, formats, collating sequences, and numeric formats. Time and date formatting. Conventions for
the formats of dates and time vary by location. For example, if you read 02/03/04, do you think it indicates 3 February 2004, 2 March 2004, or 4 March 2002? The international Gregorian calendar standard is YYYY-MM-DD, so the internal system representation of dates should probably follow that standard. Local presentation of the date on an interface might use the local format or be converted into another calendar, such as Hijri (Middle Eastern), Japanese, Korean, or Thai. The international standard notation for time is hh:mm:ss. To eliminate time zone difference problems, Universal Time (formerly Greenwich mean time) is indicated by hh:mm:ssZ. Local times can be shown as a deviation (+ or -) from Universal Time. There is a database of current time zone-related algorithms at www.twinsun. com/tz/tz-link.htm.
Many of the aspects of the country knowledge are obvious and immutable characteristics, such as language; other aspects are subtler and subject to cultural shifts.
Measurements. Most of the world uses the metric system of measurement and expresses temperature in degrees Celsius, but the US uses the British Imperial and Fahrenheit systems. Fortunately, the conversion from metric to British Imperial and temperatures from Celsius to Fahrenheit is straightforward, and algorithms for making the conversion are in the public domain. Formats. Countries differ in the type of paper most commonly used (letter, legal, folio, or A4) and paper and envelope sizes (which can be specified in either or both inches and March/April 2002
IEEE SOFTWARE
75
Some terms, especially technology terms, might not exist in some languages. The original word is often used, but sometimes a new word is coined based on a phonetic translation.
millimeters). The arrangement of the different components of an address also varies among countries. For example, the address format in China is Country Province Address Last Name
City First Name
Honorific
If a system includes printing of forms or input of names and addresses, the design must account for these differences. A good source for these variations in format, as well as other aspects of localization, are the appendices in Developing International Software by Nadine Kano.10 Collating sequences. Languages as well as countries use different alphabet-based sorting sequences. This is particularly true when languages include diacritics and ligatures as well as letter combinations that sort in various sequences. For example, in Swedish, vowels with diacriticals sort after Z. Also, list order might not be based on the alphabet; for example, in traditional Chinese, the number of strokes it takes to draw each character determines a list’s arrangement. In Latin America, the double character ch is treated as a single character and sorts between the letters c and d. Sometimes the collating sequence depends on what is being listed, as in Spanish family names.11 Numeric formats. Again, numeric formats
differ among countries, with the major differences arising from whether a comma, period, or blank space is used to separate thousands and higher numbers and whether a decimal or a comma is used to separate the decimal part of a number. Even words used to express numbers can vary. For example, in the US a “billion” is a 1 followed by nine zeros, whereas in Latin America and Europe, it means a 1 followed by 12 zeros.6 Language. Of course, language is a more dif-
ficult issue in localization. Translation software partially supports translation of content from one language to another, but in most cases human intervention is needed because direct translation might change the content’s meaning. An example of this problem is from the US Milk Processor Board’s 76
IEEE SOFTWARE
March/April 2002
television commercial that uses the tag line “Got Milk?” If translated directly into Spanish, the tag line becomes “Are You Lactating?” To market to Latina mothers, the tag line was changed to “And You, Have You Given Them Enough Milk Today?” The images show mothers cooking flan and other milk-rich Latin foods.12 The translation ratio of words and sentences is not one to one. Because the space required for a body of text can dramatically differ between languages—for instance, when English text is translated to French, its length increases 15 to 20 percent, but when it is translated into Hindi, its length might increase 80 percent—interface design must account for the differing space requirements. Individual words used in menus and on tabs can be especially problematic for design: for example, the “Preferences” selection common on Windows interfaces translates to “Bildschirmeinstellungen” in German. Therefore, menus, boxes, logos, and other graphics containing embedded words must be self-sizing, or there will be additional costs in redesigning those elements for each localized interface. Some terms, especially technology terms, might not exist in some languages. The original word is often used, but sometimes a new word is coined based on a phonetic translation. The commercial translation services create and maintain dictionaries of these specialized terms to reduce redundant translation efforts and to increase the coverage of automatic translation software. Punctuation marks also vary between languages. For example, interrogatory sentences in English end with a question mark, whereas in Greek they end with a mark that looks like an English semicolon. Content must also be examined to see if it is legal in a particular country. For example, comparative advertising (brand a is better than brand b) is now legal in the US, but not in other countries such as Germany. In many European countries, the collection of personal data is sometimes subject to local laws about data privacy. Content might be culturally loaded, in that the idea being expressed might only work in some cultures. For example, meetings in Japan are a public ritual of consensus: all brainstorming has been done and all conflict has been worked out in discussions
Localization Costs and Impact on Pricing
after work, often conducted in a social setting. So, translating the word for meeting might be easy, but the meaning will definitely be different.13 In the travel industry, specific travel-related differences between nationalities require companies such as Lastminute to tailor descriptions of accommodations—for example, the meaning of a three-star hotel.14 Asia presents some of the greatest challenges to localization. One and a third billion people speak CJK (Chinese, Japanese and Korean), and in Japan alone more than 17 million people are online. These ideographic languages (as opposed to characteroriented languages such as English) convey meaning through symbols, and the number of symbols is large. Text might include a mix of writing systems: Japanese and Korean commonly use some Chinese characters as well as limited Roman (English) characters.15 There are two main technology issues for language. First, the words seen while using a computer come from an assortment of systems, although users tend to see the interaction holistically. The main system might have all text translated, but users sometimes see nontranslated messages (especially error messages) from the operating system, the browser, or a companion system (such as a database management system). Developers might not be in total control of a user’s workstation, but they must realize that users might be confused about the source of a problem when calling for support. Second, many languages require a two-byte character set because of the large number of characters in the language. For example, many Asian languages use more than 50,000 characters. Unicode (www.unicode.org), based on ISO 10646, enables the input, display, and output of all known human languages without data corruption. However, not all systems currently support Unicode. Developers can expect to deal with a difficult and changing environment for character sets for some time. I recommend supporting only a few languages initially, especially for Internet interfaces. For example, seven languages (English, Japanese, German, French, Spanish, Portuguese, and Swedish) account for 90 percent of online users (as of 1999). Another approach might be to minimize some
The initial and ongoing costs of localization are significant. eTranslate, a Web-based service bureau, charges US$50 per page for European languages and US$60 per page for Asian languages for translation of content only. Microsoft currently spends more than $300 million per year on localization of their products into 46 languages. Berlitz Translation Services estimates that fully localizing a software product for one additional language costs at least $50,000 to $100,000, whereas Microsoft estimates its costs are $300,000 or more per product.1 Forrester Research estimates that localizing a new Web site adds 10 to 60 percent of the original development cost. Internet sites typically change twice a year,2 so localized Web sites also have significant, ongoing maintenance costs. Detailed accounting of localization costs is critical for planning future efforts, especially if the company sells localized products or localization services. In such cases, the company needs that information to accurately price development services and product maintenance. High development and maintenance costs, and their impact on product pricing, argue for a systematic approach to localization that includes cost measurement. GTC initially developed its portal without adequate cost accounting, and, although it considered localization needs from the beginning, a technical review found the initial portal to be nonscalable and not easily adaptable. When the decision was made to redesign the portal for the new technology environment (which was concurrent with a change in the company’s technical leadership), no data existed on the initial portal development with which to estimate the time needed and cost of a redesign. This lack of information reinforced the need to collect such information, and the new technical management instituted procedures to collect metrics on all development activities. In some ways, this initial mistake was serendipitous, because the impact was relatively low (there was little basis for planning the portal redesign effort) and because managers and developers are now committed to measuring all the costs associated with the main software product (now in development for several medical practices). This product will have to be localized extensively to the needs of the individual practices as well as locales, and the company must have solid cost information to price the product appropriately.
References 1. H.H. Preston and U. Flohr, “Global from Day One,” Byte, vol. 22, no. 3, Mar. 1997, pp. 97–104. 2. J.E. Yunker, “A Hands-on Guide to Asia and the Internet,” Intercom, May 2000, pp. 14–19.
of your language and other issues by creating unique content for each target market or by making the content a subset of the content for the original site. GTC’s approach was phased introduction of the portal, with phase one including Costa Rica, United Arab Emirates, and Australia. This reduced the size of the problem while still providing experience in multiple languages, including one with a non-Roman alphabet. Currency. Multinational transactions often
involve displaying the appropriate local currency, indicating the applicable local tax, including any tariff or other duties that might be incurred, calculating and timing the curMarch/April 2002
IEEE SOFTWARE
77
Cultures also differ dramatically on the meaning of any one color.
rency conversion, and determining how and when the accounting for that transaction will occur. Although the International Accounting Standards Committee of the International Federation of Accountants is currently trying to develop international standards for accounting, the most recent proposal was rejected by the US Financial Accounting Standards Board, which identified more than 200 differences between the international and US standards. Until an international standard is created and accepted, each company must determine how accounting is to be done when the transaction involves parties in different countries. The problem’s scope depends on the nature of the Web site. In the case of GTC, where orders are taken via the Web site, the in-country offices use their accounting firms (employed for all their accounting needs) as sources of knowledge about financial transactions. Images and sounds. Countries differ in their interpretation and use of images and sounds. In some countries, the flag is prominently displayed on products, but Saudi Arabia’s flag includes holy symbols associated with the Koran, and thus anything with a Saudi flag on it cannot be thrown away. Symbols like a US-style mailbox or a shopping cart are not meaningful everywhere. The “thumbs-up” and “OK” hand signals used in Western countries are regarded as sexual gestures in others. Many cultures do not accept the use of images of women or women and men together. Sound as a system feature (for example, a beep indicating an error) might be appropriate in the US, but it might embarrass Asian users in front of colleagues working nearby. Pictures and graphics should be as culturally neutral as possible, or localized. At GTC, when patient–doctor interactions needed to be shown, pictures were changed to eliminate male–female combinations and states of undress that are not acceptable in the United Arab Emirates. All sounds were eliminated as unnecessary.
Page layout In Latin-based languages, documents are laid out left to right, with the next line appearing below the previous one. Arabic and Hebrew read from right to left. East Asian languages follow a different layout—for in78
IEEE SOFTWARE
March/April 2002
stance, Japanese text typically is displayed top-to-bottom, with lines right to left. Development of international style sheets might provide part of the solution to this issue, but designers should be aware that the habitual pattern of scanning a page will differ between languages. Cultures also differ dramatically on the meaning of any one color. In Western countries, red is alarm, white is pure, black is somber, and green indicates growth or money. In Asia, red is joy, white expresses mourning, and black is a lucky color. In Arabic countries, green is a holy color. In the West, the most important object on a Web page should appear in the upper left corner, whereas in East Asia, Arabic countries, and Israel, that object should be positioned in the upper right. If you use color as part of a design, you should examine each color’s meaning when converting to other cultures and adapt as necessary. Conformity is the key for the easy information content issues: identify and conform to the local standards, and use technology to provide translation functionality where appropriate (for example, measurement conversion) and translation of data to a global, common standard (such as displaying an address in the local format but having one data definition for address information). In other cases, content issues regarding language, currency, images, and sounds are much more difficult to identify and address. Navigation Navigation between Web site pages can be structured as a network or a hierarchy. Cultures that are high in uncertainty avoidance16 might not be comfortable with links that do not follow a strict order, especially when a user can get “lost” at the site. A recent comparison of German and US Web sites found that German sites have a much more hierarchical navigational structure with few links to related sites, whereas US sites exploit the use of hyperlinks extensively within the site and to related sites.17 Although Becker and Mottay point out such inconsistencies as a design failure,9 they might, in fact, represent important localized structures. One suggestion is to explore with incountry experts whether there is a national preference for navigational structure. If not,
The Localization Industry
then consistency in navigation makes good design sense. Performance Great disparity exists between countries’ telecommunication infrastructures, so the capability of the infrastructure and cost of access in each country must be examined. Fortunately, the importance of information technology to socioeconomic development is currently driving policy changes in countries with poor infrastructure. Most users worldwide do not have fast connections, and some pay high per-minute access charges. In general, the price of Internet access is higher in developing countries; for example, the price of access in Australia is 1.5 percent of the country’s gross domestic production per capita, in Mexico it is 14.8 percent of GDP per capita, and in Ethiopia it is 76.8 percent of GDP per capita.18 Although there is general agreement that bandwidth capability will improve and costs will lessen, in the near term it is important to minimize slow-to-load features such as graphics in Internet and intranet applications. Many sites have a text-only version available as an option. Analysis and design for localization The key idea in developing global systems is that “the culture, language, and user-dependent parts of the software application are isolated from the software core during development.”19 GTC uses the following sequence once it has determined and modeled the user requirements: 1. Isolate the interface and business objects and their relationships. Interface objects are granular components that make up the page, including toolbars, content blocks, graphic blocks, background design, links, input fields, sounds, and cookies. Business objects are the processing (code and utilities) and the data storage and retrieval (data model) needed to produce the interface objects. 2. Examine the interface objects to determine if you need to change or delete them or if you need to add new objects. 3. Design the new interface objects. 4. Conduct usability tests of the new interface objects (described later). 5. Identify what new or changed business
Outsourcing some or all localization development and maintenance is possible. Decisions about whether and what to outsource are based on the traditional tradeoff issues relevant to any make-or-buy decision. The advantages of in-house localization are that the organization builds expertise, it can control process and quality, and competitors might not be able to easily reproduce the localization results. However, as discussed elsewhere in this article, in-house localization has significant costs, and the expertise required is not always available. The advantages of outsourcing localization are speed of delivery and cost, but no in-house expertise is built, the organization must depend at least to some extent on the company providing the outsourcing service, and competitive advantage cannot be maintained. Although translation software and careful preparation of source text minimizes translation costs, human intervention is still needed to handle words, especially technical terms, for which there is no equivalent in some languages, as well as to deal with differences in meaning from direct translations and cultural differences. The services offered by the localization industry are quite varied. Traditional translation services include human, human-enhanced, and automatic approaches. Some companies offer translation management systems to store and maintain translations, and some focus on specific industries. Automatic translation is especially effective when the source text has been written in an international style, sometimes called controlled language. This style Focuses on writing simple, clear copy (for instance, using a limited number of nouns to qualify a noun) ■ Avoids humor and analogies that don’t translate to other cultures ■ Uses formatting rules that facilitate translation (for example, no dashes or slashes as punctuation marks) ■
GTC reviewed the range of services localization companies offered and decided to purchase automatic-translation–enabled email and discussion room functions for the portal. The main software product and the portal are localized in-house to leverage the market research GTC did to select countries in which to operate and to build in-house expertise in this area. In each country of operation, GTC maintains offices that support system development and testing. The company’s partners that have “real estate” on the portal are responsible for their own localization, but GTC acts as an advisor when a partner has no experience with localization. This consultation has created an additional revenue stream for GTC, but not all partners use GTC’s assistance or localize their sites. Although GTC would prefer that their partners localize their pieces of the portal, it has no control over them; it fears pressing the point will cause its partners to shift to its competitors. A major source of information about localization and outsourcing vendors is the Localization Industry Standards Association (www.lisa.org): for example, in 1999, localization accounted for 32 percent of the US$11 billion world market for translation services.1
Reference 1. “Going Global,” Washington Times, 24 Apr. 2000, www.lisa.org/press/washington_times.html.
objects you need in order to implement the interface objects. 6. Design the new business objects. 7. Create a maintenance plan for the new, localized design, in concert with any existing designs. March/April 2002
IEEE SOFTWARE
79
Localization teams in target countries play a major role in initial design testing.
Localization teams in target countries play a major role in initial design testing. For example, Yahoo!’s localization team in Asia discovered that its online address book that sorts names alphabetically should, in the Asian version, sort names by the number of keystrokes required to produce them.20 In addition, the local presence prevents the image that the company is “the big, bad wolf, the outsider that everyone hopes will lose.”14 At GTC, the staff of the local company office did the initial software testing, with one of the developers from the central company office present to record issues and problems. Local IT developers likely will be brought in to assist in the testing and changes when the company and number of clients grow. Implementation of localized software to date at GTC has required complete localization of the interfaces and some localization of the business objects. The developers implemented the system’s user interface layer with Java applets. However, although Java can support better user interfaces, it tends to consume more client system resources and takes longer to load than HTML-based interfaces.21 Therefore, an important part of GTC’s usability testing was to carefully examine resource usage and download times. Although problems have not yet arisen in this area, the company anticipates having to redo some interface implementations in HTML to minimize system resource use and download times.
T
his review of the technical aspects of localization, the outsourcing resources available, and GTC’s localization effort summarizes what will confront developers who must localize Web sites. Because this review is based on one global telehealth company, additional re-
About the Author Rosann Webb Collins is an associate professor of information systems and decision
sciences at the University of South Florida. Her research focuses on global information systems and cognitive issues in systems development and testing. She is the author of Crossing Boundaries: The Deployment of Global IT Solutions. She received her PhD in business administration with a specialization in management information systems from the University of Minnesota and an MLS in library science from the University of North Carolina at Greensboro. Contact her at the Dept. of Information Systems and Decision Sciences, College of Business Administration, Univ. of South Florida, Tampa, FL 33620-7800; [email protected].
80
IEEE SOFTWARE
March/April 2002
search is needed to create a complete list of Web site localization issues and identify best localization practices.
References 1. Foreign Exchange Translations, “Secrets of Successful Web Site Globalization,” 2000, www.fxtrans.com/ resources/web_globalization.html. 2. Global Reach, “Global Internet Statistics (by Language),” 2001, www.glreach.com/globstats/index/php3. 3. “Going Global,” Washington Times, 24 Apr. 2000, www.lisa.org/press/washington_times.html. 4. M. Sawhney and S. Mandel, “Go Global,” Business 2.0, 1 May 2000, www.business2.com/articles/mag/ 0,1640,13580,FF.html. 5. D. Johnston, “Culture Shock: Taking Your Software Products International,” AS/400, May–June 1996, reprint. 6. L.C. Miller, “Transborder Tips and Traps,” Byte, vol. 19, no. 6, June 1994, pp. 93–102. 7. P. Bourges-Waldegg and S.A.R. Scrivener, “Meaning, the Central Issue in Cross-Cultural HCI Design,” Interacting with Computers, vol. 9, no. 3, Jan. 1998, pp. 287–309. 8. E. Carmel, Global Software Teams, Prentice Hall PTR, Upper Saddle River, N.J., 1998. 9. S.A. Becker and F.E. Mottay, “A Global Perspective on Web Site Usability,” IEEE Software, vol. 18, no. 1, Jan./Feb. 2001, pp. 54–61. 10. N. Kano, Developing International Software, Microsoft Press, Redmond, Wash., 1995. 11. D.W. Johnston, “Critical Business Issue: Is Your Strategy a Winner?” Software Strategies, 1 June 1999, www.softwarestrategies.com. 12. R. Wartzman, “Read Their Lips: When You Translate ‘Got Milk’ for Latinos, What Do You Get?” Wall Street J., vol. 233, no. 107, 3 June 1999, p. 1. 13. K. Nakakoji, “Crossing the Cultural Boundary,” Byte, vol. 19, no. 6, June 1994, pp. 107–109. 14. R.M. Spiegler, “Globalization: Easier Said than Done,” The Industry Standard, 9 Oct. 2000, pp. 136–155; www.thestandard.com. 15. J.E. Yunker, “A Hands-on Guide to Asia and the Internet,” Intercom, May 2000, pp. 14–19. 16. G. Hofstede, Cultures and Organizations: Software of the Mind, McGraw-Hill, London, 1991. 17. E. Lehmair, The Commercial Use of the World Wide Web: A Comparison of German and US Web Sites, unpublished master’s thesis, Univ. Karlsruhe, Karlsruhe, Germany, 1996; available from the author, lehmair@ wiwi.uni-regensburg.de. 18. Int’l Telecommunication Union, “Challenges to the Network: Internet for Development,” Oct. 1999, www. itu.int/ITU-D/ict/publications/inet/1999/index.html. 19. E.A. Karkaletsis, C.D. Spyropoulous, and G.A. Vouros, “A Knowledge-Based Methodology for Supporting Multilingual and User-Tailored Interfaces,” Interacting with Computers, vol. 9, no. 3, Jan. 1998, pp. 311–333. 20. M. Lerner, “Building Worldwide Web Sites,” 1999, www. ibm.com/software/developer/library/web-localization. html. 21. J.Z. Gao et al., “Engineering on the Internet for Global Software Production,” Computer, vol. 32, no. 5, May 1999, pp. 38–47.
For more information on this or any other computing topic, please visit our Digital Library at http://computer.org/publications/dlib.
focus
engineering Internet software
Using J2EE on a Large, Web-Based Project Eric Altendorf, Independent Consultant Moses Hohman and Roman Zabicki, ThoughtWorks
uilding large, multitier, Web-based applications requires an array of software services, from dynamic HTML generation to business domain object persistence. Rather than implement these services from scratch, application developers find it more efficient to use standard, publicly available implementations. Sun’s popular J2EE platform provides a specification and common set of interfaces for these services in the Java programming language. J2EE lets software vendors offer
B The Java 2 Enterprise Edition enables a component-based approach to developing enterprise applications. Here, the authors describe their experiences and lessons learned in using J2EE on a large, Web-based custom development and enterprise integration project.
competing implementations. This in turn lets application developers build software using their choice of service implementations, which frees them to concentrate on application-specific code. (For pointers to more detailed background information on the J2EE technology family, see the “Further Reading” sidebar.) The project we describe in this article is a Web-based enterprise software system for a Fortune 100 client, developed using J2EE technologies including Enterprise JavaBeans (EJBs) and JavaServer Pages (JSPs). The system comprises approximately 700 kLOC, 5,600 classes, and 500 JSPs. We have been developing it continuously for three years, and our client has been running it live for two. We partitioned the system horizontally into three tiers: ■
A presentation layer, which drives the user interface
■ ■
A session layer, which manages the user workspace and session business logic A domain object layer, which handles persistence and entity business logic
The system’s front end is a set of JSPs, each with a “display bean” that provides data and defines presentation logic. The display beans access and update the persisted data by means of XML data transfer objects that the session layer loads and manages. The system also integrates several external services accessed over the network. Here, we discuss our experiences and lessons learned in dealing with five key development topics: J2EE HTML-rendering technologies, JSP internationalization, external system integration, sharing information between tiers using XML data transfer objects, and maintaining complicated domain object hierarchies using code generation. March/April 2002
IEEE SOFTWARE
81
Further Reading For the reader unfamiliar with J2EE and other technologies discussed in this article, we recommend the following sources.
Java 2 Enterprise Edition ■
Information about Java 2 Enterprise Edition is available at http:// java.sun.com/j2ee/overview.html.
Enterprise JavaBeans Mastering Enterprise JavaBeans, 2nd ed., by Ed Roman et al., John Wiley & Sons, New York, 2001. ■ An Enterprise JavaBean overview is available at http://java.sun.com/ products/ejb/index.html. ■ Enterprise JavaBean specifications and document downloads are available at http://java.sun.com/products/ejb/docs.html. ■
JavaServer Pages An overview of JSPs is available at http://java.sun.com/products/ jsp/index.html. ■ Specifications for JSP 1.2 and Servlet 2.3 are available at www. jcp.org/aboutJava/communityprocess/final/jsr053. ■
Other resources A discussion of HTML templating and scriptlets is available at Martin Fowler’s “Template View ISA Pattern,” www.martinfowler.com/isa/ serverPage.html. ■ Descriptions, tutorials, and downloads of custom tag libraries are available at http://java.sun.com/products/jsp/taglibraries.html. ■
J2EE HTML-rendering technologies Most Internet applications render the user interface in HTML. Java systems generally use servlets, JSPs, or both to dynamically generate the HTML. Our solution We decided to use just JSPs for several reasons. First, there are the oft-quoted benefits of separate development roles: Readily available and relatively inexpensive HTML designers can write static HTML templates (like JSPs), while more expensive enterprise Java programmers provide the back end for dynamic content. However, separation proved to be less important during actual development. An internal business application’s graphic design requirements are typically simpler than a public Web site’s, so we didn’t need a graphic design team. Also, we encourage our consultants to maintain skills and responsibilities at all levels—from HTML to architecture—and thus few specialize in graphic design. On the other hand, we planned to build the pages so that the client could modify the design once the project was over. So, while the role separation was not so important during 82
IEEE SOFTWARE
March/April 2002
development, we anticipated that later, during maintenance, the client would find it easier to make look and feel and other HTML-only changes that businesses typically require. Finally, a template-style front end is easier to work with. When HTML and dynamic data are mixed in Java code, seeing the flow of both the program and the HTML output is often difficult. It can also be hard to debug the static HTML or make code changes without breaking the HTML. Experience After more than two years of JSP usage, our experiences are mixed. Although JSP technology permits separation of Java from HTML, it does not enforce it. Developers can still embed sections of Java code (called scriptlets) in the JSP or write display-bean methods that generate HTML and call them from the JSPs. In fact, prior to custom tags, many tasks were impossible without resorting to scriptlets or HTML-producing methods. We are still refactoring some of our older JSPs and display beans to separate the HTML and Java. We did gain the definite advantage of rapid prototyping. Using standard HTMLproducing editors, we can quickly create prototype screens, then simply take the generated HTML file, rename it as a JSP, and hook it up to a display bean. We also learned something about the applicability of JSP technology to different types of pages. The JSP model is excellent for “fill in the blank” pages composed of a static HTML template populated with data drawn from the application (strings, numbers, dates, and so on). However, JSPs are inadequate for highly dynamic pages that require different layouts or designs under different conditions. For pages with moderately varying structure, you must use either HTML-producing display-bean methods or scriptlets that control the page’s content display. For greater variations, you often need imports or includes, which create other difficulties, such as maintaining syntactically valid HTML output. They also force you to deal with the implicit dependencies resulting from bean- and variable-sharing or cascading stylesheet usage. Scriptlets are not necessarily bad if you use them in moderation for basic tasks, such as simple conditional logic. In our experience, however, such simple usage can easily accrete modifications and lead to scriptlet bloat. Worse still, if you need a similar task on sev-
eral pages, independently bloating scriptlets will likely perform that task in slightly different ways, making maintenance difficult. Custom tags are a good alternative, because they do not accrete modifications in this way. They offer a standardized solution to a common problem with a well-defined interface. This encourages developers to use them carefully, leading to cleaner templates. Our most notable successes with custom tags include tags for conditionally including or hiding country-specific content, which gave us a single JSP that serves all countries, and iterator tags for generating table rows, which we previously created using an HTML-producing method on the display bean. Internationalization issues Many business applications must deliver content to users residing in multiple countries, and must thus present data in multiple formats. Sometimes this is as simple as using different currency and date formatting, but in other cases, the presentation is so different that the result seems like an entirely separate application. The internationalization required to extend our application to Australia and Canada was only moderate. The presentation-layer functionality we needed was similar to the US version. Most screens had minor differences due to variations in each country’s business processes and legal requirements. Nonetheless, the changes surpassed the type of internationalization tasks typically discussed in J2EE tutorials, such as presenting text in different languages or data in different formats. Our main design decision was whether to ■
■
Write each JSP to handle every variation for every country (the monolithic approach) or Write one version of each JSP for each country (the tailor-made approach)
Our solution Initially, we picked the tailor-made approach. We had three main reasons for this: tight time constraints, the lead developer’s personal preference, and our temporary inability to upgrade to a JSP container that supported custom tags. Without custom tags, a monolithic approach would have forced us to use scriptlets around every localized form input, table, and hyperlink. As we noted earlier, scriptlets can be messy and quickly render a
large JSP unmanageable. If we grew to support five or 10 different countries, the monolithic JSPs would likely be so complex and difficult to read that we would have to split them up into a single JSP for each country anyway. Furthermore, once it became that complex, breaking up the JSP without error would be difficult. Experience We quickly realized that the tailor-made approach had serious problems: Screen updates often neglected one country’s version of the page; because our system had so many JSPs, keeping them in sync was virtually impossible. Even with only three countries, maintenance was becoming a nightmare. Once we upgraded to a servlet container that supported custom tags, we found a solution to our problem. Because custom tags can selectively include or exclude sections of a JSP, we did not need lots of increasingly complicated scriptlets. This let us unify each screen’s localized versions into one easy-to-read, easyto-modify JSP. So, instead of creating a monolithic JSP riddled with scriptlets such as
Custom tags offer a standardized solution to a common problem with a well-defined interface.
Canada or US-only HTML
we use a simple custom tag: Canada or US-only HTML
This example is a typical tag usage. Not only does the custom tag avoid scriptlet bloat, but we’d hazard a guess that extending this custom tag example to 10 countries would be much easier to understand. So far, the custom tag has proven sufficiently powerful for our screen internationalization needs. However, we can certainly imagine pages with variations that would be difficult to capture clearly using this kind of in-page conditional logic. In such cases, we could create one JSP per country for the page portions that varied dramatically and include these JSPs in the surrounding, unvarying template using a custom tag. The problem is that a developer March/April 2002
IEEE SOFTWARE
83
Using multiple threads to serve more than one request at a time improved performance.
would have to keep track of multiple files’ content when editing a single page’s static template. Perhaps researchers will develop tools some day that let programmers edit an entire country’s template at once (either storing it in multiple files or supplying the necessary conditional inclusion logic behind the scenes), while still keeping invariable content the same across all countries. Integrating with third-party software Very few enterprise applications run autonomously; most must connect to existing systems. Given that such systems are often archaic, use proprietary interfaces, or are simply built with a somewhat incompatible technology, this integration rarely comes easily. Our client’s business domain requires intricate calculations. Our application provides this through integration with third-party financial software, which we’ll refer to here as TPS (for third-party software). The third-party vendor originally wrote TPS for use as a stand-alone application. The client wanted to integrate TPS within our larger application to ease version management and radically simplify what had been human-powered interfaces between TPS and other business processes. Our solution At first, the third-party vendor shipped us a dynamic linked library (DLL) file that exposed a subset of TPS’s objects via Microsoft’s Component Object Model (COM). To drive the DLL, we wrote an extensive adapter composed of two types of components: a server and a pool of translators. To perform financial calculations, the main application sends XML describing financial parameters and the type of calculation required to the TPS adapter’s server component. The multithreaded server component then forwards this XML request to a translator component. This component translates the XML into a series of COM calls into TPS’s library, and returns the result in XML form. The server component maintains a pool of translator components, each of which must run in its own separate Java virtual machine (JVM) process, since the TPS DLL is not thread-safe. We found that using multiple threads to serve more than one request at a time improved performance. Experience Many challenges arose in the process of
84
IEEE SOFTWARE
March/April 2002
integrating TPS into an Internet application. The main problem is that TPS has thousands of possible input parameters. Although we don’t use all of them, the subset we do use can itself produce numerous parameter combinations. Reproducing this much functionality without error is difficult, especially because we do not use the same interface to the TPS library as the stand-alone TPS. Because no one had used the COM interface to the complicated TPS library before, our adapter inevitably used the software in unintended ways. One result was that the translator component processes occasionally crashed, sometimes in an unrepeatable manner. To keep these crashes from bringing the TPS application down, we gave the server component the ability to resurrect failed child processes. In such cases, it repeats the request once, returning a service failure only if the child process fails twice on the same request. This provides two kinds of robustness. For unrepeatable crashes, the repeated request returns the desired result. For repeatable crashes, this strategy avoids corrupting the pool with dead translator components. In addition, our server component restarts translator processes after each successful calculation as well. This eliminates any problems due to memory leaks or variable initialization in the third-party DLL (which seldom, but unpredictably, occur). The cost is a small performance hit. However, this choice, coupled with requiring that the server component resurrect child processes, ensures that the TPS financial calculation engine remains available and correct (for all previously tested requests) over long time periods. Testing the application gave rise to other challenges. Because the COM objects have complex interdependencies—which are fairly common for the problem domain—writing independent, fine-grained unit tests is difficult. We opted instead for a set of regression tests, each composed of XML input and the expected XML output. These tests are fairly simple to automate and natural to generate, because we can retrieve the XML from our application’s logs. They are also easy to maintain using Extensible Stylesheet Language Transformations (XSLTs). However, they do take longer to run than unit tests, so we run them less often—daily instead of hourly, which means we catch regression errors only on a daily basis. However, because only one or two people work on the TPS adapter at a
time, we have not found this to be a problem. Because of the complicated TPS COM object interdependencies, the vendor-supplied DLL requires a lot of quality assurance: The vendors add features, send the results to us, and we use our suite of regression tests to ensure nothing else has changed. Fortunately, we have a good relationship with the vendor, and they’ve always been quick to respond to our bug-fix requests. Nevertheless, this back and forth communication takes a lot of time. Ideally, testing should be collocated with the vendor’s development work so that feedback is more immediate. To address this problem, we are moving away from the TPS COM interface toward an XML interface. With the XML interface, there is just one COM object with one method that accepts XML input and returns XML output. Now, the vendor’s software translates XML to library function calls. When we find a bug, we simply send them the input XML that exposed it. They can easily process that XML within their debugging environment and track down the cause. Additionally, the vendor can maintain a set of regression tests that reflect how our application uses TPS and incorporate those tests into their QA process. We expect this to dramatically reduce the time it takes to incorporate additional TPS features into our application. Distribution: XML data transfer objects To facilitate information flow between tiers, multitiered and distributed enterprise applications commonly use the Data Transfer Object design pattern (www.martinfowler. com/isa/dataTransferObject.html). The DTO encapsulates a set of parameters that one component sends or returns to another component to complete a single remote method call (such as a calculation request from our main application to TPS). In our application, an object called an XML translator constructs an XML-based DTO from data in the domain object layer and ships it to the session or presentation layer, making the data available in a lightweight package. The session and presentation layers can also construct DTOs to be translated back to the domain object layer, persisting the data. Using DTOs prevents the locking problems, network chattiness, and transactional overhead associated with frequent calls to fine-grained
data-access methods on entity beans. Earlier in our project, DTOs were absolutely necessary because the production EJB and servlet containers were in different cities, and the network latency was far too great to rely on direct access to the entity beans. Even now, with servers running in the same JVM, start-up costs for a new transaction for every method call make the DTOs valuable. Our solution For our DTOs, we chose a hybrid XML–Java object approach: An XML document contains the data and is wrapped by a Java class for easy access. We write translators that run in the session layer and perform the DTO–domain object mapping, both by building DTOs from the domain object data and saving modified DTOs back to the domain objects. We can also construct from scratch “update only” DTOs in the presentation layer with only partially populated element trees. When the translator persists such a DTO, it updates only those fields that contain updated values for domain objects. This lets clients who only need to update a few fields do so easily, rather than have to translate a large domain object graph to XML, modify one or two fields, and then save the entire XML back to the domain objects again. We generate the Java wrapper classes from a sample XML document. We do not generate the translators, because the data often takes a different form in the presentation layer than in the domain object layer, and we want to control the translation. At the individual-field level, we often use different data types. For example, we represent what might be an integer status ID in the database by its status keyword in XML (“In Progress,” “Expired,” or “Canceled”), and what might be an SQL date in the database could be in ISO 8601 form in the XML. On a structural level, we control traversal of the entity bean graph. For example, if bean Foo is being translated to XML and contains a reference to bean Bar, we might insert into bean Foo’s XML either bean Bar’s XML translation or a element that lets clients look up bean Bar when required. Finally, on a semantic level, we occasionally introduce new, presentation- or session-related fields into the XML that do not exist on the domain object layer. Our translators can also register multiple
Ideally, testing should be collocated with the vendor’s development work so that feedback is more immediate.
March/April
IEEE SOFTWARE
85
The XML objects make debugging much easier, especially in production or in environments where debugging tools are unavailable.
86
IEEE SOFTWARE
translators of different “flavors” for a single domain object. This lets us handle the differing needs of various application parts. For example, if one application part requires only subset X of the domain object fields, or requires fields in a certain format, and another part requires subset Y and a different format, it’s no problem. We simply write two flavors of the translator. Experience Using XML as the DTO representation was a good choice. Because our application is an intranet application used by relatively few employees, we have not had to worry much about scalability issues, and the XML data structures’ size in the session has not yet been a problem. The XML objects make debugging much easier, especially in production or in environments where debugging tools are unavailable. We can see the current state of the business objects clearly, concisely, and in a human-readable fashion just by looking at the XML. When we have to integrate with other software systems, the XML provides a convenient base for designing the interface. Our experiences have not been entirely positive, however. We’ve encountered several largely unresolved difficulties with using DTOs. First, fine-grained access to individual entitybean fields is still awkward. When only one field is required, it’s inefficient to gather all the data a large DTO requires—which can include a hundred fields from a dozen different domain objects. Also, writing an entire XML translator flavor to return one or two fields is a lot of code overhead. You can write a session-bean method to access that field (in our architecture, all presentation-layer calls must be mediated by a session bean), but to avoid session-bean bloat— and to avoid the original network traffic and transactional issues—we must use such methods in moderation. An alternate solution that we’re currently investigating is to pass the translator one or more XPaths that specify a subset of the XML DTO’s fields, so that the translator fetches only those fields from the domain object. (For more on XPaths, see www.w3.org/ TR/xpath.) Second, using DTOs somewhat complicates the modification of domain object classes. When we add a field to a domain object, we must update the sample XML document, regenerate the XML DTO class, and manually update the translators to process the new data. However, this is not usually dif-
March/April 2002
ficult or time consuming. Third, and perhaps most significant, sometimes the presentation layer requires domain object business logic, and although DTOs provide a means of sharing data between the two layers, they do not help with sharing behavior. For example, a domain object might have an isValid() method that returns true when the object’s fields satisfy certain requirements. If the presentation layer must know the underlying domain object’s validity, we must write a session-bean method that accepts a DTO (or ID) as an argument and delegates the call to the existing method on the corresponding domain object. This works, but suffers from the same performance issues as domain object individual-field access. If the presentation layer modifies our DTO, and we need to determine the DTO state’s validity, we have an even more unpleasant situation. In this case, we must either ■
■
Write a new method that takes the DTO and duplicates the logic from the domain object method, or Translate the DTO back to a temporary “dummy” domain object on which we can call the isValid() business method
So far, the problem is not that great in our case. A possible future solution is to use method objects1 that represent rules—such as validity conditions—or other tasks. We could then run these rules against both domain objects and DTOs, keeping the business logic in only one place. Embracing change: Generated domain objects Typically, the core of an enterprise application has a domain object layer—a layer of code that manages persistence and business logic for the fundamental objects in the business domain model. Our domain object layer maintains the state of well over 100 domain objects and also provides some of their basic business functionality. Such scale and complexity always provides developers with challenges in keeping systems flexible and maintainable. Our solution In our application, most of the domain layer consists of code generated using metadata files that describe the business objects. Several factors motivated our decision to use
code generation. First, EJBs are a heavyweight technology with significant coding overhead: A bean developer must create at least four separate files for each domain object, which involve a fair amount of code or declaration duplication. Making the same change in all these classes slows down development. Because our domain objects were evolving rapidly, especially in early prototyping stages, we had to be able to quickly update the code, regenerating from the changed metadata. Later, when we began to separate persistence and transactional responsibilities (implemented with EJBs) from business responsibilities (implemented with plain Java classes), we required even more classes, further increasing the generators’ value. Second, we’d yet to fully commit to EJB technology—particularly entity beans, because at that time they were not even required by the EJB 1.0 specification (http://java.sun. com/products/ejb/docs10.html). Third, EJB technology was still rather immature; vendor-supplied containers exhibited many bugs (in fact, they still do). Using generated domain objects let us centralize the required hacks and bug workarounds in one place—the generators—yet still apply them across all domain object implementations. We named our domain object inheritance structure the “martini glass model” for the visual appearance of its UML diagram (see Figure 1). Its complex structure is partly a result of the fact that, unlike many code generation schemes, generated and handwritten customizing code never live in the same file, so merges are never required. Instead, the Java compiler and virtual machine effectively perform merges automatically as a result of the inheritance structure. Our UML model was not designed up front, but rather evolved as we required more features and flexibility. This would have been infeasible without generated code. We developed the structure in five stages, adding features and complexity on an asneeded basis: 1. We generated the four basic required classes or interfaces: the remote interface, the home interface, the primary key class, and the entity bean itself. 2. We generated the finder class (the service locator), which encapsulated the Java Naming and Directory Interface (JNDI) calls and provided a caching service for
Manually written; provides implementation for business methods defined in the DomainObjectBusiness interface
getA(){ return state.a; }
DomainObject
DomainObjectBusinessImpl
DomainObjectState DomainObjectJDBCAdaptor
getA(){ return peer.getA(); }
DomainObjectEJBAdaptor
DomainObjectBean
Figure 1. UML diagram of a sample domain object model’s core. All classes and interfaces shown are generated from metadata, except for the DomainObjectBusiness interface and the DomainObjectBusinessImpl class, which are hand-written.
the home interface. 3. We split the entity bean into a generated persistence class (entity bean class) and a handwritten business-logic class. This let us regenerate the entity bean (the field accessors) without obliterating handcoded business methods. 4. We then generalized the persistence interface (field accessor signatures), allowing for persistence implementations other than entity beans. Because our EJB container did not support read-only access to entity beans, we used our persistencelayer abstraction to permit two implementations: fully protected entity bean read-write access and Java Database Connectivity (JDBC)-based read-only direct database access. 5. We added custom mappers and finders. Mappers define the mapping between domain objects and the persisted data that represents them, and custom mappers let us implement unusual persistence requirements. Custom finders were useful because our container’s query language was insufficiently powerful for the domain object searches we needed. The finders provide an abstraction layer, delegating to either the bean home methods for simple searches, such as “find by primary key,” or custom finders implemented with SQL queries for more complex searches. Experience One problem we’ve frequently encountered March/April
IEEE SOFTWARE
87
with our domain objects is deadlocking. Our EJB container uses pessimistic concurrency control, so if one transaction accesses an entity, it will prevent code running in another transaction from accessing that same entity. Deadlock can occur if, for example, an entity calls a session-bean method—thus starting a new transaction—and the called method in turn touches the original entity. To help avoid deadlocking, we carefully set transactional contexts and minimized locking through the use of JDBC-based read-only persistence. Another problem we faced was performance. By default, every call on an entity-bean remote interface must go through the gauntlet of security context checks, transactional context checks, acquiring locks, and calls through stubs and skeletons—even if all that the caller requires is read-access to a field. In such simple cases, using JDBC-based persistence for read-only access saves a lot of overhead. One of the challenges in developing Internet applications is that many of the technologies are new and many of the implementations are buggy, incomplete, or not quite written to specification. This was certainly true for our EJB container. Many of its bugs were related to caching and transactional boundaries and were difficult to find, reproduce, and test against because the testing en-
About the Authors
vironment must exactly duplicate the running system’s transactional context management. Once we identified the bugs, however, using code generation facilitated workarounds throughout our domain object layer. One disadvantage with code generation is that to achieve the flexibility of handwritten entity beans, we must use an elaborate structure of supporting interfaces and classes. This creates a complex system that takes longer for new developers to learn. Some of the system’s features are esoteric, and few developers know how to use them. For example, we can set the persistence implementation to JDBC-based read-only for all domain objects accessed in a given transaction. This is useful for avoiding deadlocks in calculations that access many domain objects. Although few developers use or understand such advanced features, they are consistent throughout the application. This would not be true with handwritten code. Also, the system basics are quite simple. Several other ThoughtWorks projects have successfully used the generators, which let developers get an entire domain object layer up and running rapidly. The greatest benefit of our domain objectlayer generation system is that it lets us maintain our agility and frees us from architectural decisions made years ago. The generators let us easily modify individual domain objects as well as make major, global architectural changes, such as abstracting the persistence interface on every system domain object, or, in the future, migrating to the EJB 2.0 specification.
Eric Altendorf is an independent consultant. He has worked in both academic settings
and private industry, and was a software developer and architect at ThoughtWorks on the project described here. His professional interests include agile development, software architecture and design, and generative programming. His research interests include neurally plausible theories of thought and language, reinforcement learning approaches to computer-played Go, and time-series prediction. He received a BS in computer science and mathematics from Oregon State University, and plans to resume study for a doctoral degree in artificial intelligence. Contact him at [email protected].
I ■
Moses Hohman is a software developer for ThoughtWorks, a custom e-business soft-
ware development consulting firm. Currently he works out of the recently opened Bangalore, India, office, where he mentors new software developers and teaches a course on agile software development at the Indian Institute of Information Technology Bangalore. He received an AB in physics from Harvard University and a PhD in physics from the University of Chicago. Contact him at [email protected]. ■ Roman Zabicki is a software developer for ThoughtWorks. He received a BA in com-
puter science from the University of Chicago. Contact him at [email protected]. ■
88
IEEE SOFTWARE
March/April 2002
n the process of developing our system, we learned many lessons.
JSPs let us rapidly develop a Web application’s user interface and separate Java and HTML development roles. However, developers writing applications with highly dynamic content might find JSPs awkward, making it more difficult to take advantage of the separation benefits. Custom tags are a powerful, clean way to abstract shared JSP behaviors, such as iteration or conditional content inclusion. Although conventional wisdom advises against maintaining a set of regression tests on third-party code, it is in fact often useful, especially when those tests are written in a portable format such as
■
■
XML and can thus be transferred to the third-party vendor. Data transfer objects are a useful, often necessary part of multitiered applications. However, owing to the resulting dual object representations, developers must carefully consider which business methods belong in the domain object layer and which belong in the presentation layer. Doing so can help avoid excessive code duplication or cross-tier method call delegation. It is possible to change even the most fundamental architectural decisions— such as the domain object-layer design— even when you are well into the project. Code generators let developers make sweeping changes easily across the entire code base and are thus an extremely valuable tool for the agile developer.
At present we are in the process of internationalizing our application for France, our first system-wide language translation. The changes involved have highlighted some unnecessary complexity in our presentation layer. Some of this complexity we can resolve, applying the lessons discussed above uniformly throughout the application. Other issues, such as an awkward algorithm for shuttling data between HTML forms and the XML DTOs, remain problematic. We have experimented with several ideas, from the Apache Struts framework (http://jakarta.apache.org/struts) to simple custom-built architectural solutions. We anticipate that more useful lessons will come from these investigations. Reference 1. K. Beck, Smalltalk Best Practice Patterns, Prentice Hall, Upper Saddle River, N.J., 1997.
Career Opportunities MEMBER TECHNICAL STAFF/CABLE MODEM PROJECT. Responsible for design, Develop and implement software test programs and test procedures for CM (Cable Modem), which will verify the quality, performance and compliance to DOCSIS (Data-Over-Cable Service Interface Specification). Will provide documentation and support for trouble shooting and fixing any problems reported during system testing of the software. Will also be responsible for testing and making the software ready for certification process. Will understand and apply new and upcoming technology trends to the current test software and apply them to new generation Cable Modems like VoIP (Voice over Internet Protocol) and others. Requires M.S in Computer Science with at least 3 years of professional experience in job offered or network programming; Experience must include programming using SNMPv1/v2/v3, DHCP, TFTP, ToD Internet Protocols, and using Ethernet frames, TCP/IP Packets, MAC frames. Must have current authorization to be permanently employed in the United States. Annual salary of $65,000. 40 hours/week (8 am – 5 pm). Send resume with Social Security Number to: Indiana Department of Workforce Development, 10 N. Senate Avenue, Indianapolis, Indiana 46204-2277. Attention: Mr. Tim Lawhorn, Reference: I.D.# 8139386. ************ SOFTWARE ENGINEER Must have 9 months exp in job offered or 9 months in related occupation as Quality Control Engineer. Implement,
improve and maintain the ISO 9001 certification and TickIT certification for software. Develop and implement the calibration system according to the ISO 17025 and obtain NIST (National Institute for Standard and Technology) traceability. Using statistical control techniques to monitor and improve production, test processes and products in the development of RD family acquire CE Mark using directives 73/26/EEC and 89/336/EEC. Coordinate the design reviews, verification and validation of measuring and test product. Perform vendor verification for PCB, plastic and metal parts. Must Possess Certified Quality Engineer certification ASQ (American Society for Quality). To work 40 hr/week from 8am to 5 pm. Salary is $54,000 per year. Applicant must possess permanent authorization to work in the U.S. Qualified applicants send resumes with Social Security Numbers to the Indiana Department of Workforce Development, 10 N. Senate Ave., Indianapolis, IN 462042277, Attn: Mr. Gene R. Replogle. Refer to ID # 8138653. *********** RESIDENT SYSTEMS ENGINEER Must have BS in Computer Science or equivalent education experience. Must have 2 yrs exp. in job offered or 2 yrs exp. in related occupation as Computer Engineer or related. Design Release Satellite Digital Audio Receiver. Electronic integration of Component with vehicle. Mechanical integration of Component with Vehicle. Component/ Vehicle level Validation/ debugging. Track Program timing & finance. Write component
technical Spec and Diagnostic Specification. Write Class 2 Communication functional specification. Write CAN/GMLAN Communication functional specification. To work 40 hrs per week & an 8-5pm work schedule. Qualified applicants must send resume to Shannon Miller, Administrative Assistant at Delphi Delco Electronics Systems, One Corporate Center M/S CT17A, PO Box 9005, Kokomo, IN 46904-9005. Please refer to PO# 010998. ************ Senior Application Developer Needed at Ingersoll-Rand Company, Security & Safety Business Unit in Indianapolis, IN. Duties: Develop & maintain Oracle application programs & systems (business, manufacturing & engineering). Perform functions of systems analysis & programming in multiple IT & S operating systems. Perform system analysis, design, documentation, programming, testing, implementation, user training & continuing support of all applications systems. Review & recommend IT & S policies. Evaluate and implement third-party software systems applications. Utilize Oracle SQL*PLUS, PL/SQL, Packages, Forms, Reports, C Language and UNIX shell programming. Must possess Master’s Degree or equiv., in Computer Science. Will accept Bachelor’s Degree & 5 yrs. of exp. in lieu of Master’s Degree. Must also possess 2 yrs. of development exp. either in the job offered or in related occupations of Software Analyst or Programmer. Competitive salary & benefits. Send resume to Justin Zlotnick at 111 Congressional Blvd., Carmel, Indiana 46032.
feature object modeling
Domain Mapping Using Extended UML Object Diagrams Dragan Milicev, University of Belgrade
oftware tools that support modeling in engineering domains provide environments for applying modeling methods and notations, thus making modeling less time consuming and error prone. One of the most important features of modeling tools is automatic output generation, or model translation, no matter what the output represents. It can be documentation, source code (for software systems), a netlist (for on-chip hardware), or any model other than the one the user created.
S Most contemporary software and other engineering methods rely on modeling and automatic translations of models into different forms. The author advocates a UMLbased translation specification method that is visual and therefore easier to understand and use. 90
IEEE SOFTWARE
For complex applications, we might need to customize the output generator or build a new one. How can engineers easily specify or customize this automatic output generation? I propose a method where extended UML object diagrams specify the translation. This method is visual and therefore produces specifications that are clear and concise and easier to create and maintain. My work focuses on the modeling domains, whose metamodels can be defined using basic object-oriented structural concepts, such as classes and attributes, associations, and generalization.1 My approach can be used in modeling tools with different levels of customizability. Standard translation approaches Two conceptual levels are important for the modeling process. The upper level is the metamodeling level, which generally defines the modeling domains’ abstractions. That
customizing output generation of a simple modeling environment that will generate C++ code for state machine models. I assume that the user wants to obtain the code shown in Figure 1b, which is an implementation of the State design pattern.2 Code generation for state machines should be customizable. If the user needs different execution models because of performance, concurrency, distribution, or other issues, he or she should be able to change the manner in which the code is generated from the same initial state machine model. For this example, several classes will be generated in the output code. In this example, the first class is named FSM. It contains the methods that correspond to the events to which the state machine reacts. The second class is named FSMState and is abstract. It has one polymorphic operation for
each event. Finally, one class derived from FSMState is generated for each state. It
overrides the operations that represent those events on which the state reacts. Figure 1c shows a simple metamodel of this modeling domain. It defines the domain abstractions as the classes State, Transition, and so on, and their relationships. For example, a transition is connected to its source and destination states. The associations source and target represent the connections in the metamodel. A concrete model defined by the user in this domain (such as the one in Figure 1a) consists of instances of the classes from the metamodel. These are connected by the links as instances of the corresponding associations.1 For example, the state A in Figure 1a is a notational symbol for an instance of State. Similarly, the transition edge from the state A to B (indicated
Figure 1. Code generation for state machines: (a) a sample state machine model; (b) a fragment of the generated code; (c) the domain’s metamodel.
March/April 2002
IEEE SOFTWARE
91
The translator first creates the needed instances of the intermediate model using the built-in UML metamodel and then invokes the built-in code generator to produce the ultimate output.
by the arrow from A to B) is a notational symbol for an instance of Transition, linked by an instance of the association source with the instance A, and so on. In this example, the user specifies the code generation strategy to apply to each instance of StateMachine created in the model. In most modeling tools, the standard practice is to hard-code the output generation in a procedure. The procedure involves navigating through the instances in the model, reading their attribute values, and producing the textual output following the C++ syntax and semantics. For this specification, I will use C++ for generality. A small fragment of code that generates the beginning of the class FSMState declaration might be void generateStateMachineCode (StateMachine* this) { ... // File opening and // other preparation actions // Generate base state class: output