Thursday, January 17, 2008

An Early Glimpse of Future Composite Smart Client Guidance

This week the Patterns & Practices team invited a small group of members from the composite application development community to discuss ideas surrounding composite development using Windows Presentation Foundation, and to solicit feedback on the team’s latest design ideas and planned direction for the next release of composite guidance assets for the .Net community.


Glenn Block (left) and Blaine Wastell (right)

One of the first topics of the meeting included a discussion of new user interface design approaches enabled through the power of Windows Presentation Foundation, demonstrations of how some companies are currently utilizing these abilities, and the solicitation of information on future design plans from the attendees. This was in part to introduce the audience to the notion of what is being referred to as “Differentiated UI”, but was primarily a continuation of advanced WPF design research the team has been conducting over the past few weeks to ensure that the architecture choices made for any new composite guidance assets would not be a road-block for how WPF applications may be developed going forward.

The next major topic surrounded the existing features of the Composite UI Application Block and Smart Client Software Factory. Glenn, Blaine, and Francis shared some of the feedback their team has received on the existing composite guidance, and attendees were asked to list those features they felt should be carried forward, those that should be removed, and features that should be added. Attendees were then broken up into teams to discuss some of the technical challenges faced in current composite design in order to enumerate issues the team should focus on going forward.




The results of the existing CAB/SCSF feature survey can be seen in the above pictures of Glenn Block (left) and Brad Abrams (right).


Following this discussion, Glenn and his team presented a high level overview of the general direction being considered for their new guidance surrounding WPF composite development, and presented three spikes demonstrating the new ideas for module loading, managing Workspaces, and brokering events.

The current direction of the team surrounds the simplification of the existing architecture to make composite development more approachable by the masses. While still in a somewhat malleable state, some of the goals include minimizing the use of dependency injection, separating the former responsibilities of the CAB work item (i.e. the former management of smart parts, work items, event publications and subscriptions, etc.), improving component extensibility, and enabling features to be more easily replaced and possibly used independently.

Some of the notable changes being proposed include a new Dependency Injection façade for enabling other containers to be exchanged for Object Builder, the proposal of a Scope type which would provide the contextual scoping boundary association previously provided by the work item, and a new delegate-based event notification system where publications and subscriptions are associated through the use of registered interfaces.

The meeting also featured an overview of Acropolis by its chief Project Manager and Architect David Hill, and included lots of interesting conversations sprinkled throughout including such topics as Dependency Injection techniques, XAML debugging challenges, Model-View-Presenter and Presentation Model recommendations, whether the Model-View-View-Model pattern is really a rebranded Presentation Model pattern, and many other geeky goodies.

Overall, the meeting was very informative and demonstrated the Pattern & Practices team to be sincerely interested in the needs and desires of the greater .Net development community. Thanks Glenn, Blaine, Francis, and all the guest presenters that took this time to help ensure your group continues its track record of providing great guidance and assets to the .Net community.

Thursday, January 03, 2008

The Art of Separation of Concerns



Introduction

In software engineering, Separation of Concerns refers to the establishment of logical boundaries to define and delineate purpose. This improves the ability to manage and maintain systems by providing order and elegance to the form and function of system design.

The goal of this article is to promote the understanding of Separation of Concerns and to establish a set of foundational concepts useful to developers and architects toward its application.


Defining Separation of Concerns

Separation of Concerns is both principle and process. The principle of Separation of Concerns might be stated as the premise that things should be no more and no less than what they should be. That is to say, things should contain the essential attributes and behaviors inherent to their nature, but should be void of attributes and behaviors not inherent to their nature. The process of Separation of Concerns is comprised of techniques and constructs for constraining concerns within boundaries. Boundaries are often established through the use of methods, objects, components, and services to define core behavior within an application; projects, solutions, and folder hierarchies for source organization; application layers and tiers for processing organization; and versioned libraries and installers for product release organization.

Separation of Concerns is not merely the division of systems into multiple parts, but rather the establishing of boundaries based on essence. The distinction here is that unguided division leads to chaos, while guided division leads to order. Separation of Concerns involves both division and cohesion. The goal of Separation of Concerns is the establishment of boundaries which contain inherent properties and processes, but are void of non-inherent properties and processes. Arbitrary divisions, such as the separation of processes based solely on number of lines of code, or excessive division, such as separating a task into the smallest possible steps without tangible benefits or consideration of the task as a whole, may actually be detrimental to the maintainability of a system. As Albert Einstein stated, "Make everything as simple as possible, but not simpler."

At its essence, Separation of Concerns is about order. The overall goal of Separation of Concerns is to establish a well organized system where each part fulfills a meaningful and intuitive role, while maximizing its ability to adapt to change. The achievement of separation of concerns is a goal guided more by principle than rules. Because of this, Separation of Concerns might be considered as much an art as it is a science.


The Value of Separation


Applying the principle of Separation of Concerns can increase the stability, maintainability, extensibility, reusability, adoption, and even the logical and aesthetic design and flow of a system. Many of these benefits also play a supporting role in the accomplishment of one another. For instance, strategies which facilitate the reusability of components within a system, such as ensuring singularity of purpose and decoupling, can have a correlation to the system’s maintainability. The maintainability of a system often has a direct correlation to its stability since process failure is often the result of fragile, overly complex, and convoluted designs. The logical and aesthetic design and flow of a system has a correlation to the system’s maintainability and adoption through its promotion of understandable and harmonious processes. The system’s maintainability and aesthetic design has a correlation to the facilitation and understanding of its extensibility which reciprocates in its contributions back to the system’s maintainability and stability. Though not all of these benefits may be specific goals of every endeavor, each can prove instrumental in the achievement of the overall goal of manageability.

When applied to development organizations, well conceived separation of concerns can result in more agile development by minimizing the coordination necessary between the teams and maximizing the potential of each team’s ability to deliver features pertinent to their center of competency. This is particularly true of groups responsible for common concerns such as overall infrastructure, service development, and centralized user interface needs due to their increased potential for domain specific encroachment.

The principle of Separation of Concerns also greatly enhances problem resolution in enterprise wide systems. When proper delineation of responsibilities is allocated across an enterprise, it becomes easier to identify a problem’s origin.

The principle of Separation of Concerns extends into almost every facet of software development. It is the foundational principle for good architecture and system management.


Terms of Separation

Discussions pertaining to Separation of Concerns require an understanding of key concepts and definitions. The following is a list of some of the terms related to the subject of Separation of Concerns.

Concern – An inherent or imposed characteristic. Concerns are the attributes and behaviors by which a thing may be defined.

