The trap of choices
Originally posted at 11/29/2010
In a recent blog post, I presented two choices about how to access the RavenDB multi tenancy feature.
- /northwind/docs - breaking change, obvious, less work
- /docs?database=northwind - non breaking change, not so obvious, more work
That post received a respectable amount of attention, but the point of the post wasn’t so much to gather information, but to prove a point.
Out of the 14 comments that that post current have, exactly none have tried to explore the problem beyond the options offered in the post.
In the real world, I solved the problem with RavenDB multi tenancy in a way that is both backward compatible and RESTful. The syntax for the url is:
- /docs <- use the default database
- /databases/northwind/docs <- use the northwind database
That is a pretty big problem that you have to deal with when you are communicating. When outlining possible solutions to a problem, you have to be aware that in many cases you are closing off people’s minds to other alternatives, which may be preferred.
Challenge: Querying relative information with RavenDB
Originally posted at 11/30/2010
Let us say that we have the following document:
{
"Name": "Ayende",
"LastScore": 239.2,
"MaxScore": 392.6
}
And we want to find all documents whose last score is within 10% from their max score.
If I was using SQL, I could express the query like this:
select * from GameResults where (LastScore + MaxScore/100 )> MaxScore
How would you create such a query using RavenDB?
- RavenDB has the notion of linear queries, which would allow executing the above query, but I don’t want to use that.
- RavenDB’ indexes don’t support any way to compare two fields to one another.
There is a solution, though, and it is quite an elegant one.
The most amazing demo ever
I was giving a talk yesterday at the Melbourne ALT.Net group, the topic of which was How Ayende’s Build Software. This isn’t the first time that I give this talk, and I thought that talking in the abstracts is only useful so much.
So I decided to demonstrate, live, how I get stuff done as quickly as I am. One of the most influential stories that I ever read was The Man Who Was Too Lazy to Fail - Robert A. Heinlein. He does a much better job in explain the reasoning, but essentially, it comes down to finding anything that you do more than once, and removing all friction from it.
In the talk, I decided to demonstrate, live, how this is done. I asked people to give me an idea about a new feature for NH Prof. After some back and forth, we settled on warning when you are issuing a query using a like that will force the database to use a table scan. I then proceed to implement the scenario showing what I wanted:
public class EndsWith : INHibernateScenario { public void Execute(ISessionFactory factory) { using(var s = factory.OpenSession()) { s.CreateCriteria<Blog>() .Add(Restrictions.Like("Title", "%ayende")) .List(); } } }
Implemented the feature itself, and tried it out live. This showed off some aspects about the actual development, the ability to execute just the right piece of the code that I want by offering the ability to execute individual scenarios easily.
We even did some debugging because it didn’t work the first time. Then I wrote the test for it:
public class WillDetectQueriesUsingEndsWith : IntegrationTestBase { [Fact] public void WillIssueWarning() { ExecuteScenarioInDifferentAppDomain<EndsWith>(); var statementModel = model.RecentStatements.Statements.First(); Assert.True( statementModel.Alerts.Any(x=>x.HelpTopic == AlertInformation.EndsWithWillForceTableScan.HelpTopic) ); } }
So far, so good, I have been doing stuff like that for a while now, live.
But it is the next step that I think shocked most people, because I then committed the changes, and let the CI process takes care of things. By the time that I showed the people in the room that the new build is now publically available, it has already been download.
Now, just to give you some idea, that wasn’t the point of this talk. I did a whole talk on different topic, and the whole process from “I need an idea” to “users are the newly deployed feature” took something in the order of 15 minutes, and that includes debugging to fix a problem.