Ayende @ Rahien

Refunds available at head office

The Hurdles Of Playing With ASP.Net

A couple of days ago I posted an idea about how simple it is to create an MVC framework on top of ASP.Net without affecting much of the development model. Since then, I got a chance to play with it a bit, and I'm surprised at what I found.

First, the tests were done using Web Application Projects, since there isn't even a point to start doing this in Web Site Project (although the implementation that I have right now will work there as well).

Ideally, what I would have wanted to do is to reflect over all the pages that implements a certain interface, IView (to be original) and add them to the IoC container, then when a request come in, I resolve it to the proper controller based on the URL, and the controller gets is view (the page) from the container.

The problem is this, there is not easy way to get the type of the page object from ASP.Net. The pages themselves are compiled the first time that they are request (simplified), so there isn't a good way to handle it except use GetCompiledPageInstance(), and this ties me back to the paths on the HD.

I suppose that I can write some component that will find all the .aspx files in the directory, and register them, but this looks really clunky to me.

Right now I'm using strings based approach, somewhat similar to the way MonoRail is working, and I inject Hashtables to the view. The problem with this approach is that I lose all the strong typing that I could get if I could get the interfaces to work.

Comments?

Published at

Windows Doesn't Like Me Recently

So, I come home today, and find that the computer is:

  • Turned off
  • Won't boot, saying that "\WINDOWS\system32\config\system" is corrupted or missing.

That file is one of the major registery file, and is mandatory for Windows to boot successfully. I followed the procedure outlined here, but I couldn't get it to recognize all the changes that I made to it.

The problem is that this is the second time that this has happened to me on that computer in about a month. The first time, I did a complete disk scan, and it verified that the dirve is okay. What I am afraid of is that it will happen again. I really don't have time for this stuff.

Any ideas what can cause this issue?

Right now I'm installing Windows to another drive, but I'm very pissed off about it.

Tags:

Published at

The meaning of geekdom


It is to sit in Cinema City, the biggest movie theater in Israel, waiting for the movie to start, and pulling out a laptop and start reading blogs.

Diving Into Hashtables and Dictionaries

 

Most programmers had to implement a Hashtable or a map at some point (usually at school). Hopefully, they never do it again, but gain valuable insight about how the collection works.

In .Net, there are two methods that each object implements which are used with hash tables. Those methods are GetHashCode() and Equals(). When you create your own classes, you get the default behavior, which is to check for object reference equality (to the C/C++ guys, that is pointer equality).

The problem starts when you want to provide a different semantic for  Equals. For instance, if you have a range, and you want to say that if both items are the same, they are equals. So you override Equals(), make the appropriate check, and you are ready to go. [1]

First, a Hashtable is composed of buckets, like the ones of the left. A bucket has key and value, although in some cases, it has several key / value pairs.

Well, the Hashtable calls to the key's GetHashCode() method, divide the resulting value with the current capacity of the table. It then takes the remainder and check if there is already a value in the bucket.  If there is, it will double its capacity and try again[2].  Usually if there is a collision (two different keys with the same hash code), both of them will be put into the same bucket.

How does it pull the values out, then? Well, it is actually a lot simpler than that. You give the Hashtable a key and ask for a value. It calls the GetHashCode() method on the key, get the remainder from division with the capacity and then it knows in which bucket to check.

Remember, a bucket may contain more than one key, and even if we limited ourselves to a single key per bucket, it is entirely possible to have two keys with the same hash code. Therefore, the Hashtable will call the Equals method on the two objects. It will continue to do so on all the keys in the bucket  and find one where Equals() return true. If it can't find any key where Equals() is true, it will return null (or throw).

Do you see now why it is so important to implement Equals() and GetHashCode() together? And why it is crucial that objects that are equal to one another will return the same hash code?

If objects that are equals to one another do not return the same hash code, the Hashtable will look in a different bucket and will never find the correct key.

It is also important to remember that you may not want to put your objects as keys in a Hashtable, but there are plenty of others that will. Many frameworks uses Hashtable to add additional data to an object, which they can later access and act upon. Breaking the Equals()/GetHashCode() assumption will cause nothing but trouble, and it is one of those bugs that are extremely hard to find. Mostly because it is extremely non-obvious.

