Archive for March, 2011

Who Needs Classes Anyway?

12 commentsWritten on March 28th, 2011 by
Categories: JavaScript

I needed to do some client-side formatting of dates that i get back from an AJAX request in JSON format, and to my surprise, JavaScript nor jQuery has something built in for this. I briefly looked around for some jQuery plugins or JavaScript libraries but was quickly lost because there are so many of them and most of them do a lot more than the tiny bit that i need right now. So i figured i'd be better off if i'd just quickly do it myself for now. Granted, i might be better off in the long run using a specific library for this but that's not really the point of this post, so bear with me for a second. What i'd normally do in a situation like this is to think about what i need to solve and create a small class for that which takes care of the job for me. In JavaScript however, there are no classes, just objects and prototypes.

The thing is though: do i really need to think about what kind of class i'll need? Am i not better off thinking "what kind of functionality do i need to implement here?" or "what kind of behavior am i trying to implement?". Does it really matter whether or not the physical packaging of that functionality is a class, an object, a module, or something else? Not really. I just want to provide some behavior, while encapsulating some of the details of how that behavior is implemented.

With a class, that's easy to do because we're all so used to doing that... just create a class with some public methods for the behavior you want to provide and whatever you want to keep private you just mark as private. There, done. So how do you do that in JavaScript? There are actually a bunch of ways to do this in JavaScript, and the code you'll see below is just one example. Some of you will read the code and think "oh ok, you're just emulating private methods here". And while you'd be right in some way, it's a somewhat unfortunate way of thinking about the code because it means you mainly think in terms of classes and objects, whereas it might be more interesting to start thinking more in terms of 'functionality' which can come in many shapes or forms.

Take a look at the code, which i'll discuss further below:

var MyNameSpace = MyNameSpace || {};

