Skip to content

[BE-6] 3層アーキテクチャの設計、ゲーム開始#13

Merged
yone-al merged 3 commits intodevelopfrom
BE-6
Feb 16, 2026
Merged

[BE-6] 3層アーキテクチャの設計、ゲーム開始#13
yone-al merged 3 commits intodevelopfrom
BE-6

Conversation

@yone-al
Copy link
Contributor

@yone-al yone-al commented Feb 16, 2026

概要

3層アーキテクチャでの設計
ゲーム開始のレスポンス

動作確認

変更内容・エビデンス

POST http://localhost:8080/solo

{
	"result": {
		"id": 21,
		"hints": [
			"ヒント1",
			"ヒント2",
			"ヒント3"
		]
	}
}

その他

略称一覧

  • LGTM : Looks Good To Me(レビューアーがPRの内容を確認し、問題がないと判断した際に使用する)
  • ask : 質問・確認事項(修正は任意、回答や説明を求める)
  • imo : In My Opinion(個人的な意見、修正は任意)
  • nits : 些細な指摘(修正は任意、気になった点の共有)
  • must : 必須の修正事項(マージ前に必ず対応が必要)
  • memo : メモ(参考情報として共有)

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

3層アーキテクチャ(controller/service/repository)を導入し、ゲーム開始用のエンドポイント(POST /solo)で「ID + ヒント一覧」を返す土台を追加するPRです。

Changes:

  • Controller/Service/Repository の各層を新規追加し、POST /solo からゲーム開始レスポンスを返す処理を実装
  • In-memory リポジトリでラウンド(Round)を生成・保存する処理を追加
  • モデル定義(Round / StartGameResult)を追加し、main.go でDI配線を実施

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
backend/main.go メモリリポジトリ/サービス/コントローラを生成し、POST /solo を追加
backend/controllers/hint_controller.go POST /solo のハンドラでサービスを呼び出しレスポンス返却
backend/services/hint_service.go 固定のお題・ヒントを生成し、リポジトリへ保存して結果を返す
backend/repositories/hint_repository.go Round の採番・保存を行う in-memory 実装を追加
backend/model/hint.go Round/StartGameResult の型定義を追加
backend/.serena/project.yml Serena 用プロジェクト設定を追加
backend/.serena/.gitignore Serena の cache を無視する設定を追加

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


