Files
component-system/design_docs/hierarchical_analysis.md
2025-09-17 23:32:46 +02:00

5.8 KiB

Hierarchical Implementation Analysis

Overview

This document analyzes the current hierarchical implementations in the codebase (Categories and Storage Locations) to determine the best approach for creating a shared Hierarchical behavior module.

Current State Analysis

Categories vs Storage Locations Feature Comparison

Feature Categories Storage Locations Assessment
Path Resolution Simple recursive function in schema Complex virtual fields + batch computation Categories wins - cleaner approach
Cycle Prevention UI-level filtering (preventive) Changeset validation (reactive) Categories wins - more efficient
Hierarchical Display Recursive LiveView components Recursive LiveView components Tie - nearly identical
Parent Selection Smart dropdown filtering Smart dropdown filtering Tie - identical logic
Performance O(depth) recursive calls O(n) batch computation + DB queries Categories wins - simpler
Code Complexity ~50 lines of hierarchy logic ~100+ lines of hierarchy logic Categories wins - more maintainable

Key Findings

1. Vestigial is_active Field Removed

  • Status: REMOVED
  • Impact: Field was completely unused across the entire codebase
  • Files Modified:
    • lib/components_elixir/inventory/storage_location.ex (schema and changeset)
    • Migration created: 20250917210658_remove_is_active_from_storage_locations.exs

2. Categories Implementation is Superior

Path Resolution Approach

Categories: Elegant recursive function in schema

def full_path(%Category{parent: nil} = category), do: category.name
def full_path(%Category{parent: %Category{} = parent} = category) do
  "#{full_path(parent)} > #{category.name}"
end

Storage Locations: Over-engineered with virtual fields

# Virtual fields in schema
field :level, :integer, virtual: true
field :path, :string, virtual: true

# Complex batch computation in context
def compute_hierarchy_fields_batch(locations)
def compute_level_for_single(location)  
def compute_path_for_single(location)

Cycle Prevention Strategy

Categories: Prevention at UI level (efficient)

# Prevents invalid options from appearing in dropdown
|> Enum.reject(fn cat ->
  cat.id == editing_category_id ||
  (editing_category_id && is_descendant?(categories, cat.id, editing_category_id))
end)

Storage Locations: Validation at changeset level (reactive)

# Validates after user attempts invalid selection
defp validate_no_circular_reference(changeset) do
  # Complex validation logic that runs on every save attempt
end

3. Shared Patterns Identified

Both systems implement identical patterns for:

  • Hierarchical tree display with recursive LiveView components
  • Parent/child relationship filtering
  • Descendant detection algorithms
  • Root entity identification
  • UI depth-based styling and icons

Architecture Decision

The category implementation should be the template for generalization because:

  1. Simpler: No virtual fields or complex batch operations
  2. More Performant: O(depth) vs O(n) complexity
  3. Preventive: UI-level cycle prevention vs reactive validation
  4. Maintainable: Half the lines of code with same functionality

AprilTag Features Remain Storage-Specific

The AprilTag system should NOT be generalized because:

  • Physical identification is meaningless for categories
  • Future scanning/detection features are location-specific
  • Keeps domain separation clean

Implementation Complexity Comparison

Categories (Simple & Clean)

Files: 1 schema + 1 LiveView = 2 files
Lines: ~50 lines hierarchical logic
Approach: Functional, recursive, preventive
Dependencies: Standard Ecto associations

Storage Locations (Over-Engineered)

Files: 1 schema + 1 context helper + 1 LiveView = 3 files  
Lines: ~100+ lines hierarchical logic
Approach: Stateful, batch processing, reactive
Dependencies: Virtual fields + custom computation

Performance Analysis

Path Resolution Performance

  • Categories: O(depth) - traverses only parent chain
  • Storage Locations: O(n) - processes all entities for batch computation

Memory Usage

  • Categories: Minimal - uses existing associations
  • Storage Locations: Higher - virtual fields + intermediate computations

Database Queries

  • Categories: Standard association preloading
  • Storage Locations: Additional queries for path/level computation

Code Quality Assessment

Categories Strengths

Single Responsibility: Each function does one thing
Functional Style: Pure functions, no side effects
Standard Patterns: Uses established Ecto association patterns
Easy Testing: Simple recursive functions
Performance: Minimal computational overhead

Storage Locations Issues

Multiple Responsibilities: Virtual fields + validation + computation
Complex State: Virtual fields require careful management
Custom Patterns: Non-standard Ecto usage
Hard Testing: Complex batch operations
Performance: Unnecessary computational overhead

Conclusion

The categories implementation is objectively superior and should guide the refactoring:

  1. Simpler code (50% fewer lines)
  2. Better performance (O(depth) vs O(n))
  3. More maintainable (functional vs stateful)
  4. Standard patterns (Ecto associations vs virtual fields)
  5. Preventive design (UI filtering vs changeset validation)

The storage locations system should be refactored to match the categories approach, eliminating virtual fields and complex batch computations in favor of simple recursive functions.