software_engineering/developer_experience_metrics.rs
1//! # Developer Experience Metrics
2//!
3//! Two practical measures from Part 3 of the book: **focus time**, the
4//! count and duration of uninterrupted two-hour-plus blocks per week
5//! (chapter 3.6's efficiency-and-flow dimension), and **survey response
6//! rate**, itself a trust signal for a `DevEx` survey programme, not merely a
7//! data-collection statistic (chapter 3.7).
8//!
9//! ## Formula
10//!
11//! ```text
12//! Focus block = a calendar block >= 2.0 hours, uninterrupted
13//! Response rate = (survey responses received / survey invitations sent) x 100%
14//! ```
15//!
16//! ## Why it matters
17//!
18//! Refocusing after an interruption to deep, complex work routinely takes
19//! many minutes, sometimes closer to half an hour, to fully rebuild the
20//! working memory an engineer was holding before the interruption. An
21//! engineer whose day is fragmented into short blocks may show plenty of
22//! activity while accomplishing far less genuinely difficult work than the
23//! same engineer would with two protected, uninterrupted hours. Separately,
24//! a declining survey response rate often indicates eroding trust in the
25//! process — survey fatigue, doubts that results lead to action, or
26//! suspicion that anonymity is not genuinely protected — and deserves direct
27//! investigation rather than being dismissed as a data-collection
28//! inconvenience.
29//!
30//! ## Example
31//!
32//! ```rust
33//! use software_engineering::developer_experience_metrics::{
34//! is_focus_block, response_rate_percent,
35//! };
36//!
37//! // "Uninterrupted blocks of two hours or more" count as focus time.
38//! assert!(is_focus_block(2.0));
39//! assert!(is_focus_block(2.5));
40//! assert!(!is_focus_block(1.75));
41//!
42//! // A DevEx survey sent to 100 engineers, 72 responses: 72% response rate.
43//! assert_eq!(response_rate_percent(72.0, 100.0), Some(72.0));
44//! ```
45//!
46//! ## Pitfalls
47//!
48//! - **Using interruption or notification data as individual surveillance**
49//! repeats the misuse risk the book warns against for activity data;
50//! aggregate at the team level.
51//! - **Imposing a single, rigid focus-time schedule on everyone** ignores
52//! genuine individual variation in how people work best.
53//! - **Ignoring a declining response rate** misses an important trust
54//! signal in its own right — investigate rather than dismiss it.
55//!
56//! ## Sources
57//!
58//! - Chapter 3.6, Efficiency and flow: deep work and interruptions.
59//! - Chapter 3.7, Developer experience surveys and `DevEx` metrics.
60//!
61//! Topic doc: software-engineering-metrics/locales/en-001/chapters/03-06-efficiency-and-flow.md
62//! Topic doc: software-engineering-metrics/locales/en-001/chapters/03-07-developer-experience-surveys-and-devex-metrics.md
63
64/// Whether a calendar block qualifies as protected "focus time".
65///
66/// The book defines focus time as "uninterrupted blocks of two hours or
67/// more" measured from calendar data.
68///
69/// # Arguments
70///
71/// * `duration_hours` — length of the uninterrupted calendar block, in
72/// hours.
73///
74/// # Returns
75///
76/// `true` iff `duration_hours >= 2.0`.
77///
78/// # Examples
79///
80/// ```rust
81/// use software_engineering::developer_experience_metrics::is_focus_block;
82///
83/// assert!(is_focus_block(2.0));
84/// assert!(!is_focus_block(1.99));
85/// ```
86#[must_use]
87pub fn is_focus_block(duration_hours: f64) -> bool {
88 duration_hours >= 2.0
89}
90
91/// Survey response rate as a percentage: responses received / invitations
92/// sent x 100.
93///
94/// Treat this as a diagnostic signal in its own right (chapter 3.7): a
95/// declining rate often indicates eroding trust in the survey process.
96///
97/// # Arguments
98///
99/// * `responses_received` — count of survey responses received.
100/// * `invitations_sent` — count of survey invitations sent.
101///
102/// # Returns
103///
104/// `Some(percentage)`, or `None` when `invitations_sent` is zero (rate
105/// undefined).
106///
107/// # Examples
108///
109/// ```rust
110/// use software_engineering::developer_experience_metrics::response_rate_percent;
111///
112/// assert_eq!(response_rate_percent(72.0, 100.0), Some(72.0));
113/// assert_eq!(response_rate_percent(1.0, 0.0), None);
114/// ```
115#[must_use]
116pub fn response_rate_percent(responses_received: f64, invitations_sent: f64) -> Option<f64> {
117 if invitations_sent == 0.0 {
118 None
119 } else {
120 Some(responses_received / invitations_sent * 100.0)
121 }
122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127
128 // "Calculate the number and duration of uninterrupted blocks of two
129 // hours or more available in an engineer's typical week."
130 #[test]
131 fn two_hour_block_is_a_focus_block() {
132 assert!(is_focus_block(2.0));
133 assert!(is_focus_block(2.5));
134 }
135
136 // A block shorter than two hours does not count as focus time.
137 #[test]
138 fn sub_two_hour_block_is_not_a_focus_block() {
139 assert!(!is_focus_block(1.75));
140 assert!(!is_focus_block(0.0));
141 }
142
143 // "Response rate rose to over 70% within two cycles" — a percentage
144 // computed the same way as this function.
145 #[test]
146 fn response_rate_computes_percentage() {
147 assert!((response_rate_percent(72.0, 100.0).unwrap() - 72.0).abs() < 1e-9);
148 assert!(response_rate_percent(1.0, 0.0).is_none());
149 }
150
151 // "A software company's initial DevEx survey included [an] under 30%"
152 // response rate — verifying the formula against that figure.
153 #[test]
154 fn response_rate_matches_under_30_percent_example() {
155 let rate = response_rate_percent(29.0, 100.0).unwrap();
156 assert!(rate < 30.0);
157 }
158}