Friday, 21 December 2007

Messing around with LinqToSql

This post is part of a small series on .NET ORM tools. You can find the rest of them here.

As part of my continuing efforts to fragrantly misuse a number of .NET ORM tools, here is my effort with LinqToSql. The usual proviso applies: all of this is really quick and hacky, as it is just to get a little familiarity with the tool rather than to uncover any "best practices" or similar.

Scene refresher

I have a table of suppliers, and a table of states (or provinces, territories, prefectures etc.). Both suppliers and states have names, which are stored as strings/varchars, and IDs, which are stored as Guids/uniqueidentifiers. Each supplier can service many states. So we have a simple many-to-many relationship between the two main entities. It looks a bit like this:

I am using Aussie states for my tests, so I have populated the State table with the following names: NSW, VIC, QLD, TAS, SA, WA, ACT, NT.

Setting up LinqToSql

I created a new C# class library project, then added a LinqToSql Classes project item, which I named WorkshopDb.dbml. In true Microsoft style, you simply drag and drop the tables from the database onto the designer, which generates the necessary classes for you:

This adds an app.config file to the project, containing the relevant connection string. We are now ready to go!

Populating the database

As per my previous posts, I'll a test fixture to run the remainder of the code. After cleaning out my little database again, I'll add a method to encapsulate the process of creating a supplier and mapping the states it services:

private static void createSupplier(String name, String[] statesServiced) {
  WorkshopDbDataContext db = new WorkshopDbDataContext();

  Supplier supplier = new Supplier();
  supplier.SupplierId = Guid.NewGuid();
  supplier.Name = name;

  List<State> states = (
        from state in db.States
        where statesServiced.Contains(state.Name)
        select state
      ).ToList();

  states.ForEach(
    state => supplier.Supplier_StatesServiceds.Add(
      new Supplier_StatesServiced() {
        SupplierId = supplier.SupplierId,
        StateId = state.StateId
      }
    ));
    
  db.Suppliers.InsertOnSubmit(supplier);
  db.SubmitChanges();
}

As with SubSonic, LinqToSql does not automatically let me traverse the many-to-many relationship, but the new ForEach method makes it pretty easy to map each state to the supplier.Supplier_StatesServiceds collection (man, I really should have aliased that mapping table first).

We can now use that method to add the following test data:

createSupplier("Dave^2 Quality Tea", new string[] { "NSW", "VIC" });
createSupplier("ORMs'R'Us", new string[] { "NSW" });
createSupplier("Lousy Example", new string[] { "TAS", "VIC" });
createSupplier("Bridge Sellers", new string[] { "QLD" });

Querying the data

Let's run through the usual tests. First, getting a list of all suppliers.

[Test]
public void Should_be_able_to_get_all_suppliers() {
  WorkshopDbDataContext db = new WorkshopDbDataContext();
  var suppliers = from supplier in db.Suppliers select supplier;
  Assert.That(suppliers.Count(), Is.EqualTo(4));
}

So far so good. Now let's get all suppliers with an "s" in their name.

[Test]
public void Should_be_able_to_get_all_suppliers_with_s_in_their_name() {
  WorkshopDbDataContext db = new WorkshopDbDataContext();
  var suppliers = from supplier in db.Suppliers
          where supplier.Name.ToLower().Contains("s")
          select supplier;
  Assert.That(suppliers.Count(), Is.EqualTo(3));
}

And finally, let's navigate over the supplier-state relationship to get all suppliers that service NSW:

[Test]
public void Should_be_able_get_all_suppliers_that_service_NSW() {
  WorkshopDbDataContext db = new WorkshopDbDataContext();
  var suppliers = from supplier in db.Suppliers
          join servicedState in db.Supplier_StatesServiceds 
            on supplier.SupplierId 
            equals servicedState.SupplierId
          where servicedState.State.Name == "NSW"
          select supplier;
  Assert.That(suppliers.Count(), Is.EqualTo(2));
}

Pretty straight forward. This actually generates very similar SQL to the NHibernate example, but because I never actually get a list from the suppliers expression, the suppliers.Count() call actually uses SELECT Count(*) ... (I believe you can do similar queries in both NHibernate and SubSonic). The following is roughly what is executed via sp_executesql:

SELECT COUNT(*)
FROM [dbo].[Supplier]
INNER JOIN [dbo].[Supplier_StatesServiced] ON [Supplier].[SupplierId] = [Supplier_StatesServiced].[SupplierId]
INNER JOIN [dbo].[State] ON [State].[StateId] = [Supplier_StatesServiced].[StateId]
WHERE [State].[Name] = @p0

Vague semblance of a conclusion

LinqToSql was extremely easy to use, especially in the initial configuration department. Like NHibernate, the query syntax takes a bit of getting used to, but it is something that becomes familiar fairly quickly.

I should point out that both SubSonic and NHibernate currently target the .NET 2.0 world, so the "Language INtegrated Query" part of LinqToSql was always going to give LinqToSql a bit of an expressiveness advantage. If you are a big fan of LINQ queries, they may be coming to an ORM tool near you in the not-too-distant future now that .NET 3.5 has been released. That said, I still quite like how the query criteria works in the NHibernate example.

I also noticed that NHibernate was more domain model (i.e. classes) focused, whereas the LinqToSql query for retrieving all the suppliers that service NSW was more data-schema focussed (using the JOIN construct rather than have a working knowledge of the relationship). This isn't meant as praise or criticism of either, just a difference in the approaches. As a quick side note, I believe the ADO.NET Entity Framework is meant to have more advanced support for many-to-many relationships.

So far I've actually felt SubSonic was the most difficult to use for this particular scenario, but this is largely a result of the contrived example I used. I have used SubSonic a few times and in general it is exceptionally straight forward to get working.

As I was mainly looking into how each tool tackled this particular scenario, I have not gone into the different architectural approaches of the tools (ActiveRecord vs. DataMapper, implications for testability and persistence ignorance etc.). It's definitely worth looking into this side of things if you are unfamiliar with the tools. Ian Cooper has a great post on some of these issues as applied to LinqToSql.

That's it for now. Good luck on your ORM travels!

Messing around with NHibernate

This post is part of a small series on .NET ORM tools. You can find the rest of them here.

After messing around with SubSonic, I thought I'd run through the same scenario with NHibernate. A quick disclaimer: both tools a very different, so comparing them is a bit like comparing apples and oranges. As an example, a large part of SubSonic is the generation of DAL classes. There are ways of generating relevant NHibernate artifacts, but they aren't really an integral part of the tool.

Still, I'm not going to let a simple thing like facts get in the way of proceeding. I was interested to see how to perform the same basic scenario as last time around using NHibernate. And as per last time, all of this is really quick and hacky, as it is just to get a little familiarity with the tool rather than to uncover any "best practices" or similar. So here goes...

Scene refresher

I have a table of suppliers, and a table of states (or provinces, territories, prefectures etc.). Both suppliers and states have names, which are stored as strings/varchars, and IDs, which are stored as Guids/uniqueidentifiers. Each supplier can service many states. So we have a simple many-to-many relationship between the two main entities. It looks a bit like this:

I am using Aussie states for my tests, so I have populated the State table with the following names: NSW, VIC, QLD, TAS, SA, WA, ACT, NT.

Setting up NHibernate

I created a new C# class library project and added a reference to NHibernate. I chucked in an app.config for NHibernate's benefit that ended up like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="nhibernate"
       type="System.Configuration.NameValueSectionHandler, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
    />
  </configSections>
  <nhibernate>
    <add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider" />
    <add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2005Dialect" />
    <add key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver" />
    <add key="hibernate.connection.connection_string" value="Data Source=127.0.0.1\SQLEXPRESS;Initial Catalog=SubSonicWorkshop;Integrated Security=True" />
  </nhibernate>
</configuration>

Rather than using any NHibernate auto-mapping or code generation, I manually created the classes I wanted. I am using the automatic property accessors in C# 3.0, so if you're still using 2.0 you'll need to manually add a backing store for these.

/* State.cs */
public class State {
  public Guid StateId { get; set; }
  public String Name { get; set; }
}
/* Supplier.cs */
public class Supplier {
  public Guid SupplierId { get; set; }
  public String Name { get; set; }
  public IList<State> StatesServiced { get; set; }
}

I then need to tell NHibernate how I want to map between these classes and my relational data. You can do this by creating Hibernate Mapping files (.hbm.xml), and setting them to be included as embedded resources in the compiled DLL. Again, I did this manually, but you specify use attributes on your classes to do this auto-magically, or generate the classes, database, and/or mapping files using a variety of tools.

First let's look at the mapping for states (State.hbm.xml):

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 
                   assembly="NHibernateWorkshop.Tests" 
                   namespace="NHibernateWorkshop.Tests">
  <class name="State" table="State" lazy="false">
    <id name="StateId" type="guid">
      <generator class="guid" />
    </id>
    <property name="Name" type="String" />
  </class>
</hibernate-mapping>

Here I am telling NHibernate that a State has a StateId, which is the primary key. I am also telling NHibernate that it can generate this ID as a new Guid. I also let it know it can persist the Name property as a String. By default NHibernate will match the property name with the column name, but you can also specify that a property matches to a different column name if you like.

Now for the more interesting entity mapping, Supplier.hbm.xml:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="NHibernateWorkshop.Tests"
                   namespace="NHibernateWorkshop.Tests">
  <class name="Supplier" table="Supplier" lazy="false">
    <id name="SupplierId" type="guid">
      <generator class="guid" />
    </id>
    <property name="Name" type="String" />
    <bag name="StatesServiced" table="Supplier_StatesServiced">
      <key column="SupplierId" />
      <many-to-many column="StateId" class="State" />
    </bag>
  </class>
</hibernate-mapping>

This is very similar to the last mapping, with the exception of the <bag> property. This tells NHibernate that I have a many-to-many relationship between State and Supplier, and that it can navigate this relationship using the Supplier_StatesServiced table and the SupplierId and StateId keys.

Creating a test fixture for messing around

As I mentioned last time, I like working in test fixtures, so I created a new test fixture to run the remainder of the code in this post. Before I start using NHibernate within the fixture, I want to get access to the NHibernate ISession. I guess you could think of ISession as a conversation between NHibernate and the database. I'll do this by exposing a ISessionFactory property (note, there are optimal ways of doing this... this ain't it):

protected static readonly ISessionFactory SessionFactory = initialSessionFactory();
private static ISessionFactory initialSessionFactory() {
  Configuration config = new Configuration();
  config.AddAssembly("NHibernateWorkshop.Tests");
  return config.BuildSessionFactory();
}

I am going to use this property to create sessions as required. The AddAssembly(...) call gets NHibernate to load in all the .hbm.xml mapping files we created earlier, so the sessions we create know how to persist our entities.

Populating the database

Now we can get to work populating our database (I cleaned it out from last time). We are now on par with the SubSonic example. The steps and method signatures are going to be very similar from here on in. So like last time, I'll write a method to encapsulate the process of creating a supplier and mapping the states it services:

private static void createSupplier(String name, String[] statesServiced) {
  using (ISession session = SessionFactory.OpenSession())
  {
    Supplier supplier = new Supplier();
    supplier.Name = name;
    IList<State> states = session
      .CreateCriteria(typeof (State))
      .Add(
        Expression.In("Name", statesServiced)
      )
      .List<State>();
    supplier.StatesServiced = states;
    session.SaveOrUpdate(supplier);
    session.Flush();
    session.Close();
  }
}

Wow. To me all that additional setup now starts to seem worth it. I create a normal object and set the name property. I then create a criteria object that is going to query states, and add a restriction that the state's name must be in the array of statesServiced we passed in. I then assign the results to the supplier object, and ask the NHibernate session to SaveOrUpdate the supplier. (SaveOrUpdate means NHibernate will automatically determine whether it needs to INSERT or UPDATE the relevant database record.) As ISession represents a chat with a database, the whole thing is wrapping in a using (...) { } to ensure any resources used are cleaned up nicely.

I then used the following code to insert the same data as last time:

createSupplier("Dave^2 Quality Tea", new string[] { "NSW", "VIC" });
createSupplier("ORMs'R'Us", new string[] { "NSW" });
createSupplier("Lousy Example", new string[] { "TAS", "VIC" });
createSupplier("Bridge Sellers", new string[] { "QLD" });

Querying the data

Let's get a list of all the suppliers:

[Test]
public void Should_be_able_to_get_all_suppliers() {
  using (ISession session = SessionFactory.OpenSession()) {
    IList<Supplier> suppliers = session.CreateCriteria(typeof (Supplier)).List<Supplier>();
    Assert.That(suppliers.Count, Is.EqualTo(4));
  }
}

That's pretty much on a par with the SubSonic equivalent. The test passes. Now let's get all the suppliers with an "s" in their name:

[Test]
public void Should_be_able_to_get_all_suppliers_with_s_in_their_name() {
  using (ISession session = SessionFactory.OpenSession()) {
    IList<Supplier> suppliers = session
      .CreateCriteria(typeof (Supplier))
      .Add(Expression.Like("Name", "%s%"))
      .List<Supplier>();
    Assert.That(suppliers.Count, Is.EqualTo(3));
  }
}

Again, pretty simple, and very similar to the SubSonic version. Now to the tricky example. We want to navigate over the supplier-state relationship and get all the suppliers that service NSW. This one wasn't pretty in SubSonic.

[Test]
public void Should_be_able_get_all_suppliers_that_service_NSW() {
  using (ISession session = SessionFactory.OpenSession()) {
    IList<Supplier> suppliers = session
      .CreateCriteria(typeof (Supplier))
      .CreateCriteria("StatesServiced")
        .Add(Expression.Eq("Name", "NSW"))
      .List<Supplier>();
    Assert.That(suppliers.Count, Is.EqualTo(2));
  }
}

Again, wow. That was too easy. First we create a criteria that is going to return Supplier data. Then we want a sub-criteria that is going to use the StatesServiced property of the Supplier entity (not the table -- we are strictly dealing in domain objects here). We then say we only want the StatesServiced collection to include NSW. So what SQL ends up hitting the database?

SELECT {fields for supplier and state} 
FROM Supplier 
  INNER JOIN Supplier_StatesServiced ON
    Supplier.SupplierId=Supplier_StatesServiced.SupplierId 
  INNER JOIN State ON Supplier_StatesServiced.StateId=State.StateId 
WHERE State.Name = @p0

This is the query executed via a call to sp_executesql on SQL Server (slightly modified to better communicate the point, but the actual generated query is still very neat), with "NSW" passed as @p0.

This was very different to the experience with SubSonic, which I couldn't get to sensibly navigate over the many-to-many relationship.

Vague semblance of a conclusion

Ignoring the initial setup and configuration (as this can all be generated, but to be honest it was all fairly quick), I really enjoyed working with NHibernate. While the querying looked a little daunting to me at first glance, after about 3 seconds I found it very intuitive. Sometimes when I was working with SubSonic I found myself scratching my head as to how to get back specific information. Not so with NHibernate, as the query options I needed* were all fairly discoverable, and I never felt like I was going to have to fight the tool to get stuff out.

Again, there are vast differences between the SubSonic and NHibernate approaches, and there a probably situations to which one is better suited than the other. Rob Conery has a good post about the strengths and weaknesses of both tools, as well as LinqToSql.

Here are a couple of chapters from the official documentation that I used to get NHibernate going:

* Luckily I didn't need Projections or similar. That may have started to get a bit hairier.

Thursday, 20 December 2007

Messing around with SubSonic

This post is part of a small series on .NET ORM tools. You can find the rest of them here.

I recently heard a complaint about SubSonic queries, especially with regards to joining between tables. After looking at the forums, which basically recommended replacing complex queries or joins with SPs, I decided to have a quick play around myself. Note that all of this is really quick and hacky, as it is just to get a little familiarity with the tool rather than to uncover any "best practices" or similar. If you know better ways of doing the stuff below then you are more than welcome to leave a comment. :-)

Update 11 Jan 2008: Rob has announced that development of SubSonic version 2.1 is underway. 2.1 will have an updated query tool, so chances are the queries attempted in this post will be easier in the new version. This post relates to version 2.0.

Setting the scene

I have decided to use a <sarcasm>very realistic and common scenario</sarcasm> for my tests. I have a table of suppliers, and a table of states (or provinces, territories, prefectures etc.). Both suppliers and states have names, which are stored as strings/varchars, and IDs, which are stored as Guids/uniqueidentifiers. Each supplier can service many states. So we have a simple many-to-many relationship between the two main entities. It looks a bit like this:

I am using Aussie states for my tests, so I have populated the State table with the following names: NSW, VIC, QLD, TAS, SA, WA, ACT, NT (yes, my state table holds territories). This is all sitting in a little SQL Express database that I called SubSonicWorkshop.

Setting up SubSonic

After creating a new C# class library project and adding a reference to SubSonic, I add an app.config file that looks like this*:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="SubSonicService" type="SubSonic.SubSonicSection, SubSonic" requirePermission="false"/>
</configSections>
<connectionStrings>
<clear/>
<add name="SubSonicWorkshop" connectionString="Data Source=127.0.0.1\SQLEXPRESS;Initial Catalog=SubSonicWorkshop;Integrated Security=True" />
</connectionStrings>
<SubSonicService defaultProvider="SubSonicWorkshop">
<providers>
  <clear/>
  <add name="SubSonicWorkshop" type="SubSonic.SqlDataProvider, SubSonic"
    connectionStringName="SubSonicWorkshop"  generatedNamespace="SubSonicWorkshop.DataAccess" />
</providers>
</SubSonicService>
</configuration>

I then created a Generated folder within the solution and ran SubCommander to populate it:

C:\Program Files\SubSonic\SubSonic 2.0.3\SubCommander\sonic.exe generate /out Generated

After getting VS to show all files in the solution, then including all the generated class files, we are ready to go.

Populating the database

I tend to like working in test fixtures, so I created a test fixture class and use my test runner to run the following snippets of code. Firstly, let's write a method to encapsulate the process of creating a supplier and mapping the states it services:

private static void createSupplier(String name, String[] statesServiced) {
 Supplier supplier = new Supplier();
 supplier.SupplierId = Guid.NewGuid();
 supplier.Name = name;
 supplier.Save();

 if (statesServiced.Length == 0) return;

 Query stateQuery = State.CreateQuery().IN("Name", statesServiced);
 StateCollection states = new StateCollection();
 states.LoadAndCloseReader(stateQuery.ExecuteReader());

 //Not sure why this doesn't work (raises exception):
 //Supplier.SaveStateMap(supplier.SupplierId, states);
 //Using this instead:
 foreach (State state in states) {
   SupplierStatesServiced.Insert(supplier.SupplierId, state.StateId);
 }
}

This code creates and saves a supplier with the given name. It then retrieves a collection of states that match the state names passed in via the array, and maps these to the newly saved supplied. For some reason I couldn't get the Supplier.SaveStateMap(...) call to work, so I did the mapping using a loop. Seeing as I don't have SVN access through the firewall here I haven't delved into the SubSonic source to see where things are going wrong. I then made the following calls to add some test data:

createSupplier("Dave^2 Quality Tea", new string[] { "NSW", "VIC" });
createSupplier("ORMs'R'Us", new string[] { "NSW" });
createSupplier("Lousy Example", new string[] { "TAS", "VIC" });
createSupplier("Bridge Sellers", new string[] { "QLD" });

Querying the data

First up I wanted to see if I could load all my suppliers:

[Test]
public void Should_be_able_to_get_all_suppliers() {
 SupplierCollection suppliers = new SupplierCollection().Load();
 Assert.That(suppliers.Count, Is.EqualTo(4));
}

Yep, no problems there. How about getting all the suppliers that have an "s" in their name?

[Test]
public void Should_be_able_to_get_all_suppliers_with_s_in_their_name() {
 SupplierCollection suppliers = new SupplierCollection();
 suppliers.Where(Supplier.Columns.Name, Comparison.Like, "%s%");
 suppliers.Load();
 Assert.That(suppliers.Count, Is.EqualTo(3));
}

No problems there either. Now let's get a bit uglier. I want to navigate over the supplier-state relationship and get all suppliers that service NSW. I think this may be one of the situations mentioned on the SubSonic forums where you would probably want to use an SP to cut down the amount of chatting with the DB:

[Test]
public void Should_be_able_to_get_all_suppliers_that_service_NSW() {
 State nsw = new State(State.Columns.Name, "NSW");

 SupplierStatesServicedCollection statesServicedMap = new SupplierStatesServicedCollection();
 statesServicedMap.Where(State.Columns.StateId, nsw.StateId);
 statesServicedMap.Load();

 SupplierCollection nswSuppliers = new SupplierCollection();
 foreach (SupplierStatesServiced supplierService in statesServicedMap) {
   nswSuppliers.Add(supplierService.Supplier);
 }
 Assert.That(nswSuppliers.Count, Is.EqualTo(2));
}

The code above first gets the state we are interested in (NSW), and then gets all the mappings that feature this state. It then loops through all the mappings and adds the supplier the the SupplierCollection. This worked, but I'd hate to use that with more than a handful of records.

I think in the last situation you'd probably want to use an SP (or direct SQL). Because SubSonic generates partial classes, you could also add a method to State, StateCollection or StateController like FetchByServicedState(String stateName) to do this in a reusable manner.

That's it for now. I'm going to have a quick play with doing this in NHibernate and LinqToSql.

* I know I prevoiusly committed to giving colourful code samples, but I ran in to a few hurdles with the tool and am sticking to plain, boring code samples for now.

Wednesday, 19 December 2007

Launchy 2.0 -- now with QT!

My favourite application launcher just got better with the release of version 2.0. This release is a complete rewrite using QT, which means it is also coming to a Linux and OSX near you!

Not sure how if the previous versions did this, but this version seems to have really great integration with my Firefox bookmarks (including my quick searches). It also seems faster using the ever reliable gut-feel measurement, and now supports Vista (the previous version didn't play to well with Vista). I have to agree with the release notes that state "It's just better".

Quick warning: the new version is incompatible with your old plugins, skins and settings, so installing 2.0 will reset Launchy to factory-defaults.

If you weren't using Launchy before, I seriously recommend you start now. It's awesome. It's free. What more could you ask for?

Tuesday, 18 December 2007

Which Visual Studio version do you use?

6 or earlier? My condolences. :-) 2002, 2003? Up-to-date with VS 2005? Or even cutting edge and have Visual Studio 2008 via MSDN subscriber downloads?

That's nothing, try Visual Studio 2010, currently code-named "Dev10".

That's what Anand from the Sandcastle team is talkin' 'bout:

We have also recently entered the active planning phase for Visual Studio 2010 (code named “Dev10”), the next wave of release for our key products and technologies.

Good to know that despite using VS 2008 from the first day it was available, I am still behind the times :-)

Monday, 17 December 2007

Syntax highlighting for blogged code snippets

I recently found (forget the source, a mailing list or blog comment somewhere I think) the Iris Syntax Highlighter, which consists of a command line tool, .NET component, and an online app for generating highlighted source code in HTML (among other formats). It understands almost 500 syntaxes, including C#, XML, and various SQL flavours. 

You can download the whole lot and host it locally if you like, or just use the hosted version. It is published under a combined X11/Vim licence.

So rather than my usual, ugly code samples, I'll now make sure I post in glorious colour. The code will probably still be ugly, but at least it will be syntax highlighted ;-)

Friday, 14 December 2007

Developing for a non-software company

There are many challenges a developer faces when working for a company that is not in the business of producing software. I recently found Jacob's Scruffy-Looking Cat Herder blog, which has a few posts relating to this topic:

Jacob writes about just how important the YAGNI concept is in these environments, and also why in-house development doesn't have to suck (in contrast to Joel's suggestion).

Thursday, 13 December 2007

Lexical scope for closures in JavaScript

