"bidirectionality" is our shortcut word for describing two way relationships between two types. For example, if you have a Company type and a Person type, then you often want to create/read/update/delete a relationship between the two. Our current solution is to put a Pointer on one and a Search on the other. This is a little tough to learn, but it basically works in terms of viewing the related cards. But the relationship is really only easy to update via the pointer side. To achieve real bidirectionality, it needs to be equally easy to edit in both directions (and ideally we'll find ways to make the whole thing easier to set up).
One approach would be to retain our current Pointer-Search data pattern but to make it easier to have pointer-like interfaces on the search side.
For example,, let's say we've got a simple system where:
- Renzo+employer=>CSU (pointer), and
- CSU+employees-> [ Renzo ] (search)
What we want here is a simple way to express that:
- +employees searches +employer cards
- when I edit the list, each item change on the list should alter +employer card(s)
Here are some possible ideas about how we could do that:
- employees+*right+*structure is a standard virtual Search card, just as now. The edit view is overridden somehow and looks mostly like a pointer editor (without the drag and drop ordering, since order changes can't be stored). Not sure how we know to use that special view. Perhaps Wagn is smart about recognizing WQL searches that fit a certain pattern and realizes this search could handle it, perhaps the view must be required explicitly (and does not replace default edit behavior), or perhaps there is additional rule-based configuration?
- employees+*right+*structure is a search card, but its content is a new WQL directive (eg "pointed_to_by"....) that tells Wagn to treat this as a pointer/search relationship. Rest is similar to above
- employees+*righ+*structure is a PointSearch card (or something similar). This cardtype has special views and can autogenerate WQL based on a couple of fields that are filled in
- .... other?
Another approach would be to use a Type1+Type2 pattern based solution. The existance of cards in one of thse patterns would be a bi-directional link between them (it's sort-of like having a join table. a particular set of this pattern representing the whole table, and each card instance like a join record). You can add either direction with equal ease.
- Same example at above, Employee+Company+*type_plus_type might be the set (whether or not we actually have this pattern, but conceptually).
- Renzo+CSU would be created when I add to Renzo+employers or CSU+employees. We'd have to create CSU and Renzo first.
- +employees and +employers would be similar searches with the type position switched in the WQL.
- A drawback is no order on either side, but type1card+type2card+sequence could be used for ordering (I know, not that pretty).
whoops, this is a duplicate. Let's import the best stuff from the old idea here (closing the other one):
implement bidirectional relationships
1-3 are explorations of the "one approach" (see top of solution). 4 is a different approach, no?
Yeah, it is more like creating a join record in ORM. I think it might make sense when we actually are using the *type_plus_type pattern as in wiki-rate extensions. So, I guess it really needs a second thing at the top level.
But it does illustrate the concept of linking via namespace (+). It isn't how we typically use the + relationship.
Thanks for putting forward the "another solution" (type+type). Definitely worth digging into. It's come up a few times, and I've always been uneasy about it, but it's worth deeper exploration. I'm guessing you're in the same boat (not advocating yet but wanting to explore?)
To me, it has several issues that would need working out. The first is the nature of relationships.
Let's say we have three companies: Holding Co, Producer Co, and Retailer Co. What does the existence of Producer Co+Retailer Co actually tell us? (In the Pointer-Search, the pointer name is meaningful, and in fact we could put +subsidiary, +client, +franchisee, _whatever else and represent multiple company-to-company relationships). We could put something in the content, but how would we distinguish between unidirectional and bidirectional links?
I should probably clarify that "bidirectionality" might be a confusing word here. In this use, it's not really about the nature of the relationship, but about the interface. Eg, we're not talking about distinguishing between A loves B, B loves A, both, and neither. We're talking here about whether you can *edit* the fact that A loves B from both A and B.
To my mind, the Pointer / Search pattern gives us pretty good coverage for representing of standard relationships. As you have pointed out, pointers are, by default, many to many. We need some good patterns for restricting that, but it's kind of an awesome starting place.
Do you agree that with pointers/ searches, most relationship patterns are easy to represent in data, even if difficult to update? Perhaps I should change the name of this ticket to "support bidirectional editing"?
In any case, unless we think we want to get rid of the pointer-search pattern, we will very likely want to be able to edit the relationship from the search side. I suppose the question whether that discussion should happen here or elsewhere depends on how much we think we want to invest in other relationship representations.
see also Relationship Card
OK, here's where I am. I think that we are at a place where we need either to (a) commit to the pointer-search framing and make it great, or (b) really articulate the need for a supplemental (or replacement?) system and exactly how it fits into the whole framework.
For pretty much the whole time we've been working on Decko I've been feeling iffy about deeply committing to the pointer-search idea, mostly because of limitations in our current configuration options but after these explorations, for the first time I'm starting to think we can really make it awesome. So I'm going to try to articulate the argument in favor here (in a form that might be moved into documentation at some point), but I would be very interested in hearing counterarguments. So...here goes.
- Cards in Decko can refer to other cards in two main ways: in names and in content.
- Name references are structured and hierarchical. Complex names are formed by combining names. So, for example, Alphie+loves is formed by combining Alphie and loves (So it can be said to refer to Alphie and to love in its name.)
- Content references can be very loose (as in blog posts) or very structured, as in Pointer (explicit lists) or Search (implicit lists). Because of their simple but rigorous structure, these two cardtypes provide a strong basis for knowledge representation.
- Pointers can be easily translated into RDF-like "triples" . For example, if Alphie+loves is a pointer, and the items in the pointer's content are "Karen" and "Fernando", then you have effectively created two triples: "Alphie loves Karen" and "Alphie loves Fernando". Note that each of the four concepts involved (Alphie, love, Karen, and Fernando) has an associated resource (card). While Decko wasn't really designed as a triple engine, as such, triples have been shown to have enormous flexibility, and the Pointer handling
- Perhaps you are a monogamist and disapprove of such a thing. It is possible to restrict your Pointer relationship so Alphie much pick one. This is currently only enforceable in interface (eg by using dropdown or radio inputs), but will soon be easily configured in rules
- Perhaps you are a polyandrist or a polygynist and feel like it's fine for a man to have many woman but not ok for a woman to have many men. Or vice versa. The documentation's author finds you dodgy, but Decko can still handle your data needs. As above, this can currently be constricted in interface and will soon have clearer configuration options.
- Perhaps you are a polyamorist and think anybody can love anybody else. Decko is all about it. In fact, as the above examples illustrate, Pointers are by default many-to-many relationships, and you have to set additional rules to constrict them to turn them into one-to-many, many-to-one, or one-to-one.
- Pointers are great for storing relationships, but what if we want to see a relationship from a different side? If I'm asking "Whom does Alphie love?", I can look at the Alphie+loves card and see a list. But if I want to see "Who loves Karen", how does that work? That's a Search. Decko can put together a query to look for all the pointer cards that end in "+loves" and see which of them point to Karen. Turns out, Alphie does! In Decko, the goal is to be "DRY", which means "Don't Repeat Yourself". Any given bit of information should be stored just once. In this case, we don't want a separate Pointer card named "Karen+is loved by" that points to Alphie. If we did that, then when the two had a falling out, we'd have to edit two cards instead of just one. (And as data systems get complex, that can translate to hundreds or thousands of cards in a hurry).
I'm slowing down a bit on this and need to get to other work. Some quick points more relevant to our discussion:
- I get that we haven't totally gotten to symmetrical relationships yet. In the "love" case, it's possible that A loves B and B loves A are separate bits of interesting information. But if it's symmetrical, like "is married to" or "signed a contract with", we don't want to have to represent it twice. In this situation, we have to consider whether Gerry+married -> Debbie can be treated as asymmetrical in the same way that Gerry+Debbie-> married might be. Personally, I don't see why not, though I don't claim to have worked out the details. It comes down to having the system understand that "married" is reciprocal, so you would have to (A) search both sides or (B) create a rule for where the content goes (lower id, earlier in alphabet, etc)
- Since "type plus type" keeps coming up, it might be worth a little bit deeper articulation of how it's been used. We actually had this way back in the day with Hooze and again with WikiRate in rather similar situations: both involving Companies and Topics. Both ended up getting used as a deeper exploration of the nature of the relationship between the two. In this way, there is something fairly close to the Relationship Card suggestion or the idea you articulated above. It's worth noting that if this naming convention became the primary convention for representing reciprocal relationships, it would actually block you from using the WikiRate pattern.
- Regardless of how it applies here, Philipp has been doing some conceptual work with sets that would probably make it so that Decko supported type plus type and lots of other set patterns out of the box. We'll try to get that written up soon.
- I'm not sure exactly how this would work, but it would be cool if we put together some automagic around cardtypes. For example, +company on Person cards might by default try to autogenerate a search for Company cards with +person on it (and vise versa). You'd have to explicitly make one into a pointer. Or something...
I like the poly* discussion, dodgy, pretty funny. You have a bit of a sentence fragment at the end of the fourth bullet.
Something like making sets more composeable? That does sound interesting.
I think your point 4. is a matter of some shortcut buttons in the UI. Maybe you have an "association" widget, but it probably just uses the same WQL we would now.
So is it fair to say you're on board with going gangbusters on the pointer-search model, or do you think we need to give deeper attention to other options first?
Since is it closest to what we currently represent, I think it is really the only one viable in the short term. We'll have to see just how well it works. UX-wise, we should be able to support different data representations in the long run.
I think your short term challenge is to really evolve the client side to better support customization and extension. A lot of what you have on your hot-list for 1.0 will be largely in this part of the code. I think that our cards, sets, events, rules, names and all that are well developed and even refined so that with some magic on the client side it can do anything well.
I'm not that involved in the work, but our team is going towards using react and reflux on the front end. I think the reasons and results are good, and it could be a good fit for Decko.
My thinking was that we would try to support lots of UX options but focus on relatively few data representation patterns. If we do that, it makes it easier for the wagneer to switch between them. Not saying that we should make it impossible to use other patterns, but it's like rails - follow the conventions and it's all super easy. I think I'm finally coming around to thinking the pointer-search pattern that we, in some ways, stumbled into has some real strengths to it.
I'm thinking to close this and add another, narrower ticket to cover specifically bidirectional editing for the pointer/search pattern. Sound ok?
support bidirectionality+discussed in support tickets
support bidirectionality+relevant user stories