Jon Kruger -
  • About Me
  • Blog
  • Resume
  • Values
  • Presentations
About Me
Blog
Resume
Values
Presentations
  • About Me
  • Blog
  • Resume
  • Values
  • Presentations
Jon Kruger
Uncategorized

Pulling others up

If there’s one thing that everyone in software development can agree on, it’s that everyone has an opinion on what the best way is to do things. We have lots of books, blogs and articles touting “best practices” and telling us how to do things (and how not to do things).

Often times as a consultant, you are brought into an IT shop where the native developers aren’t using the latest and greatest technology and might not be using the so-called “best practices” that you subscribe to. Usually in these situations, the people that brought you in are bringing you in for your expertise and are expecting you to do things the right way. This can lead to the native developers feeling somewhat threatened.

Recently a friend of mine started at a new client and noticed that the developers there were do most of their data access through dynamic SQL written in their C# code. When he questioned why they did it that way, the developers got defensive, saying things like, “We’ve been doing it that way for years and it’s been working for us.”

While the “best practices” would not recommend you doing all of your data access this way, it dawned on me, this guy is exactly right. He’s been writing his dynamic SQL for years, and he’s been succeeding in delivering working software. So in his mind, he’s not doing anything wrong.

There are two ways of handling this situation. The one that many people choose it to rip on the guy for being so stupid for ever thinking of doing it that way, while saying things like, “No one does it that way anymore”. All this does is alienate the developer and turn them off from trying to learn something new.

The preferred method is to show them that there is a better way. I once asked Andy Hunt how to get people who don’t write unit tests to start writing unit tests. His answer was that I needed to show them what was in it for them. I don’t think he could’ve been more correct. No one wants to do something just because it’s a “best practice” or some smart person said you should do it that way. We’ve all worked with people or seen projects where some “smart” person made something way more complicated than it needed to be and no one else could understand what they did or how to write code using their framework. No one cares if those people used “best practices”, you just hate having to come to work and deal with the mess that they made.

So if you’re working with someone and you think that there is a better way than how they’re doing something, show them the better way. Acknowledge the fact that what they are doing is working for them (they probably wouldn’t be doing it if it wasn’t). Just don’t belittle them for doing it that way, because they may be doing the best that they can.

June 30, 2009by Jon Kruger
LINQ

LINQ to SQL is NOT dead!

Ever since Microsoft announced that the Entity Framework was their ORM of choice, people everywhere have been saying, “LINQ to SQL is dead!” A lot of people feel like they’re not allowed to use LINQ to SQL anymore and that they have to use Entity Framework instead.

In fact, LINQ to SQL is not only alive and well, Microsoft has even announced LINQ to SQL improvements in .NET 4.0, including finally adding using ITable<T> for tables instead of Table<T>, which makes it much easier to test. Combine that with this open source tool that will create an IDataContext interface for you and you’re on your way to testable LINQ to SQL. So no, LINQ to SQL is not dead!!

Look, just because Microsoft says you should do something a certain way doesn’t mean that you have to do everything that they say. For example, Microsoft will almost never recommend using an open source software package over something that they’ve built (I say almost never because I’m sure they’ve done it at some point, but I’ve never seen it done). That certainly doesn’t mean that the Microsoft product is better than every open source tool.

For example, if you’re going to use an ORM, LINQ to SQL can get the job done for you, but if you’re looking for an ORM with more features, you owe it to yourself to check out Fluent NHibernate.

June 6, 2009by Jon Kruger
ASP.NET MVC

Why ASP.NET MVC is better than WebForms: Repeatability

A lot of people out there are asking, “Why is ASP.NET MVC better than WebForms?” or “Why should I switch from WebForms to MVC?” Usually the response includes these items:

  • Clear separation of concerns
  • Testability – support for Test-Driven Development
  • Fine-grained control over HTML and JavaScript

This doesn’t always mean much if people don’t do TDD and are fine without fine-grained control over HTML and JavaScript.

