Archive

Archive for February, 2009

Junior developers beware, SOLID principles and design patterns are indeed useful for you

February 13th, 2009 Comments off

I have several times disagreed with Jeff. They are just rare occasions though, given the amount of blog posts he wrote and I read (and agreed with). However, given his popularity as a blogger, any misleading advice may be highly destructive to junior software developers who may turn to his blog for advices. This time around, Jeff bashes guidelines, rules, and checklist with SOLID principles being one of the targets.

Now, young developers, before you start throwing away all the books about design patterns, agile, OO principles etc., let me tell you one thing: if Jeff Atwood is a better developer at all today, it’s because he has learned from the rules preached by more knowledgeable people. Don’t believe? Read this. There you go, Jeff Atwood as a fan of Code Complete, a 900-page book full of coding rules, was so much interested in the book that he even named his blog after one of the book’s symbol. He just seems to forget about where he came from when he wrote:

While I do believe every software development team should endeavor to follow the instructions on the paint can, there’s a limit to what you can fit on a paint can. It’s the most basic, most critical information you need to proceed and not make a giant mess of the process. As brief as the instructions on a paint can are, they do represent the upper limit of what most people will realistically read, comprehend, and derive immediate benefit from.

It’s normal for a very experienced developer to rely mostly on his judgment instead of a set of rules and principles to do thing. But it’s just uncool for such an experienced developer to advise the newbies to do the same thing, i.e. they’d better use their judgment first before resorting to the distilled and valuable knowledge taught by others.

…I’ve found less and less use for rules in my career. Not because I’m a self-made genius who plays by my own rules, mind you, but because I value the skills, experience, and judgment of my team far more than any static set of rules… Rules, guidelines, and principles are gems of distilled experience that should be studied and respected. But they’re never a substute for thinking critically about your work.

The thing is people are not born making good judgment. And one of the best ways to sharpen one’s judgment is to learn from the knowledge of those people who have made good judgment. Only after one has practiced these teachings long enough, making a lot of right and wrong decisions based on these teachings, one will for the first time, really understand about them and don’t have to think about them any longer as they have become part of one’s instinct. That should be the thing experienced developers teach junior developers, not this:

The types of developers who could benefit from SOLID a) aren’t thoughtful enough about their work to care and b) won’t read much of anything

Don’t get me wrong, I respect many of Jeff’s opinions, but I think he should feel more responsible for his influence on those developers who are new to the industry and seek for advices from his writings. Obviously no one man is perfect and Jeff, like any other, doesn’t necessarily always have great things to say. But at least he should acknowledge that he’s wrong when he’s wrong.

Appendum 2/14
On the contrary to what I think Jeff Atwood should do in the previous paragraph given the large amount of thoughtful comments from many of his readers, he seems to dig himself deeper into the hole with his follow-up post.

ASP.NET MVC Validation Library

February 10th, 2009 3 comments

Inspired by the work of Emad Ibrahim, I set out to develop a validation library for ASP.NET MVC. Besides trying to meet the same objectives as Emad Ibrahim’s library, i.e. model-based validation, integration with the jQuery validation plugin, and little or no duplication between client-side and server-side validation, these are the differences of my library:

  • Built for MS Validation Application Block. (Emad Ibrahim’s library targets Castle’s validation framework. Check out his library if you need this feature.)
  • Allow users to specify the properties to be included in a server-side validation. This is useful in situation in which you use part of the model in some pages (e.g. Change Password page only uses the Password field of the User entity).
  • Allow users to tell the client-side code generator to generate script to ignore missing DOM elements. This feature goes nicely with the above feature. The generator could have been implemented to receive a list of properties to generate client script for but I have not made up my mind yet whether this is a better approach or not.
  • Allow users to specify whether they want the validation initialization code to be generated or not. This is particular useful if you want to customize the validation initialization code differently for different pages.

How does it work?
The idea of the library is that one should be able to decorate an entity object with some validation attributes and then have that entity validated at both the server-side and client-side with the minimum amount of code. Let’s say you have a User entity in your application, you can annotate it as follows:

public class User
{
     [NotNullOrEmptyValidator(MessageTemplate = "Name is required")]
     [StringLengthValidator(6, 20, MessageTemplate = "Name must be between {3} and {5}")]
     public string Name { get; set; }

