2. Shiroyagi.corp. All rights reserved
概要
● Go で API サーバーを開発してきて1年が過ぎました
○ この記事で書いたことの補足
● 良い設計の基礎知識
● Spring フレームワークと AOP (Aspect Oriented Programming)
● レイヤ化アーキテクチャ
Go に特化した内容ではなく
設計の一般的な話になってしまいました ...
3. Shiroyagi.corp. All rights reserved
自己紹介
● 森本 哲也 (@t2y)
○ http://t2y.hatenablog.jp/
● 白ヤギコーポレーション所属
○ カメリオ API という Web API サービスを開発している
■ nikkei BPnet で記事の分類に全面採用
● プログラミング言語歴
○ Python (3年) → Java (3年) → Go (1.5年)
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. Shiroyagi.corp. All rights reserved
アスペクト指向プログラミング
● 本来の思想は難しそうなので省略 ...
● オブジェクト指向プログラミング (OOP) を置き換えるもの
ではなく、それを補助するようなもの
● 目的は横断的関心事の分離
(Separation Of Cross-Cutting Concerns)
● 参考
○ 第5回:AOPとは何か
○ アスペクト指向プログラミング(AOP)は機能を挿入する仕組み?
16. Shiroyagi.corp. All rights reserved
のミドルウェア
● https://godoc.org/goji.io#Mux.Use
○ Mux (HTTP Multiplexer) 単位に設定できる
■ ミドルウェアスタックと HTTP ルーターの機能を提供
○ リクエスト単位に必ず実行するような処理を実装する
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. Shiroyagi.corp. All rights reserved
アプリケーション層のインターセプター
● アプリ (インスタンス) 単位に設定できる
○ 実際はアプリ = 顧客になっている
● アプリごとのビジネスロジックなどを実装する
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 インスタンスから呼び出すべき?
→ いま必要ないからやってない