I’d like to add one more thing to the list: repeatability. Most of us are writing line-of-business applications, and when you write these kinds of web sites, there are common UI patterns that emerge:

  • A grid that contains a list of data, and might have Add/Edit/Delete buttons above it.
  • A screen that contains a bunch of input fields and Save and Cancel buttons.
  • If you save a screen with input fields and a validation error occurs, go back to the same screen and show the validation errors at the top of the screen.

Here’s where the repeatability comes in. Let’s take the Add/Edit/Delete grid screen as an example. I should be able to write code to handle this pattern once and never have to do it again. The next time I do this screen, I should only have to write code to do the following:

  • Tell the grid what data to display
  • Tell the grid which buttons to show (if any)

The code looks like this:


    <%= Html.JQueryGrid()
        .LoadDataFromUrl("/customers/GetCustomerData")
        .AddEditDeleteButtons()
        .Caption("Customers")
        .ExpandToFitAllRows()
        .Columns(columns =>
        {
            columns.For(x => x.Id).Visible(false);
            columns.For(x => x.CompanyName).AsEditLink();
            columns.For(x => x.Address);
            columns.For(x => x.City);
            columns.For(x => x.State).Width(50);
            columns.For(x => x.Zip).Width(50);
            columns.For(x => x.CompanyEmail);
            columns.For(x => x.PhoneNumber).Width(100);
            columns.For(x => x.FaxNumber).Width(100);
            columns.For(x => x.Salesperson).Width(100);
        }) %>

Pretty clear what that does, right?

Notice what I’m not writing:

  • Code that tells the site what to do when Add, Edit, or Delete are clicked
  • Code that enables/disables the buttons based on what is selected in the grid
  • Grid paging code (other than stored proc or LINQ code that handles this, if necessary)
  • Any JavaScript code (it’s all spit out by the code that renders the grid HTML)

I could write the code to do these things, but I’m not going to unless I have to because I need to do something different than the norm. I’m going to let my conventions and HTML helpers do the work.

So why is MVC better at this than WebForms? Because of separation of concerns. In this case, separation of concerns does not mean having a presentation layer, business layer, and data access layer. I’m talking about separation of concerns within the UI layer (your business layer and data access layer will be the same regardless of whether you use MVC or WebForms).

Let’s say that I have a screen with a grid with a list of data. The grid has a pager and Add/Edit/Delete buttons. Here are all of the pieces and parts that go into implementing this in MVC:

  • HTML code for the page – View
  • Code that writes out HTML and JavaScript for grid – HTML helper fluent interface + HTML renderer + jQuery grid
  • Get data for the view – controller method
  • Store data for the view – view model, populated with very little or no code using AutoMapper
  • Handle AJAX requests from the grid pager – model binder, which passes data to controller
  • Return data in a format the grid pager can understand – method on base controller class (lets MVC convert data to JSON and call Response.Write())
  • Verify security permissions – action filter attributes on controller methods
  • Handle Add/Edit/Delete button clicks – JavaScript written out by HTML grid render
  • Determine which screen to show when button is clicked – action filter attribute
  • Get data for Add/Edit/Delete screens – controller method

How would you do this in WebForms?

  • HTML code for the page – View
  • Code that writes out HTML and JavaScript for grid – 3rd party grid control
  • Get data for the view – code behind (calling into business layer)
  • Store data from the view – copied into controls in code behind
  • Handle AJAX requests from the grid pager – web service, configured to accept AJAX requests
  • Return data in a format the grid pager can understand – some method + JSON formatter + Response.Write()
  • Verify security permissions – code behind
  • Handle Add/Edit/Delete button clicks – custom JavaScript
  • Determine which screen to show when button is clicked – code behind
  • Get data for Add/Edit/Delete screens – code behind (calling into business layer)

