Server-side Java: Counting tiers - one, two, or n?

How many tiers does your application architecture need?

1 2 3 4 Page 3
Page 3 of 4

Three-tier architectures

Often, a two-tier app will need to store data on a server. Usually, the information is stored on the filesystem; however, data integrity issues arise when multiple clients simultaneously ask the server to perform tasks. Since filesystems generally have rudimentary concurrency controls at best (lock files are found on only some platforms, and are often flawed), the most common solution is to add a third program, or database.

Databases specialize in storing, retrieving, and indexing data. Just as a two-tier architecture separates GUI and business logic, a three-tier architecture allows you to separate business logic and data access. You can also provide highly optimized data indices and retrieval methods, and provide for replication, backup, redundancy, and load-balancing procedures specific to your data's needs. Separating code into client and server code increases the scalability of your application; so does placing data on a dedicated process, host, or series of hosts.

(Currently, SQL RDBMSs, like those from Oracle and Sybase, vastly outnumber other database types. You may have heard the names of some of these other types -- OODBs (object-oriented databases), ORDBs (object-relational databases), and embedded databases -- thrown around as buzzwords, but these are still exotic species, rarely encountered in the real world.)

The general procedure for using a database is to design a schema that describes your data, and queries that store and retrieve that data. There is one shortcoming to this approach: you need to learn a whole new programming language! SQL is not Java, and with the added effort of designing and implementing a new schema, translation code to go from one schema to the other, and queries executed by your program, your development time can greatly increase. When you throw stored procedures and the hiring of a full-time DBA into the mix, the decision to go with a database can seem unnatural. I've heard people estimate that as much as 70 percent of a given project's programming and debugging is spent in the object-relational mapping code.

Granted, there are many cases in which using a database is necessary, and reduces an application's time to market. But there are also many cases in which you can store a small amount of data in a simple local file instead of a relational database. A simple rule of thumb: if you only need to store data, and can get away with retrieving files by name, use a filesystem. If you also need to search through those data, then use a database -- especially if those searches are based on varying criteria.

One reason you can benefit from using a database -- besides the improvement in concurrency, access speed, and reliability -- is that multiple applications (or services) can access the same data. This benefit is on the border between three-tier and n-tier applications.

A word on stored procedures: they are evil. Stored procedures are essentially little programs that run inside the database. Since they are close to the data, they can perform manipulations (sorting, filtering, transforming, etc.) that would be prohibitively expensive to perform on the server. Some operations require that stored procedures or triggers be efficient. However, you can easily misuse them. It is tempting to put business logic inside stored procedures. All this constitutes a disruption of the three-tiered structure: instead of GUI, logic, and storage being neatly separated, you now have logic intermingling with storage, and logic on multiple tiers within the architecture -- causing potential headaches down the road if that logic has to change. Furthermore, the stored-procedure logic is written in a different language than the application code, and is subject to a different revision-control mechanism (if there is one, which there often isn't) and a different debugger mechanism (generally text-based and rudimentary, if it exists). This makes stored-procedure code much more difficult to develop and debug.

To make this more concrete, here's an example of a stored procedure. Let's say you have a Website with a shopping cart. At checkout time, you need to calculate shipping costs. So you write a stored procedure to calculate the costs for UPS and FedEx automatically every time you save a shopping cart record. (This kind of procedure is actually called a trigger.) It all works perfectly and there are no problems. But what happens when, six months later, you need to add an option that allows your customers to ship via the US Postal Service? Since the post office uses a different rate and zone structure, you will need to write some code, naturally. But this code needs to be written in PL/SQL, and you can't use a visual debugger. If you mess up, you may interfere with the data's integrity. If you had written the original shipping cost calculator in Java in the middle tier, you could have just extended the DeliveryMethod class and you'd be done.

1 2 3 4 Page 3
Page 3 of 4
How to choose a low-code development platform