Boundary – A physical or conceptual delineation around one or more related concerns. A boundary may be a readily perceivable construct which outlines the applicable scope of a set of concerns, as is the case with methods or component libraries, or it may merely be an agreed upon organization, such as the grouping of members based on scope accessibility. Motivations for the use of boundaries include defining entities according to their base ontological essence, aiding in the elimination of redundancy, delineating roles and relationships, correlating related concerns, and improving portability and reuse.

Abstraction – the representation of an entity in non-concrete terms. As within the study of philosophy, the process of abstraction within computer science allows one to deal with ideas and entities without being encumbered by unnecessary details. Abstraction is generally accomplished either through the use of language specific constructs, such as abstract classes and interfaces, or with conceptual layers of functionality which expose only the necessary elements of a lower level set of components. The goal of abstraction is generally to allow one or both sides of a relationship to vary independently from the other. For example, if a presentation layer accesses a database through a domain layer serving as the layer of abstraction, the database and method of access can be modified without affecting the presentation layer.

Decoupling – the process of disconnecting an association or awareness of two components or systems.

Loose Coupling – the state of possessing an association or awareness from one component or system to another by means of abstraction. Loose coupling provides the ability for one component to be associated with another while allowing independent variation. For example, if component A interacts with component B through an abstraction of component B, the implementation of component B can be changed without affecting component A.

Tight Coupling – the state of possessing a direct association or awareness between one component or system and another which affects the ability for the associating component or system to vary independently.

One-way decoupling – the process of disconnecting an association between two components or systems allowing only one to vary independently from the other. An example of one-way decoupling would be to use the Observer Pattern to enable a domain model object to raise event notifications to an external observer, with the external observer calling methods on the domain model once notification is received. In this scenario, the domain model is decoupled from the observer receiving the message, while the observer is coupled to the domain model.

Two-way decoupling – the process of disconnecting an association between two components or systems allowing both to vary independently. An example of two-way loose coupling would be two components which interact with one another through interfaces specific to each component. An example of complete two-way decoupling would be the use of a brokering mechanism which maintains the relationship between two or more components which exchange messages. In this case the components are coupled with an infrastructure level component which allows them to remain decoupled from other domain level components.

Monolithic – the attribute of lacking clear or any component separation. Monolithic applications often result in large, unwieldy, rigid systems and contain functionality which cannot easily be shared with other applications outside of the use of the entire application.

Modular – the attribute of having clear component separation. Modular applications are comprised of multiple components or sub-systems which work together to achieve the overall system goals.

Add-In (or Plug-in) – a component which adds new capabilities to systems designed for the consumption of dynamic or configurable modules. Add-Ins provide the ability for systems to delegate concerns using forms of loose-coupling.

Provider – a component which satisfies a contract for a specific set of abstract functionality. Providers are specialized Add-Ins which accomplish a specific set of concerns within an application.

Extension – a component which enhances the existing capabilities of a system designed to yield control or expose data and functionality at predetermined points within its internal processes. An extension allows for the delegation of concerns not directly inherent to, or practical for the core system’s processes. Extensions often take the form of a hosted add-in, but include any process designed specifically to add new capabilities to an existing system.

Layered – the attribute of having clear separation between groups of entities with common processing goals within a system. Examples of layered separation would be the division between components concerned with the visual presentation of an application and components concerned with the data access of the application.

Inversion of Control – the process of moving a concern outside of an established boundary. Inversion of Control externalizes concerns formerly contained within a component and may be used for tasks such as minimizing non-essential concerns, or decoupling components from direct participation in specific abstraction strategies. An example of Inversion of Control would be externalizing the main control flow of a component.

Dependency Injection – the process of separating the concerns of acquiring dependencies from an entity. Dependency Injection is a specific instance of Inversion of Control where the process being inverted is the acquisition of external dependencies. An example of Dependency Injection would be a system which initializes references to a logging service for each instantiated component within the system. This would allow the system to vary the implementation assigned to all, or a subset of components within the system without the need of modifying the consuming components.

Dependency Direction – the route of association between one component or system to another. The dependency direction follows the path drawn from a consuming component or system to a consumed dependency. For example, if component A calls a method on component B then the dependency direction would be from A to B.

Refactoring – the process of changing a system such that its external interfaces and functionality remain the same, but the internal organization and processes are made more efficient and maintainable.


Horizontal Separation

Horizontal Separation of Concerns refers to the process of dividing an application into logical layers of functionally that fulfill the same role within the application.

One common division for graphical user interface applications is the separation of processes into the layers of Presentation, Business, and Resource Access. These categories encompass the main types of concerns for most application needs, and represent an organization of concerns which minimizes the level of dependencies within an application. Figure 1 depicts a typical three-layered application:




Figure 1



The Presentation Layer encompasses processes and components related to an application’s user interface. This includes components which define the visual display of an application, and may include advanced design concepts such as controllers, presenters, or a presentation model. The primary goal of the Presentation Layer is to encapsulate all user interface concerns in order to allow the application domain to be varied independently. The Presentation Layer should include all components and processes exclusively related to the visual display needs of an application, and should exclude all other components and processes. This allows other layers within the application to vary independently from its display concerns.

The Business Layer encompasses processes and components related to the application domain. This includes components which define the object model, govern business logic, and control the workflow of the system. The business layer may be represented through specialized components which represent the workflow, business processes, and entities used within the application, or through a traditional object-oriented domain model which encapsulates both data and behavior. The primary goal of the Business Layer is to encapsulate the core business concerns of an application exclusive of how data and behavior is exposed, or how data is specifically obtained. The Business Layer should include all components and processes exclusively related to the business domain of the application, and should exclude all other components and processes.

The Resource Access Layer encompasses processes and components related to the access of external information. This includes components which interface with a local data store or remote service. The goal of the Resource Access Layer is to provide a layer of abstraction around the details specific to data access. This includes tasks such as the establishing of database and service connections, maintaining knowledge about database schemas or stored procedures, knowledge about service protocols, and the marshalling of data between service entities and business entities. The Resource Access Layer should include all components and processes exclusively related to accessing data external to the system, and should exclude all other components and processes.

Another common division used by Service Oriented Applications is the division of the application into the layers of Service Interface, Business, and Resource Access as depicted in Figure 2:




Figure 2



In this division, the Business and Resource Access layers serve the same purposes as previously discussed, with the service exposure concerns encapsulated into a Service Interface Layer. This layer encompasses service interface concerns such as the exposure of business processes through various protocols and the management of service specific contracts and data types. The primary goal of the Service Interface Layer is to encapsulate all service interface concerns in order to allow the application domain to be varied independently. The Service Interface Layer should include all components and processes exclusively related to the exposure of the application as a service, and should exclude all other components and processes.

By grouping processing concerns based on their role within the application, a number of benefits are gained which improve the overall system manageability. These benefits include ease of maintenance through consistent architecture and isolation of process, increased insulation from change impact, increased adaptability to change, and increased potential for reuse.


