Iterators, again Applying this to the Account interface

... } public interface Printer extends Remote{ public PrinterStatus getStatus throws RemoteException .... } This new interface lets us make a single call to the printer server and get all the status information in one object. From a performance point of view, any interface change that reduces the number of distributed method invocations by a linear factor [ 6] is a great idea. Note also that were now returning an object instead of integers. Changing the interface in this way means that our earlier design heuristic, return objects rather than primitive values, is also satisfied. [ 6] For example, were not getting rid of 3 method invocations were reducing them by a factor of 4. On the other hand, the idea of having a separate status object clearly violates information encapsulation. Which is to say, it violates the single most important precept of object-oriented design. Compounding the offense is that the status object is purely data™it has no associated behavior and, in fact, looks suspiciously like a struct from the C programming language. Some system architects may consider this a bad thing. Pay them no heed. It is reasonable, and even a good idea, to first design server interfaces as if they were same-process objects. But performance considerations demand that you then add a set of methods that group together frequently performed sequences of commands.

7.1.5.1 Iterators, again

One final point needs to be made. You might have noticed that the use of iterators violates this rule. With iterators, we make a remote call, get a reference to an iterator, and then need to make a second remote call to the iterator before we actually get any return values. The solution is to wrap the return value from the first remote call in a data object that also contains the first set of return values. Returning to the bank example, this would look like: public interface SalesHelper extends Remote { public AccountSet getAllAccountsWithBalanceOverMoney amount throws RemoteException; ..... public class AccountSet implements Serializable { public ArrayList firstSetOfAccounts; public AccountIterator theRestOfTheAccounts public interface AccountIterator extends Remote { public int getNumberOfRemainingAccounts throws RemoteException; public ArrayList getNextint numberToFetch throws RemoteException; } Doing things this way seems a bit complicated. But it does something quite nice™it lets us define a threshold value for when an AccountIterator is necessary. For example, we might set the threshold to 50 accounts. Heres what then happens when we call getAllAccountsWithBalanceOver : • If there are 50 or fewer Account s to return, we return an AccountSet with the answers and theRestOfTheAccounts set to null . • If there are more than 50 Account s to return, we return the first 50 as part of an AccountSet , along with a reference to an iterator from which the rest can be obtained. This is a nice compromise. This interface is a little more complicated than the previous versions. However, it lets us handle small numbers of return values gracefully, and simultaneously allows us to handle large numbers of return values.

7.1.5.2 Applying this to the Account interface

In our basic use case, each conceptual operation is accounted for by a single method call. If it turns out that customers really want to transfer money, then this design point argues that we will need to add a transferMoney method, rather than implement the transfer on the client side by having it perform a makeWithdrawal followed by a makeDeposit . 7.1.6 Does the Interface Expose the Right Amount of Metadata?