When it comes to Microservices, services' development life cycles should be independent too.*
Different SLDC and different dev teams
in a real MS system, there could be several teams involved in the development of the ecosystem, each of which in charge of one or more services. In turn, these teams might be located in different offices, cities, countries, plan... Perhaps, they don't even know each other, what makes sharing knowledge or code very hard (if possible). But this could be very convenient because shared code also implies a sort of sharing reasoning and something important to recall is that, whatever makes sense for a specific team, doesn't have to make it for another team. For example, given the DTO Customer, it could be different depending on the service in play, because customers are interpreted (or seen) differently from each service.
Different needs, different technologies
Isolated SLDCs also allows teams to choose the stack that best suits their needs. Imposing DTOs implemented in a specific technology limits the capacity of the teams to choose.
DTOs are neither business rules nor services contracts
What DTOs are really? Plain objects with no other goal than moving data from one side to another. Bags of getters and setters. It's not the kind of "knowledge" that worth reuse, overall because there's no knowledge at all. Their volatility also makes them bad candidates for coupling.
Contrary to what Dherik has stated, it must be possible for a service to change its DTOs without having to make other services to change at the same time. Services should be tolerant readers, tolerant writers and fail tolerant. Otherwise, they cause coupling in such a way that makes the service architecture a no sense. Once more, and contrary to Dherik's answer, if three services need exactly the very same DTOs, it's likely something went wrong during the services decomposition.
Different business, different interpretations
While there could be (and there will be) cross-cutting concepts among services, it does not mean we have to impose a canonical model to force all services to interpret them in the same way.
Say our company has three departments, Customer Service, Sales and Shipping. Say each of these releases one or more services.
Customer Service, due to its domain language, implements services around the concept of customers, where customers are persons. For instance, customers are modeled as name, last name, age, gender, email, phone, etc.
Now say, Sales and Shipping model their services according to their respective domain languages as well. In these languages, the concept customer appears too but with a subtle difference. To them, customers are not (necessarily) persons. For Sales, customers are a Document number a Credit Card and a billing address, for Shipping a full name and a shipping address too.
If we force Sales and Shipping to adopt the canonical data model of Customer Service, we are forcing them to deal with unnecessary data that could end up introducing unnecessary complexity if they have to maintain the whole representation and keep the customer data in sync with customer service.
* Here is where the strengths of this architecture lays on
protofile for gRPC or the
avroschema for Kafka and generate the DTOs in both services, but I wouldn't share a shared library between two projects.