Vertical Separation

Vertical Separation of Concerns refers to the process of dividing an application into modules of functionality that relate to the same feature or sub-system within an application. Vertical separation divides the features of an application holistically, associating any interface, business, and resource access concerns within a single boundary. Figure 3 depicts an application separated into three modules:



Figure 3



Separating the features of an application into modules clarifies the responsibly and dependencies of each feature which can aid in testing and overall maintenance. Boundaries may be defined logically to aid in organization, or physically to enable independent development and maintenance.

Logical boundaries imply the existence of modularity, though the methods used to denote separation may have no bearing on the actual deployment or runtime behavior of an application. This can be useful for improving the maintainability of an application as well easing any future efforts for physically separating features. Figure 4 depicts an application containing logical boundaries:



Figure 4


Physical boundaries are generally used in the context of developing add-ins or composite applications, and can enable features to be managed by disparate development teams. Applications supporting add-in modules often employ techniques such as auto-discovery, or initializing modules based on an external configuration source. Figure 5 depicts a hosting framework containing modules developed by separate development teams:





Figure 5


While vertical separation groups a set of concerns based on their relevance to the total fulfillment of a specific feature within an application, this does not preclude the use of other separation of concerns strategies. For example, each module may itself be designed using layers to delineate the role of components within the module. Figure 6 depicts an application using both horizontal and vertical separation of concerns strategies:



Figure 6


Aspect Separation

Aspect Separation of Concerns, better known as Aspect-Oriented Programming, refers to the process of segregating an application’s cross-cutting concerns from its core concerns. Cross-cutting concerns, or aspects, are concerns which are interspersed across multiple boundaries within an application. Logging is one example of an activity performed across many system components.

Figure 7 depicts an application with several cross-cutting concerns:




Figure 7


Cross-cutting concerns can be difficult to maintain due to their widespread placement throughout an application. Their mixture with core concerns also adds complexity, rendering the application more difficult to maintain. By separating these concerns, both core concerns and cross-cutting concerns are made easier to manage.

Aspect separation differs from other separation techniques in that it relies on a pre-processing, compile time, or run-time fusion of cross-cutting concerns with the application. The process of fusing the two concerns back together is referred to as “weaving”. By using various strategies, cross-cutting concerns can be separated and woven back into the application for run time cohesion.

Figure 8 depicts a conceptual weaving process where separately maintained cross-cutting concerns are joined with core concerns:



Figure 8


Aspect separation tools are available for a wide range of programming languages. For more information on this topic including a list of available tools for facilitating aspect separation, see the Wikipedia Web page for Aspect-Oriented Programming.


Dependency Direction


One characteristic of good Separation of Concerns is the ideal establishment of dependency direction. An ideal dependency direction establishes the roles of consumer and dependency such that the role of dependency is occupied by the entity possessing the highest potential for reuse.

A simple example illustrating the concept of dependency direction is the common relationship between a business component and a utility component. Consider a system which provides an order inquiry process which requires that frequently requested data be cached for greater efficiency. To facilitate the caching of order inquiries, a caching utility component may be developed to separate the concerns of caching from the rest of the order inquiry process. Figure 9 depicts this system with its two components:




Figure 9



Because the function of caching is a more generic behavior than an order inquiry process, the caching component has the higher potential for reuse among the two. Therefore, the best dependency direction in this case would be from the business component to the utility component. This dependency is depicted in Figure 10:




Figure 10



Such a relationship allows the caching component to remain agnostic of the business inquiry process enabling it to be reused by future processes.

In contrast, if the caching component is design to depend specifically on the type of data being cached, or on some other aspect of the business component, then the caching component would be incapable of being reused by future processes without modification. Such a relationship is depicted in Figure 11:





Figure 11





While extending this relationship to other components would be possible, this approach would eventually result in a caching component which is overly complex and unwieldy.

Another example demonstrating the concept of dependency direction is the relationship between layers within an application. Figure 12 depicts an application which separates the concerns of presentation, business processing, and resource access into separate layers:





Figure 12



As discussed in the section on Horizontal Separation, these layers are a common pattern of separation because they represent an organization of concerns which minimizes the level of dependencies within an application. By ensuring that each layer only establishes dependencies on layers for which it possesses no mutual relationship, either directly or indirectly, each layer can be isolated from changes to direct and indirect consuming layers. Figure 13 depicts this prescribed relationship:




Figure 13



This improves the application’s ability to adapt to change and enables layers to be reused within a different context (e.g. multiple presentations of the same business processes).

In contrast, a violation of this prescription results in layers which are less insulated to change and less capable of being reused. Figure 14 depicts the resource access layer accessing the business layer.




Figure 14



The establishment of this dependency can be considered a violation of the principle of separation of concerns. This is because the resource access layer, by definition, is not inherently concerned with business processes. The boundary which comprises the resource access should only be concerned with obtaining resources such as the retrieval of data from a database or Web service. This violation results in a resource access layer which will require modification when the dependant portion of the business layer changes, and prevents the resource access layer from being reused by other applications without requiring an indirect dependency on this application’s business layer.

Another recommended best practice related to dependency direction within application layers is the prescription that layers limit their dependencies to only the layer immediately following itself in a dependency direction chain. That is to say, layers should never bypass logically adjacent layers. This restriction centralizes the access to each layer which insulates other layers from change impact, and allows consistent processes to be applied to layer access. An example of this would be restricting the Presentation Layer from directly accessing the Resource Access Layer. Such a restriction ensures that changes to the Resource Access Layer would only affect the Business Layer. Additionally, this would allow consistent processes to be applied to the access of data, such as caching, failover, auditing, error checking, etc., and the insulation of changes to these processes.


Data Concerns

Applying the principle of Separation of Concerns to data involves properly modeling information managed by a system. While the aspects of data modeling apply to both object-oriented and database design, this discussion focuses on object-oriented data concerns since the primary needs of a database often require form to follow function.

When organizing data within an object-model, the exposed information should be inherent to the entity being represented. For example, given a system which sells products to customers, an object which defines the product should not contain customer related information. This is because products are not inherently concerned with who may be purchasing the product. A better approach would be the creation of a conceptual order object which composes both customer and product information. This enables the product object to be reused by other processes in the future which may not be concerned with customer information.

In addition to considering the potential reuse of a data model within differing contexts, the intuitive organization of data is also beneficial when maintaining highly complex systems. For example, if a new developer were tasked with accessing the serial number of a particular part composed by a product object already in memory, the developer would likely first attempt to locate the particular product part and then examine the part for a “SerialNumber” or similarly named property. The developer would probably not think to look for something such as a “product number to serial number” dictionary located on the product object because this would not be a natural representation of the data. This would be similar to considering a person to have a serial number by virtue of their wearing a wrist-watch that possessed a serial number.

