Files
DP44/docs/ImprovementOpportunities.md

457 lines
15 KiB
Markdown
Raw Permalink Normal View History

2026-04-17 14:55:32 -04:00
# DataPRO Improvement Opportunities
**Status:** Analysis Complete
**Date:** 2026-04-17
**Analysis Scope:** Architecture, Stability, Performance
---
## Methodology
Items ranked by **Effort vs. Impact** matrix. priority is triage order (1 = most urgent).
- **Low Effort:** < 1 week
- **Medium Effort:** 1-3 weeks
- **High Effort:** 3+ weeks
- **High Impact:** Major architectural improvement, significantly improves stability/performance/testability
- **Medium Impact:** Noticeable improvement but not critical
- **Low Impact:** Minor cleanup, nice to have
---
## Immediate Priority (Triage 1-5)
### #1. Refactor RunTestVariables to Injectables (Low Effort, High Impact)
**Category:** State Management
**Problem:**
- `RunTestVariables.cs` is an `abstract class` with 40+ static properties
- Located in two locations (`Common/DTS.Common/Enums/` and `Common/DTS.CommonCore/Enums/`)
- Creates hidden dependencies throughout codebase
- Difficult to test, impossible to mock
- Lines 287-294 show redundancy: `TOMExcitationWarmupTimeMS = TOM_EXCITATIONWARMUPTIME_MS;` (static field initialized from const)
**Solution:**
- Create `IRunTestVariables` interface
- Implement concrete `RunTestVariablesService` class
- Register with Unity DI container as singleton
- Inject into consumers instead of static access
- Consolidate to single definition (remove `Common/DTS.CommonCore/Enums/RunTestVariables.cs`)
**Effort:** Low (3-5 days)
**Impact:** High
**Risks:**
- Breaking change across 40+ usages (grep shows widespread use in App.xaml.cs, services, ViewModels)
- **Mitigation:** Step-by-step refactoring with compiler-guided updates
**Related Files:**
- `/Users/noise/Code/BRANCH_MAINT_4_04/Common/DTS.Common/Enums/RunTestVariables.cs:1-315`
- `/Users/noise/Code/BRANCH_MAINT_4_04/Common/DTS.CommonCore/Enums/RunTestVariables.cs`
---
### #2. Create IDbAPI Interface (Low Effort, High Impact)
**Category:** Database Layer
**Problem:**
- `DbAPI.cs:237-373` exposes 15+ static properties (Connections, Database, DAS, Sensors, etc.)
- No interface abstraction (`IDbAPI` doesn't exist)
- Lines 229-240 show `_instance` singleton pattern with static wrappers
- Tight coupling: ALL modules depend on static DbAPI, making testing nearly impossible
- Violates Dependency Inversion Principle
**Solution:**
- Create `IDbAPI` interface with all current static property getters
- Implement `DbApiService` class that wraps singleton instance
- Register with Unity: `container.RegisterType<IDbAPI, DbApiService>(new ContainerControlledLifetimeManager())`
- Gradually refactor modules to inject `IDbAPI` instead of static `DbAPI.XXX`
**Effort:** Low (5-7 days)
**Impact:** High
**Risks:**
- Massive refactoring (15+ properties used across 40+ modules)
- **Mitigation:** Keep static wrappers during transition, deprecate gradually
**Related Files:**
- `/Users/noise/Code/BRANCH_MAINT_4_04/DataPRO/DbAPI/DbAPI.cs:229-373`
---
### #3. Extract Test State Management from App.xaml.cs (Medium Effort, High Impact)
**Category:** Architecture / God Class Refactoring
**Problem:**
- `App.xaml.cs:128-235` contains `StartTest()` and `EndTest()` methods with 150+ lines each
- Mixed concerns: licensing (line 307), DB initialization (line 328), test state (lines 128-235), UI operations
- Lines 103, 119 show static `RunTestVariables` modifications alongside UI thread marshaling
- God class (4620 lines total, only first 500 read but structure evident)
**Solution:**
- Extract `ITestStateService` with methods:
- `StartTest(TestConfiguration config)`
- `EndTest()`
- `SetRunTestRealtimeVariables()`
- Extract `ILicensingService` (lines 300-340)
- Extract `IDatabaseInitializer` (lines 328-400)
- Register services with Unity, inject into App.xaml.cs
**Effort:** Medium (2-3 weeks)
**Impact:** High
**Risks:**
- Disrupts architectural foundation
- **Mitigation:** Incremental extraction, keep backward compatibility
**Related Files:**
- `/Users/noise/Code/BRANCH_MAINT_4_04/DataPRO/DataPRO/App.xaml.cs:1-4620`
---
### #4. Add Unit Test Scaffolding (Low Effort, High Impact)
**Category:** Testing
**Problem:**
- Only database tests exist in `DataPRO/UnitTest/`
- No ViewModel tests (MVVM pattern but untested)
- No service layer tests
- Lines 22-30 of Architecture.md note "Limited test coverage"
**Solution:**
- Create test project structure:
- `DataPRO.Tests.ViewModels/`
- `DataPRO.Tests.Services/`
- `DataPRO.Tests.Modules/`
- Add NUnit/Xunit + Moq setup
- Write 5-10 high-value tests for critical paths:
- `RunTestVariablesService` initialization
- `TestStateService.StartTest()` flow
- Database connection pooling
**Effort:** Low (1 week)
**Impact:** High
**Risks:**
- Low risk, high reward
**Mitigation:** Start small, expand coverage iteratively
---
### #5. Fix Async Context in App.xaml.cs (Medium Effort, High Impact)
**Category:** Threading / Stability
**Problem:**
- Lines 128-161 `StartTest()` calls `DbOperations.LogDBCaching()`, `SetRunTestRealtimeVariables()` on UI thread
- Line 459: `TabPageSource.GetGroups("AllGroups")` blocks UI thread for 3-4 seconds
- Line 399-406: Database initialization on UI thread during startup
- No async/await pattern anywhere (Architecture.md line 380 notes "BackgroundWorker instead of async/await")
- Lines 238-242, 254-262, 266-274 show Dispatcher marshaling boilerplate
**Solution:**
- Convert sync DB calls to async:
```csharp
public async Task StartTestAsync()
{
await LoadTestConfigurationAsync();
await InitializeDatabaseAsync();
uiContext.Send(_ => RaiseTestStarted(), null);
}
```
- Replace `BackgroundWorker` with async/await throughout codebase
- Use `IHostBuilder` for background services
**Effort:** Medium (2-3 weeks)
**Impact:** High
**Risks:**
- Breaking changes to synchronous call chains
- **Mitigation:** Async-avoid pattern, add overloads during transition
---
## Medium Priority (Triage 6-12)
### #6. Improve DASFactory BlockingCollection Threading (Medium Effort, Medium Impact)
**Category:** Threading / DASFactory
**Problem:**
- Line 127 of `DASFactory.cs`: `private BlockingCollection<Tuple<QueueActions, DeviceHandling>> _queueActionPerDevice;`
- No visible async consumer pattern (read up to line 139, full file 1712 lines)
- Mixed threading model: UI thread produces, worker threads consume
- Lines 156-160 show `StartMulticastAutoDiscovery()` without cancellation support
**Solution:**
- Implement proper async consumer pattern:
```csharp
private readonly Channel<(QueueActions, DeviceHandling)> _deviceChannel = Channel.CreateBounded<(QueueActions, DeviceHandling)>(new BoundedChannelOptions(100) { FullMode = BoundedChannelFullMode.Wait });
```
- Add cancellation tokens to long-running Discovery operations
- Use `IHostedService` for background device monitoring
**Effort:** Medium (1-2 weeks)
**Impact:** Medium
**Risks:**
- Device discovery timing changes
- **Mitigation:** Thorough integration testing with actual hardware
---
### #7. Database Connection Pooling Optimization (Low Effort, Medium Impact)
**Category:** Database / Performance
**Problem:**
- Lines 108-138 in `DbAPI.cs` create new `SqlCommand` for every call
- Lines 137, 194: `cmd.Connection.Dispose()` on every operation
- No connection pooling configuration visible
- Stored procedure version negotiation (lines 34-97) executes during runtime path
**Solution:**
- Configure SQL Connection Pooling in connection string
- Reuse `SqlCommand` objects where possible
- Cache SP version results longer (currently cached per invocation)
- Add connection health checks
**Effort:** Low (1 week)
**Impact:** Medium
**Risks:**
- Low risk
**Mitigation:** Benchmark before/after
---
### #8. Module Dependency Audit (Medium Effort, Medium Impact)
**Category:** Architecture
**Problem:**
- 40+ Prism modules (Architecture.md line 37 notes "30+")
- Lines 68-75 of Architecture.md show module registration chaos
- Mixed initialization: `Initialize()` vs `RegisterTypes()`
- Tight coupling between modules (e.g., SensorsList → HardwareList → GroupList)
**Solution:**
- Audit module dependencies with dependency graph tool
- Create module dependency rules (e.g., "Viewers depend on Services but not vice versa")
- Introduce module-level interfaces (`ISensorsModule`, `IHardwareModule`)
- Document module contract boundaries
**Effort:** Medium (2 weeks)
**Impact:** Medium
**Risks:**
- Refactoring module initialization patterns
- **Mitigation:** Document before/after patterns
---
### #9. Replace Static Abstract RunTestVariables with Instance Pattern (Low Effort, Medium Impact)
**Category:** State Management
**Problem:**
- `RunTestVariables.cs:9`: `public abstract class RunTestVariables` with static properties
- Line 287-294: Redundant pattern `public static int Property = CONSTANT;`
- Inheritance hierarchy unnecessary for data holder
- Makes DI impossible
**Solution:**
- Convert to `sealed class RunTestVariables : IRunTestVariables`
- Use constructor injection for configuration
- Add `Reset()` method for test isolation
**Effort:** Low (3-5 days)
**Impact:** Medium
**Risks:**
- Breaking change (100+ usages inferred)
- **Mitigation:** Same as #1, step-by-step
---
### #10. Consolidate Logging Infrastructure (Medium Effort, Medium Impact)
**Category:** Architecture
**Problem:**
- Architecture.md line 380: "Mixed logging - custom APILogger and TextLogger classes"
- Two logger types: `APILogger` (custom) and `TextLogger` (file-based)
- Lines 78-82 of App.xaml.cs: `_loggers.Add(new TextLogger(...))` mixed with `APILogger.Writer = LogStuff` (line 324)
- No structured logging, no log levels per module
**Solution:**
- Adopt Serilog or Microsoft.Extensions.Logging
- Configure per-module log levels
- Structured logging for searchability
- Migration plan: wrapper adapters → direct usage
**Effort:** Medium (2-3 weeks)
**Impact:** Medium
**Risks:**
- Log message formatting changes
- **Mitigation:** Backward compatible adapter layer
---
### #11. Optimize RunTest Real-time Database Calls (Low Effort, Medium Impact)
**Category:** Performance
**Problem:**
- Comment at lines 163-165 of App.xaml.cs: "http://manuscript.dts.local/f/cases/33110/Eliminate-DB-communication-while-in-realtime"
- Prepopulation already done (lines 166-218) but still query `Defaults.GetUserSettingValue*()` (lines 169-206)
- Lines 452-459 of App.xaml.cs: `SettingsDB.GetAllGlobalValues()` blocks startup
**Solution:**
- Cache all settings in `RunTestVariables` at test start
- Add runtime settings change listener (if needed)
- Lazy-load non-critical settings
**Effort:** Low (5-7 days)
**Impact:** Medium
**Risks:**
- Settings changes during test not reflected (acceptable tradeoff)
- **Mitigation:** Document setting freeze at test start
---
### #12. Add Configuration Validation (Medium Effort, Medium Impact)
**Category:** Stability
**Problem:**
- No validation of DB connection strings
- No validation of hardware configuration before test start
- Lines 391-411 of App.xaml.cs: Command line args parsed but minimal validation
- Line 349-358: License validation only checks DB type for license type, not actual DB connectivity
**Solution:**
- Add `IConfigurationValidator` interface
- Validate:
- Database connectivity before bootstrapper
- Hardware configuration completeness before test start
- User permissions
- Fail fast with helpful error messages
**Effort:** Medium (1-2 weeks)
**Impact:** Medium
**Risks:**
- User workflow changes (earlier failures)
- **Mitigation:** Clear error messages, rollback options
---
## Low Priority (Triage 13+)
### #13. Upgrade .NET Framework to .NET 6/8 (High Effort, High Impact)
**Category:** Architecture / Modernization
**Problem:**
- Architecture.md line 316: ".NET Framework 4.8"
- Legacy platform, no long-term support
- Missing modern features (native DI, async-streaming, improved threading)
**Effort:** High (3-4 months)
**Impact:** High
**Risks:**
- Major breaking changes
- Dependency compatibility
- **Mitigation:** Phased migration, test automation
---
### #14. Add Error Handling Patterns (Medium Effort, Medium Impact)
**Category:** Stability
**Problem:**
- Lines 129-133, 186-190 of `DbAPI.cs`: Generic `catch (Exception ex)` with `return ErrorCodes.ERROR_UNKNOWN`
- No structured error handling across modules
- Stack traces lost in translation to error codes
**Solution:**
- Define error hierarchy: `ApplicationException`, `DatabaseException`, `HardwareException`
- Use `Result<T>` pattern instead of out params + error codes
- Central error handling with DI
**Effort:** Medium (2 weeks)
**Impact:** Medium
**Risks:**
- Breaking change to API contracts
- **Mitigation:** Gradual adoption
---
### #15. Build Performance Optimization (Low Effort, Low Impact)
**Category:** Build / CI
**Problem:**
- 100+ projects in solution (solution file 440+ lines)
- No indication of parallel builds
- Rebuilds entire solution on any change
**Solution:**
- Project dependency graph optimization
- Precompiled headers for common libraries
- Incremental builds
**Effort:** Low (3-5 days)
**Impact:** Low
**Risks:**
- Low risk
**Mitigation:** Measure build times before/after
---
## Summary Matrix
| Triage | # | Effort | Impact | Category |
|--------|---|--------|--------|----------|
| **1** | #1 | Low | High | State Management |
| **2** | #2 | Low | High | Database Layer |
| **3** | #3 | Medium | High | Architecture |
| **4** | #4 | Low | High | Testing |
| **5** | #5 | Medium | High | Threading |
| 6 | #6 | Medium | Medium | Threading |
| 7 | #7 | Low | Medium | Database |
| 8 | #8 | Medium | Medium | Architecture |
| 9 | #9 | Low | Medium | State Management |
| 10 | #10 | Medium | Medium | Architecture |
| 11 | #11 | Low | Medium | Performance |
| 12 | #12 | Medium | Medium | Stability |
| 13 | #13 | High | High | Modernization |
| 14 | #14 | Medium | Medium | Stability |
| 15 | #15 | Low | Low | Build |
---
## Recommended Immediate Action Plan
### Week 1-2: Quick Wins
1. **#4: Add Unit Test Scaffolding** - Establish test infrastructure, write 5-10 tests
2. **#1: Refactor RunTestVariables** - Create interface, inject into 1-2 modules as proof-of-concept
### Week 3-6: High Impact Refactoring
3. **#2: Create IDbAPI Interface** - Replace static DbAPI usage in 5 key modules
4. **#11: Optimize Real-time DB Calls** - Cache remaining settings, measure test initialization time
### Month 2-3: Architecture Modernization
5. **#5: Fix Async Context** - Replace BackgroundWorker with async/await in App.xaml.cs
6. **#3: Extract Test State** - Create `ITestStateService`, refactor StartTest/EndTest
---
## Notes
- **Static DbAPI** is the root cause of most testability issues (#1, #2, #3 should be grouped)
- **RunTestVariables** duplication (two files) suggests merging or clear separation needed
- No CI/CD pipeline visible in codebase - recommend adding GitHub Actions/Azure DevOps
- Architecture.md shows "God Class" concerns already identified in prior analysis (GLM5)
---
**Document generated by Qwen3-Coder-Next analysis agent**