Jul 28 2009

OpenForum is on CodePlex

codeplex

OpenForum v0.8 (beta) is now available on CodePlex. Special thanks to Gunnar Peipman for the nice write-up on his blog, and also to Scott Hanselman for tweeting about it.

This latest release includes a few key missing features from my inital posting. Most important, there is now a wysiwyg editor for posts (using nicEdit) and the ability to search the forum (using Lucene.net). Also, the bin download now includes “view templetes”. This should give developers who want to change the actual html structure a big head start.

The plan for the next release is to provide a better default UI and a few other basic forum features. If there is anything you would like to see added, please let me know. Thanks to everyone who already provided feedback about how to make OpenForum even better.

  • Share/Save/Bookmark

Jul 13 2009

Creating a Sql Database At Runtime

In creating OpenForum, one of the things I felt was really important was that it be as easy as possible for users to get up and running. The more steps involved in getting it setup, the fewer people who would actually try it out. I know I’ve had more then a few experiences of downloading a development tool, getting 7 steps into the install/setup process, and then deciding to look into some of the tools competitors. I want tools that are simple and powerful. If it’s a pain to just get them running, what is it going to be like to customize them? Another thing I really hate is having to copy copious numbers of files into specific directories. I’ve used at least a few WYSIWYG editors that had 10x more files then the actual application I was building! So, when it came to a database for OpenForum, I wanted to avoid requiring users to do any connection string configuration, script running, or file copying. One utility that I’ve seen which I feel does a great job of solving that problem is the ASP.NET Membership Provider, especially the way that it’s used in the default MVC template. If you’ve never tried it out, it’s pretty slick. Here are the steps to get it installed/configured.

1. Do nothing

Not bad, eh? All you have to do is run the project and go to any of the pages that use membership (i.e. try logging in). As soon as you do anything that requires the use of the Membership Provider module, a database is automagically generated for in the App_Data directory. That’s what I call easy. That was exactly the experience I wanted for OpenForum. Run the application and a database is created for you.

However, it turns out that it’s not as straight forward as I was hoping. The key piece behind making everything work is a feature in SqlExpress called User Instances. User instance databases are created on a per user basis and can be attached to the SqlExpress engine at runtime. Here’s what a connection string looks like

Data Source=.\SQLEXPRESS; AttachDbFilename=|DataDirectory|\Database1.mdf; Integrated Security=True; User Instance=True

Notice the “AttachDbFilename” property. That’s what tells Sql where the database file is on disk. The “|DataDirectory|” bit will be expanded to the path to the App_Data directory for the current project.

I’m using LinqToSql, so I did a quick experiment using CreateDatabase , but quickly ran into a problem. It turns out there is a bug somewhere in the bowels of LinqToSql that causes the AttachDbFilename stuff to fail if the path to the database file (the .mdf file) is more then 128 characters. So, I broke out the second best development tool there is, and decompiled the ASP.NET Membership Provider code to figure out how the guys at Microsoft were doing it. It turns out the solution is to first create the database in a temp directory and then copy it to where you need it to go. Not too bad really as far as workarounds go. With a few minutes more of fooling around, I had the following code that seems to work really well.


using (OpenForumDataContext context =
          new OpenForumDataContext(DEFAULT_CONNECTION_STRING))
{
    string finalDirectory = (string)AppDomain.CurrentDomain
                                      .GetData("DataDirectory");

    if (!Directory.Exists(finalDirectory))
    {
        Directory.CreateDirectory(finalDirectory);
    }

    string finalPath = Path.Combine(finalDirectory, "OpenForum");

    if (!File.Exists(finalPath + ".mdf"))
    {
        string tempPath = Path.Combine(Path.GetTempPath(),
                         Guid.NewGuid().ToString());

        using (OpenForumDataContext tempContext =
                    new OpenForumDataContext(tempPath + ".mdf"))
        {
            tempContext.CreateDatabase();
            tempContext.ExecuteCommand(Resources.DefaultData);
            tempContext.ExecuteCommand(@"Declare @name as varchar(100);
                          set @name = DB_NAME();
                          Use master;
                          exec sp_detach_db @name, 'true';");
        }

        File.Move(tempPath + ".mdf", finalPath + ".mdf");
        File.Delete(tempPath + ".ldf");
    }
}
  • Share/Save/Bookmark

Jul 5 2009

Why software is hard (Part 1 of 10,000)

The other day one of my coworkers made a really profound statement. It went a little something like this. “All software is crap. The sooner you realize that, the better off you’ll be.” I think I know what he means by that. Almost all software seems slower, harder to use, and buggier then it seems it should be… including the software that I’ve written. The truth is writing good software is really hard.

The other day, while carpooling home from work, my friend and I had an interesting conversation on one of the many aspects of software that make it so difficult. Software, by its very definition, is not flexible. People are. We have a general set of “rules” that govern our day to day decision making. Those rules make the general cases of our decision making pretty straight forward. For example, if the light is red we stop and if it’s green we go. However there are billions of exceptions to that rule. If the light is green, but there’s a semi stopped in the middle of the intersection, we don’t go. Some of these scenarios are pretty straight forward. We’ve run into them thousands of times, and we know how to react. But, what if the light is green and there’s a semi stopped in the middle of the intersection and there’s a herd of charging elephants bearing down behind you? Ok, maybe not likely, but the point is that there are lots of scenarios that come up in every day life that we have no plan for. In fact, we likely wouldn’t ever have a plan until the scenario came up. In essence, we decide how to react when the situation occurs.

In software we call these scenarios “edge cases” and we do our best to code for them. The problem is that many times there isn’t a way to allow users to “decide how to react when the situation occurs”. All those options need to be programmed into the software before it’s released.

I see this a lot in business software. In business, you do what you need to do to make the customer happy (especially if it’s a big enough customer). It’s not uncommon to bend the rules to meet customer’s needs. In fact, it’s not at all uncommon to have the rules change from day to day depending on the customer, the market, and what the sales person had for breakfast that morning. Today there may be zero exceptions to the “Net 30” terms. Tomorrow the biggest account might be told “Net 593” is no problem.

The point is that business (and life in general) is very flexible. We have general rules that we follow, but we also are free to change many of those rules as necessary in order to navigate the complex systems in which we live. Software on the other hand is ridged. Software is true or false. Software does this or it does that. Software is not flexible. We try our best as programmers to make it as flexible as possible, but inevitably at some point a user will need it to work in a way that is contrary to the rules. And what does the user say when that happens? “This software sucks!”

  • Share/Save/Bookmark