Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🔄 Refactor: Modularize Badge Module into Provider-Based Architecture
🎯 Objective
Refactored the BadgeModule to follow NestJS best practices by separating all business logic into dedicated provider classes, enforcing Single Responsibility Principle and improving testability, maintainability, and scalability.
🧱 Summary of Changes
Analyzed BadgeService and extracted the following responsibilities:
seedDefaultBadges
determineBadgeForRank
autoAssignBadges
getBadgeByRank
remove, update, create
findOne, findAllActive, findAll
Created provider classes in src/badge/providers/, each responsible for a single concern:
SeedDefaultBadgesService
DetermineBadgeForRankService
AutoAssignBadgesService
GetBadgeByRankService
RemoveBadgeService
UpdateBadgeService
CreateBadgeService
FindOneBadgeService
FindAllActiveBadgesService
FindAllBadgesService
Each class encapsulates its logic and repository interactions, enabling focused testing and isolation.
Stripped all logic from BadgeService
Transformed it into a delegator that invokes methods on the appropriate provider
Injected all new providers through the constructor
Registered all provider classes in badge.module.ts
Ensured smooth dependency injection setup
Preserved existing exports for compatibility
Updated badge.service.spec.ts to mock and test provider-based interactions
Resolved TypeScript typing issues in DTOs and mocks
Ensured all unit tests continue to pass with full coverage
Confirmed BadgeController requires no changes
BadgeService remains its single point of contact
Controller continues to delegate correctly, without internal business logic
✅ Key Benefits
✅ Separation of Concerns — Each logic path is isolated in its own class
✅ Improved Testability — Fine-grained unit tests possible for each provider
✅ Easier Maintenance — Modifying badge logic is now low-risk and isolated
✅ Clean Architecture — Strong adherence to modular, service-driven design
✅ Backward Compatible — No breaking changes to controller or service APIs
⚙️ Technical Highlights
Dependency Injection: All providers registered and injected via @module setup
Error Handling: Used standard ConflictException, NotFoundException patterns
Logging: Retained logging in key providers (e.g., creation, deletion)
Validation: Moved and maintained all business rules (e.g., uniqueness checks) inside relevant services
Persistence: Each provider interacts with its own repository method
🧪 Status
✅ All functionality validated
✅ Unit tests updated and passing
✅ No regressions
✅ Readable, scalable, and production-ready