There are times, however, when the natural organization of data does not present an efficient mechanism for information inquiry. For example, an exceptionally complex product object which needs to be inspected frequently to derive the total count of all copper elements may not be efficiently handled through the examination or cross-referencing of each of its composed elements. In cases where natural modeling is not itself sufficient, the integrity of an object-model can be maintained by supplementing conceptual types to satisfy the specialized need. For example, if the product’s composition remains static once assembled, a conceptual model representing the product’s precious metal information (e.g. “ProductPreciousMetalManifest”) might be composed at a peer level to the product information. If the product’s composition changes frequently and the composition processes are centralized then the precious metal information might be updated as part of this process. Otherwise, a specialized component could be conceived (e.g. “PreciousMetalDetector”) to dynamically return the product’s precious metal information. As with the first example, the benefits of separating conceptual needs from an otherwise natural model are that other processes may reuse the model without incurring the overhead of non-inherent characteristics, and the model is kept easily maintainable.


Behavior Concerns


Separating behavior involves the division of system processes into logical, manageable, and reusable units of code. This represents the most fundamental type of Separation of Concerns. Within object-oriented systems, fine-grained behavior is separated using methods while course-grained behavior is separated using objects, components, applications, and services.

As with the separation of data, encapsulated behavior should be inherent to its containing boundaries. For instance, a method named CreateCustomer() would be expected to only contain behavior relevant to the creation of a new customer. It wouldn’t be expected to, for example, place orders for a new customer. Similarly, a component named ProductAssembler would be expected to contain data and behavior relevant to the assembly of products. Similarly, it wouldn’t be expected to contain data or behavior related to customers.

Achieving good separation of behavior is often an iterative process. The primary behavior of a system is generally conceived during a design phase, but the specific implementation of a system design often requires several iterations of refactoring as fine-grained concerns become more apparent.

When organizing behavior, the following goals should be sought:
  • Eliminate the duplication of functionality.
  • Restrict the scope of work to a maintainable size.
  • Restrict the scope of work to the description of the containing boundary.
  • Restrict the scope of work to the inherent behavior of the containing boundary.
  • Minimize external dependencies.
  • Maximize the potential for reuse.

Extending Concerns

Extensions are a separation of concerns strategy which enables the addition of new behavior to an existing set of concerns. Extensions are used to enhance existing concerns where the desired behavior cannot be added to the targeted system, is not an inherent behavior of the system, or is otherwise impractical for inclusion as part of the system’s core set of features. Figure 15 depicts the dependency relationship of an extension to a target system:



Figure 15


Extensions interact with the target system in response to notifications of key events. Examples of behavior provided by extensions would include the display of new views or controls, the alteration of normal processing, or the alteration of data within the target system. Extensions generally take the form of a hosted add-in, and are typically registered through configuration or a dynamic discovery process.

When multiple client applications are maintained within an enterprise, it may be discovered that behavior provided by one client’s extension would be valuable to add to another client as well. If the extension is highly customized to the target application and provides a relatively simplistic behavior, the best course of action would be to reproduce the functionality in the new application. However, if the extension’s behavior is substantial in size and complexity then it may be more appropriate to provide the behavior generically through an enterprise service. If the behavior provided by the service is still inappropriate to include as a core dependency of the host system then a new extension can be developed to interact with the service on behalf of the application.


Delegating Concerns

Delegating concerns refers to the process of assigning the responsibility for fulfilling behavior to a subordinate component. This strategy separates the concerns of responsibility from execution, and is beneficial for designing components whose implementation details may vary depending on external conditions. Using this strategy, components proxy some or all data requests and method invocations to another component designed to fulfill the request in a specialized way. For example, a component designed to return a list of roles assigned to the current user may delegate the request to one or more subordinate components designed to retrieve roles from a local XML file, database, and/or a remote service. Figure 16 illustrates the delegation of authorization concerns to components specialized for differing data sources:




Figure 16



Delegation can be facilitated using the Strategy Pattern, the Plug-in Pattern, the Microsoft Provider Model, and other variant patterns which enable portions of a component’s behavior to be fulfilled externally.


Inverting Concerns

Inverting concerns, better known as Inversion of Control, refers to the process of moving a concern outside of an established boundary. Some uses for inversion of concerns include effecting aspect separation, minimizing non-essential processes, decoupling components from specific abstraction strategies, or relocating responsibilities to infrastructure components. Some specific applications would include alleviating responsibilities pertaining to hardware interaction, workflow management, registration processes, or obtaining dependencies.

Figure 17 depicts an inversion of concerns process where both a presentation component and a domain component have had concerns moved to infrastructure level components:



Figure 17


One example where inversion of concerns can be seen is in the use of the Template Method pattern. This pattern is used to generalize the behavior of a process in order to allow variation through inheritance. When applying this pattern to an existing component, the steps performed by the desired process would be generalized and encapsulated in a base class. The existing component would then inherit from the new base class, maintaining only specialized behavior. Other types would then be free to inherit from the base class to provide variant implementations. This would be an example of inverting the concerns of an algorithm sequence.


Another example of inverting concerns can be observed when converting an interactive console application to a GUI application. A typical interactive console application provides a main loop which prompts the user for information and waits for data to be entered. When converted to a GUI application, the main control of the program is generally provided by infrastructure components, and notification of user interaction is accomplished using the Observer Pattern. This inverts the main control of the user interaction process by relying on the application infrastructure or hosting environment for these concerns.

Dependency Injection is a term applied to the inversion of concerns which relate to obtaining external dependencies. This term was conceived to more clearly describe the behavior of a class of frameworks concerned with this form of inversion. The goal of dependency injection is to separate the concerns of how a dependency is obtained from the core concerns of a boundary. This improves reusability by enabling components to be supplied with dependencies which may vary depending on context.

The process of dependency injection generally involves the roles of container, dependency, and recipient.

The role of container is occupied by a component responsible for assigning dependencies to a recipient component. Containers are generally implemented using the Factory Pattern to allow creation of the recipient and dependency components.

The role of dependency is occupied by the resource being provided to the recipient. Containers are often implemented to allow existing objects to be registered for use as a dependency, or to create new instances when required.

The role of recipient is occupied by the component receiving a dependency from the container. Recipients are required to declare dependencies using a strategy supported by the container. Strategies for determining dependency information generally employ the use of reflection to examine one or more of the recipient’s member types, and may require the use of attributes/annotations to implicitly or explicitly specify dependencies. A sequence diagram representing these roles is presented in Figure 18.



Figure 18


