Monday, February 15, 2010

Minimizing calls across tiers - common themes

It’s easy to say that the number of calls between tiers should be minimized, but actually reducing the number of calls takes some effort. Fortunately, there are some strategies that can be applied at all levels in the application design to move in that direction.

Caching, which I would define as saving a commonly used data object locally so that it can be used the next time it’s needed, is an important option. By saving the object locally, future inter-tier calls to get it are avoided and if the object is very commonly used, many calls can be avoided. Cached data may be held in memory if that resource is not tightly constrained on the local tier or written to disk if it is. In either case, there will need to be a reliable way for the local tier to become aware that the underlying data has changed so that the cached data doesn’t become stale.

In deciding what types of data are good candidates for caching, the main thing to consider is the ratio of the number of reads or loads of the data type compared to the number of changes or writes. In most applications, configuration data is a particularly good candidate for caching as it is typically read hundreds or thousands of times more often than it is changed.

The concept of caching comes fairly naturally to the client and app server tiers where developers are used to implementing or integrating desired functionality, but it is also relevant on the DB tier. First, the DB server software will manage a cache of commonly used data blocks so that disk I/O operations can be avoided. Second, some DB vendors explicitly make available facilities for designating types of data that should be cached. Leveraging these features in the DB server software/hardware platform can absolutely bring caching to the DB tier.

Another common strategy for reducing calls between tiers is focusing remote interface design on the user actions identified in use case analysis. In other words, instead of focusing design on the persistence needs of a taxonomy of object types that exist in the business domain, design of application components that cross tier boundaries should be driven by what actions a user will take.

In general, a user interface has the potential to persistent instances of multiple data types. As an example, an order entry screen may have a representation of :

- the customer doing the ordering
- customer account details
- the products being ordered
- product inventory levels

and the screen implementation can probably modify all of them. The use case for the interface will almost certainly contains a single ‘save’ action to persist changes, but at some point the application logic will need to split to update different database tables. The closer that split occurs in the application stack to the DB, the fewer inter-tier calls will be needed to accomplish it.

To some extent, the approaches described here for reducing inter-tier calls may not be obvious in the context of object oriented programming. Still, as long as the duration of a call across tiers is measured in milliseconds and the duration of an inter tier call is measured in microseconds, performance considerations will argue for coarse grained remote interfaces.

No comments:

Post a Comment