I have one base-class named Product. Classes "Drink" and "Pizza" are subclasses that inherit from the "Product" class.
I also have a class named "Ingredient" Which is a part of the Pizza class, so the Pizza class should have an instance (a list) of the Ingredient class.
My question is:
Since the Ingredient has the same properties like all the other "Products", can it also inherit from the "Product" class while working together with the "Pizza" subclass?
Yes, they can!
Yes, classes that inherit from the same super-class can perfectly work together. There is no incompatibility. There is even a design pattern that uses both relations on the same classes (the composite pattern).
Remark: The wording "Working together" is somewhat ambiguous and could mean different things. But your class-diagram is precise enough and shows that you mean a possible association.
But how?
Your diagram shows a navigable association between Pizza and Ingredient (the open arrow). This means that the implementation shall make sure that a pizza can easily find its ingredients.
In your narrative you mention a list. I understand that an Ingredient can exist without any Pizza, but a Pizza can have several Ingredient. It is important to specify this multiplicity on the diagram, by indicating * on the Ingredient side of the association.
The relationship in the opposite direction has still some mysteries:
Navigability is unspecified: we don't know if an Ingredient shall be able to easily find the related pizza or if this is not relevant. You may specify this further with an arrow-head in the opposite direction (navigable) or with an X across the line (non-navigable). You have the right to leave this unspecified and decide later. The navigability has an impact on the way the classes can work together: it means that Pizza can "work with" ingredient (e.g. use it as parameter in an operation, invoke an ingredient operation directly, etc...). But the absence of navigability in the opposite direction would mean that Ingredient could not by itself initiate a collaboration with its pizza.
More important, the multiplicity: we do not know if an ingredient is associated only with one pizza (0..1), or if it can be shared between several (0..*). This is very important to know because the implementation would be very different (in the latter case you'd have a many-to-many association).
Overgeneralization ?
Inheritance is tempting when one discovers OOP. However, inheritance has a lot of implications, constraints and consequences. Therefore, use it wisely.
A useful advice is to start considering that A inherits from B, only if A is a more specialized B, or conversely, that B is a more generalization of A. It is dangerous to use inheritance just because some properties or operations share the same name. Names can by the way be misleading.
In your case, I understand a Product as something that the company sells at a given price: Drink, Pizza, maybe Antipasti or Pasta. The price indicated, is the price requested from the customer. I therefore wonder if an Ingredient is sold to the customer. AN ingredient may have a price, but it is a purchase price. A purchase price is different from a sales price: imagine that a restaurant would subcontract some very special pizza: the sales price would be different from the purchasing price.
Of course, if your Product is something more general, in the business meaning, and if it can have a sales price and a purchase price, and is not necessarily on the menu, then no problem, go-ahead. But be aware that such generalized products are much more complex to manage (e.g. here a well-known ERP example with more than 20 different screens to manage all the aspects of a product).
Other remarks
A very common advice is to prefer composition over inheritance. This rule of thumb aims to remind us to think twice before we use inheritance. Let's be clear, in case of doubt: this does not mean that inheritance and composition are incompatible.
Related
I'm trying to make a class diagram for an Online Auction System and I'm having this problem. Bids belong to both the Auction and the Buyer (Correct me if i'm wrong). So can I say that User is composed of bid AND auction is composed of Bid or is this against the rules of UML? I'm confused
In general
The term composition is ambiguous and this explains your confusion:
In OOP, object composition means to use an object in another one.
In UML, composition is a special kind of association that represents a part-whole relationship, with an exclusive ownership of the parts by the whole.
So in the UML sense, it is not possible to have an object that is part of two different compositions, because the ownership would no longer be exclusive. But you could use the object in several aggregations, which are a whole-part relations allowing a shared ownership.
In the OOP sense, there is no problem of having the same object used in (or using) several compositions. The object composition corresponds to a navigable UML association.
In your practical case
The situation is straight forward: A Bid has one Buyer, a Buyer may have several Bids, and an Auction has several Bids. You can model this with simple associations:
You could alternatively use an aggregation here, since one could argue that there is a whole-part relation between an Auction and the corresponding Bids (personally, I wouldn't see it like this):
You should however not see an aggregation on the other side, because there is no real whole-part relation between a Buyer and a Bid: a Buyer is not "made of several Bids".
Additional remarks
You could use also an association class here. But it's not required. And the semantic would be different: it would mean that there is a Bid association between a Buyer and an Auction:
Technically speaking, you'd still have three classes.
But the focus is different: the Bid is accessory to the Buyer and the Auction and cannot exist on its own (e.g. if the buyer disappears)
Have you learned about association classes in UML? They represent an object that is created from the relationship between two other classes, exactly what you are trying to map. There are plenty of contents detailing Association Classes (e.g. Correct use of an association class)
That way you shouldn't get confused reading the diagrams (which you were doing correctly btw), it would be clear to you that exists the entity Bid, which exists only associated to both Buyer and Auction.
The image shows the logistics of the Warehouse. Very very simplistic. What is its concept: There are documents: ReceivingWayBill, DispatchingWaybill, ReplacementOrder.
They interact with the main classes: Warehouse, Counterparty, Item.
And the Register class: ItemRemainsInWarehouse. It turns out, the document is confirmation of the operation, reception, sending, and so on. The Register simply stores information about the number of remaining goods.
If you miss a lot of problems of this scheme, such as: the lack of generalization, getters and setters and a heap of everything else.
Who can tell: the relationship between classes, and there is concrete aggregation everywhere, are placed correctly, or can we somehow consider the association in more detail?
It is so hard (maybe impossible) to correct your whole model with provided explanation. I give some improvements.
You should put Multiplicity of you relationships. They are so important. In some relationship, you have 1 (ReplacementOrder , Warehouse) and some of your relatioships are maybe * (Item , ReceivingWayBill)
You put Aggregation between your classes and we know that Aggregation is type of Association. You can put Associations too. You can find a lot of similar questions and answers that explain differences between Association and Aggregation (and Composition). see Question 1, Question 2 and Question 3. But I recommend this answer.
I think, there is NOT a very significant difference between Aggregation and Association. See my example in this question.
Robert C. Martin says (see here):
Association represents the ability of one instance to send a message to another instance.
Aggregation is the typical whole/part relationship. This is exactly the same as an association with the exception that instances
cannot have cyclic aggregation relationships (i.e. a part cannot
contain its whole).
Therefor: some of your relationships are exactly an Aggregation. (relationship between Item and other classes). Your Counterparty has not good API definition. Your other relationships is about using Warehouse class. I think (just guess) the other classes only use Warehouse class services (public methods). In this case, they can be Associations. Otherwise, if they need an instance of Warehouse as a part, they are Aggregations.
Aggregation is evil!
Read the UML specs about the two variants they introduced (p. 110):
none: Indicates that the Property has no aggregation semantics. [hear, hear!]
shared: Indicates that the Property has shared aggregation semantics. Precise semantics of shared aggregation varies by application area and modeler.
composite: Indicates that the Property is aggregated compositely, i.e., the composite object has responsibility for the existence and storage of the composed objects (see the definition of parts in 11.2.3).
Composite aggregation is a strong form of aggregation that requires a part object be included in at most one composite object at a time. If a composite object is deleted, all of its part instances that are objects are deleted with it.
Now, that last sentence clearly indicates where you should use composite (!) aggregation: in security related appications. When you delete a person record in a database you need to also delete all related entities. That often used example with a car being composed of motor, tires, etc. does not really fit. The tires do not vanish when you "delete" the car. Simply because you can not delete it. Even worse is the use of a shared composite since it has no definition per definition (sic!).
So what should you do? Use multiplicities! That is what people usually want to show. There are 0..n, 1, etc. elements related to to the class at the other side. Eventually you name these by using roles to make it explicit.
If you consider DispatchingWaybill and ReceivingWaybill it looks like those are association classes. With the right multiplicities (1-* / *-1) you can leave it this way. (Edit: note the little dots at the association's ends which tell that the class at the opposite has an attribute named after the role.)
Alternatively attach either with a dashed line to an association between the classes where they are currently connected to.
I have to develop a class, part of a financial application, which receives two properties and returns two results. Before you think that it is not a class, but method(s), I have to say that I have to persist both: the two user-provided parameters and the two outputs. Let's illustrate like follows in this mock:
----------------
|PetWash |
|----------------|
|petWeight |<- user provided
|petHeight |<- user provided
|ammountSoapUsed |<- system calculated
|price |<- system calculated
----------------
Should I do calculations in model classes? eg., the same model class that represents this entity should enclose the methods that do these calculations? Or should I create a kind of "calculation Engine" that would return data and store it in calculated fields?
If the first case, should I invoke calculations in the getter methods or just create a "calculate" method which would update the value for ammountSoapUsed and price? In this sense, should I just store petWeight and petHeight and calculate ammountSoapUsed and price everytime that they are needed (remember that in the real-life case calculation is much more complex)?
In truth, I'm not interested in what I could do, but in what OOP best practices recommend to do. Can you help me?
The ideal object oriented approach starts with an analysis of the problem domain. PetWash does not sound like a problem-domain concept, it sounds like the record of a pet washing event that occurred, or an estimate for a pet washing that you will offer to a customer. Which is it? Be clear.
Model the problem domain to better understand the information and operation requirements. Classes must resonate with the real world of the problem domain. CalculationEngine certainly doesn't fit this criterion. Classes can certainly do calculations, but they should provide business value recognizable to a non-technical business person. Assuming the purpose is to provide an estimate for a potential customer, what makes sense to me is an instance of a Customer class that links to multiple instances of an Animal class, where each has a height and weight. Linked to an instance of a Customer class might be instances of an Estimate class that links to instances of the Animal to be washed. And so on.
Your question is too low-level. You should neither invoke calculations in getters nor provide a calculate() operation. Focus on operations that would make sense to a non-technical business person. Again, assuming you are providing an estimate, provide operations on an instance of a Customer that add or update his or her Animals. Provide an operation that provides an Estimate when given one or more of the customer's Animals. That Estimate encapsulates the rules and calculations. If a Customer agrees to an Estimate, you can use that to manage your soap inventory or whatever. Keep the implementation hidden behind this problem-domain facade so you can swap out a bad implementation when (not if) you need to.
Most of the OO code I've seen these days dismisses the problem domain altogether and seems to build applications out of chewing gum and duct tape while trying to be agile. A good model of the problem domain is relatively durable. In stark contrast, a focus on the solution domain (a duct-taped design de jour) is not durable and is the cause of much cost overrun, expensive re-work, and canceled projects. Don't make your project one of those!
I am getting really confused about OOD when designing relatively large system. Always, we talk about has-a relationship between two entities. My question is about which one owns the other?
when designing a parking lot, there are many parking space. Should the car has an data field called parking space, or should the parking space hold the car? or both?
in a library reservation system, I am assuming there is a class Library, a class Book, and a class User. Shall the user call checkout(book), or the book call checkout(user), or the library call checkout(book, user)?
It's been very confusing for me. Any comment/suggestion is welcomed.
Lily
It depends on the situation, and what you mean by "own".
In your first example there is a one-one relationship between a car and a parking space. From a database perspective you will have to make a judgement about which should "own" the other (which table 'owns' the foreign key). You would base this judgement on expected usage - for example - since a parking space is likely to remain fixed, but you have cars coming and going all the time, it might make more logical sense for the carpark to "own" the car. That's where your design skills come into play.
In the second example, it seems to me that a single book can only be checked out to one user at a time, and "checking out" is an action that occurs on a book. Therefore the correct solution is Book.checkout(user). Building on that, a user is likely to checkout more than one book at a time, so I would be inclined to do have a checkout method on Library, such that Library.checkout(Books[], user) called Book.checkout(user) in turn.
For #1, the parking space should keep a record of if it is occupied and if so, what car is in it. Otherwise to see if you could park somewhere, you would have to poll every car to see if they are in that spot.
My immediate thinking for #2 is that it should be Library.checkout(Book, User) such that you make a note that a User has checked out a specific book.
This is heavily dependent on what you're trying to do however, and you should design it in such a way that is easiest for the problem at hand.
Sometimes replicating the data in two places isn't a terrible idea as long as you keep it synchronized. For instance, if you need to know where a specific car is parked, you're going to end up wanting to keep track of that data in the Car class as well, otherwise you're going to have to poll every parking spot to know if that car is parked there.
In Object Oriented design the object can be considered an entity. At this point you may use the Entity relationship modelling to better understand who has to own what.
When you design your model you shouldn’t care how you are going to implement it. I mean you shouldn’t think who is going to own what because this is another process of the design that is when you are going to convert your model to objects (that can be data table, XML, C# object ,…. ) : only at this point against the relationship the entity got you can decide who has to own what(sometime even against the requirements as I’ll show you later).
At the design time you must focus just on the requirements you have. In the case of the car and car parking you should think about :
How many park car one can occupied ?
How many cars a park can host ?
What kind of answer has my system to answer ? EX: as user I want know where a car is parked against its car plate number (in this case the previous answer would be wrong because if you let the park own the car you should iterate through the park to get what car is on it)
As you can see it really depends by you business requirements especially when you have “one-to-one” relationship(as in this case).
So I can suggest you to have a look at “Entity relationship Modelling” and stick to its concept to better design you object model.
In this case undoubtedly parking space should hold a car(it's called aggregation), because the relationship between car and parking space isn't permanent(different cars can be parked in the same parking place in the same day)
In this case, I think, the user wants to get a book, so the GUI of this system must have some button(or smht else) that user has to click to reserve a book. So, user calls a method checkout(book) of the system(object Library represents it) to check if the book is free(or available). Then the system(Library) checks whether the book wasn't reserved earlier by other user, so it calls method Book.check() for all instances of this book. In such solution every user account in the system should have a list of reserved books which method Book.check() uses.
To think out of box, I don't think the examples you provided have a natural "has a" or "owns a" relationship, and there are more relationships than "has a" or "owns a". In my opinion, I'd like to use a loosely coupled relationship for your examples, in implementation perspective, I would use a map to describe and maintain this relationship, which means, for a parking lot and a car, I would put a map in the Parking class, and map its slots to cars, if we find a slot existing in the map, we know that slot is occupied, if not, it's a free slot, for me, it doesn't make much sense either saying car owns the slot or the slot owns the car; for the library example, the same thing, the book and its borrower are in a very loose relationship, I'd put a map in the Library class, and map the book to its borrower. And who's the guy really does the checkout action? it's either the library staff or the auto machine or simply the library, so we can have a library.checkout(user, books), and inside the method, put books and user into the map.
For the bonus, what is really a "has a" relationship scenario? not a man has a car, this is not really a "has a", even we have "has a" in the sentence (don't let the human language mislead you), this just means, inside the car's class, there is a String field called ownerName or ownerId, that's it. One example for a real "has a" relationship scenario is human has a heart or a car has an engine, which means, in the implementation, there is really a Heart class field inside the Human Class.
How beautiful the object oriented design is!
Allowing a store whether a product is available in the stock of another store partner, the latter may either accept or reject the request, in all cases the applicant is informed of réponse.
I want to implement a diagram class.
Now I have a class product, and a class list of collections of products.
I don't know how to represent a class of operation "request for product availability.
Is there a design pattern corresponding to this situation?
or a simple example of class diagram would be welcome.
I'm assuming that you are talking about representing your design in some suitable diagram, in which case you need to study some "Modeling Language" - probably the most widely used today being UML. This is a big topic, but you could start here.
Now diagrams such as these are really only useful when your design reaches some level of complexity. Here you are thinking about just a couple of classes and one method a diagram won't help much. So maybe you are doing this as a learning exercise?
You probably need both a Class diagram and a Sequence Diagram.
The major thing you seem to be confused about is how to represent Operations, they are just listed against the class. So your Store class would have an operation transferInventory().
So your class diagram is very simple only a couple of classes Store, Product. But the interesting thing is that your Sequence diagram will show that you have more than one instance of the Store class: StoreA, StoreB and the instances communicate with each other.
One thing you haven't talked about: how did StoreA know that StoreB exists? Why did it choose that Store to ask for a product. There's some additional classes here such as a registry of Stores. I would be much more interested in figuring out that than in drawing diagrams.