Sunday, December 9, 2007

Saturday, December 8, 2007

Understanding Value of Data Value Objects

One of the critical success factors of any distributed application architecture is the decision about whether to invoke a method on remote object or to communicate with remote object using services.

This decision is highly influenced by the goal of interoperability. The technologies that allow to invoke a method on an object that is residing on a different physical machine across several layers, are usually restrictive in terms of interoperability. That is the method can be invoked by a technology specific mechanism or the output is consumable only by objects in a particular technology.

Solution to this problem is using web services.
Although, web services solve the problem of interoperability, it introduces a new problem of fine grained interfaces.

To understand the problem of fine grained interfaces, consider the following scenario:



The above diagram shows the interaction between a aspx page i.e. client and the services in order to build a UI for customer and order details.

As shown in the above diagram, in order to gather all required details to build a UI for customer and his order details, the client calls GetCustomerName(), GetOrderDetails() and GetProductDetails() methods of Customer, Order and Product Service respectively.


Hence, the client must be aware about the fine-grained details of which method of the service to invoke over the network. In other words, in this pattern, the remote objects expose a fine grained interface.




Disadvantage of fine grained interface:
In order to build a single UI, three calls to service over the network are required even in this highly simplified example. In the real world scenario, a large number of calls to service over the network will be required resulting in severe performance hit.

Solution:
Coarse grained interfaces:
When the interfaces exposed by remote objects are coarse grained, the client will deal with high-level methods like GetCustomerOrderDetails(). The method will return all the required data in single service call.

Data Value Objects (DVO):
DVO design pattern applies the concept of coarse grained interfaces.
In this pattern, the client will invoke a single service method like, GetCustomerOrderDetails(). This method will return a single DVO with all the required details.













As shown in the above diagram, a single call to GetCustomerOrderDetails() assembler service returns a DVO with all the data required for UI.

Implementing DVO:
There are many approaches to implementing DVO. Following are some of the approaches:
1. Implementing a class with attributes for DVO.


In this approach, the DVO class typically contains all the required attributes with Get, Set properties.
For example,
public class Customer
{
public string Name
{
get { return this.Name; }
set { this.Name = value; }
}
}


Advantage:
Less marshalling overhead because simple attributes


Disadvantage:
The approach requires a new class to be created for each DVO. Typically all the distributed applications requires a large number of DVO. It results in large number of classes. Thus, maintaining the attribute based DVO becomes difficult

2. Implementing a class with a generic DVO with wrapper over a simple Dataset

In this approach, class with DVO as a wrapper over a dataset is developed. The attributes of the class with still have the get, set properties. But the properties will be mapped to dataset.

For example,

public class Customer
{
public string Name
{
get { return this.customerDataSet.Rows[0][“Name”].Value; }
set { this.customerDataSet.Rows[0][“Name”] = value; }
}
}

Advantage:
i. Ease of maintenance because of dataset

No extra classes are required. For example, the Customer, Order and Product details can be added as tables to the dataset with all the required relationships
ii. Leveraging the high performance XML serialization capabilities of .NET 2.0 DataSet, reduces the marshalling overhead significantly

iii. Ease of maintenance because of dataset wrapper

The wrapper abstracts the fine grained details about the underlying data. Hence, future changes to underlying data will require changes only to the typed data set. No changes will be required to method of accessing the data as it is abstracted by a property.

Disadvantage:
Lack of type safety. An attempt to create a customer object from order table details will result in run-time error

3. Implementing a class with a generic DVO with wrapper over a Typed Dataset This approach is very similar to above approach. In this approach, class with DVO as a wrapper over a typed dataset is developed. The attributes of the class with still have the get, set properties. But the properties will be mapped to typed dataset.

For example,

public class Customer
{
public string Name
{
get { return this.customerDataSet.CustomerName; }
set { this.customerDataSet.CustomerName = value; }
}
}

Advantage:
i. Ease of maintenance because of dataset. No extra classes are required. For example, the Customer, Order and Product details can be added as tables to the dataset with all the required relationships
ii. Type Safety
An attempt to create a customer object from order table details will result in compile-time error and not run-time error.
iii. Leveraging the high performance XML serialization capabilities of .NET 2.0 DataSet, reduces the marshalling overhead significantly
iv. Ease of maintenance because of dataset wrapper
The wrapper abstracts the fine grained details about the underlying data. Hence, future changes to underlying data will require changes only to the typed data set. No changes will be required to method of accessing the data as it is abstracted by a property.


3. Passing dataset itself as DVO. In this approach, a dataset with required data is passed as DVO. The data is accessed directly from dataset.

For example,
The data will be accessed directly from dataset as
this.customerDataSet.Rows[0][“Name”].Value
Advantage:
Leveraging the high performance XML serialization capabilities of .NET 2.0 DataSet, reduces the marshalling overhead significantly
Disadvantage:
Any changes to underlying data will require changes to all tiers trying to access the data.

Summary:
In distributed applications, the DVO pattern offers a significant advantage. Of the several approaches to implement DVO, typically DVO as wrapper over a typed dataset is the most suitable option.

Wednesday, December 5, 2007

Extension Methods in C# 3.0

Extension method is new language element added to C# 3.0

Extension methods allow developers to extend the existing CLR types with methods of their own.
Without extension methods the same goal can be achieved by sub-classing the original type and adding the required method to the subclass.
However, with this approach we can invoke the newly added method only on subclass, and not on base class. But extension methods make it possible to add new method to a CLR type without having to sub-class the CLR type.

To understand how exactly the extension method works, we will develop a small code snippet to validate a US Zip Code.

To validate a zip code in C# 2.0, following is one of the possible approach:

class Validator
{
public static bool IsValidZip(String USZipCode)
{
return Regex.IsMatch(USZipCode,@"^(\d{5}-\d{4}\d{5}\d{9})$^([a-zA-Z]\d[a-zA-Z] \d[a-zA-Z]\d)$");
}
}

To use this validation logic, the caller code could be

string zip = "12345";
if(Validator.IsValidZip(zip) == true)
{
//Actions
}


Now, we will implement the same functionality using extension method.
We will create an extension method named IsValidUSZipCode.


public static class Validations

{
//Extension method

public static bool IsValidUSZipCode(this string USZipCode)
{
return System.Text.RegularExpressions.Regex.IsMatch(USZipCode,@"^(\d{5}-\d{4}\d{5}\d{9})$^([a-zA-Z]\d[a-zA-Z] \d[a-zA-Z]\d)$");
}
}

Please note the “this” keyword in parameter. It instructs the compiler to treat the method IsValidUSZipCode as extension method.

So far the code is very similar to C# 2.0 implementation.
The major difference is in the code for utilizing this extension method.

The extension methods are accessed directly from the CLR type.
So in this case, the method IsValidUSZipCode can be accessed right from String type.

To use extension method we just defined, we will simply add a using statement as follows:

using Validations;

Now, to validate zip code, add following code:

string zip = "12345";
if(zip.IsValidZip() == true)
{
//Actions
}

Note that we are invoking the extension method directly on the string type variable.

This is how C# 3.0 extension methods can be defined and used.