Development Blog

 Thursday, May 08, 2008

As some of you who follow me on twitter know, I've been working on Yet Another Context/Specification Framework as an experiment. Yeah, I know we already have NSpec and NBehave, and they're great and all, but MSpec takes things on from a slightly different angle, and it's just an experiment (for now). Here's a sample Description:

[Description]
public class Transferring_between_from_account_and_to_account
{
  static Account fromAccount;
  static Account toAccount;

  Context before_each =()=>
  {
    fromAccount = new Account {Balance = 1m};
    toAccount = new Account {Balance = 1m};
  };
  
  When the_transfer_is_made =()=>
  {
    fromAccount.Transfer(1m, toAccount);
  };
   
  It should_debit_the_from_account_by_the_amount_transferred =()=>
  {
    fromAccount.Balance.ShouldEqual(0m);
  };

  It should_credit_the_to_account_by_the_amount_transferred =()=>
  {
    toAccount.Balance.ShouldEqual(2m);
  };
}

And a TestDriven.NET run:

------ Test started: Assembly: Machine.Specifications.Example.dll ------

Transferring between from account and to account
  When the transfer is made
    * It should debit the from account by the amount transferred
    * It should credit the to account by the amount transferred


2 passed, 0 failed, 0 skipped, took 0.79 seconds.

Err, What?

Different eh? The idea was heavily inspired by Scott Bellware's SpecUnit.Net framework he showed at the ALT.NET conference. It also took heavy cues from RSpec and my insanity. I realize that the the code doesn't look much like C# code and I'm OK with that. Many have and will ask why I don't just use Boo or RSpec w/ IronRuby eventually or even one of the existing Context/Spec/BDD frameworks. Those are good questions, but my main motivations are tooling and syntax. I enjoy the tooling I get in C# and I personally like the syntax in this library considering the limitations imposed by C#.

How's it work?

The simplest way to describe it is to compare it to a normal *Unit style testing framework:

  • Description = TestContext
  • Context before_each = SetUp
  • Context before_all = SetUpFixture
  • Context after_each = TearDown
  • Context after_all = TearDownFixture
  • When = Also SetUp, but happens after Context before_each
  • It = Test

Rather than methods and attributes, MSpec uses named delegates and anonymous functions. The only reason for this is readability. You'll also notice that the fields used in the context are static. This is necessary so that the anonymous functions in the field initializers can access them. Probably the first thing you noticed is the =()=> construct. I won't mention the names that this was given on twitter, but I think it's an acceptable thing to have to deal with in exchange for the cleanliness of the rest of the syntax.

Ok, you're crazy, but how do I try it?

First, this is a very rough cut. Everything is subject to change as we experiment with the language. That said, here's how you play with it:

  1. Grab the drop here.
  2. Extract it somewhere. Put it somewhere semi-permanent because the TestDriven.NET runner will need a static location for the MSpec TDNet Runner.
  3. If you want TestDriven.NET support, run InstallTDNetRunner.bat
  4. Check out the example in Machine.Specifications.Example. Note that you can run with TD.NET.
  5. Create a project of your own. Just add Machine.Specifications.dll and get started.
  6. Send me feedback! Leave comments, email me, tweet me, whatever.

Also, this is part of Machine, so feel free to take a look at the code and/or submit patches. There's also a Gallio adapter in there, but I didn't include it in the release as it's not quite polished enough yet. If you're interested in it, talk to me. Special thanks to Scott Bellware, Jeff Brown and Jamie Cansdale for their help and support.

by Aaron on Wednesday, May 07, 2008 11:11:27 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [8]  |  Trackback
 Monday, August 27, 2007

James Kovacs replied to one of my many NHibernate Optimization Ramblings:

In the first example, how do you know that most customers are unimportant until you fetch them from the database? You have an additional problem that generally NHibernate sessions are short - especially in web apps or web services. So when do you reset your fetching strategy. What if one portion of your code uses different customer properties than another? The adaptive fetcher needs to do a lot of analysis of your post-fetch code paths or monitor the behaviour of the application as it executes. As it stands, NHibernate has a lot of options besides adaptive queries, which I believe are better including projections (since you as a programmer know the data you need) and lazy-loading of properties - both collections and objects. There are probably others. We're talking about saving milliseconds on DB queries when a round-trip to the DB is at least an order of magnitude greater. I personally feel that adaptive queries would require a lot of work for little gain. I call YAGNI.

This is probably my fault, but his first question tells me he doesn't quite understand what I'm trying to propose. It doesn't matter if customers are important or unimportant. Once the both code paths are hit and the strategy fully adapts, it is adapted and it will fetch a superset of fields that are required for that query in the context it is called. There's no reason to ever reset that strategy unless the code changes. 

Context is another important aspect of the adaptive queries, and I'm not sure how I'd implement it. At the moment I'm thinking that something along the line of scopes (nested or single level) so for each scope/query combination there would be a strategy. That's the answer to his second issue. The only analysis it needs to do is it needs to pay attention to what properties are hit on the entities it fetched by proxying that entity. That's it. No instrumentation, parsing, or any other crazy stuff.

 

using (Query.Scope("Print Customer Stuff"))
{
  customers = LoadCustomers();
  ...
}

As for the YAGNI assertion, I understand why you'd call YAGNI on the 2-12ms standard savings I showed in my tests, but You Already Do Need It at times (we use projections for just this) it's just that this would be automatic and require less maintenance and you wouldn't have to choose to do it. It would be free savings and require less manual optimization. If someone further down your chain decides they need to log customer.Name, you don't have to climb back up, find the original query and add it there. With projections at least you'd know you'd need to add it, but you'd have to change the query and change your DTO (anonymous types will help with this... I guess).

My point is, You don't need an inversion of control container, it's just easier. You don't need auto mocking containers for tests, it's just easier and you don't have to change your code when you change your constructor. You don't even need Mocks, you could write those by hand too. Well, with adaptive queries you don't have to change your code when you decide to access another field... or even another collection....

You also have to look further than field adapting. There's the potential to adapt collection initialization as well. No more select N+1's for those devs that don't pay attention, they'd just go away like magic. And yes, I realize hand optimized queries will generally prevail, but adaptively optimized queries will be free.

Today, Jacob had another great idea for a use of adaptive queries. We often do this in our MonoRail actions:

public void ShowCourseEnrollments([EntityParameter] User user)
{
  foreach (CourseEnrollment ce in user.CourseEnrollments)
  {
    // Do something with ce.Course.Number
  }
}

This probably requires a bit of explanation. Basically, when someone goes to the url /Controller/ShowCourseEnrollments.rails?user=1, MR's databinding (and our EntityParameter binder) will do an NHibernate session.Load<User>(1). At this time, the db hasn't been hit. As soon as we start enumerating user.CourseEnrollments, we're select N+1ing. Furthermore, we could potentially be doing another fetch for ce.Course. The solution to this is to either change your mapping to always fetch these things (bad idea anyone?) or to do something like this:

user = UserDao.FetchUserWithEnrollments(user.Id);

Well, what if adaptive queries kicked in at the databind, and instead of adding that method to your dao, you just got what you needed? Sure, YAGNI, but You Are Gonna Want It... if I or someone ever implements it.

by Aaron on Monday, August 27, 2007 9:11:52 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Sunday, August 26, 2007

Ayende posted a great comment with some questions about adaptive fetching. Here are his questions and my responses:

Let us assume this:
customers = LoadCustomers();
for customer in customers:
if customer.IsImportant:
print customer.Birthday
else:
print customer.CurrentCharge
What would the adaptive fetching do in this case?
Assume that you have started with mostly unimportant customers and then moved to important customers?
The amount of queries that would be generated is prohibitive.