That said, you don't need to start implementing Equals() and GetHashCode() on all your objects, only on those where reference equality functionality is not enough. In the example above, a range is equal if the start and end are equals, and the hash code is simple adding the hash codes of the start and end.

 

 

 



[1] Except that annoying compiler warning, asking you to implement GetHashCode() as well.

[2] There are a lot of things I gloss over here. I'm not describing how to implement a Hashtable, but a high level overview of how it works.

Published at

NUnit 2.4 Alpha

Halleluja! Check out the release notes for NUnit 2.4. Here are the things that I'm excited about.

  • Can install by non administrators
  • CollectionAssert - At long last, we have it. I can't tell you how often I wanted those asserts. And check out the methods that this has.
    • AllItemsAreNotNull
    • AllItemsAreUnique
    • Contains
    • IsEmpty
    • IsSubsetOf / IsNotSubsetOf
  • File Assert with support for steams!
  • App.config per assembly

The most important thing is that they have (finally) setup / teardown at the assembly level! This is a huge deal for me, since I write a lot of applications that require initial state, and then I need to remember initializing it in the setup of each test.

They also have support for setup / teardown per namespace, which is really strange.

This is looking really cool.

Tags:

Published at

Client Side C# - Script#

Nikhil has implemented a C# to javascript/ajax compiler. It looks very interesting. I got a request just like this one just a few days ago.

Being able to write Ajax in a strongly typed langauge is going to have a huge affect on the cost of using it, in my opinion. Especially if it produce valid javascript for all browser. (And from what I have seen, it does).

The killer application for this would be to be able to debug the C# code, of course. But I wouldn't like it, since it would be too many layers of indirections :-)

Tags:

Published at

Yet Another Way To Crash VS.Net

This one is in the common path, incredibly easy to trigger, and will cause you to lose your work.

  • In Vs.Net, create a C# console application project
  • Right click the project and click View Class Diagram
  • Ctrl+A, Delete to get rid of everything
  • Now change the ClassDiagram1.cd name to Foo.cs (the extention is important)
  • Watch a couple of errors before the IDE going down in flames.

It is nice because they actually got a message for it, and it says that I got a problem with the VB compiler. So this is the sixth or seventh crashing bug that I found recently. Is it just security bugs that you get a prize for?

Ladybug is here.

p.s: I see that they renamed passport ot Windows Live ID, bah...

Working With Team System Source Control


I got a chance to work a while with Team System (I'm heavily into Subversion) and I had a hard time working with it. It is not that it is not good, it has some very nice features (the diff tool is awesome, for instance), but I do not like the way it was setup (which is the default, as far as I know).

Exclusive checkouts are a pain in the ass to work with, even beyond locking files, just the idea that every time I try to edit a page (or something tries to edit a page, like a refactoring) it needs to be checked out from the repository  and the IDE is frozen in the mean time (can be seconds to half a minute).

Working with integrated source control in the IDE is not my cup of tea. I don't care about source control when I am developing. The only use I have for it is to revert stuff or check it in (and rarely do comparisons) .  Those things are best done from outside the IDE, since it forces me to think clearly about what I am doing.

I have seen the people working there edit something and immediately check it in. Often without so much as a check-in comment. It is encouraged, since otherwise they are stepping on each other toes all the time. "Joe, can you release Blah.cs for me?" are common. They do not think in terms of a change set that add some feature to the application.

I know that Team System is a lot more than just a source control (and I'm actually liking the other features very much. Integrated bug tracking in the IDE is cool[1], to mention one in particular). And yes, I know that there are (free) tools that allows workflow  similar to the one in Subversion.



[1] No, I don't have to be consistent. Integrated source control is bad. Integrated bug tracking is good. Why? Because.

Tags:

Published at

Office 2007 Beta 2 Mini Review


Well, it is looking really nice, and they updated outlook as well, if not as significantly. I'm writing this now with Word's Blogging functionality, and overall the experience is very good. Except that I can’t post this using Word, of course.

The one problem that I noticed is that I can type faster than Office can accept the input, and sometimes it feels somewhat sluggish.  I'm not overly concerned about it right now. It's a beta, and I'm running this on a heavily loaded computer.

One thing that really matters is that the UI is beautiful. I am one of those that like the XP themes, and when I had to work without one for a while, I felt that the UI was hard and ugly. I can very easily get use to the slick look of Office 2007.

Power Point gave me a lot of trouble at the begining, it set itself up to hebrew, and kept sneaking back to hebrew. Extremely annoying. There is an option to disable that (which took a lot of hunting to find), but while it improved somewhat, I still get this problem.

Smart art is really cool. If anything, this is going to be the killer feature for me. Very easy to create some very nice stuff.

Word can produce production ready PDFs, which is a welcome addition I promptly made use of. Very nice.

Tags:

Published at

NHibernate Best Practice - Assert Cascade Behaviors

I've said it before, one of the trickiest parts on NHibernate is the cascade behaviors. Why is it tricky? Because a slight configuration can cause the application to get exception at best, or silently lose data at worst.
How does this work? Let us assume that I have the Blog -> Posts model, and I want to create a new post. I can do this like this:

using(ISession session = factory.OpenSession())

{

    Blog blog = session.Load(typeof (Blog), 1) as Blog;

    blog.Posts.Add(new Post("NHibernate", "Best", "Practices"));

    session.Flush();
}

Because the way I defined the cascades from blog to posts, this will save the new post to the database. But there are a lot of reasons to change the cascading options.  The problem that such a change can break the implicit assumption in the code above. Depending on the specific  setting that was set, it may throw an exception or silently ignore the new value.
Because of this, I usually document my assumptions using tests. I got tests like:

  • SavingABlogSavesAllItsPosts
  • SavingAPostDoesNotSaveComments

After having to go through the pain of changing the configuration and ending up bad results, I make sure that if I break one of the assumption that I did, I'll at least be aware of it. There is a good chance that I will decide to go ahead with the change anyway, but this will make sure that I will double check the assumptions that the rest of the code does, and not blithely continue on the way to unpleasantness.   

Solving the Assembly Load Context Problem

One of the more annoying things about the way .Net is handling assemblies is the load context. If you load an assembly using Assembly.LoadFile(), it will not be available if you then do Assembly.Load().
There are any number of scenarios where this is a major hurdle. Any kind of plug in architecture, for instance. After getting bit by this when I wrote NHibernate Query Analyzer, I know way too much about resolving assemblies and the problems that this entails.
It can get much worse when you try to load assemblies from locations that are not in your private bin path. Anyway, I put together a small class that will fix this issues for me.

public static class AssemblyLocator

{

    static Dictionary<string, Assembly>assemblies;

   

    public static void Init()

    {

        assemblies = new Dictionary<string, Assembly>();

        AppDomain.CurrentDomain.AssemblyLoad += new AssemblyLoadEventHandler(CurrentDomain_AssemblyLoad);

        AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);

    }

 

    static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)

    {

        Assembly assembly = null;

        assemblies.TryGetValue(args.Name, out assembly);

        return assembly;

    }

 

    static void CurrentDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs args)

    {

        Assembly assembly = args.LoadedAssembly;

        assemblies[assembly.FullName] = assembly;

    }

}

As you can see, all you need to do is to call AssemblyLocator.Init(), and it will make sure that any assembly, not matter how it was loaded, will be accessible via Assembly.Load() and friends.

Tags:

Published at

Word 2007 Blogging Feature

I've tried Word's Blogging feature, and while it looks very cool, there is one big problem with it.

It refused to publish new posts to my blog. It got no problem with reading or updating existing posts, but it just refuse to post new things, claiming that it can't connect or the password is wrong. I tried both MetaWebLog and as Community Server (my blog is DasBlog)

Argh!

 

Tags:

Published at

OR/M Is Not About Data

The main benefit of an OR/M is not that it can fetch data from the database. There are multitude of other ways to do this task.

The main benefit is that it makes us think about our model as a set of objects, and not as rows in tables. Objects has behaviors, inheritance structure, encapsulation, etc.

The ability to use OO tools and practices in all the layers of your application is fantastic. It means that I can replace case statements with strategies, that I get a general algorithms instead of thinking about the specifics.

