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, August 08, 2006

While I was sitting in McDonald's today, eating some junk-burger, I looked across my table and noticed a beautiful girl. Man, she was something else. A true beauty. I looked at her walking to another table, 20 fit from my table and sitting down. In front of her was a woman. Try to guess on your own, how does the woman look like:

a. A true super-hot-mama, even more beautiful than her daughter(?).
b. Good looking woman.
c. An OK woman.
d. My GOD! What a monster ?!

I'll let you ponder for a few seconds...

Now that I'm sure you've got the right answer, have you ever thought about these questions:

In 15 years, will this beautiful girl will look like her mother(?) ?
Is there any chance that god is just messing with my head and she'll be a fine woman even if her mother(?) is a....
What about statistics? Anyone knows what are the odds for a beautiful girl to become a beautiful woman ?

And of course, a sick question to recap this self-debate:

What does her father think about this situation ?

For some strange reason, I started to think about applications. I know, I'm sick, no doubt, but bare with me: How many small beautiful applications you developed, become a monstrous Enterprise Applications that are eating their programmers for breakfast ? Go back to my questions and replace the word "girl" with "small application" and the word "mother" with "Enterprise Application". I think that this symptom of "growing organism" exists in developing real applications and we encounter it every day when we maintain legacy code or patching-up a system that shouldn't survive the prototype phase.

I guess that just like in life, with good monitoring of our state and good activities, this transformation, this growing, could still be graceful.

I just wonder what are the odds...

Design | Life
Posted by Oren Ellenbogen 
08/08/2006 07:34, Israel time UTC+03:00,     Comments [4]  | 
# Tuesday, July 25, 2006

Our SQLink R&D department was merged with Aman Computers.

At the moment, I'm still not sure if my place is at Aman although I've got a very nice offer from them and it seems like a very nice place to be at.

I'm looking for a place with (my ideal, I'm a realistic guy though):

  1. Many people who love coding, read about it, write about it and lecture about it.
  2. Building Enterprise applications.
  3. Using the newest technology (.Net 2.0+)
  4. A place that loves to teach his employees, to set goals and to push you through crises.
  5. Provide me the stage to show what I am capable of, where managers trying to bring out the best from their people.
  6. Organic teams. I would like to be one of a great team of people. I work better with other people around me and I love sharing my thoughts and teaching others.
  7. Agile methodologies.
If your place is looking for a passionate-for-code guy, someone that can upgrade the surrounding and contribute to the "team's glue", I would be glad if you'll contact me via email (oren dot ellenbogen AT gmail dot com) so we can chat. In addition, I'm *interested* in relocation(especially in the US, I've got a citizenship(+visa\green-card)) as it always been a dream of mine.
Posted by Oren Ellenbogen 
25/07/2006 11:55, Israel time UTC+03:00,     Comments [9]  | 
# Sunday, July 23, 2006

After talking about testing inner behavior inside a method, it is time to make some observations about the code and answer a lot of *why* questions. I must give credit to Shani, one of a great bunch of people I worked with during my service and a very good friend of mine. He asked me some hard questions that bother every TDD newbie or a TDD wannabee as myself (raise your hand if you're one of them.. higher!). Now I'll take my shot and reply in detail.

Question 1: Is it worth spending time on tests for simple methods ?

I've talked about "code little, think and code little" and why we need it in my last post "TDD in the eyes of a simpleminded: Part 1 - The NameResolver". One of the great comments I received was "You spent more time on the tests than on the (simple)method itself. Isn't it time consuming? You've just talked about focus on deadlines in your preface..". From my experience, the easy, 5 minutes, methods are the one you spend most the time thinking about(relatively). You keep saying to yourself "this is so easy... such a shame" and spend a full hour thinking about a various of problems that can happen and various solution to handle them: " Maybe I'll use array? no... maybe List<int>? no... Oh! Yes! I'll use an interface! I'll call it IMyCollection and make a nice method in it named "AISolveProblem(params object[] anyThing)" ". This all process take place before you even write your first line of code! It's a 5 minutes, even-a-lame-monkey-can-do-it method. You don't want to look stupid and leave "open holes" right? So you waste a great deal of time over-thinking the irrelevant. Classic.

Sure, TDD can be costly (depends on a few variables), but it makes you code along the challenges(tests) and always challenge you to come up with the simplest solution. minimum effort. It prevents you from thinking too much upfront; You don't have to think too much about avoiding potential bugs, just write test cases and make them green. Don't have red tests ? Your code is ready for production. Again, I'm not going to address the big questions like "when, how and how much?" at the moment and I'm not saying that you should TDD the entire application. I'm just stating a point here. Keep your head open for a new way of coding. That's the best I can request from you and that is what I'm doing now, during the learning process with Roy.

Question 2: Changing the class because of our tests, is that a good thing ?

I think that if the time comes and you need to change the way your class looks or behaves just because your tests become hard to write, you should lay back and smile. That means that the process of TDD just helped you design your code better. If the test was too hard to write, you must be doing some uncomfortable API (usability warning) or maybe you've put too much knowledge in one place and created a GOD(do-it-all) method\class. Having 5+ dependencies in one class should make you stop and rethink about the way you work right? testing actually makes you write the API before you actually write the implementation itself. If the early API sketching is too hard, just think about the poor programmer which will have to work with your API, about yourself (if it's hard to test it must be hard to write) and even better - the miserable programmer which will have to take over your code and maintain it later on.

Question 3: Injecting concrete implementation can lead to incorrect usages! Why do we need it?

Let me start by relaxing you - injecting concrete implementation of an interface *can* lead to serious bugs and malfunctions in your application. Let me repeat it. By providing the programmer the ability to "inject" his implementation for the class dependencies he can cause the application to die. It might even cost you your job.

Relaxed?

No? But you should be! I've just demonstrated the worst case scenario and if we'll think about it together, the world is not over and you and I still got our jobs. Programmers can make mistakes while using any API. Damn it, I've asked my boss for hiring machines but he keeps bringing people who actually use their head. You see, I don't trust the "next guy" no more than you do, but I realize that I can take care of the low-level (in Hebrew: BARZELIM) API and still provide the high-level API which will help the idiot(brighter than me) next guy a simple method for any complex scenario. We need an option to inject our dependencies as we don't want to couple our classes together.

We want the option to replace one concrete implementation with another (fake one, for example). This doesn't prevent me from developing some nice & simple API that will wrap the all thing up and inject the dependencies I want.

Question 4: Writing tests can lead to bugs in those tests? should I write tests for my test?

Sure you do! you have to test your tests, and then test those tests and than test the latter one just until you will run out of RAM, space on your HD or energy.

Writing code can lead to additional bugs to your system just as living can cause death(No research shows it does by the way). We can minimize the chance of bugs in our tests by following some simple rules:

  1. The test should be obvious by it's name (I follows Roy's tip: MethodName_State_ExpectedResult).
  2. A test should check one method only.
  3. A test should Assert only once.
  4. Writing new tests should be easy and take no more than a few lines (few != 50).

