Export (0) Print
Expand All

Chapter 4: A Technique for Architecture and Design

For more details of the topics covered in this guide, see Contents of the Guide.

Contents

Overview

This chapter describes an iterative technique that you can use to think about and sketch out your potential architecture. It will help you to bring together the key decisions discussed in this guide; including quality attributes, architecture styles, application types, technologies, and deployment decisions.

The technique includes a series of five main steps, each of which breaks down into individual considerations explained throughout the remainder of the guide. The iterative process will help you to produce candidate solutions that you can further refine by repeating the steps, finally creating an architecture design that best fits your application. At the end of the process, you can review and communicate your architecture to all interested parties.

Depending on your organization's approach to software development, you may revisit your architecture many times during the lifetime of a project. You can use this technique to refine your architecture further, building on what you have learned in the intervening period of spiking, prototyping, and actual development.

It is also important to realize that this is just one possible approach. There are many other more formal approaches to defining, reviewing, and communicating your architecture. Some are discussed briefly at the end of this chapter.

Inputs, Outputs, and Design Steps

The inputs to your design can help you to formalize the requirements and constraints that your architecture must accommodate. Common inputs are use cases and usage scenarios, functional requirements, non-functional requirements (including quality attributes such as performance, security, reliability, and others), technological requirements, the target deployment environment, and other constraints.

During the design process, you will create a list of the architecturally significant use cases, the architecture issues that require special attention, and the candidate architecture solutions that satisfy the requirements and constraints defined in the design process. A common technique for refining the design over time, until it satisfies all of the requirements and adheres to all of the constraints, is an iterative technique consisting of the five major stages shown in Figure 1.

Ee658084.8fe266bb-9218-4277-aa54-1e765bc6c010(en-us,PandP.10).png

Figure 1

The iterative steps for core architecture design activities

The steps, described in more detail in the following sections, are:

  1. Identify Architecture Objectives. Clear objectives help you to focus on your architecture and on solving the right problems in your design. Precise objectives help you to determine when you have completed the current phase, and when you are ready to move to the next phase.
  2. Key Scenarios. Use key scenarios to focus your design on what matters most, and to evaluate your candidate architectures when they are ready.
  3. Application Overview. Identify your application type, deployment architecture, architecture styles, and technologies in order to connect your design to the real world in which the application will operate.
  4. Key Issues. Identify key issues based on quality attributes and crosscutting concerns. These are the areas where mistakes are most often made when designing an application.
  5. Candidate Solutions. Create an architecture spike or prototype that evolves and improves the solution and evaluate it against your key scenarios, issues, and deployment constraints before beginning the next iteration of your architecture.

This architectural process is meant to be an iterative and incremental approach. Your first candidate architecture will be a high-level design that you can test against key scenarios, requirements, known constraints, quality attributes, and the architecture frame. As you refine your candidate architecture, you will learn more details about the design and will be able to further expand key scenarios, your application overview, and your approach to issues.


Ee658084.note(en-us,PandP.10).gifNote:
When taking an iterative approach to architecture, it is often tempting to iterate on horizontal slices (layers) of the application rather than vertical slices that require you to think about functionality across layers that comprise a complete feature (use case) for users. If you fail to iterate vertically, you run the risk of implementing a great deal of functionality before your users can validate it.


You should not try to build your architecture in a single iteration. Each iteration should add more detail. Do not get lost in the details, but instead focus on the major steps and build a framework on which you can base your architecture and design. The following sections provide guidelines and information on each of the steps.

Identify Architecture Objectives

Architecture objectives are the goals and constraints that shape your architecture and design process, scope the exercise, and help you determine when you are finished. Consider the following key points as you identify your architecture objectives:

  • Identify your architecture goals at the start. The amount of time you spend in each phase of architecture and design will depend on these goals. For example, are you building a prototype, testing potential paths, or embarking on a long-running architectural process for a new application?
  • Identify who will consume your architecture. Determine if your design will be used by other architects, or made available to developers and testers, operations staff, and management. Consider the needs and experience of your audience to make your resulting design more accessible to them.
  • Identify your constraints. Understand your technology options and constraints, usage constraints, and deployment constraints. Understand your constraints at the start so that you do not waste time or encounter surprises later in your application development process.

Scope and Time