Ayende has a post on working with closures in JavaScript. Basically, when looking at capturing variables in a closure, you need to be careful with lexical scope. In JS the scope is a function, so if you want to capture a variable that will change values during the scope of the function, you will need to reference it via another function.

From Ayende's example, where i is set in a loop, this:

if( nums[i] % 2 == 0)
    {
      var tmpNum = nums[i];
      alertLink.onclick = function() { alert('EVEN: '+ tmpNum ); };
      //tmpNum will be bound to its value when the loop exits.
    } ...

Needs to become this:

if( nums[i] % 2 == 0)
    {
      var act = function(tmpEVEN)
      {
        alertLink.onclick = function() { alert('EVEN: '+tmpEVEN); };
      };
      act(nums[i]);
      //tmpEVEN will be bound to nums[i] at the point where act(nums[i]) is called.
    } ...

Ayende notes that in C#, the first example will work as its lexical scope is the current block (I think :S). In JavaScript, we need to use a function to get the correct scope.

Wednesday, 12 December 2007

ALT.NET manifestos

I have been following the ALT.NET group for a while now. The tech talk is great, although a lot of the threads get bogged down with topics around the group's identity, leadership, direction etc, which can become a bit distracting.

One of these posts was around Martin Fowler's suggestion that the group consider writing a manifesto to act as a guide for the community. I like the idea for the primary reason that it may cut through the identity crisis that keeps coming up in threads (and have lead to suggestions of splitting the group). I ended up suggesting one:

"We are a group of people who are passionate about improving the way we develop software.
We recognise there is no single solution, but instead there are multitudes of alternatives that can be applied to different situations.
Our community is a place for sharing these alternatives, so that together we can learn, teach, and encourage new ideas."

That pretty much sums up what ALT.NET is about to me -- constantly learning and finding new ways to improve the way we develop software. Whether these alternatives are TDD, BDD, DDD, IoC, MVC, mocks, WebForms, Silverlight, WPF, or carrier pigeon doesn't matter. The important thing is that people are talking about them and making informed decisions that suit them and their requirements.

I ended up getting a couple of positive responses to it, including from notables like Ayende, Justice and Bil (1, 2, 3). It'll probably get lost in the flood of posts to the group, but I like the idea that anyone can contribute and potentially make a positive difference.

UPDATE: This ended up on the ALT.NET wiki, thanks to Bil (until someone decides to remove it :-) ). Now if only I could make a contribution with my 1337 technical skillz instead of my Dilbertish mission statement generation abilities ;-)

Monday, 10 December 2007

ASP.NET 3.5 Extensions CTP is here!

Now go play. :-)

Apologies for content-bereft post, but I've been hanging out for the ASP.NET MVC bits for ages and I can't contain my excitement to my open-plan semi-cubicle. :-)

Wednesday, 5 December 2007

The cultural divide

Interesting post by Itay Braun (found courtesy of Roy) about Israeli-American interactions (er, I can't read the Hebrew bit. Scroll down if you are in the same boat).

In my previous job I worked with a lot of different cultures across Asia. While I honestly found it a very interesting, enjoyable and rewarding experience, there were a couple of times where someone would make a statement, and half of the people present would look at each other with a "Did he/she actually just say what I think he/she said?" expression on their faces, while the other half would nod enthusiastically.

While the post focuses on Israeli and American interpretations, some of the expressions mentioned sounded very reminiscent of some of those exchanges. For example, saying "You are wrong" can mean "I disagree and want to discuss it more to reach agreement", instead of the typical (?) Western interpretation of "This person strongly disagrees and won't tolerate further debate on the issue".

All in all it just emphasises the additional care we need to take in being clear when dealing with diverse groups, both with how we express ourselves and with how we interpret what others are saying.

Monday, 3 December 2007

VS 2008 and Dreamweaver templates

I was looking through some VS 2008 options and found something that would have really helped me about 4 or so years ago:

Dreamweaver template (DWT) support :-) This, along with things like test project template downloads for NUnit, MBUnit et al (search for "NUnit" for relevant bits), makes me think Microsoft is starting to play nice, and that the MS employees might be getting the upper hand. :-)