Ayende @ Rahien

My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:


+972 52-548-6969

, @ Q c

Posts: 6,007 | Comments: 44,762

filter by tags archive

Thinking about WinFS

time to read 1 min | 187 words

I'm currently watching the Channel 9 video about WinFS, and I'm using this post to keep track of the questions & thoughts I've while seeing it:

  • One big one is the ability to delete a file while someone is holding it open. NTFS doesn't allow it, but most of the Linux file system does. The issue here is the ability to upgrade core components without rebooting. If WinFS would make it possible to delete a file while some program is using it, the reasons for reboots would suddenly drop sharply.
  • What happen if I've a relationship between files and I copy the set of file to a non-winfs medium (ftp, zip, cd, etc) and then I copy it back to a winfs medium, what happen to the relationships, the meta data?
    From the video it looks like it should work.

I'm a Castle Commiter!

time to read 1 min | 136 words

I've been voted as a commiter for the Castle Project. You might recall how excited how I was when a patch I made was accepted for Catle, so you can imagine how I feel right now about it. :-D

Along with this there is another big issue: Brail has been accepted into Castle's MonoRail and will now be available as part of their services. So I would finally have a public Subversion server that I can point people to.

I'm going to update everything in the site and upload the repository tomorrow. I want to add some more usability features. Specifically, it's the Brail pre processor that worries me. It's too strict. I'm not sure how to solve this problem, but I'll give it some thought.

Spelling mistakes

time to read 1 min | 89 words

This is embarrassing, I just realized that I'd a spelling mistake in NHibernate Query Analyzer on my site for at least four months.

I fixed it, but this also means fixing the URL :-(

I updated most of the links on my sites, but be sure to fix any links to it if you have any.

The links are:

http://www.ayende.com/projects/nhibernate-query-analyzer.aspx - Project page.

http://www.ayende.com/projects/nhibernate-query-analyzer/flash-demo.aspx - The demo.

http://www.ayende.com/projects/nhibernate-query-analyzer/downloads.aspx - Download page

MSN vs. Google

time to read 1 min | 72 words

A few days ago I noticed a sudden spike in the traffic to the site, attributed to MSN Bot going crazy and hitting my site thousands of times. It's still in the range of hundreds right now. I know that others have noticed the same.

What is interesting is that it seems that I can now find things on MSN that I can't on Google.

Book ReviewWorking Effectively With Legacy Code

time to read 2 min | 303 words

Working Effectively with Legacy Code is a book that should be a mandatory reading for anyone who is interested in coding for a living. I don't deal with many legacy systems at the present (except for NQA, of course :-) ) and still this book has been a fountain of knowledge about techniques, tips and tricks.

This is not a book about pretty code, it's a book about ugly code and all the myrad ways you can abuse design pricipals and good coding practices. What it does is show a set to systematically take a legacy code* and break down the dependencies so you can write tests for the code. The moment you've tests, you can move forward. Until you've tests, you're in a position where all you can do is "Edit & Pray" or... you can write tests.

I've had recent experiance with developing applications in a TDD from the start (Rhino Mocks) and converting a legacy application to TDD (NQA). I can't rave enough about how much easier it is to make a change in Rhino Mocks because of those tests. When I adapted Rhino Mocks to run on .Net 2.0 I'd broken just about every part of the application because I didn't consider what the change from Hashtable to Dictionary<T> would do when there is no item in the dictionary. Because I'd tests, it was literaly the work of a minute to find the problem and fix it.

One thing to note about this book, it took me over two months to read it. Like Xp Explained 2nd Ed. I just can't seem to read it for any length of time without starting to feel a sudden need to code something. Very productive for my projects, less so for my reading backlog.

* Legacy Code == Code without tests.

Seems that I learned soemthing after all

time to read 25 min | 4881 words

Did you ever had a problem that you simply couldn't solve? I had one such problem 8 months ago, I wanted some way to skip the somewhat tedious log4net logging approach:

if (logger.IsDebugEnabled)
    logger.Debug("message with ""expansive" +" " + "string concentration");

This is the recommended approach from the log4net documentation, and it makes sense, this way, if you don't enable logging, you don't pay for any string concentration. But it's very tedious to do so over and over again. I really wanted a clean way to do it, but at the time Boo's macros were far beyond my capabilities. Even for such a simple task.

Fast forward to the present....

Now I have no difficulities writing this, in fact, the entire utility was developed in one session in Notepad (the way real programmers do it :-) ). What is interesting is that in the meantime I had no education in compilers, AST, etc. I just came back to the subject and it suddenly made sense. It happened to me before in many situations, but this is the first that I can actually find a documented proof of that.

