Ayende @ Rahien

Refunds available at head office

Vs.Net Debugger wish for the day

I want to be able to see the return value of a function in the debugger. I can recall something similar in VC++ 6.0, and knowing MS, it probably didn't go away on its own. Is it still possible in VS.Net?

I'm talking about the return value of a function like:

Assert.AreEqual(30,range.Min());

Currently I need a (redundant) variable if I want to check the return value.

Tags:

Published at

Rhino Mocks Update

Sorry for not releasing it today, but I was veyr busy all day, and didn't had time to do much about the article. I did find a bug in Rhino Mocks, it only affect code that uses nested orderring and SetupResult, but when I fixed it, I realized that this is a good opportunity to fix the whole nested orderring before I ship the second version, and that took quite a bit of time.

I had a very interesting technical discussion about the logic of nested orderring with some very non technical people, I think we designed this feature for about an hour and a half. A lot of fun.

 

Tags:

Published at

WMP Surprise Feature

I just found out that Windows Media Player can adjust the play speed for all media. It was an accident when I was bored and just explored the menus, but it's so much fun to play familiar songs at different songs, I had a "Do you recognize this song?" contest with it.

More Legacy Code Quotes

This time it is from  Jeremy Miller [The Shade Tree Developer]

“The legacy code was so tightly coupled that if you put a chunk of coal between the classes you would get a diamond.”

Another thing that caught my eye:

Twice in the last year I’ve transitioned from greenfield development projects that were written with TDD to working with brownfield code that had not been written with TDD. In almost startling contrast, the test-first code was vastly easier to extend with new unit tests than the code written test-last.

I feel the exact same pain in NQA currently. Even after all the major refactoring that went there. In comparision, it's a joy to work on Rhino Mocks, because it was developed Test First.

Blog downtime

I just noticed that my blog was down, I'm pretty sure that was because of adding the popular lists, I removed it, and everything was back online again. Sorry for the down-time.
Tags:

Published at

Mock framework comparison

This is just a quicky, doesn't mean much, but allows a look at how each framework's syntax allows to setup a expectation & return value for a method:

NMock:

IMock mock = new DynamicMock(typeof(IRequest));
IRequest request = (IRequest)mock.MockInstance;
mock.ExpectAndReturn("Username","Ayende");
testedObject.HandleRequest(request);
mock.Verify();

EasyMock.Net:

MockControl control = MockControl.CreateControl(typeof(IRequest));
IRequest request = (IRequest)control.GetMock();
control.ExpectAndReturn(request.Username,"Ayende");
control.Replay();
testedObject.HandleRequest(mock);
control.Verify();

TypeMock.Net: [Update: This is the correct syntax] 

Mock requestMock = MockManager.Mock(typeof(ConcreteRequest));
requestMock.ExpectAndReturn("Username","Ayende");
//TypeMock.Net should take care of intercepting the calls for Username
testedObject.HandleRequest(new ConcreteRequest());
MockManager.Verify();

Rhino Mocks Version 1.0:

MockControl mockRequest = MockControl.CreateControl(typeof(IRequest));
IRequest request = (IRequest)mockRequest.MockInstance;
mockRequest.ExpectAndReturn(request.Username,"Ayende");
mockRequest.Replay();
testedObject.HandleRequest(request);
mockRequest.Verify();

NMock2:

using(Mockery mocks = new Mockery())
{
  IRequest request = (IRequest)mocks.NewMock(typeof(IRequest),"IRequest");
  Expect.Once.On(request).GetProperty("Username").Will(Return.Value("Ayende"));
  testedObject.HandleRequest(request);

Rhino Mocks Version 2.0:

using(MockRepository mocks = new MocksRepository)
{
   IRequest request = (IRequest)mocks.CreateMock(typeof(IRequest));
   Expect.On(request).Call(request.Username).Return("Ayende");
   mocks.ReplayAll();
   testedObject.HandleRequest(request);
}

Anyone wants to guess who get this editor's prize? :-)

When code surprises you in a good way

[Note: This is another post where I just added over several hours as I added the finishing touches for Rhino Mocks.]

I found out something nice about Rhino Mocks, it allows you to specify ordered sequences of unordered method calls. Meaning that I can specify that calls A, B & C would occur in any order, and only after those three calls, the calls for D, E & F would occur (in that order, or in any order). I'm not very clear, but I'm working on an article that should explain it all, and expose all the nice things that Rhino Mocks 2.0 can do :-)

