Sunday, March 1, 2009

Things to CodeGenerate besides the Data Access Layer

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/things_to_codegenerate_besides_the_data_access_layer.htm]

CodeSmith is a powerful code generator (worth its weight in gold). And while one of the most popular things to automatically generate is the data access layer, there's a lot more to CodeSmith than just wrapping databases:

  • System data - Given an xml file, you can generate all your interrelated system data. For example, say your application has a data-driven relationship of groups, roles, menu items, tabs, and such (i.e. security and navigation) - you could write tons of tedious and brittle SQL scripts, or you could abstract it to an xml file and generate the SQL scripts from that.
  • Data Structures - Especially before Generics in .Net 2.0, CodeSmith was popular for its strongly-typed collections (much faster performance than boxing and unboxing an ArrayList). You could make other data structures as well, depending on your application's need.
  • Documentation - While CodeSmith's default DataDictionary template is popular for documenting your database schema, you could use CodeSmith as a Super-XSLT to transform any arbitrary xml list (like a file containing business rules, config, or test cases), into human-friendly HTML reports.
  • Domain-Specific-Language - It's often more efficient to work at a higher level of abstraction. So, you could write an xml script, and use CodeSmith to translate that ("compile?") into useful actions.
    • Say you were trying to write automated UI tests, but the UI technologies keep changing, so you write a simple abstract xml script for the basic actions you care about (Load page, click button, etc...), and CodeSmith transforms that into the UI testing code for the relevant testing framework.
    • You could write abstract tests in xml (i.e. the data for pairs of input and output), and then use CodeSmith to dynamically generate all the unit tests from that.
    • You could read your file system to create an MSI installer using something like Wix.
  • Starting Templates - I favor active re-generation when possible, and there's a balance between what to code-generate vs. what to refactor, however, sometimes it's useful to passively generate a starting template - just to give you a head start. For example, say your UI is too complicated to actively re-generate, but you could take an xml file of input and generate a stating template, from which you could then modify.

Basically, CodeSmith lets you take any input (a database, xml file, your file system, etc...) and generate any text output (sql, xml files, C#, aspx, html, js, etc...), and then also call C# to do anything on those files (install them in the database, commit it to source control, execute the resulting C#, etc...). It's a beautiful thing.

Monday, February 23, 2009

What makes a framework easy to experiment with?

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/what_makes_a_framework_easy_to_experiment_with.htm]

I've been reading the excellent Framework Design Guidelines. One of the sections that stood out is the tips they offer to make your framework easy for other developers to experiment with. As most developers are experimental in nature, any framework must be "cooperative" in this manner in order to be popular.

  • "Allow a developer to use it immediately, whether or not it does what the developer ultimately wants it to do or not" (23).
  • "Types used in advanced scenarios should be places in subnamespaces" (23).
  • "Provide simple overloads of constructors and methods" (24). A type that is hard to instantiate is hard to experiment with.
  • Give common scenarios recognizable names. For example, "MyClass.CreateFile" sounds more friendly than "MyClass.OpenInputOutputSteam", so more developers would naturally experiment with the former.
  • "...a default should never result in a security hole or horribly performing code." (26)
  • "Do ensure that APIs are intuitive and can be successfully used in basic scenarios without reference documentation (27). I notice their emphasis - instead of writing tons of tutorials (which most devs won't even read), make the framework itself easy to use.
  • Make things strongly typed.
  • And the classic - A good framework makes it easy to do the right things, and hard to do the wrong things.

They offer ADO.Net as an example of what is confusing (juggling all the different types just to hit the database).

These are good points, and easy to overlook, but make sense when someone points them out to you.

Sunday, February 22, 2009

Killing the file handles, but not the process (from the command line)

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/killing_the_file_handles_but_not_the_process_from_the_comm.htm]

Most developers have come across that annoying error where you try to delete or rename an innocent file, only to be  rebuffed with "Access denied, another process is accessing this file." For example, you'll get this type of error if you create a text file, open it in Microsoft Word, and then try to delete the file. This happens for all sorts of things - whether it's a process that didn't clean up after itself (perhaps from an unexpected crash), or something like IIS that locks certain website directories. While PSTool's ProcessExplorer GUI is great for finding what process is locking the file, what if you just want to find the handle, and kill it - from the command line?

Note that there's s a difference between the process, and the handle that that process has on the file. For example, if you want to delete a website that IIS is locking, you could shutdown or kill IIS (i.e. the process itself), but say you want to leave IIS running? Killing just the handle would leave the process intact, while allowing you control of the file again.

A useful tool for this is the (free) PsTools Handle.exe. From the command line, you can query all handles to a file, and then you can delete those handles. For example, this will find all handles on the given directory:

handle.exe C:\MyFolder

And returns something like so:

inetinfo.exe pid: 1696 3DC: C:\MyFolder\MySubfolder
inetinfo.exe pid: 1696 3E0: C:\MyFolder

You can then use this info to close the handles (one-by-one), without killing the process by passing in the "-c" switch, along with the handle id (in hex), and the process id, and the "-y" switch to confirm the delete.

handle.exe -c 3DC -p 1696 -y
handle.exe -c 3E0 -p 1696 -y

You could glue these two steps together into one by calling System.Diagnostics.Process to run the first command, parse its output, and then use that to create the parameters for the second command.

I'm sure there are more elegant ways (perhaps direct C++ calls, or even some special method in the .Net Framework), and I'm all ears to any, but this approach will get the job done.

Tuesday, February 17, 2009

The different between Count, Length, and Index

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/the_different_between_count_length_and_index.htm]

When dealing with arrays and collections (like List), there are three integer "things" that can mess people up: Count, Length, and Index.

  • Count - refers to collections. This simply gets the number of items in the collection.
  • Length - refers to arrays. to quote: "Gets a 32-bit integer that represents the total number of elements in all the dimensions of the Array." (emphasis added). For a 1-d array, Count and Length seem similar. But for multi-dimensional arrays, the difference becomes apparent. A 3x2 array will have a length of 6. Because an array is allocate up front (as opposed to a collection that can grow or shrink), this conceptually makes sense. Length for an array doesn't change after declaration; Count for a List does (as you add or remove items).
  • Index - used by arrays, and some collections (like List), to indicate a specific item in the array or collection. Whereas Count and Length are 1-based properties, Index is a 0-based indexer.

This code snippet shows these in action:

    [TestMethod]
    public void TestMethod1()
    {
      //Length --> total number of items in the array
      //  acts like "Count" for a 1-d array
      string[] astr = new string[]{"a","b","c"};
      Assert.AreEqual(3, astr.Length);

      //  but very different for a 2-d array
      string[,] astr2 = new string[2, 3];
      Assert.AreEqual(6, astr2.Length); //Length = 2 * 3

      //Count --> 1-based
      List<string> lstr = new List<string>();
      lstr.Add("a");
      lstr.Add("b");
      Assert.AreEqual(2, lstr.Count);

      //Index --> 0-based
      Assert.AreEqual("a", astr[0]);
      Assert.AreEqual("b", lstr[1]);
     
    }

Monday, February 16, 2009

Real life: Taking down the Christmas lights and project failure

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/real_life_taking_down_the_christmas_lights_and_project_fail.htm]

In Chicago, we've had another cold winter. Finally, we got a reprieve as it got warm enough for the snow to melt. I looked outside at our 25 foot (?) pine tree, and saw my opportunity to take off the lights. I had done this before, and I figured it should be a quick "project".

However, as luck would have it, things did not go well. The winter wind must have pushed the lights closer to the tree trunk, and entangled them in the branches. I had borrowed someone else's extension pole to initially put them out, and returned it, so I did not have the ideal tools. Regardless, I started out working on the bottom of the tree - close to the ground where I had the most maneuverability, and things seemed optimistic. However, as I worked on higher and higher branches, it got slower. At first I thought I'd just "tough" it through, perhaps with the job taking 2-3 times longer than I thought, but things just screeched to a halt at the 15-foot mark.

With the long strands of lights entangled in all the branches, I had no choice but to actually cut the lights. I thought that I had found my solution, so now it would just take 4-5 times longer than scheduled, and I'd need to throw away the lights. But, at the 20-foot mark, I didn't even have the tools with which to cut the lights. Now I was desperate - it would be a fire-hazard to have openly-cut electrical lights hanging on a tree 20 feet in the air. So, I broke down and drove to the hardware store. The guy found an old Christmas-light extension pole, complete with claw for grasping lights to pull them down (i.e. the right tool), and I returned home with new hope.

Finally, with this new tool, I could finish the job - behind schedule and with a mess of cut-up lights for garbage. It almost felt like a software project.

Sunday, February 15, 2009

Part of the problem testing UI technologies is that they change so frequently

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/part_of_the_problem_testing_ui_technologies_is_that_they_cha.htm]

Anyone who has actually tried to write automated tests knows that testing the UI is much harder than testing a backend class library. Besides having an obscure interface to the test (like parsing an HttpResponse), and juggling far more dependencies (like needing a live application, complete with database and HttpContext), another problem is that UI technologies change much more frequently than backend ones. For example, you could still call a C# .Net 1.0 library from 8 years ago. However, during that time, the web UI has gone from Html (request/response) to JS-enabled, to advanced JS with Ajax/JSON/JQuery (by now your test harness needs its own JS engine), to Silverlight (where the request/response model no longer even applies). By the time you've built a robust UI test framework, your UI could be using a different technology that your framework cannot handle.

This makes it much harder to write automated tests for the GUI - i.e. not the sort of thing you just add in hindsight. There seems to be a lot of projects out there that have designed themselves into a corner. A manager rushes the project to market with an un-testable design because they think they'll just whip up UI testing later, but then they find they've accrued an insurmountable technical debt, and they just can have it. It's like they spent years constructing the pyramid on the east side of the river, but oops - now they realize they wanted it on the left side instead.

I think this is one of the reasons why good unit testing (and MVC) is becoming so popular in many circles.