Take the following tables, which contain the data about business rules that apply to some merchant.

Merchant: { Id, MerchantType, … }

Rules : { Id, RuleType, … }

Here is how I would have to handle if I was working on the data directly:

List<Error> errors = new List<Error>();

foreach (MerchantRow merchantRow in merhcants)

{

    foreach (RulesRow ruleRow in rules)

    {

        switch (ruleRow.RuleType)

        {

            case 1:// no outstanding debts

                switch (merchant.MerchantType)

                {

                    case 3:// internal , no validation neccecary

                        break;

                    default:

                        if (business_logic)

                            errors.Add(new Error());

                        break;

                }

        }

    }

}

 

I may be slightly exaggerating, but there is no way to avoid this in a table driven architecture. On the other hand, here is how I would handle this in an object driven architecture:

 

List<Error> errors = new List<Error>();

foreach (Merchant merchant in merchants)

{

    foreach (Rule rule in rules)

    {

        Error error = rule.GetErrors(merchant);

        if (error != null)

            errors.Add(error);

    }

}

 

All that ugly stuff about the rule type and merchant type are abstract away to objects with different behaviors. I got different types of rules, and different types of merchants, and I can work cleanly and effectively.

Adding a new merchant type is as easy as creating a new object , override several methods and mapping it to the database. I wouldn't care to find all the places where switch / case statements were used in a data driven.

This is just a tiny taste of what is possible. Given enough time and some clear thought, it is not hard to come up with some very crazy ideas that are so damned hard without taking objects all the way to the database.

Tags:

Published at

Web Continuations Considered Harmful

IanG has an excellent post about why continuations are not suitable for the web.

The underlying point that he is making is that if you try to force a foreign model into a process, you'll break stuff, hard. A good web framework should not high the nature of the beast, it should make it explicit. To do other wise is to court trouble.

Tags:

Published at

Learning Code

How I approach a code base that I am not familiar with?

I know what it is supposed to do. I got no idea how it does it, though. Hopefull it is not something as vague as "handle client transactions".

The next step is to read through the code. Not in any particular order, just pick an Access Point and start you search from there. Most of the OO techniques are about seperating concerns, and this means that you may have a hard time figuring out what exactly is going on with the code.

I write a couple of tests to verify the existing behavior. This is mainly a sanity check for me, to see that I understand what it is supposed to do. I will also try to debug through those tests, to see the flow of the code. This is very important get a... feeling for the code. A sense of what the original developer has intended.

The next step is to try to add a new feature. I don't usually go for half measures, I try to add a radically new one, and see how I can integrate it into the rest of the system. The easiest way to do it is to add a failing test and try to get it to work. One important consideration is that I'll want to make it integrate as seamlessly as possible with the rest of the system, this means maintaining the same coding standards, programming idiom are important.

After I make the first feature test work, I write several more premutations of it. To try and see how tohe system behave in unexpected circumstances.

Usually, after implementing a big feature, I have a fair amount of knowledge about the system. Good naming helps, a lot.

All of the above is true if the codebase is reasonable. If it is bad, I'll either write from scratch or use Sprout New Application.

How do you do it?

Tags:

Published at

ASP.NET 2.0 WebParts WebCast

Justin has a 2 hours web cast about web parts in ASP.NET 2.0. Hebrew only.

The web cast contains just about every bit of information that you need to start working with web parts, including very advanced topics.

Personally, I think that he is crazy, that is not the way to job security, Justin :-)

Tags:

Published at

Agility

I was at a client a couple of days ago, and I was explaining why I implemented a feature should be configurable or not. The default behavior was correct most of the time, and only some edge scenarios needed to be configured the other way. There was some argument about what should the behavior be.

At a certain point, I dropped out the argument, sneakily opened Visual Studio and modify the feature so it could work either way. I got quite a kick of saying "Okay, it is now configurable…"

Published at

Model View Controller In ASP.Net

As it turned out, it takes 20 lines of code to add MVC to ASP.Net*:

public class ModelViewControllerHandlerFactory : IHttpHandlerFactory

{

    public IHttpHandler GetHandler(HttpContext context,

                string requestType, string url, string pathTranslated)

    {

        string path = context.Request.Path;

        IController controller = Container.Current.Resolve<IController>(path);

        controller.Process(context);

        context.Items[controller.View] = controller;

        return controller.View;

    }

 

    public void ReleaseHandler(IHttpHandler handler)

    {

        IController controller = HttpContext.Current.Items[handler] as IController;

        if (controller == null)

            return;

        controller.End();

        Container.Current.Release(controller);

    }

}

This relies on Windsor Container to handle the mapping from a request path to the appropriate controller, and then it will wire up the view defined for the controller, as well as anything else needed to handle the request. The controller then does the work, pushing all the values to the view, and then the view is run normally.

This maintain a strict seperation of a concerns between the controller and the view, but still allows you to do all the usual ASP.Net magic.

* Okay, I lie. This is the bare minimum that you have, which is usually not something that you would like to do. Since it will force you to map each url in the application. Usually you will want to be a little smarter about it.

CallContext on ASP.Net

I'm very fuzzled at the moment, I just run into the CallContext class, and I'm pretty confused.

I'm a pretty heavy use of Context bound items, and I usually need to bind to the current request in asp.net or to the current thread. I even create a class to make it easier. It looks like CallContext does the same thing, but it is built into the framework.

From googling around, it looks like in 1.1, it was the way HttpContext was implemented, and from Reflecting over 2.0, it seems that there is a special HostContext property in the IllogicalCallContext that is used for this.

So, the question is if it safe to use CallContext to store items that are bound to the current operation, where an operation is bound to either a thread or a web request? It looks like it is safe in 1.1, but I don't know about 2.0...

Tags:

Published at

C++: Template Specialization

First, I am appalled to admit that I needed Google to remember that C++ has "using namespace std;", but after this confession, I think that we can move on and talk about one of the more interesting capabilities of C++, templates and template specialization.

Here is a simple example, you want to create all your objects through factories, but you have different rules about how each type should be created. We will assume that for 90% of the cases, you will want the default behavior, but you have to have a way to customize this. There are at least five ways to do this in C++ (that are specific to C++) that I can think of right now. Template Specialization is one of them, and the nicest in the bunch.

Here is the default factory implementation:

template<typename T> class Factory

{

public:

      static T* Create()

      {

            return new T();

      }

 

      static void Release(T t)

      {

            delete t;

      }

};

It just new / delete the object that you request. Not terribly useful, but we are staying in the realm of simple examples. Now we get to the fun part, specializing this for creating users. We want to add a user id, and we don't want this logic to be in the User class. Here is how it is done:

template<> class Factory<User>

{

public:

      static User * Create()

      {

            User *user = new User();

            user->Id = CalcNextUserId();

            return user;

      }

 

      static void Release(User* user)

      {

            delete user;

      }

};

Here is the class diagram.

 

You can use those classes like this:

Factory<vector<int> >::Create()
Factory<User>::Create()

The first line just new the object, but the second one call to a complete different class, even thought they are looking nearly identitcal. A lot of the neater tricks in c++ ( and most of the smart libraries {ATL, Boost, etc} ) are based on this feature. The example I gave here is a truly trivial one, but consider a Repository<> that is specialized for each object you are going to call, you got an instance data access strategy, and a consistent way to access it.

Now, I'm not a C++ programmer anymore, so there isn't much point in taking it deaper on the C++, this post is laying the background to the more exciting .Net work that I was doing lately, based on those pricnipals. Keep in mind the basic principals, you can define a general algorithm, and specialize it for a certain type, without affecting the API* or the way in any way, shape or form. There is tremendous power in this. I recall hearing that C++ Templates are turing complete, which means that you could literally do anything you want with them.

 Now to the .Net side. Generics and templates looks somewhat the same at first glance, but there are many differences between the two. There is a great post about the differences between generics and templates here.

That is for now, I'm going to blog shortly about how you can make use of those patterns in .Net.

* As a matter of fact, you can change the API if you want, which is really awesome.

Published at

Tacking Complexity Into The Heart Of Software

No, the headline is not a typo.

