glam/.opencode/rules/generic-slots-specific-classes.md
kempersc ca4a54181e Refactor schema files to improve clarity and maintainability
- Updated WorldCatIdentifier.yaml to remove unnecessary description and ensure consistent formatting.
- Enhanced WorldHeritageSite.yaml by breaking long description into multiple lines for better readability and removed unused attributes.
- Simplified WritingSystem.yaml by removing redundant attributes and ensuring consistent formatting.
- Cleaned up XPathScore.yaml by removing unnecessary attributes and ensuring consistent formatting.
- Improved YoutubeChannel.yaml by breaking long description into multiple lines for better readability.
- Enhanced YoutubeEnrichment.yaml by breaking long description into multiple lines for better readability.
- Updated YoutubeVideo.yaml to break long description into multiple lines and removed legacy field name.
- Refined has_or_had_affiliation.yaml by removing unnecessary comments and ensuring clarity.
- Cleaned up is_or_was_retrieved_at.yaml by removing unnecessary comments and ensuring clarity.
- Added rules for generic slots and avoiding rough edits in schema files to maintain structural integrity.
- Introduced changes_or_changed_through.yaml to define a new slot for linking entities to change events.
2026-01-31 00:46:23 +01:00

129 lines
3.5 KiB
Markdown

# 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
```yaml
# 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
```yaml
# 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
```yaml
# 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
```yaml
# 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_hours``has_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_name``has_name`)
* Narrow types (e.g., `has_isbn_identifier``has_identifier`)
* Contextual specifics (e.g., `has_primary_email``has_email` + type/role)
## See Also
* Rule 55: Broaden Generic Predicate Ranges
* Rule 39: Slot Naming Convention (RiC-O Style)