What's hot ? (and I mean really ...) - scroll down for more
1).  Code Templating - advanced usage of delegates & generics: my slides & demos are available for download! CodeProject article is also available.

2).  My series "TDD in the eyes of a simpleminded" is in progress(including code!): preface, part1, part2, Q&A 1, Manual Stub .vs. Mock Stub

3).  TDD Workshop: SeeCompass v0.1 and v0.2 are out.
 Tuesday, September 12, 2006

Source Code:

RhinoMocksExample.zip (94.18 KB)

You will need to download and install Nunit 2.2.8 and RhinoMocks(for .Net 2.0) in order to run the tests.

Background:

Not as usual, we'll start with the code and continue with it's UnitTests.
We have a single, simple class named MailService. This class contains one method named MailText(string textToMail, params MailInfo[] mailList) that looks like this:

public class MailService
{
   private IMailValidator m_mailValidator;
   public IMailValidator MailValidator // setter, getter

   public void MailText(string textToMail, params MailInfo[] mailList)
   {
      foreach (MailInfo mail in mailList) { //I know I can collect addresses...
         ValidationResult validationResult = this.MailValidator.Validate(mail);

         if (!validationResult.IsValid)
            throw new ArgumentException("Invalid mail: " + validationResult.ValidationMessage, "mail");

         // Send the email somehow...
      }
   }
}

And here is the IMailValidator, MailInfo and ValidationResult:

public class MailInfo {
   public string Address; //not best practice
   public MailInfo(string address) { this.Address = address; }
}

public class ValidationResult {
   public bool IsValid; //not best practice
   public string ValidationMessage; //not best practice

   public ValidationResult() { IsValid = true; ValidationMessage = string.Empty; }

   public ValidationResult(bool isValid, string message) {
      IsValid = isValid;
      ValidationMessage = message;
   }
}

public interface IMailValidator {
   ValidationResult Validate(MailInfo mail);
}

That is pretty straightforward I hope.


Testing inner behavior:

MailService.MailText has one dependency to IMailValidator. One way of testing our MailService.MailText method is via manual stub implementation of IMailValidator. Let's examine the tests and then look at the manual stub I've created.

1). Manual stub based testing:

[TestFixture]
public class MailServiceTests
{
   [Test]
   public void MailText_OneValidEmail_MethodWorks()
   {
      MailService service = new MailService();
      MailInfo mail1 = new MailInfo("valid@mercury.com");

      service.MailValidator = new StubMailValidator();

      service.MailText("Enlarge your 'memory stick'", mail1);
   }

   [Test]
   [ExpectedException(typeof(ArgumentException))]
   public void MailText_OneValidEmailAndOneInvalidEmail_ThrowException()
   {
      MailService service = new MailService();
      MailInfo validMail = new MailInfo("valid@mercury.com");
      MailInfo invalidMail = new MailInfo("invalid.com");

      service.MailValidator = new StubMailValidator();

      service.MailText("Enlarge your 'memory stick'", validMail, invalidMail);
   }
}

And here is the simple StubMailValidator in one of it's versions: (This stub was developed after the first test(MailText_OneValidEmail_MethodWorks) was written)

public class StubMailValidator : IMailValidator
{
   public ValidationResult Validate(MailInfo mail)
   {
      ValidationResult res = new ValidationResult(); //default: valid.
      if (mail.Address.IndexOf(".com") == -1) {
         res.IsValid = false;
         res.ValidationMessage = "The email address must end with .com";
      }

      return res;
   }
}

NOTICE: Manual stubs with inner logic can be devastating !

As you may or may not notice, this stub has a bug in it. Just look at the second test on the "invalid.com" MailInfo. This is an invalid email address and yet, our stub will say that it's valid and fail our second test. This is extremely dangerous! It is one of the things that makes people afraid from Unit Testing. When your stub need to switch his response according to a given parameter(s) based on some logic, you better switch your manual stub with dynamic\generated stub. You don't want any test-related logic outside of your test method. Let's look at mocked stub testing.

2). Mock stub based testing:

I'm using Oren Eini's (aka Ayende) RhinoMocks for simulating "controlled" implementation of IMailValidator. That means that you are creating some dynamic implementation of IMailValidtor and you are telling it how to act when the tested method calls it.

Let's look at our first test:

[Test]
public void MailText_OneValidEmail_MethodWorks()
{
   MailInfo validMail = new MailInfo("valid@mercury.com");
   ValidationResult validValidationResult = ValidationResult(true, string.Empty);

   // ------ (1) -------
   MockRepository mocks = new MockRepository();
   IMailValidator validator = (IMailValidator)mocks.CreateMock<IMailValidator>();
   Expect.Call(validator.Validate(validMail)).Return(validValidationResult);
   // ------------------

   service.MailValidator = validator;

   mocks.ReplayAll(); // Make sure the mock object is ready to "respond"

   service.MailText("Enlarge your 'memory stick'", validMail);

   mocks.VerifyAll(); // Make sure everything was called correctly.
}

(1) - This is the important stuff. I'm asking the MockRepository to create a new Mock from IMailValidtor type that our MailService expect. The line in bold tells this story: "listen dear mocked validator, if someone calls your Validate method with the parameter validMail - please send him back validValidationResult object". If we know that our validator will be called twice - we'll have two lines with Expect.Call as needed.

One of our main purpose in UnitTesting is to test one method (and one method only) and see if it behaves correctly if it receive a certain data. We also want to check the stomach of the method, what happen if our tested method calls another method(dependency) that return "1" - will it still behave as expected? Via Mock object I can control the dependency object's result easily inside the test. This make it very easy to detect bugs in contrast to our manual stub that sits somewhere else, outside of our test.

Recap:

If you have a dependency to some other object and your manual stub start to contain logic, you should mock that dependency and control the returned values in the same place you write your tests via mock object.

Bonus (delegates style Interaction Based Testing):

[Test]
public void MailText_OneValidEmail_MethodWorks2()
{
   MailInfo validMail = new MailInfo("valid@mercury.com");
   ValidationResult validValidationResult = ValidationResult(true, string.Empty);

   RunMock<IMailValidator>(
      delegate(IMailValidator validator, MockRepository repository) {
         Expect.Call(validator.Validate(validMail)).Return(validValidationResult);

         service.MailValidator = validator;
         repository.ReplayAll();

         service.MailText("Enlarge your 'memory stick'", validMail);
      }
   );
}

private void RunMock<TObjectToMock>(MockedProc<TObjectToMock> func)
{
   MockRepository mocks = new MockRepository();
   TObjectToMock obj = (TObjectToMock)mocks.CreateMock<TObjectToMock>();

   func(obj, mocks);

   mocks.VerifyAll();
}

private delegate void MockedProc<TObjectToMock>(TObjectToMock mockedObject, MockRepository repository);


Enjoy!
 | 
Posted by Oren Ellenbogen 
12/09/2006 12:30, Israel time UTC+03:00,     Comments [1]  | 
 Monday, September 11, 2006

We are writing .Net classes that will have to be used by COM objects. Therefore, we had to mark our objects with GuidAttribute and implement an interface that match every method we want to expose. In VB.NET Project, there is a COM Class which my colleague friend, Doron really like and is missing in C# Project. I decided to make a "C# COM Class" template so here you go:

C# Com Class.zip (7.92 KB)

Install:
Put the zip(don't extract it!) in: %USERPROFILE%\My Documents\Visual Studio 2005\Templates\ItemTemplates\

Usage:

1). Open a new instance of VS.NET 2005 and create a new C# Class Library Project.
2). Right-Click on the project -> Add -> New Item...
3). Select C# COM Class.

csharpcomclass.gif

4). Now insert a name, let's say: MyClass.

csharpcomclass_example.gif

* The namespace will be auto' generated by the project's default namespace.

Enjoy.

Posted by Oren Ellenbogen 
11/09/2006 06:02, Israel time UTC+03:00,     Comments [1]  | 
 Friday, September 08, 2006

"Inline Search is an extremely useful free add-on for Internet Explorer that mimicks Firefox's search behavior i.e. it turns searching into a web page into a non modal research experience coupled with a search as you type facility. It integrates flawlessly into IE (version 5.5 or above), giving it that little extra that makes you a lot more efficient when you are looking for a specific piece of information." (via Core Services)

This add-on is fantastic !

You can download it here.

Posted by Oren Ellenbogen 
08/09/2006 02:19, Israel time UTC+03:00,     Comments [3]  | 
 Thursday, September 07, 2006

