Skip to content

Refine overuse of mutable member variables #712

@youtalk

Description

@youtalk

Checklist

  • I've read the contribution guidelines.
  • I've searched other issues and no duplicate issues were found.
  • I've agreed with the maintainers that I can plan this task.

Description

Critical nodes in Autoware Core suffer from excessive mutable state, with some nodes containing 20-25+ member variables including publishers, subscribers, queues, and flags. This hidden mutable state creates spaghetti dependencies, makes testing fragile, and increases the risk of race conditions. This aligns with Anti-pattern 5 in the system performance documentation.

Purpose

The purpose of this task is to:

  1. Reduce mutable state complexity in critical nodes
  2. Implement pure function patterns for core algorithms
  3. Improve testability through explicit state management
  4. Eliminate race conditions and hidden dependencies

Possible approaches

Approach 1: Pure Function Pattern (Recommended)

// Before: Stateful class with side effects
class Tracker {
  std::vector<State> history_;  // Hidden mutable state
public:
  void update(const Meas& z) {
    history_.push_back(f(z, history_.back()));
  }
  Pose estimate() { return g(history_); }  // Non-pure
};

// After: Immutable inputs/outputs
struct TrackerState {
  std::vector<State> hist;
};

TrackerState update(const TrackerState& s, const Meas& z) {
  TrackerState out = s;
  out.hist.push_back(f(z, s.hist.empty() ? State{} : s.hist.back()));
  return out;
}

Pose estimate(const TrackerState& s) {
  return g(s.hist);  // Pure function
}

Approach 2: State Snapshot Pattern

class Node : public rclcpp::Node {
  struct StateSnapshot {
    Odometry current_odom;
    Trajectory current_traj;
    // All state in one structure
  };

  std::mutex state_mutex_;
  StateSnapshot state_;

  void updateState(StateSnapshot new_state) {
    std::lock_guard<std::mutex> lock(state_mutex_);
    state_ = std::move(new_state);
  }
};

Approach 3: Dependency Injection

// Extract dependencies instead of storing as members
ControlCommand computeControl(
  const VehicleInfo& info,
  const Odometry& odom,
  const Trajectory& traj,
  const ControlParams& params) {
  // Pure computation, no hidden state
  return control;
}

Definition of done

Immediate Refactoring

  • Identify top 5 nodes with highest mutable state count
  • Create state analysis report for EKFLocalizer
  • Create state analysis report for VelocitySmootherNode
  • Prototype pure function extraction for one module

Short-term Implementation

  • Refactor EKFLocalizer to use state snapshots
  • Extract pure functions from VelocitySmootherNode
  • Reduce NDTScanMatcher member variables by 50%
  • Add unit tests for extracted pure functions

Medium-term Optimization

  • Apply pure function pattern to all planning modules
  • Implement state snapshot pattern in perception nodes
  • Create shared state management utilities
  • Achieve 80% unit test coverage for pure functions

Long-term Architecture

  • Establish immutability guidelines
  • Implement static analysis checks for mutable state
  • Create functional programming patterns library
  • Document state management best practices

Metadata

Metadata

Assignees

Labels

status:staleInactive or outdated issues. (auto-assigned)

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions