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 13, 2005

I've encounter a numerous bad usages of try, catch and throw statements in my last 3 years in .NET so I thought to write here my "best practices" in this subject.

Before I begin, just to remind you about the "using" keyword

" The using statement defines a scope at the end of which an object will be disposed. " (MSDN)

Meaning, this code:

using (MyDisposableObject o = new MyDisposableObject())
{
   // use o...
}

Is equal to:

MyDisposableObject o;
try
{
   o = new MyDisposableObject();
   // use o...
}
finally
{
   // Don't forget, MyDisposableObject must implement IDisposable
   o.Dispose();
}

The using statement is much more "cleaner" than the try-finally(->call Dispose) block. Of course, in order to use the using statement, MyDisposableObject must implement IDisposable interface, but most of the .NET frameworks' classes which use external resources do, so no problem here.

When do I use the using keyword instead of "try-catch(-finally)" ?

In any case your code block doesn't required any exception handling (catch) and you're using a disposable object.
 
When do I catch an exception ?
 
You should use the catch statement only if you can REALLY handle the exception - meaning you want\need to "eat"(catch it and do nothing about it) the exception or you (want to)\can try to "fix" the application's flow according the exception type (call transactionInstance.Rollback() in my data-access-layer if an error occurred, for example).
 
Do NOT catch exceptions as a "default" behavior in your code !
The following code is a BAD practice in exception handling:

try
{
   //some code
}
catch(Exception e)
{
   throw new Exception("X operation error: " + e.Message);
}
finally // if exists.
{
   //some code
}