Based on the high-level goals for your architecture, you can scope the amount of time to spend on each of your design activities. For example, a prototype might only require a few days to design, while a complete and fully detailed architecture for a complex application could potentially take months to complete—and may involve architecture and design over many iterations. Use your understanding of the objectives to determine how much time and energy to spend on each step, to gain an understanding of what the outcome will look like, and to define clearly the purpose and priorities of your architecture. Possible purposes might include:

  • Creating a complete application design.
  • Building a prototype.
  • Identifying key technical risks.
  • Testing potential options.
  • Building shared models to gain an understanding of the system.

Each of these will result in a different emphasis on design, and a varying time commitment. For example, if you want to identify key risks in your authentication architecture, you will spend much of your time and energy identifying authentication scenarios, constraints on your authentication architecture, and possible authentication technology choices. However, if you are in the early stages of considering the overall architecture for an application, authentication will be only one of many other concerns for which you address and document solutions.

Some examples of architecture activities are building a prototype to get feedback on the order-processing UI for a Web application, testing different ways to map location data to search results, building a customer order-tracking application, and designing the authentication and authorization architecture for an application in order to perform a security review.

Key Scenarios

In the context of architecture and design, a use case is a description of a set of interactions between the system and one or more actors (either a user or another system). A scenario is a broader and more encompassing description of a user's interaction with the system, rather than a path through a use case. When thinking about the architecture of your system, the goal should be to identify several key scenarios that will help you to make decisions about your architecture. The goal is to achieve a balance between the user, business, and system goals (as shown in Figure 1 of Chapter 1 "What is Software Architecture?").

Key scenarios are those that are considered the most important scenarios for the success of your application. Key scenarios can be defined as any scenario that meets one or more of the following criteria:

  • It represents an issue—a significant unknown area or an area of significant risk.
  • It refers to an architecturally significant use case (described in the following section).
  • It represents the intersection of quality attributes with functionality.
  • It represents a tradeoff between quality attributes.

For example, your scenarios covering user authentication may be key scenarios because they are an intersection of a quality attribute (security) with important functionality (how a user logs into your system). Another example would be a scenario that centered on an unfamiliar or new technology.

Architecturally Significant Use Cases

Architecturally significant use cases have an impact on many aspects of your design. These use cases are especially important in shaping the success of your application. They are important for the acceptance of the deployed application, and they must exercise enough of the design to be useful in evaluating the architecture. Architecturally significant use cases are:

  • Business Critical. The use case has a high usage level or is particularly important to users or other stakeholders when compared to other features, or it implies high risk.
  • High Impact. The use case intersects with both functionality and quality attributes, or represents a crosscutting concern that has an end-to-end impact across the layer and tiers of your application. An example might be a Create, Read, Update, Delete (CRUD) operation that is security-sensitive.

After you have determined the architecturally significant use cases for your application, you can use them as a way to evaluate the success or failure of candidate architectures. If the candidate architecture addresses more use cases, or addresses existing use cases more effectively, it will help usually indicate that this candidate architecture is an improvement over the baseline architecture. For a definition of the term use case, see "What is a Use Case?" at http://searchsoftwarequality.techtarget.com/sDefinition/0,,sid92_gci334062,00.html.


A good use case will intersect the user view, the system view, and the business view of the architecture. Use these scenarios and use cases to test your design and determine where any issues may be. Consider the following when thinking about your use cases and scenarios:

  • Early in the project, reduce risk by creating a candidate architecture that supports architecturally significant end-to-end scenarios that exercise all layers of the architecture.
  • Using your architecture model as a guide, make changes to your architecture, design, and code to meet your scenarios, functional requirements, technological requirements, quality attributes, and constraints.
  • Create an architecture model based on what you know at the time, and define a list of questions that must be addressed in subsequent stories and iterations.
  • After you make sufficient significant changes to the architecture and design, consider creating a use case that reflects and exercises these changes.

Application Overview

