How to Show Reference type and Object type separately for same object in UML object and sequence diagram

840 Views Asked by At

enter image description here The diagram shows sample Class diagram and usage of objects of those classes in Sequence diagram.

In the above diagram instance myCar can be referred either by reference of ShowroomItem or reference of interface Vehicle. Accordingly the clients Driver/ SalesEngineer will get functionality access.

I agree that in implementation stage (e.g. Java), type identification is not required here and we will treat myCar as instance of base type (either interface) used itself.

But in sequence diagram, (for clarity) I am unable to indicate that the reference for myCar for Driver should be of Vehicle and for SalesEngineer should be of ShowroomItem.

I searched in UML 2.0 books, I did not get suitable notation. As per current understanding, I can show it either as "myCar : Vehicle" or "myCar : ShowroomItem", but that does not indicate that its Object of Car referred as Interface. This shortcomming does not enforce that playMusic can not work when referred as Vehcile.

Is there any notation to show this kind of detail?

As I am not satisfied with any answer provided, I am trying to add following to make question more clear, address some objections raised in the answers and proposing kind of solution for experts to review.

Looking at the comments, I feel either people did not get the core question, or I failed to highlight the core issue. First let me demonstrate code does not break. following code allows SalesEngineer to access Abstraction with sell() and buy() functionality and Driver to access Abstraction with only start() and stop() functionality [designed that way]. This is a strongest feature of interfaces to publish different abstractions to different clients. Java Collections use same multiple base types namely Object and Comparable in TreeSet, one for equals() and another for compare() on entities.

package com.se.stackoverflow;

interface Vehicle {
    abstract void start();
    abstract void stop();
}

interface ShowroomItem {
    abstract void buy();
    abstract void sell();
}

class Car implements ShowroomItem, Vehicle {
    // **Car IS-A Vehicle and ShowroomItem BY-DEFINITION**
    // **and as per SOLID principle interface segregation**

    public void start() { System.out.println("Started");}
    public void stop() { System.out.println("Stopped");}
    public void sell() { System.out.println("Sold");}
    public void buy() { System.out.println("Baught");}
}

class SalesEngineer {
    private ShowroomItem item = null;
    public SalesEngineer(ShowroomItem item) { this.item = item;}
    public void doTransaction() {item.buy(); item.sell();}
}

class Driver {
    private Vehicle veh = null;
    public Driver(Vehicle veh) {this.veh = veh;}
    public boolean testDrive() {veh.start(); veh.stop(); return true;}
}

public class ShowroomOwner {
    public void makeDeal(Car carForDeal) {
        Driver driver = new Driver(carForDeal);
        SalesEngineer engineer = new SalesEngineer(carForDeal);
        if (driver.testDrive()) {
            engineer.doTransaction();
        }
    }

    public static void main(String[] args) {
        // simulates client as ShowroomOwner to save space
        new ShowroomOwner().makeDeal(new Car());
    }
}

After referring "UML 2 and Unified Process" by Jim Arlow, I found we can show changing states over life line in sequence diagrams. I feel similar notation we can use to show changing types object [i havnt seen this documented in UML anywhere but its my suggestion to UML group].

e.g. here myCar is Object of its class Car (class of object can never be changed) but its reference type varies as per the left side like ShowroomItem or Vehicle.

May be following sequence diagram can show it. [Example classes are just indicative to highlight auto type casting effects]

enter image description here

3

There are 3 best solutions below

5
qwerty_so On

Since Car inherits (per your UML) from ShowRoomItem it will also have the sell() operation and the SalesEngineer can use it.

I think your model is just strange. A car which has a sell() operation is definitely one I would not buy. In other words: your class model is broken.

4
bruno On

First your class diagram is wrong, a car is not a ShowRoomItem, a car is the same before and after it is sail/buy, in your case the car will have to stop (may temporary) to be a ShowRoomItem since it is sail/buy. The fact it is a show room item is not a type but in the best case a state, but for me to have that state as an attribute of the car is a wrong choice too.

Second the actual instance the driver or sales engineer accesses is a car, and the car does not care who uses it, the radio does not disappear when the person is a sales engineer, so the car always accept to play radio if enough pre conditions are on (battery have power, may be key turn on etc)

The fact there are restrictions depending on who is the person must not be done at the level of the car, else this is out of the reality and fully artificial, but at the level of the person/role.

In UML for that kind of restrictions you can use constraints.

0
Christophe On

UML notation issue

You need to make choices about the type you want to show for each lifeline of a sequence diagram, because UML only allows a single one. Since myCar is a Car which implements Vehicle and ShowroomItem you may chose any of the 3 types.

Once the type chosen, UML has no way to provide an alternate view on the type in the same diagram. You can show the scenario with myCar being a Car. But the other lifelines must comply with the interface they know (provided no other usage dependency give them access to the full Car) and it's up to you to ensure consistency. This may be error prone, as you have demonstrated with playMusic().

You way address your concern with one or several notes in the diagram to remind the readers in plain text of the interface-related constraints. But a far better approach would be to keep it simple and show the interaction between SalesEngineer and Car and between Driver and Car in two separate diagrams. This is closer to the reality of your design, and promotes sound separation of concerns.

OOP Design issue

Qwerty_so and Bruno have already pointed to the weaknesses in your design. I fully agree with them. Indeed, a Car is a Vehicle. But a Car is not a ShowroomItem: a Car can temporarily have the role of a showroom item. Or converesely, a showroom item may correspond at a given time to a specific car.

If a car is not a showroom item it should neither inherit from such a class nor implement such an interface. Hence, prefer composition over inheritance, for example:

  • SalesEngineer trades in ShowroomItem
  • CarForSale implements ShowroomItem
  • CarForSale is associated to one Car
  • Driver drives a Vehicle (caution: bias towards rolling vehicles, because there's no driver on a plane ;-) )
  • Car implements Vehicle
  • Car can be associated to a CarForSale (but only if it is for sale by a SalesEngineer)

This design ensures better separation of concerns. For example, you can sell() or buy() only cars that are really for sale and not any car. Only cars for sale will have a price.

The other advantage is that you can show this full picture in a more robust way in a single sequence diagram since the different responsibilities are implemented by different objects.