I wrote "should" and not "must" as we should eat healthy food, it's not a must (unless you eat burgers 24-7, in that case, you are a goner). You should come up with the rules that fit you and your team. You can enforce them to keep a follow a few rules just to create a standard you all(or just you, no one said we are living in a democracy) agree on.

TDD
Posted by Oren Ellenbogen 
23/07/2006 12:07, Israel time UTC+03:00,     Comments [2]  | 
# Saturday, July 22, 2006

I've attached the code I demonstrated so far to the original posts so you could play with the code a little and understand how it all connects (if code samples in my posts were not clear enough).

Requirements:

  • Nunit 2.2.8
  • TestDriven.Net (this is actually an extra, but give yourself a break and download this gold)
  • Visual Studio .Net 2005

Code (inside the posts):

TDD in the eyes of a simpleminded: Part 1 - The NameResolver

TDD in the eyes of a simpleminded: Part 2 - Testing inner behavior

Have fun !


p.s:
in every additional post I'll publish about "TDD in the eyes of a simpleminded" I will upload the code.

TDD
Posted by Oren Ellenbogen 
22/07/2006 11:22, Israel time UTC+03:00,     Comments [0]  | 
# Friday, July 21, 2006

code:

OrenTDDWorkShop_Part2.zip (44.06 KB)

If you haven't read about the NameResolver at my previous post(TDD: Part1), now is the time as I'm going to take this class and use it later on in this post.

We are ready to take the next step and talk about "playing a doctor". Imagine this picture: you are a doctor looking for a gun's bullet in one of your patient's stomach. He was shot a few moments ago. "One bullet to the chest" the nurse inform you. It's all messy and you can't find the bullet. You need to clear the blood, move the organs, going micro-level on the details so you don't hit a vein on the way. Every mistake is a "welcome-better-place" for your patient and you don't want this on your conscience do you ?

While developing applications, we are facing a world of "playing doctors". We need to change inner behaviors in our code or others code. We want the application to live the surgery and we realize that the smallest change in a "core method" can make the application bleed all over the place without even noticing it. Every click on the keyboard raises our heart rate. But how can we check inner code inside a method? How can we get a micro-level look at the method's internals, at the stomach of our tested object ?

This is what I'm going to address at this post. But before we see solutions, let's talk about the client's requirements so we'll have something to play with.

Client's requirements v1.0:

A class named HotelReservationService is required. In it, a method named ReserveRoomForTwo that receive the couple's name in the format "[man] and [wife] [family name]". The method will reserve the room and name the room under the family's name. The method will return ReservationInformation object with the details (room, floor number & status).

  • If the received couple's name is empty ("") - Throw an exception with "The couple name must be supplied".
  • If the hotel don't have available rooms, the returned ReservationInformation should hold a status of "NoRoomAvailable".
  • if the everything goes well, the method should return a ReservationInformation filled with the floor number, room number, reservedFor (filled with the name of the family) and status of "RoomReserved".


