457 lines
15 KiB
Markdown
457 lines
15 KiB
Markdown
|
|
# 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**
|