The definition of three-tier or n-tier has changed frequently as distributed networks evolved. I use Microsoft's "Application Model" definition. That model uses the terms Data Services (database layer) , Business Services (business object layer) and User Services (presentation layer) to delineate the tiers.
Promotion of this model is intended to provide an alternative to the two-tier structure most commonly in use consisting of the presentation layer executing queries and stored procedures and dealing with the cursors and resultsets directly.
Each separate layer has a very distinct set of reponsibilities.
The Database Layer concerns itself with the specifics of the database connection and the syntactical differences between using Access, Sybase, Foxpro, DB2 etc. It builds and processes recordsets/resultsets for the business object layer.
The Business Object Layer concerns itself with enforcing business rules and moving data back and forth from the database buffers to the properties accessed by the presentation layer. The Business Object and Database layers together are compiled into a 'Component Server' EXE (or DLL running under MTS) and reside on the server.
In the Presentation Layer, database information is received as properties of the Business Object interface. The presentation layer does not need to have a connection to any database engine or data access object library; nor does it need to implement complex business rules. It is therefore small, quickly loaded into memory, and stable. And because it is 'thin', it is easily maintainable as user requirements change. The presentation layer can be implemented in a variety of packages: Visual Basic .exe's or as .ocx components, ActiveX documents or ASP scripts.
Today the interfaces, tomorrow the world!
Although VB doesn't support inheritance, it does support a related object-oriented feature, polymorphism. In this technique, abstract classes are defined as interface classes which contain publicly accessible methods. Instantiatable classes implement these abstract classes with corresponding private methods that are only accessible thru the public interface.
The purpose of interfaces is to standardize the communication between layers of software. The designer has the power to enforce consistency in the way the implementors code the business classes.
Interfaces are used throughout OLE and COM as an extra layer of encapsulation to ensure that interacting objects all look familiar to each other regardless of their internal processing details.
Middle tier classes are standardizable
This technique is useful to the three-tier architect because most of the component server classes are standardizable. One interface for the database layer and 4 for the business object layer are all that I've found to be necessary. These interfaces are described below in more detail.
Once the interface contract between the layers is negotiated, the database programmers can work independently of the user interface programmers; one group knows what services it is providing, and the other group knows what services will be available to use.
The standardization of the middle tier has a big payoff.
A typical application is going to have a large number of business objects in the middle-tier encapsulating the individual tables. However... if the interface that these objects present to the GUI layer is constant and pre-defined, and the interface to the database layer down below is also constant, these business objects are all going to be structured nearly identically. They will look extremely similar to one another. The typical differences will be field names and types, and business validation rules. This means that the middle tier is amenable to rapid development by cloning and perhaps even module code generation using Perl programs running off the table definitions.
No more server programming bottleneck
Another benefit is that the middle tier can be coded before the user interface design is complete. The programmers doing the business objects don't care what the visual presentation will look like or even which technology will be used. The middle tier can developed in skeleton form before the user interface needs it and later refined with business rule details.
This rapid early development of the middle-tier helps dispose of the issue of whether to create a functional but throwaway prototype of the system first. It probably won't be necessary.
Benefits of Thin Client
Microsoft offers a number of alternative technologies for the presentation layer. These can be selected for reasons completely related to user requirements and completely unrelated to where the data is coming from.
ASP is gaining in popularity because scripting is easy to learn and use. For web functions built on scripting, simplicity is very important. Attaching to a component server requires less script logic than attaching to a database. Server and network performance issues, error catching, and enforcement of business rules are handled in one place in the lower layers. It allows the user interface programmer to concentrate on user interface issues.
Simpler scripts of course means they can be written and changed more quickly, resulting in faster turnaround of user requests.
Reusability, the golden promise of object oriented design is achieved also. If you have an EXE input screen and later you want to create a web-based version of it, most of the code has already been written.
All code resides on the server and is easier to maintain and repair quickly. Business rules are implemented in a single place and can be found and updated easily.
Platform Flexibility
The separation of the Business Object Layer and the Database Layer means that the application can go to different database engines transparently to the business objects. This also allows migration from one platform to another with virtually no code changes in the middle tier. . You can do early development on Access/DAO then move to RDO/ODBC for system testing. Next year you can migrate the system to an ADO provider when it becomes available. The database-specific modules can be compiled together or separately depending on the chosen network hardware configuration.
Splitting the load: greater flexiblity
In the two-tier architecture, there is usually a need to strike a balance between database server loading and network traffic. Assigning more work to be done in the stored procedure can produce a smaller resultset to be passed back to the application. However, long batch procedures can result in a bottleneck forming in the database server. Complex batch procedures typically encounter progressively higher rates of paging the longer they run.
In the three-tier model, there is more room to make adjustments. Normally there is more bandwidth between the database server and component server (if they are separated) than between the client and the server. The component server can execute shorter simpler stored procedures and do some of the crunching itself asynchronously to the data retrieval. You have a better chance of achieving lower database utilization without a proportionate increase in network data flow.
Putting time-consuming processes into compiled procedures improves overall response time. The programmer can attack performance problems in the component server various alternatives for increasing speed: memory arrays, memory-mapped files, direct to disk storage, and special C++ DLL's for the most troublesome cases.
When the server script relies on the component objects for the heavy lifting, more work is done in compiled code and less in interpreted script.
These examples are not intended to be a prescription. They are only intended to show that at some early point in the design of an n-tier system, some document representing the interface "contract" should be negotiated, approved and published to all developers coding or using the services. That document would carry more detail than these examples show, including a full description of the processing in each method, and a description of all the interrelationships between methods and properties (all the usage rules).
Data Interface Specification Detail
In this example, there are two classes. One, the controlling the recordset, has a public interface. The other, establishing the connection, is private and is called by the recordset object.
Suppose you did your early development in an Access version of the database. Moving the entire application to ODBC/RDO would consist of implementing the two classes of this interface with RDO logic and substituting these two class implementations in place of the corresponding DAO modules. The only code change needed in the business objects would be replace the reference object variable type from "Recordset" to "rdoResultset" to maintain early binding.
Business Object Interface Specification Detail
Complex and volatile business rules are implemented here to keep them in one place for maintainability.
References to recordset buffers only. Buffer access syntax (recset ! field) consistent for all three data access object models: DAO, RDO and ADO.