v1.14.3 - DetectionProcessor Single Responsibility Principle Refactoring (2025-12-11)¶
What Changed?¶
This release applies the Single Responsibility Principle (SRP) to the DetectionProcessor class by splitting the monolithic process() method into focused helper methods. Each method now has a single, clear responsibility: detection input, sensor reading, timestamp tracking, response building, LED feedback, and cleanup. The refactoring improves code readability and maintainability while maintaining identical behavior and zero performance impact.
What's New¶
Main Feature: SRP-Compliant DetectionProcessor Architecture¶
What it does:
Refactors DetectionProcessor::process() from a 100+ line monolithic method into a well-organized hierarchy of single-responsibility helper methods:
- PHASE 1:
read_detection()- GPIO detection input - PHASE 2:
read_sensors()- Sensor orchestration add_timestamp_data()- Timing field population (ENABLE_TIMESTAMP)add_adcmv_data()- ADC millivolt conversion (ENABLE_ADCMV)add_bme280_data()- Environmental sensor reading (ENABLE_BME280)add_gnss_data()- GNSS position reading (ENABLE_GNSS)- PHASE 3:
build_and_queue_event()- Response building and queueing - PHASE 4a:
led_feedback()- LED feedback control - PHASE 4b:
cleanup()- State reset
How to use it: No API changesβusage remains identical:
void loop() {
DetectionProcessor::process(); // Internally orchestrates all phases
EventQueue::flush();
}
Architecture diagram:
process() orchestration:
βββ read_detection()
β βββ return if !detected
βββ read_sensors()
β βββ add_timestamp_data()
β βββ add_adcmv_data()
β βββ add_bme280_data()
β βββ add_gnss_data()
βββ build_and_queue_event()
βββ led_feedback()
βββ cleanup()
βββ cosmic_detector_reset()
Benefits:
- Single Responsibility: Each method has one clear purpose
- Improved Readability:
process()is now a 7-line high-level orchestrator - Easier Testing: Each phase can be tested independently
- Cleaner Separation: Conditional compilation flags remain unaffected
- Better Maintainability: Changes to one phase don't risk breaking others
Installation¶
Quick Start¶
# Get the release
git checkout v1.14.3
# Build all variants
task build # Development build
task prod:build # Production build
task next:build # Next-generation (ENABLE_DEVICE_RESPONSE=1)
# Upload
task upload
# Check it works
task monitor
What's Different from the Last Version?¶
β Added¶
- Private helper methods (9 new private static methods):
read_detection(detection_result_t*)- GPIO detection readingread_sensors(event_t*, const detection_result_t&)- Sensor orchestrationadd_timestamp_data(event_t*)- Timestamp field populationadd_adcmv_data(event_t*)- ADC millivolt conversionadd_bme280_data(event_t*)- Environmental sensor readingadd_gnss_data(event_t*)- GNSS position readingbuild_and_queue_event(const event_t&)- Response queueingled_feedback(const detection_result_t&)- LED feedbackcleanup()- State reset
π§ Changed¶
- detection_processor.cpp refactored (196 β 204 lines with added JSDoc)
- Monolithic
process()(100+ lines) β high-level orchestrator (7 lines) - Sensor reading logic extracted to dedicated methods
- Conditional field handling isolated in add_*() methods
-
Response building encapsulated in
build_and_queue_event() -
detection_processor.h expanded (204 β 299 lines)
- Added complete JSDoc for all 9 private helper methods
- Documentation explains each method's purpose and phase
-
Full section for private helpers with clear organization
-
Include dependency added:
- Added
#include "event_queue.h"to detection_processor.h for event_t type
π Fixed¶
- No bug fixes in this release (pure refactoring)
Architecture Improvements¶
Before (v1.14.2)¶
void DetectionProcessor::process(void) {
cosmic_detection_t detection = cosmic_detector_read();
if (detection.detected) {
// ====== 100+ lines of mixed concerns ======
// - Sensor reading (BME280, ADC, RTC, GNSS)
// - Event building (hit_type, timestamps, etc.)
// - Response creation
// - Queueing logic
// All interspersed with conditional compilation
}
cosmic_detector_reset();
}
After (v1.14.3)¶
void DetectionProcessor::process(void) {
detection_result_t detection = {};
// PHASE 1: Read detection
if (!read_detection(&detection)) {
cosmic_detector_reset();
return;
}
// PHASE 2: Read sensors and build event
event_t event = {};
read_sensors(&event, detection);
// PHASE 3: Build response and queue
build_and_queue_event(event);
// PHASE 4: LED feedback and cleanup
led_feedback(detection);
cleanup();
cosmic_detector_reset();
}
Method Responsibility Map¶
| Method | Lines | Responsibility | Complexity |
|---|---|---|---|
read_detection() |
8 | GPIO detection input | Minimal |
read_sensors() |
17 | Sensor reading orchestration | Medium |
add_timestamp_data() |
8 | Timing field population | Minimal |
add_adcmv_data() |
6 | ADC conversion | Minimal |
add_bme280_data() |
8 | Environmental reading | Minimal |
add_gnss_data() |
12 | GNSS position reading | Minimal |
build_and_queue_event() |
12 | Response queueing | Minimal |
led_feedback() |
3 | LED feedback | Trivial |
cleanup() |
1 | ADC pin reset | Trivial |
| Total | 75 | 9 single-purpose methods | Much lower |
Comparison: Old monolithic process() had ~100 lines with multiple interspersed concerns; new design has same logic split into 9 focused methods with clear separation.
Is It Safe to Upgrade?¶
Backward Compatible: β Yes (100% compatible)
- Zero behavior changes - All detection and sensor logic identical
- No API changes - Public interface unchanged (
init()andprocess()signatures identical) - Same performance - No performance impact (private helper calls compile to inline code)
- Same memory usage - RAM: 31.2% (102,352 / 327,680 bytes), Flash: 27.4% (359,381 / 1,310,720 bytes)
- All build variants supported:
- β
task build(development) - β
task prod:build(production) - β
task debug:build(debug symbols) - β
task next:build(next-generation, ENABLE_DEVICE_RESPONSE=1)
Existing users can upgrade without any code changes.
Tests Passed¶
- β Builds without errors (all 4 build variants)
- esp32dev-dev (development)
- esp32dev-release (production)
- esp32dev-debug (debug)
- esp32dev-next (next-generation)
- β RAM usage: 31.2% (102,352 / 327,680 bytes) - identical to v1.14.2
- β Flash usage: 27.4% (359,381 / 1,310,720 bytes) - identical to v1.14.2
- β Pre-commit hooks: All checks passed
- β Detection functionality: All features (ENABLE_TIMESTAMP, BME280, RTC, GNSS) working
- β Event queueing: EventQueue integration verified
- β Stream control: Command::getInstance().get_stream() respected
Release Details¶
- Date: 2025-12-11
- Version: v1.14.3
- Commits: 1 (SRP refactoring)
2e2e268- refactor(detection): apply single responsibility principle to DetectionProcessor methods- Files Changed: 2
- MODIFIED:
include/detection_processor.h(+95 lines, JSDoc for private helpers) - MODIFIED:
src/detection_processor.cpp(+8 lines, split into helper methods)
Design Principles Applied¶
Single Responsibility Principle (SRP)¶
Each method has one reason to change:
read_detection()- Only if GPIO polling changesadd_timestamp_data()- Only if timestamp logic changesadd_bme280_data()- Only if BME280 reading changesbuild_and_queue_event()- Only if queueing strategy changes- etc.
Before: One reason to change the entire process() method (100+ lines)
After: Nine focused methods, each with one reason to change
High-Level Orchestration¶
The process() method now reads like a high-level specification:
// This is what detection processing does:
1. Read detection
2. If detected, read sensors
3. Build and queue response
4. Provide feedback
5. Clean up
No implementation details in the orchestratorβonly the workflow.
Conditional Compilation Isolation¶
Optional features (ENABLE_TIMESTAMP, ENABLE_BME280, etc.) are now clearly isolated in their own methods:
// Before: #if directives scattered throughout process()
// After: Each add_*() method contains its own conditional compilation
This makes it easier to understand which code is optional and which is always present.
Code Organization¶
Header Structure (v1.14.3)¶
include/detection_processor.h:
βββ DETECTION DATA STRUCTURES
β βββ detection_result_t
βββ PUBLIC API
β βββ init()
β βββ process()
βββ PRIVATE HELPER METHODS
βββ read_detection()
βββ read_sensors()
βββ add_timestamp_data()
βββ add_adcmv_data()
βββ add_bme280_data()
βββ add_gnss_data()
βββ build_and_queue_event()
βββ led_feedback()
βββ cleanup()
Implementation Structure (v1.14.3)¶
src/detection_processor.cpp:
βββ PRIVATE STATE
β βββ g_last_event_time_us (conditional)
βββ PUBLIC API IMPLEMENTATION
β βββ init()
β βββ process()
βββ PRIVATE HELPER IMPLEMENTATIONS
βββ read_detection()
βββ read_sensors()
βββ add_timestamp_data()
βββ add_adcmv_data()
βββ add_bme280_data()
βββ add_gnss_data()
βββ build_and_queue_event()
βββ led_feedback()
βββ cleanup()
Next Steps¶
- v1.15.0 (planned): CommandParser class for unified command argument parsing and validation
- Future: Consider similar SRP refactoring for EventQueue and CommandQueue classes
- Ongoing: Monitor for opportunities to apply SRP to other monolithic methods
Related Documentation¶
- EventQueue Architecture - Event buffering system
- CommandQueue Architecture - Command handling system
- v1.14.2 Release Notes - DetectionProcessor header independence
- v1.14.1 Release Notes - DetectionProcessor class introduction