Backend Development 11 min read

Designing a Monolithic Application for Future Microservice Migration: Best Practices and Code Structure

The article explains how to design a monolithic Java application with clear business boundaries, modular code organization, MVC layering, and disciplined controller logic so that it can be smoothly refactored into a micro‑service architecture, illustrating the approach with directory trees, package schemes, and sample CommonResult code.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Designing a Monolithic Application for Future Microservice Migration: Best Practices and Code Structure

With the rapid growth of mobile and B2C models, many companies have experienced explosive business growth, prompting a shift toward microservice architectures to handle high traffic, concurrency, and stability requirements.

However, a microservice architecture is rarely adopted from the start; most projects begin with a monolithic design to quickly deliver features and capture market share, then evolve iteratively.

The author shares personal experience transitioning from monolith to microservices, highlighting the contrast between well‑designed and poorly designed architectures. Good designs feature elegant code structure, clear layering, well‑defined business boundaries, and clear responsibilities for developers, while bad designs lead to tangled code, difficult maintenance, and constant patching.

Define Clear Business Boundaries

When planning for future microservices, the monolith should already separate domains such as user, product, order, payment, and permission. Domain‑Driven Design (DDD) can guide this separation, though it requires skilled practitioners.

Code Layer Structure

Following the MVC pattern, the recommended module layout is:

├─demo-common
│   └─src/main/java & resources
├─demo-dao
│   └─src/main/java & resources
├─demo-service
│   └─src/main/java & resources
└─demo-web
    └─src/main/java & resources

The four modules serve the following purposes:

demo-common: basic utilities, constants, configuration.

demo-dao: DAO layer, mapper interfaces and XML files.

demo-service: service interfaces and business logic.

demo-web: web layer, controllers, and external API exposure.

Dependencies flow from web → service → dao → common.

Package Organization

Two common schemes exist: (1) organize packages by business domain, each containing its own MVC layers; (2) organize first by MVC layers (service, serviceImpl, dto, etc.) and then place business models inside. The author prefers the domain‑first approach because it aligns well with later microservice extraction—each business package can be copied into its own service with minimal changes.

Example package names:

com.example.jajian.service.order

,

com.example.jajian.service.user

Full source tree example:

└─src
    ├─main
    │  ├─java
    │  │  └─com
    │  │      └─example
    │  │          └─jajian
    │  │              ├─common
    │  │              └─service
    │  │                  ├─order
    │  │                  │   ├─dto/OrderDto.java
    │  │                  │   └─service/OrderService.java
    │  │                  ├─pay
    │  │                  │   ├─dto/PayDto.java
    │  │                  │   └─service/PayService.java
    │  │                  └─user
    │  │                      ├─dto/UserDto.java
    │  │                      └─service/UserService.java

Avoid Cross‑Domain Multi‑Table Joins

While multi‑table joins are convenient in a monolith, they become problematic after services are split because tables may reside in different databases accessed via RPC, making such joins impossible.

Keep Business Logic Out of Controllers

Controllers should only handle request/response conversion and delegate validation and business processing to the service layer. Global exception handlers can manage error handling uniformly.

Data Transfer Objects

DO (Data Object): maps directly to database tables, used by the DAO layer.

DTO (Data Transfer Object): carries data between service and client layers.

VO (View Object): used by the presentation layer, often for UI rendering.

Separating these objects enables flexible handling of concerns such as data masking or ID encryption.

Unified Response Wrapper

A generic CommonResult<T> class is provided to standardize API responses, with success and failure codes, data payload, and message fields.

public class CommonResult
{
    public static final String CODE_SUCCESS = "0";
    public static final String CODE_FAILED = "9999";
    private String code;
    private T data;
    private String msg;
    private CommonResult(String code, T data, String msg) { ... }
    public boolean isSuccess() { return CODE_SUCCESS.equals(code); }
    public static
CommonResult
success() { return new CommonResult<>(CODE_SUCCESS, null, null); }
    public static
CommonResult
success(T data) { return new CommonResult<>(CODE_SUCCESS, data, null); }
    public static
CommonResult
success(T data, String msg) { return new CommonResult<>(CODE_SUCCESS, data, msg); }
    public static
CommonResult
failed() { return new CommonResult<>(CODE_FAILED, null, null); }
    public static
CommonResult
failed(String errorCode, String msg) { return new CommonResult<>(errorCode, null, msg); }
    // setters/getters omitted
}

Conclusion

The article lists practical considerations for designing a monolithic system that can later be split into microservices, emphasizing clear domain boundaries, modular package structures, minimal controller logic, and standardized data objects to reduce refactoring effort and avoid common pitfalls.

JavamicroservicesMVCDDDsoftware designmonolithic architecture
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.