Before you start looking at how to implement a solution, you need to be sure you know what the problem is. This is what requirements analysis is all about. The degree of analysis needed depends on how big your project is, how many people will be working on it, and so on. The important thing is to end up with some documentation of what you think the requirements are—this information will be what you test your solution against.
Start by getting an overview from your customer of the business problem that the application will solve. You should look for the benefits the application will provide (compared to its costs), not just how the customer thinks the problem should be solved. Will the application improve productivity? Improve customer satisfaction? Reduce maintenance and training costs? These are the kinds of questions you need to ask in addition to asking what the application should do.
When you think you understand the problem, write it down in simple language the customer will understand. The following text shows part of the business problem statement for the Island Hopper sample application, which is included on the companion CD:
Problem Statement The "Island Hopper News" would like to automate its classified advertisement submission and billing process. Customers should be able to submit classified ads through the "Island Hopper News" Web site. Customers will be billed later for their ads. The editor wants to significantly reduce the time spent on processing paperwork so that the newspaper can run classified ads every week (instead of bimonthly), thereby generating more revenue. A joint review by the classified ad and accounting departments concluded that existing classified ad processes consume excessive resources without providing adequate customer service.
During requirements analysis, you should try to avoid making assumptions about the technologies used to implement a solution. If the business problem is connecting to existing software or hardware, go ahead and say so. If the business problem is making the application available over the Internet, that's fine too. But try to avoid describing assumptions such as "the application will create a file…" or "using Visual Basic…" at this point. Putting predictions like this in your problem statement can produce tunnel vision during design. Perhaps the application will work better if its results are stored in a database. Perhaps there's really no business reason to save the results at all—it's just the way things have always been done in the past.
Once you've written the problem statement, review it with your customer. The customer should verify that you understand the problem correctly before you continue. This is also an ideal time to discuss the feasibility and desirability of solving the problem. A solution might be technically possible, but the cost or time to market might be too high to justify solving the stated problem. In this case, you might need to narrow the problem scope.
The result of this step is a document describing in plain language the business problem that you and your customer have defined. This document will help keep you focused on solving the identified business problems while you design the rest of the solution.
The entire problem statement for the Island Hopper sample application is contained in the BUSINESSPROBLEM.TXT file, which is located in the \IslandHopper\Requirements directory on the companion CD.
After you have defined the overall business problem, it's time to dig into the specific functional requirements for your application. Functional specifications are described in detail within the Microsoft Solution Framework (MSF) and by most analysis methodologies. In essence, a functional specification is a document describing what the application must do from the user's perspective. A good way to generate a functional specification is to enumerate scenarios in which the application will be used. This process is known within MSF as storyboarding. Some object-oriented design techniques call this "defining the use case model."
For more information about MSF, contact your local Microsoft consulting services or Microsoft sales office, or e-mail firstname.lastname@example.org.
As you enumerate scenarios, you will begin to see a common usage pattern in most distributed applications. Users interact with applications in an iterative fashion. Some information is presented to the user. The information is analyzed. After a variable number of presentation and analysis steps, the user can elect to update the data. Each user interaction step might take a fairly lengthy and indeterminate period of time.
We'll see how this pattern maps to the three-tier application architecture a little later in this chapter in the section "Designing Classes." For now, just remember that a scenario defines a sequence of steps to complete a user-level task. Start by looking at the normal things the user will do. For example, Figure 7-1 illustrates the "Place a Classified Ad" scenario for the Island Hopper application, using a Unified Modeling Language (UML) sequence diagram. Once you have defined the normal scenarios, you can look at common error scenarios.
The result of this step is a document containing the functional specification that you and your customer agree to. It's a good idea to label each scenario or specification with a unique number. If you include references to these labels in your design documents or source code, you will be able to trace functionality from requirements clear through to implementation (just in case the requirements change).
Figure 7-1. The "Place a Classified Ad" scenario for the Island Hopper application.
The entire functional specification for "Island Hopper" is contained in the FUNCTIONALSPEC.TXT file, which is located in the \IslandHopper\Requirements directory on the companion CD.
In addition to functional requirements, you should spend some time up front defining the performance, deployment, and security requirements that must be satisfied by the application. Let's look at a few scenarios from other applications to identify the types of things you need to consider for distributed applications.
Our first scenario involves a customer service call center, as shown in Figure 7-2. A customer calls his local insurance agent at 10 P.M., after the agent has closed the office and gone home for the night. The phone call is forwarded to a customer service center, where an application server looks at the call information, queries a database, and routes the call and insurance agent information to a customer service representative. The representative answers the call using the name of the local insurance agency. This enables the insurance company to deliver 24-hour customer service, even for the customers of small insurance agencies. The representative asks the customer for his name and policy number and starts another database query that pulls up the customer information. The customer and the representative engage in a phone conversation for two minutes. The representative then updates the customer's insurance records as necessary. Changes to the customer's records are securely transacted to a back- end Oracle system.
Figure 7-2. The "Customer Service Call Center" scenario.
In this scenario, the system must be available whenever local agencies are closed. In addition, quick response time is required. If a customer is trying to reach her insurance agent after hours, she's probably got a problem she wants solved fast—and each service representative can handle only one customer at a time. This response time can be on the order of seconds, however—we don't need millisecond responses.
Another thing to notice about this application is that we can't really predict when customers will call or how many customers will use the service. We know that if a disaster strikes, there will be a surge in calls, but we don't know when the disasters will happen. So the application must be able to handle two types of increased volume: the application must be able to scale as demand on the call center increases, and the application must also be able to handle high- volume periods.
The next scenario we'll look at is banking over the Internet, as illustrated in Figure 7-3. A money center bank (this is a term for huge banks like Citibank or Bank of America) operates a cash management application for corporate customers. The application runs on existing Tandem minicomputers and IBM mainframes. The bank decides to provide better service to its customers by letting them directly access the cash management application via the Internet. Small business customers are provided with a URL to the bank's Web site, along with a Secure Sockets Layer (SSL) account for security. Large corporate customers are provided with a dedicated cash-management computer running on a Microsoft Windows NT workstation. This PC runs value-added applications. Both the Web-based customers and the PC application customers—10,000 customers in all—access the same application server that provides the front-end for the mainframe systems. Multiple firewalls are used to ensure security. Each customer can monitor his or her company's cash position over the Internet throughout the day. Any changes customers make are reliably transacted to the back-end mainframes. Most important, the bank can quickly provide new services to customers by writing new applications on the application server.
As with our first scenario, response time must be good—on the order of seconds at the user level—and the application must scale as more customers access it. We also have the problem of unpredictable load in this scenario. We know that there will be busy periods, but we don't know exactly when the busy periods will be.
In addition, in this scenario security and reliability are vital. Customers don't want their financial information to be visible to anyone else. They also don't want their transactions lost! Data integrity is essential and different levels of service must be made available to different types of users. Finally, the new application must interact with existing mainframe systems.
Figure 7-3. The "Internet Corporate Banking" scenario.
These two scenarios share the following features, which are common to most distributed applications:
The more specific information you can obtain about how these factors apply to your application, the better.
Performance can be defined in many ways. The important thing is to come to an agreement with your customers about the required service levels relative to available hardware.
One requirement to consider is availability. What percentage of time does the application need to be available? In the "Customer Service Call Center" scenario, availability might be defined as 99.99 percent between the hours of 6 P.M. and 10 A.M. and 50 percent between the hours of 10 A.M. and 6 P.M., using four replicated application server machines.
Another requirement to consider is the number of concurrent users that must be supported. You might include average and maximum numbers, with corresponding average response times. Another way of stating performance requirements is in terms of the number of transactions that must be processed in a given amount of time. In the "Internet Corporate Banking" scenario, performance might be defined as 50,000 transactions per hour, with a 0.5-second average response time and a 3-second maximum response time.
Whatever requirements are stated, you should define the minimum acceptable performance for a particular hardware configuration. This value will give you a baseline target for testing. Some variables to consider when you are defining hardware configurations are the number of processors, amount of memory, number of server machines, server speed, and network speed. As the application is built, you can test it on the target hardware configuration to determine whether the performance requirements are met. We'll look at performance validation in Chapter 13.
Now is a good time to document the existing systems that your application will need to interoperate with. For the most part, integrating into the existing enterprise computing infrastructure and policies will not cause any problems. COM and MTS don't really care where components are located, as long as a communications link can be established between the caller and the component.
Many applications can be designed and implemented without regard to how they will be deployed. In fact, you should try to build your application so that system integrators or administrators have the flexibility to deploy the application in many different ways. This flexibility will help ensure that your application will continue to be useful as machines and network infrastructure change. However, there are situations in which deployment requirements will constrain your design and implementation. Those requirements are the important things to document prior to application modeling and design.
One factor to consider is whether there are existing data or application servers you will need to use. If so, what operating systems do they use? What communications protocols do they support? What API can you use to interact with them? Where are the systems located on the network? Are there restrictions on which machines or user accounts are allowed to connect to the servers? The answers to these questions can impact your application design as well as how you implement and package particular COM classes. For example, consider a corporate policy that dictates all server machines must run within a firewall that permits only HTTP traffic. If you need to support client applications running on machines outside the firewall, you'll need to design your application so that the client application communicates with the server machine only via HTTP.
Another factor to consider is where clients and data sources are located. Are clients geographically dispersed or centrally located? If the clients are dispersed, how are they connected to each other? Is the data centrally located, or is it located near the clients that use it? Are some types of connection more expensive than other types? Are connections intermittent or persistent? Again, the answers to these questions can influence your application design. Consider a scenario in which insurance agents nationwide submit claims, ultimately to a central office. The agents are connected to an office LAN, which in turn is connected to the central office via satellite. In this scenario, it would probably be smart to run as much of the claims applications as possible in each office. For example, agents submit claims to the local office, and the local office then batches all the claims and submits them to the central office. Normal COM calls could be used for all the local traffic, but perhaps Microsoft Message Queue Server (MSMQ) should be used to communicate with the central office.
Finally, you should consider whether there are any security requirements that might impact your application design. A couple of issues are likely to arise. First, you might need to pass sensitive data between applications or components running on different machines. You might need to encrypt the data before transmitting it or perform some type of integrity checking to ensure that the data hasn't been tampered with. For example, in an online shopping application, you would probably want to encrypt the customer's credit card information before sending it across the Internet. If you are going to pass encrypted information as parameters to a COM interface, the mechanism for encrypting and decrypting the parameters must be documented as part of the interface design. If, on the other hand, you are going to use authentication mechanisms provided by the underlying communications and security layer of Windows, you might want to split secure operations into a separate COM class. Otherwise, you could end up paying a performance penalty for operations that don't really need such stringent authentication checking. The important thing at this stage is to identify any special authentication or data protection requirements.
Another issue to consider is whether there are any constraints on who is authorized to perform particular operations. If so, you should first document which operations require authorization. Then document the types of users who can be authorized to perform those operations. These user types will map to roles in the MTS security model. For example, the Island Hopper classified ads application contains some functional specifications that apply to customers, some that apply to the classified ad department employees, and others that apply to the accounting department employees. As we'll see in the section "Grouping Components into Packages and Processes" later in this chapter, these requirements have a big impact on how you package functionality in your application.
This step results in documents containing the performance, deployment, and security requirements that you and your customer agree to. Again, it's a good idea to label each requirement with a unique identifier so that you can trace design and implementation back to specific requirements.
The performance, deployment, and security requirements for the Island Hopper application are contained in the PERFORMANCE.TXT file located in the \IslandHopper\Requirements directory on the companion CD.