func (c *HintController) GetHints(ctx *gin.Context) {
result, err := c.service.GetHints()
if err != nil {
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

エラー発生時に err を一切利用せず固定メッセージだけ返しているため、サーバ側での原因追跡が困難です。少なくともサーバログへ err を出力する(あるいは gin.Context.Error で付与する)など、運用上追える形にしてください。

Suggested change
if err != nil {
if err != nil {
ctx.Error(err)

Copilot uses AI. Check for mistakes.
backend/main.go Outdated
Comment on lines +12 to +20
rounds := []model.Round{
{
ID: 1,
Answer: "お題",
Hints: []string{"ヒント1", "ヒント2", "ヒント3"},
},
}

hintRepository := repositories.NewHintMemoryRepository(rounds)
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

main.go 側で rounds に固定のお題/ヒントを初期投入している一方、service 側でも同じ固定値を生成しているため、データ定義が二重化しています(また最初の POST /solo の採番が 2 から始まります)。初期データは repository のみで管理する/サービス側に寄せる等、どこが真実のソースかを一本化してください。

Suggested change
rounds := []model.Round{
{
ID: 1,
Answer: "お題",
Hints: []string{"ヒント1", "ヒント2", "ヒント3"},
},
}
hintRepository := repositories.NewHintMemoryRepository(rounds)
hintRepository := repositories.NewHintMemoryRepository([]model.Round{})

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

@yone-al yone-al Feb 16, 2026

Choose a reason for hiding this comment

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

@copilot
rounds := []model.Round{}

hintRepository := repositories.NewHintMemoryRepository(rounds)

これでどう?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@copilot
rounds := []model.Round{}

hintRepository := repositories.NewHintMemoryRepository(rounds)

これでどう?

Comment on lines +17 to +25
func (r *HintMemoryRepository) CreateRound(answer string, hints []string) (*model.Round, error) {
newID := len(r.rounds) + 1
round := model.Round{
ID: newID,
Answer: answer,
Hints: hints,
}
r.rounds = append(r.rounds, round)
return &round, nil
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

HintMemoryRepository は Gin のハンドラから同時に呼ばれる可能性があり、rounds への append/len がデータレースになります(ID の重複や panic の原因)。mutex 等で保護するか、永続層に切り替えるなどしてスレッドセーフにしてください。

Copilot uses AI. Check for mistakes.
Comment on lines +18 to +22
newID := len(r.rounds) + 1
round := model.Round{
ID: newID,
Answer: answer,
Hints: hints,
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

newID を len(rounds)+1 で作ると、初期データの ID が連番でない/欠番がある場合に ID 衝突が起きます。既存の最大 ID を走査するか、ID 生成を別コンポーネントに寄せるなどして一意性を担保してください。

Copilot uses AI. Check for mistakes.
Hints: hints,
}
r.rounds = append(r.rounds, round)
return &round, nil
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

CreateRound が返している *Round は、append した要素ではなくローカル変数 round のアドレスです。呼び出し側が返値を保持して更新するケース等で、リポジトリ内のデータと不整合になります。append 後のスライス要素(末尾)を指すポインタを返すようにしてください。

Suggested change
return &round, nil
return &r.rounds[len(r.rounds)-1], nil

Copilot uses AI. Check for mistakes.
Comment on lines +28 to +31
result, err := s.repository.CreateRound(answer, hints)
if err != nil {
return nil, errors.New("failed to save hint data")
}
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

repository.CreateRound の err を握りつぶして固定文言に置き換えているため、原因追跡が難しくなります。呼び出し元で扱えるように err をラップして返す(%w)など、元のエラー情報を保持してください。

Copilot uses AI. Check for mistakes.
// IDとヒントを返す
response := &model.StartGameResult{
ID: result.ID,
Hints: hints,
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

レスポンスの Hints が repository から返された result.Hints ではなくローカル変数 hints を参照しています。将来 repository 側で加工/コピーした場合にレスポンスと保存内容がズレるので、返却値(result)由来のデータを使うようにしてください。

Suggested change
Hints: hints,
Hints: result.Hints,

Copilot uses AI. Check for mistakes.
Comment on lines +10 to +12
type IHintController interface {
GetHints(ctx *gin.Context)
}
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

POST /solo のハンドラ名が GetHints になっており、処理内容(ゲーム開始/ラウンド作成)と名前が一致していません。用途が伝わるように StartGame / CreateRound などの名前に揃えることを検討してください。

Copilot uses AI. Check for mistakes.
@yone-al yone-al marked this pull request as draft February 16, 2026 11:14
Copy link

Copilot AI commented Feb 16, 2026

@yone-al I've opened a new pull request, #14, to work on those changes. Once the pull request is ready, I'll request review from you.

@yone-al yone-al marked this pull request as ready for review February 16, 2026 12:10
@yone-al yone-al requested a review from Copilot February 16, 2026 12:18
Copy link
Contributor

@bearl27 bearl27 left a comment

Choose a reason for hiding this comment

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

まぁいいんじゃない

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +17 to +21
func (r *HintMemoryRepository) CreateRound(answer string, hints []string) (*model.Round, error) {
maxID := 0
for _, rd := range r.rounds {
if rd.ID > maxID {
maxID = rd.ID
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

HintMemoryRepository.CreateRound が r.rounds の走査/更新をロック無しで行っています。Gin はリクエストを並列に処理するため、複数の POST /solo が同時に来るとデータレースや slice 破損が起き得ます。mutex 等で CreateRound 全体を保護するか、スレッドセーフなストレージ実装に切り替えてください。

Copilot uses AI. Check for mistakes.
Hints: hints,
}
r.rounds = append(r.rounds, round)
return &r.rounds[len(r.rounds)-1], nil
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

append 後に slice 要素へのポインタ(&r.rounds[len-1])を返していますが、後続の append で再確保が起きると呼び出し側が保持しているポインタが無効になり得ます。返却用に新しい Round を確保して返すか、ポインタではなく値を返す形にすると安全です。

Suggested change
return &r.rounds[len(r.rounds)-1], nil
retRound := round
return &retRound, nil

Copilot uses AI. Check for mistakes.
@yone-al yone-al merged commit 1b88b57 into develop Feb 16, 2026
8 checks passed
@yone-al yone-al deleted the BE-6 branch February 16, 2026 12:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants