OCP Example

Agile Joe (Joe Ocampo) has a good post on the ‘Open Closed Principle’:

“The open closed principle is one of the oldest principles of Object Oriented Design. I won’t bore you with the history since you can find countless articles out on the net. But if you want a really comprehensive read please checkout Robert Martin’s excellent write up on the subject.

The open closed principle can be summoned up in the following statement.

open/closed principle states “software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification”;[1] that is, such an entity can allow its behavior to be modified without altering its source code.

Sounds easy enough but many developers seem to miss the mark on actually implementing this simple extensible approach. I don’t think it is a matter of skill set as much as I feel that they have never been taught how to approach applying OCP to class design.”

Read the full post here.


Advertisements

Partial page updates with jQuery and MS MVC

Just a quick and dirty, as I’m not going to go into all the details of neither jQuery nor MS MVC.  But I wanted to show a easy way to use jQuery to get ajax callbacks with MS MVC.

In my View I have a select tag as follows:

<%= Html.Select("selectList", ViewData.AirSummaryList, "PilotName", "ID") %> 
 

This is data that is bound to the list.  In the header of the View I have a call setup to make the ajax call:

$(document).ready(function(){
          $("#selectList").change(function(e){
               $("#selectList option:selected").each(function(){
                    var t = $(this).text()
                    $.post("/Home/AJAXTest", {
                        content: t
                    },function(txt){
                         $('#showResults').html(txt).show();
                    });


            });
          });
      });

The “/Home/AJAXTest” is a call to the HomeController and the AJAXTest action.  Content ‘t’ is the data being passed to the action:

public void AJAXTest(string content)
        {
            PassThroughData data = new PassThroughData();
            data.Name = content;
            RenderView("ViewUserControl1", data);
        }

I have created a new ‘MS MVC User Control’ and the data will be sent to this ‘control’ and rendered inside the ‘showResults’ div (see javascript above), as well as a structure to pass the data with (I prefer this route):

public partial class ViewUserControl1 : System.Web.Mvc.ViewUserControl<PassThroughData>
    {
    }

    public struct PassThroughData
    {
        public string Name{get;set;}
    }

With the ViewData being set to ‘PassThroughData’, inside the control’s view it’s easy to display the data:

Hello <%= ViewData.Name %>

I like this way of handling callbacks with MS MVC.  jQuery makes it fairly easy to use as well.

Note: you can use a ‘get’ as well :

 

$.get("/Home/AJAXTest", {
                        content: t
                    },function(txt){
                         $('#showResults').html(txt).show();
                    });

Also, just to show how your view could continue to use jQuery, inside the view that is loaded via the callback:

<script type="text/javascript">
$('#selectedPilot').click(function()
                        {
                           alert($(this).text());
                        });
</script>
<div id="selectedPilot"><i>You have selected</i> <b><%= ViewData.Name %></b></div>

Notes on running MS MVC on IIS 6 and migrating to MS MVC from Webforms

I took some steps to see how well MS MVC would coexist with Webforms on a hosted environment.  One of the things I really like about the new MS MVC is the ability to be run inside the same project/web application as webforms.  This will allow for a migration plan vs. just a complete total rewrite.

The first step was to add in the 3 assemblies required.  The assemblies in preview 2 were separated from the System.Web.Extensions, these assemblies are:

System.Web.Mvc (dependent on Routing)
System.Web.Routing (dependent on Abstractions)   <— note: this can be used outside of MS MVC
System.Web.Abstractions

Web.config updates:

Under ‘system.web’

<!-- MS MVC-->
      <namespaces>
        <add namespace="System.Web.Mvc"/>
        <add namespace="System.Web.Routing"/>
        <add namespace="System.Linq"/>
        <add namespace="System.Collections.Generic"/>
      </namespaces>

Under ‘assemblies’

<!-- MS MVC -->
      <add assembly="System.Web.Abstractions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <add assembly="System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

Under ‘httpModules’

  <!-- MS MVC -->
      <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

Under ‘system.webServer’

<!-- MS MVC -->
      <remove name="UrlRoutingModule"/>
      <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      
<add name="MvcScriptMap" preCondition="classicMode,bitness32" verb="*" path="*.mvc" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll"/>
      <add name="MvcScriptMap64" preCondition="classicMode,bitness64" verb="*" path="*.mvc" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll"/>
      

The next steps were done to the project structure:

Added a Controllers, Views, and Models folder

Updated the Global application (HttpApplication) to add routing:

protected void Session_Start(object sender, EventArgs e)
        {
            RegisterRoutes(RouteTable.Routes);
        }

