glam/.opencode/rules/generic-slots-specific-classes.md

3.5 KiB

Rule: Generic Slots, Specific Classes

Identifier: generic-slots-specific-classes Severity: CRITICAL

Core Principle

Slots MUST be generic predicates that can be reused across multiple classes. Classes MUST be specific to provide context and constraints.

DO NOT create class-specific slots when a generic predicate can be used.

Rationale

  1. Predicate Proliferation: Creating bespoke slots for every class explodes the schema size (e.g., has_museum_name, has_library_name, has_archive_name instead of has_name).
  2. Interoperability: Generic predicates (has_name, has_identifier, has_part) map cleanly to standard ontologies (Schema.org, Dublin Core, RiC-O).
  3. Querying: It's easier to query "all entities with a name" than "all entities with museum_name OR library_name OR archive_name".
  4. Maintenance: Updating one generic slot propagates to all classes.

Examples

Anti-Pattern: Class-Specific Slots

# WRONG: Creating specific slots for each class
slots:
  has_museum_visitor_count:
    range: integer
  has_library_patron_count:
    range: integer

classes:
  Museum:
    slots:
      - has_museum_visitor_count
  Library:
    slots:
      - has_library_patron_count

Correct Pattern: Generic Slot, Specific Class Usage

# CORRECT: One generic slot reused
slots:
  has_or_had_quantity:
    slot_uri: rico:hasOrHadQuantity
    range: Quantity
    multivalued: true

classes:
  Museum:
    slots:
      - has_or_had_quantity
    slot_usage:
      has_or_had_quantity:
        description: The number of visitors to the museum.

  Library:
    slots:
      - has_or_had_quantity
    slot_usage:
      has_or_had_quantity:
        description: The number of registered patrons.

Intermediate Class Pattern

Making slots generic often requires introducing Intermediate Classes to hold structured data, rather than flattening attributes onto the parent class.

Anti-Pattern: Specific Flattened Slots

# WRONG: Flattened specific attributes
classes:
  Museum:
    slots:
      - has_museum_budget_amount
      - has_museum_budget_currency
      - has_museum_budget_year

Correct Pattern: Generic Slot + Intermediate Class

# CORRECT: Generic slot pointing to structured class
slots:
  has_or_had_budget:
    range: Budget
    multivalued: true

classes:
  Museum:
    slots:
      - has_or_had_budget

  Budget:
    slots:
      - has_or_had_amount
      - has_or_had_currency
      - has_or_had_year

Specificity Levels

Level Component Example
Generic Slot (Predicate) has_or_had_identifier
Specific Class (Subject/Object) ISILCode
Specific Slot Usage (Context) "The ISIL code assigned to this library"

Migration Guide

If you encounter an overly specific slot:

  1. Identify the generic concept (e.g., has_museum_opening_hourshas_opening_hours).
  2. Check if a generic slot exists in modules/slots/.
  3. If yes, use the generic slot and add slot_usage to the class.
  4. If no, create the generic slot, not a specific one.

Naming Indicators

Reject slots containing:

  • Class names (e.g., has_custodian_namehas_name)
  • Narrow types (e.g., has_isbn_identifierhas_identifier)
  • Contextual specifics (e.g., has_primary_emailhas_email + type/role)

See Also

  • Rule 55: Broaden Generic Predicate Ranges
  • Rule: Slot Naming Convention (Current Style)