MyNameSpace.jsondateformatter = (function () {
    var that = this;

    var toDate = function (jsonDateString) {
        var time = jsonDateString.replace(/\/Date\(([0-9]*)\)\//, '$1');
        var date = new Date();
        date.setTime(time);
        return date;
    };

    var prefixWithZeroIfNecessary = function (number) {
        return number < 10 ? '0' + number : number;
    };

    var dayAsDoubleDigitDayString = function (date) {
        return prefixWithZeroIfNecessary(date.getDate());
    };

    var monthAsDoubleDigitMonthString = function (date) {
        // for some reason, the result of getMonth is zero-based
        return prefixWithZeroIfNecessary(date.getMonth() + 1); 
    };

    var hourAsDoubleDigitHourString = function (date) {
        return prefixWithZeroIfNecessary(date.getHours());
    };

    var minutesAsDoubleDigitMinuteString = function (date) {
        return prefixWithZeroIfNecessary(date.getMinutes());
    }

    return {
        toDate: function (jsonDateString) {
            return that.toDate(jsonDateString);
        },

        toShortDateString: function (jsonDateString) {
            var date = toDate(jsonDateString);
            return dayAsDoubleDigitDayString(date) + '/' +
                   monthAsDoubleDigitMonthString(date) + '/' +
                   date.getFullYear();
        },

        toShortDateTimeString: function (jsonDateString) {
            var date = toDate(jsonDateString);
            return dayAsDoubleDigitDayString(date) + '/' +
                   monthAsDoubleDigitMonthString(date) + '/' +
                   date.getFullYear() + ' ' +
                   hourAsDoubleDigitHourString(date) + ':' +
                   minutesAsDoubleDigitMinuteString(date);
        }
    }
})();

First, i create an object (if it doesn't already exist) to serve as a namespace. Then i add a property called 'jsondateformatter' to that 'namespace object'. So far this is pretty boring. But the value that gets assigned to the jsondateformatter property is what's interesting here. As you can see, i'm wrapping a function expression between 2 braces, and all the way at the bottom of the code i add the invoke operator, which is (). That means that my function expression will be immediately evaluated (typically referred to as an immediate function), and the result of that will be assigned to the jsondateformatter property. And what exactly is the return value of my immediate function? It's an object which contains 3 properties: toDate, toShortDateString and toShortDateTimeString. Each of those properties contains a function, and each of those functions refers to one or more variables that i created in the immediate function.

And this is where it gets beautiful (at least, in my opinion and i have to admit i'm kinda weird that way): due to the power of closures, the values of the variables that i created in the immediate function remain accessible in the functions that have been assigned to the properties of the object that my immediate function returns. Every function that i've created within the scope of the immediate function can only be accessed by the functions of the object that i return, and that's it. It's completely encapsulated and reusable. And you don't need classes to do it. You might think "yeah well ok, i guess that's cool but you're still using an object so it's not all too different!" and again, you'd be right in some way. But the object i'm returning here is nothing more than some kind of holder of the 3 functions that i want to make available. If i only needed to make one function available, i wouldn't return an object... i'd just return a specific function which closes over whatever i want to keep encapsulated.

And that is one of the cool things about trying to think in the language you're working with: you learn new ways of doing essentially the same thing, though that which you thought was the 'thing' is just one of many representations of its essence. Writing that last line made my head hurt, so i think i'll just stop here.

A Nuget Packaging Dilemma

26 commentsWritten on March 27th, 2011 by
Categories: agatha

I've been thinking about how Agatha should be packaged for Nuget and i just can't come up with something that i like. The problem is that Nuget misses a concept that is necessary for packages which depend on one of many possible dependencies. Agatha requires an Inversion Of Control container, but it allows you to use the container you prefer. I've talked before about the loyalty that many of us show to our preferred container, and i'm pretty sure that forcing users to use a specific container would severely limit the number of possible users Agatha could attract. So right now, Agatha users need to pick which container they want to use.

Now how do you make that fit into the Nuget packaging system? Ideally, Nuget would someday support a scenario where i can define that my package requires the user to also select one package from a list of suitable packages but until that's possible i can't really come up with a solution that i like. Here's what i specifically don't want:

  • I don't want the package to include something that the user might not want.
  • I don't want to force a particular container on users
  • I don't want to ILMerge any container assemblies because that would cause problems if users themselves make use of a container already.
  • I don't want to do it like the current NHibernate 3.1 package because that pretty much guarantees nobody will install it. NHibernate can get away with something like that because it's already an established project.

Ideally, i'd be able to define the following package structure:

  • Agatha-RRSL, requires one of the following packages to be installed (if no selection is made, go with Agatha-Windsor by default):
    • Agatha-Windsor, depends on Agatha-RRSL and Castle Windsor
    • Agatha-StructureMap, depends on Agatha-RRSL and StructureMap
    • Agatha-NInject, depends on Agatha-RRSL and NInject
    • ... (one for each supported container)

If that were possible, users wouldn't have to include anything they don't like and it could work together nicely with the packages of the various IOC containers.

As for how it should be packaged for now, i still have no idea. Suggestions are welcome :)

Sharing An IE Instance Among Multiple Tests With WatiN And MS Test

4 commentsWritten on March 24th, 2011 by
Categories: testing

Lost some time yesterday trying to get something working with MS Test (not my choice, but that's what my client uses) that i had expected to be easy. After all, it was especially easy to get working with NUnit. I wanted to create a base testing fixture which would instantiate one instance of Internet Explorer for the entire test run, and make that instance available to each test in the assembly. Sounds easy, no?

First problem: MS Test runs each test on a different thread.

When you use IE through WatiN, it uses COM behind the scenes. Accessing COM objects from different threads is not a safe thing to do and can lead to the following exception: System.Runtime.InteropServices.InvalidComObjectException: COM object that has been separated from its underlying RCW cannot be used.

Running each test individually worked, but running the entire suit made every test except for the first one fail with that exception because MS Test uses a different thread for each test (i suppose the development team did that to make sure it was enterprisey). Quite annoying, but luckily for me, the only other guy in the world who uses MS Test with WatiN also ran into the same problem and he described his workaround on his blog.

I made minor modifications to his IEStaticInstanceHelper class (basically just turned it into a static class) so my version looks like this:

    public static class IEStaticInstanceHelper
    {
        // TODO: move this to a config file
        public const string ROOT_URL = "http://localhost:13834/";

        private static IE _ie;
        private static int _previouslyKnownIeThreadHashCode;
        private static string _ieHwnd;

        public static void Initialize()
        {
            IE = new IE(ROOT_URL);
        }

        public static IE IE
        {
            get
            {
                if (GetCurrentThreadHashCode() != _previouslyKnownIeThreadHashCode)
                {
                    _ie = Browser.AttachTo<IE>(Find.By("hwnd", _ieHwnd));
                    _previouslyKnownIeThreadHashCode = GetCurrentThreadHashCode();
                }
                return _ie;
            }
            private set
            {
                _ie = value;
                _ieHwnd = _ie.hWnd.ToString();
                _previouslyKnownIeThreadHashCode = GetCurrentThreadHashCode();
            }
        }

        private static int GetCurrentThreadHashCode()
        {
            return Thread.CurrentThread.GetHashCode();
        }
    }

I also had the following AssemblyInitialize and AssemblyCleanup methods:

        [AssemblyInitialize]
        public static void AssemblyInitialize(TestContext testContext)
        {
            IEStaticInstanceHelper.Initialize();
        }

        [AssemblyCleanup]
        public static void AssemblyCleanup()
        {
            if (IEStaticInstanceHelper.IE != null)
            {
                IEStaticInstanceHelper.IE.Close();
                IEStaticInstanceHelper.IE.Dispose();
            }
        }

MS Test will call the AssemblyInitialize method before any test in the assembly is executed, provided that you don't forget to add the TestContext parameter to your method or it will silently be ignored (WTF?!). It'll also call the AssemblyCleanup method after each test in the assembly has finished executing.

Second problem: MS Test runs the AssemblyCleanup method in an MTA thread, even though each test is executed in STA threads by default.

As you can see in my AssemblyCleanup method, i access the IE property of IEStaticInstanceHelper. That property getter contains the following line:

    _ie = Browser.AttachTo<IE>(Find.By("hwnd", _ieHwnd));

That line works perfectly during the execution of the tests. When it is called from the AssemblyCleanup method, it times out after 30 seconds because it can't seem to find the IE window with the handle (_ieHwnd) that is known to be valid. And this, apparently, is because the current thread is an MTA thread when we're within the AssemblyCleanup method instead of an STA thread. I can't for the life of me figure out why they'd use an MTA thread for the AssemblyCleanup method while they use STA threads for the tests, but i will again assume it was done to keep up to the high enterprisey standard that people expect from something like MS Test.

The solution, while a horrible hack, is quite simple and works perfectly:

        [AssemblyCleanup]
        public static void AssemblyCleanup()
        {
            var thread = new Thread(() =>
            {
                if (IEStaticInstanceHelper.IE != null)
                {
                    IEStaticInstanceHelper.IE.Close();
                    IEStaticInstanceHelper.IE.Dispose();
                }
            });

            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
            thread.Join();
        }

There... nice and enterprisey.

NHibernate Course: Cancelled

5 commentsWritten on March 21st, 2011 by
Categories: NHibernate

I'm sorry to say that the NHibernate course i was going to give in April has been cancelled because there were too few registrations to make it worthwhile. Some people have inquired about the possibility of doing the course privately on-site, so the effort i've put into the prep-work might not be a total waste :) . I plan on making the examples i've prepared available for free on Github, so hopefully they'll be of good help to people who are new to NHibernate or for those who quickly want to experiment with some specific NHibernate features. I'll probably release it sometime next week since i intend to enjoy a bit of the spare time i've been missing lately ;) . They're not complete yet and more examples will be added over time by myself, and perhaps some contributions from people who want to add to them.

To those who did register: thanks for wanting to come, and sorry that you won't be able to. Perhaps some other time.

Update: First customer for having the course on-site has signed up. If you're interested in that as well, get in touch. Update 2: new date for the public course is June 20-22

Random Test Data Anyone?

7 commentsWritten on March 20th, 2011 by
Categories: QuickGenerate

I'm working on some NHibernate examples (which will be publicly available in a few weeks) and i needed some random test data. Luckily for me, i could just use Mark Meyers' QuickGenerate project to do the job for me.

Check out this code:

    public static class TestData
    {
        private static DomainGenerator WithAddress(DomainGenerator generator)
        {
            return generator
                .With<Address>(options => options.For(address => address.Street, new StringGenerator(1, 100)))
                .With<Address>(options => options.For(address => address.City, new StringGenerator(1, 100)))
                .With<Address>(options => options.For(address => address.Country, new StringGenerator(1, 100)));
        }

        private static DomainGenerator EmployeeGenerator(ISession session)
        {
            return WithAddress(new DomainGenerator())
                .With<Employee>(options => options.Ignore(employee => employee.Id))
                .OneToOne<Employee, Address>((employee, address) => employee.Address = address)
                .With<Employee>(options => options.For(employee => employee.FirstName, new StringGenerator(1, 50)))
                .With<Employee>(options => options.For(employee => employee.LastName, new StringGenerator(1, 75)))
                .With<Employee>(options => options.For(employee => employee.Title, new StringGenerator(1, 50)))
                .With<Employee>(options => options.For(employee => employee.Phone, new StringGenerator(1, 15)))
                .ForEach<Employee>(employee => session.Save(employee));
        }

        public static void Create(ISession session)
        {
            var customers = WithAddress(new DomainGenerator())
                .With<Customer>(options => options.Ignore(customer => customer.Id))
                .OneToOne<Customer, Address>((customer, address) => customer.Address = address)
                .With<Customer>(options => options.For(customer => customer.DiscountPercentage, new DoubleGenerator(0, 25)))
                .ForEach<Customer>(customer => session.Save(customer))
                .Many<Customer>(20, 40)
                .ToArray();

            var managers = EmployeeGenerator(session).Many<Employee>(2);

            var employees = EmployeeGenerator(session)
                .ForEach<Employee>(employee => Maybe.Do(() => managers.PickOne().AddSubordinate(employee)))
                .Many<Employee>(20)
                .ToArray();

            var suppliers = WithAddress(new DomainGenerator())
                .With<Supplier>(options => options.Ignore(supplier => supplier.Id))
                .OneToOne<Supplier, Address>((supplier, address) => supplier.Address = address)
                .With<Supplier>(options => options.For(supplier => supplier.Website, new StringGenerator(1, 100)))
                .Many<Supplier>(20)
                .ToArray();

            var products = new DomainGenerator()
                .With<ProductSource>(options => options.Ignore(productsource => productsource.Id))
                .ForEach<ProductSource>(productsource => session.Save(productsource))
                .With<Product>(options => options.Ignore(product => product.Id))
                .With<Product>(options => options.Ignore(product => product.Version))
                .With<Product>(options => options.For(
                    product => product.Category,
                    ProductCategory.Beverages,
                    ProductCategory.Condiments,
                    ProductCategory.DairyProducts,
                    ProductCategory.Produce))
                .With<Product>(g => g.Method<double>(1, 10, (product, d) => product.AddSource(suppliers.PickOne(), d)))
                .With<Product>(options => options.For(product => product.Name, new StringGenerator(1, 50)))
                .ForEach<Product>(product => session.Save(product))
                .Many<Product>(30)
                .ToArray();

            WithAddress(new DomainGenerator())
                .With<OrderItem>(options => options.Ignore(item => item.Id))
                .With<OrderItem>(options => options.For(item => item.Product, products))
                .With<Order>(options => options.Ignore(order => order.Id))
                .OneToMany<Order, OrderItem>(1, 20, (order, item) => order.AddItem(item))
                .With<Order>(options => options.For(order => order.Customer, customers))
                .With<Order>(options => options.For(order => order.Employee, employees))
                .OneToOne<Order, Address>((order, address) => order.DeliveryAddress = address)
                .ForEach<Order>(order => session.Save(order))
                .Many<Order>(200);

            session.Flush();
        }
    }

This populates my test-database with:

  • Between 20 and 40 customers, which have a DiscountPercentage value between 0 and 25
  • 2 Managers
  • 20 employees, some of them assigned to one of the managers, some of them without a manager
  • 20 suppliers
  • 30 products, each of which will have between 1 and 10 sources (= link with supplier and a cost)
  • 200 orders which are linked to the created customers and employees, and contain between 1 and 10 items using any of the 30 products that were also created

Pretty nifty and useful :) Of course, the vast majority of the data is entirely random at this point, but it's possible to use pre-defined values as well.

Thanks to Mark for fixing both my code as well as his on such short notice ;)