Notice the pattern? In WebForms the code behind is doing a lot (not to mention the fact that you can’t easily unit test code behind files). Big code behind files do not lend themselves to repeatability — but small classes that have specific responsibilities are very reusable. This is why separation of concerns matter. In my MVC screen, I deal with a view, controller, view model, model binders, HTML helpers, grid renders, and action filter attributes. In WebForms, I have a view and a code behind.

Having these small classes leads to reusability. I can use the HTML helper that renders the grid for my page on another page that renders a grid. I can create a controller attribute that will check to see if a user is logged in, or in a certain role. I now never have to write code to check that again – I just put an attribute on a controller method and I’m done with security.

It’s also amazingly easy to write code when you’re working with small, specific classes. Can you tell me what this attribute does?

[RequiresPermission(Permissions.AddUser)]

How about this one?

[RedirectWhenGridToolbarButtonClicked]

All of this leads to reusability, less bugs, code that is easy to read and write, and less development time. The ultimate goal is less development time and better quality. By reusing code, you get things done faster (because you write less code) and you have fewer bugs (because you write less code).

On my current project, development time is way down. The screen that I’ve been talking about with the grid and Add/Edit/Delete buttons and paging, and all that? Done in 2 hours. Basic input screen with validation – 4 hours. The first screen with a grid took a few days, but I wrote all the HTML helpers and renderers that write out the HTML and JavaScript for the grid, wrote the model binder that takes HttpRequest form inputs and calls controller methods (based on conventions), and wrote all the code to receive AJAX requests and send back a response. On the next screen, I call my HTML helper methods that write out the grid HTML and pass it some configuration parameters, create some controller methods that load and save data, and I’m done.

This post didn’t cover MVC basics, like what controllers, view models, and model binders are. There are plenty of posts that explain that. I’m just hoping to explain that the reusability of ASP.NET MVC can drastically reduce development time and make things a lot easier for you.

May 26, 2009by Jon Kruger
.NET, ASP.NET MVC, unit testing

Hiding Thread.CurrentPrincipal from your code

You can get information about the current user who is logged in using Thread.CurrentPrincipal. The problem with this is that it’s difficult to work with it in tests. It forces you to set the current principal in your test setup so that your code will work correctly, and this can be difficult if not impossible in situations where you’re using Windows Authentication (if you’re using Forms Authentication, it’s not quite as painful, but it’s still a pain).

I don’t like to actually have calls to Thread.CurrentPrincipal scattered throughout my code. It makes my code less readable. Usually if I’m checking the principal, I want to know what user is logged in. That leads to code like this:

var currentUser = null;
var principal = Thread.CurrentPrincipal as MyCustomPrincipal;
if (principal != null)
    currentUser = ((MyCustomPrincipal) Thread.CurrentPrincipal).User;

Ick. I don’t want to write this over and over throughout my code. What if I had a class called PrincipalFactory that dealt with everything having to do with the principal? My class could look like this:

public class PrincipalFactory : IPrincipalFactory
{
    public MyCustomPrincipal GetCurrent()
    {
        return Thread.CurrentPrincipal as MyCustomPrincipal;
    }

    public User GetCurrentUser()
    {
        var principal = GetCurrent();
        return (principal != null ? principal.User : null);
    }

    public void SetCurrentUser(User user)
    {
        Thread.CurrentPrincipal = new MyCustomPrincipal(user);
    }
}

Now when I want to know who the current user is, I can write…

var currentUser = _principalFactory.GetCurrentUser();

Isn’t that much easier on the eyes?

It’s much easier to test too. I always use dependency injection and StructureMap, which also makes testing easier. Let’s say I had a class like this:

public class AccountController : Controller
{
    private IPrincipalFactory _principalFactory;

    public AccountController(IPrincipalFactory principalFactory)
    {
        _principalFactory = principalFactory;
    }

    [Authorize]
    public ActionResult Index()
    {
        var model = new IndexViewModel();
        model.WelcomeMessage = "Hello, " + _principalFactory.GetCurrentUser().Username;
        return View(model);
    }
}

