Ayende @ Rahien

Refunds available at head office

Month Summary

A month ago, I was caught red handed, with no post in a span of eight hours or so. I decided to see just how much I can post if I really put my mind into it.

This is my 150th post for this month, and obviously the last one.

Here is a chart of my posts in the last month by day, the most prolific day was the second day of the month, which actually warranted 17 posts.

image

It has been an interesting experience, but it turns out that it takes a lot of time, so I think that I will drop back to a saner(?) 70 - 90 posts per months instead. If nothing else, blogging has actually reduced the time that I can dedicate to writing OSS stuff and (more importantly) actually having a life outside the monitor.

Observations on Learning

Here is an observation on learning. When I was at high school, I was thought Pascal, and I couldn't for the life of me understand dynamic memory allocation. I had little problem with everything else, but dynamic memory allocation (better known as pointers) was a mystery wrapped in an enigma stashed inside a headache.

About a year later, I was learning C++, and was one of the first in the class that grasped pointers and their usages. I remember trying to explain ***pppHead (sparse matrix) to another student, and he drew blank after the first level of indirection. I don't think that the quality of the teachers was that different,  and the material is basically the same, but I grokked the second and couldn't figure out the first.

I have run into this many times since, usually a piece of technology just doesn't make sense to me, and at one point, it clicks together, and it is "Oh, that is simple!"

For a while now, I have been feeling my lack of knowledge in the area of parsers, and I kept trying to learn ANTLR on my own. I got to the point where I could read EBNF fairly well, and actually make sense of it, but taking the next step to actually building a language has been beyond me. Yesterday I picked up The Definitive ANTLR Reference, and I have been going through it with a fairly rapid pace. I don't think that at my level, the book is offering something that isn't already available online, but I have been able to understand how things mesh together much better now.

I feel that now, I am not competent with parser building, it is certainly something that I can be with a reasonable amount of real world practice. In other words, I think that I am going to be able parsers and parser building to my toolbox.

Brail: DSL Support Information

Harris has more details about the internal implementation of Brail's DSL Support

Following the same line of thoughts, Alex has a similar implementation using C# 3.0. Personally, I think that Alex's implementation is cool, but it looks really similar to LISP, and that sort of scares me. I am currently reading about ANTLR, so it actually makes sense, in a weird way, except that I keep looking for the lower level implementation.

And as long as I am busy in link aggregation, Tom Opgenorth has posted a guide to Binsor, including a Getting Started example!

What would you say if I wanted to write my own... OR/M / IoC / Web Framework / Etc ?

Occasionally I get asked this question, and the answer I give is usually along the lines of: Why?

This is not a mocking question ( :-)  ), it is the criteria that I use to answer this question.

  • Are you doing it because you want to and it is fun?
  • Are you doing that to solve your own problems, and you decided that you will get better return of investment by building your own custom thing?
  • Are you doing it to solve a specific problem, without an off-the-shelf solution?

If it is any of the above, I would tell you to:

  • Have fun,
  • But look at the existing stuff first, see what the reasons for this is.

If it is something along the lines of:

  • Building it seems simpler than investing the time in learning how to use existing stuff
  • You have a policy of From-Vendor-XYZ-Or-Built-In-House
  • You need new challenges and haven't written a framework in a week or two

Then you really want to consider this twice or thrice.

I once had a client reject NHibernate and ask me to build their own custom OR/M implementation, because it didn't come from Microsoft, and they had a policy that all their stuff is either Microsoft or their own. NIH in its purest form. After showing some metrics about cost, supportability and bus factors, I have been able to convince them that this is not a really good idea, and they have been using NHibernate with great success for the last two years.

Jimmy Nilsson has some more thoughts about this subject.

Visual Basic User Group Talks, Next Wendesday

Oh, another thing that is worth mentioning is that I am going to talk about Test Driven Development and Interaction Based Testing at the VB.Net User Group meeting next week (Wendesday, 04 July, 2007).

More details can be found here: http://www.renaissance.co.il/ivbug/

The first one is:

Getting to know Test Driven Development & Design

You have just finished implementing the new WizBang 2.0 feature, and you are feeling pretty good about yourself. But, do you know if this feature broke? Testing using F5 isn't scaling beyond the simplest application, and the cost of maintaining software is often several times over the cost of building it.