I can't think about a better phrase to describe the latest songs in the industry. Listening to the radio makes you switch between the stations like you have some kind of disease; The songs lost all their meanings and instead we are swamped with "catchy" songs that we hate, but just can't live without whistle them every 2 minutes or so. Just listen to Justin Timberalke's latest song - "SexyBack", this is all about the catchy music, the words are completely irrelevant and you can't even hear the singer as the drums block his(?) voice(I'm not sure it's even Justin's voice). Does Justin OK with this kind of music? I'm not sure, but I *hope so. It still makes me think a lot about the way I worked until now and the way I'm working today; I really believe that being a programmer is as artistic as being a singer or a writer. There were times in life that I felt we are writing code just to make half-baked applications and ship them out to the mass(our clients), the quality was peripheral, and it conflicted with my "artistic"-self values. Are you familiar with that feeling ? There were also times of elation, when our code was beautiful, pure, magical. It made me smile talking about it later on. Working on a big product, at Mercury, and talking with the (amazing)guys at work, made me feel how lucky I am. Thankfully, I'm still in a position in life that I can made an influence, although I'm not naive and fully aware to the fact that clients are always right and $$$ will dictate deadlines and features packs. There is one sentence I keep saying to the guys working with me (since I was 16) - "be proud of your code". Write your name in big, CAPITAL LETTERS, at the beginning of your files, make sure everyone knows YOU did it. This will push you into excellence (you don't want others looking in your code and swearing your mom, do you? update: your mom says "no!") and inspire you to think about better, more creative and unique solutions instead of ad-hoc, ugly "But hey, it works!" solutions.

So, please, don't let **marketing or money dictate your life. Everything in Life is a trade-off, but you should decide your path, don't walk silently in a path carved by others even if it's easier. At the end of the day, saying "But I had to" or "But it's shorter" will not make you sleep better at night; If you like what you're doing, I'm sure that you are familiar with the feeling.


* I know. he is rich & famous, he must be happy. Does he ? maybe...
** Unless this is your decision, which makes it OK. As long as it is your choice.

Posted by Oren Ellenbogen 
07/09/2006 09:31, Israel time UTC+03:00,     Comments [1]  | 
 Friday, September 01, 2006

A few months ago, I lectured before Microsoft C#/C++ User Group about advance usage of delegates, generics and anonymous methods. The audience was great and I got really nice feedback. I was talking with my good friend Pavel a few days ago about lecturing in general and he made an excellent point: I should have done more "rounds" with this lecture. This could have been good experience for me to learn from the feedback I got and use it into practice before different audience. So, would you like to hear me present for ~1.5 hours about those topics (after "work hours", say 17:30+) in your "home"(=working place)? All I need is a projector and a working air conditioner(I don't have 3 built-in fan as my computer have, unfortunately). You can look at the lecture syllabus here and there are code samples and presentation(ppt) file of the entire thing right here. Of course, there should be a minimum number of people attending as I don't want to drive for an hour just to talk with 2 people (actually, I do, but this won't be very productive and bad usage of my time, so I'm sorry folks).

Minimum knowledge required to participate: good understanding of .Net 1.1 is a must; .Net 2.0 - bonus.
Lecture ("MS")Level: 400. (technical hardcore stuff, no SOA will be presented, I promise).


Drop a comment or send me an email (oren dot ellenbogen at gmail dot com) and we'll set a date.

Posted by Oren Ellenbogen 
01/09/2006 01:44, Israel time UTC+03:00,     Comments [0]  | 
 Thursday, August 31, 2006

Let it be no mistakes, I'm not a great interviewer and definitely not an experienced one but I've got really strong opinions about the way interviews should go and the questions "style" that should help you screen your candidates. It's not only "good" .vs. "evil" questions that I want to talk about here. It's the attitude and the fun of the process. Yes, you read it just right: interviews should be FUN.

Money is an interview's killer.

Money is ego. ego turns to hostility. hostility lead to bad questions. bad questions screen the wrong people. bad people is bad code. bad code is no fun. no fun is plain boring. boring is death. death is no fun. infinite loop. break;

I went to a few places after leaving my last company. What's the first thing you get after entering the building? Right! A form to fill! In some of the places, there is a cute line "desired pay: ______" in between the other lines of personal information. So you write something up (you can always leave it blank, but it will be the first question you'll be asked in those places, so save your breath), fill the rest of the form and returning it. Nice. So far, have I managed to hit 95% of your interviews experiences?

Next step. "Please sir(in Hebrew it sounds a lot WORSE, it's something like "this way man, hurry", but with a big smile), meet our HR girl(always a girl, and 99% of the time, she takes your mind out of the job)". You go in. Talk for a bit and than it arise: "Wow! X money! really?! maybe you slipped a 0 at the end ? no? oh... That is really a lot! are your sure? You do? oh....". I just hate it. I can't help to think:"Do you know what is a variable that you speak about money! I can be the next Don Box and you yabbing about money!?!" Yes, it's bullet number 1 in the "negotiations for dummies" book (I wonder if such a thing exists). So you explain and you argue and if you're convincing you continue. "Please sir ("faster you killer-budget" in Hebrew, and that smile again), lets meet our Team Leader\CTO". And what is the first thing that happens there? You know the answer ? Wow? Who told you? Oh.... you've been there haven't you?

