Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Goji とレイヤ化アーキテクチャ

1,432 views

Published on

Go 1.7 Release Party in Tokyo
http://gocon.connpass.com/event/37332/

Published in: Technology
  • Be the first to comment

Goji とレイヤ化アーキテクチャ

  1. 1. とレイヤ化アーキテクチャ 白ヤギコーポレーション 森本 哲也
  2. 2. Shiroyagi.corp. All rights reserved 概要 ● Go で API サーバーを開発してきて1年が過ぎました ○ この記事で書いたことの補足 ● 良い設計の基礎知識 ● Spring フレームワークと AOP (Aspect Oriented Programming) ● レイヤ化アーキテクチャ Go に特化した内容ではなく 設計の一般的な話になってしまいました ...
  3. 3. Shiroyagi.corp. All rights reserved 自己紹介 ● 森本 哲也 (@t2y) ○ http://t2y.hatenablog.jp/ ● 白ヤギコーポレーション所属 ○ カメリオ API という Web API サービスを開発している ■ nikkei BPnet で記事の分類に全面採用 ● プログラミング言語歴 ○ Python (3年) → Java (3年) → Go (1.5年)
  4. 4. 良い設計の 基礎知識
  5. 5. Shiroyagi.corp. All rights reserved ● 発売: 2013-04-24 (新人応援号) ● 特集1: 「良い設計の基礎知識」 ○ 井上 誠一郎 著 ○ 6章構成で全37ページ ● 私は設計の基礎知識を この記事から学びました
  6. 6. Shiroyagi.corp. All rights reserved ● 「設計とは継続する工程」 ○ 設計という行為は、何を作るか決めたあとから実際にコードを書き上げて モノができあがるまで、ずっと考え続ける行為 ○ 現代のソフトウェア開発では設計と実装は不可分 ○ 事前の設計に時間をかけても コードを書く中で考え直しは避けられない ○ 設計を通じて問題やシステムの理解が 進めば、コードのフィードバックや 最初の設計方針の誤りに気づく場合がある 設計とは?
  7. 7. Shiroyagi.corp. All rights reserved 「良い設計の基礎知識」から抜粋 ● 依存関係の整理 ○ 安定しているほうへ依存する ● フレームワークのように設計する ○ “アプリケーション全体がフレームワークの積み上げのように構成され、不安定な部分を上に 上に押し上げていくのが設計の進化の形です。この形で設計が進化すると、一番上には拡張 言語層が来ます” ● レイヤ化アーキテクチャ ○ 上位下位の関係になるように全体を分割する ○ 上位レイヤは直下のレイヤにしかアクセスしないように強制する ● 設計のトレードオフ ○ 教科書的には実行速度よりも正しい設計を優先すべき ○ システム制約により設計を変更せざるを得ない場合もあるのが現実
  8. 8. フレームワーク と
  9. 9. Shiroyagi.corp. All rights reserved フレームワーク ● Java の Web アプリケーションフレームワークの1つ ● 最初のリリースは2003年6月 ● 開発者の Rod Johnson は IoC (後に DI) の提唱者? ● モジュール ○ … たくさんある中の1つとして ○ 11. Aspect Oriented Programming with Spring ○ “The key unit of modularity in OOP is the class, whereas in AOP the unit of modularity is the aspect.”
  10. 10. Shiroyagi.corp. All rights reserved アスペクト指向プログラミング ● 本来の思想は難しそうなので省略 ... ● オブジェクト指向プログラミング (OOP) を置き換えるもの ではなく、それを補助するようなもの ● 目的は横断的関心事の分離 (Separation Of Cross-Cutting Concerns) ● 参考 ○ 第5回:AOPとは何か ○ アスペクト指向プログラミング(AOP)は機能を挿入する仕組み?
  11. 11. Shiroyagi.corp. All rights reserved シンプルな実装例 ● github.com/gogap/aop ○ Aspect Oriented Programming For Golang 例えば、ログイン処理を実行したときに ... 前処理/後処理を呼び出す仕組みを汎用化する ● 前処理/後処理は再利用可 ● 開発者は本質的な処理のみ実装すれば良い ● 例) 前: ユーザー名の存在チェック , 後: ログイン情報のセッションへの保存 ● パスワード認証のログイン処理 ● OAuth認証のログイン処理
  12. 12. Shiroyagi.corp. All rights reserved と ● Any hope for aspect oriented programming? #496 ○ “ロードマップにはない。” ○ “そういうのは go nuts で議論すると良いよ。”
  13. 13. レイヤ化アーキテクチャ
  14. 14. Shiroyagi.corp. All rights reserved 軽量 アプリケーションフレームワーク ● 設計思想 1. Simple (Sinatra や Flask の流派) 2. Composable 3. Not magic 4. Enough rope to hang yourself with ● リポジトリ ○ 旧: github.com/zenazn/goji ○ 新: github.com/goji/goji (2015-11-01 〜)
  15. 15. Shiroyagi.corp. All rights reserved カメリオ サーバーのアーキテクチャ App1 Interceptor1 Interceptor2 ... Middleware1 Middleware2 ... App2 Interceptor1 Interceptor3 ... インフラ層 net/http Goji 層 Middleware Cache Routing HTTP Handler アプリケーション層 Interceptor Business Logic Search QueryApplication Handler API 処理 Request Response 認証 キャッシュ JSON変換 重複除去 属性の要否 記事の分類処理
  16. 16. Shiroyagi.corp. All rights reserved のミドルウェア ● https://godoc.org/goji.io#Mux.Use ○ Mux (HTTP Multiplexer) 単位に設定できる ■ ミドルウェアスタックと HTTP ルーターの機能を提供 ○ リクエスト単位に必ず実行するような処理を実装する
  17. 17. Shiroyagi.corp. All rights reserved ミドルウェアで の実装例 func CommonAPIMiddleware( c *web.C, h http.Handler, ) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { for _, before := range beforeHandlers { if !before(*c, w, r) { return } } h.ServeHTTP(w, r) // next for _, after := range afterHandlers { after(*c, w, r) } } return http.HandlerFunc(fn) } type AfterHandler func(web.C, http.ResponseWriter, *http.Request) var afterHandlers = []AfterHandler{ SaveAPIStat, WriteJsonResponse, SaveResponseIntoCache, } type BeforeHandler func(web.C, http.ResponseWriter, *http.Request) bool var beforeHandlers = []BeforeHandler{ SetAppSettings, SetPropertiesToContext, CreateCacheKey, WriteCacheResponseIfAvailable, }
  18. 18. Shiroyagi.corp. All rights reserved アプリケーション層のインターセプター ● アプリ (インスタンス) 単位に設定できる ○ 実際はアプリ = 顧客になっている ● アプリごとのビジネスロジックなどを実装する
  19. 19. Shiroyagi.corp. All rights reserved アプリ層で の実装例 func ApplicationHandler(handlerFunc func(c *types.ApplicationContext)) web.HandlerType { return func(c web.C, res http.ResponseWriter, req *http.Request) { app, err := NewApplication(&c, res, req) if err != nil { err := errors.New(ERROR_NEW_APPLICATION) # error handling return } appCtx := app.GetApplicationContext() for _, before := range app.GetBeforeInterceptors() { before(appCtx) } handlerFunc(appCtx) for _, after := range app.GetAfterInterceptors() { after(appCtx) } } } 低レイヤのContext, Resposne, Request を引数に Application を生成 厳密に AOP をやるなら Application にハンドラーメソッドを定義し、 app インスタンスから呼び出すべき? → いま必要ないからやってない
  20. 20. Shiroyagi.corp. All rights reserved 「良い設計の基礎知識」から抜粋 ● 依存関係の整理 ○ 安定しているほうへ依存する ● フレームワークのように設計する ○ “アプリケーション全体がフレームワークの積み上げのように構成され、不安定な部分を上に 上に押し上げていくのが設計の進化の形です。この形で設計が進化すると、一番上には拡張 言語層が来ます” ● レイヤ化アーキテクチャ ○ 上位下位の関係になるように全体を分割する ○ 上位レイヤは直下のレイヤにしかアクセスしないように強制する ● 設計のトレードオフ ○ 教科書的には実行速度よりも正しい設計を優先すべき ○ システム制約により設計を変更せざるを得ない場合もあるのが現実
  21. 21. Shiroyagi.corp. All rights reserved 処理が安定しているとは? ● 要件が変わっても処理を変更する必要がない ● 処理に変更がないとなぜ嬉しい? ○ (その箇所で) バグが発生しない ● 安定した処理とそうでない処理を分けて考える ○ 依存関係の整理 ● 変更がある部分を上へ上へ (外へ外へ) 追い出す ○ → フレームワークようなものが出来上がる ○ → 積み重なってレイヤ化されていく
  22. 22. Shiroyagi.corp. All rights reserved 設計と学び ● Negroni と Gorilla.Context で実装していた (1.2年前) ○ Context は WAF とセットで扱いたい ● Negroni から Goji へ移行 (1年前) ○ 標準のミドルウェアで API 単位の AOP を実装するのは煩雑 → Dispatch 機能をもったミドルウェア機構を追加 ○ 顧客が増えて API 機能に対する要件が多様化 ● アプリ層を導入 (半年前) ○ ← いまここ 1年以上、開発しながら設計を考えてきた結果 こういう形になってそれなりに機能しているという話 ≠ 最初からこう設計すれば良いというわけではない
  23. 23. Shiroyagi.corp. All rights reserved まとめ ● Go 1.7 おめでとうございます! ● Go の言語機能がシンプルだから設計に注力できる?

×