154 lines
5.8 KiB
Markdown
154 lines
5.8 KiB
Markdown
# 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
|
|
```elixir
|
|
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
|
|
```elixir
|
|
# 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)
|
|
```elixir
|
|
# 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)
|
|
```elixir
|
|
# 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
|
|
|
|
### Recommended Approach: **Category-Style Hierarchical Module**
|
|
|
|
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. |