Simple solution, without TDD:

public class HotelReservationsService
{
   public ReservationInformation ReserveRoomForTwo(string coupleName)
   {
      // .... some checks ...

      NameResolver resolver = new NameResolver();
      string familyName = resolver.GetFamilyName(coupleName);

      HotelRepository repository = new HotelRepository();
      return repository.
ReserveRoom(2, familyName); // 2 = two people
   }
}

As you can notice, we have 2 dependencies here: NameResolver and HotelRepository. We need to test ReserveRoomForTwo but how can we do it ? the results of our tests for this method are coupled with the implementation of NameResolver and HotelRepository. If they have bugs in it, it will certainly affect our tests and therefore making them *unreliable*. What's the point in writing tests if you doubt that a green(successful) result might actually be red(fail) under the surface due to an inner bug in one of the dependencies?

Keeping with my metaphor, the dependencies are the blood and organs laying around and making it harder for you to find the bullet, may it be a bug or a new feature. You need to clear(isolate) the area so things will be easier to see. You need a green light you can actually *trust*.

We'll need to use Dependency Inversion Principle(DIP) to isolate our tested class from the actual implementation of its dependencies.

Our goal:

Inject dummy object instead of the dependencies and make them "act like" everything is good\bad according to our need. Will use DIP to make it happen.

We don't want to test NameResolver nor HotelRepository. We assume that they are bugs-free. We need to test one and only one class at a time. Our goal is to test the interaction between our tested class to its dependencies.


Let's use TDD to solve the client's requirements:

Say hello to your new friend: geek, this is Stub; Stub, this is geek. Come on, don't be shy, give him a hug, he will serve you well in time. Feel nice and fuzzy ? great, now let's TDD this baby. Oh, and don't worry, if you don't understand the concept of "Stub" yet, everything will be clearer in a few moments. Just think about Stub as a dummy object.

We start with? Come on! I want to hear it from you! we'll start with a Create method!

[TestFixture]
public class HotelReservationsServiceTests
{
   [Test]
   public void Create()
   {
      HotelReservationsService service = new HotelReservationsService();
      Assert.IsNotNull(service);
   }
}

As usual, in order to compile this method we'll need to create an empty class:

public class HotelReservationsService
{
}

Let's run the test - 1 passed, 0 failed. Good.

Let's write our second test and look to our requirements:

[Test]
[ExpectedException(typeof(ArgumentException), "The couple name must be supplied")]
public void ReserveRoomForTwo_EmptyCoupleName_ThrowEmptyCoupleNameException()
{
   HotelReservationsService service = new HotelReservationsService();
   ReservationInformation info = service.ReserveRoomForTwo(string.Empty);

   // We've got nothing to assert. We expect an exception to raise.
}

This will not compile as we don't have ReserveRoomForTwo method nor ReservationInformation class. Let's write them down:

public class ReservationInformation
{
   private int m_roomNumber;
   private int m_floorNumber;
   private string m_reservedFor;
   private string m_status;

   public ReservationInformation(string reservedFor, int floorNumber, int roomNumber, string status)
   {
      ReservedFor = reservedFor;
      FloorNumber = floorNumber;
      RoomNumber = roomNumber;
      Status = status;
   }

   public string ReservedFor
   {
      ... get & set ...
   }

   public int FloorNumber
   {
      ... get & set ...
   }

   public int RoomNumber
   {
      ... get & set ...
   }

   public string Status
   {
      ... get & set ...
   }
}

Now let's add the ReserveRoomForTwo method to our HotelReservationsService:

public ReservationInformation ReserveRoomForTwo(string coupleName)
{
   throw new NotImplementedException("");
}

Compile. Run tests - 1 passed, 1 failed. Our test expect for ArgumentException with a specific message but we throw NotImplementedException. Let's fix it.

public ReservationInformation ReserveRoomForTwo(string coupleName)
{
   throw new ArgumentException("The couple name must be supplied");
}

Run tests - 2 passed, 0 failed. Good.

Time for refactoring our tests as we create the HotelReservationsService in two methods. This time, instead of creating a "FactoryMethod" named GetNewHotelReservationsServer like we did in our NameResolver tests, let's use the [Setup] attribute.

[TestFixture]
public class HotelReservationsServiceTests
{
   HotelReservationsService service;

   [SetUp]
   public void SetupTest()
   {
      service = new HotelReservationsService();
   }

   [Test]
   public void Create()
   {
      Assert.IsNotNull(service);
   }

   [Test]
   [ExpectedException(typeof(ArgumentException), "The couple name must be supplied")]
   public void ReserveRoomForTwo_EmptyCoupleName_ThrowEmptyCoupleNameException()
   {
      ReservationInformation info = service.ReserveRoomForTwo(string.Empty);
      // We've got nothing to assert. We expect an exception to raise.
   }
}

Let's continue to check our requirements: We want to represent a case where the provided couple's name is good but the hotel is full.

[Test]
public void ReserveRoomForTwo_HotelIsFull_ReservationInformationWithStatusNoRoomAvailable()
{
   // We create a dummy repository and set the values we want it to return.
   FakeHotelRepository repository = new FakeHotelRepository();
   repository.StatusToReturn = "NoRoomAvailable";
   service.SetRepository(repository); // Important! set the fake repository in the service.

   
string
goodCoupleName = "man and woman FamilyName";
   ReservationInformation info = service.ReserveRoomForTwo(goodCoupleName);

   Assert.AreEqual("NoRoomAvailable", info.Status);
}

Run tests - 2 passed, 1 failed(our last one).

We get an exception here which is obvious (we hard-coded "throw new ArgumentException...") instead of a status "NoRoomAvailable". Notice that we are create a FakeHotelRepository and injecting it to our tested class. The purpose is to create a repository which will always return "NoRoomAvailable". We want to test the *interaction* between our ReserveRoomForTwo method in our tested object to the repository. This can look bizarre but let's remember that we want to test only our ReserveRoomForTwo method and not the repository class.

Let's make our test green. minimum effort.

We need some sort of HotelRepository in order to know if the hotel is full. At the moment, we don't need the NameResolver as we are looking for the status only. Let's define an interface named IHotelRepository.

public interface IHotelRepository
{
   ReservationInformation ReserveRoom(int capacity, string familyName);
}

This time we need to build the "basics" so the minimum effort will be a little more than we use to, but that's OK as we'll do it only once. Let's add this code to our HotelReservationsService class:

private IHotelRepository m_repository;

private IHotelRepository Repostiory
{
   get 
   { 
      if (m_repository == null)
         throw new ArgumentNullException("Repostiory", "Repository must be set before being used");

      return m_repository; 
   }
   set { m_repository = value;}
   }
}

public void SetRepository(IHotelRepository repository)
{
   Repostiory = repository;
}

Now we can use the repository in our ReserveRoomForTwo method:

public ReservationInformation ReserveRoomForTwo(string coupleName)
{
   if (coupleName == string.Empty)
      throw new ArgumentException("The couple name must be supplied");
   else
   {
      ReservationInformation info = this.Repostiory.ReserveRoom(2, coupleName);
      return info; // just so we'll remember that we return ReservationInformation.
   }
}

We call the repository and ask it to save a room for the received couple. All we left with is to create the FakeHotelRepository object:

internal class FakeHotelRepository : IHotelRepository
{
   public string ReservedForToReturn = "";
   public int FloorNumberToReturn = 0;
   public int RoomNumberToReturn = 0;
   public string StatusToReturn = "";

   public ReservationInformation ReserveRoom(int capacity, string familyName)
   {
      return new ReservationInformation(ReservedForToReturn, FloorNumberToReturn, RoomNumberToReturn, StatusToReturn);
   }
}

This class will sit in the tests project and will be used for testing only. Notice that we can manipulate the data we want to return from this repository. Remember: we want to test the interaction between the classes. We assume that the repository in production was tested and will be able to "know" if the hotel is really full or not. We make a fake one so we can control the internal behavior. We are playing doctors: Assuming that the repository is OK, will our class still behave as we expect ?

We can play with the repository and look at the results we get. Will do the same with the NameResolver later on.


Run the tests - 3 passed, 0 failed. So far, requirements 1 and 2 are set.


What is Stub then ?

stub is an object that helps you test another object. You never ever Assert the stub itself.
You use it only as an helper while you're looking to test another object.

In our example, the FakeHotelRepository is a classic stub. We use it to assert another object - ReservationInformation.


Let's take a pause here as this post cover a lot of material and code. The next post will answer the third requirement and I'll present additional solution for the problems we encounter here.

TDD
Posted by Oren Ellenbogen 
21/07/2006 12:57, Israel time UTC+03:00,     Comments [4]  | 
# Wednesday, July 19, 2006

After being poetic on my TDD preface post my good friend Moran, a geek with no shame, gave me a few poetic titles for future(?) posts:

"web.config - friend or foe?" (this one kills me, honestly ;-))

"yellow screen - a blessing in disguise."


Can you beat him down ? Have some issues you want me to talk about ?
Have some geeky titles to share with the rest of the geeks that follow my posts ?


Bring it!

Posted by Oren Ellenbogen 
19/07/2006 01:01, Israel time UTC+03:00,     Comments [0]  | 

If you didn't read the preface yet, I strongly recommend you to invest good 5 minutes for it now; I'll wait...

