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

PPTX
マイクロサービスにおける 結果整合性との戦い
PDF
CyberAgent における OSS の CI/CD 基盤開発 myshoes #CICD2021
PDF
ストリーム処理勉強会 大規模mqttを支える技術
PDF
マイクロサービスに至る歴史とこれから - XP祭り2021
PDF
CRDT in 15 minutes
PDF
20分でわかるgVisor入門
PPTX
Apache Spark on Kubernetes入門(Open Source Conference 2021 Online Hiroshima 発表資料)
PPTX
Fluentd1.2 & Fluent Bit
マイクロサービスにおける 結果整合性との戦い
CyberAgent における OSS の CI/CD 基盤開発 myshoes #CICD2021
ストリーム処理勉強会 大規模mqttを支える技術
マイクロサービスに至る歴史とこれから - XP祭り2021
CRDT in 15 minutes
20分でわかるgVisor入門
Apache Spark on Kubernetes入門(Open Source Conference 2021 Online Hiroshima 発表資料)
Fluentd1.2 & Fluent Bit

What's hot (20)

PDF
WebRTC入門 ~沖縄編~
PDF
正しいものを正しくつくる
PDF
株式会社コロプラ『GKE と Cloud Spanner が躍動するドラゴンクエストウォーク』第 9 回 Google Cloud INSIDE Game...
PDF
Nginxを使ったオレオレCDNの構築
PPTX
Amazon SageMakerでカスタムコンテナを使った学習
PDF
JPAのキャッシュを使ったアプリケーション高速化手法
PPTX
paizaのオンラインジャッジを支えるDockerとその周辺
PDF
C++からWebRTC (DataChannel)を利用する
PDF
Where狙いのキー、order by狙いのキー
PDF
YugabyteDBを使ってみよう(NewSQL/分散SQLデータベースよろず勉強会 #1 発表資料)
PPTX
NTTデータが考えるデータ基盤の次の一手 ~AI活用のために知っておくべき新潮流とは?~(NTTデータ テクノロジーカンファレンス 2020 発表資料)
PDF
PFN のオンプレML基盤の取り組み / オンプレML基盤 on Kubernetes 〜PFN、ヤフー〜
PPTX
Dockerからcontainerdへの移行
PDF
Tackling Complexity
PPTX
本当は恐ろしい分散システムの話
PDF
KubernetesでRedisを使うときの選択肢
PPTX
GraphQLのsubscriptionで出来ること
PDF
OpenLineage による Airflow のデータ来歴の収集と可視化(Airflow Meetup Tokyo #3 発表資料)
PDF
マルチテナントのアプリケーション実装〜実践編〜
PDF
IPv4/IPv6 移行・共存技術の動向
WebRTC入門 ~沖縄編~
正しいものを正しくつくる
株式会社コロプラ『GKE と Cloud Spanner が躍動するドラゴンクエストウォーク』第 9 回 Google Cloud INSIDE Game...
Nginxを使ったオレオレCDNの構築
Amazon SageMakerでカスタムコンテナを使った学習
JPAのキャッシュを使ったアプリケーション高速化手法
paizaのオンラインジャッジを支えるDockerとその周辺
C++からWebRTC (DataChannel)を利用する
Where狙いのキー、order by狙いのキー
YugabyteDBを使ってみよう(NewSQL/分散SQLデータベースよろず勉強会 #1 発表資料)
NTTデータが考えるデータ基盤の次の一手 ~AI活用のために知っておくべき新潮流とは?~(NTTデータ テクノロジーカンファレンス 2020 発表資料)
PFN のオンプレML基盤の取り組み / オンプレML基盤 on Kubernetes 〜PFN、ヤフー〜
Dockerからcontainerdへの移行
Tackling Complexity
本当は恐ろしい分散システムの話
KubernetesでRedisを使うときの選択肢
GraphQLのsubscriptionで出来ること
OpenLineage による Airflow のデータ来歴の収集と可視化(Airflow Meetup Tokyo #3 発表資料)
マルチテナントのアプリケーション実装〜実践編〜
IPv4/IPv6 移行・共存技術の動向
Ad

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

PPTX
REST API、gRPC、GraphQL 触ってみた【2023年12月開催勉強会資料】
PDF
Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力
PDF
YJTC18 A-1 大規模サーバの戦略
PDF
【初心者向け】API を使ってクラウドの管理を自動化しよう
PDF
[Okta x Jamf合同新年会] Okta Workflowsによるノーコード業務改善 〜Jamf APIを使ってMac端末情報を自動収集してみよう〜
PDF
Riverpodでテストを書こう
PPTX
技術選択とアーキテクトの役割
PDF
WebRTC開発者向けプラットフォーム SkyWayの裏側
PDF
S14 t3 yosuke_yamashita
PDF
第8回 福岡西区勉強会
PDF
CircleCIを使ったSpringBoot/GAEアプリ開発の効率化ノウハウ
PDF
Angular 4がやってくる!? 新機能ダイジェスト
PDF
VSCodeで始めるAzure Static Web Apps開発
PDF
Microsoft Graph API Library for Go
PPTX
PythonとRによるデータ分析環境の構築と機械学習によるデータ認識
PDF
Pyconjp2014_implementations
PDF
こんなに使える!今どきのAPIドキュメンテーションツール
PDF
Rocroにおけるgcp活用事例
PPTX
Walking front end
PDF
Django で始める PyCharm 入門
REST API、gRPC、GraphQL 触ってみた【2023年12月開催勉強会資料】
Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力
YJTC18 A-1 大規模サーバの戦略
【初心者向け】API を使ってクラウドの管理を自動化しよう
[Okta x Jamf合同新年会] Okta Workflowsによるノーコード業務改善 〜Jamf APIを使ってMac端末情報を自動収集してみよう〜
Riverpodでテストを書こう
技術選択とアーキテクトの役割
WebRTC開発者向けプラットフォーム SkyWayの裏側
S14 t3 yosuke_yamashita
第8回 福岡西区勉強会
CircleCIを使ったSpringBoot/GAEアプリ開発の効率化ノウハウ
Angular 4がやってくる!? 新機能ダイジェスト
VSCodeで始めるAzure Static Web Apps開発
Microsoft Graph API Library for Go
PythonとRによるデータ分析環境の構築と機械学習によるデータ認識
Pyconjp2014_implementations
こんなに使える!今どきのAPIドキュメンテーションツール
Rocroにおけるgcp活用事例
Walking front end
Django で始める PyCharm 入門
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 の言語機能がシンプルだから設計に注力できる?