That is not something that I put it. I debugged it, and I thought that this was just a freak chance, but apperantly another feature I put it (adding IDisposable to verify mocks*) prevented it from being fully useful. I had to add three lines of code to handle the situation, and that was that. The reverse behaviour shouldn't be possible (I think, Rhino Mocks surprised me before tested it, as expected, it doesn't work)  so currently I don't think you can say "Do X then Y then Z, Do A then B the C, but I don't care if XYZ is first, or ABC". It wouldn't be too hard to add this, but I currently don't need it, if you think this would be useful, tell me and I'll add it.

Interestingly, I found that as I neared completion, I needed less and less code to do what I want, some thing just happened, without having to add any more code, and the rest was a matter of adding a derived class and a way to call it.

A lot of the effort was spend in making the code easier to read and write. In this, I am quite inspired by NMock2 and it's use of Matchers (what NMock & Rhino Mocks call constraints) and how easy it is to use. I'm currently moving NQA to use the new version** of Rhino Mocks. It's actually fun, and I added some nicer syntax options for recording expectations. The nicer thing is that I got rid of some warts that were there because the Rhino Mocks 1.0 used Remoting, and there were several places where that leaked through. {Having to inherit from MarshalByRef to get a proxy for a concrete class, can't do normal comparision, etc}.

I'm very glad that I spent a lot of time perfecting the error messages, I make purposefully a lot of mistakes trying to convert from one version to the other, and it's good to see how easy it is to solve them using Rhino Mocks. I'm finding my share of bugs in the tests. Things that work properly, but just because the code isn't checking them well enough, or version 1.0 allowed them to slip through, and the version 2.0 doesn't.

01:00 AM: I've finally moved all of NQA to use Rhino Mocks version 2.0, it's been very educating. I've a lot of info to write that article about. Four pages of just headnotes :-) I expect to be done with the article and documentation and be able to officially release it tomorrow.

* It actually makes sense, wait for the article.

** This is the second time already, this time I'm keeping the syntax, it's too much work.

To Block Spam: ReverseDOS

AngryPets' ReverseDOS

I read about it quite a bit, and after tha last round of trackback spams, which dasBlog still doesn't handle, I decided to give it a try. The webseite is very clear, and the installation is a piece of cake. Drop the file in the bin folder, add some lines in Web.Config, and you're done.

The nice thing about it is that it should stop a wide range spams (comments, CommentAPI, refferers, trackbacks) using a single tool and without modifying the application at all. It's like Ascpecting the application.

If you've a blog and want to reduce spam, check it out.

"A man sits with a pretty girl for an hour, it seems like a minute. He sits on a hot stove for a minute, it's longer than any hour. That is relativity." -- Albert Einstein
"A book is like a garden carried in the pocket." -- arab proverb
""I have PMS and a handgun. Any questions?" (I saw this on the back of a porsche 911 ... kinda makes you think :)" -- Bumper Sticker

[Listening to: Hawk Brother - Mercedes Lackey & Heather Alexander - (04:57)]

Popular list & Google Ads

I just added a popular list for the blog, the results are not very suprising :-)

One thing I noticed is that on IE I can't see the google ads, is it just me?

[Update: It seems to be just this computer, on my laptop I can see them. Strange]

Tags:

Published at

Setting of the wrong path, on purpose

That is how I built Rhino Mock 2.0.

I've a general idea about how I want it to look like, and I knew that I didn't like the current implementation. I wasn't very sure about how to go about implementing this, however. After my experiances with NQA, and after reading Working Effectively With Legacy Code, I knew that Test First is the way to go. So I started writing tests, and writing code to make them pass.

The part that I had a problem with was that I wrote code that I knew I was going to throw in a couple of hours / days, nevertheless, the tests require that it would give a complete solution to the problem. Then I added more functionality and I needed to rip apart the guts of the engine once more, and tottaly turn it around (from one mock at a time to managing several mocks at the same time.). Because I had the tests there, it took very little time to get back to where I was, and I'd the ground work to write more complicated tests.

Rhino Mocks 2.0 is feature complete starting from about 10 minutes ago, and all that remains is to switch NQA to the new version so I can dog food it properly. I expect to release it sometimes tonight. Here are some interesting statistics:

Total lines of code: 15,071 (Project) & 2,770 (Tests) = 17,841. Doesn't look too good, does it :-)

But: lines of code in the project, excluding generated strongly typed collections and xml comments: 1952 (Project) & 2382 (Tests)

So I actually have more code in the tests than in the code itself, which is what Test First should gives me. That was a very interesting experiment, btw, and quite a bit of fun.

"Your fault, core dumped." -- Tech Support Slogan
"IBM: Itty Bitty Mouse" -- Tech Support Slogan
"Out of my mind. Back in five minutes." -- Bumper Sticker

[Listening to: Jerusalem of Gold - Ofra Haza - Greatest Hits (disk 3)(05:47)]

DynamicProxy Strangeness

Just when I need the mailing list, SourceForge seems to be down :-( Correction, not down, just slow as hellllll!!! What is worse, it doesn't sends the confirmations emails for goinging mailing lists!

Anyway, I encountered very strange stuff going on in DynamicProxy, I'm currently adding support for mocking classes in Rhino Mocks, and I found that DynamicProxy can create proxies for:

  • Interfaces
  • Concrete classes
  • Abstract classes that has no abstract methods

But it can't create proxies for:

  • Sealed classes - this is reasonable.
  • Abstract classes that has abstract methods - I just can't understand this. What is the difference between that and an interface? Or proxing a class' virtual method? This seems completely arbitary to me.

As I said, I can't access the SourceForge mailing lists right now, so I can't ask the DynamicProxy team, anyone has an opnion why this is?

Tags:

Published at

TDD Goodness

I just had a complete surprise writing a test for Rhino Mocks. I'm doing that completely Test First, and I wrote a test, expecting it to fail. But it passed. Apperantly I'm already covering this case. :-)

This is so nice.

[Update: (five minutes later) Now it begins to be scary. I just wrote another test, for a part that I knew should be hard to get working. And it passed as well. The code handles it just fine, even though I thought I would need extensive changes to get it to work. I'm talking about ~1,300 LOC, and it still manages to surpirse the hell out of me.]

"E Pluribus UNIX." -- Tech Support Slogan
"If I had my life to live over again, I'd make the same mistakes, only sooner." -- tallulah bankhead
"The world is coming to an end... SAVE YOUR BUFFERS!!" -- Tech Support Slogan

[Listening to: Michal Amdursky - Pillow Talk - - (03:53)]
Tags:

Published at

The ILiar interface

I just got this error from the compiler:

The type or namespace name 'ILiar' could not be found (are you missing a using directive or an assembly reference?)

I was trying to type IList, and moved one key column to the left :-) I would worry about working on a project that had an ILiar interface.

"Not tonight dear.... I have a modem." -- Tech Support Slogan
"To punish me for my contempt for authority, fate made me an authority myself." -- Albert Einstein
"Never write software that patronizes the user." -- Tech Support Slogan

Tags:

Published at

About Monad

I got to play with Monad today, so here are a few quick impressions:

  • No environment variables, I tried to do a cd %windir% and it didn't expand it.
  • Auto completion for file names gives the full path, unlike cmd, which gives relative path, this is very annoying, actually.
  • You get auto completion for cmdlets (Cool), but not for .Net's namespaces (Not Cool).
  • Trying to run a script normally doesn't work: regex.msh fails, while .\regex.msh succeeds, I've no idea why, they are functionaly identical.
  • It's fun to work with.

Here is a small script that handles extracting regex expression from files:

if($args.Count -lt 2)
{
 "Arguments are: <file> <regex-pattern>"
 break
}
$file = [string]$args[0]
$pattern = [string]$args[1]
$re = new-object System.Text.RegularExpressions.Regex($pattern)
foreach ($line in $(Get-Content $file))

 $match = $re.Match($line); 
 if($match.Success) 
 {
  $match.Value
 }
}

Here is how you would get all the ifs in a script:

MSH C:\Documents and Settings\Ayende\My Documents>.\regex.msh regex.msh "(?<=if\().+(?=\))"
$args.Count -lt 2
$match.Success
Tags:

Published at

Ancient History: The origins of '\'

Larry Osterman talks about the origins of the '\' as a path seperator in the original DOS here.

One thing to note, while you can use the '/' as a path seperator most of the time, and interchange it freely in paths, it's pretty useless on cmd.exe, but it works flawlessly in Monad :-)

