Collaborations, Modeling Interactions

1. Common Interaction Patterns

The most basic interactions involve a client invoking a method from a server:

class Client {
   Server myServer;
   void request() {
      String cmmd = read();
      String result = myServer.serviceA(this, cmmd);
      ...
   }
}

In each of the following problems draw a sequence diagram showing the client executing the indicated call.

1.1 Helper Interaction

The server has three helpers of type Helper1, Helper2, and Helper3. Each has a makePart method of type

String makePart(String cmmd)

The server invokes each makePart method, then assembles the returned results into the result it returns to the client.

1.2 Dispatcher Interaction

In this pattern if cmmd is "A", then the server asynchronously invokes the service method of a server of type ServerA, otherwise it invokes the server method of a server of type ServerB:

class Server {
   ServerA serverA;
   ServerB serverB;
   String service(Client c, String cmmd) {
      if (cmmd == "A") serverA->service(c); // syntax I made up for asynchronous call
      else if (cmmd == "B") serverB->service(c);
      return "done"
   }
}

In either case, the servers compute a result, then return the result to the client by calling the client's receiveResult method:

c.receiveResult(result);

1.3 Supply Chain Interaction

In this interaction the server pre-processes cmmd. This might involve translating or reformatting, for example. The pre-processed command is forwarded to a serverA of type ServerA. The server performs some post-processing on the result returned by serverA, then returns the post-processed result to the client:

class Server {
   ServerA serverA;
   String service(Client c, String cmmd) {
      cmmd = preProcess(cmmd);
      String result = serverA.service(c, cmmd);
      result = postProcess(result);
      return result;
   }
}

It turns out that serverA does exactly the same thing that the server does. It pre-processes cmmd, then forwards the result to serverB of type ServerB. It post-processes the result returned by serverB and returns this to its caller—server, presumably.

It turns out that serverB does exactly the same thing that the serverA does. It pre-processes cmmd, then forwards the result to serverC of type ServerC. It post-processes the result returned by serverC and returns this to its caller—serverA, presumably.

1.4 Pipeline Interaction

This is similar to the supply chain interaction above, except instead of returning a result to its caller, ServerC simply pre-processes the message, then consumes it.

2. Control Logic

In each of the following problems draw a sequence diagram showing what happens when an unspecified client invokes the service method. Use combined fragments to indicate control logic.

Hint:

A message from an unspecified client can be shown as a found message emanating from the interaction frame and a return as a lost message reply terminating at the interaction frame. (All of this is under "advanced options".)

2.1 Two Way Selection

class Server {
   ServerA serverA;
   String service(Client c, String cmmd) {
      boolean connected = serverA.connect(this);
      if (connected) {
         String result = serverA.service(c, cmmd);
         process(result);
         return result;
      } else {
         return "refused";
      }
   }
   // ...
}

2.2 Iteration 1

class Server {
   ServerA serverA;
   String service(Client c, String cmmd) {
      boolean connected = serverA.connect(this);
      while (!connected) {
         connected = serverA.connect(this);
      }
      String result = serverA.service(c, cmmd);
      process(result);
      return result;
   }
   ...
}

2.3 Iteration 2

In this case Cart is the server and getTotal is the method invoked by the client. Of course we don't know how many items are in the cart (so don't make any assumptions). Show all of the items as a multi-instance of the Item class.

class Cart {
   Collection<Item> contents;
   double total = 0.0;
   void incTotal(amt: double) { total = total + amt; }
   double getTotal() {
      total = 0.0;
      for(Item item: contents) {
         double price = item.getPrice();
         incTotal(price);
      }
      return total;
   }
}

Hint: When traversing a collection you can use a loop guard such as contents.hasNext().

2.4 Recursion

In this case Calculator is the server, and fact(4) is the method invoked by the client.

class Calculator {
   public int fact(int n) {
      if (n == 0) return 1;
      return n * fact(n – 1);
   }
   // ...
}

Correctly show each recursive call as a self-message. Pay attention to the activation bars for each recursive call. Use reply messages to show the actual returned values.

2.5 Perpetual Loops

Draw a class diagram showing the relationships between Interpreter, Console, and ALU.

Draw a sequence diagram showing the perpetual loop when repl is called.

class Interpreter {
   Console console = new Console();
   ALU alu = new ALU();
   public  void repl() {
      do {
         Command cmmd = console.read();
         String result = "?";
         if (cmmd.opcode == "add") {
               result = alu.add(cmmd.args);
         } else if (cmmd.opcode == "mul") {
            result = alu.mul(cmmd.args);
         } else {
            result = "unknown";
         }
         console.print(result);
      } while (cmmd != "quit");
   }
}

3. Pipelines

3.1 Data-Driven Pipelines

A pipe is a message queue with operations for reading (dequeue) and writing (enqueue) messages (i.e., strings).

A typical filter has an input pipe and an output pipe.

The output pipe of one filter can be the input pipe of another. Thus, filters can be linked to form pipelines.

There are four types of filters:

·       Producers have no input pipe. They have a produce method that generates messages and writes them to the output pipe.

·       Consumers have no output pipe. They have a consume method that reads messages from the input pipe and consumes them.

·       Testers have a Boolean-valued test method and a process method. The process method reads a message from the input pipe, then writes the message to the output pipe only if the message passes the test.

·       Transformers have a String-valued transform method and a process method. The process method reads a message from the input pipe, then writes the result of transforming the message to the output pipe.

Draw a class diagram showing the relationships between pipe, filter, transformer, tester, producer, and consumer.

Draw a sequence diagram showing the interaction of a message passing through the following pipeline:

3.2 Demand-Driven Pipelines

In a data-driven pipeline a filter is triggered when an upstream filter writes a message to its input pipe. In a demand-driven pipeline a filter is triggered when a downstream filter attempts to read from its empty output pipe. The read operation completes when the filter manages to write a processed message to its output pipe.

Draw a sequence diagram of the pipeline in part 1 assuming that all of the filters are demand-driven.

4. Sensor Notification

A nuclear reactor maintains a list of sensors that must be updated each time the temperature changes:

class Reactor {
   private double temperature;
   private List<Sensor> sensors;
   public void connect(Sensor sensor) {
      sensors.add(sensor);
      sensor.setReactor(this);
   }
   public void incTemp(double amt) {
      temperature += amt;
      for(Sensor sensor: sensors) {
         sensor->update(); // asynch call
      }
   }
   public double getTemperature() { return temperature; }
   public void shutdown() { temperature = 0; }
   // etc.
}

To allow new and different types of sensors to be dynamically added to the power plant, a sensor is any device that extends the abstract Sensor class:

abstract class Sensor {
   protected Reactor reactor;
   public void setReactor(Reactor r) {
      reactor = r;
   }
   abstract public void update();
}

For example, at one power plant there are three sensors:

·       an alarm with a buzz method that is called when the reactor's temperature rises above 1000 degrees,

·       a thermometer with a display method that displays the temperature each time it changes,

·       and lastly, a thermostat with a shutDown shuts the reactor down when the reactor's temperature rises above 1000 degrees.

Draw a class diagram showing the relationship between the Reactor, Sensor, Alarm, Thermometer, and Thermostat classes.

Draw a sequence diagram that shows the three sensors connecting to the reactor at the start of the interaction and the subsequent interaction when Homer Simpson accidentally increases the temperature to 5000 degrees.

Hint: How will sensors know the reactor's temperature?

5. Proxies

The IServer interface specifies two operations:

interface IServer {
   String service1(String cmmd);
   String service2(String cmmd);
}

IServer is implemented by Server and Proxy.

A proxy implements the IServer interface simply by delegating to a peer:

class Proxy implements IServer {
   protected IServer peer;
   public String service1(String cmmd) { return peer.service1(cmmd); }
   public String service2(String cmmd) { return peer.service2(cmmd); }
}

Proxies can be chained together to enhance the services of a basic server. Each proxy thinks it is receiving requests from the client and forwarding requests to the server.

Examples of proxies include: CacheProxy and FirewallProxy.

A firewall proxy verifies that the command is authorized before forwarding the request to its peer.

A cache proxy searches its cache for the result of a previous request. If successful, it returns the cached result, otherwise the request is forwarded to the peer.

Begin by drawing a class diagram showing the relationship between Client, IServer, Server, Proxy, FirewallProxy and CacheProxy.

5.1

Assume a client requests service1(cmmd) from a firewall proxy that has a cache proxy as its peer and that the cache proxy has a server as its peer. Draw a sequence diagram showing the interaction. Assume the request is authorized and is not cached.

5.2

Assume a client requests service1(cmmd) from a cache proxy that has a server as its peer. Draw a sequence diagram showing the interaction. Use a combined fragment to show both cases: result cached and result not cached.

5.3

If the server is busy its methods return the message "refused". A synch proxy repeatedly resends its request until the reply is something different than "refused". Assume a client requests service1(cmmd) from a synch proxy that has a server as its peer. Draw a sequence diagram showing the interaction. Use a combined fragment to show then resends.

6. Auctions

An auctioneer repeatedly broadcasts a proposed price for an item to multiple bidders. If a bidder accepts the price, the auctioneer increments the price and rebroadcasts. If no bidder accepts the price after a period of time, the auctioneer sells the item to the highest bidder.

Hints:

Since there is an unspecified number of bidders and they all do the same thing, you can show all of them using a single lifeline, but with the multi-instance box checked:

Notice that I show the proposed price as an asynchronous signal. Study Question 1: How can you tell it's a signal and not a message? Study Question 2: Why did I do this?

Here's a suggested class diagram for this problem:

Note that the auctioneer does not know the identity of the bidders. It's not necessary because the proposal is broadcast using an asynchronous signal. You may assume consider is automatically invoked by the bidder just after the signal is received. (Actually, there is a special category of operations that react to signals called receptions. They are shown in a hidden fourth compartment of a class icon.)