#252 Typed facets

tompalmer Sat 21 Jun 2008

I was looking through the facet docs and I think I'd prefer typed facets. I think it could be done with low overhead something like this:

facets {

  **
  ** Transient is a facet used to annotate fields which should not be serialized
  ** inside a serializable type. See the Serialization Doc for details.
  **
  @on=Field.type
  Bool transient

  **
  ** Serializable is a Bool marker facet used to annotate types which can be ...
  **
  @on=Type.type
  @inherited=true
  Bool serializable

  **
  ** Simple is a Bool marker facet used to annotate types which are serialized
  ** automatically via a string representation. All types which implement this
  ** facet must follow these rules: ...
  **
  @on=Type.type
  @inherited=false
  Bool simple

  **
  ** Says where you can put it. Maybe should some enum instead of Type.
  **
  @on=Facet.type // ???
  Type on

  **
  ** For facets on types, whether they are inherited.
  **
  @on=Facet.type // ???
  Bool inherited

}

And they automatically get counted in the namespace of their pod. I think this maintains the current usage almost entirely, just allows them to be easily namespaced, defined, autocompleted, referenced, ...

Thoughts?

brian Sun 22 Jun 2008

Originally we designed facets to be strongly typed. But this was one of those areas where static typing kept getting the way. Once we just decided to treat facets as pure name/value meta-data a lot thorny problems went away.

To me facets are like annotating a file or email with arbitrary meta-data tags or attributes. Having to declare a type before you can annotate something is a pain and typically gets in the way.

I don't know if you've seen it, but Fan actually maintains a database of types indexed by facets. I kind of like to think of this model as more akin to something like CloudDB than something formal like a RDBMS.

tompalmer Sun 22 Jun 2008

Thanks for the info.

cbeust Sun 22 Jun 2008

Hi Brian,

I'm curious: do you have any examples where typed facets got in the way?

-- Cedric

brian Sun 22 Jun 2008

See the original discussion http://www.fandev.org/sidewalk/topic/152

Unfortunately I didn't do a very good job capturing why we decided to fallback to untyped facets, and I can't remember all the details. Andy might recall better.

But the basic premise was the facets are meta-data, and are often used in an ad-hoc manner like Java properties files. Suppose you had to declare a type for every key in a properties file and you can kind of see the problem.

The flip side is that it gives you flexibility on the value without requiring it to be a fixed type. For example see Facet Indexing for how you can use either a single value or a list when you have more than one. It also lets you setup values with dynamic/duck typing.

tompalmer Mon 23 Jun 2008

That facet indexing thing looks really useful.

However, I don't think that my proposal disallows such things. Also, my proposal is much closer to current Fan behavior (I guess because I based it on current Fan behavior) than the original recommendation that looked closer to C# or Java. My style above still really just comes down to name/value pairs. Also, I took the docs and meta-facets straight out of the non-API-docs on this site. I think auto-API-docs might be better (though I know some people who don't agree with that). Maybe there's an easy way to allow either String keys or predefined keys without it getting too ugly?

Also, you could say @indexed directly on a facet definition if you could define them.

brian Mon 23 Jun 2008

Maybe there's an easy way to allow either String keys or predefined keys without it getting too ugly?

If we could come up with a clean way to do that, I might like it. The big difference is that typed facets have a qualified name like sys::transient versus just transient. That might be a good thing though.

tompalmer Tue 24 Jun 2008

I have two alternatives for this so far:

  1. If a facet is undefined, treat it as a String. Seems easy but risky without good IDE support. Might not be terrible, though.
  2. Make it explicit with syntax such as @@stringKey or @"stringKey" or something.

Personally, if available, I think predefined facets would be used a lot more than string key facets, so I'd like to bias the syntax that direction. It would also be nice if it didn't require rewriting code if you decided to define a facet explicitly after already having been using it as a string.

Also, I imagine that in common cases, you wouldn't see the prefix on defined facets. That is, I'd expect that normally you'd say @transient rather than @sys::transient. That's why I think transition from one to the other might not be so bad.

tompalmer Sun 20 Jul 2008

Just for the record, I still consider predefined/namespaced facets to be super important. Also, note that the Bool facets above probably should be Void instead. They are either there (with value null by default?) or not at all, right? Not really true or false. Sort of interesting to think about.

Anyway, another reason I care is the namespacing. Say I make an action framework (no intention, just for example), and I use @action to annotate actions and the cool type DB to look them up. Well, someone else could do the same thing in their action framework, and I wouldn't know how to tell the difference. I'd have to use a marker mixin or something to be sure (because that has a namespace).

Pod namespacing in Fan is already so much simpler than most other modern systems (and happily so!), and I think that would be wonderful to have on facets.

brian Sun 20 Jul 2008

I don't really see a good reason to type facets - I still see them as ad hoc name/value pairs. It keeps things really simple to just keep things as Str to Obj maps.

So I would say that one is unlikely.

Say I make an action framework (no intention, just for example), and I use @action to annotate actions and the cool type DB to look them up

The convention is to prefix your facets with the pod name to avoid naming collisions.

tompalmer Sun 20 Jul 2008

The convention is to prefix your facets with the pod name to avoid naming collisions.

I doubt I'd do that. More likely I wouldn't use facets except when the context already makes the meaning clear and when I couldn't find a statically typed way to solve the problem. Oh well.

Any chance of at least allowing @pod::facet syntax even if just a string? Just a thought. I'm still not sure I'd use it.

BillBurke Thu 24 Jul 2008

+1 on namespaced, typed annotations. Without them, you really don't know until runtime whether or not you've made a typo (which is one of the things I despise about dynamic typed languages). Plus, you have the same problems with IDE factoring of annotations as you would with regular types in a dynamic language.

I think I like the fact the annotations can take only one value, but I think I will miss the "default" value that available in Java annotations.

tompalmer Fri 25 Jul 2008

Brian and Andy are both strongly against full typing for facets. I'm trying to work on an acceptable namespacing proposal for facets/symbols instead.

Login or Signup to reply.