How COLA Architecture Transforms Complex Backend Systems
The COLA (Clean Object‑Oriented and Layered Architecture) framework replaces traditional monolithic MVC Service layers with a clear, multi‑layered structure—Adapter, Application, Domain, Infrastructure, and Client—enhancing code cohesion, reducing coupling, and improving maintainability, as illustrated through a detailed order‑creation example with refactored Java code.
Preface
As software systems evolve, traditional MVC architectures struggle with increasingly complex business logic. Service layers become bloated, making it hard for new developers to understand the flow, and they take on too many responsibilities such as external service calls and business rule validation. The COLA architecture was created to provide a practical code‑structure guideline that improves cohesion and reduces coupling.
COLA Architecture Overview
COLA (Clean Object‑Oriented and Layered Architecture) combines layered architecture, SOLID principles, Domain‑Driven Design (DDD), and Command‑Query Responsibility Segregation (CQRS) into an implementable application architecture.
Architecture Layer Description
Adapter Layer
Handles routing and adaptation for front‑end presentations (web, wireless, WAP). In a traditional B/S system, the adapter is equivalent to the MVC controller.
Application Layer
Responsible for receiving input, assembling context, parameter validation, and invoking the domain layer for business processing.
For query‑view operations, the application layer can bypass the domain layer and directly access the infrastructure layer.
Domain Layer
Core business logic resides here, gradually moved from the application layer’s executor.
Provides business entities and logic through Domain Services and Domain Entities.
Infrastructure Layer
Provides technical implementation details such as database CRUD, search engines, file systems, and RPC for distributed services.
Decouples the domain layer from external dependencies like databases and message queues.
Client Layer
Defines APIs exposed to external callers, which can be packaged as RPC SDK JARs.
Defines DTOs for input commands, queries, and output client objects.
Architecture Component Diagram
Architecture Sequence Diagram
COLA Project Structure Example
<code>├─ cola-demo-adapter
│ └─ adapter
│ ├─ consumer # Message consumer, entry point for async messages
│ ├─ scheduler # Scheduled task entry point
│ └─ web # Web controller handling HTTP/RESTful requests
├─ cola-demo-app
│ └─ app
│ └─ item
│ ├─ assembler # Converter between Client DTOs and Domain Entities
│ ├─ executor # Executes business logic
│ │ └─ query # Query executor for data retrieval
│ ├─ service # Application service exposing API to client layer
│ └─ validator # Input data validator
├─ cola-demo-client
│ └─ client
│ ├─ context # Context information
│ └─ item
│ ├─ api # Client API implemented by app service
│ └─ dto # Data Transfer Objects for client‑server communication
│ ├─ clientobject # Client object, similar to VO
│ └─ cmd # Command object encapsulating parameters
│ └─ query # Query command object
├─ cola-demo-domain
│ └─ domain
│ └─ item
│ ├─ domainservice # Domain service implementing business rules across entities
│ │ └─ impl # Concrete implementation
│ ├─ entity # Domain entity with attributes and behavior
│ └─ gateway # Domain gateway for interaction with external dependencies
├─ cola-demo-infrastructure
│ └─ infrastructure
│ ├─ config # Configuration classes (e.g., MyBatis Plus)
│ │ └─ properties # @ConfigurationProperties classes
│ ├─ item
│ ├─ convertor # Converter between DataObjects and Domain Entities
│ └─ gatewayimpl # Technical implementation of gateways
│ └─ database # Database access implementation
│ ├─ dataobject # Database data object mapping to tables
│ └─ mapper # Mapper for DB operations
│ └─ resources
│ └─ mapper # XML files for DB operations
</code>COLA Architecture Experience
Using a simple order‑creation example, the traditional MVC Service implementation looks like this:
<code>public class OrderServiceImpl implements IOrderService {
public void createOrder(OrderDTO orderDTO) {
Long payAmount = orderDTO.getPayAmount();
// 1. do biz check...
Assert.notNull(payAmount, "Actual payment amount cannot be null");
// 2. convert
OrderDO orderDO = new OrderDO();
orderDO.setOrderNo("xxxx");
List<OrderItemDO> orderItemDOList = assembleOrderItem(orderDTO);
// 3. order storage
orderMapper.insert(orderDO);
orderItemService.insertBatch(orderItemDOList);
}
}
</code>All conversion, validation, and persistence logic resides in the ServiceImpl, making the class bulky and responsibilities unclear.
Refactoring with COLA separates concerns:
Service Implementation
<code>@Service
public class OrderServiceImpl implements OrderServiceI {
@Override
public Response createOrder(OrderCreateCmd orderCreateCmd) {
return orderCreateCmdExe.execute(orderCreateCmd);
}
}
</code>Validation moves to a dedicated validator:
<code>public class OrderValidator {
public void validateOrderCreateCmd(OrderCreateCmd cmd) {
// do biz check...
Assert.notNull(cmd.getPayAmount(), "Actual payment amount cannot be null");
// other checks
}
}
</code>Conversion between command and entity is handled by an assembler:
<code>public class OrderAssembler {
public OrderEntity toEntity(OrderCreateCmd orderCreateCmd) {
OrderEntity orderEntity = new OrderEntity();
// props copy
return orderEntity;
}
public List<OrderItemEntity> toOrderItemEntityList(List<OrderItemCreateCmd> list) {
List<OrderItemEntity> itemEntityList = new ArrayList<>(list.size());
// props copy
return itemEntityList;
}
protected OrderItemEntity toOrderItemEntity(OrderItemCreateCmd orderItemCreateCmd) {
OrderItemEntity orderItemEntity = new OrderItemEntity();
// props copy
return orderItemEntity;
}
}
</code>The domain entity holds core order logic:
<code>public class OrderEntity {
private String orderNo;
// other properties
public void generateOrderNo() {
this.orderNo = UUID.randomUUID().toString().replace("-", "");
}
// other domain methods
...
}
</code>Cross‑entity business logic resides in a domain service:
<code>public class OrderCreateDomainServiceImpl implements OrderCreateDomainService {
@Override
public void process(OrderEntity orderEntity) {
// validate order item list
validateOrderItemList(orderEntity.getOrderItemList());
// generate order number
orderEntity.generateOrderNo();
}
private void validateOrderItemList(List<OrderItemEntity> orderItemEntityList) {
// do biz check...
}
}
</code>Persistence is delegated to gateways that interact with the database:
<code>public class OrderGatewayImpl implements OrderGateway {
@Override
public void insert(OrderEntity entity) {
OrderDO orderDO = convertor.toDO(entity);
orderMapper.insert(orderDO);
}
}
public class OrderItemGatewayImpl implements OrderItemGateway {
@Override
public void insertBatch(List<OrderItemEntity> orderItemEntityList) {
List<OrderItemDO> orderItemDOList = convertor.toDOList(orderItemEntityList);
orderItemMapper.insertBatch(orderItemDOList);
}
}
</code>The executor orchestrates the workflow:
<code>public class OrderCreateCmdExe {
public Response execute(OrderCreateCmd orderCreateCmd) {
// 1. validate
validator.validateOrderCreateCmd(orderCreateCmd);
// 2. convert
OrderEntity orderEntity = assembler.toEntity(orderCreateCmd);
// 3. save order
orderCreateDomainService.process(orderEntity);
orderGateway.insert(orderEntity);
// 4. save order items
List<OrderItemEntity> orderItemEntityList = assembler.toOrderItemEntityList(orderCreateCmd.getOrderItemList());
orderItemGateway.insertBatch(orderItemEntityList);
return Response.buildSuccess();
}
}
</code>Conclusion
The COLA architecture’s clear layered and package structure helps reduce the complexity of large software systems, improves code maintainability and readability, and promotes a business‑centric approach that decouples external dependencies, separating business complexity from technical complexity to achieve higher cohesion and lower coupling.
References
https://github.com/alibaba/COLA
https://blog.csdn.net/significantfrank/article/details/110934799
https://blog.csdn.net/significantfrank/article/details/109529311
https://blog.csdn.net/significantfrank/article/details/106976804
https://blog.csdn.net/significantfrank/article/details/100074716
https://blog.csdn.net/significantfrank/article/details/79614915
Dangbei Technology Team
Dangbei Technology Team public account
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.