I'm trying to create a clean API project structure relaying on the DDD principles.
So far I have :
Program.cs
for the DI configuration.EntityFramework
and all the database related stuff.Domain
, the Dal
and external layers such as Grpc
/Api
endpoints.protobuf.net-grpc
, this project implements the grpc services which interact with the Application
layer..proto
files according to the structure and naming of the Gprc
layer.Giving a concret example, let's say I have 2 business entities named User
and Role
. These entities are defined in the Domain
project. I have also a Domain service called UserService
.
Let's forget about the Dal
as this layer is irrelevant for the example.
In my Grpc
layer, which will be identically reproduced as .proto
files in my Contracts
project, I want to use the exact same naming as the Domain
(or as close as I can) because my clients will consume my API using these entities, and I don't want them to have entity names inside their code such as GrpcUser
, or UserContract
or else.
I want them to have simple class names, without any informations that reflects the fact that these are Contracts classes.
So in my Grpc
project, I would have something like : User
, Role
, UserRequest
, UserResponse
, RoleRequest
, RoleResponse
, UserService
, RoleService
.
Some of them have the same name than my Domain
entities.
But because my Grpc
layer will never directly interact with my Domain
layer, I'll never have a name conflict within these projects.
And now let's talk about the Application
layer, where I'm struggling with the naming convention I want to use.
Basically, a service from my Application
layer will sometimes have a name close to the Domain
name. So if I want a logic built around my User
entity, I will need a UserService
also in my Application
layer. But I'll have a name conflict with both the Domain
version of the UserService
, and the Grpc
version of the UserService
.
I will have to inject the Domain.UserService
in my Application.UserService
, and my Application.UserService
will later be injected in my Grpc.UserService
to open my Domain
to the external Grpc
layer.
Furthermore, my Application
services should have input and outputs. They usually return a Dto
version of the Domain
entity, so I don't have any problem to create a UserDto
, or more precise classes such as CreateUserDto
.
But for the input, usually I would need Requests
too. Exactly like my Grpc
project.
To solve my naming issue, I was starting to add Application
to all my classes in this project. For example, I would have an UserApplicationService
, which will receive a CreateUserApplicationRequest
and returns a UserDto
.
But these names are very long and not convenient to use, and I've never seen anyone using this kind of naming convention (but maybe I'm wrong about this point.)
So my questions are : are my naming choices wrong ? If not, how could I name my entities and services inside my Application
layer ?
Naming in a DDD-based project with multiple layers can definitely be challenging. Here's a breakdown of how you might approach naming for each layer:
Naming Conventions:
Services:
Prefix with Application if necessary, but for clarity and conciseness, consider a simpler approach. Use a name that reflects its role in the Application layer. For example, UserManager or UserHandler instead of UserApplicationService. DTOs and Requests:
Keep DTOs named based on their purpose rather than the layer they belong to. For example: CreateUserDto UpdateUserDto UserDto Requests:
Use names that clearly describe their role in the Application layer, such as CreateUserRequest, UpdateUserRequest. Example:
Services: UserManager (Application layer service) DTOs: UserDto, CreateUserDto, UpdateUserDto Requests: CreateUserRequest, UpdateUserRequest 3. Grpc Layer Service Names: Use straightforward names as you mentioned: UserService, RoleService Message Types: Use names that mirror the Domain where possible, e.g., User, Role Requests and Responses can be named according to their purpose, e.g., UserRequest, UserResponse General Tips: Avoid Prefixes/Suffixes: Try to avoid excessive prefixes or suffixes that might clutter names. Instead, rely on context and project structure to clarify roles.
Consistency: Ensure naming conventions are consistent across your project to avoid confusion. Document your naming conventions so that all team members follow them.
Descriptive Names: Focus on clarity and descriptiveness over brevity. Clear names help in understanding the role and purpose of each component, even if they are a bit longer.
By using these conventions, you should be able to clearly differentiate between entities, services, and DTOs while maintaining a clean and understandable codebase.