thegrubbsian http://www.thegrubbsian.com thoughts on software development, .NET, Ruby, JavaScript, Agility, etc posterous.com Wed, 05 Jan 2011 10:47:00 -0800 Yet Another jQuery Validation Plugin (this time with tinyness) http://www.thegrubbsian.com/yet-another-javascript-validation-plugin-this http://www.thegrubbsian.com/yet-another-javascript-validation-plugin-this

I've used a number of pure JavaScript libraries and jQuery plugins to handle client-side validation over the years but I never really liked any of them.  As I often do when I can't find exactly what I want, I built a new one.  

There are certainly libraries out there that cover a broader set of features, but my goal here was to make it dirt simple.  So simple in fact that anyone should be able to read the source and in a few minutes figure out how to make it conform to novel requirements.  The entire framework is shown here in the following gist:

https://gist.github.com/740006.js?file=jquery.validator

As you can see it takes up just over 100 lines and offers out-of-the-box support for a number of standard validation patterns.  However, additional validator methods can be added via the options object.  Below is a usage sample that will make things more clear:

In the above example you can see that adding validation to any input element is as simple as defining a "data-validators" attribute to the element.  The value of this attribute is essentially a JSON string with some syntactic sugar to make it easier on the eyes.  For example, you don't have to surround the whole string with curly braces and if you are defining a validator such as "required" but have no additional options to specify you don't have to do "required:{}" for the JSON to be valid.  If you look at the "expandValidatorString" method in the source you can see that these elements are added dynamically before the JSON is evaluated.

At some point I'll put this up as a repository with more complete documentation but I wanted to get it out there for some feedback before that.  Let me know what you think.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1388654/Profile_Photo_2.jpg http://posterous.com/users/4wPGcmBFNTyx JC Grubbs thegrubbsian JC Grubbs
Mon, 27 Dec 2010 22:51:00 -0800 The Joy (and Benefit) of Small Teams http://www.thegrubbsian.com/the-joy-and-benefit-of-small-teams http://www.thegrubbsian.com/the-joy-and-benefit-of-small-teams

I've had the occasion recently to work on some projects in very small teams, just 2 or 3 others at most.  This experience has rekindled in me a joy for this kind of working environment and atmosphere.  There's just something about not being lost in a sea of teammates or (even worse, leading a giant team) that really appeals to me.

As I thought through this more, I began to realize that this isn't simply something that I enjoy, but something that has that "right" feeling about it - it just clicks.  The following is a list of things that I believe are beneficial about operating in small teams and some of the things that flat out cannot be duplicated within a large team structure.

Note: Most of this will be obvious to people and I'm sure it's all been said before, but let me have my fun and blog about it...golf claps at the end would be appreciated.

Low Tolerance for the Silo Effect
When teams are small it's almost impossible for silos to develop.  Even in the face of explicit attempts to make silos, in a small team they just don't materialize.  Whether this is a result of a smaller domain or the low communications barrier, the benefit is clear.  Smaller teams have a much easier time cross training because they hardly have to do it at all, it's a natural phenomena that occurs when living so close to someone else's code.

Nobody Hides Behind the Wall
On large software teams I use the phrase "throw it over the wall" to describe the interaction that often occurs between one part of the team and another.  They don't really care who's on the other side of that wall nor what they're throwing for that matter.  Status just needs to be reported as: We made something, and we threw it over that wall.  The wall could be the one between development and QA, between the business and the BA team, or between the BAs and the developers...point is, it's a wall, and stuff get's chucked.

Clearly this is a terrible way to work and it reduces overall quality because people rely on the shleps on the other side of the wall to complain before they'll deal with their mistakes.  This cannot occur in a small team because the walls are too short for you to throw something over it and still retain the comfortable anonymity that a higher wall would provide.

Sorry: Took that analogy a bit far!

We Don't Need No Stinking Managers
While this is not strictly true all the time, my point is that with small teams the oversight tax is quite minimal.  As a team grows in size the amount of overhead incurred by management rises logarithmically.  By the time you have a team of 20-25 developers you have so many tech leads, architects, and project managers installed that your 2 for 1 pizza coupons are no longer valid.

Management and oversight is important but not at the expense of agility and direct (peer) accountability.  Small teams rarely have this problem and often a single manager can provide adequate oversight for more than one semi-self-governing project.

We Built [more of] That
This one is just my opinion, but when a large team builds an enormous software product the "I made that" quotient per individual is very low.  When a small team builds a substantial software product for their size that same metric goes through the roof.  It is profoundly more satisfying (for me anyway) to be part of a 4 person team who accomplishes the work of 7 over being part of a 23 person team who comes in over budget and delivering less scope.  Again, just my opinion.

Craftsmanship and Apprenticeship <3 Small Teams
This one may be a bit controversial but I believe it's more difficult for mentorship to occur on big teams.  It can happen of course, but the ratio of highly skilled craftsman to more junior developers forces those highly skilled individuals to be spread too thin on large teams.  On a team with one seasoned journeyman and two apprentices the two junior team members will learn a lot more simply because they have more concentrated contact with their mentor...and visa versa.

That's it...I'm sure there are loads more benefits (and joys) that people can identify from working in small teams but these are the ones that came to mind at 1:30 in the morning.  I'm very much looking forward to continuing the trend of working in smaller groups and delivering better software for it.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1388654/Profile_Photo_2.jpg http://posterous.com/users/4wPGcmBFNTyx JC Grubbs thegrubbsian JC Grubbs
Fri, 29 Oct 2010 16:14:00 -0700 Pomodoro http://www.thegrubbsian.com/pomodoro http://www.thegrubbsian.com/pomodoro

In an effort to increase my personal effectiveness I've recently been experimenting with different productivity techniques.  Over the past couple weeks I've attempted to use the Pomodoro approach to task execution.  I've modified the "official" pattern but tried to stay true to it's intent.  My spin on it consists of the following steps:

Set Up

1. Create a catalog of like sized tasks I want to complete.  These tasks don't have to be related but usually are smaller bits of a larger project.  The catalog is prioritize and ordered.  The tasks don't all have to be the same size but it helps to keep the Pomodoros same duration.

2. Arrange a distraction free environment for the duration of the upcoming Pomodoro.  This means shutting down email, IM, TweetDeck, and closing all potentially distracting browser tabs.  If I'm working in a common area I'll either move to somewhere more secluded or put my headphones in to avoid potential interruption.

3. Make sure the stage is set, meaning, make sure all the necessary software is running and projects are open.  No sense wasting the first two minutes of the cycle opening text editors and spinning up servers, etc.

Execute

4. Set a timer.  For me I'm using the simple Pomodoro Timer app for my iPhone.  This works well for me although it seems some people prefer a physical kitchen timer for this.  I find that 20 or 25 minutes work best, more than that you lose the drive to get to the finish and with less time you don't accomplish enough.

5. Do work!

6. Take a 5 minute break and GOTO step 4 until task catalog is complete.  Obviously you'll want to keep the list manageable.  I would suggest not putting more items in the catalog than you can actually accomplish in a set of sequential Pomodoros as this leads to chronic spillage on to the next task list.  You get a nice mental kick when you throw away a completed list.

It sounds like a lot of setup for just 20 or 25 minutes of heads-down time but the ritual really does put me in the mental space to knock something out.  I'm finding that I can run three Pomodoros with 5 minute breaks before I need a longer break or inevitably get pulled into a meeting or something more distracting.  

Although I haven't yet experienced it, I hear people say good things about employing this technique while pairing as it keeps a virtual carrot in front of the pair and relieves the pressure valve every 20/25 minutes or so.

 

 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1388654/Profile_Photo_2.jpg http://posterous.com/users/4wPGcmBFNTyx JC Grubbs thegrubbsian JC Grubbs
