community-group icon indicating copy to clipboard operation
community-group copied to clipboard

Toughts on the Use of "$" Prefix in the DTCG Token Standard

Open DarioSoller opened this issue 1 year ago • 9 comments
trafficstars

First, I want to express my appreciation for the tremendous effort and dedication that has gone into developing the new DTCG token standard. The work being done here is invaluable to the design and development community, and I am grateful for the opportunity to contribute my thoughts.

As a lead frontend engineer and member of a bigger design system team, I have a deep appreciation for clean code craftsmanship, the importance of maintainable and speakable code and system design. With this in mind, I have some concerns regarding the decision to prefix relevant properties of the design token data object with the "$" character:

  • Historical Context: The use of the "$" prefix can be reminiscent of older practices, such as those seen in jQuery, which may not align with modern coding standards and practices. Additionally, this prefix has been used in other contexts, such as RxJS observables, which has led to some confusion and mixed opinions within the developer community.
  • Modern Practices: Other types of prefixes, such as those used for marking private variables with an "_" underscore prefix, are also considered bad practice nowadays. With the support of modern IDEs being so advanced, there is no longer a need for such conventions.
  • Adoption and Effort: I am well aware that some tools have already started adopting the standard with the "$" prefix, and I understand the significant amount of effort that would be required to change this at this stage. However, I could not find any discussion around this specific kind of prefix in the available documentation and community discussions.
  • Collision Prevention: I recognize that the prefixes with a dollar sign ($) are intended to help prevent collisions with token names. Using this prefix eliminates the need for a reserved words list and helps future-proof the specification. However, I wonder if this is truly the only way to mark properties, aside from using a reserved word list. Could there be alternative approaches that might achieve the same goals without the drawbacks associated with the "$" prefix?
  • Type Definition Package: Moreover, an official type definition package would be a really nice addition to the standard, which might have already been discussed. This could further enhance the usability and integration of the standard across various tools and platforms.

I apologize if my feedback comes at a late stage in the process, but I felt it was important to share my perspective. I am eager to hear the thoughts of others on this matter and to engage in a constructive discussion about potential alternatives.

Thank you once again for your hard work and for considering my input.

DarioSoller avatar Aug 13 '24 09:08 DarioSoller

I'm reasonably sure the $ convention used here is based on the variable naming convention originating in Sass. The jQuery usage is less relevant, as the entire library was meant to exist under that one namespace. Design tokens are more closely related to styling variables than DOM manipulation. I'm not familiar with RxJS observables, but there will be plenty of $ among other languages, just like there is plenty of usage of different characters for other reasons. I don't know how the RxJS ecosystem clashes with what is expected to be used in this specification.

Regardless of the history, what I find beneficial in the $ prefix here has to do with JSON's restrictions. While yes it would be great to have all of these enhancements to help the developer experience, the core of the specification is expected to align with JSON's limitations, AFAICT. We have used _ to denote private because the language used doesn't support the concept of private (until it does). This isn't necessarily meant for someone to edit in an IDE but for systems to ingest and transform into styles.

Further, I find that the $ provides more clarity as a "special" field than if special keys were to exist without needing to dive into documentation. It should raise the question, "Why do these keys have this prefix?" as opposed to if keys look like any other keys. However, given that you've raised the idea, I'd like to know what you suggest as alternatives, knowing the limitations.

ddamato avatar Aug 13 '24 13:08 ddamato

Seconding @ddamato, specialness in human review is a big sell for the $ - and I don't see the $ translating to tokens in CSS or in places where it'll clash with a JQuery or equivalent.

On Tue, 13 Aug 2024 at 19:28, ddamato @.***> wrote:

I'm reasonably sure the $ convention used here is based on the variable naming convention originating in Sass https://sass-lang.com/documentation/variables/. The jQuery usage is less relevant, as the entire library was meant to exist under that one namespace. Design tokens are more closely related to styling variables than DOM manipulation. I'm not familiar with RxJS observables, but there will be plenty of $ among other languages, just like there is plenty of usage of different characters for other reasons. I don't know how the RxJS ecosystem clashes with what is expected to be used in this specification.

Regardless of the history, what I find beneficial in the $ prefix here has to do with JSON's restrictions. While yes it would be great to have all of these enhancements to help the developer experience, the core of the specification is expected to align with JSON's limitations, AFAICT. We have used _ to denote private because the language used doesn't support the concept of private (until it does). This isn't necessarily meant for someone to edit in an IDE but for systems to ingest and transform into styles.

Further, I find that the $ provides more clarity as a "special" field than if special keys were to exist without needing to dive into documentation. It should raise the question, "Why do these keys have this prefix?" as opposed to if keys look like any other keys. However, given that you've raised the idea, I'd like to know what you suggest as alternatives, knowing the limitations.

— Reply to this email directly, view it on GitHub https://github.com/design-tokens/community-group/issues/240#issuecomment-2286325605, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEKS36BFPO55XINO65KHPA3ZRIGGPAVCNFSM6AAAAABMN2DP72VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDEOBWGMZDKNRQGU . You are receiving this because you are subscribed to this thread.Message ID: @.***>

nesquarx avatar Aug 13 '24 14:08 nesquarx

Thanks for going into a discussion so quickly and sharing your thoughts on that, @ddamato. Let me try to reply in detail and also trying to challenge a little bit on what you said:

I'm reasonably sure the $ convention used here is based on the variable naming convention originating in Sass. The jQuery usage is less relevant, as the entire library was meant to exist under that one namespace. Design tokens are more closely related to styling variables than DOM manipulation. I'm not familiar with RxJS observables, but there will be plenty of $ among other languages, just like there is plenty of usage of different characters for other reasons. I don't know how the RxJS ecosystem clashes with what is expected to be used in this specification.

  • Using SASS naming conventions as an archetype for a design token naming conventions feels odd, because the SSOT for design tokens will be JSON, right? Why not stick to common naming patterns from the Javascript world then, which IMO would make more sense then having dollar signs and a lot of kebab-case variable names?
  • The jQuery example should just show, where this special character was already been used. Of course I know that it is the alias for the whole library object, but my point is that parts of the web community back then already disliked the $ for it.
  • Further the RxJS example should just show, that there already have been times, where people introduced the $ prefix for observables, in oderer to mark those variables as a stream of data, but there has ever since been controversial thoughts about that in the community.
  • I think it took me a while until I understood your statement "Design tokens are more closely related to styling variables than DOM manipulation". Do not get mislead by my examples, that I am mixing up what design tokens are and what DOM manipulation is. But as the design token definitions and SSOTs of these design tokens will be in the JSON format, I have a strong focus on how these design token definitions will later be used as the input of some Javascript tooling and maybe a whole ecosystem around it.
  • You are right that plenty of $ signs have been used in other languages, but with JSON we just are in the realm of Javascript. From my experience it has never been good advice to work against a framework or programming language, in regard of the controversies in past and common practices within Javascript.

Regardless of the history, what I find beneficial in the $ prefix here has to do with JSON's restrictions. While yes it would be great to have all of these enhancements to help the developer experience, the core of the specification is expected to align with JSON's limitations, AFAICT. We have used _ to denote private because the language used doesn't support the concept of private (until it does). This isn't necessarily meant for someone to edit in an IDE but for systems to ingest and transform into styles.

  • I know that the JSON restrictions sometimes are pretty tight. Probably this is the reason for things like JSON5 gaining more and more popularity, but they are not solving the kinds of restrictions you are referring to.
  • For defining private things I actually can live with an underscore "_", because of the JSON restrictions I also see no other possibility here. Furthermore this is common knowledge among developers. I still have the opinion that things like that should be avoided if possible, cause in fact this is coming from legacy programming times, where no IDEs existed and there has been no other possibility to indicate to developers, that this should be treated as private. Today though with the modern IDEs this is not an issue anymore, but is reducing the code readability.
  • Another disadvantage of a special character prefix is, which btw we already have been faced a lot with in SASS variables, is that you will always miss selecting the $ sign, when simply double clicking on the variable name, which might result in an annoying DX: double click word selection

Further, I find that the $ provides more clarity as a "special" field than if special keys were to exist without needing to dive into documentation. It should raise the question, "Why do these keys have this prefix?" as opposed to if keys look like any other keys. However, given that you've raised the idea, I'd like to know what you suggest as alternatives, knowing the limitations.

  • Only thing here is that I could not see how the $ special character is helping more here, compared to just a written word prefix like "token" for example. If you say a developer who sees the $ sign should ask himself "Why do these keys have this prefix?", doesn't he then have to look into the documentation, opposed to when we would actually have a speakable variable name with a prefix that marks these properties, but you already understand while reading it, for what this property stands for?

specialness in human review is a big sell for the $ - and I don't see the $ translating to tokens in CSS or in places where it'll clash with a JQuery or equivalent.

  • IMO it would be a big sell for using speakable property names, that are easier to review by humans, compared the special character prefixes, @nesquarx !?
  • I am aware, that the actual token names, except they are compiled to i.e. SCSS web platform output format, will have no dollar sign in it. I am very well differentiating this, but there are use cases where the original SSOT design token definition might be used as a source, for example to have a dynamic design token documentation on a website, which is displaying the design token value, depending on its type in different ways and also wants to show the description maybe. I am not recommending that someone should build such a documentation with jQuery 😆 but I am convinced that this could be a common use case and in theory, there it could clash with jQuery or RxJS. Like I already said, the design token SSOT definitions in the JSON files, will not only be the source for the actual design token output files for different platforms in different formats, it will also be the source for a whole ecosystem of tools around design tokens, which will have to rely on this standard in the end.

So here is my innocent take on this

Referring to your example from https://design-tokens.github.io/community-group/format/#description-0

{
  "brand": {
    "$description": "Design tokens from our brand guidelines",
    "color": {
      "$description": "Our brand's primary color palette",
      "acid green": {
        "$value": "#00ff66"
      },
      "hot pink": {
        "$value": "#dd22cc"
      }
    }
  }
}

$description but also $type can be used on a group level. If one concern is to prevent conflicts between the property names of the design token standard and possible design token names, then it would also help if there are no conflicts of properties that are on different levels in the object hierarchy of the design token definitions. While the description on the group level also is a description just like a description for a single design token, there is still the difference for what these descriptions stand for. One for a group of tokens and one for a single token. Therefore I suggest that we actually name these descriptions for what they actually stand for: tokenGroupDescription and tokenDescription

I would suggest the following:

{
  "brand": {
    "tokenGroupDescription": "Design tokens from our brand guidelines",
    "color": {
      "tokenGroupDescription": "Our brand's primary color palette",
      "acid green": {
        "tokenValue": "#00ff66",
        "tokenType": "color",
        "tokenDescription": "Really ugly green",
      },
      "hot pink": {
        "tokenValue": "#dd22cc",
        "tokenType": "color",
        "tokenDescription": "Really hot pink",
      }
    }
  }
}

with the following exemplary JSON naming schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "patternProperties": {
    ".*": {
      "type": "object",
      "properties": {
        "tokenGroupDescription": {
          "type": "string"
        },
        ".*": {
          "type": "object",
          "properties": {
            "tokenGroupDescription": {
              "type": "string"
            },
            ".*": {
              "type": "object",
              "properties": {
                "tokenValue": {
                  "type": "string",
                  "pattern": "^#[0-9a-fA-F]{6}$"
                },
                "tokenType": {
                  "type": "string",
                  "enum": ["color"]
                },
                "tokenDescription": {
                  "type": "string"
                }
              },
              "required": ["tokenValue", "tokenType"]
            }
          }
        }
      }
    }
  }
}

I am on vacation for the next time, but I sure will pick up any discussion for when I am back in September.

DarioSoller avatar Aug 15 '24 01:08 DarioSoller

I don't know what's odd about using Sass as the archetype, considering these are design tokens, meaning they have roots in design. This makes them closer to the ecosystem of style as opposed to behavior as Javascript does. This was my comment regarding DOM manipulation; it has nothing to do with examples. The JSON is merely the transportation layer between systems, as this isn't limited to a JS ecosystem. Systems could ingest tokens in Python, Rust, or whatever. It's either JSON or XML as options in this case, and I have great confidence that no one wants to parse XML again. So, it's inaccurate to say JSON is strictly in the realm of Javascript.

I don't have any details about folks disliking jQuery because of the namespace convention it used. However, I'm not going to discuss jQuery any further because it's really a tangent in this conversation. If you are really afraid of clashing, use the jQuery namespace instead of the $; problem solved.

My comment about the quality of specialness certainly involves educating oneself about the schema, most likely through documentation. Without the prefix, I can imagine someone could accidentally remove expected keys because the file would look like unstructured data, as none of the keys look all that special. Personally, I'd use more caution if I saw keys with $ prefix.

ddamato avatar Aug 15 '24 02:08 ddamato

@ddamato agreed with all of the above 💯

mryechkin avatar Aug 15 '24 03:08 mryechkin

Historical Context: The use of the "$" prefix can be reminiscent of older practices, such as those seen in jQuery, which may not align with modern coding standards and practices. Additionally, this prefix has been used in other contexts, such as RxJS observables, which has led to some confusion and mixed opinions within the developer community.

I'm reasonably sure the $ convention used here is based on the variable naming convention originating in Sass.

I don’t believe any of these are correct or relevant to the original decision. As I see you reached the conclusion, the primary need for this character is to mark reserved object keys. Reserving common words like description or group is too limiting on what tokens can be named (people may want a token named typography.description or card.group.bg-color).

The $ character specifically was inspired by JSONSchema that uses this pattern to reserve words. JSONSchema is a very relevant pattern to the DTCG spec because it allows arbitrary nesting, something that’s forbidden in other schema formats (e.g. OpenAPI). In the case of arbitrary nesting, you must reserve certain words and forbid them from usage. Using a prefix is the best of both words, being able to reserve many words, and make their reservation clear, without requiring verbosity and without reasonable conflicts with arbitrary user-provided names.

Additional technical explanation

The DTCG format is basically an Abstract Syntax Tree (AST) format. It can be parsed, and traversed, and every level (“node”) must be classified as either a group or token. As-defined, a node is a token if it contains $value (not $type), otherwise it is a group. Classification must happen using type discrimination. In traditional ASTs, you literally have a type: "[type]" key (or kind) at every level, which then determines the other properties you may have.

However, manually typing this out is very user-hostile. It’s a ton of boilerplate and overhead, but done in the service of making parsing and traversal trivially easy. So how do we keep all the benefits of an AST, without making it impossible to write by hand?

Again, borrowing from JSONSchema’s innovations in this area, the $ prefix is a brilliant solution to this hard problem of allowing an AST to be expressed in an incredibly human-readable & writable format. But while still being easy to parse. DTCG was wise to stand on the shoulders of giants here and solve the same problem in the same way.

Remember—this is a schema format. JSONSchema is a very close parallel. RxJS, jQuery, Sass, or what have you are all irrelevant. Draw what conclusions you want to personally, but none of those comparisons apply.

Could there be alternative approaches that might achieve the same goals without the drawbacks associated with the "$" prefix?

$description but also $type can be used on a group level. If one concern is to prevent conflicts between the property names of the design token standard and possible design token names, then it would also help if there are no conflicts of properties that are on different levels in the object hierarchy of the design token definitions. … Therefore I suggest that we actually name these descriptions for what they actually stand for: tokenGroupDescription and tokenDescription

Through discussion you arrived at a proposal to consider, changing $typetokenType, $grouptokenGroup, etc. You’ve come to the same exact design pattern—requiring a prefix—but you’ve just chosen verbosity because you don’t like the $ character. You mention “drawbacks” to using $ but I didn’t see a specific technical downside other than the opinion of “I see it in jQuery and jQuery is old and I think it’s bad therefore we should change it.”

This is a stylistic change that doesn’t solve any real problems with the schema as-currently-defined. And it’s one proposed without acknowledging relevant prior art like JSONSchema. So I’m personally not in favor of just changing an existing, working schema just because you personally don’t like its aesthetics. But if you feel strongly, I’d recommend making a new issue with a formal syntax proposal change to be reviewed.

drwpow avatar Aug 17 '24 21:08 drwpow

tokenGroupDescription is less readable than $description. You know, as a designer I see unnecessary words and clutter.

To be clear - $ (or any prefix) was selected to eliminate conflicts of new standard properties with somebody's custom properties down the road? Because otherwise I don't see any added value.

danosek avatar Aug 22 '24 12:08 danosek

To be clear - $ (or any prefix) was selected to eliminate conflicts of new standard properties with somebody's custom properties down the road? Because otherwise I don't see any added value.

I just answered this in my comment before yours. JSONSchema. Arbitrary nesting in ASTs.

drwpow avatar Aug 22 '24 14:08 drwpow

Thanks, @drwpow, for mentioning that the primary need for the "$" prefix derived from the necessity to mark reserved object keys. Also, thanks for adding the respective source from the JSON Schema spec, which I hadn’t considered. This brings the discussion in the right direction.

Maybe you can help me better understand a few parts of this specification. For example, at the bottom of section 8, it states:

"While the "$" prefix is not formally reserved for the Core vocabulary, it is RECOMMENDED that extension keywords (in vocabularies or otherwise) begin with a character other than "$" to avoid possible future collisions."

If I understand this correctly, we have the following situation:

  1. "$" Prefix Not Formally Reserved: The "$" prefix is not exclusively reserved for the core vocabulary, meaning that technically, you could use it for other purposes.
  2. Recommendation for Extension Keywords: Despite the lack of formal reservation, it is recommended that any extension keywords (whether they are part of a custom vocabulary or otherwise) should not begin with the "$" character.
  3. Reason for the Recommendation: The primary reason for this recommendation is to avoid possible future collisions. As the JSON Schema specification evolves, new core keywords prefixed with "$" might be introduced. If your custom keywords also use the "$" prefix, they could conflict with these future additions.

Am I understanding it wrong? Could anyone maybe provide even more technical clarification here?

And regarding one of the other comments:

tokenGroupDescription is less readable than $description. You know, as a designer I see unnecessary words and clutter.

I still stick to my suggestion because, for me, it is less friction reading a longer variable name rather than having to resolve the abstraction for what the "$" prefix stands for. Also, keeping in mind how people read words, the order of characters doesn’t really matter as long as the first and last character are correct. This implies that reading speed is not significantly affected by the length of a word.

DarioSoller avatar Sep 27 '24 14:09 DarioSoller

I confirm what @drwpow said, there is no connection to Sass's usage of $.

@DarioSoller thank you for the great question and proposing alternatives. I do like your suggestions. I'm not saying $description is better than tokenGroupDescription, in fact I'd argue tokenGroupDescription is better in the sense it fully disambiguates the purpose of this key/value pair.

We instead chose to go the $-prefix route, and ran it past the author of JSON Schema himself, @Relequestual, who confirmed we weren't doing anything silly that would come back to haunt us later.

Sometimes, multiple appropriate avenues are open to us, and our job is to make a choice so the spec can move forward!

kaelig avatar Nov 14 '24 17:11 kaelig

Thank you for the detailed response @kaelig and for considering my suggestions. I appreciate the clarification regarding the "$" prefix usage and the assurance that it was reviewed with the JSON schema author.

I understand that multiple valid approaches exist, and I respect the choices made to advance the specification. However, I personally still feel stuck with the potential contradiction between the recommendation in the JSON schema spec regarding the use of the "$" prefix for extension keywords and the decision to use it here. Maybe, just maybe, so that I can find some peace with this, you could share any further insights into how this was reconciled during your discussions with the JSON schema author @Relequestual?

I'm looking forward to seeing how the spec evolves and contributes to the community. So thanks again for your efforts!

DarioSoller avatar Nov 29 '24 17:11 DarioSoller