I raised this question after working on the code, and I’m unsure why it was deemed not a good practice. Could you please help me understand the concerns?
Here is a long answer.
Organizing related business entity classes that represent the same business concept and share common attributes is good practice because it reduces duplication, improves consistency, and makes the model easier to evolve over time.
Encapsulation of domain rules
When similar entities share a common base (abstract class, interface, or composition), shared invariants and validation rules live in one place instead of being copy‑pasted across classes.
This makes it easier to reason about the business domain, because the behavior for that concept is localized and changes to rules propagate uniformly.
Maintainability and evolution
A cohesive set of related entities is simpler to maintain than many ad‑hoc classes with overlapping fields and logic.
When the business concept changes (for example, adding a new common attribute or changing an identifier strategy), you change it once in the shared abstraction instead of touching many scattered classes.
Reuse and reduced duplication
Organizing entities around business concepts encourages reuse across use cases, services, and even applications within the same domain.
Common aspects like identifiers, auditing fields, or value object types (e.g., Email, Money) can be implemented once and reused by all entities that represent that data type, reducing boilerplate and risk of subtle inconsistencies.
Clearer domain language and structure
Grouping entities by domain meaning (rather than by technical concern) leads to packages and types that match the ubiquitous language used by the business and other developers.
This improves discoverability—when reading the codebase, it is obvious where to find and place logic related to a given business concept, which in turn makes onboarding and code reviews easier.
Better type safety and testability
Shared abstractions for a business data type make method contracts more precise and avoid treating everything as a generic “bag of fields.”
Tests can target the common behavior in one place and then focus on the differences in specialized entities, resulting in leaner test suites and less chance of inconsistent behavior between similar entity types.