Ayende @ Rahien

Hi!
My name is Ayende Rahien
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:

ayende@ayende.com

+972 52-548-6969

@

Posts: 5,947 | Comments: 44,541

filter by tags archive

NHibernate on .Net 2.0Part II


My first attempt in using generic collections in NHibernate was to just make NHibernate grok my custom collection. I took a look in the code, and it seemed rather straightforward to do so. I posted to the developer list and got the following response from Sergey, the lead developer:

  1. Have your collection class implement an interface (class MyCollection: IMyCollection)
  2. Create NHibernate-specific wrapper class (PersistentMyCollection : PersistentCollection, IMyCollection) which functions as a proxy for the real collection. All methods from IMyCollection that PersistentMyCollection implements have a Read() or Write() at the beginning, and then delegate to the real collection. PersistentMyCollection should also implement some abstract methods from PersistentCollection, these mostly have to do with snapshots and loading process.
  3. Create MyCollectionType which will derive from PersistentCollectionType and implement methods like Wrap (wrapping MyCollection in PersistentMyCollection), Instantiate, Add and Clear, and the rest.
  4. Modify the binder to accept your collection type, and that should be it.

It's straightforward but a long process, and it involves some deep knowledge about the way NHibernate works. Luckily I managed to get it most of it pre-baked by transforming the existing Set collections to use generics. I started to run into problems when I had to dynamically construct generic types, but this article sums it pretty well. I could get the correct info and get it to work.

I decided to wait with that for now, and try a less invasive approach. I'm currently trying to get it to work using a Property Accessors. I'll post my results when I'm done.

Good quotes


These quotes really cracked me up, I have to find an excuse to use them on someone sometime.

I think my favorites are:

  •  "A modest little person, with much to be modest about." --Winston Churchill
  •  "I've just learned about his illness. Let's hope it's nothing trivial." --Irvin S. Cobb

NHibernate on .Net 2.0Part I


I've been developing in .Net 2.0 [without ReSharper* :-( ], and I'm using NHiberante and Active Record for the data access layer. There were no problems with regard to their usage, but there are things that I don't like in the interface that they gives you. The problem is that you get an untyped collection. This was sort of OK in 1.0/1.1 but it's a really eye sore for developing in 2.0, where I want everything to be a generic type-safe collection.

Another issue with NHibernate is that the syncing between relationships is not automatic. That is to say, the following code is essentially a no-op:

Blog blog = session.Load(typeof(Blog),1);
blog.Posts.Add(new Post("Briliant Post By Ayende"));
session.Flush();

Since the relationship is maintained on the other side of the connection. (Think about the way it's all laid out in the tables, and you'll understand why.) This is the bare minimum to get it to work:

Post post = new Post("Briliant Post By Ayende")
Blog blog = session.Load(typeof(Blog),1);
post.Blog = blog;
session.Save(post);
session.Flush();

But the above code has a serious shortcoming, it doesn't create the association in the blog, so you would need to re-load the blog from the database to get the change. This is undesirable, naturally, so you can do:

Post post = new Post("Briliant Post By Ayende")
Blog blog = session.Load(typeof(Blog),1);
post.Blog = blog;
blog.Posts.Add(post);
session.Save(post);
session.Flush();

Or create a method AddPost() that will do both operations in one line. This is something that bothers me, I like the natural way of doing blog.Posts.Add(post) to create associations. It's what a developer come to expect. The problem is that you can't add the code to do it to the Add() method on the list since the list is something that NHibernate supplies to you.

On the next installment I'll describe how I'm going to solve this problem.

* I did try, but it's not stable by far yet.

Code Coverage and Exceptions


One of the more annoying this in code coverage in .Net is that it doesn't consider the line where an exception was thrown to be visited.

public void SomeMethod()
{
   throw new Exception(); //Will appear as unvisited to the code coverage
}

Both NCover and VS 2005 exhibit this behavior, and I assume that this has to do with the way they work, via the profiling API. Anyone can say what the reason for that is?

Visual Studio 2005: Unfit for Testing


I'm not sure who is in fault here. If it is me or if it's something in VS. I didn't get any training, or read any books, before moving to VS 2005. And I am certainly struggling with it. I'd a comfortable set of tools in VS 2003, which I knew and loved. And VS 2005 has (on the surface) superior tools. But I keep running into stupid things that making it impossible for me to use them.

I've used VS testing capabilities for less than a single day, and I can tell you right now whoever wrote them left gaping holes in the implementation. Comparing VS 2005 Unit Testing (From Microsoft, supposedly well researched and well tested) vs. the open source unit testing frameworks (which doesn't have nearly the same resources as Microsoft) the open source wins hands down.

Oh, the VS 2005 UI is much slicker, and you need to combine a lot of tools to get the same results as what VS 2005 is offering, but the problem is that VS 2005 unit testing just doesn't work!

You can't use the abstract test fixture pattern! They know about it since January, but don't seem willing to change that! Another request in April got a "By Design" status and was postphoned to the next release. They also suggest to duplicate your code in order to cover this scenario.

I don't know about Microsoft, but when I've a complex class library, I want to know that a change to a base class (with potentially dozens of children, and very complex logic) is done in one place only. I believe this is called the DRY principal, which I hear has some importance in a distant developer cult located in the Himallaya. Obviously Microsoft thinks otherwise.

The microsoft solution to testing such a class is:

  • Change all the hundreds of concrete tests that you've that refer to a spesific functionality in the base class. (Since each concrete class gets its own copy of the base class tests.) - Time estimate: days.
  • Run the tests and see all the tests breaks.
  • Make the change to the base class.
  • Run the tests again and watch all the tests that you forgot to modify breaks.

The xUnit solution for testing such a class is:

  • Make a change to the single test in the abstract test class. - Time estimate: minutes.
  • Run and see it breaks.
  • Make the change to the base class.
  • Run the tests and get the green bar.

Can you spot the difference?

It's a simple change in the test runner, you need to drop the DeclaredOnly flag, but it's probably a major change with regard to the accopanying toolkit.

This comes after I discovered other major flaw in the product, the following code is a passing test:

[TestMethod(), ExpectedException(typeof(ArgumentNullException),"Blah")] 
public void MethodUnderTest() 

  throw new ArgumentNullException("1234"); 

Can you spot the huge bug? See what the exception message is? And what is the expected exception message it?

Again, this is from a very short introduction to the VS 2005 Unit Testing capabilities, and I'm really impressed with the abilities of the UI although there are some strange holes there as well. Where is the ability to point at a test/fixture and say run those tests? The functionality exists, but it's a bit involved procedure.

Nevertheless, I'm forced to conclude that VS 2005 as it stands today is unfit to be used as a serious Unit Testing framework. It has a lot of other capabilities that I didn't even began to explore (Load testing, web testing, etc). But for unit testing it simply is an unacceptable hurdle.

The rules for Test Driven Development are:

  1. Write a small test.
  2. Write just enough code to make it pass.
  3. Remove Duplication

You can't do that in VS 2005.

By the way, I'm using the release candidate, so it's pretty certain that this is the way it will go to market, which is really sad.

Mocking in the Real World


I was in the Agile Israel meeting earilier this earlier week, and I overheard a couple of guys* talking about mocking objects. The talk went something like this:

Guy #1: Most developers don't understand mock objects.
Guy #2: But then you explain it to them and when they get it, they become the local gurus.
Guy #1: Yes, but then they try to use mocks everywhere and make a mess of things.

Do you have similar experiances? I'm the author of a mocking framework, and I find that I don't use mocking all that often. Then again, my recent projects were mainly in compiler internals and the like, not much you can mock there.

I'm currently building a business application, so I expect to make heavy use of mocking the moment I move away from the data access layer, which is my curent focus.

* This was my first meeting, so I don't know any of the names, I did meet Justin, though.

How to get the database structure script from SQL Express?


Here the scenario, I'm using VS 2005 with SQL Express 2005. I started with a database structure from the schema, and then I started writing code, every so often finding spots where the spec got it wrong, so I would change the table (Naming/Relationships/etc). I did it all inside VS 2005.

The problem: Now I can't get it out.

There doesn't seem to be a way to tell VS 2005 or SQL Server: "Thank you very much, this is the final structure, now give me the script to create it in another database."

I don't need data replication, I just need the create table ... for the entire database. This can be done very easily from Enterprise Manager, but I don't have that on the machine. I can't install it because it require uninstaling SQL Express, and that takes us to the CTP Matching Game. I'm 99.9% sure that if I would do it I would manage to lose my current database.

I tried connecting to it from Enterprise Manager 2000 on another machine, but it refuse to login, even though I'm using Windows Authentication and I can login to the computer from the second machine. Installing the full SQL Server 2005 on another machine is something that will take a couple of hours at least, and even then I'm not guaranteed to have it work (I've very bad experience with the SQL Express line).

So the question is simple, how do I get the table information out of the database?

ICollection WTF?


I’m just trying to implement a generic container for a collection from 1.1, and I took a real look at ICollection, there are not add/remove/contains methods!

WTF was going on in the mind of the person who designed it?

 

public interface ICollection : IEnumerable

{

      void CopyTo(Array array, int index);

 

      int Count { get; }

      bool IsSynchronized { get; }

      object SyncRoot { get; }

}

 

What is the use of such an interface? To provide synchronization primitives?  To allow coping to arrays? At least ICollection<T> has some abilities.

A new way to abuse C@


No, the the title is not a mistake, I just figured out something that should've been obvious. You can use C# to write code like this:

int @class = 0;

And the compiler will translate the name to the IL even though it's a reserved work. It stands to reason that you can also use it on non reserved words, doesn't it?

object @something = null;

The above compiles fine, and it's a very Ruby way to name a variable. What about the part about abusing the language? Well, consider this code:

string @a = "Cat";
a += @a;

There is only one variable involved here, and it's named 'a', but the @ is pretty confusing if you don't know what you're dealing with.

FUTURE POSTS

No future posts left, oh my!

RECENT SERIES

  1. RavenDB Sharding (3):
    22 May 2015 - Adding a new shard to an existing cluster, splitting the shard
  2. The RavenDB Comic Strip (2):
    20 May 2015 - Part II – a team in trouble!
  3. Challenge (45):
    28 Apr 2015 - What is the meaning of this change?
  4. Interview question (2):
    30 Mar 2015 - fix the index
  5. Excerpts from the RavenDB Performance team report (20):
    20 Feb 2015 - Optimizing Compare – The circle of life (a post-mortem)
View all series

RECENT COMMENTS

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats