A “chunky” interface may be a new concept to some, but chunkiness is an idea you need to be familiar with if you plan to develop distributed .NET applications anytime soon. In this article, I’ll explain the basic idea behind the term, which flies in the face of traditional object-oriented design doctrine, and clue you in to why chunkiness may be the way to go.
What is chunky?
In basic terms, a chunky interface is one that accomplishes a maximum amount of work with a minimum number of object method calls. By way of example, let’s look first at how you’d traditionally create a COM object in VB6:
Dim o as new SomeObject
o.SomeProperty = “Some value”
o.SomeOtherProperty = “Some other value”
There’s absolutely nothing wrong with using such a granular interface to set the initial values for SomeObject (and there isn’t really any alternative using COM). That is, until you try using a similar approach for a server-based object: in a distributed system where SomeObject happened to be hosted on a remote server, you’d be making three trips down the wire—one to create the object, and one each to set its two properties. With a .NET class that uses a parameterized constructor, the following code (VB.NET) would be more efficient:
Dim o as SomeObject
o = new SomeObject(“Some value”, “Some other value”)
Flying in the face of convention
I’m not telling you anything that good J2EE developers haven’t known for some time. If you look at any EJB source code, you’ll see multiple constructors, each with a long list of parameters, for each class. Object-oriented purists sometimes recoil with horror when they see such nongranular interfaces, but the realities of distributed application development are that calls to a server-hosted object are usually the source of most performance bottlenecks. Fewer method calls mean fewer trips to the server, which, unless you happen to have a dedicated T-1 between you and your application server, will result in better performance for your users.
The state vs. chunky
The idea of “chunk-ifying” your interfaces dovetails nicely with the idea of creating stateless components. A stateless object is one that doesn’t maintain any internal data between method invocations. Stateless objects are ideal for distributed applications because they consume fewer server resources than a stateful object, all other things being equal.
The trick is that stateless objects are notoriously difficult to get right, especially for developers used to creating very stateful objects like COM components. In a chunky interface, the essential information is provided with every method call, rather than hanging onto data from a previous call (that possibly came from another session). A chunky interface makes stateless programming much easier.
More to it than just constructors
Okay, so one big step toward building a chunky interface is the use of parameterized constructors, but there’s more to it than that: You’ll have to think logically about how you’ll use your object, combining related single methods into larger “meta-methods” that accept all parameters for the methods they encapsulate. You should also look at providing single overloaded methods for updating an object’s private fields.
For example, if an object’s internal data is usually refreshed following an update, make the refresh part of the update method’s logic, or provide an alternate “update and refresh” method. The latter idea is usually the way to go if you’re dealing with a pre-existing interface or an interface that could be used both locally and remotely.
For an example of what I’d consider to be the purest embodiment of a chunky interface, look at SQL. Let’s say you want to find the record in sometable where the contents of fielda are “search value.” The following SQL statement provides a very succinct way of retrieving this data from a database server:
SELECT * FROM sometable WHERE fielda = ‘search value’;
Now think about how many lines of code (and trips down the wire with a server-based cursor) you’d need to accomplish the same thing without the SQL query. You’d need something like this, assuming an ADO-like syntax:
If rs.Fields(“fielda”) = “search value” then
Found = true
Loop Until Found
Without even considering the case where there happens to be more than one record where fielda contains the text we’re looking for, you’d be absolutely mad to not expect a performance hit by using this alternative. Why should your distributed .NET components be built in this same fashion?