# Friday, November 28, 2008

We all love unit tests (do we?). Yes we do (repeat 100 times). And we all love mocking for making life easier, but sometimes we just want to write some simple unit tests that don't require any mocking at all, because the code you are testing is easy to test without having to resort to all those mocking tricks

But what if you need to test code that relies on the date or some elapsed time? Let's say you wrote a simple caching class that automatically removes items from the cache when a certain amount of time has passed since the last access. It's tempting to slap some Thread.Sleep() calls in there to trigger expiration of cache items, but that will slow down your unit test, and most importantly, it's not accurate. What if you want to test some edge cases? Like, what happens when you access an item at the exact timeout period?

A few years ago I worked with a brilliant Java architect who simply said: "just mock the time!". What he meant was that I should create a fake DateTime class which behaves like the real DateTime class with one important difference: YOU control the time, not the system clock.

How is that done?

Simply create an interface with a single getter property of type DateTime:

public interface ITimeProvider 
{
   DateTime Now { get; }
}

Then you create 2 classes that implement this interface: one that returns the real time, and one that can be used to control a "fake" time:

public class RealTimeProvider : ITimeProvider
{
    public DateTime Now { get { return DateTime.Now; } }
}

public class MockTimeProvider : ITimeProvider
{
    private DateTime _time;

    public DateTime Now { get { return _time; } set { _time = value; } }
}

Of course the class(es) you want to test should be aware of this. For example, our cache class could look like this:

public class Cache
{
     private ITimeProvider _time = new RealTimeProvider();

     public ITimeProvider TimeProvider { get { return _time; } set { _time = value; } }

     // ... the rest of the class implementation
}

In our class implementation, all calls to DateTime.Now should be replaced by TimeProvider.Now.

And now the fun part, faking the time in our unit tests:

[Test]
public void TestCacheTimeout()
{
    ITimeProvider time = new MockTimeProvider();
    Cache cache = new Cache();

    cache.TimeProvider = time; // Tell our cache class to use our fake time

    cache.Add("A" , 1); // add an item to the cache

    Assert.IsTrue(cache.Contains("A")); // check if it's added

    time.Now += TimeSpan.FromHours(1); // let one hour go by...

    Assert.IsFalse(cache.Contains("A")); // check if it was automatically removed
}

That's pretty cool and simple, isn't it? Wouldn't it be nice if we could do the same in real life? ;-)

Next week I'll talk a little about unit testing multithreaded concurrency issues...

kick it on DotNetKicks.com
Friday, November 28, 2008 6:41:29 PM (W. Europe Standard Time, UTC+01:00)  #    Comments [0] -
 |  |  | 
# Thursday, October 30, 2008

Jeff Atwood (Coding Horror) wrote an interesting blog post about detecting hyperlinks in blocks of "regular" text. I was suprised by the wave of negative comments he received, mainly because Jeff tried to solve a complex problem with a "simple" regular expression. I don't agree with these comments at all. Software developers are too obsessed with borderline cases. What's wrong with "good enough"? What's wrong with solving 99.99% of all possible situations? After all, what's the worst that can happen if the algorithm is not 100% correct? You'll see a bad hyperlink. Big deal...

Anyway, the thing is, as Jeff points out, URL's can contain some pretty weird characters you wouldn't expect, like '(', ')' and ','. This can become quite frustrating when trying to parse something like this:

My website (at http://www.mysite.com/coolpage) is becoming very popular, especially because of traffic coming from http://www.othersite.com/coolestpage, which is a cool site I recently found.

For humans, it's pretty obvious where the hyperlinks are, but what if the links contain some of the non-standard characters I mentioned above? For example:

http://www.mysite.com/coolpage(nice).aspx or http://www.othersite.com/coolest,wildestpage. Both of these are valid URLs.

If you would implement a trivial URL detector, the following URLs would be extracted from the text snippet above:

"http://www.mysite.com/coolpage)" and "http://www.othersite.com/coolestpage,".

Note the trailing parenthesis and comma. Obviously that is not what we want. The fact is that there is no way we can extract valid URLs by following a set of fixed rules, not even for humans. We humans will "parse" the URLs by looking at the context, but that's a pretty hard, if not impossible task for software.
What we can do is use some heuristics to satisfy at least 99.99% of all cases, so I started thinking about this a little bit and came up with a solution that uses regular expressions and requires no code at all.

Let's start with the basics. A URL contains 3 distinct parts, of which the last part is optional:

protocol://host/path

"host" is a hostname (or IP address), optionally followed by a port number, so this is the regex we can use for this:

([a-zA-Z-:@.0-9]+)

Of course, this will not validate the host name part of the URL, but that's not really our goal now.

Next we should specify what the path looks like. According to the specs, the path can contain any of these characters: letters, digits and any of -;:@&=$_.+!*',()

In this example, we will only try to match http and https, so our trivial regex would look like:

\b(https|http)://([a-zA-Z-:@.0-9]+)(/[-;:@&=?a-zA-Z0-9$_.+!*',()])?

That will work in most cases, but it fails miserably in our text snippet example.

Let's make an assumption: we assume that a URL containing parentheses always has matching parentheses, as in "http://www.mysite.com/Some(Nice)Page". This would exclude URLs with a single parenthesis, so "http://www.mysite.com/Some(NicePage" would not be recognized as a URL. That's a sacrifice I'm willing to make.

There are several ways of writing a regex like this, but a simple one is:

\b(https|http)://([a-zA-Z-:@.0-9]+)(/((\([-;:@&=a-zA-Z0-9$_.+!*',]*?\))|[-;:@&=?a-zA-Z0-9$_.+!*',]|%\d\d)+)?

Note that I also added some regex code for escaped characters (%nn). Nested parentheses will not be matched.

This would solve the first match in our text snippet, but not the second one with the trailing ','. Again, we will make an assumption: let's assume that a URL will never end with a period or a comma. I think that's a pretty safe assumption to make (although technically it is allowed).

Our final regex will then look like:

\b(https|http)://([a-zA-Z-:@.0-9]+)(/((\([-;:@&=a-zA-Z0-9$_.+!*',]*?\))|[-;:@&=?a-zA-Z0-9$_.+!*',]|%\d\d)+)?(?<![,.;])

This regex will match any valid URL pattern, except URLs without matching parentheses. It will also exclude URLs with a period, comma or semicolon at the end.

Again, it's not a perfect solution, but I bet it will be very hard to find a real-world example where this regex would fail to extract the URL from a piece of text. The regex can still use some tweaking, but you get the picture.

kick it on DotNetKicks.com
Thursday, October 30, 2008 6:36:30 PM (W. Europe Standard Time, UTC+01:00)  #    Comments [3] -

# Friday, March 07, 2008

Every decent programming book tells you to write readable code. Few people do.

Code is read a lot more often than it is being written. Fact.

Programming style is all about personal taste. Agreed.

On the other hand, well... let's just take a very small piece of code from the BCL written by Microsoft:


    Type p = this;
    if (p == c) 
        return false; 
    while (p != null) {
        if (p == c) 
            return true;
        p = p.BaseType;
    }
    return false; 


Without changing any of the code (except spacing and indentation):


    Type p = this;
    
    if (p == c) 
        return false; 
    
    while (p != null) 
    {
        if (p == c) 
            return true;
        
        p = p.BaseType;
    }
    
    return false; 


I know the code is longer, and there are better examples to be found, but what makes code readable is being able to see the structure of the source code. This can be accomplished by using correct spacing, empty lines and correct placement of braces.

I especially want to stress the importance of using empty lines. Their primary purpose is to visually separate blocks of code. Note the example above. The original code has no empty lines whatsoever, which makes code very hard to read (even if you wrote the code yourself).

When should you use empty lines (IMHO) :

  • Before and after every control block ("if", "for", "while")
  • Before and after return statements
  • After blocks of variable declarations
  • After blocks of assignments
  • In between assignments if they "don't belong together"
  • (a curly brace counts as an empty line of course)

This is a small code fragment which illustrates some of these points:


    newSetMethod = typeBuilder.DefineMethod( /*ommitted*/ );

    ILGenerator ilGen = newSetMethod.GetILGenerator();

    ilGen.Emit(OpCodes.Ldarg_0);
    ilGen.Emit(OpCodes.Ldstr , baseProperty.Name);
    ilGen.Emit(OpCodes.Ldarg_1);

    if (baseProperty.PropertyType.IsValueType)
    {
        ilGen.Emit(OpCodes.Box,baseProperty.PropertyType);
    }

    ilGen.EmitCall(OpCodes.Call,setFieldMethod,null);

    ilGen.Emit(OpCodes.Ret);


Of course, there's more to readability than inserting empty lines, but it's a point which is often neglected. The most often heard excuse is that it makes code shorter. (sigh)

I don't want to start a religious war, just trying to express a (strong) opinion.

kick it on DotNetKicks.com
Friday, March 07, 2008 9:04:43 PM (W. Europe Standard Time, UTC+01:00)  #    Comments [16] -
 |  | 
# Wednesday, March 05, 2008

Constructing related .NET objects (an "object graph") from XML files is a familiar challenge to most developers out there. Although it is not hard to write something like that: just read the tokens and fill the appropriate objects.

In most cases, the code produced is not very readable and hard to maintain, because the problem is usually implemented in a linear fashion with lots of loops and repeated (or similar) statements.

When faced with this problem, I usually use the "Factory Method" pattern to implement this. The idea is that every object class has its own FromXml() method which creates its own object according to the XML node passed in as a parameter.

For example, let's suppose we want to create a customer object from an XML segment where the customer name is a child element and the customer ID is an attirbute like:

<Customer id="CUST1"><Name>My Customer Name</Name></Customer>


The factory method would look like this (I'm using C# syntax for object construction):

public partial class Customer
    {
        public static Customer FromXml(XmlNode xmlNode)
        {
            Customer customer = new Customer {
                                        Id = xmlNode.Attributes["id"].Value,
                                        Name = xmlNode["Name"].InnerText,
                                        Orders = new List<Order>()
                                    };

            return customer;
        }
    }

 
Now suppose each customer has a number of orders, which are located under the <Orders/> child element. So we use the Order object's factory method to create the Order object from the XML child nodes:

public partial class Customer
    {
        public static Customer FromXml(XmlNode xmlNode)
        {
            Customer customer = new Customer {
                                        Id = xmlNode.Attributes["id"].Value,
                                        Name = xmlNode["Name"].InnerText,
                                        Orders = new List<Order>()
                                    };

            foreach (XmlNode xmlOrder in xmlNode.SelectNodes("Orders/Order"))
                customer.Orders.Add(Order.FromXml(xmlOrder, customer));

            return customer;
        }
    }
    


Got the picture? Now let's pull it all together, and parse the following XML file to our object graph containing "Customers", "Orders" and "OrderItems":

<?xml version="1.0"?>
<CustomerList>
<Customer id="CUST1">
  <Name>Mr X</Name>
  <Orders>
   <Order number="5001">
    <OrderItems>
     <OrderItem>
      <Description>Item 1</Description>
      <Price>45.00</Price>
     </OrderItem>
     <OrderItem>
      <Description>Item 2</Description>
      <Price>99.00</Price>
     </OrderItem>
    </OrderItems>
   </Order>
   <Order number="5002">
    <OrderItems>
     <OrderItem>
      <Description>Item 3</Description>
      <Price>120.00</Price>
     </OrderItem>
    </OrderItems>
   </Order>
  </Orders>
</Customer>
<Customer id="CUST2">
  <Name>John Doe</Name>
  <Orders>
   <Order number="5003">
    <OrderItems>
     <OrderItem>
      <Description>Item 4</Description>
      <Price>550.00</Price>
     </OrderItem>
     <OrderItem>
      <Description>Item 5</Description>
      <Price>41.50</Price>
     </OrderItem>
    </OrderItems>
   </Order>
  </Orders> </Customer> </CustomerList>


And the code:

XmlDocument xmlDoc = new XmlDocument();

xmlDoc.Load("test.xml");

CustomerList customerList = CustomerList.FromXml(xmlDoc.DocumentElement);

public partial class CustomerList : List<Customer>
{
}

public partial class Customer 
{
    public string Id { get; private set; }
    public string Name { get; set; }
    public List<Order> Orders { get; private set; }
}

public partial class Order
{
    public int OrderNumber { get; private set; }
    public List<OrderItem> OrderItems { get; private set; }
    public Customer Customer { get; set; }
}

public partial class OrderItem
{
    public string Description { get; set; }
    public decimal Price { get; set; }
    public Order Order { get; set; }
}

public partial class CustomerList
{
    public static CustomerList FromXml(XmlNode xmlNode)
    {
        CustomerList list = new CustomerList();

        foreach (XmlNode xmlCustomer in xmlNode.SelectNodes("Customer"))
            list.Add(Customer.FromXml(xmlCustomer));

        return list;
    }
}

public partial class Customer
{
    public static Customer FromXml(XmlNode xmlNode)
    {
        Customer customer = new Customer {
                                    Id = xmlNode.Attributes["id"].Value,
                                    Name = xmlNode["Name"].InnerText,
                                    Orders = new List<Order>()
                                };

        foreach (XmlNode xmlOrder in xmlNode.SelectNodes("Orders/Order"))
            customer.Orders.Add(Order.FromXml(xmlOrder, customer));

        return customer;
    }
}

public partial class Order
{
    public static Order FromXml(XmlNode xmlNode, Customer customer)
    {
        Order order = new Order {
                            OrderNumber = Int32.Parse(xmlNode.Attributes["number"].Value),
                            Customer = customer,
                            OrderItems = new List<OrderItem>()
                        };

        foreach (XmlNode xmlItem in xmlNode.SelectNodes("OrderItems/OrderItem"))
            order.OrderItems.Add(OrderItem.FromXml(xmlItem, order));

        return order;
    }
}

public partial class OrderItem
{
    public static OrderItem FromXml(XmlNode xmlNode, Order order)
    {
        return new OrderItem {
                                 Description = xmlNode["Description"].InnerText,
                                 Price = Decimal.Parse(xmlNode["Price"].InnerText),
                                 Order = order
                             };
    }
}


The advantages of using this pattern are obvious:

  • Very readable (and maintainable) code
  • The implementation details on how to read a particular type of object are located in the class itself, making it very easy to make a small change (for example adding a new property to an object)
  • Easy to read recursive object graphs
  • Properties that should be read-only can be made read-only (no messing with "internal" properties)

Note that a similar pattern can be used for writing objects to an XML file. Just create a member method "ToXml()".

kick it on DotNetKicks.com
Wednesday, March 05, 2008 9:03:02 PM (W. Europe Standard Time, UTC+01:00)  #    Comments [4] -
 |  | 
# Monday, August 20, 2007

What's worse than:

  • Global variables?
  • Badly chosen variable names?
  • ASP.NET WebForms :)?
  • Leaky abstractions?
  • ... enter your worst coding nightmare ...

I've got one word for you:

Dependency Injection (well, that's two words actually)

Why?

Remember 20 years ago? All of a sudden, WYSIWYG word processors were all the rage. For a good reason. WHAT YOU SEE IS WHAT YOU GET. Exactly!. Writing, editing, reading a document while you don't have to worry about what the end result will look like. It was heaven.

The same is true for writing and reading code. Code should (more or less) do what it looks like it is doing. That's obvious.

What does Dependency Injection do with your code? Nobody but the guy who implemented it knows. Now, THAT's comforting.

You read a piece of code, and you think you understand what it's doing, but the actual code is something completely different at runtime. WYSINWYG. A maintenace nightmare.

I know a lot of people will disagree, but all this code-changing magic is an accident waiting to happen. I wonder if this stuff is used in the Space Shuttle program code.

But that's just MHO.

kick it on DotNetKicks.com
Monday, August 20, 2007 7:56:47 PM (W. Europe Daylight Time, UTC+02:00)  #    Comments [4] -
 | 
# Monday, August 06, 2007

One of the most powerful features in .NET is the ability to use reflection to do all kinds of neat stuff at runtime, like

  • Find out what properties, fields, methods, etc. are in a class
  • Create objects without knowing their type at compile time
  • Call methods by name (even private ones)
  • Check attributes on classes, methods, fields, …

The web framework I built over the last few years, ProMesh.NET, relies on reflection for a lot of the features it offers. Often though, I am asked if the heave use of reflection doesn’t have a significant impact on performance.

My answer usually is: YES, but it doesn’t matter. Now you probably think that I don’t care about performance or that I’ve had too much too drink. None of the above. I’ll explain:

In ProMesh.NET, there’s a feature that allows you to just declare session properties in your class that will be constructed at runtime, like this:

   private SessionProperty<string> _mySessionVar1;
or
   private SessionProperty<string> _mySessionVar2 = new SessionProperty<string>();

You don’t have to initialize _mySessionVar1. The framework uses reflection to construct the object.

Creating _mySessionVar1 is about 20 times slower than creating _mySessionVar2. Shocking? Yes. Unacceptable? No!

The reason why it is not unacceptable is that it takes 2.2 µs (microseconds) to create _mySessionVar1, and 0.12 µs (microseconds) to create _mySessionVar2. These figures include dynamically iterating the over the class members, determining their type and looking up the appropriate constructor. This is the simplified code which creates the fields at runtime:

foreach (MemberInfo member in GetType().GetMembers())
{
if (member is FieldInfo)
{
FieldInfo field = (FieldInfo) member;

ConstructorInfo constructor =
field.FieldType.GetConstructor(Type.EmptyTypes);

field.SetValue(this, constructor.Invoke(new object[0]));
}
}

Considering this happens when a web page is requested, which usually involves some database access, a little disk access and some other time-consuming stuff, a complete web page request takes between 50ms and 2000ms. Assuming we have 20 session variables to construct at runtime, the overhead is … between 0.08% (worst case) and 0.002%.

So, yes it is MUCH slower, but it doesn’t matter. (not for applications of this kind)

kick it on DotNetKicks.com
Monday, August 06, 2007 8:48:01 PM (W. Europe Daylight Time, UTC+02:00)  #    Comments [3] -
 |  |  |  |  | 
# Wednesday, August 01, 2007

The other day I was checking out the Microsoft Web Client Software Factory, but I wasn’t very impressed. Too complicated, too “heavy”, too …

Anyway, I did stumble upon something interesting: it includes a class that allows you to define a class member that will survive page requests (in other words, it is stored in the session). Of course, the class can’t be used without implementing the whole framework. Too bad. But then I thought: hey, this shouldn’t be too hard to implement as a standalone class… and it isn’t. Fifty lines of code to be precise (and it takes the concept a little further than the original)

Imagine you are writing a web application, and imagine you could have a (typed) property in your class that, whenever you access it, you are actually writing to the session? Not too hard, but it requires some code:

public int CustomerID
{
   get
   {
      if (HttpContext.Current.Session["CustomerID"] == null)
         return -1;
      else
	 return (int) HttpContext.Current.Session["CustomerID"];
   }
   set
   {
      HttpContext.Current.Session["CustomerID"] = value;
   }
}

Not too bad, I know, but we can do better

How about this:

private SessionProperty<int> _customerID = new SessionProperty<int>("CustomerID",-1);

public int CustomerID
{
   get { return _customerID.Value; }
   set { _customerID.Value; }
}

The number of lines of code isn't that much lower, but it is a lot cleaner.

You can even do this:

private SessionProperty<Customer> _customer 
   = new SessionProperty<Customer>("CurrentCustomer",
                              delegate { return new Customer() });

public Customer CurrentCustomer
{
   get { return _customer.Value; }
   set { _customer.Value; }
}

In the example above, if there is nothing in the session when you first access the property, it will create a new instance of the Customer and store it in the session. No more fear for NullReferenceExceptions. Isn’t this cool?

Did I forget something? ... Yes! The code!

    
public delegate T Creator<T>();

public class SessionProperty<T>
{
private readonly string _sessionKey;
private readonly T _defaultValue;
private readonly Creator<T> _defaultValueCreator;

public SessionProperty(string sessionKey)
{
    _sessionKey = sessionKey;
    _defaultValue = default(T);
}

public SessionProperty(string sessionKey, T defaultValue)
{
    _sessionKey = sessionKey;
    _defaultValue = defaultValue;
}

public SessionProperty(string sessionKey, Creator<T> defaultValueCreator)
{
    _sessionKey = sessionKey;
    _defaultValueCreator = defaultValueCreator;
}

public T Value
{
    get
    {
	if (ProMeshHttpContext.Current.Session[_sessionKey] == null)
	{
	    if (_defaultValueCreator != null)
	    {
		T value = _defaultValueCreator();

		Value = value;

		return value;
	    }
	    else
		return _defaultValue;
	}
	else
	    return (T) HttpContext.Current.Session[_sessionKey];
    }
    set
    {
	HttpContext.Current.Session[_sessionKey] = value;
    }
}
kick it on DotNetKicks.com
Wednesday, August 01, 2007 9:27:36 PM (W. Europe Daylight Time, UTC+02:00)  #    Comments [3] -
 |  | 
# Wednesday, July 25, 2007

Yesterday, an old article resurfaced on dotnetkicks.com about validating Guid strings. Several comments hinted at the possibility of letting the .NET Framework convert it to a Guid and catching the FormatException.

WTF !?

I must be very old-fashioned, because I am still very religious about (mis)using exceptions in normal application flow. Exceptions were designed for exceptional events, not for validating user input.

Even Microsoft picked up on that, because they added a bunch of TryParse() methods in version 2.0 of the .NET Framework.

In case you’re wondering if there are any REAL reasons for avoiding exceptions in the normal flow of an application, I’ll give you two:

  1. Exceptions are slow. Let me repeat: SLOW.
  2. When you are in a debugging sessions, and you told the debugger to break at the first exception (which is often done), you will know what I’m talking about.

 

kick it on DotNetKicks.com
Wednesday, July 25, 2007 8:31:38 PM (W. Europe Daylight Time, UTC+02:00)  #    Comments [0] -
 |  | 
# Tuesday, July 24, 2007

In one of my previous posts, I talked about the separation between code and markup, which caused quite a bit of turmoil, especially from the PHP and MonoRail enthusiasts.

Maybe I didn’t make myself perfectly clear. I don’t have a problem with embedding view logic inside HTML markup, as long as it stays within reason. On the other hand, application logic should be kept on the server (in the controller or deeper layers).

I mentioned MonoRail (combined with the NVelocity engine) because I saw two things I didn’t like:

  1. The scripting language goes too far
  2. The templates are not designer friendly

1. The scripting language

In my (humble) opinion, a template rendering engine should be limited to the following constructs:

  • Looping over a collection
  • If…else… constructs for showing conditional blocks
  • Embedded variables fed from the server

NVelocity adds macros and variable assignment. These features allow complete programs to be written inside the template, and this is not what we want (again, IMHO)

2. Designer friendly

An HTML template file that can’t be opened by an HTML editing application is worthless. The HTML in the template should also be valid.

The NVelocity templates used by MonoRail don’t satisfy these criteria.

The first problem is that the *.vm files are actually pieces of HTML, but they are not HTML documents because there’s no <html> and/or <body> tag. HTML designer application don’t like this.

The other problem is that the NVelocity templates are not valid HTML. For example, the following fragment is not valid HTML:

<table>
  <tr><th>Header</th></tr>
  <tr><td>Row1</td></tr>
#if (showThisBlock)
  <tr><td>ConditionalRow2</td></tr>
#end
</table>
 

The only markup allowed between </tr> and <tr> is comments. The solution is easy: embed control script inside HTML comments. That’s how I did it, so this is how the template looks using ProMesh.NET:

<table>
  <tr><th>Header</th></tr>
  <tr><td>Row1</td></tr>
<!--$(if showThisBlock)-->
  <tr><td>ConditionalRow2</td></tr>
<!--$(endif)-->
</table>

 

I hope this post clarifies my earlier post. Don’t get me wrong: I really like MonoRail. In fact when I first read about it, I was surprised by the similarity to what I had written for my own use. I suppose this means I agree on a lot of things with the MonoRail developers :-)

kick it on DotNetKicks.com
Tuesday, July 24, 2007 10:16:33 PM (W. Europe Daylight Time, UTC+02:00)  #    Comments [4] -
 |  | 
# Saturday, July 21, 2007

In the early days of web development, it was common procedure to write application logic inside your HTML pages using ASP, JSP, PHP, Perl or another early web application development framework.

Of course, back then we didn’t know any better, but don’t you just cringe when you see something like this:

<table border="1">
<%
For I = iRecFirst To iRecLast
	Response.Write "<tr>" & vbCrLf
	
	For J = iFieldFirst To iFieldLast
		Response.Write vbTab & "<td>" & arrDBData(J, I) & "</td>" & vbCrLf
	Next	
	Response.Write "</tr>" & vbCrLf
Next ' I
%>
</table>

I know, this looks pretty simple, and the learning curve to write applications in this way is not that steep, but maintaining something like this is a nightmare.

Microsoft saw the need for something better and came up with ASP.NET. Indeed, at first glance it was a big improvement, urging developers to cleanly separate code from markup by providing the "code behind" way of programming. But if you look closer it was still a mess. Let me tell you why:

  • There’s a (very limiting) 1–1 relationship between the view and the code. Every .ASPX has one code behind file, and one code behind file has one .ASPX file. Implementing the MVC pattern is impossible without resorting to a bag full of tricks.
  • Events are wired in the markup, so the markup is controlling the application, not the other way around
  • The .aspx files are "kind-of" HTML files, but when you try to edit them in a standard HTML editor (Dreamweaver for example), you're in for a (nasty) surprise. ASP.NET tags are not recognized correctly, let alone rendered. So you are pushed into using the Microsoft ASP.NET markup editor, which is the crappiest piece of junk ever built.
  • Properties influencing the behavior of user interface elements are defined in the markup. And the other way around: properties defining the look of your application sometimes have to be defined in code
  • Standards based HTML/CSS? What standards based HTML/CSS?

To this day, Microsoft is still holding on to this broken development model for web applications. The Java guys had more inspiration in that area: Struts, Tapestry, Wicket, SiteMesh, Spring, ... Good ideas that quickly turned into Enterprise Frameworks that were too intimidating for the average developer (isn't this a pattern for all Java-based technologies?)

Light at the end of the tunnel?

Maybe... Ruby On Rails, MonoRail, DotNetNuke, Spring.NET,... Cool stuff, VERY cool stuff.

Which brings me to the point of this article. While I didn't have time to look at all these frameworks, I am still a little annoyed by the lack of separation between the actual presentation (markup) and the code controlling the presentation. The other day I was checking out MonoRail and was browsing through the samples, and I saw a lot of ASP-like stuff in the HTML markup. Loops, method calls, the whole shebang. I felt thrown back to the nineties.

Maybe I am too religious about this, but I like to see a 100% separation between code and markup (presentation). My requirements for a web application framework are pretty clear:

  • Pure HTML files should be used. By pure HTML, I mean that you should be able to give the HTML files to a web designer and let him/her make changes without having to worry too much about these funky codes that these weird developers have put in.
  • No hints of any application logic or code in the presentation markup
  • The learning curve should be gentle, without losing flexibility and performance
  • MVC has to be easy to implement (or included in the framework), without forcing developers to use it. 90% of web developers don’t use MVC, so don’t force them to use it if they feel more comfortable developing in other ways
  • Easy Ajax integration (I am not talking about black box toys like Microsoft Ajax)
  • Performance! Performance! Performance!

In a few days, ProMesh.NET, the web application framework I have been building, using and improving for the last 4 years will be published as Open Source on CodePlex. It’s a lightweight , fast web application framework that satisfies the requirements listed above and I look forward to sharing it with the .NET community.

kick it on DotNetKicks.com
Saturday, July 21, 2007 11:26:31 PM (W. Europe Daylight Time, UTC+02:00)  #    Comments [6] -
 |  |  |