No, I did not watch the Chronic-WHAT!-cles of Narnia.

What I did, though, is accomplish quite a few things on long-running projects and had quite a bit of time to relax, so big win on both counts. I’m pretty goal-oriented so it’s nice to check things off the list of things to do, and yet, I’m also really lazy so “doing nothing” is one of those things I like to check off.

Saturday was my day to accomplish stuff. The two items I got to check off my list of ongoing crap:

  1. I got my recliner fixed. Jenn and I bought some nice La-Z-Boy recliners for our game room upstairs. When they arrived, we noticed that one was really comfortable, but the other felt like you were sort of sitting in a hole on one side - you weren’t sitting level, more at an angle or something. We had the repair people come out and look at it, and there was a piece that wasn’t stapled down right so they fixed that. I sat in it, though, and it still didn’t feel right. I had some other people come over and try it, too, just to make sure I wasn’t being all “Princess and the Pea” with it and, sure enough, it wasn’t just me. The repair folks came back on Saturday and added some padding on the low side to reinforce the seat. Now it feels great! One less thing to worry about.
  2. I figured out how to play iTunes music through Windows Media Center. I’ll actually post a separate blog article on this later, but I figured out how to get Apple Lossless and AAC music playing through Windows Media Center just like MP3 files, and it didn’t require me to buy/install anything like MCETunes. Music was not my primary goal with my Media Center solution, but getting it to work makes me feel good.

Saturday night I had my friends Jason and Torin over to play some games. We originally planned on busting out some Colossal Arena but somehow we ended up playing Left4Dead for like four hours. Good times - even Jenn joined in on the zombie destruction.

Sunday was truly lazy and relaxing. Jenn and I took a bike ride to the Starbucks in downtown Hillsboro where I sucked down a giant Frappuccino, thereby negating any good the bike ride would have done. We watched some movies, had a little lunch, then around 4:00p Jason and I reconvened online for some more zombie mayhem. I rounded off the night with a very tasty barbecue meal Jenn made. Good times.

books, dotnet comments edit

I just got finished reading through ASP.NET 3.5 Enterprise Application Development with Visual Studio 2008 by Vince Varallo, and I came out fairly underwhelmed. I read through this book thinking, with a title like that, it would take me through creating an enterprise-class application, complete with all of the things one would think are a part of such an app. As it turns out, I think the title should be something more like “Introduction to N-Tier Development in ASP.NET.”

Each chapter is set up in the same format, and it’s a decent format - outline the problem, explain the design, implement the solution. The chapters are:

  1. A Framework for Enterprise Applications
  2. The Data Access Layer
  3. Designing the Business Logic Layer
  4. The User Interface Layer
  5. Exception Handling
  6. Role-Based Security
  7. The Workflow Engine
  8. Notifications
  9. Reporting
  10. The Query Builder Control
  11. The Dashboard
  12. Auditing
  13. Code Generator

If you go in never having built a multi-tier app where you separate your data access from your business logic and your UI, this is a good intro to that. The explanation of the separation and showing how to keep those things separated is a good education for the ASP.NET developer who has only ever just thrown a DataSource on a page and let the controls do the work.

If you have any experience with multi-tier apps, though, the goodness, unfortunately, is not to be found. Even if you have a light amount of experience, I probably wouldn’t recommend this book since it could do more damage than help. There are several reasons for this.

First, there are little things through the code that are just bad practice.

  • The naming conventions for everything in this book are absolutely horrible. “ENTBaseBO” is the name of the base class that all enterprise business objects derive from. The names only get worse and more unintelligible and distracting from there. When cruising through the method bodies presented you sometimes wonder if he’s using Hungarian notation in C# and then you realize that it’s just bad naming.
  • Almost every exception that gets thrown in the code is the generic System.Exception type. Even if a more specific exception type would be more appropriate, it’s always a general Exception.
  • Rather than overriding the ToString() method on business objects, a new “GetDisplayText()” method gets added in one of the myriad base classes which gets used throughout the book when displaying the object in UI. (Not a showstopper, but it’s Just One More Thing that didn’t make sense.)
  • The data access layer uses the Microsoft Patterns and Practices Data Access Application Block, which is good… but the book urges you to use an old version of it “because it’s simple to use and easy to understand” - even though the new one has many improvements over the old.

Larger things start creeping up on you once you get past the smaller stuff.

  • There’s no localization and no mention of it. Every string seen in any UI is hardcoded somewhere in the system (not necessarily just in the UI) rather than being stored in resource files. Even if you only plan on supporting one language, it’s still good practice to separate your strings from your code.
  • There are no tests anywhere and no mention of them. We’re building an enterprise application and we’re not going to test it? Really?
  • Rather than use standard functions built into ASP.NETlike the SiteMapProvider and navigation controls that can bind to it, a lot of effort goes into writing your own site map management system and custom controls to bind to that proprietary system. Role-based security that doesn’t hook into the RoleProvider.
  • Chapter 7, on “the workflow engine,” is almost 100 pages showing you how to write a proprietary state machine workflow system. I actually had to flip back and look at the cover to make sure we were in .NET 3.5, then I got really curious as to why this wasn’t a 10 page chapter showing how easy that sort of thing is to implement using Windows Workflow Foundation, which comes for free with the .NET framework.
  • Why is the “code generator” chapter about creating a Visual Studio wizard but has no mention of T4 or any third-party code generator? With all the code generation options out there, would I really want to roll my own using StringBuilders?

Other stuff just sits in the background and bugs at you more subconsciously. The code snippets in places are inconsistently formatted and hard to read. You start wondering why there’s a little bit of logic in stored procedures and a little bit of logic in the data access layer and a little bit of logic in the business layer and whether there might have been a way to break that up in a way that would be more maintainable. No mention at all of design patterns. No mention of MVP or MVC.

Long story already too long, if you’ve never written an n-tier application, if you’re used to just creating a single web application project that just has pages in it that were created in the Visual Studio designer and that’s it… this book will give you some ideas about how to change the way you look at your application’s structure and separate the logic out of the codebehind of your pages into different layers. If you have written any sort of n-tier application before, this is most likely not for you.

[Postscript: While writing up this review, it reminded me of the recent Jim Holmes blog post challenging MS Evangelists to present real examples with tests rather than just highlights. This book felt like one of those presentations - show you the rough idea and general concepts, but not the full “real world” view with good patterns and practices.]

UPDATE 3/15/2010: I got several questions about what book(s) I do recommend for learning enterprise app development so I posted a short list of recommendations.

dotnet, vs comments edit

CodeRush (and Refactor! Pro) from DevExpress are my Visual Studio add-ins of choice. They’re based on the “DXCore” engine, which makes writing your own Visual Studio add-ins a breeze.

DevExpress has released a free version of their CodeRush tool called “CodeRush Xpress” for users of Visual Studio

  1. It includes 60+ refactorings as well as a host of additional helpful functionality. If you have not treated yourself to trying these amazing tools, this is a great way to give it a run - huge value, no cost to you.

Once you fall in love with it, check out other plugins that are available - also free - like CR_Documentor and the DXCore Community Plugins.

I’m working on getting my Windows Media Center to play my iTunes files (by installing codecs and tag readers) and one of the things I’m doing is setting the album artist on all of the tracks because that’s something Windows Media Center needs set to get album art properly. While doing it, I found there were basically two classes of track that didn’t already have the album artist tag set - those that fell into “Various Artists” (like soundtracks and such) and those where the artist should also be set as the album artist.

To make it easy and less tedious, I wrote a script to set the album artist field to the artist. I figured I’d pass it along for other folks to use at their own risk. No promises this won’t corrupt your library or anything. Keep backups.

First, make sure you’ve set all of the tracks that are “Various Artists” as such. This script doesn’t take care of that for you. It’s not smart, it just sets “artist = album artist” for tracks missing album artist. Once you’ve taken care of all of your “Various Artists” tracks, run this script:

    var ITTrackKindFile  = 1;
    var iTunesApp = WScript.CreateObject("iTunes.Application");
    var numTracksWithoutAlbumArtist = 0;
    var mainLibrary = iTunesApp.LibraryPlaylist;
    var tracks = mainLibrary.Tracks;
    var numTracks = tracks.Count;
    var foundTracks = new Array();

    WScript.Echo("Checking " + numTracks + " tracks for missing album artist...");
    while (numTracks != 0)
    {
      var  currTrack = tracks.Item(numTracks);

      if (currTrack.Kind == ITTrackKindFile && !currTrack.Podcast)
      {
        if(currTrack.AlbumArtist == null || currTrack.AlbumArtist.length == 0)
        {
          numTracksWithoutAlbumArtist++;
          foundTracks.push(currTrack);
        }
      }

      numTracks--;
      if(numTracks % 1000 == 0)
      {
        WScript.Echo(numTracks + " tracks left to check...");
      }
    }

    if (numTracksWithoutAlbumArtist > 0)
    {
      WScript.Echo("Found " + numTracksWithoutAlbumArtist + " tracks missing album artist. Creating playlist and updating artists...");

      var playList = iTunesApp.CreatePlaylist("Fixed Album Artists");
      for(var trackIndex in foundTracks)
      {
        var currTrack = foundTracks[trackIndex];
        currTrack.AlbumArtist = currTrack.Artist;
        playList.AddTrack(currTrack);
      }
      WScript.Echo("Playlist created.");
    }
    else
    {
      WScript.Echo("No tracks missing album artist were found.");
    }

What it does is:

  • Iterate through all of the tracks in your library and find the ones that aren’t Podcasts that have no album artist.
  • Creates a playlist.
  • Sets the artist as the album artist on the tracks it found.
  • Adds those tracks to the playlist so you know which tracks were updated.

In the event it does something wrong, you can always select all the tracks in the created playlist and set the album artist back to empty.

Again, YMMV, use at your own risk… but it worked great for me.