1

I'm learning UML and want to create a small restaurant application, that has a menu, dishes contained in menu, products used in dishes. Menu is divided into different types that can contain only of the appropriate type. I suppose that class menu and dishes should be abstract. That's my UML diagram.

enter image description here

How to best display the relationship of abstract classes?

Christophe
  • 68,716
  • 7
  • 72
  • 138
Pirogov
  • 37
  • 3
  • 1
    Welcome. THis is an impressive diagram for someone who just starts to learn :-) If I understand well your question, you notice that you have a composition relationship between the abstract classes, but you have only shown composition between specific classes. This is a rather advanced subject and you may have a look [at this answer](https://stackoverflow.com/a/62981806/3723423) (it's about association classes, but similar techniques may be used for composition. – Christophe Feb 25 '21 at 19:16
  • 1
    Now the question is whether you really need this complicated construct with the specialized composition between concrete classes, or if you could just used a composition between abstract classes (which is inherited), and add some constraints to say that soup menus can only be composed of soup dishes ? – Christophe Feb 25 '21 at 19:18
  • 1
    What do you mean by "relation of abstract classes"? Your diagram has no relation between abstract classes. Only inheritance from abstract to concrete classes. Btw. abstract classes are denoted by italic names, not by adding the word "Abstract". – qwerty_so Feb 25 '21 at 20:28
  • Probably i expressed the idea not cottectly since i'm beginner at UML. By the word "relations" i meant links between classes or objects in my application, i'm sorry if i was incorrect. I would to create a model of application using UML. And i wanted to use a composition between abstract classes (which is inherited), and add some constraints to say that soup menus can only be composed of soup dishes. Can you advise sources or books about UML. Sorry for late answer. – Pirogov Feb 26 '21 at 09:05
  • @Pirogov No problem, we’ll help. I notice that your concrete dishes inherit a composition with order and have their own composition. This is illegal, as explained [here](https://stackoverflow.com/a/66220595/3723423). A question before I can help: what is the menu? Is it a price offering, is it a catalogue of related items? or is it some sort of soup combination (e.g. soup + main + dessert or starter + main without dessert, or starter soup-+main soup+desser soup)? – Christophe Feb 26 '21 at 13:57
  • @Christophe my menu is like catalogue of related items. – Pirogov Feb 26 '21 at 14:15

2 Answers2

2

First attempt

If we look at the requirements, i.e. that Orders are about Dishes, that Dishes are composed of Products, and that Menus are like catalogues of Dishes of some kind, we would come to such a diagram:

enter image description here

We'd show only a "relation" between the abstract Dish and the abstract Menu. The specialised dishes and menus inherit this association. It's just that you have to express with a comment on the association the constraint of using dishes compatible with the menu.

Further reflexions

The question is if we really need Menu specializations. This would be justified if they'd have very different behaviors.

Moreover, in your example you assume strict separation of the menu specialization. But what if at a later stage you'd have overlapping menus, e.g. Main menu with vegetarian, vegan and meat dishes, and a Vegan menu with only vegan dishes but for all kind of dishes.

If the behavior is the same for all the menu specializations and if this is only meant as an arbitrary categorisation (and if moreover, you'd have only one instance per class in practice), then it would be better to make Menu concrete and associate it with a Category class. By the way, you could also associate the abstract Dish to one or several Category, which would allow easier expression of the constraints you wanted.

Finally, it would be worth to explore the concept of association class and rethink what's between Order and Dish as well as between Dish and Product.

Christophe
  • 68,716
  • 7
  • 72
  • 138
  • You subclasses of `Dish` are all Menu's. I suppose that's an oversight? And does it make sense to avoid composition between `Order` and `Dish` but not between `Dish` and `Product` I think you should first define what the classes mean. Is an instance of a `Dish` the item on a menu, or is it the actual plate with food that is served to the customer. I suspect the first, but in that case you shouldn't have a composition to `Product` (the product *Mashed Potatoes* could be part of multiple dishes) – Geert Bellekens Feb 27 '21 at 08:01
  • I do not understand why the classes *X Menu* inherit *Dish*. First a menu contains dish(es) but is not a dish. Second on your proposal a *X Menu* inheriting both *Menu* and *Dish* implies a *X Menu* aggregates a *Y Menu* which can be itself. – bruno Feb 27 '21 at 08:02
  • Very probably you wanted *XX Dish* inheriting *Dish* rather than *XX Menu* – bruno Feb 27 '21 at 08:12
  • @bruno yes indeed! under dishes there should be only dish specializations. Sorry, it was late in the night, and I messed up in the cloning of my dish subclasses. I’ll correct this later in the day. – Christophe Feb 27 '21 at 09:15
  • @Christophe I am not surprised this was a 'typo' ;-) – bruno Feb 27 '21 at 09:18
  • @GeertBellekens well spotted for the cloning error. I have now edited the graph to correct this late-night issue. About the second composition, I hesitated for exactly the reason you mention. But I thought that objectively, nothing would prevent to have unrelated product clones as ingredients of each dish, even if I wouldn't do so, and I left it in the spirit of the OP's initial intention. But in my edited graph, I've added a question to challenge this more explicitly. Thanks for the suggestions :-) – Christophe Feb 27 '21 at 10:57
  • 1
    @Pirogov Happy that it helped. I've corrected my graph of the typos and have added some more questions for you. In the further reflections, I added sole thoughts about introducing a category class as alternative to subclassing. Finally, if you're looking for sole more reading, I'd recommend Martin Fowler's very pragmatic and comprehensive "UML distilled" book. On the web, there is https://www.uml-diagrams.org (which is the best resource imho on the topic). I now prefer other sources because they added a lot more annoying adds, but their content is top. – Christophe Feb 27 '21 at 11:04
2

I put an answer after @Christophe did because in (the first version of) his proposal there are exceptionally some problems.

An order contains at least one dish. But an order is not composed of dishes, so there is no composition, and for me nor even an aggregation.

A dish is made from at least one product, using a given quantity of them. Depending on the product the quantity is a volume (for instance for a liquid), or a weight (for instance for butter) or a number (for instance for egg), etc. For that you can use a class-relation. The relation cannot be a composition because a given product can be used for several dishes.

A menu contains a least one dish, but a given dish can be used in several menus so a composition cannot be used. In my diagrams I use an aggregation but perhaps this is not a good idea.

Supposing you always need to have specialized classes for Menu and Dish you can have :

enter image description here

but I am not sure you always need these specializations, so Dish and Menu are not abstract even they can have specializations, and you can have :

enter image description here

(I suppose a dish is always part of at least one menu, this is a choice, so a 'preparation' made by cook but not part of a menu is not a dish)

As @Christophe said in a remark the customer can ask for some specific instructions (medium versus bloody for the meat etc), that can be supported by a class-relation :

enter image description here

bruno
  • 32,421
  • 7
  • 25
  • 37
  • Hello @bruno thank you for your answer. If i will code following your first diagram i am creating abstract classes `Menu` and `Dish`? The second diagram contains not abstract classes, right? And i have a one more question after your answer: why `Dish` and `Menu` shouldn't be abstract? I didn't get it. – Pirogov Feb 27 '21 at 09:27
  • 1
    @Pirogov yes no abstract class in the second diagram, because it is useless to have. By definition an abstract class cannot be instantiated, so if for instance *Dish* is an abstract class all the dishes are instance of an other class specializing (directly or not) *Dish*. A non abstract class can be specialized, so the question is not *why classX is not abstract* but *why ClassX need to be abstract*. Do not search for a complicated solution, search for a simple one. – bruno Feb 27 '21 at 09:42
  • 1
    Nice complement. You could also add an association class between order and dish. And what's the benefit fo aggregation over a simple association here? Finally, I didn't question the abstraction dishes, since I can every evening observe that a soup has a different behavior than a main dish ;-) – Christophe Feb 27 '21 at 11:12
  • @Christophe I did not put a class-relation between order and dish because in that case the quantity is just a number and this is already managed by the multiplicity (of course there is no constraint *unique*). Of course the use of an aggregation of always questionable, the one I use between menu and dish is perhaps not a good idea – bruno Feb 27 '21 at 11:19
  • 1
    @bruno excellent argument! But as a consequence, the customer cannot ask for less salt, more pepper, medium vs blody, not too warm, or any other specific instructions one might want to give to the waiter? ;-) – Christophe Feb 27 '21 at 11:23
  • @Christophe ah yes good remark,will add that in my answer – bruno Feb 27 '21 at 11:25