Is all of that architecture needed? I've always thought so
for my larger scale applications and windows-based applications, but for my web
applications I didn't think so. Since studying design patterns and
domain-driven design, I'm changing my mind as to how much is really
beneficial. The problem I saw was that business objects took longer to
develop, longer to design, and more development time to setup testing.
However, I saw the benefit that they can be tested at all, as the user
interface is hard to test with conventional unit testing frameworks (certain
testing frameworks are coming out for this).
The additional benefit is that when the application connects
to the business layer, the business layer can catch some of the problems with
the input data and handle it appropriately, whereas in an ASP.NET page, all
data has to be handled within the page and code could possibly be duplicated. The
.NET 2.0 data source control errors that are raised are not always beneficial
in explaining what the true problem really is as well.
Because of that, and the unit testing benefit, I've changed
my mind to include at least minimal business and data layer coding. Usually,
when a small project, I have a business layer that returns a DataTable object
directly to the ASP.NET page, instead of using business objects. This approach
can still make use of the ObjectDataSource that binds directly to a business
object and calls a method within it.
In the cases where the project is larger, or often with
windows-based applications, I make use of business objects in my applications,
having a factory return a single or collection of objects to the caller. I
tend not to prefer to use strongly-typed datasets, but to create the DAL code
using the Enterprise Library Data Access Application Block. The data layer
returns a DataTable from the database call to the business layer.
Alternatively, the DataTable/DataSet objects can be used to read/write Xml
data, so these objects have dual purpose. For instance, below is a possible
data layer method:
Listing 1
public DataTable GetRoles()
{
Database database = DatabaseFactory.CreateDatabase(_connectionStringName);
DbCommand command = database.GetStoredProcCommand(this.GetRolesProcedureName);
database.AddInParameter(command, "ApplicationName", DbType.String,
this.ApplicationName);
DataTable rolesTable = database.ExecuteDataSet(command).Tables[0];
}
The business layer would perform the conversion and return a
business collection as such:
Listing 2
public RoleCollection GetRoles()
{
RoleDataGateway gateway = new RoleDataGateway();
DataTable rolesTable = gateway.GetRoles();
RolesCollection collection = new RolesCollection();
foreach (DataRow roleRow in rolesTable.Rows)
{
collection.Add(new Role(roleRow["Name"].ToString(),
roleRow["Description"].ToString()));
}
return collection;
}
ASP.NET can bind business objects; however, complex business
objects can make this process complicated. In Eval statements, you can return
a class reference through the eval statement. For instance, if the property
named DbSystem returns a class instance of type Database, this statement must
be cast to access sub properties, in the form of:
Listing 3
<%# ((Database)Eval("DbSystem")).Name %>
This can make it complicated in some object-oriented
designs, especially with large object chains. What could be a better
alternative is to convert the object to an alternative data source that is a
better approach, or to create a data source control that can handle the
breaking down of the object to the raw property values it needs.
In ASP.NET, these larger-scale business solutions often use
an MVC approach, or use one of the controller patterns such as Page or Front
controller. I've used the MVC approach to one of my applications, and although
considerably harder to develop, the ability to unit test pages/user controls
and the ability to control more of the interactions through code have provided
a key benefit to ensuring the application works correctly. I hope to write an
article on this soon.