Test-Drive ASP.NET MVC Review

A few years back I started dallying with test-driven development, but I never fully committed to the practice. This wasn’t because I didn’t believe in the value of TDD; it was more a matter of not completely understanding how to incorporate “test first” into my everyday development. Back in my web forms days, I could point fingers at the framework for my ignorance and laziness. After all, web forms weren’t exactly designed for testability so who could blame me for not embracing TDD in those conditions, right? But when I switched to ASP.NET MVC and quickly found myself fresh out of excuses and it became instantly clear that it was time to get my head around red-green-refactor once and for all or I would regretfully miss out on one of the biggest selling points the new framework had to offer.

Test-Drive ASP.NET MVC

I have previously written about how I learned ASP.NET MVC. It was primarily hands on learning but I did read a couple of ASP.NET MVC books along the way. The books I read dedicated a chapter or two to TDD and they certainly addressed the benefits of TDD and how MVC was designed with testability in mind, but TDD was merely an afterthought compared to, well, teaching one how to code the model, view and controller. This approach made some sense, and I learned a bunch about MVC from those books, but when it came to TDD the books were just a teaser and an opportunity missed.  But then I got lucky – Jonathan McCracken contacted me and asked if I’d review his book, Test-Drive ASP.NET MVC, and it was just what I needed to get over the TDD hump.

As the title suggests, Test-Drive ASP.NET MVC takes a different approach to learning MVC as it focuses on testing right from the very start. McCracken wastes no time and swiftly familiarizes us with the framework by building out a trivial Quote-O-Matic application and then dedicates the better part of his book to testing first – first by explaining TDD and then coding a full-featured Getting Organized application inspired by David Allen’s popular book, Getting Things Done. If you are a learn-by-example kind of coder (like me), you will instantly appreciate and enjoy McCracken’s style – its fast-moving, pragmatic and focused on only the most relevant information required to get you going with ASP.NET MVC and TDD.

The book continues with the test-first theme but McCracken moves away from the sample application and incorporates other practical skills like persisting models with NHibernate, leveraging Inversion of Control with the IControllerFactory and building a RESTful web service. What I most appreciated about this section was McCracken’s use of and praise for open source libraries like Rhino Mocks, SQLite and StructureMap (to name just a few) and productivity tools like ReSharper, Web Platform Installer and ASP.NET SQL Server Setup Wizard.  McCracken’s emphasis on real world, pragmatic development was clearly demonstrated in every tool choice, straight-forward code block and developer tip. Whether one is already familiar with the tools/tips or not, McCracken’s thought process is easily understood and appreciated.

The final section of the book walks the reader through security and deployment – everything from error handling and logging with ELMAH, to ASP.NET Health Monitoring, to using MSBuild with automated builds, to the deployment  of ASP.NET MVC to various web environments. These chapters, like those prior, offer enough information and explanation to simply help you get the job done. 

Do I believe Test-Drive ASP.NET MVC will turn you into an expert MVC developer overnight?  Well, no.  I don’t think any book can make that claim.  If that were possible, I think book list prices would skyrocket!  That said, Test-Drive ASP.NET MVC provides a solid foundation and a unique (and dare I say necessary) approach to learning ASP.NET MVC.  Along the way McCracken shares loads of very practical software development tips and references numerous tools and libraries. The bottom line is it’s a great ASP.NET MVC primer – if you’re new to ASP.NET MVC it’s just what you need to get started. 

Do I believe Test-Drive ASP.NET MVC will give you everything you need to start employing TDD in your everyday development?  Well, I used to think that learning TDD required a lot of practice and, if you’re lucky enough, the guidance of a mentor or coach.  I used to think that one couldn’t learn TDD from a book alone. Well, I’m still no pro, but I’m testing first now and Jonathan McCracken and his book, Test-Drive ASP.NET MVC, played a big part in making this happen.  If you are an MVC developer and a TDD newb, Test-Drive ASP.NET MVC is just the book for you.

Project Euler 20: (Iron)Python

In my attempt to learn (Iron)Python out in the open, here’s my solution for Project Euler Problem 20

As always, any feedback is welcome.

# Euler 20
# http://projecteuler.net/index.php?section=problems&id=20
# n! means n x (n - 1) x ... x 3 x 2 x 1
# Find the sum of digits in 100!
import time
start = time.time()

def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n-1)
    
print sum([int(i) for i in str(factorial(100))])

print "Elapsed Time:", (time.time() - start) * 1000, "millisecs"
a=raw_input('Press return to continue')

Project Euler 19: (Iron)Python

In my attempt to learn (Iron)Python out in the open, here’s my solution for Project Euler Problem 19

As always, any feedback is welcome.

# Euler 19
# http://projecteuler.net/index.php?section=problems&id=19
# You are given the following information, but you may
# prefer to do some research for yourself.
#
# - 1 Jan 1900 was a Monday.
# - Thirty days has September,
#   April, June and November.
#   All the rest have thirty-one,
#   Saving February alone,
#   Which has twenty-eight, rain or shine.
#   And on leap years, twenty-nine.
# - A leap year occurs on any year evenly divisible by 4,
#   but not on a century unless it is divisible by 400.
#
# How many Sundays fell on the first of the month during
# the twentieth century (1 Jan 1901 to 31 Dec 2000)?
import time
start = time.time()

import datetime
sundays = 0

for y in range(1901,2001):
    for m in range(1,13):
        # monday == 0, sunday == 6
        if datetime.datetime(y,m,1).weekday() == 6:
            sundays += 1
print sundays

print "Elapsed Time:", (time.time() - start) * 1000, "millisecs"
a=raw_input('Press return to continue')

Project Euler 18: (Iron)Python

In my attempt to learn (Iron)Python out in the open, here’s my solution for Project Euler Problem 18

As always, any feedback is welcome.

# Euler 18
# http://projecteuler.net/index.php?section=problems&id=18
# By starting at the top of the triangle below and moving
# to adjacent numbers on the row below, the maximum total
# from top to bottom is 23.
#
# 3
# 7 4
# 2 4 6
# 8 5 9 3
#
# That is, 3 + 7 + 4 + 9 = 23.

# Find the maximum total from top to bottom of the triangle below:

# 75
# 95 64
# 17 47 82
# 18 35 87 10
# 20 04 82 47 65
# 19 01 23 75 03 34
# 88 02 77 73 07 63 67
# 99 65 04 28 06 16 70 92
# 41 41 26 56 83 40 80 70 33
# 41 48 72 33 47 32 37 16 94 29
# 53 71 44 65 25 43 91 52 97 51 14
# 70 11 33 28 77 73 17 78 39 68 17 57
# 91 71 52 38 17 14 91 43 58 50 27 29 48
# 63 66 04 68 89 53 67 30 73 16 69 87 40 31
# 04 62 98 27 23 09 70 98 73 93 38 53 60 04 23

# NOTE: As there are only 16384 routes, it is possible to solve
# this problem by trying every route. However, Problem 67, is the
# same challenge with a triangle containing one-hundred rows; it
# cannot be solved by brute force, and requires a clever method! ;o)
import time
start = time.time()

triangle = [
 [75],
 [95, 64],
 [17, 47, 82],
 [18, 35, 87, 10],
 [20, 04, 82, 47, 65],
 [19, 01, 23, 75, 03, 34],
 [88, 02, 77, 73, 07, 63, 67],
 [99, 65, 04, 28, 06, 16, 70, 92],
 [41, 41, 26, 56, 83, 40, 80, 70, 33],
 [41, 48, 72, 33, 47, 32, 37, 16, 94, 29],
 [53, 71, 44, 65, 25, 43, 91, 52, 97, 51, 14],
 [70, 11, 33, 28, 77, 73, 17, 78, 39, 68, 17, 57],
 [91, 71, 52, 38, 17, 14, 91, 43, 58, 50, 27, 29, 48],
 [63, 66, 04, 68, 89, 53, 67, 30, 73, 16, 69, 87, 40, 31],
 [04, 62, 98, 27, 23, 9, 70, 98, 73, 93, 38, 53, 60, 04, 23]]
 
# Loop through each row of the triangle starting at the base.
for a in range(len(triangle) - 1, -1, -1):
    for b in range(0, a):  
        # Get the maximum value for adjacent cells in current row.
        # Update the cell which would be one step prior in the path
        # with the new total. For example, compare the first two
        # elements in row 15. Add the max of 04 and 62 to the first
        # position of row 14.This provides the max total from row 14
        # to 15 starting at the first position. Continue to work up
        # the triangle until the maximum total emerges at the
        # triangle's apex.
        triangle [a-1][b] += max(triangle [a][b], triangle [a][b+1])
 
  
print triangle [0][0]
print "Elapsed Time:", (time.time() - start) * 1000, "millisecs"
a=raw_input('Press return to continue')

Project Euler 17: (Iron)Python

In my attempt to learn (Iron)Python out in the open, here’s my solution for Project Euler Problem 17

As always, any feedback is welcome.

# Euler 17
# http://projecteuler.net/index.php?section=problems&id=17
# If the numbers 1 to 5 are written out in words:
# one, two, three, four, five, then there are
# 3 + 3 + 5 + 4 + 4 = 19 letters used in total.
# If all the numbers from 1 to 1000 (one thousand)
# inclusive were written out in words, how many letters
# would be used?
#
# NOTE: Do not count spaces or hyphens. For example, 342
# (three hundred and forty-two) contains 23 letters and
# 115 (one hundred and fifteen) contains 20 letters. The
# use of "and" when writing out numbers is in compliance
# with British usage.
import time
start = time.time()

def to_word(n):
    h = { 1 : "one", 2 : "two", 3 : "three",
        4 : "four", 5 : "five", 6 : "six",
        7 : "seven", 8 : "eight", 9 : "nine",
        10 : "ten", 11 : "eleven", 12 : "twelve",
        13 : "thirteen", 14 : "fourteen", 15 : "fifteen",
        16 : "sixteen", 17 : "seventeen", 18 : "eighteen",
        19 : "nineteen", 20 : "twenty", 30 : "thirty",
        40 : "forty", 50 : "fifty", 60 : "sixty",
        70 : "seventy", 80 : "eighty", 90 : "ninety",
        100 : "hundred", 1000 : "thousand" }

    word = ""

    # Reverse the numbers so position (ones, tens,
    # hundreds,...) can be easily determined        
    a = [int(x) for x in str(n)[::-1]]
    
    # Thousands position
    if (len(a) == 4 and a[3] != 0):
        # This can only be one thousand based
        # on the problem/method constraints
        word = h[a[3]] + " thousand "
    

    # Hundreds position
    if (len(a) >= 3 and a[2] != 0):
        word += h[a[2]] + " hundred"

        # Add "and" string if the tens or ones
        # position is occupied with a non-zero value.
        # Note: routine is broken up this way for [my] clarity.
        if (len(a) >= 2 and a[1] != 0):
            # catch 10 - 99
            word += " and"
        elif len(a) >= 1 and a[0] != 0:
            # catch 1 - 9
            word += " and"

    # Tens and ones position
    tens_position_value = 99
    if (len(a) >= 2 and a[1] != 0):
        # Calculate the tens position value per the
        # first and second element in array
        # e.g. (8 * 10) + 1 = 81
        tens_position_value = int(a[1]) * 10 + a[0]

        if tens_position_value <= 20:
            # If the tens position value is 20 or less
            # there's an entry in the hash. Use it and there's
            # no need to consider the ones position
            word += " " + h[tens_position_value]
        else:
            # Determine the tens position word by
            # dividing by 10 first. E.g. 8 * 10 = h[80]
            # We will pick up the ones position word later in
            # the next part of the routine
            word += " " + h[(a[1] * 10)]
        
    if (len(a) >= 1 and a[0] != 0 and tens_position_value > 20):
        # Deal with ones position where tens position is
        # greater than 20 or we have a single digit number
        word += " " + h[a[0]]
    
    # Trim the empty spaces off both ends of the string
    return word.replace(" ","")    


def to_word_length(n):    
    return len(to_word(n))    

print sum([to_word_length(i) for i in xrange(1,1001)])

print "Elapsed Time:", (time.time() - start) * 1000, "millisecs"
a=raw_input('Press return to continue')

Project Euler 16: (Iron)Python

In my attempt to learn (Iron)Python out in the open, here’s my solution for Project Euler Problem 16

As always, any feedback is welcome.

# Euler 16
# http://projecteuler.net/index.php?section=problems&id=16
# 2^15 = 32768 and the sum of its digits is
# 3 + 2 + 7 + 6 + 8 = 26.
# What is the sum of the digits of the number 2^1000?
import time
start = time.time()

print sum([int(i) for i in str(2**1000)])

print "Elapsed Time:", (time.time() - start) * 1000, "millisecs"
a=raw_input('Press return to continue')

Project Euler 15: (Iron)Python

In my attempt to learn (Iron)Python out in the open, here’s my solution for Project Euler Problem 15

As always, any feedback is welcome.

# Euler 15
# http://projecteuler.net/index.php?section=problems&id=15
# Starting in the top left corner of a 2x2 grid, there
# are 6 routes (without backtracking) to the bottom right
# corner. How many routes are their in a 20x20 grid?
import time
start = time.time()

def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n-1)
    
rows, cols = 20, 20
print factorial(rows+cols) / (factorial(rows) * factorial(cols))

print "Elapsed Time:", (time.time() - start) * 1000, "millisecs"
a=raw_input('Press return to continue')

Project Euler 14: (Iron)Python

In my attempt to learn (Iron)Python out in the open, here’s my solution for Project Euler Problem 14

As always, any feedback is welcome.

# Euler 14
# http://projecteuler.net/index.php?section=problems&id=14
# The following iterative sequence is defined for the set
# of positive integers:
# n ->  n/2 (n is even)
# n ->  3n + 1 (n is odd)
# Using the rule above and starting with 13, we generate
# the following sequence:
# 13  40  20  10  5  16  8  4  2  1
# It can be seen that this sequence (starting at 13 and
# finishing at 1) contains 10 terms. Although it has not
# been proved yet (Collatz Problem), it is thought that all
# starting numbers finish at 1. Which starting number,
# under one million, produces the longest chain?
# NOTE: Once the chain starts the terms are allowed to go
# above one million.
import time
start = time.time()

def collatz_length(n):
    # 0 and 1 return self as length
    if n <= 1: return n

    length = 1
    while (n != 1):
      if (n % 2 == 0):
        n /= 2
      else:
        n = 3*n + 1
      
      length += 1
    
    return length
    
starting_number, longest_chain = 1, 0

for x in xrange(1, 1000001):
    l = collatz_length(x)
    if l > longest_chain: starting_number, longest_chain = x, l 
        
print starting_number
print longest_chain

# Slow 31 seconds
print "Elapsed Time:", (time.time() - start) * 1000, "millisecs"
a=raw_input('Press return to continue')