Create an overview of what your application will look like when it is complete. This overview serves to make your architecture more tangible, connecting it to real-world constraints and decisions. An application overview consists of the following activities:

  1. Determine your application type. First, determine what type of application you are building. Is it a mobile application, a rich client, a rich Internet application, a service, a Web application, or some combination of these types? For more details of the common application archetypes, see Chapter 20 "Choosing an Application Type."
  2. Identify your deployment constraints. When you design your application architecture, you must take into account corporate policies and procedures, together with the infrastructure on which you plan to deploy your application. If the target environment is fixed or inflexible, your application design must reflect restrictions that exist in that environment. Your application design must also take into account Quality-of-Service (QoS) attributes such as security and reliability. Sometimes you must make design tradeoffs due to protocol restrictions and network topologies. By identifying the requirements and constraints that exist between the application architecture and infrastructure architecture early in the design process, you can choose an appropriate deployment topology and resolve conflicts between the application and the target infrastructure. For more information about deployment scenarios, see Chapter 19 "Physical Tiers and Deployment."
  3. Identify important architecture design styles. Determine which architecture styles you will be using in your design. An architecture style is a set of principles. You can think of it as a coarse-grained pattern that provides an abstract framework for a family of systems. Each style defines a set of rules that specify the kinds of components you can use to assemble a system, the kinds of relationships used in their assembly, constraints on the way they are assembled, and assumptions about the meaning of how you put them together. An architecture style improves partitioning and promotes design reuse by providing solutions to frequently recurring problems. Common architectural styles are Service Oriented Architecture (SOA), client/server, layered, message-bus, and domain-driven design. Applications will often use a combination of styles. For more information about the architectural styles in common use today, see Chapter 3 "Architectural Patterns and Styles."
  4. Determine relevant technologies. Finally, identify the relevant technology choices based on your application type and other constraints, and determine which technologies you will use in your design. Key factors to consider are the type of application you are developing, and your preferred options for application deployment topology and architectural styles. The choice of technologies will also be governed by organization policies, infrastructure limitations, resource skills, and so on. The following section describes some of the common Microsoft technologies for each type of application.

Relevant Technologies

When choosing the technologies you will use in your design, consider which will help you to support your chosen architectural styles, your chosen application type, and the key quality attributes for your application. For example, for the Microsoft platform, the following list will help you understand which presentation, implementation, and communication technologies are most suited to each type of application:

  • Mobile Applications. You can use presentation-layer technologies such as the .NET Compact Framework, ASP.NET for Mobile, and Silverlight for Mobile to develop applications for mobile devices.
  • Rich Client Applications. You can use combinations of Windows Presentation Foundation (WPF), Windows Forms, and XAML Browser Application (XBAP) presentation-layer technologies to develop applications with rich UIs that are deployed and run on the client.
  • Rich Internet Client Applications (RIA). You can use the Microsoft Silverlight™ browser plug-in, or Silverlight combined with AJAX, to deploy rich UI experiences within a Web browser.
  • Web Applications. You can use ASP.NET Web Forms, AJAX, Silverlight controls, ASP.NET MVC, and ASP.NET Dynamic data to create Web applications.
  • Service Applications. You can use Windows Communication Foundation (WCF) and ASP.NET Web services (ASMX) to create services that expose functionality to external systems and service consumers.

For more details about the technologies available for different types of applications, see the following topics in the appendices at the end of this guide:

Whiteboard Your Architecture

It is important that you are able to whiteboard your architecture. Whether you share your whiteboard on paper, slides, or through another format, the key is to show the major constraints and decisions in order to frame and start conversations. The value is actually twofold. If you cannot whiteboard the architecture then it suggests that it is not well understood. If you can provide a clear and concise whiteboard diagram, others will understand it and you can communicate details to them more easily.

Ee658084.f0974cb5-6fef-45e3-9826-e654f3697da2(en-us,PandP.10).png

Figure 2

Example of an architecture whiteboard showing a high-level design for a Web application indicating the protocols and authentication methods it will use.

Key Issues

Identify the issues in your application architecture to understand the areas where mistakes are most likely to be made. Potential issues include the appearance of new technologies, and critical business requirements. For example, "Can I swap from one third party service to another?," "Can I add support for a new client type?," "Can I quickly change my business rules relating to billing?," and "Can I migrate to a new technology for X?" While these factors are extremely generalized, they (and other areas of risk) generally map in implementation terms to quality attributes and crosscutting concerns.

Quality Attributes

Quality attributes are the overall features of your architecture that affect run-time behavior, system design, and user experience. The extent to which the application possesses a desired combination of quality attributes such as usability, performance, reliability, and security indicates the success of the design and the overall quality of the software application. When designing applications to meet any of these qualities, it is necessary to consider the impact on other requirements; you must analyze the tradeoffs between multiple quality attributes. The importance or priority of each quality attribute differs from system to system; for example, in a line-of-business (LOB) system, performance, scalability, security, and usability will be more important than interoperability. Interoperability is likely to be far more important in a shrink-wrap application than in a LOB application.

