Learning Angular is not that hard, you can easily learn its fundamentals within a week. But when you entered the real world and start to build or working on a live application, it becomes quite hard to maintain the form/structure of the application. The complexity of your application will increase and the frequency of reusability of the component will increase as well. So, to overcome this problem we have to find a pattern which can help us to maintain it.
How do you know your application is more complicated?
A complex application contains atleast these traits:
- Multiple components that contain the same kind of code.
- High amounts of the component.
- The high-frequency rate of application state updating.
- Components that contain a high amount of code
And we want our application to be maintainable, scalable, and testable with a high-performance rate. Complex application barely has some of these traits.
Separation of concerns
Separation of concerns is a kind of compartmentalization of our application. By using separation of concerns we can focus on a single concern at a time. we can say that the separation of concerns is an architectural disciple.
Fig: Horizontal layers in model-view-presenter
There are two ways to slice our application: vertically, horizontally. We will have to group software artifacts by feature while slicing vertically, and horizontally we will have to group by a software layer.
This same thing can be applied to our angular components. We will only have to be concerned about the presentation and user interaction layers. This process might require a lot of attention and discipline as we are adding a layer of abstraction but in the end, it's all worth it. Just remember we are only creating an abstraction that should have been there in the first place.
The Model-View-Presenter pattern
Model-view-presenter is a kind of an architectural software design pattern that can help us to implement the user interface (UI) of an application. We can minimize complex logic in classes, function, and modules by the use of Model-View-Presenter. It's something like an MVC structure, it will separate presentation from the domain model.
We will only find data binding and widget composition in the view, it will not have any kind of logic or behavior. It will delegate control to a presenter when the user interacts with our application.
The Angular variation
Just like the original Model-View-Presenter patterns and variations, we will create software artifacts that are well-fitted for the Angular platform.
As we know the angular component only focuses on presentation and user interaction. We will have to make sure that our main focus is presenting a piece of the application's particular state to the user and enabling users to affect that state. We will connect our presenter to the model and the view using the observables, as a result, we will have presenters that can be tested in isolation from their view.
Model-View-Presenter concepts for Angular
To use the Model-View-Presenter pattern in an Angular application, we will have to see concepts that are mostly inspired by the React community. Let's divide it into three categories.
- Presentational components
- Container component
- Mixed component
In presentational components, we will only have presentational and interactive views. They will only present a piece of the application state to the viewer/user and will enable them to affect its state.
Presentational components are not aware of any other parts which are available in the application with the exception of presenters. They will have a data-binding API that will describe the user interactions that they will handle and the data which will be required.
We will have to keep the complexity of presentational components to an absolute minimum, which will remove most of the reasons for unit testing in the UI.
Container components will help to expose pieces of application state to the presentational components. Container components will translate component-specific events to commands and queries for non-presentational layers by integrating the presentational layer with our application.
Normally we have a 1 to 1 relationship with container components and presentational components. The container component contains a class property that matches the input properties of its presentational component and methods which will respond to the events that are emitted through the presentational component's output properties.
When a component is not either a container component or a presentational component, it's a mixed component. This component contains mixed system concerns: they have logic that belongs in multiple horizontal layers. If you have an existing application, there is a high chance that it consists of mixed components.
While grouping all logic in a single place, it will make your application hard to test, a compilation of reusing components will increase.
To get a simple presentational component, behavior logic and complex presentational logic will be extracted from the presenter. There is no UI in the presenter and also there are almost zero or a few injected dependencies, which makes it easy to test. The presenter is barely aware of other fundamental/logic of the rest of the application. Normally one presentational component references a presenter.
The Model-View-Presenter triad
Fig: Model-view-presenter triad for an angular
: One-stop-oplossing voor Angular-webontwikkeling ?
Uw zoekopdracht eindigt hier.
As we can see in the figure, those three software artifacts combined make the Model-view-presenter triad. The model will be represented by the container component and the application state that will be displayed to the user for them to browse and alter.
The view will be represented by presentational components, a user interface that will present the application state and translates the user interaction to a component-specific event, which will often end up redirecting the control flow to the presenter.
In other words, presenters are usually an interface that is unaware of the rest of the application.
We can understand it with some Gif examples.
Fig: Data flow
We can see the state of application changes that occurred in the service in the figure. The container component will be notified because it has subscribed to an observable property in the service.
The container component will transform the emitted value into a decent shape which is most convenient for the presentational component. In the presentational component, new values will be assigned and references will be bound to the input properties.
So now the presentational component will pass that updated data to the presenter which will recalculate additional properties used in the presentational component template.
Now the data flow is completed and Angular will renders the updated DOM, displaying it to the user in a list.
Fig: Reverse data flow
By using the Model-View-Presenter pattern we can increase the separation of concern, maintainability, testability, and scalability in our complex Angular application with the use of container components, presentational components, and the presenters.