In this scenario, adaptive fetching would generate a query that pulled IsImportant and CurrentCharge for unimportant customers. As soon as a single Important customer ran through this code, the query would change to fetch IsImportant, CurrentCharge and Birthday. It would also immediately lazy load *all* missing properties from the original query for all customers originally queried, and continue to track accessed properties. That's only one additional query for each differing codepath, and that's only the first time its hit. From that point on, until the query was reset (version upgrade, app restart if it's not persisted, manually, etc), then you would have all you needed for all codepaths.

Another problem that you have here is that you do a query like:
"select u.Name, u.Email from Customer" and the query actually returns you Name,Email, Address, Photo.
That violates the law of least surprise fairly drastically.

I don't see adaptive queries having that syntax. I'm thinking more along the lines of "select ??? from customer"  or "select what  i need from customer", etc. Specifying what you're looking for puts you right back into projections. If you want to be specific, use projections.

Finally, I think that a much easier solution than trying to eek a few more milliseconds from a DB query is not to go to the DB at all. Utilize NH's caching abilities, and you'll get a significant performance benefit for little cost.

I agree that most of the time you'd get more benefit from caching than squeezing some time out of the db. I just think it gets us one step closer to making mapping between objects and the db more friendly to both sides of the map, and gives developers a tool that works automatically "for free". I'm sure it'd also make DBAs happier that their devs aren't just doing select * all the time.

Now, if you still want adaptive fetching, the best way to get it is to help build the HQL Parser, which would generate a human workable AST.

Agreed. I guess if we work on rewriting chunks of NHibernate the code would become manageable eh? So yeah, I'll stop blathering and try and start contributing.

by Aaron on Sunday, August 26, 2007 10:44:50 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Saturday, August 25, 2007

Oren replied to my original post about features I feel that NHibernate is missing. I think he may have misinterpreted some of my wants so I'll run through and reply in order.

Lazy Field Initialization

Obviously grabbing each field as it was accessed would be ludicrous. Lazy field initialization is simply something that needs to be there in order for partial object queries to work properly. It's the same idea as deciding whether or not to fetch a child collection. You query for it if you need it, you don't if you don't, and if you end up using the child collection when you didn't fetch it, it will get lazy loaded. I'm of the opinion that lazy loads are a smell, and if you hit them in anything but a border case, you're doing something wrong and you should be fetching what you need. 

I'm fine with specifying defaults on fields (don't load Photo unless I ask for it explicitly), but Lazy Field Initialization really would shine in partial queries.

Partial object queries

UserSummaryDetails is not User. Let's say I have a ReminderService that has a SendMailTo method that takes a User and a message. If all that method needs is that User's name and email address, why should I allow NHibernate to query for the entire user? It's just wasteful. Furthermore, it'd be rather tedious to have multiple Value Objects like UserSummaryDetails in your codebase just to support the different scenarios you want.

If you add Lazy Field Initialization and real partial object queries to the mix, you'd be able to query for a group of Users that just have email and name populated, and if you happen to need address, it'd requery for all of the user's addresses. You can even take it further and requery for all of the fields missing from the original user query. NHibernate should also probably slap you on the wrist (by logging it). I think I'm going to find a way to start logging all lazy loads so that we can investigate them.

Using objects like UserSummaryDetails eliminates a good chunk of the usefulness of the domain. That is,  you can no longer use the methods on the User object itself or any domain services that would consume that object.

So really what I want is the syntax I mentioned in my original post, which would just reuse NHibernate's field access strategy to set the appropriate fields. Any fields that were not set at that time would be flagged for lazy loading. On flush, only those fields that were set would be compared. Combine this with Adaptive Fetching Strategies and you've got a very powerful, self optimizing and flexible query mechanism that leaves you free to use your Domain as you wish.

Read Only Queries

Maybe it would make sense to give two sessions to each Dao, one of them that handled read only queries and one that handled read write queries. That's a good idea, but I still think it's something that should be built in (Hibernate does it). 

Join Qualifiers

I don't remember what the query was, but there was a reporting query I was trying to do involving multiple left joins that I just couldn't get to work with HQL. I was able to do it in SQL no problem by qualifying one of the joins, but every attempt in HQL hit a wall. Good point about having to support multiple db's. It's still something I'd like to see eventually.

by Aaron on Saturday, August 25, 2007 4:48:04 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [8]  |  Trackback

sqldavidson First I want to admit something somewhat embarrassing: I don't know enough about databases. Until coming here, I've always had a DBA that could handle that. I've started to realize now how important it is for all developers to have a much better understanding about databases than I do. So I picked up this book. I was really looking to better understand optimization, especially knowing when to create indexes and optimizing queries. Though the book only had a few chapters on the subject, I felt like it greatly increased my understanding on the subject.

A few months ago I wrote about Adaptive Fetching Strategies. At that time I had little knowledge about covering indexes and how they improve performance. Oh well, it's just more reason something like that should be implemented. Before we even get to that however, NHibernate needs to have a few features added to it in order to be useful in scenarios where performance is important.

Remember folks, SELECT * is bad. NHibernate is for effectively always doing a SELECT * when you're asking for an object when it comes to index coverage. Yes, it specifies columns so it doesn't have all the problems associated with SELECT *, but it is still decidedly less performant than querying for only what you want. Compound this with the extra overhead the unneeded columns add during a flush, and you've got a pretty compelling argument to only query for what you need.

OK, so you've decided that you only want to query for what you need and you're using NHibernate. Well, you can do that... kind of. Not much differently than you can if you just used ADO.NET and DataSets though. NHibernate doesn't support lazy field initialization. This means that if you query for only username and email address from your user table, you don't get back a User. You get back a List of object[]'s. Arguably a list of object[]'s is less functional than a DataSet. Combine this with the fact that you're querying using HQL, which has a subset of functionality, predictability, and therefore optimizability of real SQL, and you start to see a big hole in whole ORM thing... if you want to optimize your pages. Yes, HQL does make writing queries more pretty and more in the domain, but it would be nice if it supported things like "on".

Obviously optimizing too early is evil, but we've had several pages now where we've needed to optimize, and just resorted to querying for a table of values. No longer are we querying for objects, that's just not performant enough. Especially in display scenarios where you're not making changes to anything as NHibernate lacks the ability to do read-only queries, so you end up with that (very) expensive flush unless you change your flushing strategy to be manual (awkward) or you detach your objects from the session (also awkward).

So in short, I feel NHibernate (and any ORM for that matter) needs the following features to really be optimization friendly:

  • Lazy field initialization
  • Querying for partial objects: select u(Username, Email) from User u
  • Read-only queries that do not get flushed.
  • Join qualifiers (on in T-SQL)

And yeah, I know it's open source and I could just do it myself, but I have nightmares about that codebase, and I hardly have the time to implement such large features. All I have the time to do is complain and wish :)

by Aaron on Saturday, August 25, 2007 11:28:29 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, June 01, 2007

Ayende responded to my last post asking "But, how do you correlate queries?". Alex James and I shot off a few ideas in comments on both posts. Here are a few of the issues with correlating the queries to a strategy (assuming a Consumer->Service->Query->ORM architecture):

  • A single query can be called by multiple services.
  • Each service can have different needs for that query and so would need a different strategy.
  • Furthermore, consumers of that service may have different needs from the entities returned by that service returned by that query and so on.

So ultimately each consumer of the results of any query would need its own strategy. You could name them manually, with strings or types or something. Those names would need to be passed down starting from one of those levels. If you choose to name the strategies based on the query, you'd end up having an explosion of similar if not identical queries with differing strategies, and an explosion at the service level. If you name them at the service level, you would have to pass that name down to the Query and you'd still end up with several similar service methods. Note that none of this is different than if you optimized each query manually on your own. Different queries are different queries, it's just that in this case a query is really a query+strategy.

The other thing both Ayende and Alex suggested was using Stack traces. That would make things automatic, but it's slow and a bit awkward.

So is there any way to make this better? Maybe. Jacob had a great idea about using attributes to name the strategies. What if we took that further? What if the Dao was proxied to look like this:

public class ProxyDao : RealUserDao
{
  public IList<UserEntity> QueryAllUsers()
  {
    using (session.PushStrategyContext("RealUserDao.QueryAllUsers"))
    {
      return base.QueryAllUsers()
    }
  }
}

Now you can proxy any layer you want with this and the strategy will be automatically named without any stack trace magic. (I think proxy magic is A-OK :) ) This solution keeps getting more and more complicated... I think it would make sense to support the simple string naming from the api level and let the crazy people do the proxy stuff.

There's still other issues however, but I'll post more in a bit.. distracted by tv right now.

by Aaron on Friday, June 01, 2007 6:15:47 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [4]  |  Trackback

OK, let me start out by saying that I'm hardly an expert on the subject of ORMs. I've only really used NHibernate, and I've still got plenty to learn about it. That said, I do know a bit about being lazy...

When working in any real application you quickly realize that actually exercising lazy loading is something that should probably be avoided at all costs. You want to fetch everything you need to handle a request in one go. Scott Bellware recently struggled with this issue as we all have, and the general consensus in the comments is that you should load what you need and not lazy load anything (unless of course that lazy load happens in a branch less often traveled). Udi Dahan provided a link to a rather elegant solution to the problem that I think I'm definitely going to explore.

Even with Udi's solution, you're still required to keep the fetching strategy in sync with the domain. This isn't an incredibly difficult thing to do, but it requires discipline and effort. I've been thinking for a while about this and a few other possible performance tweaks that can make ORMs easier to use and even a bit quicker than they are today.

Let's talk about another performance issue briefly. Say you want to Display an email list containing all of your users. The list should display just their username and email address, nothing more. The easy way to do fetch the data would be to do a "from UserEntity". But is that the most efficient? What if UserEntity has 10 fields? 20? 30? Is it worth explicitly querying for "u.Username u.Email from UserEntity u"? Let's find out. Being lazy, I simply borrowed James Avery's Northwind NHibernate example, ported it to NHibernate 1.2 and added a new mapping and class called TrimmedOrder. The class is exactly the same, but the mapping only contains the Freight and ShipName properties. I also commented out the many-to-ones in both Order and TrimmedOrder. You can get the source here.