Quality attributes represent areas of concern that have the potential for application-wide impact across layers and tiers. Some attributes are related to the overall system design, while others are specific to run-time, design-time, or user-centric issues. Use the following list to help you organize your thinking about the quality attributes, and to understand which scenarios they are most likely to affect:

  • System qualities. The overall qualities of the system when considered as a whole; such as supportability and testability.
  • Run-time qualities. The qualities of the system directly expressed at run-time; such as availability, interoperability, manageability, performance, reliability, scalability, and security.
  • Design qualities. The qualities reflecting the design of the system; such as conceptual integrity, flexibility, maintainability, and reusability.
  • User qualities. The usability of the system.

For more information about ensuring that your design implements the appropriate quality attributes, see Chapter 16 "Quality Attributes."

Crosscutting Concerns

Crosscutting concerns are the features of your design that may apply across all layers, components, and tiers. These are also the areas in which high-impact design mistakes are most often made. Examples of crosscutting concerns are:

  • Authentication and Authorization. How you choose appropriate authentication and authorization strategies, flow identity across layers and tiers, and store user identities.
  • Caching. How you choose an appropriate caching technology, determine what data to cache, where to cache the data, and a suitable expiration policy.
  • Communication. How you choose appropriate protocols for communication across layers and tiers, design loose coupling across layers, perform asynchronous communication, and pass sensitive data.
  • Configuration Management. How you determine what information must be configurable, where and how to store configuration information, how to protect sensitive configuration information, and how to handle configuration information in a farm or cluster.
  • Exception Management. How you handle and log exceptions, and provide notification when required.
  • Logging and Instrumentation. How you determine which information to log, how to make the logging configurable, and determine what level of instrumentation is required.
  • Validation. How you determine where and how to perform validation; the techniques you choose for validating on length, range, format, and type; how you constrain and reject input invalid values; how you sanitize potentially malicious or dangerous input; and how you can define and reuse validation logic across your application's layers and tiers.

For more information about ensuring that your design correctly handles crosscutting concerns, see Chapter 17 "Crosscutting Concerns."

Designing for Issue Mitigation

By analyzing quality attributes and crosscutting concerns in relation to your design requirements, you can focus on specific areas of concern. For example, the quality attribute Security is obviously a vital factor in your design, and applies at many levels and areas of the architecture. The relevant crosscutting concerns for security provide guidance on specific areas where you should focus your attention. You can use the individual crosscutting categories to divide your application architecture for further analysis, and to help you identify application vulnerabilities. This approach leads to a design that optimizes security aspects. Questions you might consider when examining the crosscutting concerns for security are:

  • Auditing and Logging. Who did what and when? Is the application operating normally? Auditing refers to how your application records security-related events. Logging refers to how your application publishes information about its operation.
  • Authentication. Who are you? Authentication is the process where one entity definitively establishes the identity of another entity, typically with credentials such as a username and password.
  • Authorization. What can you do? Authorization refers to how your application controls access to resources and operations.
  • Configuration Management. What context does your application run under? Which databases does it connect to? How is your application administered? How are these settings protected? Configuration management refers to how your application handles these operations and issues.
  • Cryptography. How are you handling secrets (confidentiality)? How are you tamper-proofing your data or libraries (integrity)? How are seeding random values that must be cryptographically strong? Cryptography refers to how your application enforces confidentiality and integrity.
  • Exception Management. When a method call in your application fails, what does your application do? How much information does it reveal? Does it return friendly error messages to end users? Does it pass valuable exception information back to the calling code? Does it fail gracefully? Does it help administrators to perform root cause analysis of the fault? Exception management refers to how you handle exceptions within your application.
  • Input and Data Validation. How do you know that the input your application receives is valid and safe? Does it constrain input through entry points and encode output through exit points. Can it trust data sources such as databases and file shares? Input validation refers to how your application filters, scrubs, or rejects input before additional processing.
  • Sensitive data. How does your application handle sensitive data? Does it protect confidential user and application data? Sensitive data refers to how your application handles any data that must be protected either in memory, over the network, or in persistent stores.
  • Session Management. How does your application handle and protect user sessions? A session refers to a set of related interactions between a user and your application.

