In
Nugget 9, a simple Blazor application was created using scaffolding with Entity Framework. This Nugget is about using the
MVVM Design Pattern in this application. Yes, I am squeezing this little app for all it's got!
Why bother? You might ask. The simple answer is "Separation of Concerns". Applying this pattern to this simple app implies subdividing it into distinct sections, each responsible for a specific aspect or concern.
This design pattern offers numerous advantages, allowing different aspects of the application to be developed separately. It improves readability, maintainability, reusability, and, one of the most important, and sometimes overlooked, testability.
MVVM
In the Model-View-VideModel, the Model is an abstraction representing the data of the application. This data could be from the database or provided by an API, or service, or a combination of sources.
The ViewModel contains properties, business logic, and event handlers that the View binds to. The ViewModel also notifies the View that it needs to update through notification updates. This is where user input is validated and UI events and commands that respond to user actions are processed. For example, filtering of data and searches. The ViewModel is in communication with the Model to get the data it needs.
The View is the visible part of the app, containing all UI elements. The view should not contain any business logic.
Decoupling Index.razor Presentation from Its Code
Applying a design pattern to an application after the fact could be challenging. Because this app is very small, this could be done easily.
View-ViewModel
To start decoupling the component's view and its code, a ViewModels directory was created under the JobPostPages component, and three files were added: IIndexViewModel, IndexViewModel, and JobPostViewModel.
IIndexViewModel is an interface abstraction defining the behaviors and properties of the ViewModel when this interface is implemented in IndexViewModel.
Note that all the business logic that exists in Index.razor
Nugget 9, has been moved to the ViewModel. This includes the filtering properties and event handlers. Decoupling the logic from the view leaves behind a lean view in Index.razor. The binding now is to the ViewModel.
Note that in the view, the ViewModel is not used directly but its Interface. The ViewModel interface is injected in line 4 of the View.
ASP.Net Core supports the dependency injection (DI) software design pattern, a technique to achieve IoC or Inversion of Control. This is the Dependency Inversion Principle in SOLID, which allows an external framework to manage the creation of dependencies. Note IndexViewModel gets the DbFactory injected thanks to this mechanism.
The other class in the ViewModels directory is the JobPostViewModel I should rename this class JobPostIndexViewModel to differentiate it from the ViewModel for the Create and Edit views. This ViewModel models the Model JobPost, and it does not need all the properties and it is a plain POCO.
Conclusion
In this post, using a design pattern, the View and the ViewModel of the Index component have been decoupled. This is a very simple solution, however, this exercise shows its advantages. The solution is more readable. It also shows that the ViewModel can now be tested.
You might think that this is not a pure MVVM design pattern implementation and that it resembles the MVP (Model View Presenter) design pattern. The fact is that these design patterns are closely related and pursue the same objectives: Single Responsibility Principle, the big S of SOLID.
References
Comments
Post a Comment