55
#ccc_f2 エンプラ開発における レガシーアプリケーションの 巻き取りとモジュール分割の戦い 2017/5/20 和田 一洋

2017spring jjug ccc_f2

Embed Size (px)

Citation preview

Page 1: 2017spring jjug ccc_f2

#ccc_f2

エンプラ開発におけるレガシーアプリケーションの

巻き取りとモジュール分割の戦い2017/5/20

和田 一洋

Page 2: 2017spring jjug ccc_f2

#ccc_f2自己紹介

和田 一洋(わだ かずひろ)

• グロースエクスパートナーズ(株)所属

• 大手SIerで6年間勤務ののち2015年にGxP入社

• http://qiita.com/khwada

1

Page 3: 2017spring jjug ccc_f2

#ccc_f2紹介するプロジェクト

• 金融系のコンシューマー向けWeb会員サイト(会員数:約60万)の受託開発

• 10名強のチームで開発

• 顧客情報システム部門と開発チームを支援する業務に従事

顧客情報システム部門

弊社開発チーム10名強

要件や方式の取りまとめ支援

設計や開発改善の支援

2

Page 4: 2017spring jjug ccc_f2

#ccc_f2今日の話(変化のスイッチ)

• 以前の自分• 勉強会に参加したり、技術書を読んでも、日々の開発にどう生かせるのか、どうしたら近づいていけるのか分からなかった

• エンタープライズ開発のあるある?

• つまり「変化のスイッチ」が分からなかった• 「こうあるべき」「こうなるべき」は分かっても・・・

• 「何をまず変えれば変化の歯車が回りだすのか」「現実的にどうすれば変わるのか」が分からない※ http://d.hatena.ne.jp/Chikirin/20090210

3

Page 5: 2017spring jjug ccc_f2

#ccc_f2今日の話

• 参画から2年間の取り組みを4つのフェーズに分けてご紹介(だいたい半年ずつ)

• 各フェーズで取り組んだことと、その「変化のスイッチ」について

参画開発モダン化

巻き取り段階的な再構築

いまココ!

モジュール分割OAuth2 Provider

ふりかえりブランチ運用

CI/CD

build pipelineAPI化

モジュール再分割

4

Page 6: 2017spring jjug ccc_f2

#ccc_f2

参画期

5

参画開発モダン化

巻き取り段階的な再構築

モジュール分割OAuth2 Provider

build pipelineAPI化

モジュール再分割ふりかえりブランチ運用

CI/CD

Page 7: 2017spring jjug ccc_f2

#ccc_f2参画のきっかけ

• 既存のベンダーさんが大規模案件に追われる中、「規模は小さいがスピード感が求められる」開発を進めるために参画。

• システムの中身はほとんど知らない状態。

• レガシーフレームワーク(Struts1系ベースの独自フレームワーク)上での開発、ソースの変更履歴をコメントアウトですべて保持、そして、ベンダーをまたがったソースコードマージ・・・

⇒モジュール分割

6

Page 8: 2017spring jjug ccc_f2

#ccc_f2モジュール分割

war

レガシーフレームワーク

アプリ1

WebLogic

DB

Apache

7

Page 9: 2017spring jjug ccc_f2

#ccc_f2

war

モジュール分割

• SpringMVCベースの新規アプリを作成

• 2つのwarをearに同梱してデプロイ

レガシーフレームワーク

アプリ1

war

Spring

アプリ2

ear

WebLogic

DB

Apache

session

war

レガシーフレームワーク

アプリ1

WebLogic

DB

Apache

8

/aaa /bbb

Page 10: 2017spring jjug ccc_f2

#ccc_f2モジュール分割

• 役割分担• アプリ1:引き続き既存ベンダーが担当

• アプリ2:GxPが担当

• 制約• インフラ部門との調整にかける時間がなかったため、モジュールをear同梱することでインフラ影響を最小化

• DBは共有、HttpSessionも共有

9

Page 11: 2017spring jjug ccc_f2

#ccc_f2モジュール分割

• 残った課題(後述)• アプリ2で「メニュー」を表示できない

• 各機能の認可判定が仕様/実装ともに複雑で、認可判定ロジック(メニュー生成ロジック)は簡単には呼び出しや移植ができなかった

10

各機能

コンシューマー

各機能

認可判定ロジック

アプリ1

アプリ2

Page 12: 2017spring jjug ccc_f2

#ccc_f2モジュール分割の効果

• 提携サービスとの連携をはじめるにあたり、OAuth2連携を導入

• Spring Security OAuth2を利用して、アプリ2上にOAuth2 Provider機能を開発

⇒レストランやホテルの予約サイトなど、様々な提携サービスに「XXXXXでログイン」がついた

⇒レガシーフレームワーク上では難しい機能を実現し、モジュール分割の効果を示すことができた

11

Page 13: 2017spring jjug ccc_f2

#ccc_f2変化のスイッチ

• レガシーフレームワーク上での開発はしたくない、従来の開発文化を引き継いではいけない、という想い

• やや強引に「モジュール分割する」と決めて、顧客を説得し、ジャンプをした

• 課題も出たが、次につながる結果を出せた

12

Page 14: 2017spring jjug ccc_f2

#ccc_f2

開発モダン化期

13

参画開発モダン化

巻き取り段階的な再構築

モジュール分割OAuth2 Provider

build pipelineAPI化

モジュール再分割ふりかえりブランチ運用

CI/CD

Page 15: 2017spring jjug ccc_f2

#ccc_f2ふりかえり

• 開発が軌道に乗ったタイミングから、定期的なふりかえりを開始

• 隔週(目標)でKPTを実施• 若手を含めたチーム全員が、日常の作業からいったん離れて、プロジェクトについて考え、意見を発信する場(付箋を利用した個人ワークを挟む)

• 現在では、開発チームが10名強に増えたため、毎回2チームに分けて、それぞれテーマを決めて実施

14

Page 16: 2017spring jjug ccc_f2

#ccc_f2ふりかえり

• KPT

15

Keep

よかったので続けたいこと

Problem

Try

次にやってみること

問題点

Page 17: 2017spring jjug ccc_f2

#ccc_f2

16

ふりかえり前回までのTry進捗状況の確認 全体 10分

Keep/Problem出し 個人 5分

Keep/Problemをチーム内共有 チーム 10分

Try出し 個人 5分

Tryをチーム内共有 チーム 10分

全体共有 全体 10分

Actionの選定 全体 10分

・挙がったTryからタスク化するものを選ぶ・残っている過去のTryも含めて優先度が高い10個程度のタスクに対して、ToDoラベルをつけて担当者を割り当て

Page 18: 2017spring jjug ccc_f2

#ccc_f2補足:Atlassianツール

17

Wiki/情報共有他の例)・Redmine・Qiita:Team

Issue Tracking System他の例)・Redmine・Backlog・GitHub issues

Gitリポジトリ他の例)・GitHub・GitLab

継続的インテグレーション(CI)他の例)・Jenkins・Travis CI・Circle CI

Page 19: 2017spring jjug ccc_f2

#ccc_f2ブランチ運用

• 課題• masterへのマージタイミングをはっきり決めていなかった• 社内テスト環境にリリースするとき?

• 顧客の環境にリリースするとき?

• 本番リリースするとき?

• 並行開発時のブランチ運用ルールが曖昧で、ブランチがぐちゃぐちゃになりかけていた

⇒Git-flowをベースとしたブランチ運用を導入

18

Page 20: 2017spring jjug ccc_f2

#ccc_f2ブランチ運用

master

develop

feature/YY案件親

feature/作業1

feature/作業2

feature/保守XX

hotfixPR

本番リリース

PR PR

PR

本番リリース

本番リリース

案件親ブランチ、または、developへのマージ時に、PR(ソースコードレビュー)

masterへは「本番」リリース時にマージ(本番リリース履歴を残す)

運用上 featureブランチに親子関係を持たせる(案件親ブランチ⇔各タスクのブランチ)

19

Page 21: 2017spring jjug ccc_f2

#ccc_f2ブランチ運用

• 新たな課題• 顧客側でのテスト期間が長く、なかなか

developをmasterへマージできない

• その間、次の開発を「案件親ブランチ」で運用するが、並行開発案件が多くなると「開発親ブランチ」の数が多くなり、リリース順も分かりづらい

⇒バージョン番号を導入

20

Page 22: 2017spring jjug ccc_f2

#ccc_f2ブランチ運用

