Improve input domain model definition
Josuto opened this issue · comments
Is your feature request related to a problem? Please describe.
Several developers have expressed that they find the current domain model map definition cumbersome and confusing, which in turn degrades Developer Experience.
The constructor of every custom repository extending MongooseRepository
or MongooseTransactionalRepository
must pass an object map defining a persistable domain model as input parameter to its parent constructor. This map must specify a Default
domain model supertype definition and, optionally, one or more domain model subtype definitions.
The origin of the confusion is on the fact that the key of each subtype definition must match the name of a domain model subtype. Many developers are unaware of this requirement and provide an arbitrary name for such keys, causing the initialisation of their custom repository to fail.
Here is an example that illustrates the issue:
export class MongooseBookRepository
extends MongooseRepository<Book>
implements BookRepository
{
constructor() {
super({
Default: { type: Book, schema: BookSchema },
// Good subtype definition; the key matches the type name
PaperBook: { type: PaperBook, schema: PaperBookSchema },
// Bad subtype definition; the key does not match the type name
Audio: { type: AudioBook, schema: AudioBookSchema },
});
}
}
Moreover, reality shows that many custom repositories encompass a domain model that includes a single type. In the previous example, MongooseBookRepository
would only deal with instances of type Book
. In such cases, the key Default
is superfluous; super({ type: Book, schema: BookSchema })
would do.
Describe the solution you'd like
Simplify the structure of the domain model type map so that its semantics are clearer, and thus, easier. Also, it must work well for the implementation of custom repositories that encompass any single or multiple type domain model.
Describe alternatives you've considered
We have considered two approaches. The first one consists of keeping the Default
key to specify supertype definition and aggregating all subtype definitions in an optional JS array. The following piece of code, that is based on the previous example, illustrates the proposal:
export class MongooseBookRepository
extends MongooseRepository<Book>
implements BookRepository
{
constructor() {
super({
Default: { type: Book, schema: BookSchema },
subtypes: [
{ type: PaperBook, schema: PaperBookSchema },
{ type: AudioBook, schema: AudioBookSchema }
]
});
}
}
This approach is clearer than the original and it most likely cause the least impact on custom repositories that address a single type domain model. However, such custom repositories must still explicitly declare a Default
domain type definition.
An alternative to further simplify the domain model type map would consist of removing the Default
key entirely and define all domain subtypes via an optional subtypes
property. Consider the following example:
export class MongooseBookRepository
extends MongooseRepository<Book>
implements BookRepository
{
constructor() {
super({
type: Book,
schema: BookSchema,
subtypes: [
{ type: PaperBook, schema: PaperBookSchema },
{ type: AudioBook, schema: AudioBookSchema }
]
});
}
}
This is the cleanest possible way to define a domain model, independently from its nature (standalone or composed). Furthermore, this approach enables recursive (sub)type definition, although this is a feature to be explored in the future.
Additional context
The adoption of this feature by current monguito
users is to be explored. Thus, it is a great canary candidate.
A solution for this issue has been released in version 6.0.0.