"Hey [cute girl's name], Let me see the form he filled.... hmmm... I see.... "...
And of course, he is thinking inside "what?! that's is double than what I earn! and I'm the frickin' best in the industry!... Ok bastard, bring it on, you say you worth it ah? let's see..."

Kiss your interview goodbye. You can be Brad Abrams or Juval Lowy. It doesn't really matter. You are at war and sadly you can't win this one. You are either stupid to get what you want and arrogant to even request it or too arrogant for saying the right answers all the time.

One of the reason, among 1000 more reasons, that I've chosen Mercury as my new home was for that reason. We didn't talk about $$$ until the far end (after 2.5 technical interviews, 1 management interview and 1 HR interview). They were really interested in ME, not it the paycheck I request.

A very good comment will be "But what if we can't pay him that much? Isn't it a waste of time to go so far and at the end say to him that he requests more than we can offer". I'm with you guys. Every company has their budget. Limits should be set, no matter(?) how good this person is. But at least don't let the interviewer see anything related to money! It shouldn't bother him! And I've seen this pattern in so many places. What a shame. It happened to me in two places and I immediately "turned off" at the beginning. I knew that I'm not going to be a part of such a place and did my best to show the "better than you and still earn less" that tried to play it rough that I can raise to his challenge. After all, I want to have fun in interviews, no matter how bad it goes. My tip for you is: Let it be known, good places do exists, and good guys have a room there, just be patient and have the confidence in your abilities. Don't be afraid of bad interviews, it's good experience and it can be fun. Play your best game.


State of mind.

This is tricky, read the next paragraph and than think about it with your eyes closed.

Imagine that you are at work now, and doing the stuff you like so much. Think about the things you made that make you happy and proud, about the people you met that made you a better person and a better worker. Consider how in one hour you managed to write 10 hours work. Think about the happy customers you made. Smile. Now open your eyes.

What comes through your mind? What made this all possible? I don't know about you, but my feelings were:

1. The people. What a bunch of great people. I love them all. They enrich me and make my time better. This is my 2nd home.
2. The challenge. So many great things to think about during the day, so many challenges to figure out, so many small wins in a long but glorious battle. so many loses, but so many insights.
3. Pride.
My code means something, I 100% believe in it. I'm proud of my code and I'm working hard to worth the respect from my friends at work.

this is just from the top of my mind, no re-write here. this is the set of mind you need to set for your interviewee in order to achieve "good interview" experience. You're questions must let him understand that he could be a part of a great bunch of people, that challenges will be there for him and so is help and friendship. You should let him know that HIS thoughts and HIS answers and questions are important in this interview. You should let him know that pride is there for reach. We all love a good word here and there. You should let him understand that this can be his new home.

Remember the feeling you had after you open your eyes. That should be the interviewee's feeling at the beginning of the interview and during it. I explicitly mentioned the word "beginning" as people are nervous at the beginning, so it's extremely important that you'll start slow and let the interviewee know that you want to get to know HIM, no matter how bad\good he\she* answers your questions.

Good .vs. Bad questions.

These are a few questions that only the "best" (my best) companies asked me and I feel that it's important to share them with you. Good questions are question with space. think about driving to your work at morning. You wake up and listen to the radio: "Road 5 is jammed between this and that". "Oh... So I would probably drive in road number 2 and cut to road number 4... It's longer(length) but faster". Roads give you space to decide. Usually. Good questions are the same. The (interviewee's)answer is irrelevant (you can always ask someone how to get to ThatIsTheOne st. if you nearby) as long as his mind is set for the right questions and answers. If he is not in the right path, help him out a bit(to an extent of course). For the interviewers among you, please, If there is one thing I would like you to take from this post is this: You are interviewing someone else, not yourself. That is why good questions allow the interviewee the space to let the interviewer konw what he thinks, may it be a complete joke. If it will be supplied with good reasons, than damn - I want this guy on my team. He is creative! I would not think about this option by myself.

Good personal questions I love to hear to start with:

"Tell me about an API of some class you wrote. What was the purpose? Is it(the class) good? how do you know? Would you change it now if you could, if so - why? Are you proud of that class? Tell me why."

"Do you read books\articles in the subject(any subject that you think is fit)? if so, tell me about a thing or to you picked up and how did it affect your work? tell me about something you found in one resource that you couldn't find in any other place. Why do you think it's only there? Do you write things yourself? Why? Do you enjoy it?"

