After getting severely distracted by a little gem called RoboZZle I'd had to answer with a solid maybe. The idea behind the game is simple: for each puzzle, program a small robot to collect all of the stars without falling off the map. Here's a an example of a typical puzzle:
What's really cool is that the author, Igor Ostrovsky, has added social features so if you sign up for an account you can rate and vote for puzzles as well as submitting your own. This frees Igor from having to dream up all the puzzles and adds a lot more variety and a lot more devious minds the mix!
No modern programming language looks anything like the one used in the game, at least, not one anyone uses... so what could it possibly have to teach us? Well, solving all of the puzzles will require you to do all of these:
- Search for patterns.
- Invent algorithms.
- Create reusable functions.
- Understand recursion.
- Simplify.
There's one item in that list that is essential for solving many of the harder problems, and it's one that still gives a lot programmers headaches in the real world...
Understand Recursion
A function that calls itself, what's so hard about that? If you think you really understand recursion here's some puzzles to try, starting with something nice and easy and working up to trickier problems:
Made it this far? Well done. As a final exam I put together a puzzle of my own. At the time of writing is remains unsolved, let me know how you get on...
So yes, maybe there is something games can teach us. If so I'm going to be a genius! Oh yeah, the game is built in Silverlight too which is just awesome.
27/02/2009 12:54 AM (UTC -08:00)
I have recently spent quite a bit of time getting my ASP.Net MVC application to display errors to the user the way I want and this post outlines the steps I took to get there. This includes general application errors, page not found errors and stupid user errors. A basic understanding of ASP.Net and the MVC framework will be required to follow this post. For reference my environment looks like this:
- Windows Server 2008
- IIS7 using the Integrated Pipeline
- Visual Studio 2008
- ASP.Net MVC Beta
If you have a different setup the details provided here might not work exactly as described, especially if you are running a lesser version of IIS like 5 or 6. Upgrade, seriously.
CustomErrors Web.config Settings
Remember, ASP.Net MVC is just a new layer on top of the same old ASP.Net we know and love hate put up with. The custom errors section of the Web.config was something we always had to set up for web forms projects so it seems like a good place to start for MVC. Here's what my settings look like:
<customErrors mode="On" defaultRedirect="~/Error/Unknown" />
Nice and simple. All I'm saying here is that should anything crazy happen that my application doesn't deal with, redirect the user to my really bad error page. The URL I provide is going to map to one on my MVC controllers which I'll get to shortly.
ASP.Net allows you to add rules for specific HTTP status codes but I'm going to ignore all that because I want these settings to be used as little as possible. If you're interested in why there are already plenty of people out there talking about the issues with custom errors, e.g. this guy, that guy and another guy also.
ErrorController
In my application I have a controller dedicated to serving up application level errors. Here's a simplified version:
public class ErrorController : Controller
{
[AcceptVerbs(HttpVerbs.Get)]
public ViewResult Unknown()
{
Response.StatusCode = (int)HttpStatusCode.InternalServerError;
return View("Unknown");
}
[AcceptVerbs(HttpVerbs.Get)]
public ViewResult NotFound(string path)
{
Response.StatusCode = (int)HttpStatusCode.NotFound;
return View("NotFound", path);
}
}
The Unknown action is the target of my custom errors redirect in the Web.config. The NotFound action is going to be used by the routing system which I will describe below. Note that both actions set the HTTP status code to make sure our response is absolutely clear to the client.
There are intentionally few types of errors here because if the user is seeing these it probably means there is an improvement I can make to the application. The views that these actions render are very generic and don't have enough context to be very useful to the user. They may as well just say Oops!
IIS7 Detailed Errors
IIS7, trying to be helpful, likes to steal your custom errors pages and replace them with it's own:
Annoyingly these errors will be swapped in whenever you set the HTTP status code to something interesting. To crack down on this insubordination you need to open the Error Pages feature in IIS and click Edit Feature Settings on the right hand menu to get this dialog:
You might be tempted to think that the Custom error pages option is what you should choose to display your custom error pages... but you'd be wrong. These are IIS7 custom errors pages and something else entirely from what we are after. Set the Detailed errors option to have IIS pass through whatever errors we serve up from ASP.Net.
Internet Explorer Friendly Errors
Internet Explorer, trying to be helpful like it's big brother IIS, wont display your error pages if they are smaller than 512 bytes. By default IE has a setting called Show friendly HTTP error messages turned on and this causes your nice custom errors to be replaced with the standard canned reply:
You can find the option to turn this off in IE under Tools, Internet Options, Advanced, Browsing, Show friendly HTTP error messages. Unfortunately you can't set this for all of your users (or install Firefox for them) so just make sure that all of your error pages are larger than 512 bytes and you should be fine.
I find this one to be quite annoying during development when I only have stub pages in place.
Page Not Found
One of the most basic errors all sites will need to serve is the standard 404, page not found. I could let the custom errors settings deal with this but as well as adding an extra redirect it also requires all requests to be mapped to ASP.Net in IIS, even those without a standard extension like .aspx.
Keeping things in code is my preference as it makes them easier to test and easier to move to new environments. The MVC routing features let me deal with this nicely by adding a simple catch all route after all my standard application routes:
routes.MapRoute("Default", "{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" });
routes.MapRoute("Catch All", "{*path}",
new { controller = "Error", action = "NotFound" });
This maps any completely invalid routes to ErrorController.NotFound which we've already seen. This happens in a single request, without any redirects, works with all URLs and doesn't require a special mapping in IIS.
Route Matched But Parameters Are Invalid
If you have controller actions that take parameters you need to take some additional steps with your routing. An error that kept popping up for me early on was something like this:
The parameters dictionary does not contain a valid value of type 'System.Int32' for parameter 'id' which is required for method 'System.Web.Mvc.ActionResult Edit(Int32)' in 'Example.ProductController'. To make a parameter optional its type should either be a reference type or a Nullable type.
Ouch, what?! To get rid of these errors you can add constraints to your routes using regular expressions, e.g.
routes.MapRoute("Products - Edit", "Products/{id}/Edit",
new { controller = "Products", action = "Edit" },
new { id = @"\d{1,}" });
The last line specifies that the id parameter must be one or more digits an not contain any crazy stuff like letters or tilde symbols. Should someone decide to be sneaky and type rubbish which the ID should go, they will pass right over this route and the catch all route will send them to the 404 page.
Errors In Controllers
Even once a request has successfully been mapped to an action there is plenty that could go wrong. Here's a simple example where the requested product isn't found in the database:
public ProductController : Controller
{
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult ViewDetails(int id)
{
var product = GetProductFromDB(id);
if (product == null)
{
Response.StatusCode = (int)HttpStatusCode.NotFound;
return View("NotFound");
}
return View("Details", product);
}
One of the advantages MVC has over the web forms model is that you can delay choosing which view to render right until the last moment. Here I am using a not found page tailored specifically for the products section of the site so that I can try and guess what the user was looking for and give them as much help as possible.
There are more advanced ways of catching errors in controller but they all basically have the same effect, rendering a different view.
Conclusion
That's all for today. If you have any questions, comments or corrections I'd love to hear from you so leave a comment below.
27/01/2009 04:34 AM (UTC -08:00)
I want to follow up my last post with a clear example showing what I expected to happen and why it didn't. What is the output of the following program?
class Program
{
static void Main(string[] args)
{
Bar bar = new Bar();
Foo foo = bar;
foo.Say();
bar.Say();
}
}
class Foo
{
public virtual void Say() { Console.Write("Foo"); }
}
class Bar : Foo
{
public override void Say() { Console.Write("Bar"); }
}
Anyone who has a decent grasp of inheritance and polymorphism should have correctly guessed that the output of the program is BarBar. The class Bar overrides the default behaviour of Foo and replaces it with something else. What if we use extension methods?
class Foo {}
class Bar : Foo {}
static class Extensions
{
public static void Say(this Foo foo) { Console.Write("Foo"); }
public static void Say(this Bar bar) { Console.Write("Bar"); }
}
Because extension methods are a new addition to the framework people are more likely to get this wrong, like me. The output of this program is FooBar. The important difference is that the extension method on Bar is not able to override and replace the default behaviour on Foo and is only used if you refer to the object as a Foo.
If you're designing an API and want to avoid confusion, watch out for this one. As always there's workarounds, here's something you might try:
static class Extensions
{
public static void Say(this Foo foo)
{
if(foo is Bar)
((Bar)foo).Say();
else
Console.Write("Foo");
}
public static void Say(this Bar bar) { Console.Write("Bar"); }
}
This produces the same result as the original virtual method based program, BarBar.
While this might make you API a little more predictable it does so at the expense of the code. Tying Foo to it's derived classes like this starts to break down the reasons for using the Foo abstraction in the first place and will make your code difficult to modify in future. I would suggest these issues as the reason Microsoft didn't add a special case for IQueryable<T> in IEnumerable<T>.Where, but it turns out they have already added special cases for arrays and lists so who knows.
It's the little details like this that make great interview questions for those annoying candidates that seem to know everything...
22/01/2009 04:50 PM (UTC -08:00)
I've been taking LINQ to NHibernate (Alpha just released) for a test drive in my latest project and so far I'm pleased enough that I think I will stick with it going forward. This post is to point out a subtle behaviour that caught me unawares. Consider the following example:
session.Linq<Foo>()
.WithId(123)
.Single();
The first line is LINQ to NHibernate speak which simply returns an IQueryable<Foo> representing all available objects of type Foo. The important thing here is that it is just a query, the database has not been visited yet. The second line is my own extension method which should extend the query and filter the results by Id:
public static IEnumerable<Foo> WithId(
this IEnumerable<Foo> foos, int id)
{
return foos.Where(x => x.Id == id);
}
The third line is a standard LINQ to SQL function which makes sure that there is only one item in the list and returns it for you. This call is the first time that the code should touch the database and the result should be that only a single row is returned. Unfortunately one of the tests I wrote today turned up something suspicious... my extension method was being called 23 times and by coincidence there also happened to be 23 items in my database!
Since the code actually produced the correct results and this was really a performance issue I decided it would be a good time to check out Ayende's new NHibernate Profiler. Overall I am quite impressed as it is easy to set up, shows me everything I expect and has a reasonably intuitive interface for a developer tool. Compared to setting up a trace on the SQL server and trying to analyse the results, using the profiler was actually fun.
Now certain that my code was eagerly requesting every row in the table then throwing them away, I set out to figure out why. Using the traditional poke it with the debugger approach, I discovered that changing my extension method to this resolved the problem:
public static IQueryable<Foo> WithId(
this IQueryable<Foo> foos, int id)
{
return foos.Where(x => x.Id == id);
}
Why did I think IEnumerable<T> was a good choice? Because IQueryable<T> inherits directly from it and I was trying to use the less restrictive interface. Why does it not work like I expect? Because there is a Where extension method for each of the interfaces and a quick look with Reflector shows that they do very, very different things.
Extension methods can't be overridden like virtual methods which means objects will act like the name you give them, not like what they really are. This also means that it's not LINQ to NHibernate's fault at all, in fact you will likely run into this issue with LINQ to SQL as well.
If there's a lesson to be learnt from this story it's probably to be more careful of extension methods. I can't really call my own misunderstandings bugs in the framework so instead I'm just going to make some snarky remarks about un-intuitive behaviour and sign off...
21/01/2009 03:35 AM (UTC -08:00)
This post outlines some of my experiences moving from ASP.Net web forms to the new ASP.Net MVC framework coming from Microsoft. There is plenty of talk about all the advantages of the new framework but it comes at a price.
Should You Use It?
The Microsofties are being quite clear that the new framework isn't for everyone and that the old one isn't going away. I still use both and which one is better is way too subjective for anyone but you to answer. Many of my projects will continue to use the old model, particularly if the project sounds like this:
- Small project.
- Few technical challenges.
- Lots of content, little functionality.
- Fast delivery is a priority.
- Low budget is a priority.
- Existing web forms based CMS.
- Team not experienced with MVC.
This describes a lot of the quick marketing style sites that I do. For some of my new projects I'm moving the the new MVC framework. There is a large gray area in between but I will prefer the new framework for the following sorts of projects:
- Large project.
- Quality is a priority.
- Difficult technical problems to solve.
- Integration with external systems.
- The code base is expected to live for several years.
- The code will be reused or deployed in many places.
- Experienced team or one willing to invest time learning.
Now before I make anyone angry, yes you can do a great job of large complex projects using the web forms model, I just hate doing it.
Learning Curve
If you're like me and you've never worked with a similar framework before (for example MonoRail or Rails) you're suddenly going to find yourself very unproductive as you relearn how to do all the things you've been doing for years in web forms. Here are some of the things you will want to spend time on:
- Learning the key architecture concepts in the framework. You will need a solid understanding of how a URL makes its way through routing, a controller and finally the view.
- Form input and validation is very different to what you are used to. Spend time coming up with some patterns you like.
- Postbacks and viewstate no longer exist as you knew them. You can still do similar things but it will be a bit more manual than you are used to.
- You need to understand more about how HTML and HTTP work. Details such as the difference between GET and POST become important.
- Many of the existing controls you use are not going to suit the MVC model. As well as the usual display controls this is going to affect things like AJAX.
Expect to spend a couple of weeks before you are really comfortable working with the new framework. The good news is that once you figure these things out you will be back to your old self again.
What Helps?
The new framework isn't really based on new ideas. In fact it's really built on tried and tested concepts, even if they are new to the average Microsoft developer. Here are some things from my past experience that help ease my transition:
- Knowing ASP.Net and IIS very well. Most of your knowledge about these technologies will still be useful. Though you wont be using web forms you will still have the other ASP.Net features to work with such as session state and output caching.
- Experience with unit testing. One of the key goals on the new framework is testability and if you aren't doing it you're probably missing out on a lot of the advantages. Unit testing can be tough to pick up in a hurry so any knowledge will help.
- Familiarity with domain driven design. I had already been working with patterns for a strong domain model distinctly separate from the user interface. Most of my existing work in this area carried over very smoothly.
- jQuery (or your JavaScript library of choice). It will definitely help if you're used to getting your hands dirty with JavaScript as you will find yourself building many features from scratch, features web forms has out of the box.
Working With Beta Bits
The framework is still in beta so it's not done and there will be changes. The core feels very solid and I haven't encountered any major bugs that have stopped me. More importantly realise that there is not yet good support from third party libraries to fill in the holes so things feel very bare bones in a lot of cases. One of the few resources out there is the MVC Contrib library.
Because the framework has already had 6 releases (5 previews, 1 beta) with breaking changes most of the information in blogs and forums is out of date and wont work exactly as described. Finding information on how things are now can be tricky and keeping Reflector nearby is recommended. The best information is still in Scott Gu's blog.
Freedom
I'm starting to settle in with MVC and it feels good. My XHTML validates as strict and I haven't had to do anything remotely resembling a hack or fudge. The framework is extensible in so many ways that web forms isn't so the few things I haven't liked I've been able to change.
Yes, it's worth it.
15/01/2009 02:20 AM (UTC -08:00)