How should I organise my version 2 and version 3 code?

Workspace actions
Starting question

How should I organise my version 2 and version 3 code?

Then Pro / Supporting Point · AI

Architectural Strategies for Version Coexistence

No source links recorded for this answer.

The organization of major version increments (v2 and v3) requires a strategy that balances code maintainability with operational stability. Effective organization avoids the "branching tax"—the overhead of merging fixes across long-lived branches—by integrating both versions into a single deployment pipeline. ## Directory-Based Isolation Organizing v2 and v3 within a single repository using distinct namespaces or directories is the most robust approach for continuous integration. This method, often referred to as **Parallel Evolution**, allows both versions to share the same build environment while strictly isolating their public interfaces. 1. **Namespace Partitioning**: By placing code in `com.app.v2` and `com.app.v3`, developers can utilize IDE refactoring tools across both versions simultaneously. This prevents the "out of sight, out of mind" issue common in multi-branch setups. 2. **Shared Kernel**: Common utility functions, database schemas, and low-level data transfer objects (DTOs) should reside in a **Shared Core** module. This ensures that a security patch applied to the core logic automatically benefits both versions without manual porting. ## The Strangler Fig Pattern To manage the transition from v2 to v3, the **Strangler Fig Pattern** provides a framework for incremental replacement. Instead of a "big bang" release, the system is organized to allow v3 to grow around the edges of v2. - **Routing Layer**: An API Gateway or a reverse proxy handles incoming requests, directing legacy traffic to the v2 modules and new feature traffic to v3. - **Inter-Version Adapters**: When v3 requires data managed by v2 logic, an **Adapter Pattern** is employed. This creates a translation layer that allows v3 to call v2 services as if they were native, maintaining consistency during the migration period. ## Dependency Management and Decoupling Organizing v2 and v3 code effectively requires a strict policy on **Dependency Inversion**. To prevent v3 from becoming entangled with legacy v2 technical debt, the two versions should interact only through defined interfaces. - **Explicit Deprecation**: Within the v2 codebase, components that have been successfully migrated to v3 should be marked with compiler-level deprecation warnings. This creates a clear visual map of the remaining migration effort. - **Independent Testing Suites**: While the code lives in the same repository, the test suites must remain decoupled. v2 tests ensure backward compatibility, while v3 tests validate the new architectural requirements. This prevents a regression in v2 from blocking the development of v3 features. ## Operational Parity A dual-version organization enables **Shadow Deployment**. By having both versions active in the codebase, developers can route a copy of live v2 traffic to the v3 module in a "dry run" mode. This allows for real-world performance comparison and logic validation without affecting the end-user experience, a luxury not afforded by branch-based separation.

Select text to highlight passages.

Continue this thread

This path ends here for now.

Share your perspective, offer an example, or ask a follow-up to continue the discussion.

Other paths you could read

Earlier, at How should I organise my version 2 and version 3 code?, the conversation split. If this is not the thread you want, you can switch to one of the other paths below.

Highlights

0 saved passages and connected ideas

No highlights yet

Select text to save it here.