The second one (I gave that one in DevTeach):

Interaction based testing With Rhino Mocks

Beyond the simplest scenarios, all objects had collaborators that they work with. This flies in the face of testing objects in isolation. This is the problem that mock objects were created to solve. In this talk you will learn what mock objects are, how to utilize them and best practices on when / how to utilize them. Rhino Mocks is a mock objects framework for .Net whose core goals are to let the developer rely on the compiler work well with refactoring tools.

The last time I did any serious VBing was quite some time ago, so I encourage you to come and watch how I humilate myself in public ;-)

DevTech session: Storming Castle Windsor & NHibernate

I am announcing this a bit late, but I am going to give a talk about the Castle Winsdor & NHibernate on Thursday next week (03 July 2007).

The anouncement has an amusing typo, I am afraid, which bring to mind some horrifying options

DevTech.png

The talk will be at DevTech, a conference that my company is arranging, so a lot of the people that I work with are going to give interesting talks.

You can get more details here.

Oh, and apparently I am an architect :-)

Hibernating Rhinos - Episode #4: Hibernating Forums - Part I - Testable & Painless Persistence

Okay, here is the first episode in my OR/M challenge series. It mostly deals with the MonoRail skeleton project and with setting up the domain model in a TDD fashion. I am not sure how interesting it is, because about 60% of it is building the Active Record entities, and explaining how it works, but it lays a foundation that I will use for the next few episodes.

Lots of Um..., I am afraid, but at least I am speaking in a normal speed :-)

  • Total length: 55:44 Minutes
  • Download size: 77Mb
  • Code starts from ~4 minutes into the episode.
  • Getting the Latest code - will be updated for new episodes
  • Getting the Code from the episode

The download page is here: http://ayende.com/hibernating-rhinos.aspx

I have some ideas about where to take the next episode, but this is something that is mostly dependant on your feedback :-)

Dependency Injection in Web Forms MVC

David Hayden has a post about the issue that you face when you are trying to use dependency injection in Web Forms MVC. I talked about similar issues here.

He points out that this type of code is bad:

    protected Page_PreInit(object sender, EventArgs e)
    {
            // Constructor Injection of Data Access Service and View
            ICustomerDAO dao = Container.Resolve<ICustomerDAO>():
            _presenter = new AddCustomerPresenter(dao, this);
            
            // Property Injection of Logging
            ILoggingService logger = Container.Resolve<ILoggingService>():
            _presenter.Logger = logger;
    }

This type of code a Worst Practice in my opinion. It means that the view is responsible for setting up the presenter, that is a big No! right there.

He gives the example of WCSF & Object Builder way of doing it, but I don't think that this is a good approach:

public partial class AddCustomer : Page, IAddCustomer
{
    private AddCustomerPresenter _presenter;

    [CreateNew]
    public AddCustomerPresenter Presenter
    {
        set
        {
            this._presenter = value;
            this._presenter.View = this;
        }
    }
    
    // ...
}

The problems that I have with this approach is that the view suddenly makes assumptions about the life cycle of the controller, which is not something that I want it to do. I may want a controller per conversation, for instance, and then where would I be? Another issue is that the view is responsible for injecting itself to presenter, which is not something that I would like to see there as well.

Here is how I do it with Rhino.Igloo:

public partial class AddCustomer : BasePage, IAddCustomer
{
    private AddCustomerPresenter _presenter;

    public AddCustomerPresenter Presenter
    {
        set
        {
            this._presenter = value;
        }
    }
    
    // ...
}

The BijectionFacility will notice that we have a settable property of type that inherit from BaseController, and will get it from the container and inject that in. I don't believe in explicit Controller->View communication, but assuming that I needed that, it would be very easy to inject that into the presenter. Very easy as in adding three lines of code to ComponentRepository's InjectControllers method:

PropertyInfo view = controller.GetType().GetProperty("View");
if(view!=null)
	view.SetValue(controller, instance);

Hibernating Rhinos Status

Well, I have finished the first episode of the OR/M Challenge, and it is now in the process of being uploaded to the server. I am going to sleep, based on some good advice that I received, so I will do the actual publishing in the morning.

What is really interesting is the numbers you can see here: http://ayende.com/hibernating-rhinos.aspx

