Prototype inheritance with manual attribute handling

Hi All!

I have a TBX that I use to keep a log of journal entries, daily notes and the like. I have a prototype;“Note”; that shows the created and modified date as well as who created the note.

I want to supplement the different notes with different attributes. So today for example I replaced the battery on my aging macair and and added the “File” attribute to that note to link to the video stored in my resources folder. However, I created the note, added the attribute “File” and then changed the notes prototype from “none” to “Note”. At this point the attributes set to display in the “Note” prototype did not appear. I can of course add them manually, but want to ask why they did not appear?

Would I be correct in assuming that prototypes only fire on vanilla notes; that is, notes that have not had any attributes added manually? If this is the case how do I apply prototypes to notes that already have manually added attributes?

In short no. Take a look at my article on inheritance. Also note that the Key Attributes table listing is itself an attribute value ($KeyAttributes, a Set-type).

By adding a $File to your note’s Key Attributes, you set a local value for $KeyAttributes, breaking inheritance. Thus when you set a prototype the note couldn’t inherit the prototype’s Key Attributes as the the note already had a local value for $KeyAttributes. As the article above explains, a local value always trumps an inherited one.

This is not the end of things though. If you reset $KeyAttributes in the note (e.g. via the Quickstamp Inspector), you will see the prototype’s Key Attributes. However, $File will be gone as it is not a Key Attributes item in the prototype. So, either add $File as a Key Attribute in the prototype or add it back to that one note. If doing the latter, bear in mind that if the prototype’s Key Attributes table contents is altered this new $KeyAttributes will not be inherited, for the reasons stated above.

Separately, just because a note and its prototype’s Key Attributes table list items that fact does not affect how the listed attributes inherit as each attribute’s inheritance is discrete.

Does that help?

(If not, do please say where in the explanation you are getting lost. I do realise these things are only simple after the fact!)

Thanks Mark, that helps.

So my question somewhat changes.

If you have notes that all need a few same attributes, but many notes will also have a few different KA, what is the best approach here? I could see that by adding KA manually the link with the prototype is broken. After a while you may lose track of which note is inheriting an attribute.

Also, what’s the reasoning behind leaving the note with the prototype still set to a KA although it has stopped inheriting the prototype’s KAs? Would it not be better to set prototype to “none”, when the note loses the prototype’s inheritance?

Why not use several different prototypes then? Does it matter if, within a group of notes with the same prototypes, some notes don’t need some Key Attributes? My experience is it it doesn’t and the scenario is far outweighed by the upside of changing the prototype.

Remembering to change the prototype’s attribute (be it $KeyAttributes or others) rather than in a note using a prototype is really practice. Even so, we make mistakes and that is what hasLocalValue() is for. Want to find (and fix) notes using prototype “Note” and resetting Key Attributes inheritance? Use agent query:

$Prototype=="Note" & hasLocalValue("KeyAttributes")

and action:

$KeyAttributes=;

What you can’t have is partial inheritance. Well you can sort of, but it quickly gets complex such that you get back into the original uncertainty. So the take-aways are:

  • Pragmatic use of prototypes. Some notes showing a fewKey Attributes seemingly unneeded is far outweighed by being able to lean on Tinderbox’s inheritance.
  • You don’t have to use just one prototype. If you’ve got different sub-sets of notes needing different sets of Key Attributes than consider using multiple prototypes. If you also have queries that currently rely on a single prototype, you might want to consider the prototype naming carefully so it is easier to
    search a range of prototype using $Prototype.beginswith("Note") than by using | OR joins to match several differently named prototypes.

I’m sorry, I don’t quite follow. You can’t “set a prototype to a KA”. The Key Attributes table in the prototype—if customised—becomes the value of the prototype’s $KeyAttributes attribute and that can be inherited.

Remember $KeyAttributes controls that attributes listed in the Key Attributes table of the note tab. It has no effect on the values of the attributes displayed in the table. As said, each attribute has its own inheritance chain. For instance, if a note uses a prototype, only if the prototype customised an attribute value does the note inherit a non-doc-default value.

Thanks Mark, that really helps. It looks like multiple prototypes will be the next attempt. I like the idea of naming prototypes beginning with the same name for easier searching–great tip thank you!

