-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture Driven Leadership
The wiki outlines a typical high level application architecture and attempts to motivate UI architects to think beyond MVC pattern and solve emerging development complexities in large codebases. The repository provides a reference implementation of a modern architectural pattern, PresentationModel, in pure JavaScript to address the discussed issues.
- UI Architectures
- Presentation Model
- Large scale application development and MVP
- Architectural Structures and Views
Though a high level architecture (see next section) provides a solution to meet functional requirements, it does not provide enough detail on the following objectives that impact time-to-market:
- Modifiability – Developers should be able to modify existing functionality quickly and confidently (i.e. without side effects)
- Testability – Complex responsibilities of the user interface can be made to demonstrate their faults through testing. At least 40% of the cost of developing well-engineered systems is taken up by testing
- Performance – Application performance does not impact developer productivity (at least not directly) however getting to market fast with poor performing application will be a total failure. Hence the User Interface should respond to user request in acceptable time limits. This includes generating and rendering views, a step in workflow and completing a transaction. There are various other quality attributes such as Security, Availability and Scalability. However they generally do not have a significant impact on time-to-market.
A typical user interface architecture complies with a Model-View-Controller triad architecture. The Controller is responsible for decoupling View from the Model and vice versa. View is responsible for displaying and enabling interactive user interface(s) for a specific workflow (i.e. one View per workflow). Model is responsible for providing View (workflow) agnostic data and operations on the domain entities. For enterprise applications, CRUD workflows are considered as primary use cases.

-
Controller
- Serves requested resources by View
- Retrieves Model requested by the View
- Serves new View for the requested workflow
- Gate keeping:
- Access validation for requested service (Model, Resources etc)
- Sanitizes input parameters
- (De)serialization of input/output
-
Model
- Encapsulates Domain Model
- Authenticates operations (CRUD) on Domain Model
-
View
- Creating and rendering Widgets to display Model(s) in appropriate format
- Internationalization: display various values such as text, dates and currencies according to user locale
- Workflow navigation
- Maintains View State
- Presentation logic to for interactive experience
- Notifying Controller when user switches to a different Workflow
Above explains how I have used MVC. Have you used it exactly the same way? Search the web for MVC images and you will find various different diagrams. Additionally, with the evolution of single-page apps, some client-side MVC frameworks have emerged. How does controller provides gatekeeping on client-side? These are not MVC frameworks but rather modifications to the original MVC and they solve different set of problems in UI architectures.
There are three big issues for building and maintaining “interactive” user interface development:

- State – the current data snapshot of your user interface. Based on the state, a specific user action (such as clicking a button) will have different results. The more states a view has the more complex user interface code is.
- Logic – Any piece of code that modifies the view (such as enabling a checkbox) is presentation logic. Furthermore, it actively uses view State to make its decisions.
- Synchronization – User interface co-ordinates synchronization of data between UI elements (such as text boxes and tables) and business objects (Model).
For the remainder of this wiki, these complexities are referred as “big three”.
What about the actual display? Isn’t that complex? Display here refers to the layout (Vertical, Side-by-side etc) and widgets (textbox, checkbox, labels, tables etc). Display is not that complicated! Writing an html input tag for a textbox is a simple piece of code. Even enabling/disabling the textbox is one simple API or CSS class modification. Widgets in use have their APIs tested by the widget provider. What needs testing is the logic that will decide when the textbox should be enabled or disabled. So in order to boost and maintain development productivity we must simplify:
- coding and maintaining presentation state, logic and synchronization
- separate humble pieces of code (Display) from complex ones (the big three)
- further separate the big three from each other so that they can unit tested
The above three are the guiding principles for the “View” architecture defined below.
-
Model-View-Controller (MVC)
- Logic is stored in the Controller
- State is managed by the View
- Synchronization is managed by the Controller
- For every user interaction, the Controller receives the call. Developer does not have to write code to make this happen; it is configured rather than coded.
- View pushes the values/data to the Controller; Controller does not access the View to receive data. This includes View’s State.
- Controller manages the application workflow: even if the same View is next View in workflow, Controller shows the same View to the user.
-
Model-View-Presenter (MVP)
- State is managed by the View
- Logic and Synchronization in Presenter
- View does not know its Presenter
- View is dumb of any user interaction; it is responsible for defining the layout, widgets and knows how to interact with widgets
- All user interaction events are defined in the View and propagated to Presenter using events
- Presenter reads State from View and executes logic which may result in data synchronization or invoking methods on the View or both
- One Presenter per View
- Presenter has no knowledge of concrete widgets in use by the View (such as Select List vs. Radio buttons)
-
Presentation Model
- State and Logic in Presenter
- Synchronization in View
- Presenter referred as “Presentation Model”
- View knows the Presenter; Presenter is unaware of the View
- View observes the Model and performs synchronization accordingly (Persistence Layer and Widgets)
- View receives all user interactions but propagates them to Presentation Model
- Presentation Model does not have workflow logic; it returns control back to the View
There are different flavors of MVC, MVP and PM such as Passive View (MVP), Supervising Controller (MVP), PresentationModel (PM), ViewModel (MVVM) or “cook your own”. However two things are worth noticing:
- Their goal is reduce complexity by separating the big three
- All styles have Model and View
- Controller is replaced by Presenter; Community has stopped its efforts on dragging Controller.
In old systems, Controller was responsible for handling user interactions because reading input from devices was part of the complexity (such as interrupts for keyboard, mouse etc). For old web based applications, same pattern was used as handling user interactions was more than just difficult. This is however no longer an issue and user interactions should be handled on the client-side.
Presenter is not Controller – so is "Presenter another name for a Controller that executes on client-side”? Not really! Presenter does not contain information on different steps in a specific workflow where as a Controller also contains them.
Of course we can (and we do) always have Controller drive workflows, manage some (or most?) of user interactions and leave the remaining user interactions to the View. However instead of solving the big three, this approach further complicates them: View still has all State management while synchronization and logic is sprinkled all over Controller and View. One possible answered could be that we divide user interactions and synchronization into two categories and allocate each to Controller and View. Such division is most likely based on User Experiences hence will differ from application to application if they differ in experiences. Even if they are same in experiences, this prohibits upgrades to user experiences. Seems like we have another good principle to add our list: “UI Architecture should be agnostic of User Experiences” or “UI Architecture should promote easy upgrades to new experiences”
The “View” component of our High Level Architecture must meet the following requirements:
- Separate View State, Presentation Logic and Model Synchronization (the big three) from each other so that
-
Their code can be managed separately -
They can be mocked and unit tested easily - Isolate layout and widget interaction from the big three so that
-
Unit testing State, Logic and Synchronization does not require simulating Widgets and its events -
Widget upgrades should not require modifications to the big threes - Promotes upgrades to User Experiences without affecting the Architecture
Our View Architecture is a collage of Presentation Model and Controller in MVC. (after all this debate, surprisingly it is still useful!). We reveal the architecture in couple of steps.
Presenter contains the presentation “logic” and knowledge on when to “synchronize” data between View and the persistence layer (Model). It orchestrates the View by directly calling useful methods on the View. It observes the View for interested user interactions such as button click. When needed, Presenter instructs Model to synchronize data (CRUD).