Nearly ten thousands downloads for each of the previous episodes? Wow!

Challenge: Windsor Null Object Dependency Facility

In Scott Bellware's post about dependency injection, he has a comment about optional dependencies:

Setter dependencies are optional.  Their types should have a Null Object pattern implementation, and if not it's often a good idea to decorate them with one.  For example, if an optional dependency hasn't been set, it might not be desirable to have a null reference exception when a method is invoked on it

The challenge is to provide a facility for Windsor that will detect an optional dependency and fill it with a Null Object (i.e, an implementation that doesn't do anything). It is safe to assume that all such dependencies are using interfaces.

Can you do it?

Documentation Contributions

This is a question for the audience, assume that you have 500$, what would be the best way to spend them in a way that would improve the documentation for Castle, NHibernate or Rhino Tools?

(Just to point out, the 500$ is not related in any way to Jeff's donations, except the overall idea)

Supporting OSS in the .Net Space

Jeff Atwood wants to donate 10,000$ to open source projects in .Net-land. Check the comments, they are very interesting. This raises the question of whatever monetary support is the best way to support OSS projects. I really appreciate Jeff's efforts, and I think that they would do wonders for the moral of the developers that gets the money.

However, I want to point out some other ways to contribute, just as important, if not more so, than money:

  • Contributing to the documentation:
    • Tutorials
    • Gotchas
    • How-to
    • Samples
    • F.A.Q
  • Participating in the community (forums, mailing lists, etc) - answer questions that you can, help other people when they run into problems
  • Evangelize the project:
    • Post about it
    • Talk about it
    • Help people using it 
  • Bug hunting - there is a respectful position for Bug Contributors - they help make the project better

Contributing code is important, but it is far from the only way you can contribute, and most OSS projects can do with more help in the above mentioned ways than code contributions. Documentation, in particular, is something that OSS projects usually lack at.

As a side note, I think that Frans Bouma has hit a key point in a comment there:

You come with an example where MS provides the source. Great example. The thing is though: that's NOT what should be changed. MS should work _together_ with open source projects started by others, outside MS, and make sure these project don't hit a wall because MS thinks they have to do their own copied version of the same project.

He has some other points in the discussion that I disagree with (choosing to go OSS vs. commercial offering) , but the point above is a very important one.

SSIS Scheduling Conflicts?

I have two SSIS packages that cannot run concurrently, however, one must run once every 5 minutes, and the second every hour, so they are assured to conflict very soon. I can handle this situation manually, but I wanted to know if there was a builtin way to handle that.

DSL Support for Brail

First things first, Harris Boyce III has done all the work, my sum contribution to this feature has included some wild cheering from the side lines.

That said, this is one cool feature. Let us explore it.

There are a lot of people who consider anything resembling <html> tags to be a mess, associate them with ASP Classic mistakes, and reject them out of hand. I think that this is a mistake, but I gave up changing the whole world overnight, now I have busy formulating three steps plans that takes a week...

At any rate, consider this output:

<html>
	<body>
		<table>
			<tr>
				<th>Names</th>
			</tr>
			<tr>
				<td>Ayende</td>
			</tr>
			<tr>
				<td>Rahien</td>
			</tr>
		</table>
	</body>
</html>

How would we generate this output using Brail? The classic approach is:

<html>
	<body>
		<?brail
                       component Grid, {"source": names}:
                         	section header:
                                    output "<tr><th>Names</th><tr>"
                               	end
                             	section item:
                        	    output "<tr><td>${item}</td><tr>"
                           	end
                        end
?> </body> </html>

This works, but it not really Jump-Up-And-Down-All-Excited code. And, of course, some people faint dead away from having to deal with raw HTML, "Give me my components or give me death!"

Now, here is the DSL way of doing it:

<?brail
dsl Html:
	body:
		component GridComponent, {"source" : names}:
			section header:
				tr:
					th:
						text "Names"
					end
				end
			end 
			
			section item:
				td:
					text item
				end
			end
		end
	end
end
?>

And this baby produces the same output as the previous one.

Now, you are probably aware that I am not really fond of raising the abstraction level needlessly, so why is this a good thing? Well, because it means that you can now do stuff like this:

dsl.Register(atom)
dsl:
   feed:
       title:
           div:
               text "some content"
           end
       end
   end
end

And it will be able to produce semantically correct ATOM feed. (To be exact, it would be if we had an AtomExtension implementation to the new IDslLanguageExtension interface, which we currently don't have).

There are some quirks in the implementation, but it is a very cool direction to go to.

OR/M Challenge Screen Casts Delayed

About two weeks ago I asked how I should handle the OR/M Challenge from Rob, I got a lot of positive responses about it, and I fully intend to produce at least one or two screen casts about the subjects, but after trying to find a window where I have both the time and inclination, I must concede that it will may take a while. Just to give an idea, an hour screen cast takes anything between three hours (best case scenario) to three days to make. Finding such a big stretch of time where I actually have inclination to code is challenging. Contrary to popular opinion, I actually do get tired of code at one point.

So sorry, but it is going to be a bit late. Well, at least it is still under budget :-)

Tags:

Published at

Stories form the class room: Picking the target for BackgroundWorker

I am teaching BackgroundWorker at the moment, and I gave two demos of using it, one with printing and one with the classic long request to the database.

For the student work, I needed to find another sample that I could give them. I tend to like reasonable examples, rather than Hello world ones. I build them the following code to excersize:

WebRequest req = WebRequest.Create("http://www.msdn.com/");

using (WebResponse response = req.GetResponse())

{

    string homePageHTML =

        new StreamReader(response.GetResponseStream()).ReadToEnd();

    textBox1.Text = homePageHTML ;

}

 

At first I tried Google, but that was too fast to be a good demo, msdn.com takes ~15 seconds to get everything from the server, good, solid reason for why we need scalable application.

Sigh, this is so wrong!

Answering Mats' Challenge

Mats Helander has a challenge for OR/M developers, and Mats should know, since he is behind NPersist.

Go for the post for details, but basically it is loading all Customer->Orders->OrderLines graph in 3 statements or less.

Because I am a sucker for challenges, I implemented it with ActiveRecord. In Mats' terms, the code is so simple it hurts, and yes, I cheated :-)

internal static IList<Customer> LoadCustomersOrdersAndOrderLines()

{

    Customer[] customers = Customer.FindAll();

    Order[] orders = Order.FindAll();

    OrderLine[] orderLines = OrderLine.FindAll();

    foreach (Customer customer in customers)

    {

        customer.Orders = new List<Order>();//avoid lazy load when adding

    }

 

    foreach (Order order in orders)

    {

        order.OrderLines = new List<OrderLine>();//avoid lazy load when adding

        order.Customer.Orders.Add(order);

    }

 

    foreach (OrderLine line in orderLines)

    {

        line.Order.OrderLines.Add(line);

    }

    return customers;

}

 

Case Sensitive Optimization

I am doing some optimization work lately, and I managed to take a page down to three DB requests per page load, but I couldn't get it to less than that, and it really annoyed me. The problem was that accessing a certain properly on an entity would cause a lazy load, even though I have explicitly told it to eagerly load that.

That was... annoying.

Eventually I got rid of all the "it can't be!" mentality and looked at what was going on, the problem was that I was looking for NHibernate bug. The problem was actually more subtle than that. Let us say that I have this scenario:

Post post = session
  .CreateCriteria(typeof(Post))
  .Add(Expression.Eq("Id", 15))
  .SetFetchMode("Status", FetchMode.Join)
  .UniqueResult<Post>();

Console.WriteLine( post.Status.Name );// should not cause lazy loading.

I looked at the result, and looked at the result, and couldn't quite figure it out. Eventually it dawned upon me that the Posts' table had the following data:

Id Content Status
15 Interesting... PUBLISHED

While the PostStatuses table had this data:

Id Name
Published Published
DRAFT Draft

Do you see the problem? While NHibernate has correctly loaded the associated PostStatus entity, it has loaded it with the 'Published key, while the PostStatus entity on the Post was loaded with the 'PUBLISHED' key. Hence, it didn't exists in the current session, and when accessed, would cause a lazy load. Of course, at the DB level it didn't matter because it is set up to be case insensitive, but it sure made a different for comparing key equality on the CLR.

In this case, it was a simple case of entering the wrong value to the PostStatuses table that cause all this issue. As an aside, NHibernate has ways to deal with such cases in legacy databases, but that is something that I would rather fix in the data layer.

It is a matter of style...

Today I freaked out two co-workers by looking at their code and saying (respectively) "How long have you worked with C?" and "You didn't get a lot of time with C++, right?"

The pieces of code in question were: (for the C comment)

Customer customer = null
for(int i=0;i<array.Length;i++)
{
	customer = new Customer();
	//do stuff
}

And: (for the not a lot of time in C++ comment)

int totalCarCount;
if( IsValid )
{
	totalCarCount = GetValidTotalCars();
}
else
{
	totalCarCount = GetInvalidTotalCars();
}

int totalWheelCount;
DoComplexWheelCalculation( out totalWheelCount);

And yes, the examples here are fake, and both are good developers, and I just said what came to mind first :-)

Query Batch: Concrete Syntax

Thanks for all the feedback about this feature, I have implemented it and you can find the code here.  Instead of explaining, I am going to let the test speak for themselves. Consider this a first iteration, and I am now accepting patches for this. :-)

 