public static void RegisterRoutes(RouteCollection routes)
        {
            // Note: Change the URL to "{controller}.mvc/{action}/{id}" to enable
            //       automatic support on IIS6 and IIS7 classic mode

see the note above:  when adding routes with IIS6 and II7 classic mode, you must include the .mvc (or any unique extension).  This is important.  Your host will also need to map .mvc to the ISAPI .net.  Although, as I hope to show, you can actually just use routing to get around this.

Here are some examples of my registered routes:

routes.Add(new Route("{controller}.mvc/{action}/{id}", new MvcRouteHandler())
            {
                Defaults = new RouteValueDictionary(new { action = "Index", id = "" }),
            });

            routes.Add(new Route("{controller}.mvc", new MvcRouteHandler())
            {
                Defaults = new RouteValueDictionary(new { action = "Index" }),
            });


            routes.Add(new Route("ViewMissionSummary.aspx", new MvcRouteHandler())
            {
                Defaults = new RouteValueDictionary(new { controller = "Mission", action = "ViewMissionSummary" }),
            });

Basically, the routing will let you intercept any call to a page and route it to a controller and action!  So in the above example for ‘ViewMissionSummary’, I took an existing page in Webforms and created a new controller, action and view.

Example controller:

namespace FSWeb.Controllers
{
    public class MissionController : FSController
    {
        public void ViewMissionSummary()
        {
            ICampaignDao campaignDao = DaoFactory.GetCampaignDao();
            TargetsDestroyed targets = campaignDao.GetCampaignData();

            IMissionDao missionDao = DaoFactory.GetMissionDao();
            MissionSummaryViewData summaryData = new MissionSummaryViewData();
            summaryData.MisSummary = missionDao.GetMissionSummariesForCurrentWeek();
            summaryData.CurrentCampaign = targets.CurrentCampaign;

            RenderView("ViewMissionSummary", summaryData);
        }
    }
}

To help with binding to the view I created a new ‘MissionSummaryViewData’ struct.  As you see above, the RenderView takes the name of the view and an object ‘viewData’.  The viewData is a way to attach a specific data structure type to a view

public struct MissionSummaryViewData
    {
        private List<MissionSummary> misSummary;
        private string currentCampaign;

        public List<MissionSummary> MisSummary
        {
            get { return misSummary; }
            set { misSummary = value; }
        }

        public string CurrentCampaign
        {
            get { return currentCampaign; }
            set { currentCampaign = value; }
        }
    }

On the view code behind I tell the ‘ViewMissionSummary’ view the data type I’m going to ‘attach’ to it, ie.

public partial class ViewMissionSummary : ViewPage<MissionSummaryViewData>
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            ViewMissionSummaryRepeater.DataSource = ViewData.MisSummary;
            ViewMissionSummaryRepeater.DataBind();
        }

        public static string ConvertData(object inputString)
        {
            DateTime dt = new DateTime(Convert.ToInt64(inputString));
            return dt.ToShortDateString();
        }
    }

I don’t have to do this, I can just pass key pair values, ie. ViewData[“MissionSummaryView”] = missionSummaryViewData and call ‘RenderView’.  However, making it typed allows me to use intellisense and have type checks in my view!

ie.

Missions Flown:  <%= ViewData.MisSummary.Count.ToString()%>

ViewData is a struct defined above that has a List<MissionSummary> , which has a ‘count’ – this is very nice feature of MS MVC!  You might have noticed above that I still have ‘databinding’ going on in MS MVC.  My solution uses Repeaters which are ‘MS MVC friendly’ and I was able to bind my list to the repeater.

Routing

Now that we have this in place, lets talk about how the routing will work.  Just deploying the current code above, I can access my new code via the following url:

http://www.forgottenskies.com/ForgottenWars/Mission.mvc/ViewMissionSummary

This corresponds to the route:

{controller}.mvc/{action}

In my code though, this ViewMissionSummary still has a ViewMissionSummary.aspx webform page.  I want to replace it with the above MVC code.  Instead of changing all my links in my solution to point to this new url (which isn’t very friendly!) I create a new route:

routes.Add(new Route("ViewMissionSummary.aspx", new MvcRouteHandler())
            {
                Defaults = new RouteValueDictionary(new { controller = "Mission", action = "ViewMissionSummary" }),
            });

This tells IIS that when ViewMissionSummary.aspx is requested, forward it to the Mission controller and corresponding action!

If a user selects ‘Mission’ on the menu, it will load:

http://www.forgottenskies.com/ForgottenWars/ViewMissionSummary.aspx

Which is mapped to my specified action!

One question that comes up with this is how to use querystrings in this example.  (I’m not going to cover RESTful urls right now, as I’m assuming we’re in ‘migration mode’).

A couple of updates are required:

I update the action to take a parameter:

public void ViewMissionSummary(int? id)

I made this nullable for now, as when the page initially is loaded, it will load all the summaries if id is null.  I can pass the id via the querystring as follows:

ForgottenWars/ViewMissionSummary.aspx?id=12

Presto!

Ayende on “A maintainable environment – anti corruption as a way of life”

Ayende has a post that exemplifies principles that I see as extremely important to a good development environment.

Some key points:

    • Infrastructure Ignorance – If I have to deal with my infrastructure explicitly, then I need to have developers dealing with it on a regular basis. That doesn’t mesh well with the idea of moving all the complexity to the infrastructure.
    • Fizz Buzz concepts – the code that a developer should write should be simple and easy to follow.
    • Follow good design principals – the code written should naturally lean toward single responsibility principal, separation of concerns, etc
    • Easy to figure out – It should be simpler than the alternative for any non trivial scenario. Ideally, you can explain how to solve most scenarios using this approach in half an hour or less (ignoring the infrastructure part, which may be very complex).
    • No training wheels – one of the things that drives me crazy is having two ways to do things. One for the average developer, the second for the architect. This usually comes out of putting training wheels on the first approach that make it hard to deal with in more advance scenarios. I see this as a sign of contempt for the rest of the members of the team. If you expect the rest of the team to work in a certain way, make damn sure that this is a way that this is a way that you can live with.

