Friday, April 30, 2010

I Am Not A Developer

I am not a developer.

I am a translator of user desires.

Developers too often are primarily technically-minded people. They care about new technologies and fun new "toys" they can play with. They care about such things as clean code and maintainability, which are great, but are only half the picture. In the end, clean and maintainable code is nothing more or less than the result of a human's ability to clearly organize their thoughts and speak them in a programming language.

Clearly organized thoughts come from clearly understanding the users' desires.

Think about it. Users want their computers to do certain things, but they lack the words necessary to tell the computer how to do it, which is why they hired you. They tell you what they want the computer to do, and you in turn tell the computer. This is translation. If you don't understand the business domain, you won't understand what they're saying, and you'll be inadequate at translating it. If you don't understand code, you may understand what they're saying, but you'll still be inadequate at completing the communication path. Regardless of whether the communication breakdown is between the users and you, or whether it's between you and the computer, it's still a communication breakdown, and you will have failed at your task.

Ultimately, users are going to measure the value of their programmers by their ability to not only communicate with them clearly, but to properly translate what they tell you into another language that the computer can understand. If you understand and speak both languages, you'll become the business users' best asset.

While the developer codes what the user says, the translator codes what the user intends, which is something that can only be done when the user is fully understood.

We are not developers. We tell the computer what the users want to tell them but can't because they don't speak the language.

Saturday, March 27, 2010

Writing Your Own HttpHandler in F# - Starting the Solution

So my friend, Ryan Riley, was talking to me the other day about building an HttpHandler using F#, but he had come across a problem... how to debug the handler using Visual Studio. Knowing how much it would irritate me not to be able to debug my F# web-related work, I set out to figure out how to get this kind of project started. I'm going to make this whole thing as simple as humanly possible. And when I say simple... I mean absurdly simple...

1. Create a new MVC web application.
2. Delete everything out of the project other than the web.config.
3. Remove all the references (all of them... I told you this would be absurdly simple...)
4. Now, add an F# class library project to the solution. Call it "FunctionalWeb.Framework".
5. Delete the .fsx file. (or if you feel strongly about it, don't.)
6. Add a reference in the F# class library to System.Web.
7. Rename Module1.fs to HttpHandler.fs.
8. Paste the following code within HttpHandler.fs file, and replace anything that's already there:

namespace FunctionalWeb.Framework

open System.Web;

type HttpHandler() =
interface IHttpHandler with
member this.ProcessRequest(context:HttpContext) =
context.Response.Write("Hello from a simple F# Http Handler!")
member this.IsReusable with get() = true

9. Add a reference to FunctionalWeb.Framework in your web project.
10. Replace the content of the web.config file with the following:

<?xml version="1.0"?>
<compilation debug="true" targetFramework="4.0">
<add verb="*" path="*" validate="false" type="FunctionalWeb.Framework.HttpHandler, FunctionalWeb.Framework"/>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true"/>
<remove name="FunctionalHandler"/>
<add name="FunctionalHandler" preCondition="integratedMode" verb="*" path="*" type="FunctionalWeb.Framework.HttpHandler, FunctionalWeb.Framework"/>

Your solution should look something like this (You may or may not have the nested files below the web.config):

11. Press F5. If all goes well, you should see something like this:

As long as you allowed Visual Studio to modify the web.config in order to allow debugging, you should be able to put a breakpoint in your F# HttpHandler file, and have Visual Studio hit the breakpoint.

Congrats! You've just gotten started building your own HttpHandler with F#.

Thursday, March 18, 2010

ASP.NET MVC isn't SOLID (or How to Rely on Abstractions in Views and Controllers)

MVC is a great framework for building web applications, however, there's at least one SOLID principle I feel could be implemented more thoroughly: Dependency Inversion Principle. Dependency Inversion Principle states that "code should depend on abstractions, not concretions." This can be seen in the views, where the generic type parameter of strongly-typed views is typically based on a concrete model:

<%@ Page Title="" Language="C#" MasterPageFile="../Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MyNamespace.Widget>" %>

It can also be seen in the controller, where POST actions may have parameters that are concrete:

public void Details([Bind] Widget widget)
// do something with the widget.

Ideally, it'd be nice to rely on an interface for both of these situations, however, it's a little harder than simply replacing Widget with IWidget in the controller and the view. Somehow MVC has to figure out which implementation to use with IWidget. This is where a little creativity and dependency injection can come in handy.

Internally, MVC uses a class called the DefaultModelBinder to reconstitute the strongly-typed view model from the posted form data sent via the POST. This class's "BindModel" method is called from the controller, and the type expected by the controller's action is passed as a property of the ModelBindingContext parameter expected by BindModel. There's a whole slew of things BindModel goes through to bind the form data onto the model, but the only thing we're interested in at the moment is how it creates an instance of an object based on a specific type. Turns out this is accomplished via the "CreateModel" method.

Now, the CreateModel method is very simple. Ultimately, unless the type expected is an IDictionary<T> or an IEnumerable<T>, it's going to simply make a call to Activator.CreateInstance, pass in the type requested, and return the result. Luckily for us, CreateModel is virtual, so we can override it with something like this:

public class DependencyInjectionModelBinder: DefaultModelBinder
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
object result;

// Attempt to get the value from ObjectFactory. If this fails
// use the default method of constructing the model.
if ((result = ObjectFactory.TryGetInstance(modelType)) == null)
result = base.CreateModel(controllerContext, bindingContext, modelType);

return result;

Next, we need to ensure this new model binder is the default model binder. To do this, we need to simply add this line in our global.asax.cs file, somewhere where it will be called from Application_Start():

ModelBinders.Binders.DefaultBinder = new DependencyInjectionModelBinder();

So, now we have a DependencyInjectionModelBinder registered as our default model binder for our application. Now, supposing that Widget implements IWidget, and you want your view and controller to rely on IWidget instead of Widget, you need to ensure you've registered Widget as the default concrete class of IWidget. Add this line so it will be called from the Application_Start method in the global.asax.cs file:

ObjectFactory.Configure(x => x.For<IWidget>().Use<Widget>());

Lastly, we need to change our view and our controller to use the interface instead of the concrete class:


<%@ Page Title="" Language="C#" MasterPageFile="../Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MyNamespace.IWidget>" %>


public void Details([Bind] IWidget widget)
// do something with the widget.

That's it! You've now made MVC more SOLID by adhering to dependency inversion principle in your controller and your view. Nowhere in your application, other than when registering Widget as the default implementation of IWidget, should you need to directly reference Widget as a concrete class.