Tags:

Published at

Worst Job Ever

Inspired by My Worst Job & What are some crappy jobs you've worked?

My worst job was at a butcher. I was 14, I think. I worked for less than minimum wages (I think it translate to about 1.05$ an hour in today's rates) and the hours were terrible. My job consisted of taking a chicken and reduce it to edible parts. It was a good place to learn about anatomy, but the owner kept asking why I'm washing my hands so often. It's not recommended to those with queasy stomaches.

Along the way I learned that a chicken cost 30 NIS (6.5$), and a chicken I cut to parts cost around 90 - 110 NIS (20$). I quit after about a week, and it took me a while to even go near the shop. I'm proud that even after that, I'm not a vegeterain. :-)

[Listening to: תשאירי לי פרח - שוטי הנבואה - title(04:46)]

The REPL in .NET

A post in Project Aardvark biog by Benjamin Pollack contains some very disturbing ideas:

Thirdly, you can’t easily write and test just a small amount of code. In most languages, your only option if you want to do this is to write a test suite for your class protocol, which takes a lot of time during development and probably isn’t necessary for a lot of smaller stuff.

Didn't you guys heard about Test Driven Development? You can get it in most languages now aday. In .Net, the common framework is NUnit (but I like MbUnit as well). In C++, you have CppUnitLite. The issues he is describing sounds like normal legacy code and can be solved using the techniques listed in Working Effectively With Legacy Code.

REPL is nice, but it is good for playing with the langauge; to see what will happen if you do XYZ, not to verify that XYZ indeed happens. I know that Joel's Test doesn't include Unit Testing, but still...

This is sad. Benjamin, get yourself a copy of the following books and read them, you'll likely learn a lot.

Product image for ASIN: 0735619484 Test-Driven Development in Microsoft .NET

Product image for ASIN: 0596007396 NUnit Pocket Reference

Tags:

Published at

Rhino Mocks V2: Some Progress Made

I made quite a progress, mostly thanks to this article. I'm totally and completely blown away by the capabilities of Castle.DynamicProxy, it open up a whole world of facinating possibilities.

For instance, I wanted to get rid of this type of code:

MockControl mockView = new MockControl.CreateControl(typeof(IView));
IView view = mockView.MockInstance as IView;
view.DoSomething();
mockView.ReturnsFor(3, someVal);

I wanted to be able to do something much simpler, like this:

MockRepository mocks = new MockRepository();
IView view = mocks.CreateMock(typeof(IView));
view.DoSomething();
LastCall.On(view).Returns(someVal).Repeat(3);

It doesn't look like a great improvement, doesn't it? But this means that you no longer has to sync two objects for each mock. I thought a lot about how I would implement this in my code. LastCall is a static class, and has no information about the mocked instance beyond what I'm passing as an argument. I needed some way to get to the MockRepository from the mocked instance.

I though about using a static table, with all the mocked instances as keys, and the value being the MockRepository. But this has several disadvantages, chief among them are:

  • It's ugly hack.
  • It's a huge memory leak, those objects would never be released as long as the AppDomain is loaded.

What I really wanted was to do this:

public static IMethodOptions On(object mockedInstance)
{
   IMockedObject mockedObj = mockedInstance as IMockedObject;
   //error handling if mockedObj is null
   return mockedObj.Repository.MethodOptions[mockedInstance];
}

Using Castle.DynamicProxy, it was as easy as modifying the types implemented by the mocked object, and handling the type with the interceptor. It took me some time to figure it out, but when I did, it was so easy that I couldn't believe. So the above code is not possible due to around three or four lines of code. And I'm very pleased to find a new tool.

Rhino Mock: Thinking about next version...

I finally got the excuse to work on Rhino Mocks again :-)

I've a line in one of my presenters that looks like this:

IView[] toSave, unsaved = (IView[]) unSavedList.ToArray(typeof (IView));

Unfortantely, when I pass mocked IViews to this method, the following exception is raised: "System.InvalidCastException : At least one element in the source array could not be cast down to the destination array type."

The issue seems to be that Rhino Mocks is uing remoting proxies to do its work, and that doesn't sit well with Array.Copy(). So now I got two choices, I can modify the production code* so it would work with remoting proxies (basically avoiding the ArrayList.ToArray() and the Array.Copy() methods). Or, I can rip the guts out of Rhino Mocks and replace it with something that I like better. The two options I see now are:

  • either, use Castle.DynamicProxy.
  • or, write my own proxies using Reflection.Emit.

Pros for Castle.DynamicProxy:

  • It's nearly literally two lines of code.
    ProxyGenerator generator = new ProxyGenerator(); 
    return generator.CreateProxy(destinationType,new RhinoInterceptor(),source);
  • I'll be using tried and tested library with quite a bit of support.
  • I can get it out nearly instantly.

Cons for using Castle.DynamicProxy:

  • It means another library to carry with Rhino.Mock.

Pros for rolling my own:

  • It will teach me quite a bit about Reflection.Emit and IL

Cons for rolling my own:

  • I'm not likely to get it right on the first (or even second) attempt.
  • After looking at NMock's source, it looks like routine stuff, the moment you get it.
  • It'll take quite a bit of time.

Looking at it this way, I think that it's no brainer what I'll use :-)

* This is acceptable under normal circumstances, but a bug** in the mocking library doesn't fall under the defination of nomral circumstances.

** Yes, it's a bug, a mock should be just like the object it replace.

Music Player: Which To Choose?

I want to get myself a mobile player with enough storage to hold all my music, podcasts, etcs. I currently use a 256Mb player, and it's annoying to manually go and find out what I want to hear each time. Especially as I only do it at home, and I'm rarely there.

Basically, I would like to have something with 20Gb or more, easy to use on both the device and the computer application side. One major consideration is the sound quality and the volume. I'm often outside, and in my current player, it's nearly inauidable as soon there are traffic noises around. If it's the headphones that matter in such a case (as I guess it would be), they a recommendation for them would be appriciated as well.

My mother is taking a tour to the USA in a few days, so she can get me the newest and brightest. What do you recommend? Should I get and iPod? iRiver? Something else?

Tags:

Published at

Testing by Coverage

I'm going over NQA's test coverage right now. I added tests to some areas that desperately needed tests, and several code paths that weren't tested. The best parts were that I found pieces of dead code that I could just remove. As usual, ReSharper is invaluable in finding those parts.

I'm partly dog-fooding Rhino Mocks, and I got some interesting ideas for improvement, and partly to actually get a better code coverage on NQA :-) [I just thought that I've found a bug in NQA, but it was in my tests.]

I didn't have much chance to touch certain parts of the code, specifically, the SchemaEditing parts, and going over the tests is a great way to reacquaint myself with what is going on there. 

On the other hand, it's kind of depressing, I look over the list, and there is so much red there... :-( I'm currently reading Working Effectively With Legacy Code right now, and the definition there is "Legacy Code is code without tests."  On the third hand*, the book offer good advice about how to handle that. I wish I would've read it five months ago, I would've made a lot of different choices in how to bring NQA to the Fun-To-Work-With world.

I've finished reading  Extreme Programming Explained : Embrace Change (2nd Edition), and I'm not sure what to think. On one hand, it's the first book that actually made me put it down and reach for the code. On the other hand, it seems that it's not quite an introductory text but more of a guide. It wasn't what I expected, that is certain. I think I'll need to re-read that (which I don't usually do for tech books) to really grok what Kent is trying to say.

* It's pretty handy when juggling, too. :-)

Website Weekend

I was busy most weekend with building the site and adding some content. Writing that article to CodeProject took a lot more time that I thought it would.

This was the first time in a long time that I actually had to take an interest in the HTML I'm writing, especially for CodeProject but also for my website. I can't believe that it's 2005 and I'm still having to deal with this silly stuff.

 

"I haven't lost my mind; it's backed up on tape somewhere." -- Tech Support Slogan
"Any piece of knowledge I acquire today has a value at this moment exactly proportioned to my skill to deal with it. Tomorrow, when I know more, I recall that piece of knowledge and use it better." -- mark van doren
"Adieu, mes amis. Je vais la gloire. (Farewell, my friends! I go to glory!)" -- Final words of Isadora Duncan, dancer, d. 1927

[Listening to: One Answer - Mercedes Lackey & D.F.Sanders - Lovers, Lore, & Loss(02:35)]

 

Technorati Profile

The secret of high windows uptime

Is a machine that would refuse to reboot or turn itself off. I just came from one such machine, and I literally had to pull the plug to get it to restart. Even Shutdown.exe -f -r -JustWork didn't work.