Skip to main content

software_engineering/
communication_metrics.rs

1//! # Communication and Collaboration Metrics
2//!
3//! **Communication and collaboration**, the C in SPACE (chapter 3.1),
4//! measures how information actually flows between people and teams: how
5//! discoverable documentation is, how evenly knowledge spreads, how well
6//! cross-team dependencies get coordinated, and how new team members
7//! onboard into shared understanding. This dimension is often the least
8//! instrumented of the five, precisely because it is harder to observe
9//! than delivery data — and that gap matters, because breakdowns here
10//! frequently show up, misattributed, in every other dimension: a rising
11//! change failure rate that looks like a testing problem is sometimes
12//! actually a communication problem, a team that did not know about a
13//! dependency's change until it broke in production.
14//!
15//! ## Formula
16//!
17//! ```text
18//! Cross-team dependency resolution time = resolved at − raised at
19//!     (a request, API change, or coordinated release, team-to-team)
20//!
21//! Time to first contribution = first contribution at − joined at
22//!     (onboarding proxy for how well shared understanding flows)
23//! ```
24//!
25//! ## Why it matters
26//!
27//! A team that consistently waits weeks for a dependency another team owns
28//! has a collaboration problem that will not show up cleanly in either
29//! team's own internal delivery metrics — it needs a direct,
30//! inter-team-specific signal, the same cycle-time discipline chapter 2.6
31//! applies within a team, applied here across a team boundary instead. The
32//! time from a new team member joining to their first meaningful,
33//! independent contribution is a complementary, practical proxy for the
34//! same underlying property: a team where knowledge lives entirely in
35//! people's heads onboards slowly and unpredictably, while a team with
36//! genuinely good documentation, clear ownership, and accessible
37//! mentorship onboards faster and more consistently.
38//!
39//! ## Example
40//!
41//! ```rust
42//! use software_engineering::communication_metrics::{
43//!     cross_team_dependency_resolution_time_days, time_to_first_contribution_days,
44//! };
45//!
46//! // A shared-library change request raised on day 10, resolved on day 24:
47//! // two weeks of inter-team coordination friction.
48//! let resolution_time = cross_team_dependency_resolution_time_days(10.0, 24.0);
49//! assert_eq!(resolution_time, 14.0);
50//!
51//! // A new engineer joins on day 0 and lands their first independent
52//! // change on day 18.
53//! let onboarding_time = time_to_first_contribution_days(0.0, 18.0);
54//! assert_eq!(onboarding_time, 18.0);
55//! ```
56//!
57//! ## Pitfalls
58//!
59//! - **Measuring only intra-team cycle time** — a slow cross-team
60//!   dependency will not show up in either owning team's own internal
61//!   delivery metrics; it needs its own direct signal.
62//! - **Treating documentation existence as sufficient** — track
63//!   discoverability (is it actually found and used), not just whether
64//!   content technically exists somewhere (chapter 4.6).
65//! - **Ignoring onboarding time as "just an HR concern"** — a long or
66//!   highly variable time to first contribution is a genuine collaboration
67//!   signal about how well shared understanding flows.
68//! - **Assuming the org chart describes real communication** — periodic,
69//!   lightweight analysis of who actually collaborates with whom (code
70//!   review networks, meeting overlap) often reveals a bottleneck or an
71//!   isolated pocket the formal structure hides.
72//!
73//! ## Sources
74//!
75//! - Chapter 3.5, Communication and collaboration metrics.
76//! - Forsgren, Storey, Maddila, Zimmermann, Houck, and Butler, "The SPACE of
77//!   Developer Productivity," *ACM Queue* (2021).
78//!
79//! Topic doc: software-engineering-metrics/locales/en-001/chapters/03-05-communication-and-collaboration-metrics.md
80
81/// Time from a cross-team dependency being raised to being resolved: a
82/// shared-library update, an API change request, a coordinated release,
83/// team-to-team rather than within a single team.
84///
85/// `resolved_at_days − raised_at_days`.
86///
87/// # Arguments
88///
89/// * `raised_at_days` — when the cross-team request was raised.
90/// * `resolved_at_days` — when the other team resolved it.
91///
92/// # Returns
93///
94/// The resolution time in days.
95///
96/// # Examples
97///
98/// ```rust
99/// use software_engineering::communication_metrics::cross_team_dependency_resolution_time_days;
100///
101/// assert_eq!(cross_team_dependency_resolution_time_days(10.0, 24.0), 14.0);
102/// ```
103#[must_use]
104pub fn cross_team_dependency_resolution_time_days(raised_at_days: f64, resolved_at_days: f64) -> f64 {
105    resolved_at_days - raised_at_days
106}
107
108/// Time from a new team member joining to their first meaningful,
109/// independent contribution — a practical proxy for how well shared
110/// understanding flows in an organization.
111///
112/// `first_contribution_at_days − joined_at_days`.
113///
114/// # Arguments
115///
116/// * `joined_at_days` — when the new team member joined.
117/// * `first_contribution_at_days` — when they made their first meaningful,
118///   independent contribution.
119///
120/// # Returns
121///
122/// The time to first contribution, in days.
123///
124/// # Examples
125///
126/// ```rust
127/// use software_engineering::communication_metrics::time_to_first_contribution_days;
128///
129/// assert_eq!(time_to_first_contribution_days(0.0, 18.0), 18.0);
130/// ```
131#[must_use]
132pub fn time_to_first_contribution_days(joined_at_days: f64, first_contribution_at_days: f64) -> f64 {
133    first_contribution_at_days - joined_at_days
134}
135
136#[cfg(test)]
137mod tests {
138    use super::*;
139
140    // "Track how long a cross-team request ... takes from being raised to
141    // being resolved ... applied specifically to inter-team, rather than
142    // intra-team, coordination."
143    #[test]
144    fn cross_team_resolution_time_is_resolved_minus_raised() {
145        let time = cross_team_dependency_resolution_time_days(10.0, 24.0);
146        assert!((time - 14.0).abs() < 1e-9);
147    }
148
149    #[test]
150    fn cross_team_resolution_time_can_be_same_day() {
151        let time = cross_team_dependency_resolution_time_days(5.0, 5.0);
152        assert!((time - 0.0).abs() < 1e-9);
153    }
154
155    // "The time from a new team member joining to their first meaningful,
156    // independent contribution is a strong, practical proxy for how well
157    // shared understanding actually flows."
158    #[test]
159    fn time_to_first_contribution_is_first_contribution_minus_joined() {
160        let time = time_to_first_contribution_days(0.0, 18.0);
161        assert!((time - 18.0).abs() < 1e-9);
162    }
163
164    #[test]
165    fn time_to_first_contribution_from_a_nonzero_start_date() {
166        let time = time_to_first_contribution_days(100.0, 112.0);
167        assert!((time - 12.0).abs() < 1e-9);
168    }
169}