[Test]
public void CanUseCriteriaBatch()
{
    ICollection<SMS> loadedMSGs = null;
    new CriteriaBatch(session)
        .Add(DetachedCriteria.For<SMS>(), Order.Asc("id"))
        .OnRead<SMS>(delegate(ICollection<SMS> msgs) { loadedMSGs = msgs; })
        .Execute();
    Assert.IsNotNull(loadedMSGs);
}

[Test]
public void CanUseCriteriaBatchForUniqueResult()
{
    ICollection<SMS> loadedMSGs = null;
    SMS loadedMsg = null;
    new CriteriaBatch(session)
        .Add(DetachedCriteria.For<SMS>(), Order.Asc("id"))
            .OnRead<SMS>(delegate(ICollection<SMS> msgs) { loadedMSGs = msgs; })
        .Add(DetachedCriteria.For<SMS>())
            .Paging(0, 1)
            .OnRead<SMS>(delegate(SMS msg) { loadedMsg = msg; })
        .Execute();
    Assert.IsNotNull(loadedMSGs);
    Assert.IsNotNull(loadedMsg);
}

[Test]
public void CanUseCriteriaBatchWithAutomaticCountQuery()
{
    ICollection<SMS> loadedMSGs = null;
    int msg_count = 0;
    SMS loadedMsg = null;
    new CriteriaBatch(session)
     .Add(DetachedCriteria.For<SMS>(), Order.Asc("id"))
         .OnRead<SMS>(delegate(ICollection<SMS> msgs, int count) { loadedMSGs = msgs;
                                                                     msg_count = count;})
     .Add(DetachedCriteria.For<SMS>())
         .Paging(0, 1)
          .OnRead<SMS>(delegate(SMS msg) { loadedMsg = msg; })
    .Execute();
    Assert.IsNotNull(loadedMSGs);
    Assert.AreEqual(1, msg_count);
    Assert.IsNotNull(loadedMsg);

}