The rest was just a few simple tests. One for reading, and one for writing. Here are the results:

  Order TrimmedOrder Performance Gain
Read Test 18.62 ms 11.66 ms 1.6 times faster
Write Test 227.13 ms 161.24 ms 1.41 times faster

Notes: The Read Test was averaged over 50 iterations and the Write test was averaged over 20 iterations. The db was queried for all orders once before anything was tested because I found the first query was always slower, but after that all queries seemed level. In the writing test, I wrote random values to the two properties mapped by TrimmedOrder. The Write Test values were adjusted by subtracting the read test values so that only the write itself was timed (in theory). 

Now, these gains aren't anything to write home about, but they are significant. Some of you may wonder why the Write Test sees any gain given that the database calls would be exactly the same, as NHibernate doesn't update columns that didn't change. Well, without profiling, I'm willing to bet that the reason is simply that NHibernate has discover which fields changed while flushing by testing them against their old values.

So now we have two problems: we have to know exactly what collections the domain needs ahead of time or we lazy load and unless we use projection queries, we're not getting the best performance we can get. Also, NHibernate doesn't currently support deferred (lazy) property loading, so projection queries return object[]'s rather than partially initialized entities, which means that as far as I know, you cannot use projection queries to do updates, so we just can't solve the Write problem without additional mappings or something else hackish.

What do we do? Yes, I'm finally nearing the point of this post. What if we taught the ORM to learn? Bear with me here. Let's go back to the email list example. If we were using Udi's Fetching Strategy approach, we'd do something like this:

IList<UserEntity> users = Repository<IEmailListService>.FindAll();

Which would ultimately get a FetchingStrategy associated with this service. Now what if every object fetched by this FetchingStrategy was proxied and would communicate back to the FetchingStrategy about its usages... and the FetchingStrategy remembered how its objects were used, so the next time it got invoked it would only return what was used last time... and it would keep learning, and refining so that it would simply return all the fields and collections that were ever accessed via that particular FetchingStrategy. If ever it returned too little, it would just lazy load what needed to be loaded and make note that it should provide that field next time (of course this would be configurable so that it would just load everything on a miss so you're not hitting the db several times in these cases). This would mean the first time your FetchingStrategy was invoked it would be "slower" but most every time after that it will have adapted and improved... all for mostly free. And yes, I know that Udi's FetchingStrategy would just return an hql query and live closer to the domain objects, but mine would live closer to NHibernate and it would probably be responsible for actually querying from NHibernate (so it's probably really a Dao, but you get my point.)

There are probably a few other things this could help with too, such as marking queries as readonly automatically so as to avoid an unnecessary and costly flush (unfortunately this is not currently supported any ways).

Caveats? Plenty I'm sure. Here's some I can think of:

  • There's the fact that it's not implemented. Jacob and I started to work on it and quickly decided it would be best to get lazy loaded properties hashed out first. It's probably a decent ways off the NHibernate radar, but maybe we can change that.
  • Then there's the proxy element. The Entities are often proxied normally to lazy load collections and such, so I don't think adding in reporting back to the FetchingStrategy would be a huge burden.
  • Complexity... yeah, this is complicated, but so are ORMs and software :)
  • Increased startup cost (kind of). You could always persist the strategies to help alleviate this a little...
  • Instance variables, access strategies, etc. Much like lazy loaded collections, restrictions would apply to lazy loaded properties and such. You'd probably need to just always load things that are field accessed, and you'd certainly have to avoid accessing the instance variables that back deferred properties.
  • Objects fetched by multiple strategies. This is a big one. There will be tons of questions when it comes time to solve this problem. If I access property A after an object is fetched from two different strategies, do I notify both strategies? Will data be fetched twice if both strategies need it?
  • Caching complications. Most of these would come from the lazy loaded properties, so that's something that'd have to be tackled eventually.

Now I'm just waiting for Gavin King or Sergey Koshcheyev to come tell me why this is a horrible idea, but until then, what do you all think?

by Aaron on Friday, June 01, 2007 9:12:39 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [5]  |  Trackback
 Wednesday, April 11, 2007

We were on the phone today with Scott Bellware and he asked us if we could toss together a simple MonoRail project that showed the Castle.Tools.CodeGenerator stuff in action. A few other people have been asking us to do something similar for the other things we've been discussing on our blog. So, Aaron and I sat down and pair-programmed out some source that does just that. It shows several things:

  • An Action/View map is generated using Castle.Tools.CodeGenerator, and used to do view renderings, and (if desired) action redirections and the like.
  • PropertyBag wrappers are created using the IDictionaryAdapterFactory code that Lee contributed.
  • We show how we test our controllers using the test fixture code Aaron has been posting about.
  • It has a small service layer that roughly shows how we architecture our code around here.
  • It uses Windsor integration, so you can see how that's used if you've been curious.

Please keep in mind this took us about an hour to whip up and we did not actually practice full TDD with it. Enjoy!

Source

by Jacob on Wednesday, April 11, 2007 5:41:13 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [13]  |  Trackback
 Wednesday, March 28, 2007

Shortly after I posted my original EleutianControllerTests, Scott Bellware, Hamilton and myself chatted about the subject, and Hamilton decided to help out by making some of the previously internal methods public. Context still isn't settable directly however (maybe we should have him change that too...), so you still have to do a little bit of magic to get your context in there. There's actually more code to do this now then when I just set it w/ reflection, but it's arguably more "correct" and doesn't involve "reflection" and you can mock more (like logging and such). Anyways, here's the code:

 

using System;
using System.Collections;
using System.Collections.Specialized;
using System.IO;
using System.ComponentModel.Design;
using System.Security.Principal;
using System.Web;

using Castle.MonoRail.Framework;
using Castle.MonoRail.Framework.Internal;
using Castle.Core.Logging;
using Castle.MonoRail.Framework.Services;

using NUnit.Framework;

using Rhino.Mocks;

public class EleutianControllerTests
{
  #region Constants
  private const string ApplicationPhysicalPath = "Q:\\PhysicalPath";
  #endregion

  #region Member Data
  protected string _virtualDirectory = String.Empty;
  protected MockRepository _mocks;
  protected IRailsEngineContext _context;
  protected IRequest _request;
  protected IResponse _response;
  protected IServerUtility _serverUtility;
  protected IDictionary _session;
  protected Flash _flash;
  protected IViewEngineManager _viewEngineManager;
  protected ControllerMetaDescriptor _descriptor;
  protected NameValueCollection _parameters;
  #endregion

  #region Test Setup and Teardown Methods
  [SetUp]
  public virtual void Setup()
  {
    _mocks = new MockRepository();
    _viewEngineManager = _mocks.CreateMock<IViewEngineManager>();
    _descriptor = _mocks.CreateMock<ControllerMetaDescriptor>();
    _context = _mocks.CreateMock<MockRailsEngineContext>(_viewEngineManager, _descriptor);
    _request = _mocks.DynamicMock<IRequest>();
    _response = _mocks.DynamicMock<IResponse>();
    _serverUtility = _mocks.DynamicMock<IServerUtility>();
    _session = _mocks.DynamicMock<IDictionary>();
    _flash = new Flash();
    _parameters = new NameValueCollection();
  }

  protected void InitializeController(Controller controller, string areaName, string controllerName, string actionName)
  {
    controller.InitializeControllerState(areaName, controllerName, actionName);
    controller.InitializeFieldsFromServiceProvider(_context);

    InitializeRailsContext(areaName, controllerName, actionName);
  }

  protected void InitializeRailsContext(string areaName, string controllerName, string actionName)
  {
    SetupResult.For(_context.UrlInfo).Return(
      new UrlInfo("eleutian.com", "www", _virtualDirectory, "http", 80,
                  Path.Combine(Path.Combine(areaName, controllerName), actionName), areaName, controllerName,
                  actionName, "rails"));
    SetupResult.For(_context.Server).Return(_serverUtility);
    SetupResult.For(_context.Flash).Return(_flash);
    SetupResult.For(_context.ApplicationPath).Return("/");
    SetupResult.For(_context.Request).Return(_request);
    SetupResult.For(_context.Response).Return(_response);
    SetupResult.For(_context.ApplicationPhysicalPath).Return(ApplicationPhysicalPath);
    SetupResult.For(_request.Params).Return(_parameters);
    SetupResult.For(_context.Session).Return(_session);
  }
  #endregion
}

public abstract class MockRailsEngineContext : IRailsEngineContext
{
  #region Member Data
  private IViewEngineManager _viewEngineManager;
  private IControllerDescriptorProvider _controllerDescriptorProvider;
  #endregion

  #region Properties
  public abstract void Transfer(string path, bool preserveForm);
  public abstract string RequestType { get; }
  public abstract string Url { get; }
  public abstract string UrlReferrer { get; }
  public abstract HttpContext UnderlyingContext { get; }
  public abstract NameValueCollection Params { get; }
  public abstract IDictionary Session { get; }
  public abstract IRequest Request { get; }
  public abstract IResponse Response { get; }
  public abstract ITrace Trace { get; }
  public abstract ICacheProvider Cache { get; }
  public abstract Flash Flash { get; }
  public abstract IPrincipal CurrentUser { get; set; }
  public abstract Exception LastException { get; set; }
  public abstract string ApplicationPath { get; }
  public abstract string ApplicationPhysicalPath { get; }
  public abstract UrlInfo UrlInfo { get; }
  public abstract IServerUtility Server { get; }
  public abstract IDictionary Items { get; }
  public abstract Controller CurrentController { get; set; }
  #endregion


  #region Constructors
  public MockRailsEngineContext(IViewEngineManager viewEngineManager, ControllerMetaDescriptor descriptor)
  {
    _viewEngineManager = viewEngineManager;
    _controllerDescriptorProvider = new ControllerDescriptorProviderStub(descriptor);
  }
  #endregion

  #region Methods
  public abstract void AddService(Type serviceType, object serviceInstance);
  public abstract void AddService(Type serviceType, object serviceInstance, bool promote);
  public abstract void AddService(Type serviceType, ServiceCreatorCallback callback);
  public abstract void AddService(Type serviceType, ServiceCreatorCallback callback, bool promote);
  public abstract void RemoveService(Type serviceType);
  public abstract void RemoveService(Type serviceType, bool promote);
  public object GetService(Type serviceType)
  {
    if (typeof(IViewEngineManager).Equals(serviceType))
    {
      return _viewEngineManager;
    }
    else if (typeof(IControllerDescriptorProvider).Equals(serviceType))
    {
      return _controllerDescriptorProvider;
    }
    else if (typeof(ILoggerFactory).Equals(serviceType))
    {
      return null;
    }
    else if (typeof(IUrlBuilder).Equals(serviceType))
    {
      return new DefaultUrlBuilder();
    }

    return null;
  }
  #endregion

  #region Classes
  private class ControllerDescriptorProviderStub : IControllerDescriptorProvider
  {
    private ControllerMetaDescriptor _descriptor;

    public ControllerDescriptorProviderStub(ControllerMetaDescriptor descriptor)
    {
      _descriptor = descriptor;
    }

    public ControllerMetaDescriptor BuildDescriptor(Controller controller)
    {
      return _descriptor;
    }

    public ControllerMetaDescriptor BuildDescriptor(Type controllerType)
    {
      return _descriptor;
    }

    public void Service(IServiceProvider provider)
    {
    }
  }
  #endregion
}

Source
by Aaron on Wednesday, March 28, 2007 2:51:30 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [6]  |  Trackback
 Tuesday, March 27, 2007

Update: Hamilton committed my patch, so if you're running off trunk you won't need to do this anymore. Thanks Hamilton!

Currently MonoRail uses ResourceSets wrapped up in an implementation of IResource to provide Resources to views. Unfortunately, ResourceSets do not cascade when it comes to resource resolution.  ResourceManager.GetResourceSet does have a flag called tryParents, but all that does is try less and less specific cultures until it finds a match. In other words, if you have two resource files:
Foo.ko.resx: defines A, B
Foo.resx: defines A, B, C

If you locale is ko-KR, calling RseourceManager.GetResourceSet will yield a ResourceSet that maps to Foo.ko.resx, so asking for B will work, but asking for C will not. A ResourceSet only knows about itself.

ResourceManagers on the other hand, are perfectly capable of handling this cascade, which is quite necessary in at least our localized app, as we do not want to have to define strings in all languages for everything. So with ResourceManagers, asking for A, B, and C all behave as expected, preferring the most specified culture and cascading down as necessary.

Below is an implementation of an IResourceFactory that spits out wrapped ResourceManagers instead of ResourceSets.

To use it you'll need to add this to your web.config:

<monorail>
  <services>
    <service id="ResourceFactory" type="Eleutian.Shared.MonoRail.ResourceManagerFactory, Eleutian.Shared" />
  </services>
</monorail>

Source

by Aaron on Tuesday, March 27, 2007 4:13:12 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Thursday, March 22, 2007

In a previous post I talked about how we use automatically generated interfaces to wrap our PropertyBag's. You can also use this technique in your ViewComponents to clean up that code quite a lot. We used to have code like this:

public class SomeComponent : ViewComponent
{
  public override void Initialize()
  {
    base.Initialize();
    User user = (User)this.ComponentParams["User"];
    float value = this.Service.CalculateThatValue(user);
    this.ComponentParams["SomeCalculatedValue"] = value;
  }
}

Now we can make an interface:

public interface ISomeComponentView
{
  User User { get; set; }
  float SomeCalculatedValue { get; set; }
}

And ask the code we wrote for the PropertyBag to give us a hand in cleaning things up:

public class SomeComponent : ViewComponent
{
  public override void Initialize()
  {
    base.Initialize();
    ISomeComponentView view = this.ViewFactory.ResolveView<ISomeComponentView>(this.ComponentParams);
    float value = this.Service.CalculateThatValue(view.User);
    view.SomeCalculatedValue = value;
  }
}

Much better! If you're looking for an implementation of that ViewFactory service, Lee Henson tossed one together shortly after our post. He's also added some other, pretty nitfy features since then. Like the ability to specify a prefix with an attribute for the generated dictionary keys. As he mentions in his post, you can use it for anything (and probably should) that uses strings as keys into an IDictionary (Session, Flash, etc..). I'm planning on checking it in to CastleContrib soon, until then, grab it off the list. Thanks Lee!

by Jacob on Thursday, March 22, 2007 9:21:27 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, March 16, 2007

Last week, Aaron and I were hanging out with a bunch of the Microsoft MVP's that were up in Seattle for the MVP Summit. We had an absolute blast and got to meet some excellent developers. It was a great opportunity to get a sense for how others in our situation were handling similar problems and to share things that we have all learned along the way. We had a few beers at the Party with Palermo event and the following day a few of the guys dropped by the Eleutian Seattle offices and we threw together a podcast with Scott Hanselman. It's a very quick introduction to MonoRail for those that aren't familiar. We go on to discuss testability and IoC in the context of the Castle project. It was a great chance to expose MonoRail and the concepts behind it to a wider audience.

In no particular order, here are some blogs if you're interested in some good reading on various areas of software development:

  • Scott Bellware - Development practices, C# 3.0, Ruby, and more. His company, Dovetail, is looking into starting development using MonoRail. They are hiring.
  • Jeremy Miller - Agile, especially TDD, IoC, etc...  Jeremy wrote StructureMap, an IoC framework. So, he definitely knows the why behind a lot of the agile practices.
  • Scott Hanselman - Anything and everything development and technology. I always find something new here. I'm sure you will also.

I'm glad to see some of the news that came out of the summit. I'm sure one of us will be back to expound on them once we've done a little more research and tinkering.

by Jacob on Friday, March 16, 2007 10:56:57 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Sunday, February 25, 2007

Roy Osherove brings up several good points with regards to the preached design methodology of old and the new testable design some of us have come to know and love lately.

I think that TDD really helps to eliminate a large number of these issues. If you test everything yourself, then inherently your API is testable. Unfortunately, as Jonathan Cogley points out, TDD is not yet mainstream.

A nice side effect of having a testable API or application is that often times your code is also extensible. The thing that blocks it from being fully testable and extensible are those darn sealed and internal keywords, and of course, not making things virtual that really should be. Even open source projects are guilty of not having testable or extensible enough APIs. Yes, Castle MonoRail provides AbstractMRTestCase, but that actually uses ASP.NET and is way more heavy than I like.

Here is our base class for Controller Tests. This allows you to unit test nearly every aspect of your controller, without ever hitting ASP.NET. Notice the lovely and necessary use of reflection? In order to mock the context, you'll want to call InitializeController and pass it the controller you're testing, but be sure to do it in your _mocks.Unordered block (we almost ALWAYS use mocks.Unordered... it makes tests more readable and ensures that you're tests aren't too tightly coupled with your implementation, but that's the subject for another post.)

  public class EleutianControllerTests
  {
    #region Constants
    private const string ApplicationPhysicalPath = "Q:\\PhysicalPath";
    #endregion

    #region Member Data
    protected string _virtualDirectory = String.Empty;
    protected MockRepository _mocks;
    protected IControllerServices _controllerServices;
    protected IRailsEngineContext _context;
    protected IRequest _request;
    protected IResponse _response;
    protected IServerUtility _serverUtility;
    protected IDictionary _session;
    protected Flash _flash;
    protected NameValueCollection _parameters;
    #endregion

    #regi