1.2 The Customer Manager Example
The customer manager component explored here is, at its heart, a dictionary (also known as a directory or a look-up table), which is a classic, and basic, data structure. When we begin to develop principles and guidelines for designing with contracts, we deliberately use clean, simple, basic examples so as not to detract from the main message. For instance, Chapter 3 develops a contract for the DICTIONARY class. However, lessons learned from simple examples can be applied to realistic problems, such as customer manager components. We look at more complex examples toward the end of the book.
Let's imagine you are planning to use a software component that will manage all the information about your organization's customers. (The term "component" has many meanings. Components that manage a data resource are only one kind of component.)
An installed customer manager component has exclusive control over all customer objects. Figure 1.1 is a UML-style diagram showing extracts from the CUSTOMER_MANAGER and CUSTOMER types.
Figure 1.1 The CUSTOMER_MANAGER and CUSTOMER types CUSTOMER_MANAGER and CUSTOMER types.
There is an association between these types. The black diamond tells us that customer objects are exclusively owned by a customer manager object. The asterisk tells us that a customer manager owns zero, one, or more customer objects.
The box for CUSTOMER_MANAGER lists the features you can use if you are a client of a customer manager object. (A feature is a method you can call or a public attribute you can inspect.) These features allow you to:
Find out how many customers the manager owns. (The count feature might be implemented as a read-only attribute, or it might be made accessible through a get_count() method, depending on the implementation language.)
Ask whether a particular customer id is active.
Add a new customer to the customer manager component.
Ask for the name of a customer whose id you know.
Give an existing customer a new name.
The box for CUSTOMER lists some of the attributes of a customer (we do not need to explore the details of the methods).
The customer manager component has exclusive rights to modify customer objects, and clients of the component do not access customer objects directly. Instead, we provide some simpler types to allow clients to communicate with the customer manager component about customer objects. Figure 1.2 shows just one of these simpler types, the BASIC_CUSTOMER_DETAILS type. This type allows a client to pass in the basic information needed to create a new customer object, for instance.
Figure 1.2 The BASIC_CUSTOMER_DETAILS type
The basic details of a customer are an id (given to him or her by the bank), a name, an address, and a date of birth.
In Eiffel, attributes can be public, but then they are read-only. So the design in Figure 1.2 is also the Eiffel programmer's view. If we were programming in Java, for example, we would program it with the attributes and methods shown in Figure 1.3 (in the code, we'd make the Java attributes private, but we haven't shown that detail on the UML-style diagram).
Figure 1.3 A Java design for the BASIC_CUSTOMER_DETAILS type
In Eiffel syntax, the name of a customer would be given by a_customer.name. In Java syntax, it would be given by a_customer.get_name().
The customer manager exclusively owns the customer objects, and only the customer manager can change the information about a customer, so there are no set methods in the BASIC_CUSTOMER_DETAILS class. If you do succeed in changing the state of a basic customer details object, this has no effect on the corresponding customer object that the customer manager owns. You have to call a method on the customer manager component in order to change anything about a customer object.