On my current project, we are applying the Open Close Principle in our architecture. Some of inspiration for this came from Ayende’s post Composite Architecture – The Open Close Principle as applied to system architecture. In part of his post, he writes about how each new feature was implemented with new code and didn’t require touching existing code.
Applying this principal to our project has been working out very well. For example, we are using the specification pattern with our repositories. As a result we no longer need to add new methods to our repositories every time a new requirement comes along where we need to apply a different criteria. We are having similar successes in other parts of our project.
One area where we haven’t been as successful is with our controllers. When adding new features, there were many instances where we needed to add methods to existing controllers. At times, these new methods would also add new dependencies to the controller. Basically, the source for our controllers is not closed for changes.
As an alternative, we started looking at mapping each URL or action to a ControllerAction class. For example, the URL /register/form would map to the RegisterFormAction class. By default, action classes execute the method that matches the request type (GET, POST, PUT, etc …). So if the request is a GET request, then the Get method is executed. If there are any parameters for the Get method, they are mapped to the values passed in the query string. The following is code for a sample action.
// url: ~/register/form public class RegisterFormAction : ControllerAction
{
private readonly IRepository<Class> m_classRepository;
public RegisterFormAction(IRepository<Class> classRepository)
{
m_classRepository = classRepository;
}
public ActionResult Get()
{
var model = new RegistrationForm(); return ShowForm(model);
}
public ActionResult Post(RegistrationForm model)
{
if (!ModelState.IsValid)
{
return ShowForm(model); } // TODO: map and save registration // redirect to ~/registration/confirmation
return RedirectToAction("Confirmation"); } private ActionResult ShowForm(RegistrationModel model)
{
var filter = new ActiveClassFilter();
model.Classes = m_classRepository.FetchFor( filter, OrderBy<Class>(c => c.ClassName));
return View(model);
} }
We are still debating whether we want to go this route in our project. The debate typically centers around these two questions: Are we going to far in applying the Open Closed principal? Or, are we just afraid to break from the ASP.NET MVC convention of having controller classes? I’m starting to lean towards the latter.
I also noticed the other people are looking in the same direction. Recently, Chad Myers blogged about Going Controller-less in MVC: The Way Fowler Meant It To Be. It’s always nice to know that other people are thinking the same way you are
If we decide to go this route, I add more posts detailing what we implement. Until then, I love to know what other people think.
Hey,
I really like this and have been using jeffrey pallermo’s simple implementation for the last few days.
Its much easier to organise, and makes so much more sense.
Would like to see your implementation when it’s ready.
Adam
As for implementation, I haven’t got any further than some code written in Notepad++. Right now I am looking at Pallermo’s code. If we decide to write something, I’ll be sure to post about it.
[...] 9, 2009 by mscarman Last month I posted about separating actions into their own classes. Recently, I got a chance to try this concept out on a small project. The results, so far, have [...]