Value Objects Represent Sets and Lists Paths, Names, and Attributes Are All Distinct

mean, it is fairly clear that Context s list methods are all related to each other and to the RMI registrys list method. However, even in such a simple interface, there are a significant number of design decisions that may not be obvious. In the remainder of this section, well explore some of the decisions made while designing Context . Some of them are implied by the interface; some are just arbitrary decisions that had to be made. Most of them could have been done differently; the key is to know in advance what were building so were confident it will meet our needs, and so we can test it.

15.4.1 Value Objects Represent Sets and Lists

Most of the arguments are objects that we need to define. Even in a method such as bind , in which we try to be as similar as possible to the registrys bind method: public void bindPath path, String name, AttributeSet attributes, Remote server we use two new objects, Path and AttributeSet . When we get to the context-specific API, even the return values are new objects: public ContextList listSubContexts throws RemoteException, NamingException; Moreover, weve explicitly chosen not to use object arrays or the Javasoft container classes. For example, we could have defined bind to have either of the following signatures: public void bindPath path, String name, Attribute[] attributes, Remote server public void bindPath path, String name, ArrayList attributes, Remote server There are two reasons for designing the interface using AttributeSet instead of Attribute[] . First, it preserves flexibility at very little cost. If you use array types or classes defined by a third party, then you limit your future options. We can always add fields, or functionality, to AttributeSet . We cannot add fields or functionality to either java.util.ArrayList or Attribute[] . Second, it allows for validation on the client side. When you try to construct an instance of Path or AttributeSet , the objects can validate their member variables. For example, Path has a private constructor and a static buildPath method: public static Path buildPathString[] components { ArrayList arrayList = new ArrayListcomponents.length; for int i = 0; i components.length; i++ { if null = components[i] 0=components[i].length { arrayList.addcomponents[i]; } } return new PatharrayList; } This way of constructing paths has two nice consequences: • All the path components are instances of String . • None of the path components are empty strings and we could easily extend this to enforce other name-formatting conventions, should we so desire.

15.4.2 Paths, Names, and Attributes Are All Distinct

Given that attributes can be omitted, its not very surprising that attributes are treated differently from paths and names in a methods such as: public Remote lookupPath path, String name, AttributeSet attributes throws RemoteException, NamingException; However, the fact that server names are treated differently from context names might seem a bit surprising. When I defined paths, I said: If we form a path from the strings usr , bin , and games which we denote by usrbingames we make the following assertions: there is a context named usr ; if we list the subcontexts of usr , we will find a subcontext named bin ; if we list the subcontexts of bin , we will find a context named games . The meaning of the separation of path from name is that specifying the path usrbingames, which specifies a subcontext of the base context, is different than specifying the name games and the path usrbin, which specifies a server bound locally into the context specified by usrbin. Its worth repeating this in a slightly different way: the namespace for subcontexts is different than the namespace for locally bound servers. That means the following four queries, written in pseudocode, can all return different results: lookupusrbingames, tank, null Returns all servers named tank in the context specified by the path usrbingames. lookupusrbingamestank, null, null Returns all servers from the context specified by the path usrbingamestank. The server is guaranteed to match the name and attribute properties. However, since theyre null , any server from the context will do. lookupSubContextusrbingamestank, null Returns all subcontexts of the context specified by the path usrgamesbintank. lookupSubContextusrbingames, tank Returns the subcontext named tank of the context specified by usrbingames. This design decision is rather arbitrary. I feel the last two points are really separate cases, and the first two just fell out of how I think about things. Other design decisions are quite possible and indeed, may be the usual case here.

15.4.3 Null Arguments Are Okay