Code:

OrenTDDWorkShop.zip (37.09 KB)


the NameResolver:

This class should have a method named GetFamilyName that gets a string as parameter and return the last name of a person.

The client defines these requirements:

  • If the sent string is empty (""), the method should return "None".
  • The string can contain only one word - in this case, return that word.
  • The string can contain first name and last name separated by space between them. The method should return the last name (obviously).

Simple enough right ?

Let's TDD this thing. We start with a "Create" test:

[TestFixture]
public class NameResolverTests
{
   [Test]
   public void Create()
   {
      NameResolver c = new NameResolver();
      Assert.IsNotNull(c);
   }
}

This code doesn't compile as we don't have NameResolver class yet. This test will check that we have an empty constructor for NameResolver and that we can actually initialize it. So let's write the required code:

public class NameResolver
{

}

Run the test. It works. It's time to test our GetFamilyName method. Let's see if the first requirement works:

[Test]
public void GetFamilyName_EmptyString_ReturnTheWordNone()
{
   NameResolver c = new NameResolver();

   string actualResult = c.GetFamilyName(string.Empty);
   Assert.AreEqual("None", actualResult);
}

Notice the structure of the method:

MethodName_State_ExpectedResult

This will not compile as we don't have the method GetFamilyName, so we'll make the minimum effort to make it compile.

public class NameResolver
{
   public string GetFamilyName(string fullName)
   {
      throw new NotImplementedException("");
   }
}

Now it compiles. Nice. Let's run the test. 1 passed, 1 failed(our last test).

Let's refactor the method so it will pass, remember, minimum effort.

public string GetFamilyName(string fullName)
{
   return "None";
}

I know, it doesn't make sense at first. The trick here is "baby-steps". You will add new code or refactor existing one only if you have a test that prove you *need* to do so. Our tests pass without problems so we don't have to modify our GetFamilyName. It works as expected so far!

Before we are running along and writing another test that will fail let's make some refactoring. We can do it with peace as we have tests to run after we change our code. In my tests you can see a line that repeat itself which is "NameResolver c = new NameResolver();". We don't like initializing new objects in the tests method as this initialization can get complex later on and we don't want to change X test methods. Refactoring:

[Test]
public void Create()
{
   NameResolver c = GetNewNameResolver();
   Assert.IsNotNull(c);
}

[Test]
public void GetFamilyName_EmptyString_ReturnTheWordNone()
{
   NameResolver c = GetNewNameResolver();

   string actualResult = c.GetFamilyName(string.Empty);
   Assert.AreEqual("None", actualResult);
}

private NameResolver GetNewNameResolver()
{
   return new NameResolver();
}

Compile - Good. Run tests - Good. That was simple.

Let's carry on and prove ourself that GetFamilyName is not good:

[Test]
public void GetFamilyName_OneWordOnly_ReturnThatWord()
{
   NameResolver c = GetNewNameResolver();

   string actualResult = c.GetFamilyName("test");
   Assert.AreEqual("test", actualResult);
}

Perfect, run the test - 2 passed, 1 failed (our last one)

expected: <"test">
but was: <"None">

This is quite obvious, we return None no matter what. Let's fix it. remember, minimum effort.

public string GetFamilyName(string fullName)
{
   if (fullName == string.Empty)
      return "None";

   return fullName;
}

