Optivem Journal

Optivem Journal

Clean Architecture

Clean Architecture: Do NOT Inject Loggers Everywhere

Code Example

Valentina Jemuović's avatar
Valentina Jemuović
May 07, 2026
∙ Paid

🔒 Hello, this is Valentina with a premium issue of the Optivem Journal. I help Engineering Leaders & Senior Software Developers apply TDD in Legacy Code.


Logging injected directly into use cases, services and handlers is justified as:

  • “we need debugging”

  • “we need traceability”

  • “we need observability”

But…

❌Logger in every use case

  • every use case now knows about logging

  • business logic is mixed with runtime reporting

  • logs become part of how code is “explained”

class CreateOrderUseCase {

    private final Logger logger;

    public CreateOrderUseCase(Logger logger) {
        this.logger = logger;
    }

    public OrderResult execute(CreateOrderCommand cmd) {

        logger.info("CreateOrder started");

        Order order = new Order(cmd.userId());

        logger.info("Order created", Map.of(
            "orderId", order.getId()
        ));

        return new OrderResult(order.getId());
    }
}

⚠️Structured logging doesn’t fix the real issue

After a while, debugging becomes painful, so you switch to structured logging:

logger.info("OrderCreated", Map.of(
    "userId", cmd.userId(),
    "orderId", order.getId()
));

This is better:

  • easier to search

  • consistent format

  • better for tools

But the real problem doesn’t change.

You still have logging calls inside every use case.

You’ve just improved how logs look.


🚀 Register now: ATDD – Acceptance Testing Workshop
Get 100 EUR off with code DISCOUNT_100


✅Infrastructure Layer: Logging outside the use case

This post is for paid subscribers

Already a paid subscriber? Sign in
© 2026 Valentina Jemuović, Optivem · Privacy ∙ Terms ∙ Collection notice
Start your SubstackGet the app
Substack is the home for great culture