Ok, so I set a prototype’s KA. I then set a note to “Note” prototype. The note now inherits the the prototype’s KA. I now add a KA manually. The inheritance is now broken as the KA value is now local. At this point the prototype is not having any effect on the note. Yet the note is still a “Note” prototype. The “Note” prototype is not automatically removed and set to “none”. Why is the note still set to the “Note” prototype, when there is clearly no longer any impact from the prototype to the note? This is what I do not understand.

Because, you as the user have chosen to customise an inherited value, under the way inheritance works, this breaks the inheritance of that attribute (i.e. $KeyAttributes). Think back to the $Color based example in the article. If you change the $Color of the note and then change the $Color of its prototype, the note’s $Color remains unchanged. It is entirely consistent. Setting to ‘blue’ the $Color of a note, that otherwise inherits the $Color value ‘red’ from its prototype, does not alter the note’s prototype assignment. Indeed, the latter is also—you’ve guessed—and other attribute value! In this case $Prototype.

It seems you’ve somehow assumed that setting a prototype ‘locks’ the attributes inherited by the prototype. If you stop to consider that can’t really work. I do understand that once you internalise an incorrect assumption about how something works it is hard to shake it. But if you recall how inheritance works and that the items in the Key Attributes table are no more than the contents of a set of attribute names stored in a Set-type attribute you should be able to see how inheritance of the table is affected.

Is this helping make sense of things? If my guess about your assumption in the last paragraph is true, I’d love to know what you think caused you to make such an assumption so we can better document things to help avoid this mistake.

I think it also worth saying there is noting ‘key’ about Key Attributes. I think the original, and perfectly sensible idea behind the original use of ‘key’ was these were attribute(s) of sufficient important to a given note as to warrant showing them in the (then note window and now) note pane’s (key) attribute’s table. Bear in mind a default note has zero Key Attributes. they appears only if/when you set them. People sometimes set an attribute as a Key Attribute as they don’t understand any other way to edit it, but that simply reflect not having looked at the documentation.

In older days, with smaller screen, Key Attributes were probably used less and they took space onscreen otherwise used to show $Text. The current v6+ UI and bigger screen have made this less of an issue making he use of Key Attributes as an attribute editing interface have less effect on $text editing.

Remember: inheritance means that this note uses the prototypes’s value unless it has a value of its own.

Thanks Mark, once again, great explanations. I think I had incorrectly thought that a prototype sets which attributes a note had access to. But on thinking with your explanation, this is clearly wrong, because any note can access and set a value to any attribute whether the attribute is in the prototype’s $KeyAttributes or not.

So the prototype’s function in terms of attributes is essentially to set the $KeyAttributes value and pass on this value to notes that are set to this prototype, which can be overridden when a local attribute is altered, added or deleted?

And by value we’re talking about $KeyAttributes? And perhaps some other attributes that have a definitive value. But those that don’t have a value such as $StartDate in the Task prototype cannot pass on any value to a note that uses the Task prototype, because no value is set?

It was my understanding that a prototype can set ANY attribute, whether it is a key attribute or not – but I may be wrong.

First, remember, there really is nothing ‘key’’ or special about ‘Key Attributes’. The phrase is just a piece of Tinderbox terminology. I can’t stress that strongly enough. Key Attributes have NO role in inheritance, they simply make it easy/quick to edit a small subset of attributes on-screen.

Sorry, not quite. Once again, ‘key’ attributes are just an ad hoc list of any system/user attributes you wish to see shown in a note’s text pane. As such, that list is stored in the notes $KeyAttributes attribute. As a prototype is just a note, albeit with special behaviours it too records its Key Attributes list in its $KeyAttributes.

. Indeed, any note may be made into a prototype. You won’t be surprised that a note’s status as a prototype is stored as an attribute value. If a note’s $IsPrototype is set to true then Tinderbox teats as a prototype! A Tinderbox document is links and notes but notes are themselves just a collection of attribute values (this includes the title ($Name), text ($text) and so forth).

Recall the inheritance chain (image from my inheritance tutorial):

attribute-value-inheritance-flows-downwards

In a normal note the default value of any non-read-only attribute is inherited from the app by the TBX document and thus the note. If a note is given a prototype, it is inserted in the inheritance chain between the document level and the note. This is how a change to a prototype ripples down to notes using the prototype.

The act of inheriting a value does not set it. Rather the default is calculated on the fly. Were you to open the XML of a TBX you’ll find most notes have virtually no per-attribute data. Why? Because the value you see on screen in the app is inherited.