You can use these questions and answers to make key security design decisions for your application, and document these are part of your architecture. For example, Figure 3 shows the security issues identified in a typical Web application architecture.

Ee658084.ce49e95f-cfd5-4ece-87a9-beff06f0a39e(en-us,PandP.10).png

Figure 3

Security issues identified in a typical Web application architecture.

Candidate Solutions

After you define the key issues, you can create your initial baseline architecture and then start to fill in the details to produce a candidate architecture. Along the way, you may use architectural spikes to explore specific areas of the design or to validate new concepts. You then validate your new candidate architecture against the key scenarios and requirements you have defined, before iteratively following the cycle and improving the design.


Ee658084.note(en-us,PandP.10).gifNote:
It is important, especially if your design and development is following an agile process, that your iteration encompass both architecture and development activities. This avoids the big design up front approach.

Baseline and Candidate Architectures

A baseline architecture describes the existing system —it is how your system looks today. If this is a new architecture, your initial baseline is the first high-level architectural design from which candidate architectures will be built. A candidate architecture includes the application type, the deployment architecture, the architectural style, technology choices, quality attributes, and crosscutting concerns.

As you evolve the design, ensure that at each stage you understand the key risks and adapt your design to reduce them, optimize for effective and efficient communication of design information, and build your architecture with flexibility and refactoring in mind. You may need to modify your architecture a number of times, through several iterations, candidate architectures, and by using multiple architectural spikes. If the candidate architecture is an improvement, it can become the baseline from which new candidate architectures can be created and tested.

This iterative and incremental approach allows you to get the big risks out of the way first, iteratively render your architecture, and use architectural tests to prove that each new baseline is an improvement over the last. Consider the following questions to help you test a new candidate architecture that results from an architectural spike:

  • Does this architecture succeed without introducing any new risks?
  • Does this architecture mitigate more known risks than the previous iteration?
  • Does this architecture meet additional requirements?
  • Does this architecture enable architecturally significant use cases?
  • Does this architecture address quality attribute concerns?
  • Does this architecture address additional crosscutting concerns?

Architectural Spikes

An architectural spike is a test implementation of a small part of the application's overall design or architecture. The purpose is to analyze a technical aspect of a specific piece of the solution in order to validate technical assumptions, choose between potential designs and implementation strategies, or sometimes to estimate implementation timescales.

Architectural spikes are often used as part of agile or extreme programming development approaches but can be a very effective way to refine and evolve a solution's design regardless of the development approach adopted. By focusing on key parts of the solution's overall design, architectural spikes can be used to resolve important technical challenges and to reduce overall risk and uncertainty in the solution's design.

What to Do Next

After you complete the architecture-modeling activity, you can begin to refine the design, plan tests, and communicate the design to others. Keep in mind the following guidelines:

  • If you capture your candidate architectures and architectural test cases in a document, keep the document lightweight so that you can easily update it. Such a document may include details of your objectives, application type, deployment topology, key scenarios and requirements, technologies, quality attributes, and tests.
  • Use the quality attributes to help shape your design and implementation. For example, developers should be aware of anti-patterns related to the identified architectural risks, and use the appropriate proven patterns to help address the issues.
  • Communicate the information you capture to relevant team members and other stakeholders. This may include your application development team, your test team, and your network and system administrators.

Reviewing Your Architecture

Reviewing the architecture for your application is a critically important task in order to reduce the cost of mistakes and to find and fix architectural problems as early as possible. Architecture review is a proven, cost-effective way of reducing project costs and the chances of project failure. Review your architecture frequently: at major project milestones, and in response to other significant architectural changes. Build your architecture with common review questions in mind, both to improve your architecture and to reduce the time required for each review.

The main goal of an architecture review is to determine the feasibility of your baseline and candidate architectures, and verify that the architecture correctly links the functional requirements and the quality attributes with the proposed technical solution. Additionally, it helps you to identify issues and recognize areas for improvement.

Scenario-Based Evaluations

