見出し画像

【Go初学】プロジェクトレイアウト[3]

前回記載したレイアウトの続き。そんなものに時間掛けずに別のことやれと思うが、ついつい気になってしまい配置をあれこれ試してしまう、の更に続き。package-oriented-design のベースは変わらず、前回の不穏な臭いを改善した。ひとまずこの形で進めてみる予定。
前回の構成からの変更点は、ルーティングやトークン検証周りの処理を、リクエスト情報を伝播させるミドルウェアの形で実装してみた。それに伴い main.goが middleware を通して handler を取得して ListenAndServe() するように変更した。

├── cmd
│   ├── go.mod
│   ├── go.sum
│   ├── main
│   └── main.go
├── configs
│   └── config.yml
├── internal
│   ├── api
│   │   └── v1
│   │       ├── auth
│   │       │   ├── controller.go
│   │       │   ├── go.mod
│   │       │   ├── go.sum
│   │       │   ├── model.go
│   │       │   ├── repository.go
│   │       │   ├── route.go
│   │       │   ├── service.go
│   │       │   └── viewmodel.go
│   │       ├── session
│   │       │   ├── controller.go
│   │       │   ├── go.mod
│   │       │   ├── go.sum
│   │       │   ├── model.go
│   │       │   ├── repository.go
│   │       │   ├── route.go
│   │       │   ├── service.go
│   │       │   └── viewmodel.go
│   │       ├── user
│   │       │   ├── controller.go
│   │       │   ├── go.mod
│   │       │   ├── go.sum
│   │       │   ├── model.go
│   │       │   ├── repository_test.go
│   │       │   ├── repository.go
│   │       │   ├── route_test.go
│   │       │   ├── route.go
│   │       │   ├── seed_test.go
│   │       │   ├── service_test.go
│   │       │   ├── service.go
│   │       │   └── viewmodel.go
│   │       └── zo
│   │           ├── controller.go
│   │           ├── go.mod
│   │           ├── go.sum
│   │           ├── model.go
│   │           ├── repository_test.go
│   │           ├── repository.go
│   │           ├── route_test.go
│   │           ├── route.go
│   │           ├── seed_test.go
│   │           ├── service_test.go
│   │           ├── service.go
│   │           └── viewmodel.go
│   ├── config
│   │   ├── config.go
│   │   ├── go.mod
│   │   └── go.sum
│   ├── middleware
│   │   ├── go.mod
│   │   ├── go.sum
│   │   ├── jwt_middleware.go
│   │   ├── middleware.go
│   │   └── router_middleware.go
│   ├── platform
│   │   ├── myauth
│   │   │   ├── go.mod
│   │   │   ├── go.sum
│   │   │   └── myauth.go
│   │   ├── mycontext
│   │   │   ├── go.mod
│   │   │   └── mycontext.go
│   │   ├── mydb
│   │   │   ├── database.go
│   │   │   ├── go.mod
│   │   │   └── go.sum
│   │   ├── myerror
│   │   │   ├── go.mod
│   │   │   └── myerror.go
│   │   ├── myhttp
│   │   │   ├── go.mod
│   │   │   ├── go.sum
│   │   │   └── http.go
│   │   └── myrouter
│   │       ├── go.mod
│   │       ├── go.sum
│   │       ├── route_key.go
│   │       └── router.go
│   ├── test
│   │   ├── config.yml
│   │   ├── go.mod
│   │   ├── go.sum
│   │   ├── test.go
│   │   └── util.go
├── migrations
│   ├── 2021-12-09_12-00_go_p_zo_Zos_CREATE.sql
│   ├── 2021-12-24_13-48_go_p_zo_Users_CREATE.sql
│   └── 2022-01-13_22-51_Go_P_Zo_Clients_CREATE.sql
├── pkg
│   └── common
│       ├── common.go
│       └── go.mod
├── go.mod
├── LICENSE
├── NOTICE
├── README.md
└── workspace.code-workspace

▼要改善としていたところ

・myrouter の役割
以前は myrouter が各APIパッケージを参照してルーティングの定義を登録し、API側もテストの際 myrouter を使おうとするため、myrouter -> API -> myrouter と循環参照になり、テストファイルを別パッケージに切り出していた。
これを、myrouter は外部から渡されたルーティング定義を登録し、リクエストが来た際に対応したハンドラを呼び出す振る舞いへ変更した。改善の流れとしては、不穏な臭いのするパッケージ参照の流れを確認し、platform/ 下のパッケージが別パッケージ(api)を参照する流れが正しくないと気づいた。そして platform パッケージ内は外側から利用されるものという役割と考えると、myrouter の振る舞いも自然とこうなったら良さそうという振る舞いが見えた(その後 middleware へ置き換えた)。

・APIのテストファイルの配置
上記の通り循環参照が解消したため、テストファイルもAPIパッケージ内に配置し直すことができた(フォルダ名をパッケージ名とするお作法が無ければ別階層に分けたいが・・)。

・ルート定義やのそのテストの配置
参考サイトでは cmd下で routes(handlers) とテストがレイアウト定義されている。ただ internal の各APIパッケージ内でルーティングの定義とテストは行ったほうが分離できてよいのではと思いその形にした。
だがAPIパッケージ内のテストでは統合されたテストが行えないことに気が付いた。アクセストークン認証を必要とするAPIの場合、そのAPI呼び出しのためにまずアクセストークンを取得する必要があるが、同階層のトークン取得APIを呼び出すわけにいかない。cmd下でルーティングのテストを行うレイアウトになっていたのはアプリケーションの統合的なテストを行うためということかもと思った。

▼あとがき

記事を書きながらふと「あれ、これ正しくなさそうだな」と気付き呼び出し処理など修正した。ちょっと忘れた頃に見返すと、情報を再構築する際に、それまで見落としていた問題に気が付きやすいのかもしれない。記事ドリブンな学習も継続していきたい。

この記事が気に入ったらサポートをしてみませんか?