I have an ERD Diagram of an E-commerce with the following entities Product , Tag , ProductTag,Category and other entities of course.
I tried to convert it into class diagram as follows:
1- removed the id
2- converted the foreign key into object of the type i'm refering to(product_id converted into => product: Product)
my question is , is this good approach to follow on all my entities? does it like achieve the SOLID principle? I have a presentation in 2 days and I want to be very sure of what I have made , any comment or modification would be really enough .I also chose these tables because they represent one to many and many to many. thanks in advance.
Basically your approach is correct. It's just a couple of UML specifications you got wrong.
The label in the middle of the connectors is just the name of the connector. Unless you do some OCL wizardry this name is meaningless. There is a way to adorn it with a black triangle to show the reading direction. This sometimes helps business people to understand how classes are related to each other (see Fig. 11.27 on p. 202 of UML 2.5). But usually you would not use it.
The shared aggregation has no semantics (p. 110 of UML: Indicates that the Property has shared aggregation semantics. Precise semantics of shared aggregation varies by application area and modeler.). So leave the open diamond away. Composite (filled diamond) can be used to show responsibility (when I'm killed I will kill my composites first). Usually it adds too little to be really useful, it only heats up the futile composition-discussion.
The navigation-direction is incorrect. The AC in the middle sees both connected classes so it's shown without any arrow. If you have an additional (directed) association you place it as lone (extra) connector. In that case put role names towards any end. That makes navigation clearer than just a simple arrow. I for myself use arrows only on rough sketches on the drawing board.
P.S. Just noticing that you have operations in your classes that have the same name as the class and take one paramter being also the class. I would guess you intend to show a constructor here. In that case you would make it Classname():Classname and provide only the paramaters that are needed for the constructor. Else these opreations don't seem to make much sense. Similarly the CRUD operations seem to work on a list of 'itself' which is also probably not desired. You would have a collection class which handles the base class where these operation make sense. So to summarize: you would only add getter/setter operations for the (private) properties matching the columns from your table.
P.P.S.: As per Christophe's comment it's a good idea to adorn the class instantiation operation with a <<create>> stereotype which highlights its purpose. See p. 196 of UML 2.5:
This stereotype is part of the standard (see p. 677) and the table on p. 678 states:
Specifies that the designated feature creates an instance of the classifier to which the feature is attached.
On the modeling part of your question, there’s already a perfect answer. For the records, I’d nevertheless like to add a complementary answer on the SOLID part:
Single responsibility: your classes have more than one reason to change, because you may want to change Product for what it is (e.g. add more product-related attributes), but you may also want to change the class to add new getByXxx() operations to find products in the database based on other criteria, independently of what a product really is. SO it's not complying.
Open-closed principle: we cannot tell
Liskov substitution principle: in absence of inheritance, this is not relevant. Moreover, you couldn't tell without having precondition, postcondition and invariant constraints.
Interface segregation principe: is probably not compliant, because you impose an implicit interface that all inheriting class would have to provide, even if they don't need it (e.g. products not stored in a database). A first step in the right direction, would be to use an interface for the common database operations.
Dependency inversion: we cannot tell but probably it isn't , because update(), delete(),... probably depends on some database, so that you can't switch it to another database. With DIP, you'd inject the database in the class that use it, so that you could at any moment inject another database that offers the same interface.
You didn't ask, but your design seems to correspond to active records. If you want to go for a cleaner, more SOLID design, you should prefer factor out the database related code to either repositories or table data gateways.
Related
I have a problem with the boundaries of aggregates. I was trying to read about aggregates, aggregate roots, and boundaries, looking for some code examples but I still struggle with it.
The app that I'm working on is an app to manage architecture projects.
Among the screens in the app there will be a screen with all details for the selected project, and one with all jobs for the selected constructor.
I have one AggregateRoot - ArchitectureProject.It has an Architect, Stages, etc. and it has a list of ConstructorJobs (as it has to be on the screen with project details). ConstructorJob has its name, some value, and a Constructor. A Constructor can have some ConstructorType. As for me, Constructor is another AggregateRoot. I have a problem with ConstructorJob. Where should I place it? What should be responsible for managing it?
I was trying to thing what cannot exist with what, and ConstructorJob cannot exists without Project, but on the other hand it has to have Constructor as well...
I can't imagine that Constructor would belong to Project Aggregate, as ConstructorType would be 4th level child to id, so searching for all constructors of that type would be painful, wouldn't be?
I would appreciate any explanation, how to handle such cases.
I think you are missing an important rule which usually makes your life a lot easier:
Rule: Reference Other Aggregates by Identity
See also Vaughn Vernon's Book Implementing Domain-Driven Design, chapter 10 - Aggregates.
It is important to note that Aggregates in the sense of domain-driven design are not so much focused on if the existence of one aggregate makes sense without the other. It is more about transactional boundaries. So an aggregate should create a boundary around elements that should only change together within the same transaction - to adhere to consistency.
So I guess, that you will change your Project in different use cases you would change the Constructor - which I guess can be referenced in different projects.
This means you should reference other aggregates within aggregates only by id which avoids modelling huge aggregates with deep hierarchies. It also means that if your aggregates tend to grow bigger over time that you might have missed some new aggregate which you initially modelled as entity and should be an aggregate on its own.
As for me, Constructor is another AggregateRoot. I have a problem with ConstructorJob. Where should I place it? What should be responsible for managing it?
In your case I would model it the following way:
The ConstructorJob is a Value Object which holds some data (name, etc.) and also a reference to a Constructor aggregate. But this reference is not a reference in terms of object reference like you would do it with a child entity of an aggregate root. The constructor aggregate is referenced by an identifier (UUID, integer or whatever you are using as id type) in the ConstructorJob.
The ConstructorJob value object would be part of the Project aggregate. The project aggregate could of course directly hold the id of the constructor aggregate but I guess in your case the value object might fit quite well.
So I have to make a class diagram for a Unity game I made as part of a project.
Trouble is I have to make a class for every script, of which there are 60.
The guidelines given to me simply states: Create a class diagram of your game.
So should I be splitting this up into several different class diagrams or literally just one inevitably disgusting 60 class diagram?
Your guidelines already told you what to do for this project: "Create a class diagram of your game." If this is a class project, create a single horse blanket, make your professor happy, and get a good grade.
However, on a real-world project, you should create many micro-subject-area diagrams for your audience. Review with each person only the diagrams that matter to them. That's how you (and your victims) can survive very large projects.
To create micro-subject-area diagrams, create a set of diagrams, each containing 7 ± 3 classes. Every class has only one fully-defining diagram showing all of its compartments and associations. Everywhere else, the class should appear only with its class name (to help define other classes) and a hyperlink. The hyperlink makes it work like an edge connector that takes you to its fully-defining diagram. (If you use MagicDraw, there is a free plug-in available, called AutoStyler, that automates this.)
It is legitimate to split up class diagrams, as class diagrams are meant to clarify things, which a gigantic mega class diagram arguably does not do. As such, class diagrams should usually concentrate on a few specific aspects that you want to show:
Do you want to provide a detailed structural representation of a given set of classes? If so, only depict these classes with all members, but skip any other classes (e.g., do not draw them as class nodes, but instead just mention their names as member/parameter types where appropriate).
Do you want to provide the class structure related to a particular functionality? If so, draw the relevant set of classes, but skip irrelevant members (e.g. members that have to be there for the sake of infrastructure support, but that are not a part of the actual business logic you are focusing on).
etc.
Now, when there is any expectation of completeness rather than a mere overview, it needs to be clear what parts of the diagram are complete and which ones are abbreviated. Again, this is possible in various ways:
As in the first bullet item above, mentioning a type name without drawing it is a clear indication that there is another type that is not depicted in the current diagram, without making the depicted class incomplete.
Alternatively, you can make use of "natural boundaries by abstraction" in your code: If you use classes from an extensive hierarchy, it may be sufficient to draw only the base class, or a few general base classes, in one diagram, while detailing the actual class hierarchy (without any of the context from the other diagram) in a separate diagram.
Two remarks on your specific question:
In your case, "60 scripts" sounds like various of them may easily fall into the last case, allowing you to separate overall architectural diagrams from a class hierarchy diagram.
You say there are "guidelines". If this is for some kind of competition or for any other kind of evaluation (e.g., for studying), take all this advice with caution: Internal grading guidelines might not necessarily be congruent with what would be practical/useful in an actual project.
tl;dr
Create as many class diagrams as you need
Avoid wallpaper diagrams only
Create wallpaper diagrams, though. But assemble them from existing diagrams.
Try to spot sub-domains (things that belong together) and place them in one diagram
Why and how are dependency relationships used?
I've come across a PiggyBank example where the Analysis Model consists of a class diagram with dependency relationships.
They use two relationships "use" and "instantiate" to describe the relationships between the classes.
I don't agree with the relationship that the boundary class TransferMoneyForm has a "use" to the TranferMoneControl. I believe it should be the other way around.
Can someone exaplain to me how these two relationships should be used. Thank you in advance.
The diagram shown there is not a correct and full UML class diagram. In such all the associations and generalizations should be defined, and what is abstract, what is public or not. To show what descends from what, what is hidden, what will be never instantiated and what fields of one class has types of other classes. Here we see only information about the
functions.
And it is logical. If you'll look at the previous chapter, there is written: "A control class represents a self-contained process..." So, they are talking on processes, not classes, instances and fields.
It is NOT a class diagram. And nowhere is said that it is. It is named "Transfer Money Participants diagram". They do use the elements of the class diagram, but not to the fullest and so create something more common. It is some approximate undefined diagram on some classes, something between class, communication or component diagrams. Maybe, it is the old style of IBM? Experts (What's the best UML diagramming tool?, 1st answer) say, "IBM Rational Software Architect did not implement UML 2.0". )
As for the question, who uses whom... According to Sparx VP UML, a "usage dependency" is a "relationship in which one element requires another element ... for its full functionality". According to wiki, "The client element somehow "uses" the supplier". Here the form hasn't sense without the controlling class, and vice versa. So, I'd say, the use goes in both sides. But more honest would be to create a normal communication or component diagram. The class diagram has NOT an element to say about sending and accepting the messages. And the "use" is definitely not for it. And when they have decided not to use logic, they can put there virtually anything.
If you are making a class diagram and one your class uses function(s) of another one, that is the case to draw a use dependency connection.
I am trying to figure out if it is correct to put in the fields of the particular class a reference to an object/collection that this class is related with.
Let's say I have a class University that aggregates many instances of Student class. When I put on my diagram both classes, I add the relationship of aggregation between them.
And now the question: Can I add in University a field like 'students : Student[]'? Do I have to? Or maybe I must not?
Thanks in advance,
Piotr
Attributes own association properties in UML 2. This is new and it is not always easy to understand the concept. I didn't understand why we need an attribute till I have seen the following demo.
The golden rule is that attributes should be created in order to save association information in the model. I have found an interesting teaching session on association and aggregation in UML 2.
It is a 2m30s flash demo
http://www.download-omondo.com/AggregationAndComposition.swf
The above association creation is for expert level, I mean modeler who wants clean design and clean model as well as perfect metamodel. If you don't care then just create an association at model level and it would do the job but the code generation will not be done. It means that mappings for database will needed to be created at code level later by developers.
To understand the difference between both kinds of associations see this other flash demo at: http://www.download-omondo.com/association.swf
It depends on what you are doing with your model, but generally, you shouldn't have to use an attribute for this, you can use an association instead. Associations are able to contain more information that attributes, such as whether they are composite or shared, which ends are navigable, multiplicity on each end, named endpoints, etc.
One benefit of associations is that one association can actually represent a property on each class it is connected to, while an attribute only represents a property on the class it belongs to.
So, in your case, University has Students, so you'd draw an association from University to Student, naming each endpoint and setting the multiplicity correctly.
Now when you go to generate code from your model, just be sure to take into account associations as well as attributes. This way you won't need to add the properties both as attributes and associations, just as associations. I have a few diagrams I've tested this approach with, generating sql and php code from the xmi via an xsl transform, and it works quite well... if you'd like more details I can dig it up.
There are 3 types of relations : association, aggregation and composition. composition is a specialization of aggregation, aggregation is a specialization of association.
Using one or the other depends on the phase of your analysis. You could just use association in first draft and then refine it later to aggregation or composition, the difference with aggregation is that a student had no meaning out of one University Universe. If there are several universities instances, it would be aggregation rather.
If you use relations, there's no need to and you shouldn't add students[] because it is redundant. And if you do that you lose the semantics of the 3 types of relations.
We are developing an extension (in C# .NET env.) for a GIS application, which will has predefined types
for modeling the real world objects, start from GenericObject, and goes to more specific types like Pipe and Road with their detailed properties and methods like BottomOfPipe, Diameter and so on.
Surely, there will be an Object Model, Interfaces, Inheritance and lots of other essential parts in the TypeLibrary, and by now we fixed some of them. But as you may know, designing an Object Model is a very ambiguous work, and (I as much as I know), can be done in many different ways and many different results and weaknesses.
Is there any distinct rules in designing O.M.: the Hierarchy, the way of defining Interfaces, abstract and coclasses enums?
Any suggestion, reference or practice?
A couple of good ones:
SOLID
Single responsibility principle
Open/closed principle
Liskoff substitution principle
Interface segregation principle
Dependency inversion principle
More information and more principles here:
http://mmiika.wordpress.com/oo-design-principles/
Check out Domain-Driven Design: Tackling Complexity in the Heart of Software. I think it will answer your questions.
what they said, plus it looks like you are modeling real-world entities, so:
restrict your object model to exactly match the real-world entities.
You can use inheritance and components to reduce the code/model, but only in ways that make sense with the underlying domain.
For example, a Pipe class with a Diameter property would make sense, while a DiameterizedObject class (with a Diameter property) with a GeometryType property of GeometryType.Pipe would not. Both models could be made to work, but the former clearly corresponds to the problem domain, while the latter implements an artificial (non-real-world) perspective.
One additional clue: you know you've got the model right when you find yourself discovering new features in the code that you didn't plan from the start - they just 'naturally' fall out of the model. For example, your model may have Pipe and Junction classes (as connectivity adapters) sufficient to solve the immediate problem of (say) joining different-diameter pipes to each other and calculating flow rates, maximum pressures, and structural integrity. You later realize that since you modeled the structural and connectivity properties of the Pipes and Junctions accurately (within the requirements of the domain) you can also create a JungleGym object from connected pipes and correctly calculate how much structural load it will bear.
This is an extreme example, but it should get the point across: correct object models support extension and often manifest beneficial unexpected properties and features (not bugs!).
The Liskov Substitution Principle, often expressed in terms of "is-a".
Many examples of OOP would be better off making use of "has-a" (in c++ private inheritance or explicit composition) rather than public inheritance ("is-a")
Getting Inheritance right is hard. Doing so with interfaces (pure virtual classes) is often easier than for base/sub classes
Check out the "principles" of Object oriented design. These have guidelines for all the questions you ask.
References:
"Object oriented software construction" by Robert Martin
http://www.objectmentor.com/resources/publishedArticles.html
Checkout the "Design Principles" articles at the above site. They are the best references available.
"BottomOfPipe"? Is that another way of saying the depth of the Pipe below the Road?
Any kind of design is difficult and can be done different ways. There are no guarantees that your design will work when you create it.
The advantage that people who design ball bearings and such have is many more years of experience and data to determine what works and what does not. Software doesn't have as much time or hard data.
Here's some advice:
Inheritance means IS-A. If that doesn't hold, don't use inheritance.
A deep hierarchy is probably a sign of trouble.
From Scott Meyers: Make non-leaf classes interfaces or abstract.
Prefer composition to inheritance.