Chapter 10: Component Guidelines
For more details of the topics covered in this guide, see Contents of the Guide.
- General Guidelines for Component Design
- Layered Component Distribution
- Presentation Layer Components
- Services Layer Components
- Business Layer Components
- Data Layer Components
- Crosscutting Components
- Relevant Design Patterns
- patterns & practices Offerings
- Additional Resources
Components provide a way to isolate specific sets of functionality within units that you can distribute and install separately from other functionality. This chapter contains some general guidelines for creating components, and describes the types of components commonly found in each layer of applications that are designed using the layered approach described elsewhere in this guide. However, the techniques for building components are generally applicable irrespective of the application structure.
General Guidelines for Component Design
When designing components for use in your applications, consider the following general guidelines:
Apply the SOLID design principles to the classes within your component. The SOLID principles are, briefly, the following:
- Single responsibility principle. A class should have only responsibility.
- Open/closed principle. Classes should be extensible without requiring modification.
- Liskov substitution principle. Subtypes must be substitutable for their base types
- Interface segregation principle. Class interfaces should be client specific and fine grained. Classes should expose separate interfaces for different clients where the interface requirements differ.
- Dependency inversion principle. Dependencies between classes should be replaced by abstractions to allow top down design without requiring design of low level modules first. Abstractions should not depend upon details—details should depend upon abstractions.
- Design components to be highly cohesive. Do not overload components by adding unrelated or mixed functionality. For example, always avoid mixing data access logic and business logic within your business components. Where functionality is cohesive, you can create assemblies that contain more than one component and install components in the appropriate layers of your application—even when the layers are physically separated.
- A component should not rely on internal details of other components. Each component or object should call a method of another object or component, and that method should have information about how to process the request and, if appropriate, how to route it to appropriate subcomponents or other components. This helps to create an application that is more maintainable and adaptable.
- Understand how components will communicate with each other. This requires an understanding of the deployment scenarios your application must support. You must determine if communication across physical boundaries or process boundaries should be supported, or if all components will run within the same process.
- Keep crosscutting code abstracted from the application-specific logic. Crosscutting code refers to code related to security, communications, or operational management such as logging and instrumentation. Mixing the code that implements these functions with the component logic can lead to a design that is difficult to extend and maintain.
- Apply the key principles of the component-based architectural style. These principles are that components should be reusable, replaceable, extensible, encapsulated, independent, and not context specific. For information about the component-based architectural style, see Chapter 3 "Architectural Patterns and Styles".
Layered Component Distribution
Each layer of an application will contain a series of components that implement the functionality for that layer. These components should be cohesive and loosely coupled to simplify reuse and maintenance. Figure 1 shows the types of components commonly found in each layer.
The following sections describe the components shown in Figure 1.
Presentation Layer Components
Presentation layer components implement the functionality required to allow users to interact with the application. The following types of components are commonly found in the presentation layer:
- User Interface Components. The specific user interface for the application is encapsulated into user interface (UI) components. These are the application's visual elements used to display information to the user and accept user input. UI components designed to work in a Separated Presentation pattern implementation are sometimes called Views. In most cases, their specific role is to present the user with an interface that represents the application's underlying data and logic in the most appropriate way, and to interpret user input gestures and forward them to presentation logic components that define how the input affects the underlying data and application state. In some cases, the user interface components may contain logic that is specific to the user interface implementation. In general, however, they should contain as little application logic as possible as this can affect maintainability and reuse, and make them hard to unit test.
Presentation Logic Components. Presentation logic is the application code that defines the logical behavior and structure of the application in a way that is independent of any specific user interface implementation. Presentation logic components are primarily concerned with implementing the application's use cases (or user stories), and orchestrating the user's interactions with the underlying logic and state of the application in a UI independent way. They are also responsible for organizing data from the business layer in a consumable format for the UI components; for example, they may aggregate data from multiple sources, and transform data for display more easily. Presentation logic components can be further subdivided into the following two categories:
- Presenter, Controller, Presentation Model, and ViewModel Components. Used when implementing the Separated Presentation pattern, these kinds of components often encapsulate presentation logic within the presentation layer. To maximize reuse opportunities and testability, these components are not specific to any specific UI classes, elements, or controls.
- Presentation Entity Components. These components encapsulate business logic and data and make it easy for the UI and presentation logic components in the presentation layer to consume; for example, by performing data type conversion or by aggregating data from several sources. In some cases, these are the business entities from the business layer consumed directly by the presentation tier. In other cases, they may represent a subset of the business entity components and be specifically designed to support the presentation layer of the application. Presentation entities help to ensure data consistency and validity in the presentation layer. In some separated presentation patterns these components are sometimes referred to as models.
For more information about designing your presentation layer, see Chapter 6 "Presentation Layer Guidelines." For more information about designing presentation components, see Chapter 11 "Designing Presentation Components."
Services Layer Components
Your application may expose a service layer to interact with clients or other systems using. Services layer components provide other clients and applications with a way to access business logic in the application, and make use of the functionality of the application by passing messages to and from it over a communication channel. The following types of components are commonly found in the services layer:
- Service Interfaces. Services expose a service interface to which all inbound messages are sent. The definition of the set of messages that must be exchanged with a service in order for the service to perform a specific business task constitutes a contract. You can think of a service interface as a façade that exposes the business logic implemented in the application (typically, logic in the business layer) to potential consumers.
- Message Types. When exchanging data across the service layer, data structures are wrapped by message structures that support different types of operations. For example, you might have a Command message, a Document message, or another type of message. These message types are the message contracts for communication between service consumers and providers. The services layer will usually also expose data types and contracts that define the data types used in messages, and isolate the internal data types from those contained in the message type. This avoids exposure of internal data types to external consumers, which would cause issues in terms of versioning the interface.
For more information about communication and messaging, see Chapter 18 "Communication and Messaging."
Business Layer Components
Business layer components implement the core functionality of the system, and encapsulate the relevant business logic. The following types of components are commonly found in the business layer:
- Application Façade. This optional component typically provides a simplified interface to the business logic components, often by combining multiple business operations into a single operation that makes it easier to use the business logic, and reduces dependencies because external callers do not need to know details of the business components and relationships between them.
Business Logic Components. Business logic is defined as any application logic that is concerned with the retrieval, processing, transformation, and management of application data; application of business rules and policies; and ensuring data consistency and validity. To maximize reuse opportunities, business logic components should not contain any behavior or application logic that is specific to a use case or user story. Business logic components can be further subdivided into the following two categories:
- Business Workflow Components. After the UI components collect input from the user and pass it to the business layer, the application can use this input to perform a business process. Many business processes involve multiple steps that must be performed in the correct order, and may interact with each other through an orchestration. Business workflow components define and coordinate long-running, multistep business processes, and can be implemented using business process management tools. Business workflow components work with business process components that instantiate and perform operations on workflow components. For more information on business workflow components, see Chapter 14 "Designing Workflow Components."
- Business Entity Components. Business entities, or—more generally—business objects, encapsulate the business logic and data necessary to represent real world elements, such as Customers or Orders, within your application. They store data values and expose them through properties; contain and manage business data used by the application; and provide stateful programmatic access to the business data and related functionality. Business entities also validate the data contained within the entity and encapsulate business logic to ensure consistency and to implement business rules and behavior. For more information about business entity components, see Chapter 13 "Designing Business Entities."
There are many cases where business entities must be accessible to components and services in both the business layer and the data layer. For example, business entities can be mapped to the data source and accessed by business components. If the layers are located on the same physical tier, the business entities can be shared directly through references. However, you should still separate business logic from data access logic. You can achieve this by moving business entities into a separate assembly that can be shared by both the business services and data services assemblies. This is similar to using a dependency inversion pattern, where business entities are decoupled from the business and data layer so that both business and data layers are dependent on business entities as a shared contract.
For more information about designing your business layer, see Chapter 7 "Business Layer Guidelines." For more information about designing business components, see Chapter 12 "Designing Business Components." For more information about designing business entity components, see Chapter 13 "Designing Business Entities." For more information about designing workflow components, see Chapter 14 "Designing Workflow Components."
Data Layer Components
Data layer components provide access to data that is hosted within the boundaries of the system, and to data exposed by other networked systems. The following types of components are commonly found in the data layer:
- Data Access Components. These components abstract the logic required to access the underlying data stores. Most data access tasks require common logic that can be extracted and implemented in separate reusable helper components or a suitable support framework. This can reduce the complexity of the data access components and centralize the logic, which simplifies maintenance. Other tasks that are common across data layer components, and not specific to any set of components, may be implemented as separate utility components. Helper and utility components are often encapsulated in a library or framework so that they can easily be reused in other applications.
- Service Agents. When a business component must use functionality provided by an external service, you might need to implement code to manage the semantics of communicating with that particular service. Service agents isolate the idiosyncrasies of calling diverse services from your application, and can provide additional services such as caching, offline support, and basic mapping between the format of the data exposed by the service and the format your application requires.
Many tasks carried out by the code of an application are required in more than one layer. Crosscutting components implement specific types of functionality that can be accessed from components in any layer. The following are common types of crosscutting components:
- Components for implementing security. These may include components that perform authentication, authorization, and validation.
- Components for implementing operational management tasks. These may include components that implement exception handling policies, logging, performance counters, configuration, and tracing.
- Components for implementing communication. These may include components that communicate with other services and applications.
For more information about managing crosscutting concerns, see Chapter 17 "Crosscutting Concerns."
Relevant Design Patterns
Key patterns for components are organized by categories as detailed in the following table. Consider using these patterns when making design decisions for each category.
Application Façade. Centralize and aggregate behavior to provide a uniform service layer.
Chain of Responsibility. Avoid coupling the sender of a request to its receiver by allowing more than one object to handle the request.
Command. Encapsulate request processing in a separate command object with a common execution interface.
Domain Model. A set of business objects that represents the entities in a domain and the relationships between them.
Entity Translator. An object that transforms message data types to business types for requests, and reverses the transformation for responses.
Table Module. A single component that handles the business logic for all rows in a database table or view.
Entity Translator. An object that transforms message data types into business types for requests, and reverses the transformation for responses.
Application Controller. Implement a centralized point for handling screen navigation and the flow of an application.
Model-View-Controller. Separate the UI code into three separate units: Model (data), View (interface), and Controller (processing logic), with a focus on the View. Two variations on this pattern include Passive View and Supervising Presenter, which define how the View interacts with the Model.
Model-View-ViewModel. A variation on the presentation model pattern that uses the Command pattern to communicate from the View to the ViewModel.
Model-View-Presenter. Separate request processing into three separate roles, with the View being responsible for handling user input and passing control to a Presenter object.
Passive View. Reduce the view to the absolute minimum by allowing the controller to process user input and maintain the responsibility for updating the view.
Presentation Model. Move all view logic and state out of the view, and render the view through data binding and templates.
Supervising Presenter (or Supervising Controller). A variation of the MVC pattern in which the controller handles complex logic, in particular coordinating between views, but the view is responsible for simple view-specific logic.
Façade. Implement a unified interface to a set of operations in order to provide a simplified interface and reduce coupling between systems.
Remote Façade. Create a high level unified interface to a set of operations or processes in a remote subsystem by providing a course-grained interface over fine-grained operations in order to make that subsystem easier to use, and to minimize calls across the network.
Service Interface. A programmatic interface that other systems can use to interact with the service.
Data-Driven Workflow. A workflow that contains tasks whose sequence is determined by the values of data in the workflow or the system.
Human Workflow. A workflow that involves tasks performed manually by humans.
Sequential Workflow. A workflow that contains tasks that follow a sequence, where one task is initiated after completion of the preceding task.
State-Driven Workflow. A workflow that contains tasks whose sequence is determined by the state of the system.
For more information on the Façade pattern, see Chapter 4, "Structural Patterns” in Gamma, Erich, Richard Helm, Ralph Johnson, and John Vlissides. Design Patterns: Elements of Reusable Object-Oriented Software. Addison Wesley Professional, 1995.
For more information on the Chain of Responsibility pattern, see “Patterns in Practice” at http://msdn.microsoft.com/en-us/magazine/cc546578.aspx.
For more information on the Command pattern, see 5, "Behavioral Patterns" in Gamma, Erich, Richard Helm, Ralph Johnson, and John Vlissides. Design Patterns: Elements of Reusable Object-Oriented Software. Addison Wesley Professional, 1995.
For more information on the Entity Translator pattern, see "Useful Patterns for Services" at http://msdn.microsoft.com/en-us/library/cc304800.aspx.
For more information on the Data-Driven Workflow, Human Workflow, Sequential Workflow, and State-Driven Workflow, see "Windows Workflow Foundation Overview" at http://msdn.microsoft.com/en-us/library/ms734631.aspx and "Workflow Patterns" at http://www.workflowpatterns.com/.
For more information on the Application Controller and Model-View-Controller (MVC) patterns, see Fowler, Martin. Patterns of Enterprise Application Architecture. Addison-Wesley, 2002. Or at http://martinfowler.com/eaaCatalog/.
For more information on the Supervising Presenter and Presentation Model patterns, see "Patterns in the Composite Application Library" at http://msdn.microsoft.com/en-us/library/dd458924.aspx.
For more information on the Remote Façade pattern, see "P of EAA: Remote Façade" at http://martinfowler.com/eaaCatalog/remoteFacade.html.
patterns & practices Offerings
For more information on relevant offerings available from the Microsoft patterns & practices group, see the following resources:
- "Composite Client Application Guidance" at http://msdn.microsoft.com/en-us/library/cc707819.aspx.
- "Enterprise Library" at http://msdn.microsoft.com/en-us/library/cc467894.aspx.
- "Smart Client Software Factory" at http://msdn.microsoft.com/en-us/library/aa480482.aspx.
- "Unity" (dependency injection mechanism) at http://msdn.microsoft.com/en-us/library/dd203101.aspx.
- "Web Client Software Factory" at http://msdn.microsoft.com/en-us/library/bb264518.aspx.
For more information, see the following:
- "Integration Patterns" at http://msdn.microsoft.com/en-us/library/ms978729.aspx.
- Martin, Robert C. and Micah Martin. Agile Principles, Patterns, and Practices in C#. Prentice Hall, 2006.
- "User Interface Control Guidelines" at http://msdn.microsoft.com/en-us/library/bb158625.aspx.