Extreme ASP.NET Makeover: Separation of Concerns - Overview
Separation of concerns is a concept that, when applied to software development, deals with creating distance between dissimilar aspects of your code. This may seem like a complicated statement, but we all have dealt with it in the past, even if we haven’t known it. You’ve probably heard that you shouldn’t have your data access code in your Web page. That is separation of concerns. The Web page shouldn’t directly know how to deal with database concerns like connection strings, command objects, and so on.
Why do we care? Well, separation of concerns is one of the concepts that allows us to work on a specific aspect of an application without having significant impact on other parts of the application. Think of it this way: Should I be able to work on the engine in my car without having to deal with the wheels? In our software, we shouldn’t have to deal with the database infrastructure when we’re working in aspx.cs (or aspx.vb) files.
If we aren’t paying attention to separation of concerns, we would start seeing some common issues while working on our codebases. We’ve all been in a situation where you try to change what appears to be a little thing and end up having to dive deep into the bowels of your application’s infrastructure. To take a quick example, say you wanted to change how you determine what the user is authorized to do on a page. In ScrewTurn, permissions are determined through a call to the AuthChecker singleton class. (We’ll discuss how to cure “singletonitis” in an upcoming article. For now, we’ll focus on separation of concerns.) To determine if the user has permission to download an attachment, for example, we make the following call:
If we look at this one line of code on its own, nothing immediately appears to be a problem. But let’s imagine that this call exists in many, or all, of the Web pages in the application. What we see then is that changing how you determine a user’s ability to download attachments will require you to modify each and every one of those Web pages. That is, there is a ripple effect of one change imposing the need to modify nonrelated code.
There is another issue at play here. Consider the amount of intimate detail about authorization that exists in the application. A good example is the Page_Load method in the Default.aspx.cs file. In Page_Load, there are calls for security information for a given user, including the following:
Can the user view a page?
Can the user download attachments on a page?
Can the user set permissions?
Can the user administer a page?
Can the user view discussions on a page?
Can the user post to discussions on a page?
Can the user manage discussions on a page?
Can the user edit a page?
This is a lot of authorization for the Page_Load method to have to know about. Of course, the Page_Load method does need to retrieve and use this information. But our question is this: Does it need to know how to retrieve all of those pieces of information? And just as important, does it need to be done for each individual task that could be performed? Asked a different way, does Page_Load need to have a full understanding of how security is being handled? No, it doesn’t. Can it simply ask some other class to have all security information given to it? Yes, it can! Page_Load simply needs to get the permissions, and it shouldn’t know or care about the mechanics of how this is accomplished.
Warning: Code Maintenance Ahead
The ultimate goal when applying separation of concerns is maintainability. This being a brownfield application, ScrewTurn Wiki likely has areas that are hard to work with because classes are doing too much and have become fragile. The slightest change to one class has ripple effects throughout the code. By separating concerns, we can break apart the code into its individual pieces so that when you look at a class, you aren’t distracted by extra code that is not part of its responsibility.
This is a good segue into one of the ways you can start separating concerns in your classes. Like many things in our craft, knowing when separation of concerns has been broken is not easy to see. There is one simple thing you can ask yourself when you look at any piece of code:
Does this code belong in this class?
Or put another way:
Is this part of the class’s immediate responsibility?
The idea of responsibility is an important one. When we start thinking of separation of concerns and of classes having responsibility, we gravitate toward the Single Responsibility Principle:
A class should have only one reason to change. – Robert C. Martin in Agile Software Development: Principles, Patterns, and Practices
Earlier, when we were discussing the contents of the Page_Load method in the Default.aspx.cs file, we proposed asking the question, “Does it need to know how to retrieve all of those pieces of information individually?” In our case, the answer should be no. The Page_Load method should know only that it needs to retrieve authorization information, not the gory details of how that information is retrieved. Separating those two needs is at the root of determining separation of concerns.
There’s yet another good reason to try to separate concerns in your application. In a previous article, we mentioned user interface testing with WatiN. If you’ve tried setting up UI testing, you’ll quickly discover that it can become cumbersome to create this safety net. The tests are slow and often need to be reworked as the UI changes. By moving code out of the ASPX pages and into separate classes, we open up the testing arena and are able to write true unit tests, ones that test only a single class in isolation, without having to fire up a browser instance, Web server, and database. These tests are faster, less fragile, and can lead us to a place where the code in the ASPX pages is limited to interaction between the various UI widgets.
From Principles to Practice
Enough talk. Let’s take this and apply it to the ScrewTurn Wiki codebase. First, we’ll start with the Default.aspx page’s code behind file. To make things easy, we will start at the top and look at the contents of the Page_Load. This is a busy method and not uncommon for a brownfield application. In this method alone, we can see several responsibilities:
Redirect the page if necessary
Determine the user’s rights for the page
Set up various UI widgets
Display the contents of the requested wiki page
Other videos from this article
Read the full article at http://msdn.microsoft.com/en-us/magazine/ee210417