     [NotNullOrEmptyValidator(MessageTemplate = "Email is required")]
     [EmailValidator(MessageTemplate = "Invalid email address")]
     public string Email { get; set; }

     [NotNullOrEmptyValidator(MessageTemplate = "Location is required")]
     public string Location { get; set; }

     [NotNullOrEmptyValidator(MessageTemplate = "Password is required")]
     [StringLengthValidator(6, 50, MessageTemplate = "Password must be between {3} and {5}")]
     public string Password { get; set; }
}

Now, whenever this entity is populated with form posted values, you can perform server-side validation by invoking the Validate() extension method on the entity. Let’s do that in the action method.

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditUser([Bind(Prefix="")]User user)
{
     try
     {
          user.Validate<User>();
     }
     catch (EntityValidationException ex)
     {
          ViewData.ModelState.PopulateWithErrors(ex);
     }
     return View();
}

The above code will perform validation on the entity given its validation attributes. If there’s any validation error, an EntityValidationException object is thrown and you can use it the populate the model state with error messages. The method PopulateWithErrors is another extension method provided by the library.

If you want to limit the properties to be validated (e.g. in a password change scenario), you can pass an array of property names into the Validate() method.

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ChangePassword([Bind(Prefix="")]User user)
{
     try
     {
          // Only validate the password property
          user.Validate<User>(new[] {"password"});
     }
     catch (EntityValidationException ex)
     {
          ViewData.ModelState.PopulateWithErrors(ex);
     }
     return View();
}

I could have added a custom model binder to the library so that validation happens at the model binding phase but I think that’s not a flexible approach since in many cases we would want to perform validation in the service layer instead so that the validation takes place consistently for any client of the service.

Let’s see the result of the server-side validation:

Okay, let’s move to client-side validation. The trick behind the client-side validation is that the view will invokes the HtmlHelper’s ClientSideValidation() extension method which will retrieve all validation attributes of the specified entity type (e.g. User) and generate equivalent client-side validation script for them.

Currently, while you can apply as many validation attributes to an entity as you like and the server-side validation will work perfectly fine, only a couple of validation rules are supported by the client-side code generator, namely required field validation, string length validation, and email validation. These3 rules are sufficient for my current need and I will add more on a needed basis (or you can download the code and implement more rules yourself.)

There are a couple of overloads of the ClientSideValidation() method:

// Generates validation script for the User type
Html.ClientSideValidation<User>();

// Generates validation script for the User type, including the code to initialize form validation
Html.ClientSideValidation<User>(string formName);

// Generates validation script for the User type and adds necessary code to avoid JavaScript error if one or
// more properties in the User type do not match with any DOM element.
Html.ClientSideValidation<User>(bool ignoreMissingElements);

// See the above 2 overloads
Html.ClientSideValidation<User>(string formName, bool ignoreMissingElements);

For example, the generated code for an invocation of the second overload will result in the following code:

<script language="JavaScript"><!--
$().ready(function() {

$("#edit-user-form").validate();
$("#name").rules("add", {
	minlength : "6", maxlength : "20",
	required : true,
	messages: {
		minlength : "Name must be between 6 and 20", maxlength : "Name must be between 6 and 20",
		required : "Name is required"

	}
});

$("#email").rules("add", {
	required : true,
	email : true,
	messages: {
		required : "Email is required",
		email : "Invalid email address"
	}
});

$("#location").rules("add", {
	required : true,
	messages: {
		required : "Location is required"

	}
});

$("#password").rules("add", {
	minlength : "6", maxlength : "50",
	required : true,
	messages: {
		minlength : "Password must be between 6 and 50", maxlength : "Password must be between 6 and 50",
		required : "Password is required"
	}
});

});
--></script>

That’s it, you don’t need to write a single line of JavaScript to have this nice client-side validation:

How can I download and use it?
The library is hosted at CodePlex. I have built it with ASP.NET MVC Beta, Enterprise Library 4.1, jQuery 1.2, and jQuery validation plug-in 1.5. You might need to make a couple of changes if you want it to work with a different version of those libraries. Any bug, please post on the project page instead of posting here. Thanks & hope you’ll find the library useful.