All of the major programming languages have evolved tremendously over the past decade especially to make the developers job easy. C# by Microsoft has been at the top of the game of adding plethora of easy to use and extremely powerful constructs ranging from async programming to functional programming. The well-developed programming languages have made it extremely easy for beginners to pick up coding and start developing applications quickly.
However, when developing extensible applications for the future, just using the language to write down logic for applications does not do the job well. We have to think about the overall design of the application for it to be able to scale and extend well. This means utilizing appropriate design patterns wherever applicable.
I recently had a first-hand experience of how the of use appropriate design-patterns can be a lifesaver for any application, and thought to share this experience for the benefit of others. The first software application that I developed at Concurrency as an intern working with Min Maung (Technical Architect at Concurrency) was a WPF (Windows Presentation Foundation) application, which would enable users to view, edit, update and create new configurations (JSON configuration) crucial for another project. The Json configuration was a complex object consisting complex properties like Array of objects, Enumerations etc. My first task at hand was to allow the user to open a single configuration file and provide the basic CRUD operations on that file. Below is a screenshot of the UI for your understanding.
This functionality was easy to develop especially because of the presence of DataContext and Variable Bindings in WPF. What came next was a big challenge. Min asked me to add another feature where the user can select a Directory from File menu, and the application should open all the valid configuration files in new Tabs and the existing functionality remains the same per Tab. So, what's the big deal?
The problem was that I had bound a single Config object as the DataContext of the View. For the Open-Directory functionality, the View remains same for all config objects but had to be bound with different Config objects (different data). Since the DataContext of the View was bound directly to the Config object from code-behind, it was not possible to add new List elements to the Tab to reuse the View.
This application-extensibility issue occurred at the first place because the application was not designed properly. Even though I had followed the best-practices for C#, wrote superior logic for the code-behind, it was not scalable. Note: Scalability here refers to the Application feature scalability rather than scaling for load or Infrastructure Scalability.
What to do? Who will rescue?
MVVM Design pattern came to my rescue. As explained above, the problem came because the View was tightly coupled with the Model and made it impossible to reuse View. MVVM solves this problem as it is based on the "Separation of Concern" Principle. MVVM stands for "Model View ViewModel" where each component is designed to handle a single responsibility. Model refers to the business/domain model which should be handling the data coming from any back-end service or a database. View is the User Interface component and only deals with the layout and design of the UI. ViewModel is an abstraction of the View exposing public properties and commands, and represents the state of the data as required by the View. MVVM was specifically designed to simplify event-driven programming of User-Interfaces and was later incorporated into Windows Presentation Foundation (WPF).
Utilizing the MVVM design pattern, I was able to easily implement the required Open all configs in a Directory folder, but of course I had to redesign the whole application. Below is a screenshot of the required feature developed using MVVM design pattern:
The main purpose of this blog was to highlight the importance of Design Patterns while developing large-scale, maintainable and high-quality applications. At the same time, developers should keep in mind that each design pattern is designed for only one specific purpose. Forcing design patterns or using the wrong one at the wrong place can over-complicate the code and induce difficult to solve bugs. The right judgement comes from experience. So next time you are working on any application, do think about design patterns!