In my test code, I’m going to use Rhino Mocks to stub out the IPrincipalFactory. So the test will essentially pretend that a user named “Jon” is the current user and then we’ll make sure that the Index() method does the right thing.

using System;
using NUnit.Framework;
using Rhino.Mocks;

[TestFixture]
public class When_displaying_the_index_view()
{
    [Test]
    public void Should_display_the_welcome_message_for_the_current_user()
    {
        // Arrange
        var principalFactory = MockRepository.GenerateStub();
        principalFactory.Stub(pf => pf.GetCurrentUser()).Return(new User { Username = "Jon" });

        var controller = new AccountController(principalFactory);

        // Act
        controller.Index();

        // Assert
        Assert.IsTrue(((IndexViewModel)_controller.ViewData.Model).WelcomeMessage, Is.EqualTo("Welcome, Jon"));
    }
}

This is much easier and cleaner than having to deal with Thread.CurrentPrincipal all over the place. If you didn’t hide Thread.CurrentPrincipal inside the PrincipalFactory class, you could still test it by setting Thread.CurrentPrincipal in the beginning of your test. I’ve been on projects that did it this way, and inevitably someone forgets to set Thread.CurrentPrincipal back to what it was before the test, or an exception happens and somehow the code that sets it back to the original value doesn’t run, and now tests will have different outcomes depending on what order you run them and which ones you run. This is usually a real pain to debug because you don’t know which test is causing the problem. Not fun.

April 13, 2009by Jon Kruger
SQL, TDD, unit testing

Writing tests for stored procedures

With all of the talk about unit tests and test driven development, there is little talk about writing tests for stored procedures and other database code. I would argue that testing stored procs is just as important (if not more important) than testing .NET code because (a) you don’t recompile all of your SQL code when you change something and (b) bugs in stored procs can lead to really bad things like data corruption that are hard to fix.

Writing tests for database code is not rocket science. There are no SQL testing frameworks to learn (at least I don’t know of any), but that’s fine because you can do just fine with plain ol’ T-SQL.

Let’s say I have a database that looks like this:

create table Users
(
    UserId int not null primary key identity(1,1),
    Username varchar(255)
)

create table Roles
(
    RoleId int not null primary key identity(1,1),
    RoleName varchar(255)
)

create table UsersInRoles
(
    UserId int not null, -- foreign key to Users
    RoleId int not null, -- foreign key to Roles
)

And let’s say that we were going to write a stored proc that looks like this:

create procedure [dbo].[IsUserInRole]
(
    @UserId int,
    @RoleId int
)
as
begin

if exists (select 1 from UsersInRoles where UserId = @UserId and RoleId = @RoleId)
    return 1
return 0

end

We can easily write a test for this. The test might look like this:

create procedure [dbo].[unittest_IsUserInRole]
as
begin

begin transaction

-- set stuff up
declare @UserId int
declare @AnotherUserId int
declare @RoleId int
declare @AnotherRoleId int

insert into Users (Username) values ('test')
set @UserId = scope_identity()

insert into Users (Username) values ('another user')
set @AnotherUserId = scope_identity()

insert into Roles (RoleName) values ('test role')
set @RoleId = scope_identity()

insert into Roles (RoleName) values ('another test role')
set @AnotherRoleId = scope_identity()

insert into UsersInRoles (UserId, RoleId) values (@UserId, @RoleId)

-- test stuff
declare @result int

-- should return true if the user is in the role
exec @result = IsUserInRole @UserId, @RoleId
if @result <> 1
raiserror('Test failed: should return true if the user is in the role', 16, 1)

-- should return false if user is not in the role but is in another role
exec @result = IsUserInRole @UserId, @AnotherRoleId
if @result <> 0
raiserror('Test failed: should return false if user is not in the role but is in another role', 16, 1)