It refers to a discussion that I had with a developer about the different advantages of developing application frameworks. The main points where:

 

  • Using text-book Microsoft's Mort approach – pass around data sets as the data layer all the way to the UI, business logic modify the data sets directly.
    • Advantages:
      • Easy to explain
      • Easy to get a developer up to speed on the project
      • Lots of resources and people running into problems that you would be able to Google.
      • Easy to see the flow of a single execution thread in the program.
      • Lot of tool support
    • Disadvantages:
      • Hard to work with when the application grows / change
      • Easy to get duplicate code, because business logic is scattered in data sets' events, some helper classes, wrapper object, etc
      • Very hard to see the flow of a program from a high level view
  • Using Inversion Of Control Container as well as object relational mapping:
    • Advantages:
      • Easy to work and develop with
      • Centralizing control of the application and reducing dependencies.
      • Very easy to extend the application
      • Very easy to see the high level flow of execution
      • Reduced complexity because can now use objects and OOD to solve issues
    • Disadvantages:
      • Requires training developers to use it
      • Not all developers can understand parts of the code base – the IoC's Container code, for instance
      • Hard to see a single flow of execution in the program

 

We both agreed that IoC + OR/M was a better approach from a technical / design point of view (feel free to agree, but I would like to hear why), the argument was whatever it was worth going this path when it would be harder to get developers to work with the system.

I am in the firm belief that an application framework should embed as much functionality as possible, and that building specific functionality to an application should be extremely simple for developers who know the system. My assumption is that if you are bringing new developers in and out of a project often enough that learning how the project works is a hurdle, you got more pressing problems to worry about.

The application we discussed was a live application, which means that it is constantly modified, updated and extended. Under those circumstances, I think that a big investment in an application framework will have a fairly significant ROI.

The other side is that while we are building the application framework, there is nothing much to show for it except some unit tests that doesn't really mean anything without a lot of explanations, and that is to other developers, not to business guys.

Going the Mort's way will allow other developers to start adding business value to the application immediately, but there would be a lot more work to do for most scenarios.

 

What do you think /

Published at

Date Merging Challange Solved

I will give some wierder problem next time, Scott solved the problem (the simple one and the harder) in a really nice way. What more, he posted about how he solved the problem, and this is great.

I often don't bother to explicitly think about the step to a solution, so it was a pleasant surprise to see how he got to the answer, not to mention that anyone reading it gains some valuable insight about how to solve those kind of problems.

Great job Scott!

SQL Challange, Date Merging

FromDate ToDate
01/01/2000 31/01/2000
01/02/2000 28/02/2000
05/03/2000 31/03/2000

I have the following table, what must I do to get to this one:

FromDate ToDate
01/01/2000 28/02/2000
05/03/2000 31/03/2000

Basically, the first two date ranges were merge into a single date range because they were adjunct to each other.

Update: It looks like I barely get a chance to post a problem before it is solved. Let try increasing the complexity of this one. Good job, Scott.

Now I want to get all the inclusive date range. So for this data:

FromDate ToDate
01/01/2000 31/01/2000
01/02/2000 28/02/2000
05/03/2000 31/03/2000
01/02/2000 15/02/2000
15/03/2000 15/04/2000

And the result should be:

FromDate ToDate
01/01/2000 28/02/2000
05/03/2000 15/04/2000

More Dynamic Than Thou

Well, that didn't take very long. In a couple of hours, I have four ways to solve my challange. I guess this means that C# is getting near C++ in expressiveness, I guess.

Omer van Kloeten got very near to what I had in mind, but I am afraid that it is not dynamic enough for me. So, without further ado, I present to you my Foo:

class Foo

{

    public Action<string> DoWork = delegate { };

}

 

static void Main (string[] args)

{

    Foo foo = new Foo();

    foo.DoWork("Foo");

    foo.DoWork = Console.WriteLine;

    foo.DoWork("Bar");

}

Now the challange is to consider when this would be useful...

Hint: A good place to search for reasons to do this would be Ruby / Python, where you can do this stuff

Note: It is trivial to make this code work in 1.1 as well.

Tags:

Published at

It is not as simple as you might think

I really like this post, asking for clarification to file copy operation.

Check out this link, both for the fun factor, and for realizing that a "simple" operation such as copying a file is anything but, and that there are a multidue of concerns that need to be addressed in order to get a sufficent result.