Best practices

Patterns for reliable experiment code and safe operation.

Separate configuration from code

Device addresses, calibration files and channel maps belong in configuration/, not in experiment source. A run should be reproducible from the project directory and its data file.

One responsibility per class

Keep experiment logic, device communication and analysis separate. A driver should not know about a specific experiment; an experiment should not open sockets directly. This makes simulation and reuse possible.

Declare parameters, do not hard-code

Use NumberValue, BoolValue and StringCombo for anything an operator may change. The same declarations drive the GUI, the web dashboard and scan validation.

Make cleanup explicit

Acquire devices through the framework, use leases, and close clients in close(). Do not rely on process exit for hardware cleanup. Long-running services should stop timers and worker threads in closeEvent.

Keep timing deterministic

Do not perform file I/O, plotting or network calls inside a timed sequence. Prepare data before the run and hand results to analysis asynchronously.

Automate checks

Run scripts/check.sh before committing. Add regression tests for experiment semantics, not only for helper functions. Use simulation for routine CI and reserve real hardware for verification runs.

Operate safely

Before an unattended campaign, verify:

  • simulated run of the exact scan;
  • disk headroom and save acknowledgement behaviour;
  • device leases and health;
  • alerting and remote access;
  • a documented stop procedure.