liveBook · Manning

ImposeConstraints strategy

As explained in Building User-Friendly DSLs

A book-specific validation strategy that detects and reports missing or invalid domain-specific language content rather than silently accepting it.

ImposeConstraints prevents failures caused by invalid domain-specific language content by adding checks to the Domain IDE. Violations become explicit issues that tell domain experts what to fix and where, rather than silently reaching the generator, build step, or Runtime. section 9.2.1 section 9.4

Implement constraints around the kinds of invalid content that can make generated software fail or behave nonsensically:

  • Check unspecified content, such as empty names, undefined types, missing reference targets, or undefined numeric values. section 9.3.2 section 9.4
  • Check types across related DSL content, such as requiring an attribute reference and its target to have matching types. section 9.4 section 9.3.6
  • Check uniqueness after name transformations, because distinct names can produce the same generated identifier and confusing Runtime fields. section 9.3.6

Rejecting similar attribute names

If two attributes become the same camel-cased identifier, such as fooBar, report the conflict on the affected attribute. A constraint can compute the current identifier, compare it with neighboring attributes, and issue a message listing similarly named attributes. This is preferable to allowing duplicate generated fields with incompatible types. section 9.3.6

const thisCamelCasedName =
   camelCase(astObject.settings["name"])    #1
const similarlyNamed =                          #2
   ancestors[0].settings["attributes"].filter((attribute) =>
  attribute !== astObject                           #3
     && camelCase(attribute.settings["name"])
         === thisCamelCasedName                    #4
)
if (similarlyNamed.length > 0) {         #5
  issues.push(
 `This attribute's name is too similar to the following
     other attributes' names:
         ${quotedNamesOf(similarlyNamed).join(", ")}`   #6
    )
}

Shows the implementation pattern for detecting name collisions: transform the current name, filter comparable attributes, and report matches. section 9.3.6

Use this strategy as the first measure, optionally alongside HandleFaultyContent. PreventPersistence is a later safeguard because preserving faulty ASTs can let domain experts share them with software developers for repair. section 9.4

How Building User-Friendly DSLs covers it

How deep it goes
Defines unspecified-content, type-checking, and uniqueness constraints with JavaScript implementation patterns, but defers complete DSL coverage.
Examples
Uses missing names, missing types, invalid references, undefined numbers, and camel-cased attribute-name collisions as constraint cases.
What it assumes
Assumes familiarity with DSL content, ASTs, generators, and Domain IDE behavior while teaching concrete constraint categories through examples.
What you can do after
Implement validation in the Domain IDE that reports actionable issues before faulty DSL content causes downstream failures.
How it connects
Connects Domain-Specific Languages, abstract syntax trees, generators, HandleFaultyContent, PreventPersistence, and uniqueness constraints.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Building User-Friendly DSLs. The section links point to the parts of the book it draws on.