In this lesson, you will learn how to decouple your WebSocket infrastructure from your core business logic by transforming raw socket messages into meaningful domain events.
Why Decouple?
If you put business logic directly inside your socket.on('message', ...) handlers, your system becomes fragile. If you ever switch from WebSockets to a different transport (like WebTransport or SSE), you would have to rewrite your entire backend. Instead, treat your WebSocket layer as a transport adapter that simply translates incoming data into a standard internal event format.
The Mapping Pattern
Think of your WebSocket gateway as a translator. When a message arrives, the gateway identifies the intent, validates the payload, and then publishes an internal domain event (often via an EventEmitter or a message broker like Redis Pub/Sub). This allows your "Order Service" or "User Service" to listen for business actions without knowing anything about WebSockets.
Here is how you might map a raw socket message to a domain event:
// WebSocket Gateway
socket.on('place_order', (data) => {
// 1. Sanitize and validate
const orderDetails = validateOrder(data);
// 2. Map to a Domain Event
// We emit an event that the internal system understands
eventBus.emit('ORDER_REQUESTED', {
userId: socket.user.id,
order: orderDetails,
timestamp: Date.now()
});
});
// Domain Logic (in a completely separate file)
eventBus.on('ORDER_REQUESTED', async (event) => {
await orderService.process(event.order);
console.log(`Processing order for user ${event.userId}`);
});
The Benefits
By mapping events this way, you achieve two major goals:
- Testability: You can unit test your business logic by emitting
ORDER_REQUESTEDevents directly in your test suite without ever mocking a WebSocket connection. - System Agnostic Design: Your domain layer remains clean. Whether the request came from a WebSocket, an HTTP REST API, or a message queue, the domain layer handles it exactly the same way.
Key Takeaway: Never execute business logic directly in your socket handlers; instead, map incoming messages to domain events to keep your core logic transport-agnostic and modular.