One example use of dependency injection would be to abstract caching functionality from a business component in lieu of using the Factory or Factory Method patterns. By supplying a recipient with a caching component using dependency injection, the recipient remains loosely coupled to the caching component without the added coupling to a specific factory.

Another example would be the use of dependency injection to control the number of caching components created in lieu of using the Singleton Pattern. This enables the application to ensure that only a single instance is used throughout the lifetime of an application, or to control which recipients receive which instances of the component. This also increases the ability to test components in isolation of their dependencies by enabling mock dependencies to be supplied rather than requiring singletons to be tested along with their consumers.

Components using patterns such as Factory, Factory Method, Abstract Factory, Singleton, Plug-in, Service Locator to abstract the concerns of object creation or dependency retrieval are good candidates to consider for supplementing or replacement with dependency injection. By using dependency injection in lieu of, or in cooperation with these and other such patterns, consuming components can be completely abstracted from the particular abstraction strategy.


The Exaggeration Exercise

It is often the case that the negative consequences of a design choice, particularly those relating to scalability and reuse, do not become apparent until long after a system has become established. Problems with scalability and reuse are usually rooted in a lack of adherence to the principle of Separation of Concerns. One process that can aid in optimizing concerns is considering the impact of a design when applied under exaggerated circumstances. Through this exercise, the use of a system is hypothetically exaggerated beyond the system’s known expectations in order to reveal potential weaknesses in a design approach. For example, when designing an object model to be used by two existing systems, one might consider what the consequences would be if the object model were shared by fifty systems. By exaggerating the use of a design, poorly organized responsibilities will often become easier to identify.

To demonstrate this exercise, consider the following example concerning the creation of a new composite customer relationship management system:

Within a corporation, an IT department has been requested to create a custom CRM application which will allow disparate development teams to contribute specialized modules of functionality. The main customer related segments within the corporation will be sales, billing, and technical support, though there may be multiple development teams assigned to support the functions of each segment. It has been requested that the application present a main screen allowing customers to be queried by a number of different criteria including name, address, phone number, order number, and any registered product serial numbers. However, the resulting views and workflows should depend upon which business function is being carried out at a given time. For example, upon submitting customer search criteria, sales users may be displayed with a view pertaining to past purchasing trends, credit rating scores, and suggested up-selling scripts; while a billing user may be presented with a view displaying customer payment history, billing dispute history, and outstanding balances. An initial analysis reveals that there will be a total of three workflow variations resulting from a total of five different search criteria fields, and that there will be three backend systems involved in obtaining the information needed by all segments. Because the variations are low, the choice is made to centralize the main view, customer search functionality, and workflow initiation within a search module. It is understood that the addition of new search criteria and workflow needs will require modifications by the search module development team, but it is believed that these needs will be infrequent.

Applying the exaggeration exercise to this design choice might entail considering what consequences might ensue if the number of business segments or number of backend systems were increased to fifty. As a result of centralizing the search functionality and workflow initiation, increasing the scope of these concerns will also increase the responsibility and workload of the search module development team. This would include the scoping, analysis, design, coding, and testing of all new features and change requests related to these concerns. In turn, this would likely result in the need to increase the number of development resources required for the search module team. It is also likely that the same initial assumptions that lead to the consolidation of these concerns also informed other design decisions made for the search module. This may have led to design choices that would not readily accommodate such an increase in responsibilities, requiring some level of internal redesign to handle new concerns.

An outstanding problem that can be observed through this exercise is that the amount of work required by the search team is proportionally related to the number of business segments or workflows supported by the system. The fact that the initial solution doesn’t scale as the need increases can be an indication that concerns may have been inappropriately distributed throughout the system. The decision for consolidating search functionality and the resulting workflow decisions within the search module was the result of recognizing similarities between each use case. What was not given equal consideration was the fact that each use case had to be treated in a specialized way, and the fact that the number of possibilities has no true boundaries. Because the search screen provides a central function for many modules, it can be said to possess inherent infrastructure concerns. It should, therefore, be expected to provide the behavior that is common to all modules. However, the details of each case are not common, and can be considered the inherent concerns of each respective module. Upon recognizing the inherent responsibilities, an alternate approach might include the development of a framework to consolidate the common concerns, but enabling the distribution of each domain specific concern. Such an approach could be accomplished by requiring each module to provide an add-in which registers available search criteria and provides handling capabilities to invoke the corresponding workflow. A framework would then be responsible for presenting a consolidated view of the search criteria, and providing a generic infrastructure for associating each search criteria to its corresponding workflow handler. By using this approach, the search module can be designed to accommodate an unlimited number of use cases.

While the exaggeration exercise can be useful in creating highly scalable designs, this is only a byproduct of its primary goal which is the achievement of optimal Separation of Concerns. The exaggeration exercise might be compared to the medical practice of taking a patient’s temperature to test for symptoms of a possible underlying problem. This exercise attempts to identify problems pertaining to separation of concerns by examining the scalability aspect of a potential design. This might be compared to using a magnifying glass to look at the details of a design as depicted in Figure 19.


Figure 19


It is through the exaggeration of a design’s actual scope that small problems are magnified for easier identification. Once identified, it may then be determined what course of action should be taken.

Separation Anxiety

Applying the principle of separation of concerns often involves advanced concepts and constructs which bring a certain level of complexity to the application beyond that of merely addressing the domain concerns of the application. For developers inexperienced in these programming techniques the reaction falls within the spectrum of enthusiastic excitement over the opportunity to add to one’s repertoire of design skills, and an adverse reaction to the additional amount of complexity involved in getting the job done in the most expedient way possible. These techniques often lead inexperienced or more tactical-minded developers to characterize such designs as “overly-complex” or “over-engineered” based upon their frustrations in first learning, and then maneuvering through such architectures on a day-to-day basis. Furthermore, there is often an ever-present pressure from project managers, product managers, upper level management, marketing, or end users for instant gratification which tends to encourage and reward expediency over thoughtful design. These conditions can present obstacles to developing good designs beyond merely solving the technical problems.

While designs which promote separation of concerns often add complexity to an application, it should be pointed out that they also remove the complexity that is generally associated with a lack of separation of concerns. For many applications, the trade-off is often between ordered complexity and disordered complexity. Applications which do not exhibit an appropriate amount of separation of concerns are often difficult to learn due to the need to understand the whole before understanding the part, and difficult to maintain and extend. Highly complex, yet poorly modularized applications also have the effect of causing high turnover in development staff (which tends to further compound design and implementation problems), or attracting individuals who have an aversion to change and seek to build their career by being the indispensible “master of the maze” within their organization. Development teams should certainly not seek complexity for complexity’s sake (unless entering an obfuscation contest), but the notion that avoiding advanced design concepts equates to avoiding complexity should be dispelled.


Conclusion