Mon, 25 Oct 2010 12:33:00 -0700 NoRMatic: a gooey sugar layer for NoRM/MongoDB http://www.thegrubbsian.com/normatic-a-gooey-sugar-layer-for-normmongodb http://www.thegrubbsian.com/normatic-a-gooey-sugar-layer-for-normmongodb

It's been out on the Githubs for a few weeks now, but I wanted to do a quick writeup on NoRMatic.  If you're using MongoDB with .NET or Mono, it's pretty likely that you've come across NoRM, the great driver and LINQ provider for MongoDB.  While NoRM is awesome, it can be a little low-level at times and for Crew we needed a library to abstract a few common bits.

Some of the features that NoRMatic provides:

  • ActiveRecord style interface (Save, Delete, GetById methods, etc)
  • SoftDelete
  • Versioning
  • Validation (via DataAnnotations attributes)
  • Save and Delete Callbacks (Before/After)
  • Global Query Filters
  • Basic Auditing (DateUpdated, UpdatedBy)
  • Simple Log Listener
  • Connection String Provider (to connect models to different databases)

Check out the documentation at the Github page for more information.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1388654/Profile_Photo_2.jpg http://posterous.com/users/4wPGcmBFNTyx JC Grubbs thegrubbsian JC Grubbs
Fri, 11 Jun 2010 16:05:16 -0700 jQuery.ganttView a Lightweight Gantt Chart for jQuery http://www.thegrubbsian.com/2010/06/11/jquery-ganttview-a-lightweight-gantt-chart-for-jquery http://www.thegrubbsian.com/2010/06/11/jquery-ganttview-a-lightweight-gantt-chart-for-jquery I just wanted to drop a quick post about a new jQuery plugin that I've been working on for a recent project. As the title of the post implies it renders a simple HTML based Gantt chart using jQuery and the excellent date.js library. The screenshot below should give you an idea of what can be done with the plugin.
Media_httpwwwthegrubb_jfagg

The current version is fairly stable and has been tested in FireFox 3.6, Safari 4, Chrome 5, and IE8 and works well in all those browsers. There are likely a few issues with it in IE7 and I wouldn't even bother checking IE6, unless someone sends me a patch I have no interest in supporting IE6.
The source code and documentation can be found on GitHub: http://github.com/thegrubbsian/jquery.ganttView
Let me know what you think and if there are any specific features you'd like to see added.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1388654/Profile_Photo_2.jpg http://posterous.com/users/4wPGcmBFNTyx JC Grubbs thegrubbsian JC Grubbs
Tue, 22 Dec 2009 04:33:15 -0800 LINQ-to-SQL Sugar http://www.thegrubbsian.com/2009/12/21/linq-to-sql-sugar http://www.thegrubbsian.com/2009/12/21/linq-to-sql-sugar Yes, yes, LINQ-to-SQL is probably, one day, going to be consumed or deprecated by it's big brother the Entity Framework. However, for the current .NET platform (3.5) and likely for the next (4.0) it is still a viable ORM option in the Visual Studio box. There are lots of reasons to use LINQ-to-SQL and lots of reasons not to use it...that is for another post. What I do want to share is a set of extension methods that (for me) made using LINQ-to-SQL just a little bit nicer. The title is indeed descriptive...these are "sugar" added to LINQ-to-SQL and don't fundamentally improve how it works, just how the programmer works with the library. I'm sure developers using LINQ-to-SQL have created scads of other such saccarine extensions to the framework...if you have some I'd be interested in hearing about them. So here's my LinqToSqlExtensions class:
public static class LinqToSqlExtensions {

    public static TEntity GetById(this Table @this, int id)
        where TEntity : class {
        return @this.SingleOrDefault(x => ((IIdentified)x).ID == id);
    }

    public static TEntity Upsert(this Table @this, int id)
        where TEntity : class, new() {

        var entity = @this.SingleOrDefault(x => ((IIdentified)x).ID == id);

        if (entity == null) {
            entity = new TEntity();
            @this.InsertOnSubmit(entity);
        }

        if (entity is IAuditable)
            ((IAuditable) entity).ModifiedDate = DateTime.Now;
        return entity;
    }

    public static TEntity Upsert(this Table @this, Func predicate)
        where TEntity : class, new() {

        var entity = @this.SingleOrDefault(predicate);

        if (entity == null) {
            entity = new TEntity();
            @this.InsertOnSubmit(entity);
        }

        if (entity is IAuditable)
            ((IAuditable) entity).ModifiedDate = DateTime.Now;

        return entity;
    }

    public static void Delete(this Table @this, TEntity entity)
        where TEntity : class {
        @this.DeleteOnSubmit(entity);
    }

    public static void DeleteById(this Table @this, int id)
        where TEntity : class {
        var entity = @this.GetById(id);
        @this.Delete(entity);
    }

    public static void DeleteAll(this Table @this, 
        IEnumerable entities) where TEntity : class {
        entities.ToList().ForEach(e => @this.Delete(e));
    }

