Inject abstract class in entities using Clean code #4386
-
Hi, I'm trying to setup a clean code architecture using Adonisjs6. I'm struggling when I try to inject a Slugify abastract class to my entity. For exemple, here is my abstract class : export default abstract class Slugify {
abstract makeSlug(text: string): string
} And here my actual entity : import Slugify from '#domain/contracts/helpers/slugify'
export class Post {
id?: string
displayName: string
slug?: string
private slugify!: Slugify
constructor(props: {
id?: string
displayName: string
slug?: string
}) {
this.id = props.id
this.displayName = props.displayName
this.slug = props.slug
}
setSlug() {
this.slug = this.slugify.makeSlug(this.displayName)
return this
}
setId() {
this.id = 'id'
return this
}
} The question is : How can I inject Slugify in the Entity directly ? I have a solution by injecting de Slugify in the use-case and pass it in the |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 3 replies
-
Okay, I have many follow up questions here.
|
Beta Was this translation helpful? Give feedback.
-
Hey @shankiflang! 👋🏻 I am not sure you architectured correctly your dependencies. Your Nevertheless, if you want to keep it that way, I would recommend changing how your entity works and not using the constructor to inject its props since it is needed for dependency injection. For example, you could have a static method interface PostProps {
id?: string
displayName: string
slug?: string
}
@inject()
export default class Post {
constructor(private slugify: Slugify) {}
static async create(props: PostProps) {
const post = await app.container.make(Post)
post.id = props.id
post.displayName = props.displayName
post.slug = props.slug
}
} @inject()
export class CreatePost implements CreatePostUseCase {
constructor(private postRepository: PostRepository) {}
async handle(payload: CreatePostDto) {
const post = await Post.create({ /* ... */ })
} If you want to keep injecting your stuff in your constructor + its props, you need to rely on @inject()
export class CreatePost implements CreatePostUseCase {
constructor(private postRepository: PostRepository) {}
async handle(payload: CreatePostDto) {
const post = await app.container.make(Post, [{ displayName: 'foo' }])
post.setSlug().setId()
}
} and your entity will looks like this: interface PostProps {
id?: string
displayName: string
slug?: string
}
export class Post {
constructor(private props: PostProps, private slugify: Slugify) {}
} Note, since your method |
Beta Was this translation helpful? Give feedback.
Yes, if your
Slugify
"service" is stable and does not make any external calls or side effects, there is no need to abstract it or inject it via dependency injection. Simply require it and use it as-is.