Learning new stuff as a developer

March 12th, 2011 / Comments

Constant learning is vital to most careers but it is especially vital for developers. Learning is rewarding and addictive, but also difficult. It takes time, determination and motivation to push yourself out of your comfort zone and reach the next camp in the ascent of your career. There’s no room for stupid pride either so be prepared to :

  • ask stupid questions of people who know what you want to know
  • feel confused after reading that page for the third time
  • bow to those of superior knowledge
  • feel overwhelmed

Ultimately what really matters is that you slowly but surely insert information into your databrain and keep it there.

I started to take learning seriously about 6 years ago. Prior to that I was in the pleasure zone known as IGNORANCE where I thought I knew all I needed to and that I was somehow immune to having to learn stuff. That’s ignorance all over, you don’t know what you need to know so it doesn’t exist, right? Slowly that changed as I started to buy more tech books and write more code in my spare time. My delusions of grandeur were tested to their brittle limits

But I had a problem…. I wasn’t very good at learning. I would read a book but nothing much would happen. I’d forget things I’d read about or used before, or I’d have no frame of reference on which to hang new information. That’s when I begun to take learning how to learn seriously.

Learning how to learn. Is that right?!

Yep that’s right there are loads of techniques for learning stuff. I started with the assumption that I had problems committing information to memory so I got into mnemonics and other memory techniques. I bought half a dozen (that’s six) of the Tony Buzan books and came up with elaborate story methods, journey methods, location methods, peg methods and the beginnings of a number system. Got nowhere with those as I wasn’t able to (or didn’t try hard enough to) translate the kind of programming information I was learning into any of these methods. After about six months (that’s half a dozen) I scrapped it, then moved onto mind maps.

Free your mind with FreeMind

I had a great time with FreeMind. The first thing I did was change the default style and colours to this custom patterns.xml file because out of the box it looks bland (or it did when I started using it). I find mind maps to be a great way of organising information together but in the end I concluded that they are clunky, non-portable and complex. I know the whole point of a mind map is to keep it simple and use minimal and sharp wording but is this suited to learning typical programmer information? Look at this fraction of one of my mind maps and you tell me :

And here’s the same mindmap fully expanded :


Viewing these mind maps is only possible in FreeMind itself (although you can export to a web page and PDF now too). The other problem is that the mind maps are just visually huge and the interface is fiddly. Finally there are just too many little steps to take when you want to note something down. And that’s the whole problem. When learning stuff I want to take notes immediately and move on. For me it has to be transient, simple and unobtrusive.

I still use FreeMind but not for taking learning notes.

In my next post I’ll emit more off-scented verbage about where this all ended up and how I take notes nowadays.

In a nutshell it’s a mixture of low tech and high tech :

  • 6×4″ index cards
  • The excellent ZIM wiki
  • A Samsung Galaxy Tab
  • The Kindle app
  • Photo scanner

Inspiration , Productivity

Comments

ASP.NET MVC [Remote] validation – what about success messages?

January 27th, 2011 / Comments

Since ASP.NET MVC 3 it’s easy to validate an individual form field by firing off a HTTP request to a controller action. This action returns either Json(true) if the value is valid or a Json(“error message”) if it is not valid. If you return an error then jquery.validate.js will add your error message to the validation element for the field being validated. It’s easy to setup on your view model :

	[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email address")]
[EmailAddress]
[Remote("RemoteValidation_UniqueEmailAddress", "Account")]
public string Email { get; set; }
	

When the user makes a change to the Email field the /Account/RemoteValidation_UniqueEmailAddress action is automatically called on the server. The server side action is just as simple to setup :

	public ActionResult RemoteValidation_UniqueEmailAddress( string Email)
{
   object oResult = false;
   if( Validation.IsEmailAddress( Email) == false)
   {
      return Json( "Please enter a valid email address", JsonRequestBehavior.AllowGet);
   }
   else if( m_oMembershipService.IsThisEmailAlreadyTaken( Email) == true)
   {
      return Json( "This email address is already in use", JsonRequestBehavior.AllowGet);
   }
   else
   {
      return Json( true, JsonRequestBehavior.AllowGet);
   }
}
	

A remote validation error is displayed in exactly the same way as a view would render it. This is because the javascript latches onto the Html.ValidationMessageFor element you setup in your view :


This is ok isn’t it? But…

I want the Email Address label to be bold and red too

In the interests of best practice web form techniques I want the email address label to be bold and red, as well as the error message. To do this I had to hack jquery.validate.js so that it calls a local javascript function with the same name as the server function (with “_response” appended to it) :

	remote: function(value, element, param) {
    if ( this.optional(element) )
        return "dependency-mismatch";
 
    var previous = this.previousValue(element);
    if (!this.settings.messages[element.name] )
        this.settings.messages[element.name] = {};
 
    previous.originalMessage = this.settings.messages[element.name].remote;
    this.settings.messages[element.name].remote = previous.message;
 
    param = typeof param == "string" && {url:param} || param;
 
    if ( previous.old !== value ) {
        previous.old = value;
        var validator = this;
        this.startRequest(element);
        var data = {};
        data[element.name] = value;
 
        $.ajax($.extend(true, {
            url: param,
            mode: "abort",
            port: "validate" + element.name,
            dataType: "json",
            data: data,
            success: function(response) {
 
                //START OF HACK
                var aParts = param.url.split(/\//);//eg; param.url = "/Account/RemoteValidation_UniqueEmailAddress"    ELMS
                oCustomResultFunction = aParts[aParts.length - 1] + "_response";//ELMS
                //END OF HACK
 
                validator.settings.messages[element.name].remote = previous.originalMessage;
                var valid = response === true;
 
                if ( valid ) {
                    var submitted = validator.formSubmitted;
                    validator.prepareElement(element);
                    validator.formSubmitted = submitted;
                    validator.successList.push(element);
 
        //START OF HACK
        var bShowErrors = true;
        if( typeof(window[oCustomResultFunction]) == "function")
        {
            bShowErrors = window[oCustomResultFunction]( true, null, validator);
        }
        //END OF HACK
 
        if( bShowErrors)//HACK
        {
            validator.showErrors();
        }
 
        }
        else
        {
            var errors = {};
            var message = (previous.message = response || validator.defaultMessage( element, "remote" ));
            errors[element.name] = $.isFunction(message) ? message(value) : message;
 
            //START OF HACK
            var bShowErrors = true;
            if( typeof(window[oCustomResultFunction]) == "function")
            {
                bShowErrors = window[oCustomResultFunction]( false, errors, validator);
            }
            //END OF HACK
 
            if( bShowErrors)//HACK
            {
                validator.showErrors(errors);
            }
        }
 
        previous.valid = valid;
        validator.stopRequest(element, valid);
    }
}, param));
        return "pending";
    } else if( this.pending[element.name] ) {
        return "pending";
    }
    return previous.valid;
},
	

And now a client side javacsript function called RemoteValidation_UniqueEmailAddress_response will be called with the result of the remote validation. In this example I know that the function only targets the Email field but it’s wise to check the errors collection that comes back in case other model errors were added in the server function (see the outcommented code below). The aErrors collection is keyed on the client side ID of the invalid field/s :

	function RemoteValidation_UniqueEmailAddress_response( bIsValid, aErrors, oValidator)
{
    if( bIsValid == false)
    {
        /* This bit is optional
        for( var sId in aErrors)
        {
            $("label[for=" + sId + "]").addClass( "error").css( "font-weight", "bold");
        }*/
 
        $("label[for=Email]").addClass( "error").css( "font-weight", "bold");
    }
    else
    {
        $("label[for=Email]").removeClass( "error").css( "font-weight", "normal");
    }
 
    return true;
}
	

The first argument to the function is whether there is an error or not. The second parameter is the errors collection. Now when I enter an invalid email address my form looks like this

That’s better but something is still bothering me

Success messages would be nice

As well as catering for validation errors you now get the chance to provide success feedback as well which can be just as important as error feedback. For example if the user is registering on a site and choosing a username the validation could check that the username is available. If it is then you can present a jolly green tick to the user. This completely removes ambiguiuty, especially if the previous username they entered was already taken and they saw a validation error

One last bit of code :

	var g_bEmailHasBeenInErrorState = false;
function RemoteValidation_UniqueEmailAddress_response( bIsValid, aErrors, oValidator)
{
    if( bIsValid == false)
    {
        $("label[for=Email]").addClass( "error").css( "font-weight", "bold");
        g_bEmailHasBeenInErrorState = true;
    }
    else
    {
        $("label[for=Email]").removeClass( "error").css( "font-weight", "normal");
 
        if( g_bEmailHasBeenInErrorState)
        {
            g_bEmailHasBeenInErrorState = false;
 
            $("#Email").after( "<img style='float:left;' src='<%=Url.Content( "~/Content/img/tick.gif")%>' alt='This is a valid email for this web site' />");
        }
    }
 
    return true;
}
	

Hang on a minute. Why isn’t this functionality in jquery.validate.js anyway? Go to your room!

I didn’t refer once to AJAX because :

  • XML is moribund everywhere but the enterprise.
  • IE had javascript HTTP requests before the web existed.
  • Prior to that you could just screen scrape a hidden iframe for crying out loud!

ASP.NET MVC , jQuery , UI

Comments

MongoDB and ASP.NET MVC – A basic web app

January 16th, 2011 / Comments

I first heard about document databases (NoSql) last year thanks to Rob Conery’s blog post. At the time I couldn’t imagine a database without SQL but there really is such a thing and MongoDB is a leading example. Today I’ve spent some time working with MondoDB putting together a basic ASP.NET MVC web application to CRUD a bugs database.

A document database differs from a relational database in that, when you can get away with it, a record (known as a document here) can contain all it’s own data. It is not necessary to have normalised tables with joins pulling data together into a result set. Instead of having an order table, a product table, a customer table, an address table etc… you can have a single record containing all this information.

Here is an example of a single record for a user :

	{
    "name": "Mr Card Holder",
    "email": "[email protected]",
    "bankAccounts":
    [
        {
            "number": "12332424324",
            "sortCode": "12-34-56"
        },
        {
            "number": "8484949533",
            "sortCode": "11-33-12"
        },
    ],
    "address":
    {
        "address1": "100 The Big Road",
        "address2": "Islington",
        "address3": "London",
        "postCode": "LI95RF"
    }
}
	

And that’s how the record is stored in the database; the exact opposite of a normalised database. The user’s bank accounts are stored in the user document. In this example a user’s bank accounts are unique to that user so it’s ok to store them right there. But what about when the associated information needs to be more centralised such as an author’s list of published books? What happens when there are multiple authors on a book? In this case you would have a separate collection for the books and put the list of book ObjectIds in the author document. Like this :

	{
    "name": "Mr Author",
    "email": "[email protected]",
    "publishedBooks":
    [
        {"id": "12332424324"},
        {"id": "5r4654635654"},
        {"id": "5654743"}
    ],
    "address":
    {
        "address1": "142 The Other Road",
        "address2": "Kensington",
        "address3": "London",
        "postCode": "L92RF"
    }
}
	

After loading the author from MongoDB you would then perform a second query to load the associated books.

The data is stored in BSON format (a binary format of JSON). You still get indexes and the equivalent of where clauses, the simplicity is not at the cost of functionality. Pretty much the only thing you don’t get are complex transactions.

I wanted to try this out for myself so I installed MongoDB and saw it working from the command line and then started looking into a C# driver. After a quick look around the internet it seems that there are two main options for C# drivers :

I chose the official driver because, although it isn’t as mature as Sam Corder’s driver, I’d already started reading the docs for it.

A day in Visual Studio and a JSON Viewer

First I wrote a very rudimentary membership provider that uses the Mongo database. This lets you register on the site and then login which is enough for my test. Hopefully the MongoDB guys will release a complete ASP.NET membership provider soon.

Secondly I wrote an ASP.NET MVC controller, domain class and MongoDB bug repository to help me figure out how to work with a Mongo database using C#. The BugRepository class contains database code like this :

	public Bug Read( string sId)
{
    MongoServer oServer = MongoServer.Create();
    MongoDatabase oDatabase = oServer.GetDatabase( "TestDB");
    MongoCollection aBugs = oDatabase.GetCollection( "bugs");
 
    Bug oResult = aBugs.FindOneById( ObjectId.Parse( sId));
 
    return oResult;
}
 
public Bug Update( Bug oBug)
{
    MongoServer oServer = MongoServer.Create();
    MongoDatabase oDatabase = oServer.GetDatabase( "TestDB");
    MongoCollection aBugs = oDatabase.GetCollection( "bugs");
 
    aBugs.Save( oBug);
 
    return oBug;
}
	

If, like me, you are just getting started using MongoDB with C# you may find it useful to see the code so here is the source code for the test app. You’ll need Visual Studio 2010 and MVC 3. This is what you’ll get :

My main resources while figuring this out were :

One more thing. Document databases are absolutely perfect for content management systems. One of the challenges for a CMS is handling dynamic schemas and in relational databases this usually involves at least two generic looking tables. To a document database the collection schema is a trivial concept, it just doesn’t care! You can add new properties to a collection whenever you feel like it, even when there is huge amount of data already there. Drupal has already integrated MongoDB I expect more to follow.

ASP.NET MVC , MongoDB

Comments