SlideShare a Scribd company logo
とレイヤ化アーキテクチャ
白ヤギコーポレーション 森本 哲也
Shiroyagi.corp. All rights reserved
概要
● Go で API サーバーを開発してきて1年が過ぎました
○ この記事で書いたことの補足
● 良い設計の基礎知識
● Spring フレームワークと AOP (Aspect Oriented Programming)
● レイヤ化アーキテクチャ
Go に特化した内容ではなく
設計の一般的な話になってしまいました ...
Shiroyagi.corp. All rights reserved
自己紹介
● 森本 哲也 (@t2y)
○ http://t2y.hatenablog.jp/
● 白ヤギコーポレーション所属
○ カメリオ API という Web API サービスを開発している
■ nikkei BPnet で記事の分類に全面採用
● プログラミング言語歴
○ Python (3年) → Java (3年) → Go (1.5年)
良い設計の
基礎知識
Shiroyagi.corp. All rights reserved
● 発売: 2013-04-24 (新人応援号)
● 特集1: 「良い設計の基礎知識」
○ 井上 誠一郎 著
○ 6章構成で全37ページ
● 私は設計の基礎知識を
この記事から学びました
Shiroyagi.corp. All rights reserved
● 「設計とは継続する工程」
○ 設計という行為は、何を作るか決めたあとから実際にコードを書き上げて
モノができあがるまで、ずっと考え続ける行為
○ 現代のソフトウェア開発では設計と実装は不可分
○ 事前の設計に時間をかけても
コードを書く中で考え直しは避けられない
○ 設計を通じて問題やシステムの理解が
進めば、コードのフィードバックや
最初の設計方針の誤りに気づく場合がある
設計とは?
Shiroyagi.corp. All rights reserved
「良い設計の基礎知識」から抜粋
● 依存関係の整理
○ 安定しているほうへ依存する
● フレームワークのように設計する
○ “アプリケーション全体がフレームワークの積み上げのように構成され、不安定な部分を上に
上に押し上げていくのが設計の進化の形です。この形で設計が進化すると、一番上には拡張
言語層が来ます”
● レイヤ化アーキテクチャ
○ 上位下位の関係になるように全体を分割する
○ 上位レイヤは直下のレイヤにしかアクセスしないように強制する
● 設計のトレードオフ
○ 教科書的には実行速度よりも正しい設計を優先すべき
○ システム制約により設計を変更せざるを得ない場合もあるのが現実
フレームワーク
と
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.”
Shiroyagi.corp. All rights reserved
アスペクト指向プログラミング
● 本来の思想は難しそうなので省略 ...
● オブジェクト指向プログラミング (OOP) を置き換えるもの
ではなく、それを補助するようなもの
● 目的は横断的関心事の分離
(Separation Of Cross-Cutting Concerns)
● 参考
○ 第5回:AOPとは何か
○ アスペクト指向プログラミング(AOP)は機能を挿入する仕組み?
Shiroyagi.corp. All rights reserved
シンプルな実装例
● github.com/gogap/aop
○ Aspect Oriented Programming For Golang
例えば、ログイン処理を実行したときに ...
前処理/後処理を呼び出す仕組みを汎用化する
● 前処理/後処理は再利用可
● 開発者は本質的な処理のみ実装すれば良い
● 例) 前: ユーザー名の存在チェック ,
後: ログイン情報のセッションへの保存
● パスワード認証のログイン処理
● OAuth認証のログイン処理
Shiroyagi.corp. All rights reserved
と
● Any hope for aspect oriented programming? #496
○ “ロードマップにはない。”
○ “そういうのは go nuts で議論すると良いよ。”
レイヤ化アーキテクチャ
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 〜)
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変換
重複除去
属性の要否
記事の分類処理
Shiroyagi.corp. All rights reserved
のミドルウェア
● https://godoc.org/goji.io#Mux.Use
○ Mux (HTTP Multiplexer) 単位に設定できる
■ ミドルウェアスタックと HTTP ルーターの機能を提供
○ リクエスト単位に必ず実行するような処理を実装する
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,
}
Shiroyagi.corp. All rights reserved
アプリケーション層のインターセプター
● アプリ (インスタンス) 単位に設定できる
○ 実際はアプリ = 顧客になっている
● アプリごとのビジネスロジックなどを実装する
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 インスタンスから呼び出すべき?
→ いま必要ないからやってない
Shiroyagi.corp. All rights reserved
「良い設計の基礎知識」から抜粋
● 依存関係の整理
○ 安定しているほうへ依存する
● フレームワークのように設計する
○ “アプリケーション全体がフレームワークの積み上げのように構成され、不安定な部分を上に
上に押し上げていくのが設計の進化の形です。この形で設計が進化すると、一番上には拡張
言語層が来ます”
● レイヤ化アーキテクチャ
○ 上位下位の関係になるように全体を分割する
○ 上位レイヤは直下のレイヤにしかアクセスしないように強制する
● 設計のトレードオフ
○ 教科書的には実行速度よりも正しい設計を優先すべき
○ システム制約により設計を変更せざるを得ない場合もあるのが現実
Shiroyagi.corp. All rights reserved
処理が安定しているとは?
● 要件が変わっても処理を変更する必要がない
● 処理に変更がないとなぜ嬉しい?
○ (その箇所で) バグが発生しない
● 安定した処理とそうでない処理を分けて考える
○ 依存関係の整理
● 変更がある部分を上へ上へ (外へ外へ) 追い出す
○ → フレームワークようなものが出来上がる
○ → 積み重なってレイヤ化されていく
Shiroyagi.corp. All rights reserved
設計と学び
● Negroni と Gorilla.Context で実装していた (1.2年前)
○ Context は WAF とセットで扱いたい
● Negroni から Goji へ移行 (1年前)
○ 標準のミドルウェアで API 単位の AOP を実装するのは煩雑
→ Dispatch 機能をもったミドルウェア機構を追加
○ 顧客が増えて API 機能に対する要件が多様化
● アプリ層を導入 (半年前)
○ ← いまここ
1年以上、開発しながら設計を考えてきた結果
こういう形になってそれなりに機能しているという話
≠ 最初からこう設計すれば良いというわけではない
Shiroyagi.corp. All rights reserved
まとめ
● Go 1.7 おめでとうございます!
● Go の言語機能がシンプルだから設計に注力できる?

More Related Content

PDF
データベース設計徹底指南
PDF
DynamoDB設計のちょっとした技
PDF
ブルックスのいう銀の弾丸とは何か?
PDF
速習!論理レプリケーション ~基礎から最新動向まで~(PostgreSQL Conference Japan 2022 発表資料)
PPTX
分散トレーシングAWS:X-Rayとの上手い付き合い方
PDF
[Cloud OnAir] BigQuery の仕組みからベストプラクティスまでのご紹介 2018年9月6日 放送
PDF
AWS Black Belt Techシリーズ Amazon CloudSearch
PDF
マルチテナント化で知っておきたいデータベースのこと
データベース設計徹底指南
DynamoDB設計のちょっとした技
ブルックスのいう銀の弾丸とは何か?
速習!論理レプリケーション ~基礎から最新動向まで~(PostgreSQL Conference Japan 2022 発表資料)
分散トレーシングAWS:X-Rayとの上手い付き合い方
[Cloud OnAir] BigQuery の仕組みからベストプラクティスまでのご紹介 2018年9月6日 放送
AWS Black Belt Techシリーズ Amazon CloudSearch
マルチテナント化で知っておきたいデータベースのこと

What's hot (20)

PDF
[AKIBA.AWS] VGWのルーティング仕様
PDF
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
KEY
やはりお前らのMVCは間違っている
PDF
20190522 AWS Black Belt Online Seminar AWS Step Functions
PPTX
がっつりMongoDB事例紹介
PDF
[AWSマイスターシリーズ]Amazon Elastic Load Balancing (ELB)
PPTX
Awsをオンプレドメコンに連携させる
PDF
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
PDF
Scala警察のすすめ
PDF
はじめよう DynamoDB ハンズオン
PDF
ロードバランスへの長い道
PDF
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
PDF
SageMakerでもAUTOMATIC1111したい
PPTX
RLSを用いたマルチテナント実装 for Django
PPTX
グラフデータベース入門
PDF
Spring Boot の Web アプリケーションを Docker に載せて AWS ECS で動かしている話
PDF
今だからこそ知りたい Docker Compose/Swarm 入門
PDF
ドメイン駆動設計のためのオブジェクト指向入門
PDF
イミュータブルデータモデル(入門編)
PDF
これからのJDK 何を選ぶ?どう選ぶ? (v1.2) in 熊本
[AKIBA.AWS] VGWのルーティング仕様
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
やはりお前らのMVCは間違っている
20190522 AWS Black Belt Online Seminar AWS Step Functions
がっつりMongoDB事例紹介
[AWSマイスターシリーズ]Amazon Elastic Load Balancing (ELB)
Awsをオンプレドメコンに連携させる
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
Scala警察のすすめ
はじめよう DynamoDB ハンズオン
ロードバランスへの長い道
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
SageMakerでもAUTOMATIC1111したい
RLSを用いたマルチテナント実装 for Django
グラフデータベース入門
Spring Boot の Web アプリケーションを Docker に載せて AWS ECS で動かしている話
今だからこそ知りたい Docker Compose/Swarm 入門
ドメイン駆動設計のためのオブジェクト指向入門
イミュータブルデータモデル(入門編)
これからのJDK 何を選ぶ?どう選ぶ? (v1.2) in 熊本
Ad