Run tests - Good! Now that the tests were OK, we can refactor (we have the tests as our backup - to see that we didn't introduce new bugs). You can see that the lines of GetFamlyName("...") and the Assert repeat itself. Let's extract this into a private helper method and use it:

[TestFixture]
public class NameResolverTests
{
   [Test]
   public void Create()
   {
      NameResolver c = GetNewNameResolver();
      Assert.IsNotNull(c);
   }

   [Test]
   public void GetFamilyName_EmptyString_ReturnTheWordNone()
   {
      NameResolver c = GetNewNameResolver();
      VerifyGetFamilyName(c, string.Empty, "None");
   }

   [Test]
   public void GetFamilyName_OneWordOnly_ReturnThatWord()
   {
      NameResolver c = GetNewNameResolver();
      VerifyGetFamilyName(c, "test", "test");
   }
   
   private
void VerifyGetFamilyName(
      NameResolver nameResolver, 
      string fullNameToCheck, 
      string expectedResult)
   {
      string actualResult = nameResolver.GetFamilyName(fullNameToCheck);
      Assert.AreEqual(expectedResult, actualResult);
   }

   private NameResolver GetNewNameResolver()
   {
      return new NameResolver();
   }
}

VerifyGetFamilyName will help us to write smaller test. We want the option to write a new test with only a couple of lines. Adding new tests should be fun.

Let's move on.

Now we don't have bugs anymore right? we do ?
prove it!

Here you go:

[Test]
public void GetFamilyName_TwoWords_ReturnLastWord()
{
   NameResolver c = GetNewNameResolver();
   VerifyGetFamilyName(c, "one two", "two");
}

Run test - 3 passed, 1 failed (our last one).
It makes sense, we don't check for space character yet so Let's fix it with minimum effort (remember?).

public string GetFamilyName(string fullName)
{
   if (fullName == string.Empty)
      return "None";
   else if (fullName.IndexOf(" ") == -1) // no spaces
      return fullName;
   else
   {
      string[] words = fullName.Split(' ');
      return words[1];
   }
}

Run tests - Good !

Hold on, you think you're done but you're not. The client adds another requirement (things change, you know):

  • the string can contain 3 words - first name, middle name and last name; Separated by space, of course. Return the last name (obvious).

We have a bug! How do I know? Here you go:

[Test]
public void GetFamilyName_ThreeWords_ReturnLastWord()
{
   NameResolver c = GetNewNameResolver();
   VerifyGetFamilyName(c, "one two three", "three");
}

Run tests -  4 passed, 1 failed(our last one). Let's fix the method so our last test will work. minimum effort.

public string GetFamilyName(string fullName)
{
   if (fullName == string.Empty)
      return "None";
   else if (fullName.IndexOf(" ") == -1) // no spaces
      return fullName;
   else
   {
      string[] words = fullName.Split(' ');
      return words[2];
   }
}

Run tests - 4 passed, 1 failed (GetFamilyName_TwoWords_ReturnLastWord()). Oops! our last test passed but I screwed up our previous test (to two words scenario - "one two"). This is a great thing with TDD, you cover your ass with tests! Let's refactor:

public string GetFamilyName(string fullName)
{
   if (fullName == string.Empty)
      return "None";
   else if (fullName.IndexOf(" ") == -1) // no spaces
      return fullName;
   else
   {
      string[] words = fullName.Split(' ');
      return words[words.Length-1];
   }
}

Run tests - 5 passed, 0 failed! Good!


Conclusions:

We want to work with ~100% code coverage. That means that every piece of code in GetFamilyName method is accounted for. I don't add new features to this method until I have a test that shows it is required. In addition, look at our GetFamilyName method, the code is so simple you want to cry with joy. Instead of thinking about all the possibilities to screw this method up at the beginning, write your "bugs" and see if the method can handle it. In addition, let's say that the client request another feature ("I want to allow sending names in Hebrew and names in English. The GetFamilyName should be able to handle them both". You can change whatever you need (but with minimum effort) and you've got the tests to see that everything is still ticking as expected. Refactoring is something you can do here with a smile on your face. You don't have to be afraid changing the code. The well known sentence "But what if I'll create 5 other bugs?!" is no longer valid. You've got the tests to tell you "You're OK!".

Good tests = peace of mind.

TDD
Posted by Oren Ellenbogen 
19/07/2006 12:33, Israel time UTC+03:00,     Comments [5]  | 
# Tuesday, July 18, 2006

I sat down for about 15 minutes before I could even write this sentence.

You see, as human beings, we (usually) tend to think too much before we speak.
As programmers, we (usually) tend to think too much before we write our first line of code.
"But what if the programmer will send null?"
"What if the programmer will send string when I expect int? should I throw an exception?"
"Should I return int or maybe void will do?"
"Should I implement the feature in this class? maybe I should use some external object and implement it there?"
"Should I inherit from this class or encapsulate it?"

We tend to over-think stuff. That's the way we are wired.

Tell me if you can relate to this monologue:
" I'm putting a lot of effort in finding solutions to many problems before they appear. These effort makes me tired so a few "end-cases" still slips me by; This, of course, only makes me think more before I write my code. Little, not-more-than-1-day-max missions turn into "Projects". The frustration when something breaks for unknown reason is sky-high as I spent 1-2 days just to think about how to avoid these bugs! I simply don't have enough time. I'm working like hell but the day is just too short and I've got too many tasks to complete. "

I remember sitting with my last team leader, Pasha, in the office one evening(~3 years ago), after spending 12 hours in refactoring something that never actually worked; His words were: " Oren, you fell in love with your code. You're spending way too much time on things that... are not really important at the moment.... If you keep it up this way, you'll never finish your task. "
I remember my response, his words were like a knife in my heart: " Hey! I put my guts in this code, I've stayed the all week for more than 14 hours per day! I even sat at home during the weekend and worked on this task just to keep up with the deadline! you can't tell me that this is not important! Someone can use this some day! And the design is so extendable! "Not really important..." (bad, bad, dirty thoughts) ".

He was right. I couldn't make the deadline. It was a battle I couldn't win; I had to much work and almost no time at this point.

I remember that day like it was a few hours ago. I couldn't sleep the all night. I kept running scenarios in my head and analyzing his words. I thought about the way I worked until that point, about the times I managed to complete my tasks in time and those times I worked extra hours and still miss my deadlines. I could really see what he meant. I wasn't able to think in small tasks. I connected every little piece of code with 1000 other usages "that could be used someday". I thought that I could make it all work at once. I thought that I can prevent bugs from happening. The reality proved me otherwise.

I knew that I can get better, so I set my mind on "think less, do more". I needed some basic rules to contain my need to over-think, so I use these simple rules to make my life easier:

  • I refactor only when I see a tangible reason (2 places with the same code).
  • I think in small "Contexts" (=tasks). No context should be bigger than 1-1.5 days of work.
  • I'm trying to WIN *small* battles.
  • I write some API usages, test that API with my programmers (to see if it's comfortable enough) and only than starting to code it.
  • I participate others when things get a little more complicated than they should be.
  • I write my milestones on my white-board so I could look at them during the day.


This is the mantra behind TDD.
TDD is about letting things go. To Work in small tasks and most importantly:

Let the *code* prove you wrong, not your thoughts or fears.


I don't have a bug until I can write a test that proves me otheriwse.
With this said, we can now start practicing TDD. Let's write NameResolver class.

* As this post turned to be quite long, you can see the example here.


clarification
: if it wasn't obvious, the simpleminded is yours truly.

TDD
Posted by Oren Ellenbogen 
18/07/2006 09:19, Israel time UTC+03:00,     Comments [0]  | 
# Sunday, July 16, 2006

This is another brilliant idea from Juval Lowy. I got to see him speak about unify ASP.NET and WinForms security models last week and during the session (which was really great by the way, but that's for another day), I've notice this genius row:

public event EventHandler<EventArgs> Click = delegate {};

Isn't it a beauty ?!

I know, it doesn't ring a bell yet, so I'll make the picture a bit clearer. But before we move forward, let's take a few steps backward.

Starting from scratch, a reminder:

We want to raise our Click event.
I'm sure you are familiar with these lines:

private void OnClick(EventArgs e)
{
   if (this.Click != null) // check if the invocation list is empty
      this.Click(this, e);
}

The reason we do it is we we don't want to raise an event with an empty invocation list; This will raise an exception, which is a big no-no if we can avoid it. simple ah ?

This implementation is problematic as between the check (if statement) and the activation the listener can be removed. A quick fix will look like this:

private void OnClick(EventArgs e)
{
   EventHandler<EventArgs> handler = this.Click;
   if (handler != null) // check if the invocation list is empty
      handler(this, e);
}


Ok, so it's a little safer invocation now (I remember a version with locking, but the above will do for now).

Rewind:

Now let's get back to Juval's genius line I've showed before:

public event EventHandler<EventArgs> Click = delegate {};

attaching delegate{} to the invocation list will create (behind the scene) a class, with a random name, with an empty method (matching EventHandler<EventArgs> signature), with a random name.

Why is this so brilliant ? Because now we verified that the the event invocation list is
always filled with *at least* one (empty)listener.

We can't clear the empty listener as we don't have it's instance (it was generated for us) nor it's name.

The checks for not-empty invocation list can be thrown to the garbage. We now have a safe event, guaranteed.

This is certainly a best practice for working with events (following Framework Design Guidelines structure):

   Do   Consider attaching an empty delegate to your event.


Recap

public class MyClass
{
    public event EventHandler Click = delegate {};
    
    private void OnClick(EventArgs e)
    {
        // no need to check if (this.Click!=null)
        this.Click(this, e);
    }
}

nice and easy.


Extra: one more step for safe events:

If we're talking about safe events, there is an advanced scenario in which you want the "eat" exception raised by one of the listeners, so the the other listeners will still be triggered. In the above, any exception in one of our listeners will stop the triggering of our invocation list.

The solution is quite simple also:

private void OnClick(EventArgs e)
{
   EventHandler<EventArgs> handler = this.Click;
   if(handler != null)
   {
      Delegate[] list = handler.GetInvocationList();

      foreach (Delegate del in list)
      {
         try
         {
            EventHandler<EventArgs> listener = (EventHandler<EventArgs>)del;

            listener(this, e);
         }
         catch { }
      }
   }
}

Juval even wrote a cool generic utility class named EventsHelper which you can get here.

Brilliant.

.NET | Design
Posted by Oren Ellenbogen 
16/07/2006 10:13, Israel time UTC+03:00,     Comments [6]  | 
# Saturday, July 15, 2006

I'm having 1-on-1 coaching with Roy Osherove on TDD coming up in the following 2-3 weeks. My goal is to practice real TDD work process to determine if our department can benefit from this developing methodology (or as a design tool).

I've read a big bunch of articles and blogs (Jeremy D. Miller, Sam Gentile, Scott Bellware, Roy Osherove and others) about TDD and even practiced it for a bit during the last two years, but to be sincere, it wasn't a real Test Driven Development. I stopped TDD-ing in the middle and moved back to write-with-haste, switched to TDD and so forth. I was lazy and I had no one to guide me through. I had to "guess" the right process and to read a big set of articles to see if I'm on the right track. I was lacking of some good feedback.

This 1-on-1 with Roy should give me a clear insight about the process and immediate feedback. If the process will prove itself, we'll arrange a 3 days course for my department and try to fit TDD to our development process (where and how I'm still not sure, but I've got the feeling that I'll be smarter in a few weeks).

What is SEE Infrastructure all about ?

SEE stand for: Simple Expression Engine which I've wrote about before.

I came up with SEE as I wanted to SEE what sort of filter the GUI requests from our Data Services.

I'll give you an example for a client's request and a solution based on our old infrastructure and how SEE changed the picture.

Example:

Let's imagine we have a screen with one GridView. Our goal is to show all the (1) active orders (2) from today with (3) price bigger than 1000 NIS. It should be easy as counting 1,2,3 right ?

-- OLD --

With our old infrastructure the code will look something like this:

(1) Orders.aspx:

OrdersFilter filter = new OrdersFilter();
filter.IsActive = true;
filter.Date = DateTime.Today;
filter.Price = 1000;

EntityCollection<Order> orders = OrdersService.Instance.Get(filter);
// ... bind orders to our GridView ...

(2) OrdersDal.cs:

in our Data Access Object for the Orders entity, we're required to override a method which builds the dynamic SQL based on the given filter:

if (this.Filter.IsActive != null)
{
   query.Append(" AND Orders.IsActive = @IsActive");
   paramaters.Add(DbServices.CreateParameter("IsActive", SqlDbType.Bit, this.Filter.IsActive));
}

if (this.Filter.Date != null)
{
   query.Append(" AND Orders.OrderDate = @Date");
   paramaters.Add(DbServices.CreateParameter("Date", SqlDbType.DateTime, this.Filter.Date));
}

if (this.Filter.Price != null)
{
   query.Append(" AND Orders.Price > @Price");
   paramaters.Add(DbServices.CreateParameter("Price", SqlDbType.Double, this.Filter.Price));
}

Now, look at the 2 lines marked in red. The filter at the GUI sent Price = 1000 while the DAL object looks for Price > 1000 (remember, this is the client's request).

Not only we've got a mismatch, the coding wasn't trivial nor "easy". We had to know(=remember) what method to override at our OrdersDal.

-- New --

Orders.aspx:

FilterExpression filter = new FilterExpression();
filter.Where(
   Where.EqualTo(Order.Field.IsActive, true),
   Operator.And(),
   Where.EqualTo(Order.Field.Date, DateTime.Today),
   Operator.And(),
   Where.GreaterThan(Order.Field.Price, 1000)
);

EntityCollection<Order> orders = OrdersService.Instance.GetByExpression(filter);
// ... bind orders to our GridView ...


That's it. No mismatch - the GUI programmer can now see exactly what results the Orders Service will return and no need to look at OrdersDal.
Coding was short and fun.


I thought that this small but important infrastructure will be a nice platform to practice a "Real-World" work with TDD. The infrastructure at its current form is working quite well so I know how to API should look in general and what are my "big" problems (Mapping, Resolving db function names and a few more).

Is SEE revolutionary ?

Hardly!
Expressions like languages are all over the place lately:

  1. LINQ - to be honest, this is a really great query language but it ruined my Visual Studio .Net 2005!! The product requires some installation that simply is a disaster for a developer station.
  2. HQL - Nhibernate. This is actually very nice but I get no errors during writing.
  3. eSql - Looks great. is it safe for production? I'm not so sure... anyway, it's all with C# 3.0 and suffers from symptom (1).

I can add additional 2-3 infrastructures to the list but you get the picture.  

So why do I\you still need SEE for ?

SEE is an home-made infrastructure which was developed by the KISS (keep it simple, stupid) principle. I know that there are many folks out there who still write\generate custom Data Access Objects. Integrating SEE in your custom DAO objects will be very simple as the infrastructure gives a solution to a very narrow problem domain. There is no need to learn a new "quotation marks prisoner" language. The developer can enjoy the VS.NET IntelliSense and as you could see in my previous example, the API is very easy to understand.

Moving toward one of the other languages\technologies can take some time as the learning curve can be quite high.

You could SEE with a very small time investment by your side.


Where do you come along ?

I will upload any code I'll write during this coaching lessons so you can see our progress, bit after bit. In addition, I'm going to write a prolonged post after each lesson, to share with you my insights. This is the interesting part though - my infrastructure will change according to your requests (well, some of them anyway, and only the "good" and "simple" ones ;)). Feel free to suggest new features or to change method\classes names\relations. This will able me to practice changes to our SEE infrastructure as part of the TDD practice.

I hope that we'll enjoy the process and learn new things on the way,
Oren.

Design | TDD
Posted by Oren Ellenbogen 
15/07/2006 0