One Service, Many Callers

Why a service's method should take plain values, not a request DTO, illustrated with a signup flow that gets called from two completely different forms.

September 1, 20261 min read30 / 43

TicketService's bookTicket method takes a user ID, a show ID, and a list of seat IDs, one plain value at a time. It doesn't take the request DTO itself.

The Same Signup Service, Called From Two Different Forms

Picture a signup service at a company running two separate sign-up flows. One is the plain signup form: a name, an email, a password, straight into a SignUpRequestDTO. The other lives on a masterclass registration page, collecting the same kind of information through its own separate MasterClassRegistrationRequestDTO, then checking behind the scenes whether that person already has an account, creating one only if they don't.

Both flows end up needing the exact same signup logic, just reached from two different forms, carrying two different DTOs. If the signup service's method took a SignUpRequestDTO directly, the masterclass flow would be stuck converting its own DTO into that other one, just to call a method that never actually needed to know about either specific form in the first place.

A Service Depends on Plain Values, Never a Specific DTO

A service takes the plain values it actually needs, a name, an email, a set of IDs, not a DTO belonging to any one particular caller. That's what lets the exact same bookTicket method stay reachable from a checkout flow today and a completely different entry point later, with neither one needing to know or care about the other's request shape.

A DTO is how one specific caller happens to package its request. A service's real job doesn't change based on who's asking, so its parameters shouldn't be tied to any one caller's packaging either.