Slide 1

Slide 1 text

2024/04/19 Nakaya Ryota 再利用パターン

Slide 2

Slide 2 text

ギフティ入社:2019年1月 
 所属:技術本部 Distribution Section GiftExperience dev Unit 
 前職:バックオフィス系システムのパッケージベンダー(上流メイン) 
 言語:Go、Ruby、Java 
 分報:#times_nakaya 
 好きな4文字熟語:不労所得 
 
 自己紹介

Slide 3

Slide 3 text

みなさん、ダブルメンテって嫌いですよね
 
 (僕は嫌いです)


Slide 4

Slide 4 text


 重複しているものを見ると共通化したくなりますよね
 
 DRY(Don't Repeat Yourself) 原則、口を酸っぱくして指摘され ますよね


Slide 5

Slide 5 text

共通化はエンジニアの性
 
 ソフトウェアの利点は、再利用可能であること


Slide 6

Slide 6 text

コードを再利用するときに
 どういう手法があるんだろう?


Slide 7

Slide 7 text

● 再利用パターン
 ○ 関数に切り出す
 ○ ライブラリ化
 ○ 共有サービス
 ○ サイドカーコンテナ
 ● 共通化の罠
 Agenda

Slide 8

Slide 8 text

● 再利用パターン
 ○ 関数に切り出す
 ○ ライブラリ化
 ○ 共有サービス
 ○ サイドカーコンテナ
 ● 共通化の罠
 Agenda

Slide 9

Slide 9 text

● 共通の処理を関数(サブルーチン)に切り出す
 関数に切り出す def hoge ... taxed_item_price = item_price * 1.1 ... end def fuga ... taxed_item_price = item_price * 1.1 ... end

Slide 10

Slide 10 text

● 共通の処理を関数(サブルーチン)に切り出す
 関数に切り出す def hoge ... taxed_item_price = item_price * 1.1 ... end def fuga ... taxed_item_price = item_price * 1.1 ... end def hoge ... taxed_item_price = taxed_item_price(item_price) ... end def fuga ... taxed_item_price = taxed_item_price(item_price) ... end def taxed_item_price(item_price) item_price * 1.1 end 消費税計算を行う処理を関数化して再利用→


Slide 11

Slide 11 text

● 関数化以外にも変数化、定数化、クラス化など言語によって様々な方法で共通化ができる
 ● それらを高度に組み合わせて形式化した、デザインパターンなどもある
 ● ただし、再利用できる範囲は同一コードベース内に限られる
 関数に切り出す

Slide 12

Slide 12 text

● 再利用パターン
 ○ 関数に切り出す
 ○ ライブラリ化
 ○ 共有サービス
 ○ サイドカーコンテナ
 ● 共通化の罠
 Agenda

Slide 13

Slide 13 text

● コードをとある単位でパッケージングしてインポート可能にする
 ● Ruby なら gem、Node.js なら module など
 ライブラリ化

Slide 14

Slide 14 text

● 複数のコードベースを跨いだ共通化が可能
 ● ライブラリの粒度や依存関係の管理が大変
 ○ 粒度が粗いと、使用していない機能の変更でもバージョンアップする必要が出てきうる
 ○ 粒度が小さいと、ライブラリ間の依存関係が増え、管理が煩雑になる
 ● 言語の縛りがある
 ○ Ruby の gem は Ruby でしか使えない
 ○ 少なくともインポートする側の処理系が扱えるものでないとダメ
 ● 処理がコードに閉じない場合(永続化処理があるなど)は、使い所が難しい
 ○ 誰がテーブルスキーマを管理するのかなど、考えることが増える
 ライブラリ化

Slide 15

Slide 15 text

● 再利用パターン
 ○ 関数に切り出す
 ○ ライブラリ化
 ○ 共有サービス
 ○ サイドカーコンテナ
 ● 共通化の罠
 Agenda

Slide 16

Slide 16 text

● 共通機能を全く別のサービスとして管理する
 ● なんらかの通信プロトコル、フォーマットを使用してデータをやり取りする
 ○ Web なら HTTP や WebSocket など
 ○ フォーマット
 ■ JSON、XML など
 ○ プログラミング言語に依存しない
 共有サービス

Slide 17

Slide 17 text

● インターフェースだけを共有し、内部実装には依存しないのでより疎結合になる
 ○ サービス側は IF を守っていれば自由に更新できる
 ● プログラミング言語の縛りがない
 ● 性能、スケーラビリティ、耐障害性など運用特性上のリスクが出てくる
 ○ 協調スケーリングが必要
 ○ リモート呼び出しのため、ネットワークレイテンシがある
 ○ 共有サービスが SPOF になる
 ● 共有サービスの更新で、全ての依存サービスが壊れるリスクがある
 共有サービス

Slide 18

Slide 18 text

● 再利用パターン
 ○ 関数に切り出す
 ○ ライブラリ化
 ○ 共有サービス
 ○ サイドカーコンテナ
 ● 共通化の罠
 Agenda

Slide 19

Slide 19 text

サイドカーコンテナ ● コンテナ限定のパターン
 ● マイクロサービスの文脈でよく出てくる
 ○ サービスメッシュとか
 ○ ロギング、モニタリング、プロトコル変換など全てのアプリが必要とする共通処理を行う
 ● アプリケーションコンテナの横に、共通処理を担うコンテナを横付けするようにホストする
 ● サイドカーのコンテナイメージ自体は共通でメンテされる


Slide 20

Slide 20 text

サイドカーコンテナ ● プログラミング言語の縛りがない
 ● マシンリソースの割り当てがコントロールできる
 ● サイドカーコンテナを立てて運用するためのテクノロジーが必要
 ● サービスごとにサイドカーを立てるのが非効率的なので最近はアンビエントメッシュという手法 も出てきている


Slide 21

Slide 21 text

● 再利用パターン
 ○ 関数に切り出す
 ○ ライブラリ化
 ○ 共有サービス
 ○ サイドカーコンテナ
 ● 共通化の罠
 Agenda

Slide 22

Slide 22 text

● ゴッドクラス、ゴッドサービスに気をつける
 ● コードを共通化すると、それを使うコード側に依存関係が発生する
 ● 利用箇所が増えれば増えるほど、共有コードの変更による影響範囲が増える
 ● どこでも使うからと、一つのクラスや一つのサービスにロジックを集中させ、全員がそこに依存 すると、それの変更時に全てが壊れる可能性がある
 ● 適度な抽象化と凝集化と変化率が重要
 ○ 全再利用の原則
 ○ 閉鎖性共通の原則
 ○ 単一責任の原則
 ○ 安定度・抽象度等価の原則
 共通化の罠

Slide 23

Slide 23 text

● その処理が呼ばれる際のコンテキストが重要
 ○ システム内に同様の処理を行う部分が複数あったとしても、それぞれが使われるコンテキストが別なら共通化 しない方が良い
 ○ たまたま一時的に同じ(共通化できる)状態になっているだけの可能性がある
 ● 変更の文脈それ自体はコードでは表現されない
 ○ 文脈を加味した設計力が求められる
 ○ 再利用は基本的に良いことだが、システム全体の構造がわかるまでは共有は慎重に行う
 共通化の罠

Slide 24

Slide 24 text

fin