Wednesday, September 9, 2009

Throw vs Throw Ex

Just for demonstrating, if you have classes in C# as follows,

using System;
namespace WindowsApplication1 {
public class Class1 {
public static void DoSomething() {
try { Class2.DoSomething(); } catch(Exception ex) { throw ex; }
}}

public class Class2 {
public static void DoSomething() {
try { Class3.DoSomething(); } catch(Exception ex) { throw ex; }
}}

public class Class3 {
public static void DoSomething() {
try { int divider=0; int number=5/divider; } catch(Exception ex) { throw ex; }
}}}

And you call,

Class1.DoSomething();

What's the difference if you rethrow the exception using plain 'throw;' or 'throw ex;'?

Answer:

If you use "throw ex;", The stack trace is something like,

System.DivideByZeroException: Attempted to divide by zero.
at WindowsApplication1.Class1.DoSomething() in C:\WindowsApplication1\main.cs:line 15
at WindowsApplication1.Form1.button1_Click(Object sender, EventArgs e) in C:\WindowsApplication1\Form1.cs:line 103

But if you use just 'throw' instead of 'throw ex' to rethrow the same exception, that is,

public class Class3 {
public static void DoSomething() {
try { int divider=0; int number=5/divider; } catch { throw ; }
}}

And of course for all rethrow statements, the stack trace is now like,

System.DivideByZeroException: Attempted to divide by zero.
at WindowsApplication1.Class3.DoSomething() in C:\WindowsApplication1\Main.cs:line 46
at WindowsApplication1.Class2.DoSomething() in C:\WindowsApplication1\Main.cs:line 30
at WindowsApplication1.Class1.DoSomething() in C:\WindowsApplication1\Main.cs:line 15
at WindowsApplication1.Form1.button1_Click(Object sender, EventArgs e) in C:\WindowsApplication1\Form1.cs:line 103

See the difference? BTW, This concerns both C# and VB. VB docs state that in "Throw expression" the expression would be required. This is not completely true, you can use just "Throw" in VB to rethrow the same exception. C# docs do tell that in "throw expression" the expression "is omitted when rethrowing the current exception object in a catch clause".

Tuesday, September 8, 2009

Layering Architecture and Namespaces

I was wondering whether do I need to have separate namespaces for each layer, such as MyComponent.DAL, MyComponent.BO, MyComponent.Service. What are the pros and cons of having/not having separate namespaces?

I see two approaches here.

Approach #1

Separate DLLs for each component containing layers in separate namespaces (UI, Service, BO, DAL) as follows,

Component1.dll with Component_1.DAL, Component_1.BO, Component_1.Service and Component_2.UI
Component2.dll with Component_2.DAL, Component_2.BO, Component_2.Service and Component_2.UI
...
...
...
Component_N.dll with Component_N.DAL, Component_N.BO, Component_N.Service and Component_N.UI

Approach #2

Separate DLLs for each layer containing all components as follows,

UI.dll
Service.dll
BO.dll
DAL.dll

In Approach #1, addition of components is easy without affecting other modules. But in Approach #2, recompilation of whole system is needed (UI.dll, Service.dll, BO.dll, DAL.dll). On the other hand, Approach #2 facilitates easy replacement of layers.

Architect's Advice

Components are usually self contained and are deployed at only one layer, say, business logic or data access or user interface, where as modules cut across all layers.

With Approach #1,

You would be able to have module specific DLLs with need of recompiling and distribution limited to that assembly only. This will improve management and distribution and is good if you are planning to provide this as one unit of functionality to end user/client. In this model, you can scale out by deploying such components on multiple machines and is usually called vertical partitioning of application. You can easily replace one module with another or add new module as new set of functionality.

In this approach if you have to modify cross cutting concerns like change in UI framework or UI standards or introducing new UI pattern or providing centralized business rules, caching, exception, logging/tracing, transaction management, data access functionality then you will have to change each and every module/component specific dlls to incorporate this change. Additionally you will have to manage the dlls of cross cutting concerns in each and every module increasing the overall module size and you will lose on ensuring flexibility and consistency of standards for cross cutting concerns across modules.

This approach is good if you are building a small size product which you want to distribute to clients who can run it by installing locally and doesn’t need high amount of resources like CPU/memory/databases to run and you can define self contained standards for all cross cutting concerns and cross cutting concerns changes from modules to modules or clients to clients where you provide this as tailored functionality. Has limitation on scaling Up. UI, business, data access in total can consume lots of memory on the machine. Scaling out will not be possible as all are tightly coupled into one assembly.

Approach #2 has consequence of recompiling but it helps you to,

1. Maintain consistent standards and provides high flexibility for cross cutting concerns across all your layers.

2. Recommended in scenario where modules (components) are usually known upfront and incremental addition of modules is not expected frequently as against modification of functionality within module.

3. You can easily scale up and scale out by tiering approach as against approach #1.