I'm trying to understand loose coupling vs tight coupling, and I've hit a wall regarding the word dependent class. Can someone please tell me/or provide an example of what is a dependent class?
Thanks in advance!
This is not directly related to C++ and is not a direct C++ programming problem. But in your context the word dependence refers to the UML.
UML or the Unified Modeling Language is a design language that uses diagrams to illustrate the architecture and interaction of code, and is a handy tool to visualize object oriented systems.
When 1 class has a dependence on another it indicates that there is an arrow originating on the dependent class and terminating on the depended-on class.
Dependence can be loosely defined as there exist calls to the methods of 1 class in another or there exist initializations of objects of 1 class in another. Implying that the latter depends on the former
like this
Read more here: https://www.uml-diagrams.org/dependency.html, https://en.wikipedia.org/wiki/Unified_Modeling_Language
Related
Is it ppssible to implement a concatenative inheritance or at least mixins in C++?
It feels like it is impossible to do in C++, but I cannot prove it.
Thank you.
According to this article:
Concatenative inheritance is the process of combining the properties
of one or more source objects into a new destination object.
Are we speaking of class inheritance ?
This is the basic way public inheritance works in C++. Thanks to multiple inheritance, you can even combine several base classes.
There might be some constraints however (e.g. name conflicts between different sources have to be addressed, depending on use case you might need virtual functions, and there might be the need to create explicitly a combined constructors).
Or is inheritance from instantiated objects meant ?
If it's really about objects and not classes, the story is different. You cannot clone and combine object of random type with each other, since C++ is a strongly typed language.
But first, let's correct the misleading wording. It's not really about concatenative inheritance, since inheritance is for classes. It's rather "concatenative prototyping", since you create new objects by taking over values and behaviors of existing objects.
To realize some kind of "concatenative prototyping" in C++, you therefore need to design it, based on the principle of composition, using a set of well defined "concatenable" (i.e. composable) base classes. This can be achieved, using the prototype design pattern together with the entity-component-system architecture.
What's the purpose
You are currently looking for this kind of construct, probably because you used it heavily in a dynamically typed language.
So keep in mind the popular quote (Mark Twain ? Maslow ? ):
If you have a hammer in your hand, every problem looks like nails
So the question is what you are really looking for and what problem you intend to solve. IMHO, it cannot be excluded that other idioms could be more suitable in the C++ world to achieve the same objective.
Does UML Class Diagram support expressing Concept?
Also, is there any other diagrams that expresses Concept?
Just in case of misunderstanding, I mean the "Concept" in C++ and generic programming.
Basically the question can be answered with an answer to the "base class" question :
"does UML make any attempt to make it 1-to-1 fitting to C++?"
Answer is simply "no".
This is a very common misunderstanding, one can meet people looking for possibilities of expressing a pointer in UML or any other C++ specific things. You will unluckily not find it.
The misunderstanding is comes historically from the availability of C++ code generation engines which come with some UML modeling tools. All those code generation engines come with their own coding patterns to address the transition from model to code. Simply because there is no standard for the transition patterns itself.
UML comes from OMG and OMG has a generation patterns document for (Corba)IDL-to-C++ but none for UML-to-C++.
After reading shortly Wikipedia explanation of C++ "concepts" it looks to me like tool with same goals as generic classes and type constraints in C#
If I understood it correctly then by following older Stack Overflow question Representing a C# Generic Method in a UML Class Diagram it turns out that you should check the http://www.uml-diagrams.org/template.html as already suggested by #Aleks
Basically I mean to model your interfaces and classes as you'd normally do it. Just use the templating annotation and you can also chart some type restrictions using a virtual dependency, inheritance associations between the formal parameters used in the template
You can show in UML all structures used by concept - i.e., functions, algorithms, classes and so on. But not the concept itself, for it is an element creating syntax.
Also, you can't show in UML macros, preprocessor commands, etc.
All these things simply do not belong to model, but to the language/grammar/syntax. There are other tools for their support. Formal grammars, theories, etc. Yes, there are diagrams for it. Look for "formal grammar diagrams" in google and you'll see heaps of them.
I have an app with my own - user defined class and I also use Qt framework libraries to initiate objects of other classes that are built-in. So in my class let's call it 'myclass' I create instances of Qt built-in classes and work on them. THIS IS DONE ... Now, I need to create class diagram for that. I was wondering to which out of Association, Aggregation, Composition or Generalization this could this be classified as ?
Thanks
It is not generalization as you are not inheriting in here, so it cannot qualify as an "is-a" relationship.
As for association, composition or aggregation... here you can find a pretty good explanation which is which. It is not possible to tell the right one for you without knowing your use case better. However, reading the other link will help you to understand the differences and judge based on your scenario.
Difference between association, aggregation and composition
Hope that helps.
The important thing to keep in mind about UML is that there's often no actual right or wrong answer when deciding on what to use, but some tools are better than others. UML is simply a tool for communication and as long as the tool is used in a way that everyone understands what is being communicated, then it serves its purpose.
For a class diagram, at its most basic level, you could actually model everything with just Association and Generalisation, but then this would lack detail that others may want to see.
Generalisation has a one to one relationship with inheritance, so it's clear when to use that.
Association describes any class with a relationship or dependancy with another class; quite a generalisation there(!) which is why it could be used in replacement of Aggregation and Composition.
Aggregation is used when an object (B) makes up another object (A) and B can be shared amongst other objects. For example, a library consists of books, so a book could be modelled as an aggregate of the library because other classes, could also aggregate a book, such as the person borrowing it.
Use composition when an object (B) is used directly to make up an object (A). In this case, if you were modelling the human body and had classes of organs, you would model a heart class as a composition object of a body class.
The fact that you're using the Qt framework is irrelevant to what you use to model your classes and a diagram doesn't need to model everything, just what is necessary to communicate concepts to others.
If, for example you're using container classes such as QList and QMap, you probably don't even want those in the diagram, but if you were to use QTcpSocket and inherit from it, then it may be better to show that.
Just remember, it's all about what you're trying to communicate.
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I'm doing a simple project to manage data for a tabletop game, but I'm mostly using it to get experience about correct coding.
I've just reached a point where I have five classes that are tightly coupled, and I'm not sure whether leaving the whole thing as it is, or refactoring.
What I have is basically this:
class ShipTemplate: This class ( that has nothing to do with c++ templates ) has all constant members and contains basic informations about a category of Ships.
class TemplateSet: This class contains all ShipTemplates that are currently available to build, and it has a name. It should be stand-alone, since it represents the available technology of each player at any time, so one would be able to save/load different sets at different times.
class Ship: This class represents a complete ship, with loadouts, name and other things. It contains a const reference to a ShipTemplate, which the class is not allowed to change, to refer to its basic functionality. It could extend ShipTemplate, but I wanted to keep track of which Ships had a particular underlying ShipTemplate, and it seemed easier doing it like this.
class Fleet: This class contains a list of Ships, it has a name and contains other information. It should contain a cost variable equal to the sum of the cost of all Ships in it.
class Deployment: This class contains pointers to all the Ships, Fleets, and TemplateSets available to the player. It also needs to keep track of ShipTemplates that are no longer available, but that are still used by already built Ships. It should contain a cost variable equal to the sum of the cost of all Ships available to the Player. It has to manage the transfer of Ships from one Fleet to another. It has to find out which Ships are within a given Fleet, or which Ships have a given ShipTemplate.
Unfortunately every class is pretty interwined with all the others. I thought about different approaches, but I'm not sure if even one of them is the correct one.
Use friend statements all over the place, so that if one class modifies something, it can correctly update all the others.
Use very long names, like Deployment::modifyShipThrustInFleet, and allow any modification solely through the Deployment class, which will take care of everything.
Remove TemplateSets and Fleets and represent them within Deployment, so that it can update correctly cost values/pointers without breaking any "correctness" rule. This too implies that every modification to the system has to pass through Deployment.
Insert into lower classes pointers to upper classes, so for example when changing something in a Ship it can automatically update costs of both its Deployment and Fleet.
Is there some other solution I didn't see, or maybe a refactor into more classes that can help me achieve readable, mantainable code?
Just some thoughts.
When thinking in object oriented way, thinking about real-life objects lays out the view, what you should describe in program. And what is object in real-life? It is a "thing" which has certain features and exposes some functionality.
For example ShipTemplate is a blue-print of the ship. It should define size, layout, part types and quantities (DieselEngine, SteamEngine, AntiAircraftGun, UnderwaterMines, etc), and how they are connected with each other.
Ship on the other had is constructed according to blueprint - it should have all part instances. For example it might have two DieselEngines and three AntiAircraftGuns. And it is correct, that ship does not inherit from blueprint. Blueprint is only a description of ship, not it's parent.
Now, each type of the object (blueprint, part, ship) has it's own properties and functionality. For example, each engine consumes some amount of fuel and can increase speed of the ship to some value. Why not have base class for Engine, which has these features? (inheritance). The same goes for the guns (lets call it ShipWeapon). There is of course a big difference between mine-gun and anti-aircraft gun, but they are both guns, they are both mountable on the ship, they both have weight, ammo type, reload time, ammo capacity, whether gun is operating.
So these are some properties of the objects. What about functionality? Other important concept of OO design is that each object has (encapsulated) some functions which can be done with it (and it may or may not alter objects state). For example ShipWeapon should have method Fire(), which maybe should decrees amount of ammo in it. Or try to target at first with Aim(sometarget). Engine on the other hand would have Start(), Stop(), SetSpeed(speed). Note that these would work internally on the object and it's state. Ship might have SetCourse(direction, speed), which would start it's engines at required power and orient its rudder. Also ship might have Colide(ship). And Hit(typeofattackinggun), which would iterate through all parts of ship and damage some randomly (and set IsOperating for a gun, or turn off one of the engines, etc.)
As you can see you can go into a lot of detail while designing OO approach. Its also very good to know when to stop - just how much detail (or accuracy) you really need for you program to work.
Also, there could be a global World, which would hold all ships. And so on..
There is other part of program, the infrastructure. How you data objects (ships, worlds, players) are managed, how they know and interact with each other. For example each ship as an object can be observed by global map and each ship would notify it about movement (observer pattern). Or global world would query state of each ship at some time intervals, based on global clock. Or...
I guess what I was trying to say is to stick to main OO principles - encapsulation, inheritance, polymorphism. And there is a lot of literature out there for object-oriented design, design patterns, etc., which is useful. Wiki entry is a bit "academic" but has main definitions, which make you think :) Also look at SOLID
PS. And it is usually a sign of a bad design to do everything in a single class.
Now that you have described haw you want to represent the various data, before defining the complete relations, try to complete the description by defining the "protocols":
What can each class be able to do to the others? WHat methods and rules between methods are needed to achieve your goal?
Once you have defined how classes act on each other you will most likely discover what is candidate to be private, what is public and what level of friendship must exist between the parties.
May be is not your case, but -usually- when complex relations exist, one possible pattern can be the use of a "communication bus class", that expose the action that can be "sent" to the various object, each having a private interface and being friend of ... the bus itself (an only the bus).
EDIT
Following Svalorzen comment:
It depends on the side you are watching it.
This will, in fact, introduce multiple level of "privacy", allowing to implement encapsulation on a wider unit that the class itself. Whether this is good or bad is a matter of context, not idiom.
Instead of having just classes with everything private (for no-one else) or public (for anyone), you have a "capsule" that is a "club" (the "club of the classes having 'bus' as a friend") and a "club manager" the is the real "filter towards the public" (and hence the real OOP object), allowing certain methods that need to interact with more classes private parts at a same time, to do that inside the club only.
The deny of "friendship" is nothing more than a misconception that confuse techniques with tools, making OOP objects the same as C++ classes. That's -generally speaking- a FASLE IDIOM. C++ classes can be smaller units than OOP objects (think to the pimpl idiom: what is the "object" there?).
The fact that a class can be a friend of another doesn't make it a friend of anyone, hence the private parts are not made public. You are just defining another level of privacy where encapsulation apply the same as with "private". It just apply on a wider group. That "wider group" plays, respect to OOP, the same role a non-friend class plays.
The misconception that "friend breaks encapsulation" has nothing to do with the concept of OOP. It has to do with the way OOP has been implemented in Java, that is a completely different language respect to C++. In C++ friendsip is just a construct to "group thimgs together" just like class, struct, templates, inheritance, membership etc.
What OOP relation (composition, inheritance, linking...) has to be mapped to what C++ construct, unlike in java, when the language philosophy is defined to be one-way only, is not defined by the language itself and by it's standard library.
The mapping "OOP object = C++ class" is just a common cultural misconception inherited from the past, when C++ has no templates, no lambdas, no friendship, nothing more than classes (and was in fact called "C with classes") when the only way to implement an OOP hierarchy was through classes,since that was the only way to create a hierarchy relation using that time c++ constructs.
Nowadays I can even implement an OOP system using C++ members and implicit conversion for "OOP inheritance" and C++ private inheritance for "OOP membership". Or I can implement an OOP object with a "cluster of classes (or mat be labdas)", defining its run-time behavior (think to std::locale and related facets).
Starting a design with the OOP object == C++ classes idioms is in fact cutting away two degrees of freedom C++ adds to program design, restricting your mind to what C++ was more than ten years ago.
A class design guideline found in Sutter&Alexandrescu's coding standards book, among others, is to make base classes abstract, such that one cannot instantiate them. This is to prevent a.o. slicing and problems with polymorphic assignment and copying.
However, when using a class library like e.g. Qt, it is common practice to inherit from concrdete classes from the library to add additional behavior. For example one would create a class MyListBox which inherits from QListBox, adding application-specific behavior for all list boxes in my application.
How is can this common practice be reconciled with the advice to have non-instantiatiable base classes?
Your very first sentence contains the answer you are looking for:
A class design guideline found in Sutter&Alexandrescu's coding standards book
(emphasis mine).
It's just that - a guideline, not a rule carved in stone.
If you have specific technical limitations, for example in the library you are using, you may ignore it if the given alternative at that particular moment is way worse (like having to use some pattern that triples the total amount of code or having to rewrite the library).
The whole point of my answer: All these patterns, guidelines and best practices are means by which you can reach your programming goal. They are not the goal, themselves.
That guideline only applies to base classes should not be instantiated (usually because doing so would make no sense). This is not the case in your example: for example, just because you inherited from QDialog doesn't mean that you wouldn't want to use plain old QDialogs elsewhere in the code.