Using $Prototype in queries (or not)

This is mostly a question about how others tend to think of Prototypes.

I have always used $Prototype in Agent queries, e.g. $Prototype=="Person". This implies that the Prototype is a “type” of note. I’m now questioning this approach.

I am inclined recently to think of Prototypes as nothing more than a set of default values for notes, so using them in Agent queries starts to feel “wrong”; like I’m forcing Prototypes into double duty.

My thinking now is for Prototypes to include a User Attribute like “NoteType” or a Tag or something else I can query on.

I guess I’m asking here if this is over-thinking it. Do you have any qualms about using Prototype as a way of defining the type of note?

Yes, that is the way I think about prototypes, too. It is dangerous to use $Protypes as a $Type operator because what is the prototype changes? It is better to have a $Type attribute that you have assigned to the local note when performing and $OnAdd rather than it solely being part fo the prototype.

You are NOT overthinking it. I’ve been mulling this for a while.

I have not fully landed on a clear answer that fully works for me.

“What if the prototype changes?” is the question. I ran into this when setting up my blog to (optionally) use Markdown notes. I used a MarkdownPost prototype for a bunch of new notes, which of course weren’t then included on the blog because $Prototype=“Post” wasn’t finding them. As soon as I changed it to $Prototype="Post" | $Prototype="MarkdownPost" I knew I’d gone off-track :slight_smile:

This is a bit like the “tags” vs. “folders” discussion that pops up in note making forums from time to time.

In my designs for Tinderbox documents, Prototypes are archetypes of classes of notes, with an array of inheritable values for key attributes. In that case, using a $Type attribute whose value means the same as the meaning my design has given to the prototype, is superfluous. My approach is not prescriptive – it’s just what works for me. Find a design standard that works for you, and use it consistently.

3 Likes

I believe that the most common use for prototypes is to identify a type of note: A Task or A Reference or A Person. That is to say, Pick Up Milk inherits from A Task because it is a task.

One characteristic of being A Task is that a note inherits some displayed attributes, and perhaps also some default settings.

In this context, agents that look for $Prototype=="A Task" are quite common, perhaps the most common agents!

Not, you might also have A Project which might itself inherit from A Task, but represents something bigger and less well defined. Now, we might look for $Prototype=="A Task" | $Prototype=="A Project", or we could look specifically for only projects and only tasks.

There used to be a bitter argument among C++ experts on whether C++ inheritance represented an “is-a” relationship, or whether it just represents “acts like” or “is based on”. It’s always a tension with any sort of object inheritance.

1 Like

I definitely tend to use prototypes to bind possibly disparate—in outline location terms—groups of similar notes for easy query retrieval. But Tinderbox is a toolbox: a hammer is great for nails—less so for screws. Put another way, there is rarely a ‘right’ way. Tinderbox isn’t an app that feeds you into fixed processes.

I think the starting point here is a user misalignment of structure and intent. Prototypes are just prototypes. They don’t have a particular purpose or a ‘correct’ method of use. In contrast, planning to use prototypes one way and then developing one’s TBX in a way that works against that is a shot in foot, albeit unintentional. Then again, Tinderbox, is impressively supporting undoing the effects of premature formalisation or just bad initial guesses as to structure. That lessens—or should—remove the normal software experience of an eaerly bad choice ending in a do-over.

My use of Tinderbox is all over the shop, not least as so much of it is solving other people’s problems and thus working inside their structures. Usefully, it nerfs the reflexive notion that there is a right way to use whatever tool we pick from the box. seeing what people pick and why, is instructive.

Another take on this do we design the process or does it constrain us (by intent)? The latter isn’t bad as sometimes we want a process that stops us impulsively colouring outside lines we know we shouldn’t. Conversely, when exploring a new problem space we likely want no guard rails as we don’t know where the emergent narrative/structure leads us.

I think of prototypes—or what they represent—in the loosest of terms. In visual-literal terms, I can see the blue triangles are different from the green triangles? Why? We don’t know, that’s what we are figuring out! But, now we realise some of the blue circles aren’t the same as the others. Trivial, we make a new prototype and now some of our blue circles are red diamonds., and so on… Everything else (text, map position, export template, etc.) might be unchanged but we’ve captured a new difference that we need going forward.

Wrapping back around to the opening question, if my process is rigidly built on discrete prototypes, then I’m essentially committing to colour inside those lines and shouldn’t ‘just’ add new prototypes without first reviewing the effect on my (deliberate) fixed process. It might be we just need an ‘OR’ in a query or maybe we’ve discovered our process is sub-par and needs a structural review. Whatever, Tinderbox supports either.

It is not the spoon that bends…

1 Like

Thanks for all the responses here. I tried to be careful not to word my question so that it sounded like I was asking for the “correct” way of using Prototypes. Just curious how others think about them, so thanks for all that!

I have grown uncomfortable with painting Prototypes into a type-of-thing corner, since that’s not necessarily what they are. In practice, though, it’s not been a significant problem either way. I’m still noodling on it.

This whole thing came up because I’ve finally started refactoring/rebuilding my decade-and-a-half old Daybook, and thought it a good idea to revisit some of my old assumptions.

One thing for sure, I’ve been having so much fun with Tinderbox the past few days that I can hardly contain myself :grin:.

3 Likes

My prototypes tend to operate in two layers. The top layer IDs general types. The secondary layer differentiates based on attribute values I want to inherit. Agents usually query inheritsFrom() the top level prototypes.

So for example, all images in my blog have a specific prototype that descends from “p_images” but each has a specific prototype that is basically a tool for setting css classes, image widths, etc. The same things happens for various styles of posts and videos and etc.

The way my head is wired, I need that first, type-based layer.

2 Likes

That seems like a sensible approach that could mitigate the issues I’ve felt around prototypes, thanks!

1 Like

I also chain prototypes, i.e. where a prototype may itself use a prototype. It is particularly useful for switching rules or edicts (as $RuleDisabled and $EdictDisabled are intrinsic). As TBX scale is size I find agents can get cumbersome due to the sheer number of aliases and having to consider accidental effects on notes via aliases. Plus, all aliases run their rules/edicts every agent/rule cycle.

Thus for work like checking for certain sorts of linkages, or attribute values, I normally push to rule or edict code in a prototype and then get my existing prototype use the former as its own prototype if/when the rule or edict is needed. This allows for fine control of the load running action on the doc, especially where each note might be querying most of the document albeit for per-(calling-)note criteria. As the main prototype has no rule or edict, it only gains then (and thus its inheriting notes too) if the upstream prototype is used.

[Edit: lest the idea above appears mine, kudos goes to @eastgate for suggesting it to me when I was struggling with controlling the self-inflicted issue of too many complex actions running.]

1 Like

I thought that at first, too, but I’ve found that I leave $Type in the prototype blank and then populate it with an $OnAdd. That way, I have a $Type for my notes that is independent of the prototype.