You should write the smallest classes that fit your requirements. That way, you are less likely to repeat yourself, there are fewer tests, and there are fewer things that can go wrong when you need to change your code.
If your client code really needs to follow the domain logic , you must either:
1) deserialize directly into domain model classes (especially if you use an ORM that supports ignorance of ignorance).
// Customer is a business object / aggregate root with domain logic ICustomer customer = customerRepository.Get<Customer>(customerId);
2) Use data transfer objects to initialize domain model classes:
I would rather not write DTO if I don't need it, so I prefer the first approach. But sometimes DTOs are necessary, for example, when you consume auto-generated classes created by service proxies, or if you are a service that exposes your own DTOs.
If a client should not follow business logic , it should never know about your domain model classes. In these cases, the client must use data transfer objects or user-defined view model classes.
source share