Dreaming in Code: Multi Linq

I was asked how we will approach the same Multi Query approach with Linq integration, here are some thoughts about it.

var posts = from post in data.Posts
            where post.User.Name == "Ayende"
		orderby post.PublishedDate desc;
var postsCount = posts.Count();
posts.Skip(10).Take(15);

new LinqQueryBatch()
 .Add(posts)
 .Add(postsCount)
 .Execute();//perform the query

foreach(Post p in posts)//no query
{
  Console.WriteLine(p.ToString());
}
//no query
Console.WriteLine("Overall posts by Ayende: {0}", postsCount.Single() );

The LinqQueryBatch in this case doesn't need to pass delegates to process the results, it can modify the Linq Query directly, so trying to find the result will find the one that was already loaded when we executed the multi query.

Again, this is something that I am merely thinking about, no concrete code created.

When Query Objects are a first level concern

I mentioned that I recently had a shift in my think about having services that return query objects. Now I have more interesting problems. How do I test such a thing? To be more accurate, how do you test such a thing in an accurate & maintainable way? To say that queries can be complicated is an understatement. You can try to deconstruct the query, but is this a really good idea? Something as simple a inner vs. left join can have interesting implications.

I guess that I am asking whatever this approach still allows for a Unit Test.

Right now I am testing that against an in memory database, so it mostly involved setting up the data, calling the service that returns the query, execute that and verify the results.

Any thoughts?