A TDD-driven implementation focusing on functional principles, immutability, and tests as living documentation.
This repository contains my solution to the classic Mars Rover exercise. The primary goal was not just to solve the algorithmic puzzle, but to strictly apply Test Driven Development (TDD) discipline. I used "Baby Steps" and Triangulation to allow the architecture to emerge naturally, avoiding Big Design Up Front.
- Functional Approach over Stateful Classes
Instead of using a classic OOP approach (a Class that mutates its internal state), I opted for a Functional Programming style:
- Separation of Data & Behavior: The robot state (createRobot) is decoupled from the logic (operateRobot).
- Immutability: The operateRobot function is pure; it returns a new robot instance rather than mutating the existing one. This makes the system predictable and easier to debug.
- Ergonomic API Design (Named Arguments)
The main function uses the Options Object Pattern to simulate named arguments:
Why?
operateRobot({ robot, commands: "L" })
- Readability: It acts as Living Documentation at the call site. It is immediately clear what each parameter represents without looking at the function definition.
- Maintainability: It avoids the "Telescoping Argument" problem. We can easily add optional parameters in the future (e.g., obstacles) without forcing the caller to pass null or undefined for intermediate arguments.
The tests are structured to serve as Living Documentation. They tell a logical story about the system's capabilities:
- Sanity & Robustness:
- Base Case: Handling empty inputs.
- Filtering: Ensuring the system ignores invalid characters ("garbage") without crashing.
- Unit Logic:
- Verifying isolated rotations and movements from every cardinal direction.
- Integration: Proving the system can handle complex sequences of mixed valid/invalid commands.
JavaScript (ES6+) Vitest (Test Runner)
Install dependencies:
npm installRun tests:
npm testCheck Coverage:
npm run coverage- Key Takeaway: The process highlighted the adaptability of TDD. I initially felt the urge to jump into complex logic, but consciously paused to handle the Empty Command (Base Case) first. Later, I realized the need to handle Invalid Characters (Input Sanitization). The existing test suite acted as a safety net, allowing me to add this validation at the end without fear of breaking the core logic (Regressions).
- Future Improvements: Implementing spherical world boundaries and obstacle detection.