2

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

Kedar Tokekar
  • 418
  • 3
  • 10
  • `PlayMusic` with capital P is indeed nowhere. But `playMusic` is definitely an operation of the base class! Also the Generalizations should be Realizations. – qwerty_so Jan 18 '21 at 10:07
  • Yes @qwerty_so you are right. About realization. Mistake accepted. I will try correcting diagram. But playMusic() (typo accepted) I purposely did not add to base class to show that it can not be called on base class ref. This is a demo code to put my point.. – Kedar Tokekar Jan 18 '21 at 14:32
  • edited the image – Kedar Tokekar Jan 18 '21 at 14:52
  • Still, then playMusic is a legal operation. Puzzled. – qwerty_so Jan 18 '21 at 14:54
  • `I feel either people did not get the core question, or I failed to highlight the core issue` : considering all 3 we "do not get the core question" clearly the problem comes from your question. `This is a strongest feature of interfaces to publish different abstractions to different clients` : this is absolutely false, an interface does not know the 'clients' and do not care of them, you confuse interface and interface realization. `changing states over life line in sequence diagrams.` : the notation/concept you use in your diagram is not part of the standard, and a type is not a state – bruno Jan 25 '21 at 12:04
  • *Car IS-A Vehicle and ShowroomItem BY-DEFINITION* : of course this is 'legal', I can also have the class Vegetable and say Car inherits it, the Java code will compile, we just said to have car inheriting ShowroomItem is a non sense – bruno Jan 25 '21 at 12:09
  • @bruno, I do respect your (everyones) reputation. I would like to know, with your view, how can we understand the role of interfaces Comparable, Runnable etc in Java? those were written by keeping in mind a specific client (e.g. TreeSet) who is ONLY interested in sorting. Otherwise TreeSet only knows our entity as Object. If we do not implement it for entity and use it in TreeSet, it throws ClassCastException. Means it type casts our entity to Comparable with sole purpose of changing self abstraction so as to compare two objects. How can show that scenario in sequence diagram? – Kedar Tokekar Jan 25 '21 at 14:33
  • @KedarTokekar *TreeSet* doesn't implement *Comparable* nor *Runnable*, but *C* must be a *Comparable* to use a `TreeSet`, the fact this cannot be check at compile time is a weakness of the language but whatever. The *cast* of an instance does not change its type. In your case *Car* is a *Vehicle* and (unfortunately) a *ShowroomItem* so you can apply *start/stop/buy/sell* on a *Car*, without any *cast*, and I do not see a link with the implementation of *TreeSet* nor the link with your initial question where a user of a *Car* can or not call *start/stop/buy/sell* depending on who he is – bruno Jan 25 '21 at 16:50

3 Answers3

3

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.

Christophe
  • 68,716
  • 7
  • 72
  • 138
2

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.

qwerty_so
  • 35,448
  • 8
  • 62
  • 86
  • This model is just to put my main point of equivalent uml of e.g.If Vehicle v = new Car(); then v.start() and v.stop() only should work. Similarly for ShowroomItem. I want to know how to show object is of Car type but presently being addressed as Vehicle type in UML object diagram and sequence diagram. – Kedar Tokekar Jan 18 '21 at 14:35
  • Even if this is a demo it should be reasonable. And the above is not, at least to me. So hard to answer. You could go with constraints as bruno suggests. – qwerty_so Jan 18 '21 at 14:57
  • 1
    I don’t feel like writing up a full answer, so I’ll just add that this screams for the need for a “role mixin”. See this for hints: https://ontouml.readthedocs.io/en/latest/classes/nonsortals/rolemixin/ – Jim L. Jan 18 '21 at 16:17
  • @JimL. OntoUML is a specific profile, I guess? – qwerty_so Jan 18 '21 at 18:14
  • 1
    It’s an ontologically well-founded profile for UML that helps prevent costly problems. – Jim L. Jan 18 '21 at 18:17
2

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.

bruno
  • 32,421
  • 7
  • 25
  • 37
  • In the *Fifth element* the car very well disallowed features based on the electronic driving license the driver had to insert before starting the car ;-) – Christophe Jan 18 '21 at 17:54
  • @Christophe but that applies only to flying cars :-)) – bruno Jan 18 '21 at 17:58
  • 1
    actually the flying car already exists. Aeromobil is build by a Slovakian company. I had the opportunity to see one from very close distance (in 2017 in an exhibition hall) It proves that the future is already now, but just unevenly distributed: https://m.youtube.com/watch?v=r7cN6Q2lqAw - what else does the aeromobil prove: prefer composition over inheritance ;-) – Christophe Jan 18 '21 at 18:07
  • 1
    @Christophe my car you can see in my profile is a convertible and named *volante* by Aston Martin, in french *volante* means *flying* ... but fortunately it is made to stay on the floor even at high speed ;-) But they work on a really flying car https://www.electronicdesign.com/markets/automotive/article/21806791/rollsroyce-aston-martin-join-race-for-autonomous-flying-cars – bruno Jan 18 '21 at 18:19