Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: detect circular dependency for services #22

Merged
merged 5 commits into from
Jan 24, 2024

Conversation

thiagomini
Copy link
Contributor

Fixes #18

@thiagomini thiagomini added the enhancement New feature or request label Jan 22, 2024
@thiagomini thiagomini self-assigned this Jan 22, 2024
@tolgap
Copy link
Contributor

tolgap commented Jan 22, 2024

@thiagomini great PR! Just wanted to request 1 thing on the tests. Could we, just as a sanity check, also add a test case where there is no circular dependency, yet we still use forwardRef? 😄

@thiagomini
Copy link
Contributor Author

thiagomini commented Jan 22, 2024

Hey, @tolgap , do you mean to check if there's a circular dependency between the files? We can do that, but there's an existing eslint-rule for that: import-js/eslint-plugin-import#941

I've also read somewhere that checking for circular dependency consumes quite a lot of memory, so I'm not 100% convinced we should do that - do you want to add more thoughts to this discussion?

{
code: `
@Module({
imports: [CatsModule], // ⚠️ Circular-dependency detected
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reminder to remove the comment

@tolgap
Copy link
Contributor

tolgap commented Jan 22, 2024

Hey, @tolgap , do you mean to check if there's a circular dependency between the files? We can do that, but there's an existing eslint-rule for that: import-js/eslint-plugin-import#941

@thiagomini I meant that we should not only test the postive case, but also the negative case!

@thiagomini thiagomini marked this pull request as ready for review January 23, 2024 13:41
Copy link
Collaborator

@rickdgeerling rickdgeerling left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💪 Awesome

Copy link
Contributor

@tolgap tolgap left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔥

@thiagomini thiagomini merged commit d95cd9e into main Jan 24, 2024
2 checks passed

[Forward references](https://docs.nestjs.com/fundamentals/circular-dependency#forward-reference) are commonly used to handle circular dependencies between services or modules. For example, if `FooService` and `BarService` depend on each other, you can use `forwardRef()` to resolve the circular dependency. However, `forwardRef()` must be a last resort, and we generally recommend changing your code to avoid circular dependencies. This rule detects usage of the `forwardRef()` method so you can keep track of what potentially needs refactoring.

One strategy to avoid circular dependencies between services is to make each responsible for a single use case. That way you decrease the interface and likelihood of circular dependencies. You can also avoid using services as facades for data repositories. Instead, services should be usually used to encapsulate business logic (commands). Leave query responsibilities to repositories.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be hesitant to advise detailed alternative strategies. It could easily be interpreted as the official way to structure a Nest app, whereas it's highly dependent on the context. i.e. if it's a simple REST app, entity-based module structure is appropriate, and simply splitting splitting the service would probably suffice.

If the app's primary responsibility is transforming and loading data, transaction scripts are a great fit.

Highly complex apps with lots of business logic would again require a different approach, and DDD would probably be a better fit, but that would depend on the skills within the team too 😄

I'd suggest we drop the second paragraph and just stick to the generic "we recommend refactoring the code to avoid the circular dependency" from the first paragraph 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think you are right; I thought of providing some direction to users who would ask themselves, "Then what should we do?", but maybe a blog post is a better way of doing it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Feat: warn about usage of forwardRef
3 participants