Why you want to use Enterprise Services for your .NET application
Part 1: Introduction
Part 2: Basic Architectural Considerations and the benefits of Processes and Process Models
UI -> BusinessLogic -> DataAccess. This three layer model is the most common way to separate functional blocks of applications. It's clear, simple and very obvious. If you're writing a web application, all stuff on top of ASP, JSP or ASP.NET is your UI layer, whatever is called by that layer is your business logic layer and that, in itself is split into a "logic" and into a "data access" layer, which serves to make your data access code more resilient against changes in data access technology, database product choice or, in the simplest and most common case, schema changes in the underlying data store. If you are writing a GUI application, all GUI-related functionality is in the top-layer and you may be able to use the same business logic layer as you are using for a web application. Ideally, all user-interface type and technology specific aspects are handled in the UI layer, and business logic shall be as resilient against changes in the UI as it is against changes in the data layer. That's why we have those layers.
I call them "layers", not "tiers". In my world (not necessarily in everyone else's), a layer is a purely logical concept. Layering is about separating functionally different areas of code. To me, a tier is a solely a physical concept. It is about how code gets distributed in a runtime environment. A GUI application, which ends up being compiled into a single EXE may be built using multiple separate layers just as much as a server application, which potentially maps each layer on a distinct physical tier. More likely is, though, that stuff from two or more layers gets mapped into a tier or that two tiers handle one layer. Example: SQL Server stored procedures and components manipulating ADO.NET DataSets using ad-hoc SQL are all things that belong to an data access layer. Still they are physically deployed in two places: Inside SQL Server and in a process that is accessing SQL Server from the outside. I would call that two separate tiers, but one layer. A "single EXE" GUI application has many layers, but possibly only one tier (if it does, for instance use the JetDB engine mapped into its own process space).
That's all well-known and very obvious to mostly everybody as long as the "UI" role is very obvious (Web front or GUI) and the "Data Store" role is very obvious (some RDBMS). Most commonly, (sub-)systems which feature this type of layers are running in "reactionary mode". They are triggered by some user activity and run one or more (potentially parallel) sequences of activities in response to the user activity. Not seldomly, architectural confusion begins whenever a system shall perform autonomous actions (for instance based on timers) or when the trigger for an activity is not a user, but some other binary lifeform. Where does that fit into the layering picture? Does it fit at all? Also, if my business code needs to invoke a remote system through a web service or needs to submit a document to a remote site using an infrastructure like BizTalk or if it simply wants to send an email via SMTP. Where does that go?
In my world, the acronym "UI" doesn't mean "user-interface", it means "use-case-interface". Everything that triggers any activity in the business logic layer is a "UI". A Web Services is a UI, a BizTalk Server application integration component (AIC) is a UI, a Windows Service process is a UI. The business code doesn't really care whether the current method call was originally triggered by a human being clicking anywhere on a remote screen. All such UIs can share a lot of code. Indeed, "business logic" is all code that is UI-agnostic in this expanded scenario.
The "Data Access" layer isn't just for databases. All code that accesses any functionality outside your own application and which is triggered by activities that root in your own application belongs there. If you call a remote web service or a remote application that's not under your own immediate control, you need to make your business code resilient against changes in those external applications. If you send a Word document attached to an Email via SMTP now, you may want to send an PDF document via other ways tomorrow. The fact that the information must be sent doesn't change, formatting and ways of sending does. So, I like to speak of "Infrastructure Access Layer" rather than "Data Access" layer to limit confusion.
What we're getting out of this are three separate layers of code. "Use-Case Interface", "Business Logic" and "Infrastructure Access". It's a good way to organize interfaces and code and works very well for working in large teams. What we're not getting out of this a consistent and reliable mapping to a runtime environment. Business logic will execute in the process space of ASP.NET, a BizTalk AIC, a Windows Service or a desktop GUI application. All these process spaces are very different. The GUI EXE runs reliably as long as the user Alt-F4's it or until the machine becomes unresponsive courtesy of Windows Exploder. BizTalk will load and unload an AIC (and hence your entire layered model) for the duration of a single action. ASP.NET will load your code, but it'll sometimes recycle the process "suddenly" for various good reasons. A Windows service has a very predicable execution profile (starts/stops at boot/shutdown), but by itself it doesn't have a concept of communication with the outside world -- you'll have to make it an RPC or Remoting server or a Message Queue listener yourself and that will involve creating and maintaining worker threads, etc.
If you want to write applications that are dealing with data efficiently and truly scale, you will want to cache large parts of those 80% of all tables in your data model that hold static or near-static data in memory. You will want to keep pools of infrastructure objects ready and initialized. You will want to have pre-activated and smart "gatekeepers" that guard access to limited or expensive external resources such as 3270 terminal sessions, remote web services with low bandwidth, etc. What you need is a predictable execution environment, which allows you coordination of such access to limited resources, which will allow you to keep caches alive and current and which provides you with a security boundary that will allow authorization for accessing services and security-identity switches that can access services with elevated privileges for such authorized users. What you want is to go "out of process".
"Going out of process" and hosting your business logic in a decicated environment is not "necessary evil", it's a carefully chosen and intended feature of your architecture. Enterprise Services/COM+ (and J2EE application servers) provide you with such a predictable hosting environment for your "Business Logic" and "Infrastructure Layer" components. "Going out of process" means that you will isolate your business code from unique behavior of your "Use-Case Interface" hosting environment.
What you get is a process with a well-defined process model. It'll create and manage thread pools, it'll manage external access, it'll provide you with a way to access this functionality from other processes. Using Enterprise Services applications "in process" is a special case for whenever you only deal with a single "Use-case Interface" and you are ready to deal with possible restrictions its process model imposes for your business logic. Hosting business logic "out of process" is the default.
That's why you want an application server environment. Enterprise Services/COM+ and most J2EE application servers provide such an environment. These principles count on the server, but also on the desktop. Paying the price of cross-process marshaling is not something you are forced to do under torture, it's something which you'll do because you'll get something for that price. Power = Work /Time.
Today's favorite Enterprise Services attribute: [assembly:ApplicationActivation(ActivationOption.Server)]
Next installment: Part 3: Management of expensive and limited resources