“The code that a developer should write should be simple and easy to follow”

There is so much about this that needs to be expounded upon. I really think the Single Responsibility Principle(SRP) is vital to this concept. I’ve seen some pretty ugly looking code all over the place where I’m at right now. Very large functions that are procedural in nature. I’d personally rather have many classes than classes stuffed with tons of code. Also, too much code in asp.net code behind pages is a major ‘no-no’. For myself, I’ve had to do much refactoring to get code back into business/presenter classes and out of the code behind. (This is one reason I like the Monorail/MS MVC approach). I could go on and on about this one.

“Easy to figure out”

Whew, amen here. Here is my code smell for this one: When you have no code in the business layer and all it is a pass through. Why do I say this ? Typically this means all the logic is in the UI or in the data layer. This is why I’m a big fan of a domain driven design with clean POCO business objects. Separation of Concerns is important here. I know it’s always debatable in the MS developer world, but when I see datasets I cringe. I think datasets tend to make developers think just in terms of the data layer. They are confusing to see the domain picture. So for me ‘Easy to figure out’ == well defined domain model.

I should add, I think creating a rules engine (IRules) and/or validation objects that can be kept away from the actual entity objects is important. This allows me to see the domain without clutter of all the rules (ie. different sets of business rules for a each client – the entity would hold a collection of ‘IRule’ objects associated to it’s particular instance)

The struggle is working in environments where principles aren’t openly discussed. I think ‘best practices’ should be complemented with developers all speaking a common language of good OO principles. On some teams I really enjoyed working with, stressing these principles made us a successful team, it was a very growing experience to me as a developer.

Ayende on "A maintainable environment – anti corruption as a way of life"

Ayende has a post that exemplifies principles that I see as extremely important to a good development environment.

Some key points:

    • Infrastructure Ignorance – If I have to deal with my infrastructure explicitly, then I need to have developers dealing with it on a regular basis. That doesn’t mesh well with the idea of moving all the complexity to the infrastructure.
    • Fizz Buzz concepts – the code that a developer should write should be simple and easy to follow.
    • Follow good design principals – the code written should naturally lean toward single responsibility principal, separation of concerns, etc
    • Easy to figure out – It should be simpler than the alternative for any non trivial scenario. Ideally, you can explain how to solve most scenarios using this approach in half an hour or less (ignoring the infrastructure part, which may be very complex).
    • No training wheels – one of the things that drives me crazy is having two ways to do things. One for the average developer, the second for the architect. This usually comes out of putting training wheels on the first approach that make it hard to deal with in more advance scenarios. I see this as a sign of contempt for the rest of the members of the team. If you expect the rest of the team to work in a certain way, make damn sure that this is a way that this is a way that you can live with.

“The code that a developer should write should be simple and easy to follow”

There is so much about this that needs to be expounded upon. I really think the Single Responsibility Principle(SRP) is vital to this concept. I’ve seen some pretty ugly looking code all over the place where I’m at right now. Very large functions that are procedural in nature. I’d personally rather have many classes than classes stuffed with tons of code. Also, too much code in asp.net code behind pages is a major ‘no-no’. For myself, I’ve had to do much refactoring to get code back into business/presenter classes and out of the code behind. (This is one reason I like the Monorail/MS MVC approach). I could go on and on about this one.

“Easy to figure out”

Whew, amen here. Here is my code smell for this one: When you have no code in the business layer and all it is a pass through. Why do I say this ? Typically this means all the logic is in the UI or in the data layer. This is why I’m a big fan of a domain driven design with clean POCO business objects. Separation of Concerns is important here. I know it’s always debatable in the MS developer world, but when I see datasets I cringe. I think datasets tend to make developers think just in terms of the data layer. They are confusing to see the domain picture. So for me ‘Easy to figure out’ == well defined domain model.

I should add, I think creating a rules engine (IRules) and/or validation objects that can be kept away from the actual entity objects is important. This allows me to see the domain without clutter of all the rules (ie. different sets of business rules for a each client – the entity would hold a collection of ‘IRule’ objects associated to it’s particular instance)

The struggle is working in environments where principles aren’t openly discussed. I think ‘best practices’ should be complemented with developers all speaking a common language of good OO principles. On some teams I really enjoyed working with, stressing these principles made us a successful team, it was a very growing experience to me as a developer.

AOP Concept : MS MVC ActionFilterAttributes

David Hayden has an excellent post on ‘ActionFilterAttributes’ with MS MVC Preview 2.  I really like this feature since it allows for cross-cutting concerns across controller actions.

It’s very easy to implement a filter and they use attributes which makes it very easy to apply to a controller action.

I am looking forward to developing with MS MVC!

On a side note, Scott Guthrie has a link to the MS MVC Source code here