View has following properties:
- It is humble: contains semantic-less code to generate layout and inject appropriate widgets
- It is passive: View does not initiate any sort of action unless told by the presenter to do so. This includes rendering, modification to View’s widgets and so on. View knows the data elements of the Model. It uses this knowledge for data binding with its widgets. Hence data formatting is also performed by the View. Additionally, there can be more than one Model utilized by the View.
Model
- Lives on client
- Composed of one or multiple Domain Entities (often a subset of business domain entities)
- Contains the data fields required by the View
- Has knowledge of persistence layer i.e. communication mechanism, allowed operations and named services (depending on the technology stack)
Following are the “don’ts”:
- Presenter does not know anything about the persistence layer
- View does not know the Presenter
- Model does not know the Presenter and the View utilizing it
- Model is not as same as conventional “Model” referred in MVC i.e. it does not live on server; does not represent business layer
With this description of the three components, we have isolated:
- Synchronization (location): persistence layer location and allowed operations resides solely in Model
- Logic (View modifications): lives in Presenter alone
- Logic (Sync): decision to synchronize persistence data between Model and View is performed by presentation logic. Since this is logic, it lives in Presenter alone.
- Layout and Widgets: resides only in View
What about View “State”?
A View’s “State” is only consumed by its Logic. To illustrate its use, we’ll use a simple example: Consider a form that has a checkbox widget along with other widgets. What makes our checkbox special from other widgets is that based on its value (checked/unchecked or true/false), certain other widgets must be disabled/enabled and other widgets must be injected into the View. Hence our Presenter would love to get quick access to the value of this checkbox. However, this was a simple example. It is not too surprising that a View’s State is often determined by a set of values i.e. multiple widgets. This could easily lead to code complexity based on the permutations. Meet “Presentation Model”! (For clarity, other components are not shown from Step 1)

Presentation Model stores interested up-to-date values from View. This means it does not store values from all the fields; only the fields which determine the View’s State. The PM is created by the Presenter and passed to the View on initialization. From here, View updates the field values of PM whenever the values of registered widgets change. PM encapsulates the code which determines the current State. Presenter observes the PM for State changes only; it is not interested in individual field values. Presentation Model is unaware of the View and Presenter. Notice that the “Model” from Step 1 is now “Data Model”. This is only a name change and does not impact the aforementioned responsibilities of Model. The Presentation Model does not synchronize with Data Model. There is a concern that some fields in both Models will be same i.e. from our example of checkbox in the form, the checkbox contains the value that is actually stored in persistence layer. However the code to set/get values from Model is too simple to introduce pollution of Presentation State in Data Model. With Presentation Model, we have now covered the big three plus separation of non-complex code. However before we announce completion of our View component architecture, there is one responsibility missing: workflow navigation.
A workflow consists of one or more views stitched together in a meaningful sequence to aid users’ achieve their goal. The so far described View architecture is per View i.e. if a workflow consists of two distinct Views, e.g. one for listing a model and another to edit model, we will have two distinct set of above components:
- 1) Displaying list of entities: EntityListModel, EntityListView, EntityListPresenter and EntityListPM
- 2) Editing Entity: EntityModel, EntityView, EntityPresenter and EntityPM
In 1) when the user interacts with the widget (e.g. hyperlink) to edit the entity, the EntityListPresenter is unaware of this interaction. EntityListPresenter is unaware of the components in 2). Recall the difference between a Controller and Presenter: Controller has knowledge of a workflow i.e. user interactions which require different views in the workflow while the Presenter knows the user interaction that modify its own view.