I remember in high school I was unabled to grasp the idea of dynamic memory (on my defense, I didn't try very hard), that was on Pascal with ^ going all over the place. Six months later, I was a triple star programmer (and proud of it :-) ) in C. Again, nothing much has changed, except maybe that this time I was more willing to learn.

Anyway, here is the code, less than 60 lines of code, and I found it useful in reducing common repetitive statements.


  This macros allows a convenient way to log properly, without getting tired by writing logger.IsXXXEnabled all the time.
  The macros depend on a ILog field/local named logger being present, this you've to define yourself.

  namespace log4net
  import System
  import Boo.Lang.Compiler
  import Boo.Lang.Compiler.Ast
  class LogdbgMacro(AbstractAstMacro):
  Logs a debug message if debug messages logging are enabled.
  Usage: logdbg "message" [exception]
      override def Expand(macro as MacroStatement):
          return GenerateStatement("Debug"macro)
  class LogwarnMacro(AbstractAstMacro):
  Logs a warning message if warning messages are enabled enabled.
  Usage: logwarn "warning" [exception]
      override def Expand(macro as MacroStatement):
          return GenerateStatement("Warn"macro)
  class LogerrorMacro(AbstractAstMacro):
  Logs an error message if error logging is enabled
  Usage: logerror "error" [exception]
      override def Expand(macro as MacroStatement):
          return GenerateStatement("Error"macro)
  class LogfatalMacro(AbstractAstMacro):
  Logs a fatal error message if fatal error logging is enabled
  Usage: logfatal "fatal error" [exception]
      override def Expand(macro as MacroStatement):
          return GenerateStatement("Fatal"macro)
  class LogInfoMacro(AbstractAstMacro):
  Logs an informative message if informative messages logging is enabled.
  Usage: loginfo "didja know?" [exception]
      override def Expand(macro as MacroStatement):
          return GenerateStatement("Info"macro)
  internal def GenerateStatement(logOption as stringmacro as MacroStatement):
      if len(macro.Arguments) < or len(macro.Arguments) > :
          raise CompilerError(macro.LexicalInfo"The log can be called with either one or two parameters only!")
      isEnabledProp MethodInvocationExpressionTarget: AstUtil.CreateReferenceExpression("logger.get_Is${logOption}Enabled") )
      ifEnabled IfStatement(Condition: isEnabledPropTrueBlock: Block() )
      mie MethodInvocationExpression(Target: AstUtil.CreateReferenceExpression("logger.${logOption}") )
      mie.Arguments.Add(macro.Arguments[1]) if len(macro.Arguments)==2
      return ifEnabled

Brail 1.2.1

time to read 1 min | 121 words

A new release for a new day :-)

Brail will now notice if you change anything in the Common Scripts folder and will recompile the views so you no longer has to restart the application to test a change in Common Scripts.

Brail can now serve a request entirely from memory (previously it touched the disk at every request to verify that the file existed and wasn’t changed).

The last should be a significant perofrmance improvement, but I'm not saying anything for cetain until I'll have some performance data.

Download here.


No future posts left, oh my!


  1. Speaking (3):
    23 Sep 2015 - Build Stuff 2015 (Lithuania & Ukraine), Nov 18 - 24
  2. Production postmortem (11):
    22 Sep 2015 - The case of the Unicode Poo
  3. Technical observations from my wife (2):
    15 Sep 2015 - Disk speeds
  4. Find the bug (5):
    11 Sep 2015 - The concurrent memory buster
  5. Buffer allocation strategies (3):
    09 Sep 2015 - Bad usage patterns
View all series



Main feed Feed Stats
Comments feed   Comments Feed Stats