dilemma.dev _
01
02
03
04
05
06

ship_it()

The deadline is now. The tests pass — mostly. The edge cases you found at 2 AM are documented in TODOs that no one will ever read. The stakeholders need a demo. The investors need a number. The function works for the happy path and you've convinced yourself that's enough.

fn decide(pressure: f64) -> Action {
    if pressure > 0.9 {
        Action::Ship // it's good enough
    }
}

// rewrite_it()

// the architecture is wrong
// you knew it three sprints ago
// the tech debt compounds daily
// every patch makes the next one harder
// but rewriting means missing the window
// and windows don't reopen

// TODO: this entire module
// TODO: actually, the whole crate
match reality {
    Reality::Ideal => rewrite(),
    _ => panic!("not enough time"),
}
01
02
03
04
05
06
good enough never enough
╔══════════════════════════╦══════════════════════════╗
║       PATH_A             ║       PATH_B             ║
╠══════════════════════════╬══════════════════════════╣
07
08
09
10
11
12

abstract()

Build the framework. Generalize the solution. Make it handle every future case you can imagine and three you can't. Write the config parser, the plugin system, the middleware stack. Future-you will thank present-you. Probably.

trait Solvable<T, E, C>
where
    T: Problem,
    E: Environment,
    C: Context + Clone,
{
    fn solve(&self) -> Result<T, E>;
}

// hardcode()

// just make it work
// for this one case
// with this one input
// on this one machine
// the abstraction is a lie
// YAGNI is a survival strategy

fn solve() -> String {
    "42".to_string()
    // works on my machine
    // ¯\_(ツ)_/¯
}
07
08
09
10
11
12
elegant complexity brutal simplicity
╔══════════════════════════╦══════════════════════════╗
║       PATH_A             ║       PATH_B             ║
╠══════════════════════════╬══════════════════════════╣
13
14
15
16
17
18

stay()

The codebase is familiar. The team knows your name. The deploy pipeline doesn't surprise you anymore. You've memorized the quirks of the ORM, the undocumented API behaviors, the way the CI server fails on Tuesdays. Mastery is a form of comfort.

loop {
    let day = Day::next();
    day.commit();
    day.push();
    day.review();
    // repeat until mass extinction
}

// leave()

// the greenfield beckons
// new stack, new language, new terror
// you'll be the junior again
// asking obvious questions in standups
// but at least the code won't haunt you
// at least not the same code

fn leap(fear: f64) -> Future {
    if fear < f64::INFINITY {
        Future::Unknown
    } else {
        unreachable!()
    }
}
13
14
15
16
17
18
known suffering unknown possibility
╔══════════════════════════╦══════════════════════════╗
║       PATH_A             ║       PATH_B             ║
╠══════════════════════════╬══════════════════════════╣
19
20
21
22
23
24

test()

Write the tests first. Cover every branch. Mock the dependencies. Assert the invariants. The suite runs for 47 minutes but you know, with mathematical certainty, that the code behaves as specified. The specification, however, is wrong.

#[test]
fn test_everything() {
    assert_eq!(
        universe.meaning(),
        Expected::Defined
    ); // FAILED
}

// deploy()

// testing is for people who fear
// the production environment
// real engineers test in prod
// the users are your QA team
// move fast, break things
// but mostly break things

fn deploy(confidence: bool) {
    match confidence {
        true => yolo_push(),
        false => yolo_push(),
    }
}
19
20
21
22
23
24
false certainty honest chaos
decide() true false ship wait retry panic! ok err err ok ???

every branch terminates.

// every branch diverges.

> enter_