Originally posted at 4/12/2011
Can you spot the NRE hiding in the code?
if (parentObject!= null) { lock (parentObject) { if (parentObject != null) { properties = properties.Clone(); parentObject[parentKey] = this; parentObject = null; } } }
Originally posted at 4/12/2011
Can you spot the NRE hiding in the code?
if (parentObject!= null) { lock (parentObject) { if (parentObject != null) { properties = properties.Clone(); parentObject[parentKey] = this; parentObject = null; } } }
Originally posted at 4/11/2011
I was trying to take a backup of my blog to see if I can do some fancy stuff there, when I realized that the blog backup was 2 GB (!) in size. Now, I know that I post a lot, but I don’t think that I post that much.
As it turns out, the problem was with unbounded logs that started taking up most of the space in the database:
In general, when building applications that are meant to run over long periods of time without attention, it is better to have some way of getting rid of unimportant information automatically.
One of the interesting aspects of build RavenDB was that it opened up my mind to the way we can use the very nature of the server to open up additional information about the server operations.
One thing that I noticed recently is that if I need to debug a test for RavenDB, I often need to stop the current thread (the Test thread) and then literally go to the server test instance and look at what is actually going on in there.
The fun part is that this is really nice, because I can go an inspect the running test instance, see what is going on, modify things to see how they affect the behavior, etc. The only problem is that this is actually quite complex to setup manually (stop on debugger, freeze the appropriate thread, resume run, inspect server – modify stuff there, stop on debugger, thaw thread, continue run, etc).
What occurred to me, however, is that I can codify this behavior, and end up with this:
This method will only operate while a debugger is attached, but it is going to save me a long time. Once I am done, I need to delete the marker document:
This is especially important if you are running in and in memory mode, since the moment the test is over, the database is completely wiped out.
Originally posted at 4/4/2011
One of the things that I really tried to do with RavenDB is to make sure that it is safe by default, which means that it will automatically detect common errors and warn you about it.
Today I run into the following Stack Overflow question.
What can I say, it works!
Originally posted at 4/4/2011
One of the advantages of RavenDB is that the documents format is highly human readable. Except for one thing. Can you tell me what date is represented by this value:
/Date(1224043200000+0300)/
I thought not :-)
We have recently moved toward this format instead:
2011-04-04T11:28:46.0404749+03:00
Which it both machine and human readable.
This make figuring out what something is so much easier.
Originally posted at 3/22/2011
This time, taking on Who Can Help Me, I found some really interesting things there.
For one thing, we got this little guy:
I was all ready to discover INewsRepository –<> NewsRepository : Repository<NewsItem>, etc. What I found, instead was a real service:
That is how it is supposed to be, to be frank. There is a need to abstract something, and we write just enough code to make it work. I would argue with the implementation of this, however, because the approach for multi threading is wrong headed. We shouldn’t spin out a new thread pool work item just to execute the request when the FluentTwitter API already contains async version that can do quite well for us, but the overall concept is sound. And I was relieved not to find nested repositories in my first few steps there.
Of course, I then discovered that this nice service has some friends from the left side of the blanket:
I think that I expressed my opinion about code such as this:
A waste of keystrokes, and highly inefficient to boot. You don’t make queries by Id in NHibernate, you use Get or Load instead.
Overloading the infrastructure – After reviewing the code, I was surprised to see so much of it dedicated for caching:
What surprised me more is that in the entire application there were exactly two locations where a cache was used. In both cases, it led to the same service. Implementing a much simpler solution in that service would have chopped quite a bit of code out of this project.
And then there was this:
Luckily, this is dead code, but I was quite amused by this code, in a “shake you head in disbelief” fashion.
First, for a code that is obviously meant to be used in a multi threaded fashion, it is not thread safe. Second, it is actually a memory leak waiting to happen, more than anything else. If you call that method, your items will never freed.
The next is a personal opinion, but I can’t help feeling that this is pretty heavy weight:
Well, that is true whenever you are looking at an XSD, but in this case, we just need to expose two properties, and I think that it would have been perfectly fine to stick that into the <appSettings/> section. There are actually several places where similar approach has been tried, but I don’t see this of any value if you aren’t writing a library that might require special configuration. If you are writing an app, using the default modes is usually more than enough.
Reading the controllers code wasn’t a real surprise. One thing that did bother me is the amount of mapping that is going on there, and how much of that I was simply unable to follow. For example:
Which is then calling;
Which then goes into additional custom implementations and convention based ones.
The reason that this is important is that this is a prime location for Select N+1 issues, and indeed, we have several such occurrences of the problem just in this piece of code.
Originally posted at 3/31/2011
I am currently sitting with 3 guys in the pub, and the discussion naturally turned to performance. I asked all three the following question: “How many CLR objects can you create in one second?”
I got the following replies:
Then I sat down to check:
class Program { static void Main(string[] args) { var sp = Stopwatch.StartNew(); int i = 0; while(sp.ElapsedMilliseconds < 1000) { new MyClass(); i++; } sp.Stop(); Console.WriteLine("Created {0} in {1}", i, sp.Elapsed); } } public class MyClass { public string A; public int B; public DateTime C; }
The result?
Created 7,715,305 in 00:00:01
Originally posted at 3/30/2011
I have seen all of those in production code…
throw new NullReferenceException();
public class AbstractController : Controller // or // public class AbstractPag : Page { public static bool IsAdmin { get;set; } }
public static class BlogMgr { public static void AddPostToBlog(Blog blog, Post post) { blog.Posts.Add(post); post.Blog = blog; } }
* I could only think of three, but I didn’t want to modify the title. Can you complete the list?
Originally posted at 3/30/2011
One thing that we haven’t done so far is manage transactions. I am strongly against having automatic transactions that wrap the entire request. However, I do like automatic transactions that wrap a single action. We can implement this as:
public class NHibernateActionFilter : ActionFilterAttribute { private static readonly ISessionFactory sessionFactory = BuildSessionFactory(); private static ISessionFactory BuildSessionFactory() { return new Configuration() .Configure() .BuildSessionFactory(); } public override void OnActionExecuting(ActionExecutingContext filterContext) { var sessionController = filterContext.Controller as SessionController; if (sessionController == null) return; sessionController.Session = sessionFactory.OpenSession(); sessionController.Session.BeginTransaction(); } public override void OnActionExecuted(ActionExecutedContext filterContext) { var sessionController = filterContext.Controller as SessionController; if (sessionController == null) return; using (var session = sessionController.Session) { if (session == null) return; if (!session.Transaction.IsActive) return; if (filterContext.Exception != null) session.Transaction.Rollback(); else session.Transaction.Commit(); } } }
This one is pretty simple, except that you should note that we are checking if the transaction is active before trying something. That is important because we might have got here because of an error in the opening the transaction, we would get a second error which would mask the first.
Originally posted at 3/30/2011
While I don’t really mind having global state, it tends to bite you on the ass eventually, so let us try to deal with this guy, shall we?
public class NHibernateActionFilter : ActionFilterAttribute { private static readonly ISessionFactory sessionFactory = BuildSessionFactory(); public static ISession CurrentSession { get { return HttpContext.Current.Items["NHibernateSession"] as ISession; } set { HttpContext.Current.Items["NHibernateSession"] = value; } } private static ISessionFactory BuildSessionFactory() { return new Configuration() .Configure() .BuildSessionFactory(); } public override void OnActionExecuting(ActionExecutingContext filterContext) { CurrentSession = sessionFactory.OpenSession(); } public override void OnActionExecuted(ActionExecutedContext filterContext) { var session = CurrentSession; if (session != null) { session.Dispose(); } } }
One easy way to do so would be to put the session directly where we want it to be, in the controller. We already have an extension point for that, the SessionController. Instead of referencing the global session, it can just hold its own:
public class SessionController : Controller { public HttpSessionStateBase HttpSession { get { return base.Session; } } public new ISession Session { get; set; } }
Which leads us to:
public class NHibernateActionFilter : ActionFilterAttribute { private static readonly ISessionFactory sessionFactory = BuildSessionFactory(); private static ISessionFactory BuildSessionFactory() { return new Configuration() .Configure() .BuildSessionFactory(); } public override void OnActionExecuting(ActionExecutingContext filterContext) { var sessionController = filterContext.Controller as SessionController; if (sessionController == null) return; sessionController.Session = sessionFactory.OpenSession(); } public override void OnActionExecuted(ActionExecutedContext filterContext) { var sessionController = filterContext.Controller as SessionController; if (sessionController == null) return; var session = sessionController.Session; if (session == null) return; session.Dispose(); } }
Now we have absolutely no global state, and yet we have a very easy access to the current session.
There are still a few things missing, can you see them?
No future posts left, oh my!