Refactored service layer from pure functions to struct-based services #19
Refactored service layer from pure functions to struct-based services #19MichaelBoegner wants to merge 33 commits intomainfrom
Conversation
…vice to more scalable naming of AIService
There was a problem hiding this comment.
Pull Request Overview
This PR refactors the service layer from pure functions to struct-based services, introducing dependency injection and improved encapsulation. The changes move from a functional programming approach to an object-oriented service pattern.
Key changes include:
- Converting standalone functions to methods on service structs (UserService, TokenService, InterviewService, etc.)
- Introducing service constructors that accept dependencies via dependency injection
- Updating all handlers and tests to use the new service-based architecture
Reviewed Changes
Copilot reviewed 31 out of 31 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| user/service.go | Converted user functions to UserService methods with dependency injection |
| user/service_test.go | Updated tests to use UserService struct instead of standalone functions |
| user/repository_mock.go | Changed mock field from private to public for external access |
| user/model.go | Added UserService struct and constructor |
| token/service.go | Converted token functions to TokenService methods |
| token/service_test.go | Updated tests to use TokenService struct |
| token/model.go | Added TokenService struct and constructor |
| interview/service.go | Converted interview functions to InterviewService methods |
| interview/service_test.go | Updated tests to use InterviewService struct |
| interview/model.go | Added InterviewService struct and constructor |
| conversation/service.go | Converted conversation functions to ConversationService methods |
| conversation/service_test.go | Updated tests to use ConversationService struct |
| conversation/model.go | Added ConversationService struct and constructor |
| mailer/service.go | Updated method receivers from Mailer to MailerService |
| mailer/model.go | Renamed Mailer struct to MailerService and updated constructor |
| chatgpt/service.go | Updated method receivers from OpenAIClient to AIService |
| chatgpt/model.go | Renamed OpenAIClient to AIService and updated constructor |
| billing/service.go | Converted billing functions to BillingService methods |
| billing/service_test.go | Updated tests to use BillingService struct |
| billing/model.go | Renamed Billing to BillingService and added dependency injection |
| dashboard/service.go | Converted dashboard functions to DashboardService methods |
| dashboard/model.go | Added DashboardService struct and constructor |
| handlers/model.go | Updated Handler struct to use service dependencies instead of repositories |
| handlers/handlers.go | Updated all handlers to use service methods instead of standalone functions |
| handlers/handlers_test.go | Updated tests to use new service-based architecture |
| internal/server/server.go | Updated server initialization to create and inject services |
| internal/testutil/server.go | Updated test server to use service-based architecture |
| internal/testutil/helpers.go | Updated helper functions to accept service parameters |
| internal/mocks/openai_mock.go | Renamed MockOpenAIClient to MockAIService |
| internal/mocks/mailer_mock.go | Renamed MockMailer to MockMailerService |
| learninglog/03_29_2025.md | Updated documentation to reflect new service naming |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
There was a problem hiding this comment.
Pull Request Overview
Copilot reviewed 31 out of 31 changed files in this pull request and generated 8 comments.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| } | ||
|
|
||
| user, err := h.UserRepo.GetUser(params.UserID) | ||
| user, err := h.UserService.UserRepo.GetUser(params.UserID) |
There was a problem hiding this comment.
Direct access to h.UserService.UserRepo breaks encapsulation. This should use h.UserService.GetUser(params.UserID) to maintain proper abstraction boundaries.
| user, err := h.UserService.UserRepo.GetUser(params.UserID) | |
| user, err := h.UserService.GetUser(params.UserID) |
| } | ||
|
|
||
| err = h.InterviewRepo.UpdateStatus(interviewID, userID, payload.Status) | ||
| err = h.InterviewService.InterviewRepo.UpdateStatus(interviewID, userID, payload.Status) |
There was a problem hiding this comment.
Direct access to h.InterviewService.InterviewRepo breaks encapsulation. Consider adding an UpdateStatus method to InterviewService to maintain proper abstraction boundaries.
| err = h.InterviewService.InterviewRepo.UpdateStatus(interviewID, userID, payload.Status) | |
| err = h.InterviewService.UpdateStatus(interviewID, userID, payload.Status) |
| exists, err := h.BillingService.BillingRepo.HasWebhookBeenProcessed(webhookID) | ||
| if err != nil { | ||
| h.Logger.Error("h.BillingRepo.HasWebhookBeenProcessed failed", "error", err) |
There was a problem hiding this comment.
Direct access to h.BillingService.BillingRepo breaks encapsulation. Consider adding a HasWebhookBeenProcessed method to BillingService to maintain proper abstraction boundaries.
| exists, err := h.BillingService.BillingRepo.HasWebhookBeenProcessed(webhookID) | |
| if err != nil { | |
| h.Logger.Error("h.BillingRepo.HasWebhookBeenProcessed failed", "error", err) | |
| exists, err := h.BillingService.HasWebhookBeenProcessed(webhookID) | |
| if err != nil { | |
| h.Logger.Error("h.BillingService.HasWebhookBeenProcessed failed", "error", err) |
| } | ||
|
|
||
| exists, err := h.UserRepo.HasActiveOrCancelledSubscription(SubCreatedAttrs.UserEmail) | ||
| exists, err := h.UserService.UserRepo.HasActiveOrCancelledSubscription(SubCreatedAttrs.UserEmail) |
There was a problem hiding this comment.
Direct access to h.UserService.UserRepo breaks encapsulation. Consider adding a HasActiveOrCancelledSubscription method to UserService to maintain proper abstraction boundaries.
| exists, err := h.UserService.UserRepo.HasActiveOrCancelledSubscription(SubCreatedAttrs.UserEmail) | |
| exists, err := h.UserService.HasActiveOrCancelledSubscription(SubCreatedAttrs.UserEmail) |
| } | ||
|
|
||
| err = h.BillingRepo.MarkWebhookProcessed(webhookID, eventType) | ||
| err = h.BillingService.BillingRepo.MarkWebhookProcessed(webhookID, eventType) |
There was a problem hiding this comment.
Direct access to h.BillingService.BillingRepo breaks encapsulation. Consider adding a MarkWebhookProcessed method to BillingService to maintain proper abstraction boundaries.
| err = h.BillingService.BillingRepo.MarkWebhookProcessed(webhookID, eventType) | |
| err = h.BillingService.MarkWebhookProcessed(webhookID, eventType) |
… methods to maintain consistency
Summary
This PR refactors the service layer from pure functions to struct-based services, introducing dependency injection and improved encapsulation. The changes move from a functional programming approach to an object-oriented service pattern.
What changed