Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
リプレイスを安心安全に 〜段階的リプレイスと等価比較〜/Safe and Secure Replacement ~ Phased Replacement and Equivalent Comparison ~
Search
Shun Uehara
June 26, 2024
Programming
1
230
リプレイスを安心安全に 〜段階的リプレイスと等価比較〜/Safe and Secure Replacement ~ Phased Replacement and Equivalent Comparison ~
こちらで発表した資料になります。
https://zozotech-inc.connpass.com/event/316086/
Shun Uehara
June 26, 2024
Tweet
Share
Other Decks in Programming
See All in Programming
アーキテクチャレベルで考える開発生産性 / architecture-and-productivity
minodriven
15
5.5k
凝集性から考えるLaravelのmiddleware、routingに書くか? Policyに書くか?
newnomad
1
160
我々はなぜテストを書くのか / Why we write test codes
takaking22
6
690
デプロイ・QA・Four keys を自動化×見える化する freee の統合デリバリー基盤
akito0922
1
330
Ruby Function Composition
bkuhlmann
1
400
Using Next.js as a full-stack framework / Next.jsをフルスタックフレームワークとして使ってみた
mongolyy
PRO
1
160
Google Cloud で プロダクト開発 事業として成長させるZennの例 / grows-zenn-with-google-cloud
wadayusuke
1
250
有効な使い方を正しく理解して実装する PHP8.3の最新機能 / Proper understanding and implementation of effective usage Latest features in PHP 8.3
seike460
PRO
2
210
並行処理を学びGuzzleと仲良くなる
shimabox
2
400
どうせキレイに書けない処理は逆にAIに書いてもらうほうが良い説 / #kyotojs 22
potato4d
2
150
関数型プログラミングへの第一歩: 純粋関数を知る
74k3z4k1
0
120
Adding Tests to Untestable Legacy Code
afilina
PRO
0
190
Featured
See All Featured
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
73
15k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
247
20k
KATA
mclloyd
18
12k
Designing with Data
zakiwarfel
96
4.9k
Gamification - CAS2011
davidbonilla
77
4.8k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
188
16k
The Straight Up "How To Draw Better" Workshop
denniskardys
228
130k
Atom: Resistance is Futile
akmur
260
25k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
501
140k
A Tale of Four Properties
chriscoyier
154
22k
Fashionably flexible responsive web design (full day workshop)
malarkey
399
65k
Statistics for Hackers
jakevdp
791
220k
Transcript
リプレイスを安心安全に 〜段階的リプレイスと等価比較〜 株式会社ZOZO 基幹システム本部 物流開発部 基幹リプレイスブロック 上原 駿 Copyright
© ZOZO, Inc. 1 ZOZO物流システムリプレイスの旅 〜序章〜 これまでとこれから
© ZOZO, Inc. 株式会社ZOZO 基幹システム本部 物流開発部 基幹リプレイスブロック 上原 駿 2023年2月に株式会社ZOZOに中途入社
前職のSESのベンチャー企業では、 上流工程からのリプレイスプロジェクト等に尽力。 現在は物流システムのリプレイスに従事。 趣味は、ゲーム(APEX)、野球、筋トレ。 2
© ZOZO, Inc. 3 アジェンダ ➢ 入荷リプレイスについて ➢ 入荷リプレイスの進め方 ➢
まとめ
© ZOZO, Inc. 入荷リプレイスについて 4
© ZOZO, Inc. 入荷領域で障害が発生すると・・・ • 運送業者やブランドに影響が出てしまう • ZOZOTOWNで販売するための在庫が増えない • 入荷作業予定だったアルバイトスタッフの休業保証などが発生してしまう
加えて • 今後の人件費削減のため、入荷業務の自動化など新規開発を推進しなくてはいけない 既存システムにおける入荷領域の重要性 5
© ZOZO, Inc. 既存システムの課題整理 • ビジネスロジックの複雑化に伴う機能追加の労力の増大 • 障害の分離が出来ず、単一障害点になってしまっている • Classic
ASPのサポート終了 6
© ZOZO, Inc. 既存の課題に対する解決案 7 • ビジネスロジックの複雑化に伴う機能追加の労力の増大 • 障害の分離が出来ず、単一障害点になってしまっている •
Classic ASPのサポート終了
© ZOZO, Inc. 既存の課題に対する解決案 8 • ビジネスロジックの複雑化に伴う機能追加の労力の増大 →曖昧になってしまっている各領域の境界をはっきりとさせる必要がある • 障害の分離が出来ず、単一障害点になってしまっている
• Classic ASPのサポート終了
© ZOZO, Inc. 既存の課題に対する解決案 9 • ビジネスロジックの複雑化に伴う機能追加の労力の増大 →曖昧になってしまっている各領域の境界をはっきりとさせる必要がある • 障害の分離が出来ず、単一障害点になってしまっている
→DBを分離してマイクロサービス化が必要 • Classic ASPのサポート終了
© ZOZO, Inc. 既存の課題に対する解決案 10 • ビジネスロジックの複雑化に伴う機能追加の労力の増大 →曖昧になってしまっている各領域の境界をはっきりとさせる必要がある • 障害の分離が出来ず、単一障害点になってしまっている
→DBを分離してマイクロサービス化が必要 • Classic ASPのサポート終了 →言語の変更が必要
© ZOZO, Inc. DB分割ができるかどうかの検討 結論から言うと、DB分割は現状難しいと判断した。 入荷は基幹DBとの結びつきが強く、 入荷で使用するテーブルに対するCRUD処理が様々な領域で書かれているため、 データ分離の観点から設計フェーズでは実現可能かどうかが判断できなかった。 11 hogeTable
Back Office 経理 セール 管理 注文 確認 入荷 発送 商品 管理 他機能で作成されたデータを参照していたり、 入荷のデータを元に他機能でデータを作っていたり ・・・
© ZOZO, Inc. 解決する課題の決定 • ビジネスロジックの複雑化に伴う機能追加の労力の増大 • 障害の分離が出来ず、単一障害点になってしまっている • Classic
ASPのサポート終了 12
© ZOZO, Inc. 解決する課題の決定 • ビジネスロジックの複雑化に伴う機能追加の労力の増大 • 障害の分離が出来ず、単一障害点になってしまっている • Classic
ASPのサポート終了 13 マイクロサービス化の設計難易度 開発、運用コスト > マイクロサービス化のメリット
© ZOZO, Inc. 入荷リプレイスの概要と要件 [概要] 入荷に関する機能をモジュール化して、独立性を高めることを目的とするリプレイスプロジェクト [要件] • 言語をClassic ASPからJavaに変える
• モジュラーモノリスに加える • テストコードを追加してデグレを起こさないようにする • 言語を変えても既存と等価であることを担保する • 将来的にマイクロサービス化を検討するためにテーブルの使用箇所を可視化する • これらを段階的にリリースする 14
© ZOZO, Inc. 既存課題と要件の対応 • ビジネスロジックの複雑化に伴う機能追加の労力の増大 • 障害の分離が出来ず、単一障害点になってしまっている • Classic
ASPのサポート終了 15
© ZOZO, Inc. 既存課題と要件の対応 • ビジネスロジックの複雑化に伴う機能追加の労力の増大 ◦ モジュラーモノリスに加える • 障害の分離が出来ず、単一障害点になってしまっている
• Classic ASPのサポート終了 16
© ZOZO, Inc. 既存課題と要件の対応 • ビジネスロジックの複雑化に伴う機能追加の労力の増大 ◦ モジュラーモノリスに加える • 障害の分離が出来ず、単一障害点になってしまっている
◦ 将来的にマイクロサービス化を検討するためにテーブルの使用箇所を可視化する • Classic ASPのサポート終了 17
© ZOZO, Inc. 既存課題と要件の対応 • ビジネスロジックの複雑化に伴う機能追加の労力の増大 ◦ モジュラーモノリスに加える • 障害の分離が出来ず、単一障害点になってしまっている
◦ 将来的にマイクロサービス化を検討するためにテーブルの使用箇所を可視化する • Classic ASPのサポート終了 ◦ 言語をASPからJavaに変える ◦ テストコードを追加してデグレを起こさないようにする ◦ 言語を変えても既存と等価であることを担保する 18
© ZOZO, Inc. 入荷リプレイスの進め方 19
© ZOZO, Inc. 段階リリースの流れ 入荷リプレイスの全体像 20 フェーズ1 ビジネスロジックAPI化 フェーズ3 マイクロ
サービス 化 フェーズ2 フロント エンド メリット • フェーズ定義毎にリリースを行うことで大きな問題を起こしにくい状態になる • リプレイスのゴールを途中で変更することができる リリース リリース
© ZOZO, Inc. • ASPで実装しているビジネスロジックをJavaAPI化する • JavaAPIは、既に存在しているモジュラーモノリスに実装する • Javaから基幹DBに参照・更新ができるようにする •
逆にASPからの基幹DBへのアクセスはしないようにする フェーズ1の定義 21 モジュラーモノリス モノリス BackOffice(ASP) 入荷API(Java) 基幹DB フェーズ1 フェーズX フェーズ2 モノリス フェーズ1 実施 BackOffice(ASP) ユーザー 基幹DB ユーザー 発送API(Java) view ロジック ビジネス ロジック view ロジック ビジネス ロジック
© ZOZO, Inc. フェーズ2の定義 • 入荷用のフロントエンドを実装する • オンプレ依存は基幹DBだけとなる このフェーズまで来ると脱ASPが完了する。 22
AWS(モジュラーモノリス) モノリス ユーザー 基幹DB 入荷用 フロントエンド フェーズ1 フェーズX フェーズ2 フェーズ 2 実施 モジュラーモノリス モノリス BackOffice(ASP) 入荷API(Java) 基幹 DB view ロジック ビジネス ロジック view ロジック ユーザー 発送API(Java) 入荷API(Java) ビジネス ロジック
© ZOZO, Inc. フェーズ1の話に少し戻ります 23 フェーズ1 フェーズX フェーズ2
© ZOZO, Inc. DBアクセスする処理のインターフェースにマーカーインターフェースを継承させることで、処理単 位の参照テーブルや更新テーブルがIDEで検索できるようにした。 実装を進めながら処理単位での参照・更新を機械的に整理することができる。 また、これをすることで将来的にDB分割が可能かどうか判断する材料を増やせる。 (データ観点で疎結合な部分を見つけやすくするため) ※マーカーインターフェースとは、メソッド定義を含まず、このインターフェースを実装するクラスが特定の属性を持っていることを示すためのもの 将来的なDB分割のためにCRUD整理
public interface HogeQueryDataSource extends hogeTable { boolean existsBy(Integer hoge); } 24 フェーズ1 フェーズX フェーズ2
© ZOZO, Inc. 等価比較の仕組みを導入 私の経験上、 「処理の等価性はどう担保するのか」は、言語リプレイスの大きな壁の一つであると考えている。 この問題に対して入荷リプレイスでは、機械的に等価性を判断してくれる自動テストの仕組みを導入 した。 自動テストをするためには、本来入力値と期待値が必要。 今回は本番環境のユーザー入力と既存システムの出力を使用してテストした。
この仕組みのおかげで普段よりも正確に、かつ膨大な量のテストをすることが可能になった。 また、本番環境の入力値を使用しているので、潜在的なバグが見つかるなどの嬉しい副産物もあっ た。 フェーズ1では、このようにして「処理の等価性を担保した」 25 フェーズ1 フェーズX フェーズ2
© ZOZO, Inc. 等価比較する 等価比較の仕組み〜取得系処理図解〜 26 本番リクエスト 比較用ファサード 旧実装 (ASP)
新実装 (Java) 期待値となる 処理結果 (JSON) 処理結果 (JSON) フェーズ1 フェーズX フェーズ2
© ZOZO, Inc. 等価比較する 等価比較の仕組み〜取得系処理図解〜 27 本番リクエスト 比較用ファサード 旧実装 (ASP)
新実装 (Java) 期待値となる 処理結果 (JSON) 処理結果 (JSON) フェーズ1 フェーズX フェーズ2 本番リクエスト/期待値(旧実装の値)となる 処理結果のペアで新実装の自動テストをしている Slack通知 DB登録 不等価
© ZOZO, Inc. 基幹DB 共通のIDと共にDBに履歴 を残す 等価比較の仕組み〜更新系処理図解〜 28 旧実装 (ASP)
新実装 (Java) 旧実装のSQL 実行履歴 (共通ID) 新実装のSQL 実行履歴 (共通ID) 本番リクエスト 比較用ファサード ※新実装の更新処理はコミットせずにロールバックする 全実行履歴の 等価比較バッチ 比較処理 Slack通知 比較結果のDB登録 ※旧実装の更新処理はコミットする 新旧実行履歴 フェーズ1 フェーズX フェーズ2
© ZOZO, Inc. 比較期間 : 取得系 1週間くらい 更新系 2週間くらい 不具合が出たら修正する
等価比較の仕組み〜等価比較中〜 29 フェーズ1 フェーズX フェーズ2 モジュラーモノリス モノリス BackOffice(ASP) 基幹DB ユーザー 発送API (Java) 不等価 入荷API(Java) 等価比較API (Java)
© ZOZO, Inc. 充分な検証が行われているので安心してAPI呼び出しのみに切り替えられる 等価比較の仕組み〜等価比較期間完了後〜 30 フェーズ1 フェーズX フェーズ2 モジュラーモノリス
モノリス BackOffice(ASP) 基幹DB ユーザー 発送API (Java) 入荷API(Java) 等価比較API (Java)
© ZOZO, Inc. 等価比較の仕組み〜メリデメ〜 [メリット] • 自動テストの入力値が本番の値なので本番運用後の不具合が出づらい • 本番運用前に本番環境でテストができる •
充分な検証の後なので安心して本番運用に新実装を乗せられる • エビデンスの用意に手間がかからない • 入力値や期待値の準備がいらない [デメリット] • 等価比較を実施すると処理量は増えるので本番環境に高負荷がかかってしまうことがある 31 フェーズ1 フェーズX フェーズ2
© ZOZO, Inc. まとめ 32
© ZOZO, Inc. まとめ このように段階的にリプレイスを進め、等価比較などを駆使した結果、安心安全にリプレイスを進め ることができました。 現状はフェーズ2に差し掛かっている状態です。 フェーズ2までは確実に行いますが、マイクロサービス化を進めるかどうかはまだ未定です。 ただし、この選択がそもそもできるのは段階的にフェーズを分けて、リプレイスを進めているからで す。
立ち止まり、進むか止めるか一度考えることができるのがこのリプレイスの最大のメリットです。 もし、自社システムのリプレイスを検討しているのであれば、 こういった方法でのリプレイスも選択肢の一つとして検討してもらえると嬉しいなと思います。 33
None