In a sense, the goal of Separation of Concerns is one of artistic and mechanical harmony. A system comprised of cooperating components each of which performs only those tasks inherent to its nature is a unique form of artistic achievement which blends both form and function. It is an endeavor which can satisfy both the creative and analytical cravings of the human mind while at the same time helping one to meet and often far surpass external expectations.

Saturday, August 25, 2007

Interactive Application Architecture Patterns

An Introduction to the Model-View-Controller, Model-View-Presenter, and Presentation-Abstraction-Control Patterns

This article presents an introduction, overview, and comparison of three similar interactive application architecture patterns: the Model-View-Controller, Model-View-Presenter, and Presentation-Abstraction-Control pattern.

Introduction

The MVC, MVP, and PAC patterns are each intended to address the needs of interactive applications by separating the concerns assigned to different components within their respective architectures. While similar, each of these patterns differs slightly in their motivations and applicability to various design goals. This article discusses each pattern along with its history and design motivations to encourage the correct understanding and application of these patterns.

In discussing architecture patterns in general, it is helpful to understand that patterns in this class are often motivated by design considerations which were formed within the context of specific development environments. As such, platform specific motivations and the pattern’s implementation details often become part of the formal description of the pattern.

For instance, the Model-View-Controller pattern had the primary design motivation of separating presentation from domain concerns. The division between the input and output of the application, which resulted in the concept of the Controller component, was really a byproduct of the complexities required in dealing with device input and output. Today’s development environments have come a long way in shielding developers from such complexities, making divisions between device input and output at the application level unnecessary. In such environments, the application of the Model-View-Controller pattern may result in an approach which adheres to the intent of the pattern while not following its original form, or adheres to its original form without following its original intent. For example, the original goals of the Model-View-Controller pattern can be accomplished today within many development environments by merely separating an application’s Forms and associated Controls from a Domain Model or other domain specific implementation strategy. The inclusion of a Controller for intercepting user input is unnecessary in platforms which natively provide this functionality. When attempting to follow the original form of the Model-View-Controller pattern within such development environments, the resulting architecture may fall somewhere between a strict implementation of MVC which goes against the grain of the hosting environment and an implementation which assigns different responsibilities to the original components.

From this observation it can be deduced that the Model-View-Controller pattern hasn’t adequately been distilled into pattern language. That is to say, the components prescribed by the MVC pattern are not agnostic of the assumed development environment, and most descriptions do not make this explicit. This often results in the misapplication of the pattern.

Another suggestion when studying and considering the use of interactive design patterns is to take the whole subject with a grain of salt. Many of the base patterns, such as those presented in the seminal work Design Patterns – Elements of Reusable Object-Oriented Software by Gamma, etc. al. are well distilled patterns which describe solutions to common problems in a implementation-agnostic way. Because of the nature of these patterns, we don’t generally find scores of competing constructs purporting to address the same issue. However, when entering the realm of compound patterns such as interactive application patterns, models, styles, etc., the study of such constructs can feel a bit like watching a documentary of the history of airplanes. Is that a Controller I see in that last image?



It’s best to think of architecture patterns as being as much in the realm of art as science. Interactive architecture patterns aren’t the computer science equivalent of Newton’s Law of Gravity. They merely represent our ever evolving attempt to achieve the best model for the needs of the day.

Finally, when considering the use of these various patterns, remember that you should be considering them for their applicability to your problem, not so you can proclaim: “I use the such-and-such pattern” with thumbs tucked securely under the straps of your overalls. The use of patterns should be the result of having started with a problem for which an existing pattern was known or found to be applicable, not the result of starting with a pattern for which a problem was sought out or invented to be applicable. With that said, let’s proceed with the discussion.


The Model–View-Controller Pattern

Overview

The Model-View-Controller pattern is a methodology for separating the concerns of an application’s data, presentation, and user input into specialized components.

Origins and Motivation

The MVC pattern was originally conceived in 1978-79 by Trygve Reenskaug and had the primary goal of providing an interface for users to manipulate multiple views of data as if working with real world entities. The pattern was first referred to as the Thing-Model-View-Editor before Reenskaug and his colleges settled on the name Model-View-Controller (1). A modified version of Dr. Reenskaug’s design was later implemented as part of the Xerox PARC Smalltalk-80 class library. A description of this implementation can be found in the work: Applications Programming in Smalltalk-80(TM): How to use Model-View-Controller (MVC).

Structure

The following diagram depicts the structure of the Model-View-Controller pattern:


Note: While some descriptions of the MVC pattern show an indirect association from the View to the Controller, the original implementation of MVC in Smalltalk-80 coupled View to Controller, and vice-versa (2).

Components

The Model refers to the data and business functionality of the application. This is often represented by a Domain Model where objects seek to model real world entities by representing their properties and behavior.

The View is the visual representation of the Model and is comprised of the screens and widgets used within an application.

The Controller is a component which responds to user input such as data entry and commands issued from a keyboard or mouse. Its responsibility is to act as a bridge between the human and the application, allowing the user to interact with the screen and data.

Collaborations

Within the MVC pattern, a Model-View-Controller triad exists for each object intended to be manipulated by a user.

The Model represents the state, structure, and behavior of the data being viewed and manipulated by the user. The Model contains no direct link to the View or Controller, and may be modified by the View, Controller, or other objects with the system. When notification to the View and Controller are necessary, the Model uses the Observer Pattern to send a message informing its dependants that the data has changed.

The View and Controller components work together to allow the user to view and interact with the Model. Each View is associated with a single Controller, and each Controller is associated with a single View. Both the View and Controller components maintain a direct link to the Model.

Note: Within the Smalltalk-80 implementation, both the View and Controller maintained a direct link to one another, though the link from the View to the Controller was largely a byproduct of its implementation rather than an inherent part of the MVC pattern. The link was not maintained to delegate user input intercepted by the View to the Controller as is the case with the Dolphin Smalltalk Model-View-Presenter pattern, but was rather used by the View to initialize the controller with an instance of itself, and by a top level Controller to locate the active Controller within a View hierarchy.

The View’s responsibility can be seen as primarily dealing with output while the Controller’s responsibility can be seen as primarily dealing with input. It is the shared responsibility of both the View and the Controller to interact with the Model. The Controller interacts with the Model as the result of responding to user input, while the View interacts with the Model as the result of updates to itself. Both may access and modify data within the Model as appropriate.

As data is entered by the user, the Controller intercepts the user’s input and responds appropriately. Some user actions will result in interaction with the Model such as changing data or invoking methods, while other user actions may result in visual changes to the View such as the collapsing of menus, the highlighting of scrollbars, etc.

MVC Misconceptions

One common misconception about the relationship between the MVC components is that the purpose of the Controller is to separate the View from the Model. While the MVC pattern does decouple the application’s domain layer from its presentation layer, this is achieved through the Observer Pattern, not through the Controller. The Controller’s job is to mediate between the human and the application, not between the View and the Model.

Pattern Variations and Derivatives

The classic Model-View-Controller pattern is largely no longer used today in its original design, though it has given rise to a number of variations adapted to newer development platforms such as Microsoft Windows and Web development. Two of these variations, the Model-View-Presenter and Presentation-Abstraction-Control patterns will be discussed in the remainder of this article.


The Model-View-Presenter Pattern

The Model-View-Presenter pattern is a variation on the Model-View-Controller pattern, and similarly separates the concerns of an application’s data, presentation, and user input into specialized components.

The definition and distinctive characteristics of this pattern are not easily summarized due to the fact that there are several patterns commonly accepted under the name “Model-View-Presenter” which do not share the same distinctive qualities over their predecessor, the Model-View-Controller pattern. For this reason, this article will discuss the original Model-View-Presenter pattern along with some of its variations and derivatives.



The Taligent Model-View-Presenter Pattern

Overview

The Taligent Model-View-Presenter pattern separates the application concerns of data, data specification, data manipulation, application coordination, user interaction, and presentation into specialized components.

Origins and Motivation

The MVP pattern was based on the Taligent programming model, which itself was influenced by the original Smalltalk-80 MVC pattern. The pattern was first formally described by Mike Potel in 1996 while working for Taligent, Inc.. Taligent was started by Apple Computer, Inc. as a joint venture with IBM (and later joined by Hewlett Packard) before becoming the wholly owned subsidiary of IBM in late 1995. Many of the elements of the original MVP pattern began taking form at Apple under the management of Larry Tesler, who formerly worked at Xerox PARC where he was one of the contributors of the design and implementation of Smalltalk.

While the main elements of the pattern were already being utilized at Taligent between 1992 and 1994, it wasn’t until after Taligent, Inc. was purchased by IBM in 1995 that Mike Potel first suggested the name “Model-View-Presenter” to describe the architecture found within the Taligent programming model. Dr. Potel credits Arn Schaeffer, Dave Anderson, and David Goldsmith as leading contributors to the Taligent programming model from which the MVP pattern was derived (3).

Structure

The following diagram depicts the structure of the Taligent Model-View-Presenter pattern:

Components

The Model refers to the data and business functionality of the application.

Selections are components which specify what portion of the data within the Model is to be operated upon. Examples would be selections which define rows, columns, or individual elements which meet specific criteria.

Commands are components which define the operations which can be performed on the data. Examples might be deleting, printing, or saving data within the Model.

The View is the visual representation of the Model and is comprised of the screens and widgets used within an application.

Interactors are components which address how user events are mapped onto operations performed on the Model, such as mouse movements, keyboard input, and the selection of checkboxes or menu items.

The Presenter is a component which orchestrates the overall interaction of the other components within the application. Its roles include the creation of the appropriate Models, Selections, Commands, Views, and Interactors, and directing the workflow within the application.

Collaborations

The most notable collaborative differences between the Taligent Model-View-Presenter pattern and the Model-View-Controller pattern are found within the Presenters and Interactors.

The Presenter acts as an overall manager for a particular subsystem within an application. It maintains the lifecycle and relationships between the Views, Interactors, Commands, Selections, and Model. The responsibility for intercepting user events is governed by Interactors; therefore Presenters are not needed for each widget on a given View as were Smalltalk-80 Controllers. There is generally a single Presenter per View, though in some cases a Presenter may manage multiple logically related Views.

Interactors are somewhat analogous to Smalltalk-80 Controllers. They are the components which respond to user events and in turn call the appropriate Commands and Selections of the Model.



The Dolphin Smalltalk Model-View-Presenter Pattern

Overview

The Dolphin Smalltalk Model-View-Presenter pattern separates an application’s concerns of data, presentation, and presentation logic into the specialized components of Model, View, and Presenter. The Dolphin Smalltalk team simplified the Taligent MVP pattern by eliminating Interactors, Commands, and Selections from the pattern’s formal description. This in turn simplified the role of the Presenter, changing it from a subsystem controller to a component which mediated updates to the Model on behalf of the View.

Origins and Motivation

The Dolphin Smalltalk Model-View-Presenter pattern was adapted from the Taligent Model-View-Presenter pattern to address flexibility issues the Dolphin development team was having in its approach to view/domain separation. One of the team’s early considerations included a variation on the MVC pattern used by ParcPlace Systems’ VisualWorks. While the Dolphin team considered the VisualWorks MVC design initially, they later became disenchanted with its prescribed Application Model whose complexity at times tempted developers to allow the model to access the view directly. They also found that the MVC concept of a Controller, whose primary purpose was to respond to user events, didn’t mesh well with more current development platforms whose native widgets handled user events directly. After encountering the Taligent MVP pattern, the Dolphin team concluded it was more applicable for achieving their design goals. While they saw benefits in the Taligent MVP pattern, they mistakenly believed that Taligent derived their pattern from the VisualWorks’ MVC implementation and had eliminated the use of an Application Model by moving presentation logic concerns from the Model to the Presenter. They described this as “Twisting the Triad”, though this does not accurately portray the differences between the Taligent MVP pattern and the original Smalltalk-80 MVC pattern. Due to this misunderstanding, they viewed the Presenter component as being a replacement of the Application Model within VisualWorks’ MVC rather than an evolution of the Controller component within the Smalltalk-80 MVC. The resulting pattern implemented by the Dolphin Smalltalk team was void of most of the components which gave the original MVP its distinctiveness from MVC, though it introduced distinctive qualities of its own.

Structure

The following diagram depicts the structure of the Dolphin Smalltalk Model-View-Presenter pattern:

Components

The Model refers to the data and business functionality of the application.

The View is the visual representation of the Model and is comprised of the screens and widgets used within an application.

The Presenter is a component which contains the presentation logic which interacts with the Model.

Collaborations

Within the Dolphin MVP pattern, Views intercept the initial user events generated by the operating system. This choice was primarily the result of development on the Microsoft Windows operating system whose native widgets already handled most controller functionality. In a few cases the View responded to user events by updating the Model directly, but in most cases user events were delegated to the Presenter. Implied by the Dolphin Smalltalk description is that Views only delegated events when updates to the Model were required, thus leaving all other presentation logic within the View.

As with the Taligent MVP pattern, there is usually a single Presenter which handles updates to the Model for a specific View.

As with the Model-View-Controller pattern, the View is notified of any changes to the Model using the Observer Pattern and responds by updating the relevant portions of the screen.

Dolphin Smalltalk MVP vs. Smalltalk-80 MVC

