comixスマートフォン用の表示で見るcomixジャンプみたいなブログになりたい。GoTweetこの記事は?インディー開発をしたり、本を読んだり、勉強会に参加したりして、GoのWebAPI開発における自分なりの実装パターンが固まってきたので現状を整理します。具体的にはORM、フレームワーク、パッケージ構成あたりの話。ある程度アンチパターンを踏んできてますが、僕自身プロダクションレベルでのGo開発経験がバリバリあるわけではないので、ここは間違ってるぞ!とか自分はこうしてる!など(建設的な)マサカリや大歓迎でございます。以下のような小〜中規模程度のJSONで話すWebAPIを想定。APIの数は20本前後シンプルなCRUDベースのAPIが多いが、ちょっと複雑なリレーションやビジネスロジックも多少あり。外部システムとの連携は(システム内の)DBがメイン。Push通知など外部のAPIと連携する箇所も。ちなみにインディー開発中心なので、ミッションクリティカルなシステムであることは想定してません。言え、ある程度の規模までプロダクションレベルに耐えうるものを想定。(と言うより、そこを目指しています...!)テクノロジースタックこのあたりは好みもあると思いますが、僕は以下の構成でやることが多いです。上記の環境をDockerで作って開発してます。使っており、ファイル保存時に自動でビルドが走るようにしてます。*1なお、環境というかインフラはAWSやHeroku、VPS想定。GAE/GCPだとDatastoreを使うことが多いと思うので、また違ってきそう。銀の弾丸はないので、何が正しいか正しくないかは状況次第ですが、アーキテクチャやライブラリの選定基準や開発方針としては以下の2つを意識してます。前置きが長くなりましたが、ここからGo界隈でよく盛り上がるトピック別に現状を書いていきます。パッケージをいい感じに使えるようにしたライブラリ。パッケージで頑張るのがGoっぽいとは思うのですが、structへのマッピングを自分でやるのは大変なので、メンテもきちんとされているsqlxを使うようになりました。アリだとは思うのですが...と言うか自分も最初使ってました。エラーハンドリングが重要なGoの世界観と合わないと思ってるのと便利な分コードが複雑なので、慣れてきたら薄いライブラリを使うのがいいかなと思ってます。MySQLならschemalexが枯れてて安心感があります。その他の選択肢xoxoDBから直接Goのモデルを生成してくれる便利なやつ。Recordっぽいものを使いたい人向け。フレームワーク関連いわゆるWAFは使ってません。フレームワークを採用するのも良いと思いますが、個人的には余計なDSLを覚えずに可能な限りGoだけで書きたいので、現状は使ってません。RubyにおけるRailsみたいなデファクトスタンダードとなるフレームワークが誕生すれば、また別かもしれない。JSONではなくHTMLをレンダリングするような場合だと、これだけだと辛いかもしれませんが、JSON形式のWebAPIならこれで充分かなと思ってます。その他の選択肢go-json-restフレームワークと言うよりルーティングとミドルウェアのライブラリ集+JSONがいい感じに扱えるライブラリって感じです。コードも読みやすいので、最初の選択肢としてはアリかなと思ってます。echoフレームワークを使うなら、パフォーマンスが良好&コミュニティも活発なのでこれが一番いいかな〜。GAE用のドキュメントが分かりやすかったので、GAEを利用する時にも良いかもしれません。個人的にはGoに慣れてきて、一番困るのがこれかなと思ってます。フレームワークを利用していればまだいいのですが、使ってないと自由過ぎて困ります。これは今も試行錯誤していますが、最近はいわゆる?レイヤードアーキテクチャ+ポートパターンを採用しています。*4概要図こういうやつです。レイヤードアーキテクチャ+ポートパターン基本的に通常のレイヤードアーキテクチャのように上から下に流れるようにしてる(下位のレイヤは上位のレイヤに依存しない)のですが、ドメインレイヤーにインターフェイス(ポート)を置くことで、ドメインレイヤだけどこにも依存しないようにしてます。破線部分については後述します。フォルダ構成こんな感じでやってます。僕がよく使うRailsやCakePHPのようなMVCモデルと比較しながら説明していきます。プレゼンテーション層MVCで言うコントローラーとビューにあたる箇所。コントローラーの責務はリクエストを受け取り、それをアプリケーションレイヤで利用出来る形にしてアプリケーションレイヤを操作すること。その結果を(ビューと連携して)レンダリングすること。ここは極力コード量が少なくなるように意識しています。ビューの責務はレンダリングに関すること全般。JSON形式のWebAPIだとコントローラー側でJSONを出力するだけで事足りることが多いので、あんまり書かないことが多いかも。僕は汎用的なレンダリングのロジックだけ書くことが多いです。アプリケーションレイヤいわゆるサービスクラスっぽい役割をする箇所。アプリケーションレイヤの責務はドメインレイヤとインフラストラクチャレイヤのビジネスロジックを操作すること。ちなみに、DBのトランザクションはここで制御しています。ドメインレイヤみんな大好きモデルを扱う箇所。ドメインレイヤの責務はビジネスロジックの実装を持つことですが、技術的な実装(直接的なDBの操作やPush通知の送信など)は行ってません。先述の通り通常のレイヤードアーキテクチャとは異なり、ドメインレイヤとインフラストラクチャレイヤとの間にインターフェイスを設け、技術と実装を分離するようにしています。定義することもあります。*5インフラストラクチャレイヤ技術的な実装を扱う箇所。インフラストラクチャレイヤの責務は直接的なDB操作(SQLの実行)やPush通知の送信など技術的な実装を行うこと。通常のレイヤードアーキテクチャでは、インフラストラクチャレイヤはどこのレイヤにも依存しませんが、技術と実装を分離するために必要に応じてドメインレイヤのインターフェイスに依存させています。オレオレルール厳密なレイヤードアーキテクチャでは直下のレイヤにのみ依存すると思うのですが、2個下のレイヤに依存するのはある程度OKにしています。これが上記概要図の破線の意味です。理想は直下のレイヤにのみ依存させるのがベストだと思うのですが、現実問題として厳密にやりすぎると辛いときがあるのである程度は許容してます。muchかなと思っています。言え、薄いライブラリしか使っていないとMVCモデルでは少し辛いケースが多く、また、テスト観点から技術と実装を分離したくなることが多いので、このようなアーキテクチャにしています。逆に言うと、フルスタックなフレームワークやORMを使っている場合はMVC(+サービスクラス的なもの)で充分なケースも多いと思います。テスト観点だけであれば、インフラストラクチャレイヤがDBのみの場合は、インターフェイスを置かず通常のレイヤードアーキテクチャでもいいかなと思ってます。単体テスト時のDBアクセスは低速でアンチパターンですが、RailsやCakePHPをこれまで使ってきた身からすると、そこまで違和感ないので。縦割りパッケージ構成レイヤではなく、機能で分けるパターン。packageを作るパターン。microservies化を想定しているならアリかなと思います。Goっぽいなと思いつつ、個人的には共通処理の扱いが難しいなと思ってます。言え、今後はvgoを使うのが主流になっていくはず。最後に書いてみて、コードがないと分かりづらい気がしたので次はコード編を書いてみたい。その時は今回書けなかったログとかエラーハンドリングのことも書くぞ。あと、冒頭にも述べましたが、Goは導入事例が増えてきたとは言え、RubyやJavaに比べると枯れておらず、ベストプラクティスがそこまで世に出回っていないので、自分なりの考えや現状を書くことで誰かのためになったり、議論のきっかけになったりすればいいなと思ってます。−脚注*1:単純にMakefike経由でビルドしているだけ。達人に学ぶソフトウェアの構造と設計』でも言及されている通り、技術的な実装に引っ張られないアーキテクチャが本当は理想なのでしょうが...。*3:ただ、フレームワークはそんなにたくさんは試していないので、他にもっと良い選択肢があるかもしれない。*4:この用語は『pospomeのサーバサイドアーキテクチャ』を参考にしています。*5:このあたりは現在進行系で悩み中です...リポジトリパターンやDAOをどうやって使うとか...難しい...。*6:もちろん開発するプロダクトや個人/チームのスキルにも依るとは思います。*7:翻って、そこからまた自分が成長出来ればいいなとこっそりと思ってます。(6)月別アーカイブはてなブログをはじめよう!itosho525さんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。