"Do you love doing what you're doing? Tell me about it, why do you love it so much? do you take things "to bed"? do you love to think about work after work hours? do you think that this is a good thing?"

"Did you made a change in the last place you worked at? If so - tell me how. Are you proud of that change? Do you like to change places you work at? Did you get recognition about it? If so - did you enjoy it?"

"Why do you think you are good at what you're doing? Please give me examples of what makes you more special than the "next guy". What are you really good at? Do you think that it's possible for you to get better at it? Can you teach others? do you enjoy it?"


This should let you a good look at the inside of the interviewee, about his true nature, his true character. There is no fear here. No mistakes. Every answer is OK. This is simply how he\she is wired. I would always start with these questions as they will set the right mood. After talking about his personality and a little digging through his code, we can decide that the personality is not suited for the team and tell him goodbye or we can go a little deeper into the technical stuff.

Technical questions style I love to hear:

I love thinking questions (surprise surprise). Show a given algorithm and let the interviewee tell you what he believe that this code does. Talk about general syntax and basic patterns and see if he follows. Don't let him know if he is correct or not at the beginning, no fun in that.

Try to focus on algorithms instead of hardcore-"who cares?!" questions. Remember, it's all about space. If there is no place for multiple choices and multiple answers, you are doing it wrong. Always try to give hard questions in between, something nice that will show the interviewee that we are having fun, but we also mean business. Try to challenge and guide him for the solution. Always, always, let him get to the solution by himself, help him only with clues until he figure it out.


To recap, I am a big fan of Logic\Tree\Recursive solutions\Object Oriented\Design Patterns questions rather than "what this line of code will do: int i=10; i = i++*++i;". There are variety of questions out there, pick the ones you like the most and have a nice list of them so you can change the questions from time to time.

People make the company. Your interview should leave you with the best people and those (best)people should want to work for you after that interview. Invest time teaching your employees how to make interviews for others(if they need to have that skill). Hiring is the company's core, no less.


* I'm sorry if I wrote he instead of he\she somewhere in this post. We are all son of God(are we?).
Posted by Oren Ellenbogen 
31/08/2006 03:56, Israel time UTC+03:00,     Comments [3]  | 
 Wednesday, August 16, 2006

This (very)little beauty is getting along quite nicely. I'm going to work quite a bit on it in the following days so keep tracking...

source:

Lnbogen.SeeCompass_v0.2.zip (205.34 KB)

 | 
Posted by Oren Ellenbogen 
16/08/2006 01:08, Israel time UTC+03:00,     Comments [0]  | 
 Tuesday, August 15, 2006

Hey guys & gals,

After a few intense interviews and a great time talking about things I just love (code, code, code), I did it.  

I'm very proud to inform you that I've join Mercury as a programmer at the Performance Center product

 

 mercury_logo.gif

" Mercury Performance Center™ is an enterprise-class application performance testing platform. It provides a complete, on-demand optimization solution for your application performance process, integrating load testing with diagnostics... Mercury Performance Center is the platform on which you can base your quality initiative. Mercury Performance Center delivers a 24x7, globally accessible and shareable pool of load testing resources to minimize the total cost of load testing in the enterprise "


Man, I'm so eager to start !!!

Posted by Oren Ellenbogen 
15/08/2006 11:30, Israel time UTC+03:00,     Comments [7]  | 
 Friday, August 11, 2006

After sitting with Roy during our last meeting, we managed to write some neat tests and code and the SEE(Simple Expression Engine) infrastructure started to crystallized. Roy even managed to refactor the name of my infrastructure and brought a brilliant suffix - SeeCompass. SEE is like a compass that helps you navigate in the ocean of data; man, I think that the web-bully will not be happy with this phrase.

If you don't remember what is SeeCompass all about read this post.

Source:

Lnbogen.SeeCompass.zip (156.39 KB)

How to start:

1. Open the solution (I know, revolutionary).
2. Open Lnbogen.SeeCompass.Framework.Tests project.
3. Open the file FilterExpressionTests.cs under FilterExpression directory.
4. Jump to the test Build_EmptyFilter_EmptyString (remember the method name structure: MethodToTest_MethodState_ExpectedResult).
5. Move on to the next test, one at a time.


I know, it can be a little hard to grasp the "entire picture" at the moment, but the tests should give you a good pick at the future.
As always, I left one failing test which will lead to a very drastic refactoring (BetweenExpression should have more than one parameter) - this will give me an entry point to continue.

 | 
Posted by Oren Ellenbogen 
11/08/2006 06:59, Israel time UTC+03:00,     Comments [0]  |