How can I define a symmetric relationship in Graql - vaticle-typeql

I'm trying to model the Modern dataset (http://www.tinkerpop.com/docs/3.0.0.M7/images/tinkerpop-modern.png) in Graql. Marko knows Vadas and Vadas knows Marko - for the purposes of this example, I'm assuming that they are friends.
So can I do this?
insert friendship isa relation-type;
insert friend isa role-type;
insert friendship has-role friend, has-role friend;
All the examples I've seen so far, have two different roles on a relationship (e.g. teacher/student).

Roles must be distinct, so you cannot have two friend roles in a single relation.
If the relation you are describing is symmetric, you should instead introduce two roles friend1 and friend2. If you want, these can both be ako friend.
Given the dataset you're using, it might be better to not describe this as a symmetric relationship and instead uses a knows relationship, where one role is the knower and the other role is known-about.

As Felix Chapman pointed out, role-types are unique, so a true symmetric relation is not possible.
There are a few ways around it; say you have defined your relation as
insert
friendship isa relation-type
has-role friend1
has-role friend2;
The first possibility is to use ako and abstract roles:
friend isa role-type is abstract;
friend1 ako friend;
friend2 ako friend;
person isa entity-type plays-role friend;
The second possibility is using inference rules:
SymmetricFriendship isa inference-rule,
lhs {match (friend1 $x, friend2 $y) isa friendship;
select $x, $y},
rhs {match (friend1 $y, friend2 $x} isa friendship;};
The second way makes the friendship relation a true symmetric relation from a mathematical point of view, but given Graql's match syntax and for performance reasons, there is rarely the need to explicitly make a relation symmetric, so I personally prefer the first way.

You can do something symmetric by adding an entity that models a group of friends:
friendship sub relation,
relates friend,
relates friend-group;
person sub entity,
plays friend;
group sub entity,
plays friend-group;
This does feel like a kludge. The friendship relation effectively just expresses the subset relationship. I have used group instead of pair because now friendship is not binary any more, as I do not know how to restrict the number of friends in a friend-group. Moreover, the same two friends can be part of multiple friendships.
Graql as a modeling language would be more powerful if it would allow specifying variadic relations, e.g. using ranges for the number of role-players for each role. This would cover this use case as well:
friendship sub relation,
relates 2 friend;

You can use the fact that any role can be repeated in a relationship instance:
friendship sub relation,
relates friend;
name sub attribute,
datatype string;
person sub entity,
has name,
plays friend;
Then you can say
insert $x isa Person, has name "X";
insert $y isa Person, has name "Y";
match
$x isa Person, has name "X";
$y isa Person, has name "Y";
insert $xy (friend: $x, friend: $y) isa friendship;

Related

How to use Single-Responsibility Principle

I am trying to understand design principles in c++.
In database I have users.
users:
id
name
age
gender
I want to get my users in three ways.
First: I want all my users.
Second: I want all my users filtered by age.
Third: I want all my users filtered by age and gender.
For example, if I use same class for getAllUsers and getFilteredByAge, it means that my class has two responsibility, it is responsible for getting users and also for filtering them. Am I right or not? And how Single-Responsibility Principle works in this example, should I split this three in different classes, or is there any better way ?
A good definition for SRP is:
A module should be responsible to one, and only one, actor.
(Clean Architecture)
This means that if the person telling you what these functions do is the same, then you can leave them in the same class/module.
If, let's say, getAllUsers() is requested by accounting and getUserAtLeastThisOld(int minimumAge) is requested by HR, then it might be sensible to have them in separate classes.
Following are answers to your question
Q] If I use same class for getAllUsers and getFilteredByAge, it means that my class has two responsibility?
A] No,because your class's job is to get users, rather these functions should be overloads and should not be in different classes.
Q] it is responsible for getting users and also for filtering them. Am I right or not?
A] I guess No!, filtering is not a different task, it is something that should be applied before retrieving objects.
Q] how Single-Responsibility Principle works in this example, should I split this three in different classes, or is there any better way ?
A]
In this case I suggest you to have only one class, which should have following functions overloads
GetUsers() - get all users
GetUsers(AgeFilter) - get users as per age filter
GetUsers(AgeFilter, genderFilter) - get users as per age filter and
gender filter
Note : Now suppose in future you have want to add more functionality to this class
for e.g compute salary for user, or adding family details for users
then in such case you can go for creating another class instead of putting burden on single class...

About the use of const or friendship

I'm using some kind of "manager" to store a "Context" class, in some cases I want to pass this "Context" to other functions to read data from it.
Actually, when the manager pass this "Context" to a function, it pass a "const& Context", and I the Context have some functions declared as const (for reading) and others that aren't const (becouse the manager have to change the data inside the context)
now, I ask myself, is there any difference if I just do private mutators and give friendship to manager?
I think it must be some difference.
I know, it's a particular case, but for me C++ still have a lot of magic around there.
In my experience with C++, the main difference between having private mutators and giving friendship and having public mutators not giving friendship is that the second option allows you to not give anything and everything access to the information but only certain. Let's say you create a class called Student which has 2 child classes. Regular Student and Teachers Assistant. A lot of times there's so many students that it's hard for the teacher to take care of everything so he takes the best students as TA's. When the program is looking at these students, they should probably have more access to the Student's information than the regular student. With private mutators and giving friendship, you are saying some information (like a grade on a test) is private but can be changed by a TA possibly. On the other hand, if you have public mutators and no friendship, it is possible that a regular student can access the information and change the grades.
Hope this was helpful.
I'll start with two general statements:
const-correctness is a very good thing
firendship forms extremely close coupling between the two classes, which is generally a bad thing
Is your Context so tied in to the manager that only the manager would ever want to modify it (both now and as your program evolves through the years)? And is Context happy to have the manager modify it as it pleases (accessing all its private data)? If any of the answers is "no," you shouldn't go the friendship route.
Friendship should be used sparingly. When class X grants friendship to class or function Y, you now have two separate places in code which must maintain X's internal invariants: X itself, and Y. This requires more maintenance and is more error-prone.
In short, reserve friendship for very special cases. What you describe seems like a clear-cut use for normal measures - const observers, non-const modifiers.

Notation of UML class diagram

I have the following class cDrawObjectCreator:
class cDrawObjectCreator
{
public:
cDrawObjectCreator( cCompositeRoot *compositeObject ) { m_compositeRoot = compositeObject; }
~cDrawObjectCreator() {};
...
private:
cCompositeRoot *m_compositeRoot;
};
It is correct diagram?
or the following diagram is correct?
First one again. For the same reasons as in the previous Question.
Please read this, to see the difference between Compostion and Aggregation.
As a general rule, aggregation (hollow diamond) is a specialization of association, and composition (filled diamond) is a specialization of aggregation.
Remember the purpose of modeling is to facilitate communication so you would use different level of abstractions depending on the purpose and the stakeholders.
If you want to say that cMimicObjectCreator has an exclusive ownership of cCompositeRoot (that is, like a human / an animal body has a brain) then you would use composition (filled diamond). And if you want to say that cMimicObjectCreator has a cCompositeRoot (but not exclusively and that there are cases where the part class is not exist in the whole/container, like say...a boat with a GPS equipment) then you would use aggregation relationship.
To answer your original question, I think the first diagram is more appropriate. However remember also you can always use association relationship in place of composition or aggregation relationship if you want to be more "general".

Can two classes friend each other?

I haven't yet worked out a specific case. But I am about to embark on writing some code that I feel will end up needing this; and so I wanted to know if:
Two classes can friend each other; so that they can freely access the private
and protected members of the other (I believe the answer is yes, and ofcourse I
can simply try it out!). Any detailed references or other question links with answers
are also very welcome. I am aware of forward declarations and include guard compiler
pre-directives and their use. My questions are rather more related to the semantics
of the C++ language in terms of what it can offer with regard to this possibility
of mutual friendship and how to use it properly.
Is this generally recommended? Do people employ this kind of design on a regular basis?
Under what circumstances would this be a recommended design (preferably with some
examples).
You can have mutual friendship:
class A {
friend class B;
};
class B {
friend class A;
};
Whether or not this makes sense depends entirely on the problem you are trying to solve. It definitely could make sense in certain circumstances.
The only example from my current project that utilizes mutual friendship is a container implementation: the container class is a friend of its iterator class and vice versa.

Friend scope in C++

If I have three classes, A, B, C. A and B are friends (bidirectionally). Also, B and C are friends (bidirectionally). A has a pointer to B and B has a pointer to C. Why can't A access C's private data through the pointer?
Just to clarify: This is a pure theoretical C++ language question, not a design advice question.
Friendship in C++ is not transitive:
John is a friend of mine and he can use my wireless connection any time (I trust him).
John's friend Tim though is a waster and though John is my friend I do not include Tim as a friend, and thus I don't let him use my wireless connection.
Friendship is NOT inherited
Also John's children are a bunch of hooligans so I don't trust them either they are definitely not my friends nor are my own children who I trust as far as I could throw them.
Though our children can not directly accesses the wireless they can get access to it if they go through us. So John's children can access my wireless if they access it via John (ie they are supervised and protected by John).
Also, friendship is not symmetric.
John has a goverment job so he unfortunately is not allowed to trust anyone, especially when it comes to wireless.
You are always your own best friend.
This allows things like copy constructors where you can access the private member of another object even though there is no real accesses.
So I am also automatically friends with all my clones :-) as they are just other instances of myself.
Friendship in C++ is not transitive:
(A is friend of B) and (B is friend of C) does not mean (A is friend of C)
Also, friendship is not symmetric.
(A is friend of B) does not mean (B is friend of A)
You have to explicitly state that A is a friend of C to be able to access C's private stuff from within A. If adding a setter and getter to a class exposes information not meant to be exposed, you should consider friends if you can't find your design being faulty (using friend is valid. It's not a sign for bad design). If you can add a setter and getter without that being destructive to the interface, then you should avoid making other classes friends. Note that a nested class is always a friend of the nesting class. So a nested class can see the privates of the nesting class.
I just found this article while waiting for replies. It answers my question pretty well:
Friend scope in C++
Because in C++ friendship is not a transitive property. Actually it should be avoided whenever possible because it introduces complexity in a system.
Imagine that B is a mediator class and A and C are components that need to be managed, do you really think it makes sense that a button should need access to the implementation of a checkbox?
By the way, I don't see where the 'hierarchy' of your title is in the case you ask.
This is all well summed-up here:
What does it mean that "friendship isn't inherited, transitive, or reciprocal"?
-->
It means that classes derived from a friend class don't
automatically become friends (do you trust the kids of your friends?),
a friend of a friend doesn't automatically become a friend (do you
trust the friends of your friends?), and that a class declaring
another class as "friend" doesn't automatically become a friend of
that class (do you trust anyone who calls you a friend?).
from
http://yosefk.com/c++fqa/friend.html#fqa-14.4