The Controller knows the inputs and outputs of a step (view) in a workflow and has information on the next step (view) in that workflow. For each step, it knows which View and Presenter serves the step i.e. it creates the View and Presenter objects and passes the View object to the Presenter. However its is tempting, there is no need for the Controller to know the Model used by the step. Following figure shows the interactions for the example described above in this section.

At this point, the definition of View (step) in the workflow becomes stricter: A View is composed of multiple first class widgets (foundation or synthetic) and covers the content area controlled by the Controller. To illustrate the need for this definition, we go back to our example and provide two different flavors of User Experience.
-
1 - First Experience
- a - List of Entities are displayed in table in the View
- b - When the user clicks the hyperlink to edit an entity, list view should no longer be visible and the edit form is embedded in place of list view
-
2 - Second Experience
- a - List of Entities are displayed in table in the View (same as first experience)
- b - When the user clicks the hyperlink to edit an entity, the edit form is displayed below the list view. List view is still visible and user can click on a different entity to edit
- c - Upon Save action, the data must be synchronized with the persistence layer, the edit form should no longer be visible and the modified entity row in the table should reflect the updated values
- d - Upon Cancel action, the edit form should not be visible and the view should return to its previous state
So the obvious question is: Both experiences have two steps in this workflow. Instead of defining Views as steps in a workflow, it is less complicated to define them as displays controlled by Controller. Given this definition, the navigation between a) and b) of first experience is controlled by Controller whereas a) and b) of second experience is not considered workflow navigation rather a single view composed of a table widget and composite form. A single Presenter orchestrates 2b, 2c, and 2d.
What about reusability? In CRUD workflows, typically modifications and deletion functionality is provided from one single location so it is hard to imagine reusing the edit form in more than one place. However, it is not so uncommon to lookup/search entities from multiple views. For example, consider two entities in an Employee Management system. System defines Academic Degree as a general entity and allows zero or more to be associated to an Employee. The system administrator is provided a user interface that allows for CRUD operations for Academic Degree. While the edit form for employee allows associating multiple Academic Degrees. It would be useful if the lookup/search component from the CRUD of Academic Degree can be reused in Employee edit form. So how do we meet this much needed requirement? Simple answer: Widgets!
For simplicity, it is useful to divide Widgets into two categories: Foundational Widgets and Synthetic Widgets. A Foundational widget is provided by the environment itself such as for web they are textbox, checkbox, radio button, button, label, select list and other html tags like table can also be considered as foundational widgets. These widgets have predefined styling attributes and supported events. A Synthetic widget is composed of one or more foundational widgets and possibly other synthetic widgets. Though the user of a synthetic widget can directly access the containing widgets (at least in html), it can lead to issues when widget receives upgrades. A well defined synthetic widget encapsulates the containing widgets and provides useful API as well as event targets for its user. A View in our architecture is also a Synthetic Widget. How it handles the presentation logic, state and other complexities are of no interest to its consumer i.e. other Views. However, to utilize the View we must encapsulate View, Presenter and accompanying components in a Widget component.

Following are the responsibilities of the Widget component:
- Encapsulate View, Presenter, Presentation Model and Model
- Create View and Presenter objects internally and pass the View to Presenter (just as Controller does it)
- Hide under-the-hood events and stop them from bubbling up to consuming View/Widget
- Provide Event subscription to itself

Next comes “Controller” of high-level architecture. The responsibility of this component is to provide switching between workflows. The controller described in View’s architecture is a page level controller that has knowledge of various steps (pages) within a workflow. The high level Controller knows about these View Controllers i.e. which Page Level Controller is needed for a specific workflow. Just as with View’s Controller, the Application Controller is also configured rather than coded. Model component will have significantly fewer lines of code compared to View. Depending on the Business Layer and complexity of Domain Model, the Model will act as adaptor to convert Domain Entities into View Model and vice versa. This is needed to reduce chattiness between View Model and Server and also to reduce the payload. “View Model” will talk to “Server Controller” to synchronize with Persistence layer. Hence the connection from “View Model” to “Business Layer” can be modified to point to Application Controller.
Reference Application - PresentationModel in pure JavaScript
Download and deploy the reference app. The stack uses YUI3's App Framework and Node.js to provide sample implementation of proposed architecture. NOTE: all data is static (no db!) and this is purely for demonstration purposes. Following are the client-side components and their interactions:

