Part-DB-server/ENTITY_REFACTORING.md
copilot-swe-agent[bot] 2d36373bea Add trait dependency documentation and architecture diagrams
Co-authored-by: jbtronics <5410681+jbtronics@users.noreply.github.com>
2026-01-02 23:51:52 +00:00

7.2 KiB

Entity Inheritance Hierarchy Decomposition

Overview

This refactoring decomposes the deep entity inheritance hierarchy into a more flexible trait-based architecture. This provides better code reusability, composition, and maintainability.

Architecture Diagram

Before (Deep Inheritance):

AbstractDBElement (ID logic)
    └─ AbstractNamedDBElement (name + timestamps)
        └─ AttachmentContainingDBElement (attachments)
            └─ AbstractStructuralDBElement (tree/hierarchy + parameters)
                ├─ AbstractPartsContainingDBElement
                │   ├─ Category
                │   ├─ Footprint
                │   ├─ StorageLocation
                │   └─ AbstractCompany (company fields)
                │       ├─ Manufacturer
                │       └─ Supplier

After (Trait Composition):

Traits:                          Interfaces:
- DBElementTrait                 - DBElementInterface
- NamedElementTrait              - NamedElementInterface
- TimestampTrait                 - TimeStampableInterface
- AttachmentsTrait               - HasAttachmentsInterface
- MasterAttachmentTrait          - HasMasterAttachmentInterface
- StructuralElementTrait         - StructuralElementInterface
- ParametersTrait                - HasParametersInterface
- CompanyTrait                   - CompanyInterface

Class Hierarchy (now uses traits):
AbstractDBElement (uses DBElementTrait, implements DBElementInterface)
    └─ AbstractNamedDBElement (uses NamedElementTrait + TimestampTrait)
        └─ AttachmentContainingDBElement (uses AttachmentsTrait + MasterAttachmentTrait)
            └─ AbstractStructuralDBElement (uses StructuralElementTrait + ParametersTrait)
                ├─ AbstractPartsContainingDBElement
                │   ├─ Category (gets all traits via inheritance)
                │   ├─ Footprint (gets all traits via inheritance)
                │   └─ AbstractCompany (uses CompanyTrait)
                │       ├─ Manufacturer
                │       └─ Supplier

Changes Made

New Traits Created

  1. DBElementTrait (src/Entity/Base/DBElementTrait.php)

    • Provides basic database element functionality with an ID
    • Includes getID() method and clone helper
    • Extracted from AbstractDBElement
  2. NamedElementTrait (src/Entity/Base/NamedElementTrait.php)

    • Provides named element functionality (name property and methods)
    • Includes getName(), setName(), and __toString() methods
    • Extracted from AbstractNamedDBElement
  3. AttachmentsTrait (src/Entity/Base/AttachmentsTrait.php)

    • Provides attachments collection functionality
    • Includes methods for adding, removing, and getting attachments
    • Includes clone helper for deep cloning attachments
    • Extracted from AttachmentContainingDBElement
  4. StructuralElementTrait (src/Entity/Base/StructuralElementTrait.php)

    • Provides tree/hierarchy functionality for structural elements
    • Includes parent/child relationships, path calculations, level tracking
    • Includes methods like isRoot(), isChildOf(), getFullPath(), etc.
    • Extracted from AbstractStructuralDBElement
  5. CompanyTrait (src/Entity/Base/CompanyTrait.php)

    • Provides company-specific fields (address, phone, email, website, etc.)
    • Includes getters and setters for all company fields
    • Extracted from AbstractCompany

New Interfaces Created

  1. DBElementInterface (src/Entity/Contracts/DBElementInterface.php)

    • Interface for entities with a database ID
    • Defines getID() method
  2. StructuralElementInterface (src/Entity/Contracts/StructuralElementInterface.php)

    • Interface for structural/hierarchical elements
    • Defines methods for tree navigation and hierarchy
  3. CompanyInterface (src/Entity/Contracts/CompanyInterface.php)

    • Interface for company entities
    • Defines basic company information accessors
  4. HasParametersInterface (src/Entity/Contracts/HasParametersInterface.php)

    • Interface for entities that have parameters
    • Defines getParameters() method

Refactored Classes

  1. AbstractDBElement

    • Now uses DBElementTrait
    • Implements DBElementInterface
    • Simplified to just use the trait instead of duplicating code
  2. AbstractNamedDBElement

    • Now uses NamedElementTrait in addition to existing TimestampTrait
    • Cleaner implementation with trait composition
  3. AttachmentContainingDBElement

    • Now uses AttachmentsTrait and MasterAttachmentTrait
    • Simplified constructor and clone methods
  4. AbstractStructuralDBElement

    • Now uses StructuralElementTrait and ParametersTrait
    • Implements StructuralElementInterface and HasParametersInterface
    • Much cleaner with most functionality extracted to trait
  5. AbstractCompany

    • Now uses CompanyTrait
    • Implements CompanyInterface
    • Significantly simplified from ~260 lines to ~20 lines

Benefits

1. Better Code Reusability

  • Traits can be reused in different contexts without requiring inheritance
  • Easier to mix and match functionality

2. Improved Maintainability

  • Each trait focuses on a single concern (SRP - Single Responsibility Principle)
  • Easier to locate and modify specific functionality
  • Reduced code duplication

3. More Flexible Architecture

  • Entities can now compose functionality as needed
  • Not locked into a rigid inheritance hierarchy
  • Easier to add new functionality without modifying base classes

4. Better Testability

  • Traits can be tested independently
  • Easier to mock specific functionality

5. Clearer Contracts

  • Interfaces make dependencies explicit
  • Better IDE support and type hinting

Migration Path

This refactoring is backward compatible - all existing entities continue to work as before. The changes are internal to the base classes and do not affect the public API.

For New Entities

New entities can now:

  1. Use traits directly without deep inheritance
  2. Mix and match functionality as needed
  3. Implement only the interfaces they need

Example:

class MyCustomEntity extends AbstractDBElement implements NamedElementInterface 
{
    use NamedElementTrait;
    
    // Custom functionality
}

Technical Details

Trait Usage Pattern

All traits follow this pattern:

  1. Declare properties with appropriate Doctrine/validation annotations
  2. Provide initialization methods (e.g., initializeAttachments())
  3. Provide business logic methods
  4. Provide clone helpers for deep cloning when needed

Interface Contracts

All interfaces define the minimal contract required for that functionality:

  • DBElementInterface: requires getID()
  • NamedElementInterface: requires getName()
  • StructuralElementInterface: requires hierarchy methods
  • CompanyInterface: requires company info accessors
  • HasParametersInterface: requires getParameters()

Future Improvements

Potential future enhancements:

  1. Extract more functionality from remaining abstract classes
  2. Create more granular traits for specific features
  3. Add trait-specific unit tests
  4. Consider creating trait-based mixins for common entity patterns