- Deleted obsolete slot definitions: statement_summary, statement_text, statement_type, status_name, supersede_articles, supersede_condition, supersede_name, temporal_dynamics, total_amount, typical_contents, use_cases, was_acquired_through, was_fetched_at, was_retrieved_at. - Updated existing slot definitions for states_or_stated to enhance clarity and structure. - Introduced new classes: Article, ConditionofAccess, FinancialStatementType, MaximumQuantity, Series, Summary, Type, and their respective slots to improve schema organization and usability. - Added new slots: changes_or_changed_through, has_or_had_condition_of_access, has_or_had_heritage_type, is_or_was_part_of_series, is_or_was_retrieved_at, maximum_of_maximum to capture additional metadata and relationships.
6.9 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 |
Class Naming Convention
🚨 CRITICAL: Follow these naming rules for classes within the files:
-
Abstract Base Class (
[Entity]Type.yaml):- MUST end with
Typesuffix. - Example:
DigitalPlatformType,WarehouseType.
- MUST end with
-
Concrete Subclasses (
[Entity]Types.yaml):- MUST NOT end with
Typesuffix. - Use the natural entity name.
- Example:
DigitalLibrary(✅),CentralDepot(✅). - Incorrect:
DigitalLibraryType(❌),CentralDepotType(❌).
- MUST NOT end with
Rationale: The file context (WarehouseTypes.yaml) already establishes these are types. Repeating "Type" in the class name is redundant and makes the class name less natural when used as an object instance (e.g., "This object is a CentralDepot").
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 |
CentralDepotType (Class Name) |
Redundant "Type" suffix on concrete subclass | CentralDepot |
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 |