C# underbelly

This week, I came across a post by Brett Schucher on the Object Mentor blog where I found out something very surprising - virtual methods are resolved at compile time with an index of a virtual table indicating the address of the method to call.

Because I don't have a C++ background (or any non-managed code) this part of the underbelly of C# has previously passed me by and I was shocked when I read the post - "this isn't evaluated at runtime?"
My assumption has always been that this was part of the jitter and in fact I hadn't really thought about it that much - after reading a bit about it, frankly I'm still not sure why it was implemented that way... a nod to the past or a technology constraint?

Imagine my surprise when the following day, whilst consuming the delights of Jon Skeet's C# in Depth book the very same subject is referred to in passing when discussing generic method overloads with a cautionary sidebar warning - "Possibly unexpected behaviour!". He describes how the compiler doesn't know what overloads will be available when compiling the generic type and that is is because of the compiler resolving virtual methods rather than execution time resolution occuring.
(If I haven't got that paraphrased correctly, my humble apologies to the almighty Skeet)

Stumbling into this twice in two days - odd indeed.

Suffice to say I feel enlightened somewhat and exposed to some new topics that I can research. I do feel that my lack of knowledge in this are does validate one of Joel Spolsky's themes of the stack overflow podcasts : programmers should learn C. His premise that knowing a lower level language that forces you to know about the nitty-gritty details definitely applies in this case and I feel I really should know more about the core details.

To be honest though, I don't have the time learn a whole new language - I already speak "Dad", "husband" and C# that take up ALL my waking hours.

But I can keep on reading, stay inquisitive and continue being new.

(note: if you haven't come across Jon Skeet's book yet - I recommend it heartily)

Posted at at 9:59 AM on Thursday, December 18, 2008 by Posted by Justin Davies | 0 comments Links to this post   | Filed under:

more test-first development and refactoring with classic ASP

In this, the sixth part of a series on unit testing classic ASP, we will continue with our test-first development of the class we created in part five. All the previous parts are available at:

Part one: how to unit test classic ASP
Part two: user stories for classic ASP unit testing example
Part three: beginnings of a classic ASP unit test framework
Part four: automating classic ASP unit tests with NUnit
Part five: using the classic ASP unit test framework

We last left our OrderSettings class and its unit tests in a green pass state, but the CanOrderAt function was still hardcoded. We therefore need to include a new assertion in our unit test ASP file "OrderSettingsTest.asp" to test for a different time:

Dim onePm, twoPm, tenAM
onePm = "10/10/2008 13:00:00"
twoPm = "10/10/2008 14:00:00"
tenAM = "10/10/2008 10:00:00"

tester.AssertIsFalse currentOrderSettings.CanOrderAt(onePm), "Can Not Order At 13:00"
tester.AssertIsTrue currentOrderSettings.CanOrderAt(twoPm), "Can Order At 14:00"
tester.AssertIsTrue currentOrderSettings.CanOrderAt(tenAm), "Can Order At 10:00"

The unit tests now fail on the last assertion so it is time for us to introduce some real code in the CanOrderAt function:

    Public Function CanOrderAt(dateTime)
        
        Dim checkDate, cutOffDate, nextDate
        
        dateTime = CDate(dateTime)
        
        ' first strip the time off the date sent into this function
        checkDate = DateAdd("h",0-DatePart("h",dateTime),dateTime)
        checkDate = DateAdd("n",0-DatePart("n",dateTime),checkDate)
        checkDate = DateAdd("s",0-DatePart("s",dateTime),checkDate)
        
        ' now use this and add the time from the cutOffTime property
        cutOffDate = DateAdd("h",DatePart("h",Me.CutOffTime),checkDate)
        cutOffDate = DateAdd("n",DatePart("n",Me.CutOffTime),cutOffDate)
        cutOffDate = DateAdd("s",DatePart("s",Me.CutOffTime),cutOffDate)
        
        ' add the time from the nextOrderTime property
        nextDate = DateAdd("h",DatePart("h",Me.NextOrderTime),checkDate)
        nextDate = DateAdd("n",DatePart("n",Me.NextOrderTime),nextDate)
        nextDate = DateAdd("s",DatePart("s",Me.NextOrderTime),nextDate)
        
        CanOrderAt = (dateTime < cutOffDate) Or (dateTime >= nextDate)
        
    End Function

This is our first attempt at the code for this method - it strips the time off the original date and stores this in a variable called "checkDate"; we then derive two new variables by adding the time from our properties to this date so that the day remains the same as the one passed in. We can now compare the times and return whether ordering is possible.
When we run our unit tests, they pass.

There is obviously room for refactoring here, so we will now test-first a new class that will handle common date operations for us and enable us to change the code we have just written. We start by creating a new folder in our Unit test area called "Utilitites" and creating a new "DateUtilityFixture.cs" file:

namespace ASPTesting.Tests.UnitTests.Utilities
{
    [TestFixture]
    public class DateUtilityFixture : AspFixture
    {
        [Test]
        public void DateUtilityTest()
        {
            RunAspTest("UnitTests/Utilities/DateUtilityTest.asp");
        }
    }
}

This code is expecting a new DateUtilityTest.asp file - if we run the unit tests now, they fail due to a server error, so let's create the new test file:

<!--#include virtual="Tests/UnitTester.asp"-->
<!--#include virtual="Utilities/DateUtility.asp"-->

<%
dim tester
Set tester = new UnitTester
tester.Init("Testing Date Utility")

Dim dateUtil
Set dateUtil = new DateUtility

%>

Here we have an include for a file called "DateUtility" in our main project that does not yet exist and we set up the unit tester and create an instance of the DateUtility class. If we run the unit test for this it fails because of the missing DateUtility class, but before we write it, we should introduce some tests:

Dim dateUtil
Set dateUtil = new DateUtility

dim aDate, expectedDate, baseDate
aDate = CDate("10/10/2008 21:53:46")
expectedDate = CDate("10/10/2008 00:00:00")

tester.Given("a date of " + CStr(aDate) + " and we are testing StripTime")
tester.AssertAreEqual dateUtil.StripTime(aDate), expectedDate

aDate = CDate("10/10/2008 00:00:00")
tester.Given("a date of " + CStr(aDte) + " and we are testing StripTime")
tester.AssertAreEqual dateUtil.StripTime(aDate), expectedDate

We now have two tests for a StripTime function that we can now write in a new file in our main project - DateUtility. We have the stripping code already inside our OrderSettings class at the moment so we copy that code into our new class and refine it:

<%
Class DateUtility

    Public Function StripTime(inputDate)
    
        dim newDate
        
        inputDate = CDate(inputDate)
    
        newDate = DateAdd("h",0-DatePart("h",inputDate),inputDate)
        newDate = DateAdd("n",0-DatePart("n",inputDate),newDate)
        newDate = DateAdd("s",0-DatePart("s",inputDate),newDate)
        
        StripTime = newDate
    End Function
    
End Class 
%>

We now run our unit tests and they all pass. We could now add some more edge cases in for this function, but for this exercise we will continue onto refactoring our main OrderSettings class.

Because we have unit tests surrounding both the date utility function and the OrderSettings CanOrderAt function we can now refactor with some level of confidence and we see the true value of unit tests with classic ASP - we can confidently change the code! Let's have a look at the new OrderSettings code:

<!--#include virtual="Utilities/DateUtility.asp"-->
<%
Class OrderSettings

    Private m_cutOffTime
    Private m_nextOrderTime

    Public Property Get CutOffTime()
        CutOffTime = m_cutOffTime
    End Property
    Public Property Let CutOffTime(value)
        m_cutOffTime = CDate(value)
    End Property
    
    Public Property Get NextOrderTime()
        NextOrderTime = m_nextOrderTime
    End Property
    Public Property Let NextOrderTime(value)
        m_nextOrderTime = CDate(value)
    End Property
    
    Public Function CanOrderAt(dateTime)
        
        Dim checkDate, cutOffDate, nextDate, dateUtil
        
        Set dateUtil = new DateUtility
        
        dateTime = CDate(dateTime)
        
        checkDate = dateUtil.StripTime(dateTime)
        
        ' now use this and add the time from the cutOffTime property
        cutOffDate = DateAdd("h",DatePart("h",Me.CutOffTime),checkDate)
        cutOffDate = DateAdd("n",DatePart("n",Me.CutOffTime),cutOffDate)
        cutOffDate = DateAdd("s",DatePart("s",Me.CutOffTime),cutOffDate)
        
        ' add the time from the nextOrderTime property
        nextDate = DateAdd("h",DatePart("h",Me.NextOrderTime),checkDate)
        nextDate = DateAdd("n",DatePart("n",Me.NextOrderTime),nextDate)
        nextDate = DateAdd("s",DatePart("s",Me.NextOrderTime),nextDate)
        
        CanOrderAt = (dateTime < cutOffDate) Or (dateTime >= nextDate)
        
    End Function
End Class
%>

We have a new include declaration at the top of the file for the new DateUtility class and now our strip time functionality is one line (and we no longer need the comment as it is self explanatory).
We can now clean the rest of the code by introducing a new AddTime method to the DateUtility class. As always, we start with some new tests in the DateUtilityTest.asp file:

aDate = CDate("10/10/2008 00:00:00")
baseDate = CDate("01/01/2007 23:59:01")
expectedDate = CDate("10/10/2008 23:59:01")
tester.Given("a date of " + CStr(aDate) + " and a baseDate of " + CStr(baseDate) 
         + " and we are testing AddTime")
tester.AssertAreEqual dateUtil.AddTimeFrom(aDate, baseDate), expectedDate

These two new assertions cause our unit tests to fail because the function is not available. We therefore create it and add the code in from our OrderSettings class.
(Note that you could, in true red/green/refactor style, create the function and return a nominal date value first, thus causing the test to fail from an assertion as opposed to a runtime error. This would ensure your test fail for the correct reason - we are not doing so throughout here for brevity).

<%
Class DateUtility

    Public Function StripTime(inputDate)
    
        dim newDate
        
        inputDate = CDate(inputDate)
    
        newDate = DateAdd("h",0-DatePart("h",inputDate),inputDate)
        newDate = DateAdd("n",0-DatePart("n",inputDate),newDate)
        newDate = DateAdd("s",0-DatePart("s",inputDate),newDate)
        
        StripTime = newDate
    End Function
    
    Public Function AddTimeFrom(inputDate, fromDate)
    
        dim newDate
        
        inputDate = CDate(inputDate)
        fromDate = CDate(fromDate)
        
        newDate = DateAdd("h",DatePart("h", fromDate),inputDate)
        newDate = DateAdd("n",DatePart("n", fromDate),newDate)
        newDate = DateAdd("s",DatePart("s", fromDate),newDate)
        
        AddTimeFrom = newDate
    End Function
    
End Class 
%>

We now have our function coded and when we run our unit tests, they now pass. Again, we could add edge cases here and better describe our desired behaviour for this class, but we will continue on in this example.
We now refactor the CanOrderAt function of the OrderSettings class:

    Public Function CanOrderAt(dateTime)
        
        Dim checkDate, cutOffDate, nextDate, dateUtil
        
        Set dateUtil = new DateUtility
        
        dateTime = CDate(dateTime)
        
        checkDate = dateUtil.StripTime(dateTime)
        
        cutOffDate = dateUtil.AddTimeFrom(checkDate,Me.CutOffTime)
        
        nextDate = dateUtil.AddTimeFrom(checkDate,Me.NextOrderTime)
        
        CanOrderAt = (dateTime < cutOffDate) Or (dateTime >= nextDate)
        
    End Function

When we run our unit tests, they all pass!

This part has illustrated how we can do some true test-first development with classic ASP and bring some good practices such as encapsulation and single responsibility principle to our code. We refactored our code with confidence because we had tests surrounding the code that we were adding and modifying.
We have now provided the functionality we need for our first user story that we were exploring:

As a user if I access the system between 13:00 and 14:00, I cannot place an order and the system will provide an appropriate message.

Our order page would use this CanOrderAt function of our new API to evaluate whether ordering was possible for the current time and would display a message accordingly (we are not going to code that page or any other main ASP page in our unit test examples and simply explore our unit testing examples).

In the next part of this series we will explore some more classic ASP unit testing and attempt to deliver more functionality for our user story backlog.

Posted at at 8:58 PM on Thursday, December 11, 2008 by Posted by Justin Davies | 3 comments Links to this post   | Filed under: ,

Controller reponsibilities, anemia and me

Ian Cooper has written an excellent essay on the Fat Controller where he describes the bloating of controllers due to too much responsibility (of various kinds).

Looking back to one of my last projects where we used MVC for the first time, it is startlingly clear with hindsight that we took some wrong steps... our controllers were "fat" with far too much orchestration of and complete knowledge about the domain objects themselves.

More importantly the domain was completely anemic, due mostly to the entities being pre-generated via codesmith from database tables. What we were left with were effectively DTO POCO objects - good for persisting and passing around, but very little else; hitting the buttons on the benefits of the Anemic Domain Model, but bad in rectrospect with my architecural glasses!

This ultimately meant that the controller had everything injected into it via an IOC container - repositories, utilities (small versions of services) and anything else it needed to service the request with complete control.

This is going to be a common mistake, I believe, of those starting out with MVC and in fact a lot of people are vocal about these concerns - take a look at some of the links that Ian points to in his post.

I now know what I did to be wrong and I ask my inner architect to forgive me - I feel it in my bones the more I read back on the basics like Separation of Concerns and Single Responsibility Principle... and more importantly Domain Driven Design.

Without making that mistake and ultimately learning from it though, I don't think I would have truly seen the advantage of a rich domain model and services; reading books and posts about the theory really doesn't match up to personal experience of a D'oh moment.

Time to dig out Eric Evans' DDD book once again and flagellate its principles into me, along with the basics. Oh yes! DRY me, SRP, LOC, LOD and SOC it to me, oh yes!

Posted at at 1:22 PM on Thursday, December 4, 2008 by Posted by Justin Davies | 0 comments Links to this post   | Filed under: ,