6 KiB
6 KiB
Rule: LinkML Type/Types File Naming Convention
Version: 1.0.0
Created: 2025-01-04
Status: Active
Applies to: schemas/20251121/linkml/modules/classes/
Rule Statement
When creating class hierarchies that replace enums in LinkML schemas, follow the Type/Types naming pattern to clearly distinguish abstract base classes from their concrete subclasses.
Pattern Definition
| File Name Pattern | Purpose | Contains |
|---|---|---|
[Entity]Type.yaml (singular) |
Abstract base class | Single abstract class defining the type taxonomy |
[Entity]Types.yaml (plural) |
Concrete subclasses | All concrete subclasses inheriting from the base |
Examples
Current Implementations
| Base Class File | Subclasses File | Subclass Count | Description |
|---|---|---|---|
DigitalPlatformType.yaml |
DigitalPlatformTypes.yaml |
69 | Digital platform type taxonomy |
WebPortalType.yaml |
WebPortalTypes.yaml |
~15 | Web portal type taxonomy |
CustodianType.yaml |
CustodianTypes.yaml |
19 | Heritage custodian type taxonomy (GLAMORCUBESFIXPHDNT) |
DataServiceEndpointType.yaml |
DataServiceEndpointTypes.yaml |
7 | API/data service endpoint types |
File Structure Example
modules/classes/
├── DigitalPlatformType.yaml # Abstract base class
├── DigitalPlatformTypes.yaml # 69 concrete subclasses
├── WebPortalType.yaml # Abstract base class
├── WebPortalTypes.yaml # ~15 concrete subclasses
├── CustodianType.yaml # Abstract base class
└── CustodianTypes.yaml # 19 concrete subclasses
Import Pattern
The subclasses file MUST import the base class file:
# In DigitalPlatformTypes.yaml (subclasses file)
id: https://w3id.org/heritage-custodian/linkml/digital_platform_types
name: digital_platform_types
imports:
- linkml:types
- ./DigitalPlatformType # Import base class (singular)
classes:
DigitalLibrary:
is_a: DigitalPlatformType # Inherit from base
description: >-
A digital library platform providing access to digitized collections.
class_uri: schema:DigitalDocument
DigitalArchive:
is_a: DigitalPlatformType
description: >-
A digital archive for born-digital or digitized archival materials.
Slot Range Pattern
When other classes reference the type taxonomy, use the base class (singular) as the range:
# In DigitalPlatform.yaml
imports:
- ./DigitalPlatformType # Import base class for range
- ./DigitalPlatformTypes # Import subclasses for validation
classes:
DigitalPlatform:
slots:
- platform_type
slot_usage:
platform_type:
range: DigitalPlatformType # Use base class as range
description: >-
The type of digital platform. Value must be one of the
concrete subclasses defined in DigitalPlatformTypes.
Anti-Patterns
What NOT to Do
| Anti-Pattern | Why It's Wrong | Correct Alternative |
|---|---|---|
DigitalPlatformTypeBase.yaml |
"Base" suffix is redundant; singular "Type" already implies base class | DigitalPlatformType.yaml |
DigitalPlatformTypeClasses.yaml |
"Classes" is less intuitive than "Types" for a type taxonomy | DigitalPlatformTypes.yaml |
| All types in single file | Large files are hard to navigate; separation clarifies architecture | Split into Type.yaml + Types.yaml |
DigitalPlatformEnum.yaml |
Enums lack extensibility; class hierarchies are preferred | Use class hierarchy pattern |
Example of Incorrect Naming
# WRONG - Don't use "Base" suffix
# File: DigitalPlatformTypeBase.yaml
classes:
DigitalPlatformTypeBase: # Redundant "Base"
abstract: true
# CORRECT - Use singular "Type"
# File: DigitalPlatformType.yaml
classes:
DigitalPlatformType: # Clean, clear naming
abstract: true
Rationale
- Clarity: "Type" (singular) = one abstract concept; "Types" (plural) = many concrete implementations
- Discoverability: Related files appear adjacent in alphabetical directory listings
- Consistency: Follows established pattern across entire schema
- Semantics: Mirrors natural language ("a platform type" vs "the platform types")
- Scalability: Easy to add new types without modifying base class file
Migration Checklist
When renaming existing files to follow this convention:
Pre-Migration
- Identify all files referencing the old name
- Create backup or ensure version control is clean
- Document the old → new name mapping
File Rename
- Rename file:
[Entity]TypeBase.yaml→[Entity]Type.yaml - Update
id:field in renamed file - Update
name:field in renamed file - Update class name inside the file
- Update all internal documentation references
Update References
- Update imports in
[Entity]Types.yaml(subclasses file) - Update
is_a:in all subclasses - Update imports in consuming classes (e.g.,
DigitalPlatform.yaml) - Update
range:in slot definitions - Update any
slot_usage:references
Documentation
- Update AGENTS.md if convention is documented there
- Update any design documents
- Add migration note to changelog
Verification
# Verify no references to old name remain
grep -r "OldClassName" schemas/20251121/linkml/
# Verify new file exists
ls -la schemas/20251121/linkml/modules/classes/NewClassName.yaml
# Verify old file is removed
ls -la schemas/20251121/linkml/modules/classes/OldClassName.yaml # Should fail
# Validate schema
linkml-validate schemas/20251121/linkml/01_custodian_name.yaml
Related Rules
- Rule 0: LinkML Schemas Are the Single Source of Truth
- Rule 9: Enum-to-Class Promotion - Single Source of Truth
Changelog
| Date | Version | Change |
|---|---|---|
| 2025-01-04 | 1.0.0 | Initial rule created after DigitalPlatformType refactoring |