Scenario-based evaluations are a powerful method for reviewing an architecture design. In a scenario-based evaluation, the focus is on the scenarios that are most important from the business perspective, and which have the greatest impact on the architecture. Consider using one of the following common review methodologies:

  • Software Architecture Analysis Method (SAAM). SAAM was originally designed for assessing modifiability, but later was extended for reviewing architecture with respect to quality attributes such as modifiability, portability, extensibility, integratability, and functional coverage.
  • Architecture Tradeoff Analysis Method (ATAM). ATAM is a refined and improved version of SAAM that helps you review architectural decisions with respect to the quality attributes requirements, and how well they satisfy particular quality goals.
  • Active Design Review (ADR). ADR is best suited for incomplete or in-progress architectures. The main difference is that the review is more focused on a set of issues or individual sections of the architecture at a time, rather than performing a general review.
  • Active Reviews of Intermediate Designs (ARID). ARID combines the ADR aspect of reviewing in-progress architecture with a focus on a set of issues, and the ATAM and SAAM approach of scenario-based review focused on quality attributes.
  • Cost Benefit Analysis Method (CBAM). This CBAM focuses on analyzing the costs, benefits, and schedule implications of architectural decisions.
  • Architecture Level Modifiability Analysis (ALMA). ALMA evaluates the modifiability of architecture for business information systems (BIS).
  • Family Architecture Assessment Method (FAAM). FAAM evaluates information system family architectures for interoperability and extensibility.

For information about techniques for analyzing and reviewing architecture designs, see "Evaluating Software Architectures: Methods and Case Studies (SEI Series in Software Engineering)" by Paul Clements, Rick Kazman, and Mark Klein (Addison-Wesley Professional , ISBN-10: 020170482X, ISBN-13: 978-0201704822)

Representing and Communicating Your Architecture Design

Communicating your design is critical for architecture reviews, as well as to ensure it is implemented correctly. You must communicate your architectural design to all the stakeholders including the development team, system administrators and operators, business owners, and other interested parties.

One way to think of an architectural view is as a map of the important decisions. The map is not the terrain; instead, it is an abstraction that helps you to share and communicate the architecture. There are several well-known methods for describing architecture to others, including the following:

  • 4+1. This approach uses five views of the complete architecture. Four of the views describe the architecture from different approaches: the logical view (such as the object model), the process view (such as concurrency and synchronization aspects), the physical view (the map of the software layers and functions onto the distributed hardware infrastructure), and the development view. A fifth view shows the scenarios and use cases for the software. For more information, see "Architectural Blueprints—The “4+1” View Model of Software Architecture" at http://www.cs.ubc.ca/~gregor/teaching/papers/4+1view-architecture.pdf.
  • Agile Modeling. This approach follows the concept that content is more important than representation. This ensures that the models created are simple and easy to understand, sufficiently accurate, and consistent. The simplicity of the document ensures that there is active stakeholder participation in the modeling of the artifact. For more information, see "Agile Modeling: Effective Practices for eXtreme Programming and the Unified Process" by Scott Ambler (J. Wiley, ISBN-10: 0471202827, ISBN-13: 978-0471202820).
  • IEEE 1471. IEEE 1471 is the short name for a standard formally known as ANSI/IEEE 1471-2000, which enhance the content of an architectural description; in particular giving specific meaning to context, views, and viewpoints. For more information, see “Recommended Practice for Architecture Description of Software-Intensive Systems” at http://standards.ieee.org/reading/ieee/std_public/description/se/1471-2000_desc.html.
  • Unified Modeling Language (UML). This approach represents three views of a system model. The functional requirements view (functional requirements of the system from the point of view of the user, including use cases); the static structural view (objects, attributes, relationships, and operations including class diagrams); and the dynamic behavior view (collaboration among objects and changes to the internal state of objects, including includes sequence, activity, and state diagrams). For more information, see "UML Distilled: A Brief Guide to the Standard Object Modeling Language" by Martin Fowler (Addison-Wesley Professional, ISBN-10: 0321193687, ISBN-13: 978-0321193681)

Additional Resources

Ambler, Scott. Agile Modeling: Effective Practices for eXtreme Programming and the Unified Process. J. Wiley, 2002.

Clements, Paul, Rick Kazman, and Mark Klein. Evaluating Software Architectures: Methods and Case Studies (SEI Series in Software Engineering). Addison-Wesley Professional, 2001.

Fowler, Martin. UML Distilled: A Brief Guide to the Standard Object Modeling Language. Addison-Wesley Professional, 2003.


Show:
© 2015 Microsoft