Files
DP44/docs/ImprovementOpportunities.md
2026-04-17 14:55:32 -04:00

15 KiB

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:
    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:
    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:

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

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

  1. #2: Create IDbAPI Interface - Replace static DbAPI usage in 5 key modules
  2. #11: Optimize Real-time DB Calls - Cache remaining settings, measure test initialization time

Month 2-3: Architecture Modernization

  1. #5: Fix Async Context - Replace BackgroundWorker with async/await in App.xaml.cs
  2. #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