on
Shift Left
Shifting Left is not a new or novel concept in software development but it's been one of the most consistent improvements I've tried to make across software teams. Unlike methodologies like TDD or DDD shift left occupies a higher conceptual space that lends itself to less implementation resistance.
If you imagine software development as a timeline like
developers machine --> ci system --> deployed environment
Then at it's core Shift Left is about moving as much that could go wrong in the right hand stages to the left hand stages to catch them earlier.
Reality
Shift Left traditionally has referred to testing but I like to generalize it to "assertions" about a codebase. As such, "shift left" to me means including things like:
- Code formatting checks
- Static analysis
- Black box service-level tests
- "Sandbox" style interactive development
While the ways you go about getting these things done differs by language, build tool, etc the end result is the same: A wholistic development environment that lets you iterate quickly and with confidence. It dovetails nicely with trunk-based development where by the time things make it to the main branch you have a high degree of certainty that they won't fail in a variety of ways.
Strategies
The toolbox I lean on to implement this is pretty consistent
- Containerized dependencies for local black box service testing
- The ecosystems build tooling to tie together multiple tasks (and cache them!)
- Open source static analysis tools (language specific)
As an example, I'm working in .NET right now and leveraging:
- TestContainers for black box service testing
- The DotNet SDK and MSBuild for dependency/target management
- Built in .NET static analysis/formatting rules (strongest strictness)
dotnet format --verify-no-changes
But when I'm working in Java I used:
- TestContainers for black box service testing
- Gradle for dependency/target management
- Spotbugs and PMD for static analysis locally
- Spotless for formatting
I actively avoid tools like SonarQube that primarily do work that could be done locally on a centralized server. The rules that exist on those centralized services can be shared as build-logic and still run locally. Systems like that appear nice for a managers checklist of "code quality" but do little to actually improve things (because of how late they exist in the development cycle).
Other Benefits
Beyond the obvious benefits of surfacing these checks during development Shifting Left makes pull requests cleaner. Gone are a whole class of problems or feedback that might clutter up a PR with things that could be automated. It also lends itself nicely to keeping the CI and local process as close as possible. Ideally when implemented the CICD system is just calling the same tasks that the developer did during their builds!
For new developers to a codebase Shifting Left helps front-load any issues or machine dependencies they may need. Instead of getting to a post-merge stage and realizing "oh I never ran this expensive test that only runs in a deployed environment" they can follow a simple workflow and understand the true scope of what all is needed for a change to be made successfully.
Lastly in the new age of AI coding tools we find ourselves in, providing more ways to verify and assert on code quality locally means LLM agents and tools can more easily verify the correctness of their own changes rather than introducing another external system for them to monitor.