Hello I'm try to understand one example of UML to represent a System of vending machine. In this example are 3 classes Customer, Item and Balance. The problem here is Why Balance is represented as independent Object. I don't understand why because I think that should be a Customer attribute. Could help me to understand why?
Thanks.
Because it is important to the modeled domain.
Think of it this way: attribute and association is the same thing (Association Class vs. Attribute), only you visualize it differently.
In the very same sense you could have a class Image to which Customer would point, or class String to which association name would point.
However since you are modeling a vending machine state, you care about who (Customer) is buying what (Item) with which resources (Balance).
p.s. (unrelated to question, but related to the model): generally don't add accessor methods to your models, they are superficial, and login/logout sounds to me like overloading of concepts
Related
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!
Let's say there are two classes related to each other via some relations. For example, a Student maintains a list of the Classes he takes, and each Class has a list of Students taking it. Then I am afraid of letting the Student directly being able to modify its set of Classes, because each modification would have to be followed by a similar modification of a Class's list of Students, and vice versa.
One solution is to have a class whose sole purpose is to keep track of Class-Student relations, say Registrar. But then if some method in Student requires knowledge of its Class list, the Student needs to be passed the Registrar. This seems bad. It seems Student shouldn't have access to the Registrar, where it can also access other Students. I can think of a solution, creating a class that acts as a mediator between Student and Registrar, showing the Student only what it needs to know, but this seems possibly like overkill. Another solution is to remove from Student any method that needs to access its classes and put it instead in Registrar or some other class that has access to Registrar.
The reason I'm asking is that I'm working on a chess game in Java. I'm thinking about the Piece-Cell relations and the Piece-Player relations. If in the above example it wasn't OK for a Student to have access to the Registrar, is it OK here for a Piece to have access to the Board, since a Piece needs to look around anyway to decide if a move is valid?
What's the standard practice in such cases?
If relations can be changed - classes should be decoupled as much as possible, so along with each class create an interface, do not introduce tied relations between classes.
High level of separation you can achieve using intermediate services/helpers which encapsulates logic of communication between classes, so in this case you should not inject one class to an other even both are abstracted by interfaces, basically Student does not know anything about Class, and Class does not know anything about Student. I'm not sure whether such complexity is makes sense in your case but anyway you can achieve it.
Here is you may find a useful design pattern Mediator which can encapsulate interaction logic between two decoupled entities, take a look at it.
With the mediator pattern, communication between objects is
encapsulated with a mediator object. Objects no longer communicate
directly with each other, but instead communicate through the
mediator. This reduces the dependencies between communicating objects,
thereby lowering the coupling.
What I think you have found in your pretty nice example and explanation is that OO does not solve all problems well. As long as the responsibility is well shaped and sharp, everything is fine. And as long each responsibility fits in exactly one bucket (the class), it is pretty easy to design. But here you have a tradeoff:
If I define for each responsibility a separate class, I will get a bloated design that is pretty difficult to understand (and sometimes to maintain).
If I include for each separate responsibility at least one interface, I will get more classes and interfaces than I need.
If I decide that one of the two classes is responsible for the relation as well, this one object has more knowledge than usual about the other.
And if you introduce in each case a mediator or something similar, your design will be more complex than the problem.
So perhaps you should ask the questions:
What is the likelihood that the relation between the 2 objects will change?
What is the likelihood that the relation will exist between more 1 type of objects at each end?
Is that part of the system a highly visible part, so that a lot of other parts will interface it (and therefore will be dependent on it)?
Take the simplest solution that could possibly work and start with that. As long as the solution is kept simple, it is only your code (you don't design a library for others), there are chances that you can change the design later without hassle.
So in your concrete case,
the board field should have access to the whole board XOR
the figure on the field should have the responsibility of moving XOR
there should be an object type (ChessGame?) that is responsible for the overall knowledge about moving, blocking, attacking ...
I do think that all are valid, and it depends on your special "business case" which one is the most valid.
I am currently implementing something similar to an hospital intra site, where doctors can see info about their patients.
Currently, I have a LOT of info regarding each Client: his full name, date of birth, blood type, where he lives, diseases he had, etc.
My first attempt was something of the form:
class Client {
private string fullName;
private Date dateOfBirth;
...
public Get/Set FullName()
public Get/Set DateOfBirth()
...
}
which is basically putting everything together under the same class.
After a while I decided that maybe I should pack together similar concepts into a more general one. For example, I can encapsulate both userName and password into the same concept -- LoginInfo, for example.
If doing this, should I provide all the getters/setters on the Client class that delegate the work to the correct inner concepts, or should I just put getters for the concepts themselves? The first approach would shield the outside world to the Client class implementation, but then maybe, we wouldn't win that much by having all these innner concepts.
Should code outside the Client class even know the different kinds of concepts that'd use inside it?
Any other idea / approach?
I still don't know much about what methods I'll need to have on the Client class. Maybe if there are a lot, it'd be definetely good idea to use small inner concepts to group similar methods in themselves, instead of having such a loose coupled big class.
The data of Client will all be persisted using a standard database, if that makes any difference.
I would say it is useful to pack related pieces of data into common classes. I would only provide delegating getters/setters in Client for very commonly used properties though (if even then - it should be a case by case decision). If a concept makes sense in the problem domain, it is fine to expose it to the outside world too. Your LoginInfo is a marginal detail in this regard, but disease history, health check results etc. etc. are prime candidates for this.
I would also recommend you check out Martin Fowler's excellent Analysis Patterns, which dedicates a chapter to health care patterns; you may probably get some useful ideas out of it.
Something to consider when deciding how to organize data: are there any requirements for tracking history of data. For example, do you need to know what the patient's address was 5 years ago (in addition to knowing their current address, of course)? If so, making that "historically-sensitive" data its own class, will likely make it easier for you down the road. Of course, some data won't be "historically-sensitive" - date of birth for example. :)
Something else to consider: what data will be shared among patients? If you maintain data about family medical history, should that data be shared among siblings? If so, then encapsulating that data in its own object will save you lots of copy/synchronization pain later.
These aren't the only considerations when analyzing your data. But they're definitely part of the puzzle.
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.
So there are many ways of structuring objects (I'm talking of OOP here). For the question, I will use the classic "Car" example of OOP. Basically, How do I know when to make the car an object, or the wheel of a car an object, when both program structures would accomplish the goal?
How do I classify and categorize the parts of an object to determine whether or not they are better suited as simple attributes or variables of an object, or if they really need to be an object themselves?
Well the first thing you have to realize is the OOAD ("Object-oriented analysis and design") is a tool and not a means to an end. What you get out of that process is a model, not a true representation of what you're modelling. That model makes certain assumptions. The purpose of that model is to solve a problem you have.
So how do you know how to design objects? How do you know if you've done it right? By the end result: has it solved your problem?
So, for the Car example, in some models a car count could simply be an integer count, for example the car traffic through an intersection in a traffic model. In such a model rarely do you care about the make, model or construction of cars, just the number. You might care about the type of vehicle to the point of is it a truck or car (for example). Do you model that as a Vehicle object with a type of Car or Truck? Or just separate carCount and truckCount tallies?
The short answer is: whichever works best.
The normal test for something being an object or not is does it have behaviour? Remember that ultimately objects = data + behaviour.
So you might say that cars have the following state:
of wheels;
Height of suspension;
Left or right drive;
Colour;
Width;
Weight;
Length;
Height;
of doors;
Whether it has a sunroof;
Whether it has a stereo, CD player, MP3 player and/or satnav;
Size of the petrol tank;
Number of cylinders;
of turbo charges and/or fuel injection;
Maximum torque;
Maximum brake-horsepower;
and so on.
Chances are you'll only care about a small subset of that: pick whatever is relevant. A racing game might go into more detail about the wheels, such as how hot they are, how worn, the width and tread type and so on. In such a case, a Wheel object could be said to be a collection of all that state (but little behaviour) because a Car has a number of Wheels and the Wheels are interchangeable.
So that brings up the second point about objects: an object can exist because of a relationship such that the object represents a complete set of data. So a Wheel could have tread, width, temperature and so on. You can't divide that up and say a Car has tread but no wheel width so it makes sense for Wheel to be an object since a Wheel in it's entirety is interchangeable.
But again, does that make sense for what're doing? That's the key question.
Don't start out by classifying things - seems like people are too eager to start building inheritance hierarchies.
write down a list of specific, concrete scenarios - what your app will do, step by step. An object model is only useful if it does what you need it to do - so start working back from the scenarios to see what common objects and behaviours you can shake out of each one.
identify the "roles" in your scenarios - not necessarily actual class names - just vague "roles" that turn up when you think through concrete scenarios for how your software will work. These roles might later become classes, interfaces, abstract classes - whatever you need - at the start they're just placeholders for doing a type of work.
Work out what each role "does". The key is having a bunch of named roles - that identify things that the objects will do. Thins is about distilling out a set of things each role can do - they might do the whole thing, or put together a bunch of other objects to do the work, or they might co-ordinate the work... it depends on your scenarios.
The most important thing in OOD/OOP - is OBJECTS DO THINGS - not what's inside them - what they do.
Don't think about inheritance early on - because it will tie you up in overcomplicated hierarchies and make you think in terms of SQL-oriented programming rather than object-oriented programming. Inheritance is just one way of sharing common code. There are lots of other ways - delegation, mixins, prototype-based programming...
Here are some guidelines I came up with to help with this:
What should be on a checklist that would help someone develop good OO software?
There are some good answers here, but possibly more than you were looking for. To address your specific questions briefly:
How do I know when to make the car an object, or the wheel of a car an object, when both program structures would accomplish the goal?
When you need to distinguish one instance from another, then you need an object. The key distinction of an object is: it has identity.
Extending this answer slightly to classes, when the behaviors and/or properties of two similar objects diverge, you need a new class.
So, if you're modeling a traffic simulation that counts wheels, a Vehicle class with a NumberOfWheels property may be sufficient. If you're modeling a racing simulation with detailed road-surface and wheel-torque physics, each wheel probably needs to be an independent object.
How do I classify and categorize the parts of an object to determine whether or not they are better suited as simple attributes or variables of an object, or if they really need to be an object themselves?
The key distinctions are identity and behavior. A part with unique existence is an object. A part with autonomous behavior requires its own class.
For example, if you're creating a very simple car-crash simulation, NumberOfPassengers and DamageResistance may be sufficient properties of a generic Vehicle class. This would be enough to tell you if the car was totalled and the passengers survived. If your simulation is much more detailed, perhaps you want to know how far each passenger was thrown in a head-on collision, then you would need a Passenger class and distinct Passenger objects in each Vehicle.
I like Wirfs-Brock's Responsibility-Driven Design (RDD) and also recommend this updated (free paper) Responsibility-Driven Modeling approach by Alistair Cockburn.
In over 15 years of OO development, whenever I've felt I'm getting lost in a software architecture, going back to the RDD basics always helps me clarify what the software is supposed to be doing and how.
If you like a test-driven approach, this article shows how to relate RDD to mocking objects and tests.
Attributes or variables are often "base" types of a language. The question is what you can sensibly abstract.
For example, you can reduce a Wheel to descriptors made up of base types like integers, floating-point values and strings, which represent characteristic attributes of any wheel: numberOfTreads, diameter, width, recommendedPressure, brand. Those attributes can all be expressed with base types to make a Wheel object.
Can you group some of those attributes into a more abstract arrangement that you can reuse, independent of a Wheel? I think so. Perhaps create a Dimensions object with the attributes diameter and width. Then your Wheel has a Dimensions object instance associated with it, instead of diameter and width. But you could think about using that Dimensions object with other objects, which may not necessarily be Wheel instances.
Going up the list, you can reduce a Car to be made up of base types, but also other objects, such as Wheel objects. It is sensible to do so, because other motor and non-motor vehicles (such as a Bicycle) also contain Wheel instances.
Abstracting Wheel and Dimensions lets you re-use these object types in different contexts you may not initially consider. It makes your life a little easier because you have less code to rewrite, in theory.
If you can create a hierarchy of objects, to the point where the deepest, lowest-level object is only made up of a few base types, that is probably a good place to start.
If it's true that "both program structures would accomplish the goal" equally well, then it doesn't matter which you pick.
If, however, the program does not have a single fixed "goal" but will evolve significantly over its lifetime, then pick either one for now, and refactor as necessary as future modifications dictate. We call it "software" for a reason.
Grow your classes bottom-up.
1) Class boundaries and semantics depend on context. Until you have a context, you don't have anything. (You may not even have a car in your example). Context is given by the user story (or use case).
2) Throw all the state and behavior suggested by the given context into one class (you could name this after the user story if you would like).
3) Use systematic Refactoring to tease this class apart into separate classes. While refactoring, use existing classes as reuse opportunities.
When you're done, you'll have a set of well-defined classes that are just enough to fulfill the needs of the given user story (and the user stories that came before).