On the surface, the differences between the Dolphin Smalltalk MVP pattern and the Smalltalk-80 MVC pattern are difficult to discern. Both of the patterns contain a triad. Both of the patterns contain a Model and View which are virtually identical in function. Both the Smalltalk-80 Controller and the Dolphin Smalltalk Presenter are involved in updating the Model. Both of the patterns use the Observer Pattern to update the View when changes occur to the Model. With all these similarities, it is clear why so much confusion surrounds understanding how the Model-View-Presenter pattern sets itself apart from the Model-View-Controller pattern. The key is in understanding the primary functions which Presenters and Controllers play within their respective triads.

Within the original Model-View-Controller pattern, the primary purpose of the Controller was to intercept user input. The Controller’s role of updating the Model was largely a byproduct of this function rather than an inherent part of its purpose.

Conversely, within the Dolphin Smalltalk Model-View-Presenter pattern, the primary purpose of the Presenter was to update the Model. The Presenter’s role of intercepting events delegated by the View was largely a byproduct of this function rather than an inherent part of its purpose.

Part of the original idea leading to the development of the MVC pattern was a separation between the representation of a user’s mental idea of the data (i.e. the Model), and the logic which allowed the user to interact with that representation (i.e. the Editor). This was considered Model/Editor separation (4). Because the tasks involved in displaying data on the screen were technically very different from the tasks involved in interpreting the user’s input from devices such as the keyboard and the mouse, the combination of these tasks into a single object resulted in unnecessary complexity. Therefore, the concerns of input and output were separated into Views and Controllers. Because Controllers were assigned the input responsibility of the Editor, it naturally followed that they took on the responsibility of updating the Model when input was received from the user.

Within the Dolphin Smalltalk MVP pattern, the role of intercepting the user’s input was moved to the View. This effectively eliminated the original need for Controllers or Interactors altogether. While the original idea of the Presenter was seen by the Taligent team as a Controller elevated to an application level, the Dolphin team mistakenly considered it a replacement of the VisualWorks’ Application Model and maintained the Presenter as a mediating component within the triad.

So then, while the Dolphin Smalltalk MVP and the Smalltalk-80 MVC patterns may appear similar on the surface, Presenters and Controllers differ in the purposes they were conceived to address.


The Fowler Patterns

During his research and preparation of material on presentation layer patterns in 2006 for an upcoming book, Martin Fowler decided that the treatment given to the design intensions behind today’s use of the Model-View-Presenter pattern be divided under the names Supervising Controller and Passive View. This distinction was made around the level of responsibility the Presenter/Controller component of the pattern takes on for presentation layer logic.

The Supervising Controller and Passive View patterns are well distilled constructs which deal with the concerns of presentation logic apart from any specific domain logic strategy. This distilment renders patterns which describe solutions not specific to the Model-View-Presenter pattern, and are an excellent example of how patterns come about. While discussed here within the context of the Model-View-Presenter pattern, these patterns are best understood as facilitating patterns (as with the Observer Pattern) rather than variations of the Model-View-Presenter pattern.


The Supervising Controller Pattern

Overview

The Supervising Controller pattern separates an application’s concerns of presentation and presentation logic into the specialized components of View and Controller, with the View assigned the responsibility of simple presentation logic and the Controller assigned the responsibilities of responding to user input and handling complex presentation logic.

Structure

The following diagram depicts the structure of the Supervising Controller pattern:


Note: The model is here depicted in gray to denote its peripheral role to the pattern description.

Components

The View is the visual components used within an application such as screens and widgets.

The Controller is a component which processes user events and the complex presentation logic within an application.

Collaborations

Within the Supervising Controller pattern, Views delegate user events to the Controller which in turn interacts with the business domain of the application.

For simple presentation logic, the View uses data binding techniques and the Observer Pattern to update itself when changes occur within the application.

Complex presentation logic, particularly any logic one desires to unit test, is delegated to the Presenter.


The Passive View Pattern

Overview

The Passive View pattern separates an application’s concerns of presentation and presentation logic into the specialized components of View and Controller, with the Controller taking on the responsibility for responding to user events and presentation logic.

Structure

The following diagram depicts the structure of the Passive View pattern:


Note: The model is here depicted in gray to denote its peripheral role to the pattern description.

Components

The View is the visual components used within an application such screens and widgets.

The Controller is a component which processes user events and the presentation logic within an application.

Collaborations

Within the Passive View pattern, Views delegate user events to the Controller which in turn interacts with the business domain of the application and/or updates the View. The View maintains no link to the domain layer and relies solely on the Controller for all presentation related logic.

Controllers within this pattern take on a mediating role between the Views and domain logic strategy used. This formalizes a role often erroneously ascribed to Controllers within the Model-View-Controller pattern.


The Microsoft Patterns & Practices Patterns

Beginning with the Composite UI Application Block, and more formally in the Smart Client Software Factory and Web Client Software Factory released by the Microsoft Pattern & Practices teams in 2006, Microsoft began incorporating the MVP pattern into its guidance automation, documentation, examples, and labs. In addition to the Model, View, and Presenter components, the Web Client Software Factory also encourages the user of an Application Controller (5) for decoupling page flow logic from presentation specific logic.

While Microsoft’s implementation of the Model-View-Presenter pattern doesn’t differ significantly from the Dolphin Model-View-Presenter description, its implementation and incorporation into these popular frameworks are worthy of note due to their influence on the .Net community’s perspective on this pattern.


The Microsoft Model-View-Presenter Pattern

Overview

The Microsoft Model-View-Presenter pattern separates an application’s concerns of data, presentation, and presentation logic into the specialized components of Model, View, and Presenter.

Structure

The following diagram depicts the structure of the Microsoft Model-View-Presenter pattern implementation:


Components

The Model refers to the data and business functionality of the application.

The View is the visual representation of the Model and is comprised of the Forms and Controls used within an application.

The Presenter is a component which contains the presentation logic which interacts with the Model and optionally updates the View.

Collaborations

Within the Smart Client Software Factory, each View is defined with a corresponding View interface and Presenter. Each View creates a private instance of its Presenter upon initialization, and each Presenter is defined with a reference to the View interface type which is set by the View after creation. As user events are intercepted by the View, the code-behind invokes methods on the Presenter which in turn interact with the Model. In addition to methods which mediate access to the Model, the Presenter is typically created with methods to be invoked when the View is ready to be displayed and when the View is ready to be closed. Presenter methods are typically named abstractly to denote a particular action to be taken as opposed to having any direct correspondence to event names contained within the View.

The Model is often represented by a suite of business layer components within the application rather than a traditional Domain Model. The business layer typically consists of Business Entities, Business Workflows, and Business Components as described in the book Application Architecture for .Net: Designing Applications and Services. The Presenter also often interacts with the domain layer through a service layer allowing further abstraction tec