• バージョン番号• リリース順に採番

• バージョン番号ごとのdevelopブランチを作成

• 採番ルール• メジャーバージョン:一定規模以上の案件

• マイナーバージョン:定期保守リリースなど

• リビジョン:緊急リリース

• 間に案件が入った場合、マイナーバージョンで間に挟み、一度決めたバージョンは変更しない

9.1.1メジャー

マイナーリビジョン

21

Page 23: 2017spring jjug ccc_f2

#ccc_f2ブランチ運用

master

develop/v10.0.0

feature/YY案件親

feature/作業1

feature/作業2

develop/v9.1.0

feature/保守XX

hotfix

v9.0.0 v9.0.1

feature/保守ZZ

v9.1.0 v10.0.0

22

Page 24: 2017spring jjug ccc_f2

#ccc_f2CI/CD(テスト自動化)

• ふりかえりでも、テストコードを書いてテスト自動化に取り組みたいという意見が多かった

• 一方、Excelにスクリーンショットを貼る形式でのテスト結果エビデンスの納品が必要

⇒テスト観点を整理

23

Page 25: 2017spring jjug ccc_f2

#ccc_f2CI/CD(テスト自動化)

• エビデンス納品対象のテストを「結合テスト」と定義• 単体テストは原則JUnit化

JUnitでテストしづらいところは、手動(打鍵)でテスト

• 結合テストは打鍵してExcelにスクリーンショットを貼りつけ、整形してエビデンスとするただしSelenide(Seleniumラッパー)を利用して、ブラウザオートメーションによる打鍵補助を導入

24

Page 26: 2017spring jjug ccc_f2

#ccc_f2CI/CD(テスト自動化)

テストフェーズ テスト観点 実施&レビュー方法

単体 validationや業務ロジックのパターン網羅/境界値テストAPI呼び出しの正常系/異常系

JUnit(DB読み書きや他システムAPIはモック)テストコードレビュー

画面単体 画面レイアウト/文言正常系/異常系メッセージの表示位置JavaScriptの挙動

打鍵Excelでのテストエビデンスのレビュー

結合 画面遷移会員やデータのパターンデータの登録更新パターンモジュール間を結合したシナリオ

打鍵(Selenideによる打鍵補助)Excelでのテスト設計/テスト結果のレビュー

25

Page 27: 2017spring jjug ccc_f2

#ccc_f2CI/CD(テスト自動化)

• レビューアに優しいテストコード 例)validation

• 画面入力1項目ごとにグルーピングして階層化@RunWith(Enclosed.class)

• テストメソッド名は日本語に

26

Page 28: 2017spring jjug ccc_f2

#ccc_f2CI/CD(テスト自動化)

• 次のステップ• 外部仕様に対するテストコード

• 実装ロジックをなぞるテストコードは、プロダクトコードを直すときは必ずテストコードを触ることになる

• 改修時のデグレ防止、実装後のリファクタリングの自由度を上げられるテストコードに

• E2Eテストの自動化• selenideの資産を活用

• 主要なシナリオに限って回帰テストを定期自動実行

27

Page 29: 2017spring jjug ccc_f2

#ccc_f2CI/CD(テスト環境デプロイ)

成果物

成果物

ソースコード

WebLogicコンソール

デプロイ

成果物

push

テスト環境

pull

当初、ローカルでbuild、デプロイは手作業で実施

28

Page 30: 2017spring jjug ccc_f2

#ccc_f2CI/CD(テスト環境デプロイ)

• 課題• デプロイの手作業が煩雑

• 並行開発が増え、テスト環境が増えるとさらに煩雑

• テスト環境にデプロイしようとしてbuildするまで、JUnitテストをまとめて実行するタイミングがない

⇒Bambooを導入

29

Page 31: 2017spring jjug ccc_f2

#ccc_f2CI/CD(テスト環境デプロイ)

成果物

ソースコード

デプロイ

push

v9.0.0

テスト環境1

v9.0.1

テスト環境2

v9.1.0

テスト環境3

v9.2.0

テスト環境4

Trigger

pushをtriggerにbuildが走り、JUnitが落ちるとメール通知

デプロイの開始/終了を通知

30

Page 32: 2017spring jjug ccc_f2

#ccc_f2CI/CD(テスト環境デプロイ)

31

各環境にデプロイされているブランチを画面上で一覧参照

環境を選んで、build対象の/build番号を指定してデプロイ

Page 33: 2017spring jjug ccc_f2

#ccc_f2変化のスイッチ

• ふりかえりを起点に、手の届く範囲から地道な改善を積み重ねた• 参画期に、スピードを優先して進めた部分を見直して足場固め

• 自分たちでプロジェクトを改善できるという実感を得た

• 「自動化」という当たり前のことも、取り組んでいくと、教科書的な話だけでない次の課題やステップが見えてくる = チームの成長

32

Page 34: 2017spring jjug ccc_f2

#ccc_f2

巻き取り期

33

参画開発モダン化

巻き取り段階的な再構築

モジュール分割OAuth2 Provider

build pipelineAPI化

モジュール再分割ふりかえりブランチ運用

CI/CD

Page 35: 2017spring jjug ccc_f2

#ccc_f2巻き取り

• 参画から1年が経過したころ

• 諸般の事情により、レガシーフレームワーク上の「アプリ1」の保守開発も巻き取ることに

34

Page 36: 2017spring jjug ccc_f2

#ccc_f2巻き取り

• 課題:「アプリ1」のビルド方法・・・• 本番のwarを解凍し、リリース対象のclassファイルを入れ替えて、圧縮しなおすことでwarを作成して、リリースしていた

• テスト環境/本番環境の環境差異はコメントアウトで切替

• リリース時のミスも頻発・・・

⇒巻き取りに際してビルド改善の工数を確保していただいた

35

Page 37: 2017spring jjug ccc_f2

#ccc_f2build pipeline

• 「アプリ1」をgradleでビルドできるように• 環境ごとの差異は設定ファイルに追い出して、設定値でふるまいを変えるように改修

• ソースコードとビルド成果物を1:1に

• 地道に検証• gradleでbuildしたwarの中身を逆コンパイル

• 本番環境のwarの中身を逆コンパイル

⇒diffを取り、意図しない差異がないかを検証

36

Page 38: 2017spring jjug ccc_f2

#ccc_f2build pipeline

アプリ1push アプリ1trigger

war

アプリ2

trigger

build

push trigger

deploy

アプリ2

ear

37

Page 39: 2017spring jjug ccc_f2

#ccc_f2API化

• 「アプリ1」を巻き取ったことで、全体最適の視点で機能配置を考えられるように

• 2つのアプリの疎結合化に着手

• アプリ間連携をRest API化• HttpSession経由での新たな共有はしない

38

Page 40: 2017spring jjug ccc_f2

#ccc_f2API化

• 参画期の残課題だった「認可判定ロジック」を移植してAPI化

• 「アプリ2」でもメニューを表示できるように

各機能

コンシューマー

各機能

認可判定API

認可判定ロジック

移植

アプリ1

アプリ2

39

Page 41: 2017spring jjug ccc_f2

#ccc_f2変化のスイッチ

• 開発モダン化期で自動化をしていたからこそ、その流れに乗せることを前提にできた• 継続開発で顧客との築いてきた信頼関係が前提

• 各活動の意義を理解していただき、各案件や保守の中で少しずつ工数を使わせていただいた

• 「アプリ1」に手を出せるようになったことにより、部分最適から全体最適へ視点が変わった

40

Page 42: 2017spring jjug ccc_f2

#ccc_f2

段階的な再構築期

41

参画開発モダン化

巻き取り段階的な再構築

モジュール分割OAuth2 Provider

build pipelineAPI化

モジュール再分割ふりかえりブランチ運用

CI/CD

Page 43: 2017spring jjug ccc_f2

#ccc_f2段階的な再構築

• 顧客内でレガシーフレームワークの撤廃が求められるように

• 合わせて画面リニューアル、スマホ最適化方式の見直しなどを進めたい

• ただし、移植中の案件凍結はなるべく避けたい

⇒各開発案件内で、改修対象機能を「アプリ2」に移植していく方針に(段階的な再構築)

42

Page 44: 2017spring jjug ccc_f2

#ccc_f2段階的な再構築

機能1

機能2

機能3

機能4

機能5

機能1

機能2

機能3

アプリ1 アプリ1 アプリ2

機能4

機能5

アプリ2

機能1

機能2

機能3

もともと 現在 移植完了後…?

43

レガシーフレームワーク

レガシーフレームワーク Spring Spring

Page 45: 2017spring jjug ccc_f2

#ccc_f2モジュール再分割

• これでは、新しく、別のモノリシックなアプリケーションを作っているだけ・・・

• とはいえ、分割すればよい、というものでもない

⇒改めて、「このプロジェクトにおけるモジュール分割の意味」を考えた

44

Page 46: 2017spring jjug ccc_f2

#ccc_f2モジュール再分割

• 当初は「ベンダー」切り口でのモジュール分割• ベンダーをまたがったソースコードマージを避ける

• 1社体制になった今のモジュール分割• 複数案件並行開発時のマージを最小化

• 改修時の影響調査/リグレッションテスト範囲を局所化

• (将来的に)モジュールごとに非機能要件を分ける

45

Page 47: 2017spring jjug ccc_f2

#ccc_f2モジュール再分割

• 新規アプリへの切り出し• CRUD対象テーブルが比較的独立しており、同時に改修が入るケースが多い機能群

• 方式• 引き続きearに同梱(インフラの見直しは、

H/W保守切れのタイミングまで待つ)

• メモリ上でのHttpSession共有はしない(疎結合化)

• Oracle DBへのconnection数の増大を防ぐために、weblogicのconnection pool管理を利用

46

Page 48: 2017spring jjug ccc_f2

#ccc_f2モジュール再分割

アプリ1

レガシーフレームワーク

アプリ2

認可判定

Spring

各機能 各機能

アプリ3

Session管理

Spring

各機能

Session管理

Session管理

Session管理(DB)

コンシューマー

cookie

47

再分割後

Page 49: 2017spring jjug ccc_f2

#ccc_f2

サービス

モジュール再分割

アプリ1

レガシーフレームワーク

アプリ2

認可判定

Spring

各機能 各機能

アプリ3

Session管理

Spring

各機能

Session管理(DB)

コンシューマー

cookie

将来像(仮)

48

Spring

各機能

Page 50: 2017spring jjug ccc_f2

#ccc_f2変化のスイッチ

• 「一括再構築」はリスクも高く、案件凍結が必要になるため避けたい。⇒これまでの実績から「段階的に進める」という提案ができた⇒再構築の効果も、早期から段階的に得られる

• 「マイクロサービスアーキテクチャ」という世のトレンドを、自分たちのプロジェクトに引きつけてどうしていくべきか考えた

49

Page 51: 2017spring jjug ccc_f2

#ccc_f2

まとめ

50

Page 52: 2017spring jjug ccc_f2

#ccc_f2まとめ

51

参画期

強い思いでジャンプ⇒モジュール分割

開発モダン化期

ふりかえりを起点に地道な改善・デファクトに乗る・ブランチ管理・自動化⇒次のジャンプの土台

巻き取り期

自動化を土台にして新たなジャンプ⇒全体最適への視点の変化

段階的な再構築期

「段階的」に進める⇒世の中のトレンドを自分たちのプロジェクトにひきつけて「アプリ分割」

外発的 内発的

Page 53: 2017spring jjug ccc_f2

#ccc_f2まとめ

• 内発的なスイッチ• ふりかえりを起点に、手の届く範囲から改善

• 自分たちでプロジェクトを改善できる、という実感を得る

• 取り組んでいくと、教科書的な話だけでなく、次の課題やステップが見えてくる = チームの成長

• 外発的なスイッチ• 世の中のアーキテクチャ/技術トレンドの変化、新しいツールの普及(「当たり前」が変わっていく)

• やや(?)無茶な要件やスケジュールを真剣に考えてみる機会が、ブレークスルーを生むことも

52

Page 54: 2017spring jjug ccc_f2

#ccc_f2まとめ

• 内発的なスイッチ• 自分たちでコントロールできる

• 外発的なスイッチ• 自分たちでコントロールできない

• ただし、チームがちゃんと準備をしていれば、チャンスが訪れたときに掴むことができる

• 準備 = 社内外の勉強会などを通して世の中のトレンドを知る。知るだけでなく、触ってみて、自分たちのプロジェクトに引きつけて考える。

53

Page 55: 2017spring jjug ccc_f2

#ccc_f2

54

ありがとうございました。