-- should return false if user is not in the role but another user is in the role
exec @result = IsUserInRole @AnotherUserId, @RoleId
if @result <> 0
raiserror('Test failed: should return false if user is not in the role but another user is in the role', 16, 1)

-- should return false if the user does not exist
declare @NonExistantUserId
select @NonExistantUserId = max(UserId) + 1 from Users
exec @result = IsUserInRole @NonExistantUserId , @RoleId
if @result <> 0
raiserror('Test failed: should return false if the user does not exist', 16, 1)

-- should return false if the role does not exist
declare @NonExistantRoleId
select @NonExistantRoleId = max(RoleId) + 1 from Roles
exec @result = IsUserInRole @UserId, @NonExistantRoleId
if @result <> 0
raiserror('Test failed: should return false if the role does not exist', 16, 1)

rollback transaction

end

Notice that I’m beginning a transaction at the beginning of the test procedure and I’m rolling it all back at the end. That way all of the test objects that I insert into the tables won’t be left around after the test is done. If one of my assertions fails, the test will throw an error (but everything will still get rolled back).

The last step is to call the test proc from a standard .NET unit test using your favorite testing framework, which might look like this:

[TestFixture]
public class When_checking_to_see_if_a_user_is_in_a_role
{
    [Test]
    public void Run_IsUserInRole_tests()
    {
        // call the test stored procedure here
    }
}

That’s it! Now you can have peace of mind when you write T-SQL code too!

April 13, 2009by Jon Kruger
JavaScript

Strict equality operators in JavaScript: === and !==

The first time you see this, you think it’s a typo. But yes, === and !== are valid operators in JavaScript.

These operators do a strict comparison of equality by comparing both the type and the value. It’s easier to explain if I show you an example.

// This line will return true because both things mean 2
'2' == 2 

// This line will return false because on one side you have a string and
// on the other side you have a number.
'2' === 2 

Here’s another example:

var x = null;

if (x == undefined) // true
{
    // do something
}

if (x === undefined) // false!
{
    // do something
}

The first if statement evaluates to true because JavaScript says that null means the same as undefined, but the second if statement evaluates to false because null is not exactly the same as undefined.

Why would you care about this? Well, for the simple JavaScript that we write to manipulate stuff on a page of HTML, it probably doesn’t matter. But if you’re writing a complicated JavaScript library, this may be something that you might use. If anything, it’s good to know what it means so that you don’t freak out when you see it in someone else’s code.

April 7, 2009by Jon Kruger
ASP.NET MVC

ASP.NET MVC: Pass parameters when redirecting from one action to another

In ASP.NET MVC, it’s common to have a situation where you post to one controller action and then redirect to another controller action. Let’s say that you want to pass values from the first controller method to the other. The problem is that in out-of-the-box ASP.NET MVC, there is no way to redirect to another action and pass a parameter into the action that you are redirecting to. Here is one way you can get around this problem:

public class AccountController : Controller
{
    [AcceptGet]
    public ActionResult Index(IndexViewModel model)
    {
        model.Message = (string) TempData["Message"];

        return View(model);
    }

    [AcceptPost]
    public ActionResult Save(SaveUpdateModel model)
    {
        // save the information
        TempData["Message"] = model.Message;
        return RedirectToAction("Index");
    }
}

The reason that you would do a redirect in this case is so that (a) you can reuse the code in the Index method and (b) you are redirecting to a GET operation, so if the user clicks Refresh in their browser, it won’t try to re-post the previous page.

I don’t really like how that code works, for various reasons:

  • I’m using hardcoded strings (“Index” and “Message”). These might not get caught by refactoring tools if I want to change names, and I don’t get compile time checking on them.
  • In the Index() method, I have to grab the value out of TempData. That works fine if you’re being redirected from the Save() action, but what if I’m being redirected from another action? What if I’m not being redirected from anywhere and the user is accessing the action directly? Ideally, when the Index() method is called, it should have everything that it needs in its parameters at the beginning of the method.