    public static void CommitChanges(this DataContext @this, RepositoryContext context) {

        var changeSet = @this.GetChangeSet();

        for (var i = 0; i (TEntity entity, RepositoryContext context, 
        bool isInsert) where TEntity : IAuditable {
        
        entity.ModifiedDate = DateTime.Now;
        entity.ModifiedBy = context.UserID;

        if (isInsert) {
            entity.CreatedDate = DateTime.Now;
            entity.CreatedBy = context.UserID;
        }
    }
}
Here's a rundown of the methods it creates and how to use them: GetById Simple enough, allows you to avoid using the LINQ syntax to find an element by it's identifier.
var thing = DataContext.Things.GetById(3);
Upsert This is probably the most convenient addition. It simply checks to see whether the object exists (by it's ID) if so it returns it if not it creates a new one and returns that. It just avoids a lot of query-for-an-object-and-if-its-null-create-a-new-one-and-insert-it code.
var thing = DataContext.Things.Upsert(2);
var anotherThing = DataContext.Things.Upsert(x => x.Name == "That Thing");
Delete and DeleteById Pretty obvious...
DataContext.Things.Delete(thing);
DataContext.Things.DeleteById(3);
CommitChanges This is just a replacement for SubmitChanges that allows us to update some audit columns automagically. Some of this magic is provided via a set of partial classes on those that LINQ-to-SQL generates that applies some additional interfaces to those classes. So, I have a Partials.cs file that contains the following:
public interface IAuditable {
    public DateTime CreatedDate { get; set; }
    public DateTime UpdatedDate { get; set; }
    public int CreatedBy { get; set; }
    public int UpdatedBy { get; set; }
}

public interface IIdentified {
    public int ID { get; set; }
}

partial class Thing : IIdentified, IAuditable { }
public class OtherThing : IIdentified { }
public class LastThing : IAuditable { }
As long as your generated class (and it's related table) have properties of the same names as the IAuditable and IIdentified interfaces the LINQ-to-SQL extension methods can update them appropriately and in the background. I could have accomplished much of this by just inheriting a new DataContext and adding some additional functionality, but doing it this way you can add these methods to even a closed assembly.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1388654/Profile_Photo_2.jpg http://posterous.com/users/4wPGcmBFNTyx JC Grubbs thegrubbsian JC Grubbs
Tue, 15 Dec 2009 21:28:00 -0800 Scriptability via the DLR and PostSharp http://www.thegrubbsian.com/2009/12/15/scriptability-via-the-dlr-and-postsharp http://www.thegrubbsian.com/2009/12/15/scriptability-via-the-dlr-and-postsharp

Making an application scriptable (particularly in a static language) has historically been difficult. With the advent of the DLR (Dynamic Language Runtime) on the .NET platform it becomes almost trivial to add scripting support to any application. For a recent project I needed the ability to add scripting hooks throughout the application and coupling the DLR with PostSharp AOP attributes made this effort pretty straightforward. Here's how it was done:

Bring in the DLR
The DLR is implemented as a set of plain old DLL's on top of the .NET Framework version 3.5...contrary to popular belief, you do not have to be running VS2010 or .NET 4 to use it.  Simply go to the CodePlex page for the DLR (http://dlr.codeplex.com), grab the source, and compile it.  There are solution files for VS2008 and VS2010. For my purposes I used IronPython as the scripting language but IronRuby is available in the download as well.  To use the DLR your project will need to reference the following assemblies:

  • Microsoft.Dynamic.dll
  • Microsoft.Scripting.Core.dll
  • Microsoft.Scripting.dll

In order to use IronPython, you will also need to reference these:

  • IronPython.dll
  • IronPython.Modules.dll
  • Microsoft.Scripting.ExtensionAttribute.dll

Register the Languages
Now that your project contains all the references it needs it's time to set up the little bit of code needed to host the DLR.  First you'll need to add a few things to your configuration file (App.config or Web.config depending on your project type...this works equally well with either).  Just add the following to the node of your config file:

<section name="microsoft.scripting" 
        type="Microsoft.Scripting.Hosting.Configuration.Section, Microsoft.Scripting, 
                Version=0.9.6.20, Culture=neutral, PublicKeyToken=null" 
        requirePermission="false" />

And add the following somewhere in the root node:

<microsoft.scripting>
    <languages>
        <language names="IronPython;Python;py" 
        extensions=".py" displayName="IronPython 2.6" 
        type="IronPython.Runtime.PythonContext, IronPython, 
        Version=2.6.10920.0, Culture=neutral, PublicKeyToken=null" />
    </languages>
</microsoft.scripting>

This basically just tells the runtime what languages to register, what versions of those languages, and some info about file extensions, etc.

Bring in PostSharp
Now I'm going to skip over to PostSharp for a minute. If you're not familiar with PostSharp you should run over to the website (http://www.postsharp.org) and check it out before continuing. In short, it's an AOP (Aspect Oriented Programming) library for .NET that allows easy injection of cross-cutting concerns through an application primarily via attributes. The 10sec. version of how it works is this...it injects code in a post-compilation step. This sounds scary, but it's not. In fact, this allows it to be extremely fast at runtime even if a small penalty is paid at compile-time. In order to get PostSharp setup, it's a simple download and install. If you don't want to install it on your machine, you can simply bin deploy it but it does require a tweak to your .proj file to get the post-compilation to work. If you want to go that route, you can find instructions here. At this point you will either follow those instructions or if you've installed directly, just include the following assemblies in your project:

  • PostSharp.Laos.dll
  • PostSharp.Public.dll

The ScriptHook Attribute
PostSharp's primary way of injecting an aspect is through attributes. In our case we're going to inherit from the OnMethodBoundaryAspect attribute in the PostSharp.Laos namespace. This attribute exposes four virtual methods that allow injection of code at different points in the execution of a method:

  • OnEntry
  • OnExit
  • OnException
  • OnSuccess

Each of these methods accept a MethodExecutionEventArgs as an argument that provides access (including arguments) to the method on which the attribute is applied. Here's the ScriptHook attribute:

[Serializable]
public class ScriptHookAttribute : OnMethodBoundaryAspect {

    private readonly ScriptEventTypes _scriptEventType;

    public ScriptEventAttribute(ScriptEventTypes scriptEventType) {
        _scriptEventType = scriptEventType;
    }

    public override void OnSuccess(MethodExecutionEventArgs eventArgs) {
        var args = eventArgs.GetReadOnlyArgumentArray();
        ScriptRunner.ExecuteEvent(_scriptEventType, args);
    }
}

For now, ignore the ScriptRunner reference, but notice that I've created an enum (ScriptEventTypes) that distinguishes different "types" of scripts to be run, by types, I mean different usages. At some point you can switch on the type of event that's occurring and change which scripts are loaded or how they are handled, etc. You would use the attribute like this:

[ScriptHook(ScriptEventTypes.ThingSaved)]
public void SaveThing(Thing t) { }

[ScriptHook(ScriptEventTypes.ThingDeleted)]
public void DeleteThing(Thing t) { }

The ScriptRunner
At this point we've got the DLR available and we have the PostSharp attribute that's injecting our hooks. Now we need something to execute our scripts. Enter the ScriptRunner:

public static class ScriptRunner {

    public static void ExecuteEvent(ScriptEventTypes scriptEventType, object[] eventContext) {

    IScriptEvent scriptEvent = null;

    switch (scriptEventType) {
        case ScriptEventTypes.ThingSaved:
            scriptEvent = new ThingSavedScriptEvent();
            break;
        case ScriptEventTypes.ThingDeleted:
            scriptEvent = new ThingDeletedScriptEvent;
            break;
        }

        if (scriptEvent != null) {
            try {
                scriptEvent.ExecuteScripts(eventContext);
            } catch {
                throw new ScriptExecutionExecption();
            }
        }
    }
}

The runner is just a simple static class with a single ExecuteEvent method...it's so simple in fact that it speaks for itself. The one thing to note is the eventContext argument to the ExecuteEvent method. If you look back at the ScriptHook attribute you can see that is' passing an object array from the MethodExecutionEventArgs instance. This object array contains all the arguments to the executing method. So for SaveThing() or DeleteThing() for example the eventContext array contains the instance of Thing that was passed.

The IScriptEvent Classes
Lastly, we need something to actually grab the scripts and execute them in something like the context of the executing method. So that's where our example ThingSavedScriptEvent and ThingDeletedScriptEvent come in to play. Here's an example:

public class ThingSavedScriptEvent : IScriptEvent {

    private readonly ScriptRuntime _scriptRuntime;
    private readonly IThingRepository _thingRepo;

    public ProjectCreatedScriptEvent() {
        _thingRepo = new ThingRepository();
        _scriptRuntime = ScriptRuntime.CreateFromConfiguration();
    }

    public void ExecuteScripts(object[] contextValues) {

        var thing = (Thing)contextValues.SingleOrDefault(x => x is Thing);
        
                var scriptScope = _scriptRuntime.CreateScope();
        scriptScope.SetVariable("thingRepo", _thingRepo);
        scriptScope.SetVariable("thing", thing);

        var script = GetScript();

        var scriptEngine = _scriptRuntime.GetEngine("IronPython");
        scriptEngine.Execute(script, scriptScope);
    }

    private static string GetScript() {

        var script = string.Empty;
        try {
            code = File.ReadAllText(HttpContext.Current.Server.MapPath(
                ConfigSettings.ProjectTemplateStorePath + "ThingSaved.py"));
        } catch (FileNotFoundException) { }
        return script;
    }
}

The ScriptRuntime class is where the DLR magic happens. We create an instance of it and then ask it for an engine that can execute IronPython scripts. ScriptScope is a class used for constructing the scope that the script will have available to it. Here for example we're "passing" the 'thingRepo' and 'thing' variables into the script via the ScriptScope. Lastly, we get the engine from the ScriptRuntime, pass it both the ScriptScope and the literal text of the script. And that's that...pretty easy eh?

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1388654/Profile_Photo_2.jpg http://posterous.com/users/4wPGcmBFNTyx JC Grubbs thegrubbsian JC Grubbs
Sun, 23 Aug 2009 00:31:27 -0700 The Reusable Test Scope Pattern http://www.thegrubbsian.com/2009/08/22/the-reusable-test-scope-pattern http://www.thegrubbsian.com/2009/08/22/the-reusable-test-scope-pattern I’m almost positive someone has come up with this pattern before, but it was a big help on a recent project so I thought I’d share it. The basic goal of the pattern is to make the setup and teardown work of test classes reusable. We found this to cause particular pain for integration tests written against a database where multiple dependent records needed to be created before the actual test could be performed. The second goal was that these externalized bits of code would be composable so that tests requiring multiple setup resources could create just the right ones. Before really describing the workflow of the pattern, here are the basic components of our implementation: The ITestScope Interface
public interface ITestScope {
    void SetupScope();
    void TeardownScope();
}
These two methods (SetupScope and TeardownScope) are where we move all of the test setup and cleanup logic. Any state that needs to be maintained between setup and teardown (i.e. needs to be available to the test itself) can be stored in public properties or fields on the class implementing ITestScope. The TestBase Class
public abstract class TestBase {
    public abstract void ScopeSetup();
    public abstract void ScopeTeardown();
}
Requiring that all test classes inherit from TestBase insures that at least developers will be considering the setup and cleanup of their tests. The TestBase.ScopeSetup method would include instantiating and calling the TestScope.SetupScope methods for any scopes that are needed in the test class...likewise for teardown. The TestFactory Class
public static class TestFactory {
    public static TRepository GetRepository() where TRepository : class {}
    public static TController GetController() where TController : Controller {}
}
This isn't directly related to the scope pattern, but it's invaluable as a point where you can use a DI container in the test project. All repository or controllers (or other resources) can be obtained from here. An Example So here's an example test class that might use this pattern.
public class CustomerTestScope : ITestScope {
        
        private ICustomerRepository _customerRepo;
        
        public Customer TestCustomer { get; private set; }
        
        public CustomerTestScope(ICustomerRepository customerRepo) {
                _customerRepo = customerRepo;
        }
        
        public void SetupScope() {
                TestCustomer = _customerRepo.Create();
                // Other complex test setup logic
        }
        
        public void TeardownScope() {
                _customerRepo.Delete(TestCustomer);
                // The reverse of the complex setup logic
        }
}

[TestClass]
public class CustomerRepositoryTests : TestBase {

        private CustomerTestScope _customerScope;
        private ICustomerRepository _customerRepo;

        [TestInitialize]
        public override void ScopeSetup() {
        
                _customerRepo = TestFactory.GetRepository();
        
                _customerScope = new CustomerTestScope(_customerRepo);
                _customerScope.SetupScope();
        }
        
        [TestMethod]
        public void SaveCustomer_ShouldRenameCustomer_WhenNewNameGiven() {
        
                _customerScope.TestCustomer.Name = "New Name";
                _customerRepo.Save(_customerScope.TestCustomer);
                
                var customer = _customerRepo.GetById(_customerScope.TestCustomer.ID);
                
                Assert.IsTrue(customer.Name == "New Name", 
                        "SaveCustomer failed to update customer name.");
        }
        
        [TestCleanup]
        public override void ScopeTeardown() {
                _customerScope.TeardownScope();
        }
}
If additional scopes were needed then they could simple be added to the test class. For example, if a ProductTestScope was also needed then it would be initialized just like the CustomerTestScope and torn down appropriately. Dependencies between scopes would be supplied via constructor parameters. This does imply that the SetupScope methods be called in sequence and TeardownScope be called in reverse order. That's the pattern, pretty simple but now the logic for creating these setup conditions can be offloaded and reused in a simple way and we've made it easy to clean up that test data after the tests complete.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1388654/Profile_Photo_2.jpg http://posterous.com/users/4wPGcmBFNTyx JC Grubbs thegrubbsian JC Grubbs
Sat, 01 Aug 2009 19:57:00 -0700 Thoughts on Legacy Code http://www.thegrubbsian.com/2009/08/01/thoughts-on-legacy-code http://www.thegrubbsian.com/2009/08/01/thoughts-on-legacy-code

I was listening to a recent Hanselminutes podcast episode in which Scott spoke with Michael Feathers of ObjectMentor on the topic of legacy code. They touched on a number of really effective techniques for approaching a legacy code-base and I wanted to echo some of their thoughts and add a few of my own.

First, the definition of legacy code (as was discussed in the show) is really much broader than the face value of the phrase itself. In reality it’s harder to define “legacy code” than it is to know it when you see it. Generally I know I’m dealing with legacy code when any of the following happen:

  1. I’m fearful of making changes…the magic box where this code lives might get angry
  2. I’m confused and lost after more than a few clicks of “Go to Definition”
  3. I find few or no tests, or the quality of tests is poor
  4. There are tests but I get mixed or untrustworthy results from running them
  5. I have to write more lines of setup code to write a test than the lines of code that I want to test
  6. I can find nobody who will admit to understanding (or writing) this code

Doubtless there are more than just these indicators to tell you that you’re dealing with legacy code, but these are red-flags for sure. So what are some high-level techniques that we can use to help bring legacy code into the present…well, here are a few:

Under The Rug
We’ve all done it at home…there’s that last little bit of something that you missed with the broom. So, you lift up the corner of the living room rug and kick it under there with your foot. While you’re mom probably wouldn’t approve, sometimes with code this can be an acceptable approach – provided you acknowledge what you’re doing. What I mean by sweeping it under the rug is that you wrap a section of “legacy code” in a bit of more modern, testable code. In this way you can continue to use the legacy sections but a cleaner interface can be created for testing.

The Strangler Application
This is a pattern that was introduced to me in the Hanselminutes podcast. The basic premise is an extension of the “Under the Rug” concept. But instead of just wrapping the code in a clean exterior, we actually take that opportunity to slowly “choke” out the old code.

One technique that can be employed to slowly transform the codebase is using the “I” in SOLID…Interface Segregation. Applying one or more interfaces to each legacy class allows you to incrementally swap out implementations with clean, new code.

Embrace Continual Design
One thought that came out in the Hanselminutes episode was that design is never over. And I think this is really important to realize. Even in production/support mode, design is something that needs to be addressed. When extending an application, are we setting it up for continued success and maintainability. When re-factoring something or transforming it to un-legacy code, are we taking care that it won’t regress back into legacy code. If a team is focused on continual design it’s less likely for code to become legacy in the first place.

Posthumous Test Coverage
A third approach to legacy code is by testing the crap out of it. One could even make the argument that this is a pre-requisite to the previous three approaches. Spending a lot of time covering legacy code in tests has two major benefits. First, it helps the developer really understand the intent of the code, it’s style, quirks, and patterns. Secondly, it does what tests do best…helps make code changes safer. If a codebase is adequately covered in tests then making changes becomes less scary and potential regression is reduced.

Forklift
Lastly, there is one approach to legacy code that is rarely mentioned…and rightly so, it’s the most aggressive and can be the most costly. Start over…sometimes it’s the best approach.

Once in my life I had to deal with a massive codebase that had been through many, many, cycles of attempted refactorings. The years had left this poor application in a state of wild and unruly disrepair. After discussing all the options with the client it became evident that actually starting over was the best (and in this case, cheapest) way to accomplish the goal.

Starting over can be daunting but if you attack it in a practical and measured way, and possibly mix it with the other techniques described here it can be liberating. It’s important to have a good requirements phase when starting over, you can’t just look at legacy code and start re-writing it. And you need to have all the trappings of a well staffed project in place as well, including strong QA.

~~

So those are some thoughts on legacy code. As always, I’d appreciate hearing what everyone else thinks…what other techniques have you used?

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1388654/Profile_Photo_2.jpg http://posterous.com/users/4wPGcmBFNTyx JC Grubbs thegrubbsian JC Grubbs
Thu, 02 Jul 2009 21:29:59 -0700 Martin: A Lightweight REST Framework Inspired by Sinatra and MVC http://www.thegrubbsian.com/2009/07/02/martin-a-framework-inspired-by-sinatra http://www.thegrubbsian.com/2009/07/02/martin-a-framework-inspired-by-sinatra Those of you who work in the Rails community will know something about Sinatra. It's a lightweight web framework for building REST services in Ruby. I'm not a Ruby programmer (I know enough to be dangerous) but I really like the idea of Sinatra. The basic premise of Sinatra is that every method defines a route, and a route (URL + Verb) invokes a single method. Ruby, being a dynamic language, makes this extremely easy. Like I said I'm no Ruby guru but the built-in introspection of the language makes it easier to build a DSL that can describe these route methods. Martin, isn't at all a port of Sinatra. Rather it's inspired by the lightweight nature of Sinatra and it's general pattern. Martin relies on the new System.Web.Routing namespace in .NET 3.5 SP1 and will eventually ship with a DSL that will encapsulate defining your RouteTable. Because it doesn't have any external dependencies and really doesn't need any templates it can plug into any ASP.NET or ASP.NET MVC project and live along side just fine*. In Martin, the first step to creating a new action is defining it with the Config API. At this point it's excruciatingly simple. In Global.asax:
protected void Application_Start(object sender, EventArgs e) {
    Config.AddAction("Show/CurrentDate");
}
What this does is maps the URL: http://domain.com/Show/CurrentDate to the DateAction.Get() method. Behind the scenes there is a factory class that's constructing instances of DateAction, calling the Get() method, and then responding with the result to the request pipeline. The DateAction class looks like this:
public class DateAction : ActionBase {
    public override IResponse Get() {
        return Text(string.Format("The current date is {0}.", DateTime.Now));
    }
}
There are four methods on ActionBase that can be overridden: Get(), Post(), Put(), and Delete(). Each method (obviously) corresponds to an HTTP Verb and only requests using that verb will invoke the appropriate method. So, the same URL pattern can be mapped to two different methods provided that the request uses different verbs. The ActionBase class provides a way to get access to any RouteData or Request items that might be part of the request. Using the ValueOf(String key) method you can find for example an ID that's tacked on to the URL or a piece of data from the querystring or form collection. ~~ For now the project is in a very early stage, no real sample, no real documentation. However, it's so simple that reading through the handful of classes that make up the project is almost all the documentation you'll need. If you get a chance, poke around and let me know what you think...if you want to help make it better just let me know and I'll get you commit rights to the Google Code repo. Source at: http://code.google.com/p/martin-framework/ * In the case of integration with ASP.NET MVC the routes defined by Martin and those your application might need could conflict so care must be taken to insure there are no collisions.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1388654/Profile_Photo_2.jpg http://posterous.com/users/4wPGcmBFNTyx JC Grubbs thegrubbsian JC Grubbs
Fri, 05 Jun 2009 18:38:18 -0700 jQuery Plugin: tablePager http://www.thegrubbsian.com/2009/06/05/jquery-plugin-tablepager http://www.thegrubbsian.com/2009/06/05/jquery-plugin-tablepager Here's a quick table pager plugin for jQuery. Unlike a number of the other plugins out there, this one doesn't alter the DOM tree of the table itself it just hides the rows that are not available for the current page. In this way you can still get access to all the elements of the table throughout the lifetime of the page. Plugin Source:
(function($) {
    $.fn.tablePager = function(options) {

        /*
        options = {
        firstBtn: Element,
        prevBtn: Element,
        nextBtn: Element,
        lastBtn: Element,
        indicator: Element,
        sizeSelect: Element,
        pageSize: Number,
        onPageChange: Callback,
        onPageSizeChange: Callback
        };
        */

        var tbl = this;
        var defaults = { pageSize: 10 };
        var opts = $.extend(defaults, options);

        var pageIndex = 0;
        var pageSize = opts.pageSize;
        var rowCount = getRows().length;
        var pageCount = getPageCount();

        function init() {
            bindControlHandlers();
            updatePaging();
            updateIndicator();
        }

        function getRows() {
            return tbl.find("tbody tr");
        }

        function bindControlHandlers() {
            if (opts.firstBtn) { 
                opts.firstBtn.unbind().bind("click", 
                    function() { changePage(0); }); 
            }
            if (opts.prevBtn) { 
                opts.prevBtn.unbind().bind("click", 
                        function() { changePage(pageIndex - 1); }); 
            }
            if (opts.nextBtn) { 
                opts.nextBtn.unbind().bind("click", 
                        function() { changePage(pageIndex + 1); }); 
            }
            if (opts.lastBtn) { 
                opts.lastBtn.unbind().bind("click", 
                        function() { changePage(pageCount - 1); }); 
            }
            if (opts.sizeSelect) { 
                opts.sizeSelect.unbind().bind("change", 
                    function() { changePageSize(parseInt($(this).val())); }); 
            }
        }

        function getPageCount() {
            return (rowCount % pageSize) ? 
                Math.floor(rowCount / pageSize) + 1 : (rowCount / pageSize);
        }

        function changePage(toIndex) {
            if (toIndex >= 0 && toIndex = start && i 

Usage:

var pager = $("#testTable").tablePager({
    firstBtn: $(".first"), // The element that pages to the first page
    prevBtn: $(".prev"), // The element that pages to the previous page
    nextBtn: $(".next"), // The element that pages to the next page
    lastBtn: $(".last"), // The element that pages to the last page
    indicator: $(".curpage"), // The input element that stores the current page (i.e. "1/5")
    sizeSelect: $(".pagesize"), // The select element that indicates the current page size
    pageSize: 5, // The initial page size
    onPageChange: function(newIndex) { alert(newIndex); }, // Page change callback
    onPageSizeChange: function(newSize) { alert(newSize); } // Page size change callback
});

pager.changePage(2); // Causes the page to change from outside the plugin
var pageIndex = pager.getPageIndex(); // Returns the current page index
var pageSize = pager.getPageSize(); // Returns the current page size


And here's some example markup for the pager elements:

First  
Prev  
Next  
Last

  

    5
    10
    20



As you can see it's really simple and flexible.  You can supply any elements you want to the pager.  If you don't supply a first and last button elements for example then those will be ignored, if you don't specify an indicator then that will be ignored too.  The most important thing is that your DOM stays intact, this allows you to continue to manipulate the "hidden" portions of the table (i.e. the stuff not on the current page) without having to access some crazy expando property that other pager plugins use to stash the un-shown portions of the table.

As always, I'd appreciate any feedback.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1388654/Profile_Photo_2.jpg http://posterous.com/users/4wPGcmBFNTyx JC Grubbs thegrubbsian JC Grubbs
Sat, 02 May 2009 23:48:02 -0700 Easy Compression with ASP.NET MVC http://www.thegrubbsian.com/2009/05/02/easy-compression-with-aspnet-mvc http://www.thegrubbsian.com/2009/05/02/easy-compression-with-aspnet-mvc ASP.NET MVC already comes with great performance out of the box...due mostly to the lightweight nature of the framework. However, in the never-ending pursuit of faster load times I starting looking into what it would take to put together an Action Filter to compress the output of a controller action. Turns out, it's pretty damn easy. Here's what I came up with:
public class CompressAttribute : ActionFilterAttribute {

        public override void OnActionExecuting(ActionExecutingContext filterContext) {

            var encodingsAccepted = filterContext.HttpContext.Request.Headers["Accept-Encoding"];
            if (string.IsNullOrEmpty(encodingsAccepted)) return;

            encodingsAccepted = encodingsAccepted.ToLowerInvariant();
            var response = filterContext.HttpContext.Response;

            if (encodingsAccepted.Contains("deflate")) {
                response.AppendHeader("Content-encoding", "deflate");
                response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
            } else if (encodingsAccepted.Contains("gzip")) {
                response.AppendHeader("Content-encoding", "gzip");
                response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
            }
        }
    }
And you can use it like this:
[Compress]
public class ThingController : Controller { ... }
or on a controller action:
public class ThingController: Controller {

    [Compress]
    public ActionResult Index() { ... }
}
As you can see it really just sets a new filter for the response; GZipStream or DeflateStream depending on what the browser can handle and then sets the appropriate flag. After doing some lightweight testing it looks like the compressed output is on average 18% of the original size. My next task is to do some testing around how long the client takes to actually decompress the response. My guess is that it's pretty negligible though.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1388654/Profile_Photo_2.jpg http://posterous.com/users/4wPGcmBFNTyx JC Grubbs thegrubbsian JC Grubbs
Fri, 24 Apr 2009 21:10:46 -0700 NInject vs. StructureMap vs. I Made This http://www.thegrubbsian.com/2009/04/24/ninject-vs-structuremap-vs-i-made-this http://www.thegrubbsian.com/2009/04/24/ninject-vs-structuremap-vs-i-made-this As I've mentioned before my team is working on a large scale ASP.NET MVC application and we're using dependency injection to decouple our data access layer from the application. Initially we were using NInject as our IoC tool of choice. It's lightweight and has a really nice configuration DSL and it's pretty fast. The problem arose when trying to get NInject's scope caching to work. It has this nifty feature where it will cache the objects it creates and you could specify the scope of that caching...for example SingletonBehavior, or OnPerSessionBehavior. That's great but I couldn't make it work, regardless of the configuration it would always return a brand new object every time. So then I went and checked out StructureMap. It's a little more complex to get set up and I personally don't think it's registration DSL is as nice as NInject's but it works. It has a similar caching feature where you can specify an Instance Scope of Application, Session, Request, Thread, etc. Same problem though, no matter how I configured it the caching was always at the Application level. So every session in the app would get back the same objects...not very secure on the data front. Now, I am completely open to the possibility that I don't know enough about either of these tools and that the roadblocks I ran into were user error. However, I realized I was spending way too much time on something that is essentially a very simple problem. Here's what I needed out of an IoC tool: 1. Constructor Injection - I don't really care about property or method injection, just constructors 2. Cache the Output at Session Level 3. Easy Registration with Constructor Args So the following is what I came up with to solve the problem:
namespace DI {

    internal class InjectionBinder {
        public Type Abstract { get; set; }
        public Type Concrete { get; set; }
        public object[] CtorArgs { get; set; }
    }

    /// 
    /// A lightweight dependency injection tool that supports constructor injection and HttpContext.Session caching.
    /// 
    public static class Injector {

        private const string SessionBindingKey = "__InjectorBindings__";
        private const string SessionCacheKey = "__InjectorCache__";

        private static List _bindings {
            get {
                if (HttpContext.Current.Session[SessionBindingKey] == null)
                    HttpContext.Current.Session[SessionBindingKey] = new List();
                return (List)HttpContext.Current.Session[SessionBindingKey];
            }
            set { HttpContext.Current.Session[SessionBindingKey] = value; }
        }

        private static List> _cache {
            get {
                if (HttpContext.Current.Session[SessionCacheKey] == null)
                    HttpContext.Current.Session[SessionCacheKey] = new List>();
                return (List>)HttpContext.Current.Session[SessionCacheKey];
            }
            set { HttpContext.Current.Session[SessionCacheKey] = value; }
        }

        /// 
        /// Returns a concrete instance of the specified abstract type using the provided bindings and 
        /// attempts to satisfy that type's constructor arguments.
        /// 
        /// The abstract type of the object to initialize.
        /// 
        public static object GetInstance(Type abstractType) {

            // Return the item from the cache if it's in there
            var cache = _cache.ToDictionary(o => o.Key, o => o.Value);
            if (cache.ContainsKey(abstractType))
                return cache[abstractType];

            // If the type is in the bindings, return the concrete
            var foundBinding = _bindings.Find(b => b.Abstract == abstractType);
            if (foundBinding != null)
                return Activator.CreateInstance(foundBinding.Concrete, foundBinding.CtorArgs);

            object obj = null;
            var ctors = abstractType.GetConstructors().ToList();

            // If the type has no constructor, then just create one
            if (ctors.Count == 0)
                return Activator.CreateInstance(abstractType);
            
            // If there are constructors, find one which takes arguments of the types we have binders for
            ctors.ForEach(c => {
                var prms = c.GetParameters().ToList();
                var args = new List();
                var haveBindings = true;
                prms.ForEach(p => {
                    var binding = _bindings.Find(b => b.Abstract == p.ParameterType);
                    if (binding == null) { haveBindings = false; }
                    else { args.Add(Activator.CreateInstance(binding.Concrete, binding.CtorArgs)); }
                });
                if (haveBindings) { obj = Activator.CreateInstance(abstractType, args.ToArray()); }
            });

            return obj;
        }

        /// 
        /// Returns a concrete instance of the specified abstract type using the provided bindings and 
        /// attempts to satisfy that type's constructor arguments.
        /// 
        /// The abstract type of the object to initialize.
        /// 
        public static TAbstract GetInstance() where TAbstract : class {
            return GetInstance(typeof (TAbstract)) as TAbstract;
        }

        /// 
        /// Creates a binding rule between an abstract type and a concrete type.
        /// 
        /// The abstract type for the binding.
        /// The concrete type for the binding
        /// The list of constructor arguments to use when initializing the instance of the concrete type.
        public static void Bind(object[] ctorArgs) {
            var binding = _bindings.Find(b => b.Abstract == typeof(TAbstract));
            if (binding != null) {
                binding.Concrete = typeof(TConcrete);
                binding.CtorArgs = ctorArgs;
            } else {
                _bindings.Add(new InjectionBinder {
                    Abstract = typeof(TAbstract),
                    Concrete = typeof(TConcrete),
                    CtorArgs = ctorArgs
                });
            }
        }

        /// 
        /// Clears all Injector binding rules and empties the internal cache.
        /// 
        public static void Kill() {
            HttpContext.Current.Session[SessionBindingKey] = null;
            HttpContext.Current.Session[SessionCacheKey] = null;
        }
    }
}
And here's how we register the bindings:
private static void BindInjectionContainer() {
    Injector.Kill(); // Clears out previously created bindings and empties the cache

    var currentClient = new Client(); // Doesn't matter...just an example
    var currentUser = new User();
    var currentCulture = "en-US";

    Injector.Bind(new object[] { currentClient, currentCulture });
    Injector.Bind(new object[] { currentClient, currentCulture, currentUser });
    Injector.Bind(new object[] {});
}
And lastly, here's how you request an object:
var secRepo = Injector.GetInstance();
So, it may be ridiculous to roll-your-own on the IoC container but as you can see it was pretty simple to get what I needed. It's very solution specific but what's wrong with that. In this instance it's pretty easy to swap out for something more feature rich if necessary but for now...I call YAGNI on all that.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1388654/Profile_Photo_2.jpg http://posterous.com/users/4wPGcmBFNTyx JC Grubbs thegrubbsian JC Grubbs
Wed, 22 Apr 2009 21:04:54 -0700 Server Block Formatting in Visual Studio http://www.thegrubbsian.com/2009/04/22/server-block-formatting-in-visual-studio http://www.thegrubbsian.com/2009/04/22/server-block-formatting-in-visual-studio This is one of those more-for-me-than-you posts. If you're working with ASP.NET MVC (or god help you ASP Classic) you'll likely be annoyed by the way server blocks are formatted in Visual Studio. In particular closing curly braces seem to throw the formatting engine a real curve-ball. For example, you type something like this:
But after slapping return, you ultimately get this lovely thing:
Thanks Visual Studio! So how do we fix this. Well, you'd like it if hitting Ctrl+K+D took care of this for you, but apparently that ignores server blocks. Next you'll hunt and peck your way through the mounds of Visual Studio options in Tools > Options...but that search will ultimately prove fruitless. Finally, you'll turn to the humble macro...I know macro can be a dirty word but in this case it's really your only option. Here's how this goes: 1. Mouse over to Tools > Macros > Macro IDE 2. Notice that Visual Studio macros are in Visual Basic...really? I know...but go with it. 3. Right-click 'My Macros' 4. Choose 'Add New Item' 5. Choose 'Module' in the dialog 6. Enter the following method in the newly created Module:
Public Module FormatCurrentFile

    Sub FixServerBlocks()
        Dim selection As TextSelection = DTE.ActiveDocument.Selection
        Dim fixed As String = ""
        Dim regex As String = "\"
        While selection.FindPattern(regex, vsFindOptions.vsFindOptionsRegularExpression)
            selection.ReplacePattern(regex, fixed, vsFindOptions.vsFindOptionsRegularExpression)
        End While
    End Sub

End Module
Now you can go through Tools > Options > Keyboard and map a key command to this macro...I chose Ctrl+K+C for example since it's close to the other magic formatting keys that you'll want to run right before the macro. There you have it. Thanks to some help from StackOverflow.com for this solution: http://stackoverflow.com/questions/720042

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1388654/Profile_Photo_2.jpg http://posterous.com/users/4wPGcmBFNTyx JC Grubbs thegrubbsian JC Grubbs
Sat, 14 Mar 2009 00:28:25 -0700 ASP.NET MVC, StructureMap, and the 404 http://www.thegrubbsian.com/2009/03/13/aspnet-mvc-structuremap-and-the-404 http://www.thegrubbsian.com/2009/03/13/aspnet-mvc-structuremap-and-the-404 ASP.NET has a great mechanism for handling 404's in an elegant way. In a purely declarative manner you can add the following to your Web.config:
This works great when you are using ASP.NET, but when you're using StructureMap (or any IoC container) to override the DefaultControllerFactory in ASP.NET MVC you have a bit of a problem in finding the non-existent controller type...namely...an Exception. For example, here's what I'm doing with the controller factory and StructureMap:
public class InjectionControllerFactory : DefaultControllerFactory {
    protected override IController GetControllerInstance(Type controllerType) {
        return ObjectFactory.GetInstance(controllerType) as Controller;
    }
}
The problem is that when controllerType is null (i.e. there is no controller for the given URL) then an exception is thrown in the call to ObjectFactory.GetInstance. So our fancy error setup in the Web.config is moot because an exception is thrown before we even get there. So, how do we fix this? Well...it's simple really...let MVC do it's thing. The DefaultControllerFactory method that we're overriding here already handles this situation gracefully, so just call the base method if the ObjectFactory.GetInstance call can't be completed.
public class InjectionControllerFactory : DefaultControllerFactory {
    protected override IController GetControllerInstance(Type controllerType) {
        if (controllerType != null) {
            return ObjectFactory.GetInstance(controllerType) as Controller;
        return base.GetControllerInstance(controllerType);
    }
}
Voila, now our "virtual" 404 is handled and our special 404 page is displayed.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1388654/Profile_Photo_2.jpg http://posterous.com/users/4wPGcmBFNTyx JC Grubbs thegrubbsian JC Grubbs
Fri, 13 Mar 2009 02:50:46 -0700 ASP.NET MVC En Masse - Areas http://www.thegrubbsian.com/2009/03/12/aspnet-mvc-en-masse-areas http://www.thegrubbsian.com/2009/03/12/aspnet-mvc-en-masse-areas So I'm embarking on my first really large ASP.NET MVC project and I'm really excited about the prospects. But, with any new programming model comes change and little snags that you didn't see coming. So I'm going to try and blog about these as the project progresses so others can see how we handled such obstacles and to help reinforce the solution in my own mind. The first thing that you'll run into in any large MVC application (and I suspect this would happen with Rails or Django as well) is that you end up with a lot of controllers...I mean...a lot of controllers. Inevitably these controllers revolve around similar functionality but you can't quite bring yourself to combine them because doing so would create uber-controllers that break single responsibility and become unmanageable in their own right. The solution of course is to inject some conceptual node above the controller layer...in essence you want to group controllers. So after doing some digging I found an excellent blog post by Phil Haack (the instigator of ASP.NET MVC at Microsoft). I think Phil is great, he's stuck it to the "man" with an great project that beats WebForms hands down. Anyway, in his post he describes a mechanism for extending routing so that you can add essentially another layer to the application above controller, he calls them "areas" but I don't think it really matters what you call them If you download the source code for his prototype you'll see that it's basically a standard MVC project with just a few small modifications.
  • AreaRouteHelper.cs - This guy's job is to add areas to route mapping.  It allows you to map routes inside areas and also map routes to the "root" or controllers that aren't in an area.
  • AreaViewEngine.cs - this just adds patterns so that aspx/ascx views can be found one more level down in the file structure.
  • Changes to the global.asax to register the new area engine.
  • Changes to how the route table is set up (using AreaRoutHelper methods)
It's super simple to set up and a really effective way to extend the MVC structure.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1388654/Profile_Photo_2.jpg http://posterous.com/users/4wPGcmBFNTyx JC Grubbs thegrubbsian JC Grubbs
Sat, 07 Mar 2009 06:24:19 -0800 iPhone http://www.thegrubbsian.com/2009/03/06/iphone http://www.thegrubbsian.com/2009/03/06/iphone I've finally joined the ranks of society...I have an iPhone. I write this to you on that very device. Bravo, Mr. Jobs, bravo.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1388654/Profile_Photo_2.jpg http://posterous.com/users/4wPGcmBFNTyx JC Grubbs thegrubbsian JC Grubbs
Fri, 06 Mar 2009 19:18:32 -0800 Easy "LIKE" Operations in LINQ to SQL http://www.thegrubbsian.com/2009/03/06/easy-like-operations-in-linq-to-sql http://www.thegrubbsian.com/2009/03/06/easy-like-operations-in-linq-to-sql

There are two basic ways to do LIKE operations in LINQ to SQL queries...the easy way and the hard way.  The hard way consists of copious usage of String.StartsWith, String.Contains, and String.EndsWith.  The easy way takes advantage of a handy class called SqlMethods found in the System.Data.Linq.SqlClient namespace.

Using the SqlMethods.Like() method, you can do the following:

var keyword = "Marshmal";
var things = from thing in db.Things
                     where SqlMethods.Like(thing.Name, keyword)
                     select thing;

And if you want to search the start, middle, or end of your string, just tack on the '%' as you would in any normal SQL statement:

var keyword = "mallow";
var things = from thing in db.Things
                     where SqlMethods.Like(thing.Name, "%" + keyword)
                     select thing;

And there you have it...an easy way to find your marshmallows.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1388654/Profile_Photo_2.jpg http://posterous.com/users/4wPGcmBFNTyx JC Grubbs thegrubbsian JC Grubbs
Wed, 28 Jan 2009 21:34:45 -0800 Custom JavaScript Events with the Observer Pattern http://www.thegrubbsian.com/2009/01/28/custom-javascript-events-with-the-observer-pattern http://www.thegrubbsian.com/2009/01/28/custom-javascript-events-with-the-observer-pattern

Anyone that's worked with JavaScript in the browser knows that it's all about events.  And in our daily work with the DOM we use the provided events like "click", "change", and "load" all over the place.  But what if you want to create new events for custom objects that might not even have any associated UI.  Unfortunately, the W3C standard for custom events in JavaScript has spotty implementation across browsers, or none at all in some cases.

So, what are we to do...well...here's a simple implementation of the observer pattern that can help solve the lack of internal support for custom events.  Here's the Observer "classes":

var Observer = function() {
    this.observations = [];
};

var Observation = function(name, func) {
    this.name = name;
    this.func = func;
};

Observer.prototype = {
    observe: function(name, func) {
        var exists = this.observations.findAll(function(i) {
            return i.name == name && i.func == func; }).length > 0;
        if (!exists) { this.observations.push(new Observation(name, func)); }
    },
    unobserve: function(name, func) {
        this.observations.remove(function(i) {
            return i.name == name && i.func == func;
        });
    },
    fire: function(name, data, scope) {
        var funcs = this.observations.findAll(function(i) {
            return i.name == name; });
        funcs.forEach(function(i) { i.func.call(scope || window, data); });
    }
};

First thing you'll notice is methods on the "observations" array like forEach() and findAll().  These methods are added by my set of JavaScript extensions found in a previous post.  You'll also notice that this is very simple...so simple in fact that I'm not going to go through it line-by-line...I'm just going to demonstrate.  Here's how you might use this object:

var Person = function() {

    this.name = "John Doe";
    this.age = 23;
    this.observer = new Observer();
    
    this.changeName = function(newName) {
        this.name = newName;
        this.observer.fire("nameChanged", newName);
    };
    
    this.changeAge = function(newAge) {
        this.age = newAge;
        this.observer.fire("ageChanged", newAge);
    };
};

var p1 = new Person();
var p2 = new Person();

p1.observer.observe("nameChanged", alertNameChanged);
p2.observer.observe("ageChanged", alertAgeChanged);

function alertNameChanged(data) { alert("name changed to: " + data); }
function alertAgeChanged(data) { alert("age changed to: " + data); }

p1.changeName("James Doeson");
p2.changeAge(35);

Super simple...create an observer, observe a few things by name, fire a few things by name.  So now you have a behavior very similar to custom events.  One thing to note is that you can change the scope of the callback by passing a third parameter to the observe() method.  So, if you want this to reference some different object within the callback function, just pass it in.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1388654/Profile_Photo_2.jpg http://posterous.com/users/4wPGcmBFNTyx JC Grubbs thegrubbsian JC Grubbs
Mon, 26 Jan 2009 01:24:00 -0800 Useful JavaScript Extensions http://www.thegrubbsian.com/2009/01/25/useful-javascript-extensions http://www.thegrubbsian.com/2009/01/25/useful-javascript-extensions

Over the years I've collected a set of useful extensions to the Object, Array, and String constructs in JavaScript and I thought I might publish them.  They are all pretty simple but it's a pain to have to write these over and over for each new project so I just compiled them into on file and off we go.  There are probably improvements that could be made to these methods and new ones to be added so please feel free to share your ideas and I'll incorporate them back in.

Here is a listing of all the methods that this file adds:

ObjUtil.isString(Object)
ObjUtil.isNumber(Object)
ObjUtil.isBoolean(Object)
ObjUtil.isArray(Object)
Object.isFunc(Object)
ObjUtil.isDate(Object)
ObjUtil.isRegEx(Object)

ObjUtil.addOverload(Object, String, Function)
This function adds some pseudo function overloading to JavaScript.  The first argument is the name of the function you'd like to expose and the second is the function to be called using that name.  The limitation here is that the only way to distinguish between method implementations is by the number of arguments (JavaScript does not discriminate by type or name).  Thanks to John Resig for the inspiration for this method.

var obj = { };
obj.addOverload("doSomething", function(a) { ... });
obj.addOverload("doSomething", function(a, b) { ... });
obj.doSomething(a);
obj.doSomething(a, b);

ObjUtil.compareTo(Object, Object)
A generic comparison method that can be used in sorting functions.  Handles differences in lexicographical order of strings by converting to lower case.

Function.partial()
Adds partial function capability through simple currying.  Thanks to Oliver Steele's Functional.js library for this method.

var add = function(a, b, c) { return a + b + c; };
var addPart = add.partial(1, undefined, 3);
alert(addPart(2)); // alerts 6

String.toBoolean()
Converts the following values to true/false: "true" or "1".

Array.copy()
Copies an array's contents to a new array.  Keep in mind that if the array isn't made of simple types like string, number, or boolean that the new array will contain references to the old array's objects.  However, using the copy facilitates sorting and other mutations without affecting the original array.

Array.forEach(Function)
Takes a in a function and calls that function once for every item in the array.

var arr = [1,2,3];
arr.forEach(function(i) { alert(i); });

Array.find(Function)
Takes a function that returns a boolean and returns the item that matches the functions criteria.  If more than one item match the first one is returned.
var arr = [{name:"Bill", age:17}, {name:"Bob", age:27}, {name:"Brian", age:34}];
var item = arr.find(function(i) { return i.name == "Bob"; });

Array.findAll(Function)
Takes a function that returns a boolean and returns an array of all items matching the functions criteria.
var arr = [{name:"Bill", age:17}, {name:"Bob", age:27}, {name:"Brian", age:34}];
var items = arr.findAll(function(i) { return i.age > 25; });

Array.contains(Object)
Tests if an array contains a certain item, returns a boolean.

Array.distinct()
Returns a new array of distinct values from the source array.

Array.min()
Returns the minimum alpha-numeric value in the array.

Array.max()
Returns the maximum alpha-numeric value in the array.

Array.first()
Returns the first item in an array or null if the array is empty.

Array.last() Returns the last item in an array or null if the array is empty.

Array.sortAscending() Sorts the array in ascending numerical or lexicographical order depending on if the first item in the array is a number or not.

Array.sortDescending()
Sorts the array in descending numerical or lexicographical order depending on if the first item in the array is a number or not.

Array.randomize()
Randomizes the order of the array.

Array.count(), Array.count(Function)
Returns the number of items in the array.  If a function is passed in it counts the items matching the functions criteria.

var birds = [{name:"Bill", birdType:"ostrich"}, {name:"Bob", birdType:"penguin"}, {name:"Brian", birdType:"penguin"}];
var penguinCount = birds.count(function(i) { i.birdType == 'penguin'; });

Array.except(Array)
Takes two Array objects and returns a new array of only the items that are unique to both of the first two.
var arrA = [1,2,3,4,5];
var arrB = [3,4,5,6,7,8];
var itmes = arrA.except(arrB);

Array.intersect(Array)
Takes two Array objects and returns a new array of only the items shared between the first two.
var arrA = [1,2,3,4,5];
var arrB = [3,4,5,6,7,8];
var itmes = arrA.intersect(arrB);

Array.average()
Returns the average numeric value in the array.

Array.sum()
Returns the sum of the numeric values in the array.

Array.union(Array)
Returns a new array after joining two others but does not include duplicates.

var arrA = [1,2,3,4,5];
var arrB = [3,4,5,6,7,8];
var newArr = arrA.union(arrB);

Array.safePush(Object)
Adds an item to an array but only if that item doesn't already exist in the array.

Array.getRandom()
Returns a random item from the array.

Array.insertAt(Number, Object)
Adds an item to an array at the specified position (first parameter).

Array.remove(Function)
Removes items matching the functions criteria from the array.

var arr = [{id:1, name:"Bob"}, {id:2, name:"Tom"}, {id:3, name:"Jim"}];
arr.remove(function(i) { return i.name == "Tom"; });

Array.indexOf(Object)
Returns the index of the item in the array or -1 if the item isn't found.

Download JavaScriptExtensions.zip

Note: There is a "tests.html" file which contains examples and unit tests for all of these extensions.  The unit tests are written for FireUnit for FireBug.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1388654/Profile_Photo_2.jpg http://posterous.com/users/4wPGcmBFNTyx JC Grubbs thegrubbsian JC Grubbs