Only when a note sets a non-default, i.e. non-inherited value, does that value get stored in a note (and the TBX’s XML) and is considered a ‘local’ value. So the same holds true for a prototype which we know is a special form of note.

Just $KeyAttributes? No! It is any attribute. Remember there is nothing ‘key’ about $KeyAttributes, it’s just one of many system attributes.

Yes and no. They do pass, via inheritance, a value. it just so happens the value in the latter case is a value of no value—which in the case of a Date-type attribute like $StartDate is actually the string "never". For a Number-type it is number 0, Boolean it is false and for pretty much everything else an empty string "".

Lastly, remember, again that there really is nothing ‘key’’ or special about ‘Key Attributes’. The phrase is simply a piece of Tinderbox terminology. I’m fast coming to the conclusion the choice of terminology was an unintentionally infelicitous choice 20 years back, but it’s too late to rename it now without causing even more confusion!

A prototype can set any attribute.

(There are a very small number of attributes that aren’t inheritable, because inheritance would make no sense for them. For example, A note has its own $Xpos and $Ypos; if you move a prototype, that doesn’t mean you wanted to move every instance!)

Thank you all for persisting with my lack of understanding!

So a prototype then is just a simple way to set a number of attributes at once, but these attributes could be easily enough set using the quickstamp or adding them individually in the note’s text pane?

$KeyAttributes is an attribute that allows you to list a number of other attributes so they appear in the note’s text pane?

Does this mean that every note has in some way every attribute connected to it even if the value is no value, "never" 0, false or ""? In terms of a note having an attribute it has all of them in some way shape or form? We’re just talking about setting some specific attributes that we are interested in and making them easier to set and more visible, but in reality although the other attributes may not be visible they are still connected to that note in some fashion even if it’s a no value value?

Exactly. In the light of how we got that:

a prototype is just a simple way to alter the inherited values of a number of attributes at once in notes using the prototype.

The prototype is where you make the change. A stamp, agent, Get Info dialog, Key Attributes table, etc. is where you change/review attribute titles.

The more you use prototypes the more you’ll see their power. As well as a way to set an attribute value for lots of notes at one go it is also a useful way to find all notes of a given type in a single agent query term, e.g. $Prototype=="Note" matches every note using the prototype ‘note’ regardless of where it is in the document. The combo of its ability of a changes to a prototype affect lots of notes and once and to find said notes easily is, in my experience, a key part of prototypes. I use them a lot!

Exactly, no more, no less. the attributes shown therein are not privileged over others except in being easier to view/edit for a given note. Of course the contents of Key Attributes can vary per note (either set locally or inherited via a prototype)

Yes! Think of a note like a pre-printed library index hard with pre-printed boxes for different information. For each card in the index, every box (field) is available—as an empty box (i.e. default value)—even if that box is never used.

As a bit of computer program optimisation under the hood, Tinderbox doesn’t store all those empty boxes. Instead - if you look at the value of an (as yet un-set) attribute Tinderbox simply shows you the inherited [sic] default whether at document level or a non-default inherited via a prototypes.

Correct.

Now we’re on the same page (hopefully!), I’m really interested to know how documentation could make this more obvious to the reader. It may well be there is no description that fits all, but I note I’ve spend a lot of time recently dealing with (understandable after the fact) misconceptions about where Key Attributes fit.

I think part of the problem is that in order to make demos/tutorials easier, their authors (me too!) tend to put attributes of relevance at Key Attributes making it easier to see and edit. this clearly has the unintended effect of giving a mystical quality to Key Attributes. Yet as we have established above it is just an ad hoc list of some of the attributes available. I ask this only in the hope of finding better ways to make some of the concepts easier to grasp without needing to seek clarification. That is an inditement of either author or reader; ‘intuitive’ is in the eye of the beholder and some abstractions aren’t obvious at first encounter.

Thank you too for your useful comments above. It is all useful to finding more efficient ways to help people trying to push deeper into the app.

Perhaps I’m pessimistic, but I think the only thing that would really work would be to change the name of Key Attributes to something else, though I realise that is a bit unlikely to happen. Part of the problem, as I see it, is that you don’t know that you don’t know something until you run into a difficulty. I suspect that people are unlikely to read the documentation on Key Attributes before they start using them (I know I didn’t) because they assume they know (from the name) what they are for and what they do. This is just human nature, it seems to me, and is unlikely to change. A lot of our behaviour is based on using experience to suggest how things might work when we first encounter them. Decades ago I saw a film in which a man who had just come out of prison was trying to open a car door, and had some difficulty because in the intervening time they had changed from having a button that you pressed to having a flap that you pulled. He made several attempts pressing the flap. I think there may be a fair bit of that kind of confusion in adapting to new software.

Recent threads here and elsewhere about using Key Attributes shows the following aren’t intuitive to many readers:

  • All notes have all attributes. Depending on the degree of tech grounding or not a range of different metaphors are needed. A tech type might understand a TBX is essentially a flat-file database, whereas a more general user might ned an analogy like a printed library index card or rollodex card.
  • Prototypes are still notes. Changes to prototype attributes don’t (excluding action code) change local values in other notes but instead change the default they inherit.
  • A good number of folks don’t really understand what inheritance means in terms of Tinderbox use. IOW, we need some metaphors that aren’t tech-based to help users map their general knowledge across to the tech context.
  • Key Attributes need devaluing in prominence and it stressed they are just an ad hoc list of attributes with no special significance to the app—as opposed to the user who chooses them.
  • Early-stage tutorials using Key Attributes as a convenience (easier to see/edit attribute values) should deliberately repeat the point of the bullet above. Key Attributes are not ‘key’!

Not sure there is anything you can do. It’s a matter of user discovery. There is a good Getting Started PDF, the atbref is a good reference file and the help file has what it needs to have. As @MartinBoycott-Brown said

I suspect that people are unlikely to read the documentation

TB is a powerful, feature rich tool that needs learning to use properly. Once a user discovers this the information is available.

1 Like

One vote for changing $KeyAttribute to $VisibleAttribute or $VisiblySetAttribute or $MoreEasilyVisiblySetAttribute or… , ok, sorry, heat related mental derangement kicking in. How about $ShowcasedAttribute? Or… How scary, difficult, time consuming would it be to make the change in the code? I’m thinking a search and replace wont do it :wink:

1 Like

I get it. I think ‘displayed attributes’ is really at the heart of this. It is problematic for those who find it hard to envisage any part of the app not shown on screen (such abstraction isn’t universal and no reflection on the individual).

I think a key thing for now is to consistently emphasise that there is nothing ‘key’ about Key Attributes. They are just a user-set subset of attributes shown in the text pane for the user’s convenience. I’ve an idea for some new content for aTbRef to act as a background reference (e.g. to link to from posts here) but it may not be for some weeks as under several hard deadlines at present.

In many ways $KeyAttributes makes sense. They are the attributes that are key to that particular note or prototype. I think whatever, you call it there will be misconceptions until people understand attributes in general. I’m not sure that renaming the attribute will help people better understand the concept. It is something that must be learned until it is understood.

2 Likes

Wearing my hat as a psychologist, and as someone who has an interest in language and the effect it has on people, I have to disagree with much of this. I think the name “Key Attributes” is at the heart of the problem. I think it probably even contributes to people misunderstanding attributes in general. I suspect the problem you have encountered and documented in this thread is an example of this. Would this whole difficulty have arisen if Key Attributes had been called something else? Somehow I doubt it. If they are called “Visible Attributes” then the implication is that there are others that are not visible. I looked up the definition of “key” in the Mac dictionary and found this: “Computing - a field in a record which is used to identify that record uniquely” and “adjective - of crucial importance”. I don’t think either of those apply to Tinderbox’s Key Attributes. Yet those are the sorts of meanings that people carry in their heads as they encounter Key Attributes for the first time in Tinderbox. It should not really be necessary (in my view) for people to have to discover that the concept “key” has a totally different (and unique) meaning in this particular context. I agree that we all have to learn and adapt – and we have to be ready to learn and adapt – but I think this is a case in which a choice that seemed quite reasonable at the time turns out to create misunderstanding and friction for the user. Which also translates into time taken up with educating users. I note that “Ziplinks” have also been the fount of some misconception in recent weeks, which I think also illustrates that what you call things creates impressions that may be hard to eradicate. There have been experiments in cognitive psychology in which people have been given information, then been told it is false, but continue to be influenced by the original information. Some of these are described in a good article in The New Yorker: Why Facts Don’t Change Our Minds. In short, I think vital learning can be obstructed by what we call things, and getting the name right can make it unnecessary for people to learn, because they are not having to work against what they already know.

1 Like