Why is it bad ? The catch statement doesn't handling the original exception, it creates a (bad)new one which means:
  1. The Stack Trace of the original exception will be LOST, which means I lose the ability to view the entire "process" (who called to who flow).
  2. In the demonstrated code, I catch an exception and re-throwing a pointless new exception. Throwing exceptions is an expensive task so you should avoid (at any cost) throwing them as long as you don't really need to !
  3. If you wrap an exception, at least save the original exception in the InnerException property (I'll elaborate later on).
When do I wrap an exception, when do I rethrow it ?
  1. You should catch and wrap the exception with a new one only if you can add INFORMATIVE data to the original exception which WILL be used later on. Writing this type of code (in my DAL) will be a smart idea usually:

    SqlTransaction trans;
    SqlConnection conn = null;
    try
    {
        // use the connection to do some DB operation
        
        trans.Commit();
    }
    catch(Exception e)
    {
        if (trans != null)
            trans.Rollback();
        
        // Wrap the exception with DALException
        // I can check if e is SqlException and by the e.Number -
        // Set a "clean"(show to user) message to the DALException.
        // I can add the full "sql" exception in some custom property, 
        // I can determine which stored procedure went wrong, 
        // I can determine the line number (and so on).

        throw new DALException("clean message to the user", e);
    }
    finally
    {
        if ( conn != null && conn.State == ConnectionState.Open )
            conn.Close();
    }

    Why is this code smart ? Because I call the Rollback() in case of an error, which will ensure "clean" database. Because it "hides" the original SqlException which allows me, at my Business Layer, to catch a generic DALException which will abstract the Business Layer from the Data Access Layer. Because I CAN add more informative data to the exception so the Business Layer could send the GUI (to show the user).

  2. You should rethrow the exception if you catch-ed it but you "found out" that you can't really handle it:
    try
    {
        // do some code...
    }
    catch(Exception e)
    {
        if (e is SqlException)
        {
            // Add more information about the exception and
            // throw a new, more informative, exception:
            throw new DALException ("more data", e);
        }
        else
        {
            // I can't handle it really, so I'm not even going to try
            throw; // <-- look at this syntax ! I'll explain later on
        }    
    }
     
    Calling throw; will bubble the original exception (including its' Stack Trace) - this will actually "cancel" the catch statement.
When you wrap an exception, you should *almost* always use the "InnerException" property
 
When you wrap an exception, you should save the original exception as InnerException:

try
{
}
catch(Exception e)
{
   throw new MyCustomException("custom data", e);

   // OR

   MyCustomException mce = new MyCustomException("custom data");
   mce.InnerException = e;
}

This will preserve the original stack which will be important for later debugging.

 

Any Insights you want to share with me ?

Posted by Oren Ellenbogen 
13/09/2005 11:16, Israel time UTC+03:00,     Comments [2]  | 
# Sunday, September 11, 2005

Searching Oren Ellenbogen in Google placed me on the third(3rd!) place !
It's a huge progress if you keep in mind that just last week I was at the 15th place (second page, at the middle)...

update [14.09.2005]:

I'm at the first place now ! Respect !

Posted by Oren Ellenbogen 
11/09/2005 12:36, Israel time UTC+03:00,     Comments [1]  | 
# Saturday, September 10, 2005

Man, I had a lot on my mind during the previous week.
The week began with installing my application in one of our client's server which was pretty hard task due to couple of unexpected incompatibilities - lack of local IIS(meaning - no debugger!) and AD(Active Directory) complicated tree structure. This two alone are a major headache for any programmer, but I'm glad that it's behind me now (another happy customer, I LOVE IT!). The week continued and I had to fix some nasty bugs in a couple of applications which I'm responsible for, which turns out nice - there is nothing better than a good bug and a good solution (IMHO anyway).

I spent the end of the week to prepare for my presentation on the next week. I'm going to talk about DHTML, XML and XMLHTTP with my co-worker Roee(which is going to talk about Javascript and the server-side .vs. client-side pros & cons) in one of IDF computers' unit. It's a huge time consuming task to organize a decent power-point presentation, a few demos and a set of exercises and most importantly - organize my time properly. But again, I can't complain because I love giving presentation and work a little on my speaking abilities and time organization abilities.

In addition, I'm working now on Localization and Member-Roles Management solutions for our new ASP.NET 1.1 application. I know those requirements have built-in solutions in ASP.NET 2.0, but the client demanded ASP.NET 1.1 so unfortunately I can't use them yet.

btw - I'll upload the presentations, demos and exercises about XML\DHTML\XMLHTTP at the end of next week, maybe it will save one of you some time.

OK, back to work...

Posted by Oren Ellenbogen 
10/09/2005 04:38, Israel time UTC+03:00,     Comments [2]  | 
# Sunday, September 04, 2005

Hey y'all,

I can't seem to stop, those add-ins bastards are too addictive !
Oh well, here are more great VS.NET add-ins you should all check them out:

  1. GhostDoc - This great utility will able you to "auto" document your methods\properties with a single mouse click.
  2. WhidbeyCommands 2 - Just read the man's post :) TIP: if you give presentations while using the VS.NET, you MUST download this baby (check out "Demo font" option) !
  3. HandleWhiteSpace - Clean your files from unnecessary white spaces.
peace.
Posted by Oren Ellenbogen 
04/09/2005 09:08, Israel time UTC+03:00,     Comments [5]  | 
# Saturday, September 03, 2005

Sometimes we have to close the window after our screen logic has executed, so usually we're writing window.close(); in our page BUT this causes this message to arise -

close_areyousure.gif

If you want to avoid this message, simply write:

window.opener = window;
window.close();

Posted by Oren Ellenbogen 
03/09/2005 11:29, Israel time UTC+03:00,     Comments [1]  | 

It's possible to use built in keywords in order to mark some lines in you code for later reference. For example, I use the "TODO" keyword as a remark over a set of lines I know I'll have to change later on -

todos.gif

As you can see, my TODO task is now appearing at my Visual Studio .Net "Task list" which is great for a constant reminder.
As default, the Task list shows only the "Build Errors" so in order to support other keywords you'll have to (mouse)right-click over one of the table headers ("Description" for example) -> Show Tasks -> All (or any other suitable option). In addition, you can select how to sort the results by (I use "Priority").

* If you want to change the custom tasks priority or names - go into Tools-> Options... -> Environment -> Task List.

Posted by Oren Ellenbogen 
03/09/2005 11:13, Israel time UTC+03:00,     Comments [0]  | 
# Tuesday, August 23, 2005

It stroke me today at the train (on my way home) while I was reading a book named "Object Thinking" (by David West); I'm at chapter 7 which is talking about discovering the client domain, i.e what does he(the client) expect from the application. In short, although it's hard(especially if you're a technical person in your nature), you must understand the client's requirements without casting it to your world "I'll implement it with web-service" or "This is a classic multi-threading application"; You're job in this initiatory step is just to analyze the client's needs and trying to depict his world in simple "objects" world; What are my primary entities (for example: "Employee", "Employer", "Agreement" etc), what are the relationships between them and how the client expect to "activate" those entities (screens functionality).

I remembered my meeting with our last client and reading this stuff made me think about how well (?) did I managed to handle this task. While the client was depicting his world to me I was trying to understand and write his requirements and his special needs from the application. I've noticed that writing down the client's needs\remarks\requests sometimes stopped the conversation flow, caused needless repetition over the question & answers and sometimes even got me out of focus.

So, maybe tape-recording the entire meeting(well, the important stuff anyhow), concentrating on asking the right question and analyzing the answers later can create a better characterization ? better understanding of the client's domain ? shorter and more thorough meetings ?
It seems like a good idea, I think I'll give it a try on my next meeting.

What do you think?

Posted by Oren Ellenbogen 
23/08/2005 08:58, Israel time UTC+03:00,     Comments [2]  | 
# Sunday, August 21, 2005

Did I mention that I'm working with a well known hacker ?
Well, It's about time, so I present to you - Amir Markowitz aka "The Hacker".

Amir taught me today how to send javascript commands directly through the address bar !
Look at the "damage" he did to my site !

redbackground1.gif

As you can see, he managed to change the background color in one simple command.

Think about changing Page_IsValid property or performing __doPostBack("","") through the address bar -

javascript:void(Page_IsValid=true); __doPostBack("","");

This could be deadly if you don't perform Server-side validation as well !

 

 

Posted by Oren Ellenbogen 
21/08/2005 12:35, Israel time UTC+03:00,     Comments [0]  | 
# Saturday, August 20, 2005

Read this post by the legendary Brad Abrams and watch the videos you're interested at. I've seen "Designing Inheritance Hierarchies" and "Enabling Development Tools" videos (for the moment) and I promise that you can learn a thing or two as well ;-).

Happy learning...

update:
I thought it will be interesting to write my notes from the Designing Inheritance Hierarchies video, so here it is:

  1. Interfaces don't allow backward compatibility ! Let's assume we have to following interface

          public interface IMyInterface
          {
               void MyMethod();
          }

    Now let's assume that I have MyClass which inherits from IMyInterface. If I'll decide to add a new 
    signature to the interface, MyClass will be broken (TypeLoadException will be thrown in compile time).

  2. Base Classes version better than interfaces - if MyClass was inherited from MyBaseClass instead of IMyInterface I wouldn't have a problem to add new signatures to the class without causing the inherited classes to break.
  3. If you must inherit from 2 "root" classes, the recommended pattern is:

          public class A {}
          public class B {}
        
          public class C : A // Let's assume that A is "more" root to C than B
          {
             public B BInstance
             {
                get
                {
                    // return B class instance.
                }
             }
          }

  4. You can use Interfaces in "private" way via Explicit declaration:

      public interface IMyInterface
      {
         string ReturnSomething();
      }

      public class MyClass : IMyInterface
      {
          string IMyInterface.ReturnSomething()
          {
            return "oren";
          }
      }

      Now, when you create a new instance of MyClass, you won't see 
          ReturnSomething method on the public view:

      MyClass.gif

      Though, you can always call this method simply by casting c to IMyInterface:

      MyClassViaCasting.gif

      This can be useful if you want to "hide" some of the interfaces' abilities in your 
          class. This is recommendable if you don't want the "clients" to use a 
          certain behavior directly
through the class. 
         .NET framework use this ability in Int32 structure:

      int i = 5;
      i.ToString() // work
      i.ToInt32(); // don't work.
      ((IConvertible)i).ToInt32(); // work !

      " This member supports the .NET Framework infrastructure and 
        is not intended to be used directly from your code. " 
      (from MSDN, Int32.IConvertible.ToInt32 method)

 

I hope I've managed to give you some insights, just enough to convince you to start viewing these videos.

Posted by Oren Ellenbogen 
20/08/2005 06:21, Israel time UTC+03:00,     Comments [0]  | 

I'm currently using a .resx file at my projects to contain my friendly client's messages. I'm reading from this file via ResourceManager class which allows me to supply consistent messages at my GUI layer, e.g for every successful delete in my application you'll get the same message format "The {0} was deleted successfully" - in my "Workers" form you'll see The worker was deleted successfully and in my "Cars" form you'll see The car was deleted successfully;

I've encounter the SR (String Resource) Generator a week ago and I thought to give it a try. So, what is SR generator ?

" This custom tool allows the generation of a resource class (and optionally .resx file) from either a .resx file, or the Microsoft SR.strings file. "

I think that a simple example will show the tool's capabilities.

  1. I've downloaded the source which also includes the .msi file and installed it.
  2. I've added a file named SR.strings to my web application:

             SRGSolutionOnAdd.gif

  3. I've used the "Custom Tool" option and call SRCodeGen - this is an EXE which will parse your .strings file.
             SRGFileProperties.gif
     
  4. Next I've edit the SR.strings file -       

      [strings]
      Worker = Worker
      ItemDeleted(string itemName) = The {0} was deleted successfully.
      ItemAdded(int itemId, string itemName) = The {1} was added successfully, it's new ID is: {0}.

      [strings.he]
      Worker = עובד
      ItemDeleted(string itemName) = ה{0} נמחק בהצלחה.
      ItemAdded(int itemId, string itemName) = ה{1} נוסף בהצלחה, מספרו החדש {0}.

  5. I've saved the file in UTF-8 format, for Hebrew support.
             SRGFileEncoding.gif
     
  6. Rebuild the web project, this will cause the SRCodeGen to generate required files:
  7.                   SRGGeneratedFiles.gif
  8. Now lets use the SR class which was generated for us, here is my usage of it 
  9.          PageMessage.Text = SR.ItemDeleted(SR.Worker); // In my Worker.Delete()
     
             OR
             
             PageMessage.Text = SR.ItemAdded(newId, SR.Worker); // In my Worker.Add()
     
  10. Finally we can select the SR.Culture we want to use, so the messages will be formated in the correct language. This can be done easily be calling:
                  SR.Culture = new System.Globalization.CultureInfo("he");
   
                  OR
 
                  SR.Culture = new System.Globalization.CultureInfo("en");

         You can put this code in your Global.asax.cs in Application_Start method or 
         change it at any time, according to your needs.

 

This tool is a MUST in my opinion for two main reasons:

  1. IntelliSense, IntelliSense, IntelliSense ! (don't you love it ?!?!).
  2. Changing the messages Culture requires only one line of code, simple as that.
Posted by Oren Ellenbogen 
20/08/2005 01:10, Israel time UTC+03:00,     Comments [0]  |