Is There Business Logic in Your Middle Tier?
By Jonathan Goodyear
Most Web developers are familiar with the concept of an n-tier application. Although "n" implies three or more tiers, three is the standard: user interface, business logic, and data. In Classic ASP, the user interface tier consisted of HTML tags interspersed with VBScript to build the page layout. The data tier was a database such as SQL Server. The business logic tier sandwiched in the middle, however, was often horribly underused.
In most Classic ASP Web applications I've seen, the business logic tier really didn't have any "business logic" in it. It merely consisted of stored procedure (or embedded SQL) calls wrapped inside Visual Basic pass-through components. In fact, the only reason Classic ASP developers used VB components at all was because of the performance advantage of leveraging compiled code. It's quite obvious that the term "object-oriented" was merely paid lip service during the Classic ASP era.
But let's jump ahead to the wonderful world of ASP.NET. In ASP.NET, every page is inherently an object, so you can't help but develop object-oriented code, right? Unfortunately, this has not been the case for many Classic ASP developers making the switch to ASP.NET. They are still mired in the old way of thinking when it comes to the business logic tier of their applications. Most ASP.NET applications I see today have ever fattening user interface tiers (in code-behind logic), and the thinnest business logic tier imaginable.
This time around, the performance-advantage argument no longer applies. All the code in ASP.NET is compiled, so that benefit went right out the window. The only slight advantage that remains is that you're encapsulating your stored procedure calls - hardly the vision that our object-oriented forefathers had in mind.
So what's missing? The logic of course. To effectively leverage object-oriented concepts in your development, you need to change the way you think about your business logic tier. Instead of thinking of it as nothing more than a means to extract data from your database, think of and build your business logic components as an SDK (Software Development Kit), not unlike the .NET Framework itself. Inheritance, polymorphism, and all the other object-oriented goodies that .NET provides for you make this process a snap.
I wrote an article on organizing your .NET namespace structure (http://www.fawcette.com/vsm/2003_04/online/goodyear/default_pf.aspx), so I won't go into that too much here. Suffice it to say that in your company's .NET object hierarchy, your company name becomes the top-level namespace (similar to the System namespace in the .NET Framework) and application and functional sub-systems make up the rest of the namespace hierarchy, staying as close as possible to the standard namespaces implemented in the .NET Framework.
Even the most organized .NET namespace hierarchy doesn't solve the problem, however, if your business logic components don't have the right logic in them. There are a few fundamental things that all your business logic components should contain. First, they should be self-validating. When you build your business logic components into an SDK, you are effectively disconnecting it from your Web application, and any input validation that it performs. Therefore, your business logic components are the last line of defense to make sure that only valid values make it into your database. Even if you have field value constraints implemented in your database, you'll still want to validate your input data so you can throw more informative custom exceptions to the consumers of the component, whatever that consumer may be.
Speaking of database connectivity, each of your business logic components that talks to a database should inherit from a base class that implements a property for a database connection string. Because your components can now be used by multiple consumers, you can't have any connection string retrieval logic baked into them. It is much better to have the consumer provide that information at run time.
I'm a firm believer that the user interface tier of any application (including ASP.NET Web applications) should be ADO.NET-free. ADO.NET is a great technology for retrieving and manipulating data, but it isn't very well suited to representing the logical entities in your application. Typed DataSets are about as close as you can come, and those are an absolute nightmare to manage (Whidbey will go a long way toward fixing this).
Instead, your business logic components should distill your ADO.NET objects into objects that represent the entities in your system. For instance, if you're retrieving a list of customers from your database, don't return a DataSet with customer information in it. Instead, create a typed collection of Customer objects and pass that back. While you're building that typed collection, you'll also have the opportunity to perform any other necessary logic that wasn't performed by the stored procedure.
As long as your typed collection implements the IEnumerable interface, you'll still be able to bind it to all the server controls that you know and love. You'll also be able to take advantage of all the custom properties, methods, and sub-objects that you've implemented in your objects. IntelliSense alone will be enough to sell you on that feature.
The bottom line is that the code-behind class for each of your ASP.NET pages should only contain the glue that binds your company's business logic SDK with the elements of the page, and the elements of the page to each other via event wire-ups (where applicable). Put all the real logic that makes up your Web application into a framework of business logic components that can be re-used by any number of different consumers: Windows Forms applications, Web services, mobile devices, etc. Moving to ASP.NET requires more than just changing the technology or platform you're using. It means finally changing your mindset about the way an application is built, and where its constituent pieces go.
Hopefully, the ideas I've presented here will get you started in the right direction. You'll definitely find that your applications come into focus much more quickly and easily using this approach.
Jonathan Goodyear is president of ASPSoft (http://www.aspsoft.com), an Internet consulting firm based in Orlando, FL. He's a Microsoft Certified Solution Developer (MCSD) and author of Debugging ASP.NET (New Riders). Jonathan also is a contributing editor for asp.netPRO. E-mail him at mailto:[email protected] or through his angryCoder eZine at http://www.angryCoder.com.