Join Jess Chadwick for an in-depth discussion in this video Using loose coupling for maintainability, part of ASP.NET Core: Razor Pages.
- [Instructor] Now that I've shown you how to easily and effectively integrate code and markup together, I also need to explain the patterns and techniques that will help you build applications that are not only easy to write at first, but also, easy to maintain after years of enhancements and hundreds or thousand more lines of code have been added to them. Though there are a variety of software design principles available to help us create maintainable applications, the ones that are perhaps most important are those that encourage what's called separation of concerns.
Put simply, separation of concerns means that your application is built in such a way that each component focuses on doing one thing well, and is generally not concerned or dependent upon how other components work, even when they have to interact with those other components in order to create a fully functional application. The amount or extent that one component depends upon another component is called coupling and you can think of coupling as a spectrum between tight and loose coupling.
The more components depend on each other, or know about one another, the more tightly coupled they are. The less they know about each other, the more loosely coupled they are. For a great example of loose coupling, look inside any electronic device at its circuit board. This board consists of many different components, resistors, capacitors, integrated circuits, et cetera, that don't do much individually and don't directly depend on the existence of any other component in order to function in isolation.
However, when you put them all together in the correct way, you create a fully working system that is far more than the sum of its parts. Not to mention, most of those parts can be easily replaced or even upgraded without effecting the rest of the system. The general opinion in the software industry is that loose coupling helps make your application easy to change over time without a high risk of changes to one component breaking other components in the application.
To be fair, however, many techniques for loose coupling do tend to rely on abstractions that introduce more classes into your application, and when application logic is spread throughout multiple files, that may actually make code more difficult to follow than just having everything in one place. Consider the development model that initially launched with ASP.NET Core, the ASP.NET Core MVC, or Model View Controller framework.
This framework claims separation of concerns as its top design principle and forces web requests to funnel logic through a Controller class for that Controller to tell the framework which View to display and for the framework to locate and execute the View to be rendered to the response. The framework demands that each of these steps be strictly independent of each other, so developers are encouraged to keep processing logic in the Controller and keep the View ignorant of where that data it renders came from.
Compare that to the Razor Pages development model, which promotes a simpler and more direct approach of keeping the markup and logic close together, and using the physical location of the View to determine the page's URL. This logic and markup can be combined in the same page, like I've been showing, or kept as a separate View and Class files, which I'll show later on. However, just because the View and logic are meant to live more closely together, doesn't mean that you have to write tightly coupled code.
There are plenty of ways to strike a good balance to keep your pages loosely coupled, and in fact, I've already shown two of them. Almost from the very beginning, I've been retrieving data from a database to display in my Razor Pages, however, I never contacted the database directly. My pages never even knew that my implementation was using into the framework. That's because all my pages ever depended on was my Recipes service class, an implementation that focused solely on working with the Recipe model.
Heck, I even used an interface as the type of the service property to decouple it even further. The other loose coupling technique that I've shown is the introduction of a shared layout that all of my pages in this site will use. Though on the surface, all this approach really seems to do is put the shared markup in one place so that it doesn't have to be repeated everywhere, what's actually going on here is a true separation of concerns. The layout doesn't really care about the actual content of the pages that it's wrapping, and the individual pages don't really care about the markup that they're being wrapped in, but even with this approach, you still have to be careful adding things like sections and view data properties does increase the coupling between the layout and the pages that live inside it.
So, try to keep those at a minimum in order to keep the coupling low. In this chapter, I'll introduce you to two more ways to keep your pages loosely coupled. First, I'll show you how to separate your page's code into a separate class called a page model. Then, I'll show you how to leverage a technique called dependency injection to allow your pages to depend on abstractions rather than having the responsibility of creating and managing their own instances of the components they depend on.
By using all of these techniques and just generally keeping an eye on how much components interact with and know about each other, you can keep the coupling in your application to a minimum. Not to mention, if you ever feel as though you have a use case that's more complex than most, keep in mind that you're still operating in an ASP.NET Core MVC application under the hood and you're free to combine both the MVC and Razor Pages models in the same exact site.
- Creating a new application
- Setting up pages
- Rendering dynamic content
- Reusing markup with layouts
- Increasing the maintainability of pages
- Processing data
- Validating input
- Securing an application