Personally, I don’t like to see TempData or ViewData anywhere in my controller methods. Don’t get me wrong, I need them and I’m going to use them, but I want it all done under the covers. I favor the “One Model In, One Model Out” pattern, where each controller action method takes in one model parameter (or none) and returns another model. Doing it this way allows me to avoid the use of magic strings and hashtables. I want my code to look like this:

[PassParametersDuringRedirect]
public class AccountController : Controller
{
    [AcceptGet]
    public ActionResult Index(IndexPresentationModel model)
    {
        return View(model);
    }

    [AcceptPost]
    public ActionResult Save(SaveUpdateModel model)
    {
        // save the information

        var presentationModel = new IndexPresentationModel();

        presentationModel.Message = model.Message;

        return this.RedirectToAction(c => c.Index(presentationModel));
    }
}

This code does exactly what I want. Now…

  • I don’t have any magic strings.
  • Everything is strongly typed.
  • The parameter passed to the Index() method will always be complete. I don’t have to load anything out of TempData to get it to work.

One thing I love about ASP.NET MVC is that it is very extensible, so you can usually make it do what you want. This is the purpose of the MVCContrib project — people extending ASP.NET MVC to make it even better.

You may notice that in the code snippet above, I decorated my controller class with the [PassParametersDuringRedirect] attribute. Now, any parameters that I pass into RedirectToAction() will get passed into the action that I redirected to.

One slight problem… this new version of RedirectToAction() is an extension method on the Controller class, which means to call it, you would have to write “this.RedirectToAction()”. If you don’t want to have to write “this.” every time, you can just create a base controller class that has this method:

protected RedirectToRouteResult RedirectToAction(Expression> action) 
    where T : Controller
{
    return ControllerExtensions.RedirectToAction(this, action);
}
April 6, 2009by Jon Kruger
Design, Quality

Don’t cheat on those small apps!

At some point, we all have to write some small apps. I’m talking about things like…

  • Some small utility or diagnostic app
  • Something to help with your deployment process
  • Other small applications or websites (i.e. something that takes a month or less)

In these cases, we often throw good software design principles out the window. We say that we don’t need to write unit tests, we don’t need dependency injection, we can put data access code in our code-behinds, and things like that. Since it’s a small app, we think we can get away with it.

Just because your app didn’t take you long to write doesn’t mean that you get off easy. The consequences of your decisions just aren’t as severe, but that doesn’t mean that the pain is gone!

How many times have you written some small utility to help with something and then your boss sees it and really likes it, and then he asks you to add more functionality to it. Eventually you’ve spent a couple months on the app. If you cheated at the beginning, that code is going to hard to change and it’s going to start becoming more of a pain.

Maybe you’re writing a console app to help with your deployment process. Now this code better work, because if it doesn’t, your app might not deploy correctly. This is very important code! Doesn’t code this important warrant some extra attention (i.e. tests)?

Look, I’m not saying that every little app has to be this big, blown-out, enterprise application. I’m just saying that you should be careful when you cheat, because you don’t want that to come back to haunt you.

Many times you can take simple steps to make things easier to change. Take dependency injection, for example. It is really easy to set up an IoC container like StructureMap, it doesn’t overly complicate your code, and you don’t have to write tons of extra code to use it. But if you want to write tests for you code, dependency injection will make it a lot easier. You’re just putting code in better places.

Again, there are times to use dependency injection and there are times where it’s superfluous. There are times when unit testing is essential and times when you can get away with it (personally I always like writing tests if I can, that way I know my code works). But you need to be careful. Software is software, and many of the same development principles that apply to big apps still apply to small apps.

March 31, 2009by Jon Kruger
Uncategorized

Why does software development take so long?

Every year, thousands of software development projects are developed. In most of these applications (especially line-of-business applications) you will see a lot of the same UI patterns:

  • When the value in one dropdown changes, the list in another dropdown needs to change
  • Two list boxes with arrow buttons that allow you move items between the lists
  • A grid with add/edit/delete buttons that allow you to manipulate the list

Most applications have other common characteristics, like:

  • The concept of a User that has to log in, reset their password, and change their password
  • Some concept of security roles
  • Loading objects from a database by ID

Every project also has housekeeping tasks, like:

  • Setting up automated builds
  • Copying files to a QA site after a build
  • Coming up with a way to create a development copy of the database

The problem is that on every project, it seems that way too much time is spent getting this stuff to work. Why??

These are solved problems. We’ve all solved them before. But we end up re-implementing the same stuff over and over.

This is a problem. Making an AJAX call to update the list in a child dropdown when the parent dropdown changes is not rocket science. I don’t want to write this code ever again. I want to write stuff like this:

State: <%= this.Select(model => model.State)
                      .Options(Model.StateOptions, opt => opt.Id, opt => opt.StateCode)
                      .UpdateOptionsFor(model => model.County)
                      .WithAjaxCallTo(“/state/GetCountiesInState”) %>
County: <%= this.Select(model => model.County) %>

(I’m using the MvcContrib HTML Helpers here.)

You write the code to implement this fluent interface once, and you don’t ever have to write it again. That’s the way that it should be. Every time you do something, you should be trying to find a better way to do it so that you can do it better next time.

A lot of people have already done lots of work for you, and you should take advantage of it. I’m talking about things like this:

  • Using the built-in ASP.NET Membership stuff instead of rolling your own code to do Forms Authentication
  • Using Rails scaffolding to create your website
  • Using styling and controls from jQuery UI
  • Using convention-based MVC frameworks (e.g. Rails or ASP.NET MVC + MVCContrib)
  • Using the auto-mapping capabilities of Fluent NHibernate instead of writing mapping files or CRUD stored procedures
  • Use S#arp Architecture as the framework for your application

Every developer should have a toolbox of code that he/she can draw from so that you can avoid being a plumber and spend your time doing valuable things, like writing business logic, designing user interfaces, and other things that you are being paid to do.

March 28, 2009by Jon Kruger
JavaScript, TDD, unit testing

A real world story of why TDD is good

As if I needed any more convincing, I ran into another situation where TDD saved me from a lot of pain.

On my current project, we have a lot of client-side Ajax-y goodness. The feature that I was working on was dragging something from one part of the page and dropping it on another part of the page. I was using jQuery UI’s Draggables and Droppables to do this. I got most of the way done, and then realized that jQuery UI draggable/droppable support does not work completely in IE because of some IE bugs that they apparently have not worked around yet. (A newer version of the jQuery UI has come out since I wrote this so it’s probably fixed now.)

Luckily, I wrote all my JavaScript the TDD way, so all of the UI concerns were separated out from the code that has the logic in it. So I was easily able to pull out jQuery’s drag and drop and replaced it with Yahoo UI’s drag and drop in only 4 hours (and I’ve never used YUI before). The only code I needed to change was the JavaScript that was in the ASPX page (this is all of the untestable stuff that wires stuff up to actual DOM objects). All of the underpinning logic (some of which still uses jQuery, as does the rest of the site) all works the same as it did before.

If TDD hadn’t led me into well-designed, object-oriented JavaScript, doing this would have taken a lot longer than 4 hours. In fact, it probably would’ve been really difficult to do without just rewriting most of what I had done. But this is one of the reasons that we write tests first — it gives a code based is easy to change and easy to maintain. I experienced that first-hand today.

March 17, 2009by Jon Kruger
Page 19 of 23« First...10«18192021»...Last »

About Me

I am a technical leader and software developer in Columbus, OH, currently working as a Sr. Engineering Manager at Upstart. Find out more here...

I am a technical leader and software developer in Columbus, OH, currently working as a Senior Engineering Manager at Upstart. Find out more here...