129 lines
3.5 KiB
Markdown
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: Slot Naming Convention (Current Style)
|