Similar to Goji とレイヤ化アーキテクチャ (20)

PDF
CloudSpiral 2014年度 Webアプリ講義(1日目)
PDF
20200708サーバーレスでのAPI管理の考え方
ODP
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
PPTX
20170510 タウンwi fixlifull_スマホアプリ開発の実例 (1)
PDF
GoCon2016 spring 自作Webフレームワーク uconを作った話
PPTX
JavaOne 2016 Report for Java EE
PPTX
Angular でもっとAPIファースト・もっとモダンデザインなWebアプリケーションを作ろう!
PDF
ネットワークについて
PDF
最新Web 通信系API総まくり!WebRTC, Streams, Push api etc.
PPTX
【 ヒカ☆ラボ 】LIFULL Home's androidアプリの開発の裏側について
PDF
50分で掴み取る ASP.NET Web API パターン&テクニック
PDF
ビズリーチの新サービスをScalaで作ってみた 〜マイクロサービスの裏側 #jissenscala
PPTX
API Academy:マイクロサービス化へのファーストステップ
PDF
BPStudy20121221
PDF
Go言語で作る webアプリ@gocon 2013 spring
PPTX
マイクロサービスのためのフレームワークGoaのご紹介
PPTX
APIに関するセッション資料
PDF
OpenStack and ACI
PPTX
REST API、gRPC、GraphQL 触ってみた【2023年12月開催勉強会資料】
PDF
ScalaMatsuri 2016
CloudSpiral 2014年度 Webアプリ講義(1日目)
20200708サーバーレスでのAPI管理の考え方
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
20170510 タウンwi fixlifull_スマホアプリ開発の実例 (1)
GoCon2016 spring 自作Webフレームワーク uconを作った話
JavaOne 2016 Report for Java EE
Angular でもっとAPIファースト・もっとモダンデザインなWebアプリケーションを作ろう!
ネットワークについて
最新Web 通信系API総まくり!WebRTC, Streams, Push api etc.
【 ヒカ☆ラボ 】LIFULL Home's androidアプリの開発の裏側について
50分で掴み取る ASP.NET Web API パターン&テクニック
ビズリーチの新サービスをScalaで作ってみた 〜マイクロサービスの裏側 #jissenscala
API Academy:マイクロサービス化へのファーストステップ
BPStudy20121221
Go言語で作る webアプリ@gocon 2013 spring
マイクロサービスのためのフレームワークGoaのご紹介
APIに関するセッション資料
OpenStack and ACI
REST API、gRPC、GraphQL 触ってみた【2023年12月開催勉強会資料】
ScalaMatsuri 2016
Ad

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

  • 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年)
  • 5. Shiroyagi.corp. All rights reserved ● 発売: 2013-04-24 (新人応援号) ● 特集1: 「良い設計の基礎知識」 ○ 井上 誠一郎 著 ○ 6章構成で全37ページ ● 私は設計の基礎知識を この記事から学びました
  • 6. Shiroyagi.corp. All rights reserved ● 「設計とは継続する工程」 ○ 設計という行為は、何を作るか決めたあとから実際にコードを書き上げて モノができあがるまで、ずっと考え続ける行為 ○ 現代のソフトウェア開発では設計と実装は不可分 ○ 事前の設計に時間をかけても コードを書く中で考え直しは避けられない ○ 設計を通じて問題やシステムの理解が 進めば、コードのフィードバックや 最初の設計方針の誤りに気づく場合がある 設計とは?
  • 7. Shiroyagi.corp. All rights reserved 「良い設計の基礎知識」から抜粋 ● 依存関係の整理 ○ 安定しているほうへ依存する ● フレームワークのように設計する ○ “アプリケーション全体がフレームワークの積み上げのように構成され、不安定な部分を上に 上に押し上げていくのが設計の進化の形です。この形で設計が進化すると、一番上には拡張 言語層が来ます” ● レイヤ化アーキテクチャ ○ 上位下位の関係になるように全体を分割する ○ 上位レイヤは直下のレイヤにしかアクセスしないように強制する ● 設計のトレードオフ ○ 教科書的には実行速度よりも正しい設計を優先すべき ○ システム制約により設計を変更せざるを得ない場合もあるのが現実
  • 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)は機能を挿入する仕組み?
  • 11. Shiroyagi.corp. All rights reserved シンプルな実装例 ● github.com/gogap/aop ○ Aspect Oriented Programming For Golang 例えば、ログイン処理を実行したときに ... 前処理/後処理を呼び出す仕組みを汎用化する ● 前処理/後処理は再利用可 ● 開発者は本質的な処理のみ実装すれば良い ● 例) 前: ユーザー名の存在チェック , 後: ログイン情報のセッションへの保存 ● パスワード認証のログイン処理 ● OAuth認証のログイン処理
  • 12. Shiroyagi.corp. All rights reserved と ● Any hope for aspect oriented programming? #496 ○ “ロードマップにはない。” ○ “そういうのは go nuts で議論すると良いよ。”
  • 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. 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. 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 インスタンスから呼び出すべき? → いま必要ないからやってない
  • 20. Shiroyagi.corp. All rights reserved 「良い設計の基礎知識」から抜粋 ● 依存関係の整理 ○ 安定しているほうへ依存する ● フレームワークのように設計する ○ “アプリケーション全体がフレームワークの積み上げのように構成され、不安定な部分を上に 上に押し上げていくのが設計の進化の形です。この形で設計が進化すると、一番上には拡張 言語層が来ます” ● レイヤ化アーキテクチャ ○ 上位下位の関係になるように全体を分割する ○ 上位レイヤは直下のレイヤにしかアクセスしないように強制する ● 設計のトレードオフ ○ 教科書的には実行速度よりも正しい設計を優先すべき ○ システム制約により設計を変更せざるを得ない場合もあるのが現実
  • 21. Shiroyagi.corp. All rights reserved 処理が安定しているとは? ● 要件が変わっても処理を変更する必要がない ● 処理に変更がないとなぜ嬉しい? ○ (その箇所で) バグが発生しない ● 安定した処理とそうでない処理を分けて考える ○ 依存関係の整理 ● 変更がある部分を上へ上へ (外へ外へ) 追い出す ○ → フレームワークようなものが出来上がる ○ → 積み重なってレイヤ化されていく
  • 22. Shiroyagi.corp. All rights reserved 設計と学び ● Negroni と Gorilla.Context で実装していた (1.2年前) ○ Context は WAF とセットで扱いたい ● Negroni から Goji へ移行 (1年前) ○ 標準のミドルウェアで API 単位の AOP を実装するのは煩雑 → Dispatch 機能をもったミドルウェア機構を追加 ○ 顧客が増えて API 機能に対する要件が多様化 ● アプリ層を導入 (半年前) ○ ← いまここ 1年以上、開発しながら設計を考えてきた結果 こういう形になってそれなりに機能しているという話 ≠ 最初からこう設計すれば良いというわけではない
  • 23. Shiroyagi.corp. All rights reserved まとめ ● Go 1.7 おめでとうございます! ● Go の言語機能がシンプルだから設計に注力できる?