発展質問:サンプルよりもやや複雑な検索処理を実装したい場合 #94
-
素晴らしい書籍をありがとうございます! 書籍の内容からはみ出してしまうのですが、次のような場合にはどのような実装が望ましいのか、自分で答えが出せず、こちらに質問させて頂きました。もしご意見を頂戴できれば大変ありがたいです。いや、本と関係ないので…とご回答頂いても大丈夫です🙏 実際のWEBアプリケーションでは、例えばタスク一覧に、そのユーザー名を併せて表示することがあるかと思います。 type TaskWithUserName struct {
Title string
UserName string
} このような構造体はどのディレクトリ・パッケージに定義するのが妥当なのか、はたまたこの考え方自体がイマイチなのか、知見を頂けましたら幸いです…!
|
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
ご質問ありがとうございます!お返事すぐかけるかわかりませんが && ベストアンサーがかけるかわかりませんが何でも聞いてもらってOKです! よくも悪くもGoはあまり「ルール」がないので設計方針によるかなと思います。チーム・リポジトリの中で統一された設計思想があれば問題ないかなと思います。@tenkoh -sanに記載していただいた考え方も良いと思います! 私の場合個人的にはパフォーマンスが問題になるまでは素朴なリポジトリの実装でservice層でデータを組み立てるアプローチでもいいかなと思います。 考えたことそのうえで思いついたいくつかのアプローチとメリデメ並べると以下のような感じでしょうか。 どこでデータを組み合わせるか
どこに構造体を定義するか
type TaskDetail {
Task
User
}
func buildRespose(tds []TaskDetail) OpenAPIとかで自動生成したレスポンス型 {
// TaskDetailからタスクタイトルとユーザー名が入ったリストを作る
} その他
ちなみに、こちらに関しては例えば以下の書き方をすればN+1にはならないかなと思いました。 package server
import "github.com/samber/lo"
func (s *service) ListTaskWithUserName() ([]TaskWithUserName, error) {
tasks, err := s.taskRepo.All()
if err != nil {
return nil, err
}
userIDs := lo.Map(tasks, func(t Task, _ int) string { return t.UserID })
users, err := s.userRepo.List(userIDs)
if err != nil {
return nil, err
}
userMap := lo.SliceToMap(users, func(u User) (string, User) { return u.ID, u })
var results []TaskWithUserName
for _, task := range tasks {
result := TaskWithUserName{Title: task.Title}
if u, ok := userMap[task.UserID]; ok {
result.UserName = u.Name
}
results = append(results, result)
}
return results, nil
}
type User struct {
ID string
Name string
}
type UserRepo interface {
List([]string) ([]User, error)
}
type Task struct {
ID string
Title string
UserID string
}
type TaskRepo interface {
All() ([]Task, error)
}
type TaskWithUserName struct {
Title string
UserName string
}
type service struct {
userRepo UserRepo
taskRepo TaskRepo
} |
Beta Was this translation helpful? Give feedback.
ご質問ありがとうございます!お返事すぐかけるかわかりませんが && ベストアンサーがかけるかわかりませんが何でも聞いてもらってOKです!
よくも悪くもGoはあまり「ルール」がないので設計方針によるかなと思います。チーム・リポジトリの中で統一された設計思想があれば問題ないかなと思います。@tenkoh -sanに記載していただいた考え方も良いと思います!
(身も蓋もない回答でごめんなさい)。
私の場合
個人的にはパフォーマンスが問題になるまでは素朴なリポジトリの実装でservice層でデータを組み立てるアプローチでもいいかなと思います。
ただし、「タスクをユーザー名で検索する」みたいな検索条件を実装する必要がある場合はJOINする一択になるかなとは思います。
考えたこと
そのうえで思いついたいくつかのアプローチとメリデメ並べると以下のような感じでしょうか。
どこでデータを組み合わせるか