モノリス化したコード・組織の両方を分割して アーキテクチャを改善する / Developers Summit 2023 Summer
by
Kaiichiro Ota
Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
モノリス化したコード・組織の両方を分割して アーキテクチャを改善する 前田浩邦 太田絵一郎 内山武尊 サイボウズ kintone開発チーム 2023/07/27 Developers Summit 2023 Summer 1
Slide 2
Slide 2 text
kintone ▌業務システムを自分たちで作成 ⚫ 案件管理、顧客管理、など ▌2011年 サービスの提供開始 ⚫ 導入 30,000社 (2023年6月末) 2
Slide 3
Slide 3 text
本発表の内容 3 モノリス化した コード・組織 肥大化したコード、 複雑化の進行 停滞感、 プロセスの重さ 1. コード分割 2. チーム分割 複雑化の抑制、 モノリス化を防ぐ オーナーシップの芽生え、 チーム独自のプロセス改善 継続的に発展できる コード・組織へ 3. 両分割の連携 kintoneチームの アーキテクチャ改善
Slide 4
Slide 4 text
発表者について ▌前田 浩邦 (マエタ ヒロクニ) ⚫ 基盤チーム プログラマ ⚫ コード分割について発表 ▌太田 絵一郎 (オオタ カイイチロウ) ⚫ 新機能開発チーム マネージャー ⚫ チーム分割について発表 ▌内山 武尊 (ウチヤマ タケル) ⚫ 新機能開発チーム プログラマ ⚫ 各分割のふりかえり、連携について発表 4
Slide 5
Slide 5 text
1. コード分割 5
Slide 6
Slide 6 text
コード分割の背景 ▌コードの肥大化、複雑化 ⚫ kintoneはリリースして10年、継続してサービス提供 ⚫ コードに関しては初期のモノリスの状態のまま開発 ▌分割前のコードの状態 ⚫ サーバーサイド: src/main/java下 ≧ 350,000行 ⚫ フロントエンド: src/main/js下 ≧ 370,000行 ⚫ あらゆるコードの修正がし放題 6
Slide 7
Slide 7 text
コード分割の背景 ▌開発効率の低下 ⚫ 可読性の低下、機能追加の際に影響範囲の確認が大変 ⚫ オンボーディングに時間がかかる ▌改善活動をするも、限界を感じていた ⚫ 目についたコードをリファクタリングしたところで、残りは膨大 ⚫ このようなリファクタリングを、あと何回やればいいのか? ▌→ 抜本的な改善として、コード分割という取り組みを開始 7
Slide 8
Slide 8 text
コード分割とは ▌コードを以下のような状態にすること ⚫ 機能ごとにパッケージ・ディレクトリに分割 ⚫ 機能間で関わらないなら、コード間も関わらない、依存しない ▌機能に沿っていて、独立して理解可能なコードの塊を増やしていくこと で、開発の効率化を目指す ⚫ 分割してしまえば、膨大さを気にしなくて済む ⚫ バックエンドとフロントエンドの両方で進める 8
Slide 9
Slide 9 text
kintoneのアプリ ▌業務の数だけ作成 ⚫ 案件管理、顧客管理、など ▌簡単な“データベース” ⚫ 蓄積したデータはチームで共有 ▌データを蓄積する以外にも ⚫ ワークフロー、アクセス権、など 9
Slide 10
Slide 10 text
アプリ機能とアプリ設定機能 ▌アプリ機能: “データベース“にあるデータ (レコード) の表示、追加、編集 10
Slide 11
Slide 11 text
アプリ機能とアプリ設定機能 ▌アプリ設定機能: “データベース”の設定 11 登録するデータの形を設定
Slide 12
Slide 12 text
▌メンタルモデル: ⚫ どのような部分から構成され、どう関係し合ってるかという捉え方 ▌PMのメンタルモデルが、コード分割に違和感なく適用できるものだった コード分割の基準: プロダクトマネージャー (PM) のメンタルモデル 12 現場で業務をする人 (アプリを使う人) 情シス・業務リーダー (アプリを作る人) レコードを表示する アクセス権を変更する kintone アプリ機能 アプリ設定機能
Slide 13
Slide 13 text
▌ユーザーの属性が違うと、利用するkintoneの機能も異なってくる ⚫ 現場で業務をする人 (アプリを使う人) → アプリ機能 ⚫ 情シス・業務リーダー (アプリを作る人) → アプリ設定機能 ▌コード分割では、このようなメンタルモデルに、実際のコードを合わせる コード分割の基準: プロダクトマネージャー (PM) のメンタルモデル 13 現場で業務をする人 (アプリを使う人) 情シス・業務リーダー (アプリを作る人) レコードを表示する アクセス権を変更する kintone アプリ機能 アプリ設定機能
Slide 14
Slide 14 text
分割後に目指す状態 (サーバーサイド) 14 GetRecordController com.kintone.app UpdateAccessRight SettingController IAccessRightService AccessRight SettingDto com.kintone.appsettings AccessRight SettingService Impl RecordDto 共有モジュール 依存を禁止 アプリ機能 アプリ設定機能 RecordService
Slide 15
Slide 15 text
分割後に目指す状態 (サーバーサイド) 15 GetRecordController com.kintone.app UpdateAccessRight SettingController IAccessRightService AccessRight SettingDto com.kintone.appsettings AccessRight SettingService Impl RecordDto 共有モジュール 依存を禁止 アプリ機能 アプリ設定機能 RecordService 機能に対応するパッケージを作成 機能に属する全コードをパッケージに配置 機能の性質上関わらないならば、 コードでも関わらせない
Slide 16
Slide 16 text
分割後に目指す状態 (サーバーサイド) 16 GetRecordController com.kintone.app UpdateAccessRight SettingController IAccessRightService AccessRight SettingDto com.kintone.appsettings AccessRight SettingService Impl RecordDto 共有モジュール 依存を禁止 アプリ機能 アプリ設定機能 RecordService 機能の性質上関わりがあるならば、 現状は共有を許容
Slide 17
Slide 17 text
分割後に目指す状態 (フロントエンド) 17 RecordList Component RecordListPage js/app/components AccessRight SettingPage js/appsettings/components アプリ機能 アプリ設定機能 依存を禁止 GlobalHeaderComponent TableComponent 共有モジュール AccessRight Component JS API
Slide 18
Slide 18 text
分割維持のための依存監視 ▌依存が守られているかを確認するテストを作成 ⚫ サーバーサイド: ArchUnitを使って依存のルール定義 ⚫ フロントエンド: 依存をチェックするスクリプトを自作 ▌テストをCIで実行することで依存を監視 ⚫ 意図しない依存が入り込めばテストが落ちる ▌→ 常に意図通りの分割された状態を維持できる 18
Slide 19
Slide 19 text
現在(2023年7月)の分割の状況 ▌分割の考え方やコード構成、チェックスクリプトなどのツールは整備済み ▌誰でも分割に取り組める状態になっている ▌全体のコードに対する分割されたコードの割合 (行数で計算) ⚫ サーバーサイド: 約10% (約36,000行) ⚫ フロントエンド: 約15% (約50,000行) 19
Slide 20
Slide 20 text
コード分割を実際にやってみての学びと変化 20
Slide 21
Slide 21 text
コード分割で得られた効果 ▌凝集度の向上と複雑化の抑制 ▌既存コードを変更したときの影響範囲の確認を容易にする ▌モノリス化を防ぐ 21
Slide 22
Slide 22 text
分割による凝集度の向上 22 画面A アプリ設定 画面 共通モジュール アプリ設定 専用処理 画面A アプリ設定 画面 共通モジュール アプリ設定 専用処理 アプリ設定機能 依存を 禁止 ▌共通モジュールにアプリ設定専用処理が書かれていた 機能ごと分割することによって凝集度が向上し、可読性が改善
Slide 23
Slide 23 text
複雑化の抑制 23 画面A アプリ設定 画面 共通モジュール アプリ設定 専用処理 画面A アプリ設定 画面 共通モジュール アプリ設定 専用処理 アプリ設定機能 依存を 禁止 ▌共通モジュールに画面専用処理を書くような 凝集度を下げる変更を無意識にやりがち 依存関係を監視することで、複雑化を抑制する
Slide 24
Slide 24 text
モノリス化を防ぐ 24 メソッドA メソッドB アプリ設定機能 アプリ機能 モデル1 抑制できた依存 チーム内で依存関係を議論することでモノリス化を抑制 ▌既存のユーティリティクラスにメソッドを追加 ▌他機能で依存が増えていることをCIで検知 ▌修正内容が他機能に入ることの妥当性を議論
Slide 25
Slide 25 text
振り返り - コード分割 ▌効果 ⚫ 凝集度の向上と複雑化の抑制 ⚫ 既存コードを変更したときの影響範囲の確認を容易にする ⚫ モノリス化を防ぐ ▌課題 ⚫ コード分割の加速 ⚫ 分割したコードにオーナーシップが必要 ⚫ 元に戻さないために機能の境目を意識し続ける必要がある 25
Slide 26
Slide 26 text
2. チーム分割 26
Slide 27
Slide 27 text
「チーム分割」以前の体制 ▌kintoneの新機能開発チーム ▌Large Scale Scrum (LeSS) ベースの複数チーム開発 ⚫ エンジニア3〜4名/チーム × 4〜6チーム ⚫ 全員がプロダクト全体を作る ⚫ 柔軟にリソース配分できるメリット ⚫ ここをやるぞ!となったらリソース一点集中できた ▌チームをスケールしつつ、大小の機能アップデートをコンスタントに毎月リ リースしてきた 27
Slide 28
Slide 28 text
少しずつ起きてきたこと 28 具体的に何が起きていた? スムーズに開発が進まないことが 増えた? ふりかえりの雰囲気が重い チームの魅力が薄いのでは
Slide 29
Slide 29 text
チーム体制の問題分析 ▌育成・キャッチアップに時間がかかる ▌関わる人が多く、改善・意思決定が進めづらい ▌作ること(How)で精一杯、Why/Whatはほぼプロダクトマネージャーのみが考える 29 ▌根本原因のひとつ:全員が全体を作る体制 ⚫ 開発する上で知る/考慮することが多い(認知負荷が高い) ⚫ 全員が全体のオーナーを持つ状態 ▌長年かけて、機能/仕様は徐々に複雑化 開発スピード・自律性・モチベーションの低下
Slide 30
Slide 30 text
「チーム分割」の提案 ▌目的:認知負荷を減らし、チームの自律性を高めること ⚫ 自律性 = 内発的動機付けの要素 ⚫ Ref. モチベーション3.0(ダニエル・ピンク) ⚫ プロダクトの持続的成長には、開発スピード・モチベーションどちらも重要 ▌何を変えるのか? ⚫ 「全員が全機能を作る」をやめて、チームごとに担当領域を持ち分担 ⚫ スクラムマスターを置く(長らく不在だった) 30
Slide 31
Slide 31 text
担当領域の決め方 / チームの再設計 ▌顧客に関するPMのメンタルモデルを第一の基準に ⚫ アプリを作る、アプリを使う、管理する、他システムと連携する、etc. ⚫ 仕事が偏らないか、過去のバックログアイテムを分類してシミュレートもした ▌4つの領域チーム体制 ⚫ アプリ設定⚙️ ⚫ アプリ🍮 ⚫ ナビゲーション/スレッド系🐤 ⚫ システム管理/外部連携🐰 31 ※絵文字はメンバーが付けた愛称です
Slide 32
Slide 32 text
「チーム分割」を段階的に進める ▌領域の切り方、チーム間の連携の仕方など、開始前はすべてが不確実 ⚫ 分担によるオーバーヘッドがメリットを上回るリスクもあった ⚫ 機能開発は極力継続したい ▌スモールスタートで、知見を得ながら徐々に変えていった 32 従来 2022/6〜10(シーズン1) 2022/10〜(シーズン2) (全体を全員で開発) チーム ⚙️ チーム 🍮 チーム 🐤 チーム 🐰 チーム ⚙️ (残りの領域を 全員で開発)
Slide 33
Slide 33 text
現在(2023年7月)のチーム体制 33 アプリ設定チーム ⚙️ アプリチーム 🍮 ナビゲーション/ スレッド系チーム 🐤 システム管理/ 外部連携チーム 🐰 各チームにエンジニア、QA、 スクラムマスターが所属 デザイン/ ドキュメント プロダクト マネージャー 全体スクラム マスター 各領域にフォーカスして動く人たち: 領域横断で動く人たち:
Slide 34
Slide 34 text
今回のチーム分割でやらなかったこと ▌技術カット(例:フロント/サーバー)では領域を分けなかった ⚫ 1チームで価値を届けられず、ほぼ常にチーム間の調整が必要となる ため ▌モノ(コード/サービス/DBなど)を事前に分割しなかった ⚫ 望ましいが、膨大な時間がかかる ⚫ 過去にマイクロサービス化を検討し、少なくとも短期では困難と判断した経験 もあった ⚫ 「モノから変える」ではなく「組織から変える」(≒逆コンウェイ戦略) ▌参考:「チームトポロジー」 34
Slide 35
Slide 35 text
チーム分割を実際にやってみての学びと変化 35
Slide 36
Slide 36 text
チーム分割で得られた効果 ▌担当領域の学習しやすさ、ノウハウ蓄積 ▌オーナーシップの実感 ▌チーム独自でのプロセス改善の促進 36
Slide 37
Slide 37 text
認知負荷が下がって機能の学習がしやすくなった ▌ほぼ全ての機能がカバー範囲だったため、幅広い知識が求められていた ⚫ 様々な機能の開発タスクがあるため学習が進みにくかった 37 ▌領域ごとに関連する開発タスクを集中的に担当 ▌社内外からの問い合わせに対して領域チームごとに対応
Slide 38
Slide 38 text
チームに新しく入ったメンバーによる改善活動が増えた 38 ▌ほぼ全ての機能がカバー範囲だったため、幅広い知識が求められていた ▌エンジニアの人数も多く影響が広いため提案しにくい ⚫ どこに注力すれば良いかが分かりにくい ▌領域が分割されたことで改善点が見つけやすくなった ▌領域チーム内で小さく始められるようになった
Slide 39
Slide 39 text
振り返り - チーム分割 ▌効果 ⚫ 担当領域の学習しやすさ、ノウハウ蓄積 ⚫ オーナーシップの実感 ⚫ チーム独自でのプロセス改善の促進 ▌課題 ⚫ 複数の領域に跨っている機能を修正するコスト増加 39
Slide 40
Slide 40 text
3. 両分割の連携 40
Slide 41
Slide 41 text
それぞれの活動の課題点(再掲) ▌コード分割 ⚫ 取り組みの加速 ⚫ コードのオーナーシップ ▌チーム分割 ⚫ チーム間の連携コスト ⚫ 複数の領域で対応が必要なタスクの分担 41
Slide 42
Slide 42 text
互いの活動を補完する 42 コード分割 チーム分割 共通部分を修正する機会を減らす 領域の理解を深める オーナーシップの実感 コード分割作業の加速
Slide 43
Slide 43 text
チーム分割がコード分割に与える効果 43 コード分割 チーム分割 オーナーシップの実感 コード分割作業の加速
Slide 44
Slide 44 text
▌仕組みを整えた直後は、コード分割は進んでいなかった ⚫ 2, 3人のメンバが週に1時間ほど集まって行うのみ ⚫ 分割するのも小さな機能に留まっていた ▌kintoneチームのメンバにヒアリング ⚫ やり方がイメージできなくて手を出しづらい ⚫ 優先順位が下がりがち コード分割トライアルプロジェクト (チーム分割 → コード分割) 44
Slide 45
Slide 45 text
▌コア機能かつ分割しやすそうな、アプリ設定機能の分割にチャレンジ (2022/11 ~ 2023/01) ▌目的 アプリ設定チーム⚙️ (アプリ設定機能のオーナー) による分割の学習 コード分割トライアルプロジェクト (チーム分割 → コード分割) 45 ▌アプリ設定機能のうち1/4を分割できた ▌プロジェクト終了後も分割を継続中 ▌チーム分割 → コード分割という形の補完
Slide 46
Slide 46 text
コード分割がチーム分割に与える効果 46 コード分割 共通モジュールの依存整理 他機能への影響の可視化・制限 領域の理解を深める チーム分割
Slide 47
Slide 47 text
互いの活動を補完する 47 共通モジュールの依存整理 他機能への影響の可視化・制限 領域の理解を深める コード分割 チーム分割 オーナーシップの実感 コード分割作業の加速
Slide 48
Slide 48 text
次に目指す姿: メンタルモデルに沿ったアーキテクチャ ▌プロセスを自主的に改善していける小さなチームが、機能ごとに独立した コードベースを所有している状態 48 アプリ設定機能 com.kintone.appsettings js/appsettings/components 情シス・業務リーダー (アプリを作る人) 現場で業務をする人 (アプリを使う人) アプリ機能 com.kintone.app js/app/components アプリチーム🍮 アプリ設定チーム⚙️
Slide 49
Slide 49 text
全体を通した学び・所感 ▌コードと組織の改善を独立に進めたのはよかった ⚫ 改善のやり方として、分割でうまくいくのかすらわかっていなかった ⚫ 独立で進めることで、それぞれが試行錯誤しやすかった ▌それぞれ改善が組み合わせることで課題点を補って更なる改善を期待で きる ▌個々の改善の積み重ねが、アーキテクチャ改善となっていきそう 49
Slide 50
Slide 50 text
まとめ ▌コード・組織のモノリス化が課題 ▌コード分割とチーム分割というアプローチを使い、それぞれの問題に独立 に取り組む ▌両分割の成果があがってきていて、両者の成果を連携した次の目標も 描けてきた ▌引き続きコードとチームの分割を通して、アーキテクチャを改善する 50
Slide 51
Slide 51 text
補足情報 ▌「コード分割」について ⚫ 技術ブログ記事 ⚫ https://blog.cybozu.io/entry/2023/03/14/110000 ⚫ JJUG CCC 2023 Spring 発表資料 ⚫ https://speakerdeck.com/hirokunimaeta/jjug-ccc-2023-spring ▌「チーム分割」について ⚫ DevOpsDays Tokyo 2023 発表資料 ⚫ https://speakerdeck.com/kaiichiro/fei-da-hua-monorisuhua- surupurodakutokai-fa-zu-zhi-wozi-lu-de-dexiao-sanatimuqun- nibian-eteiku-kintonekai-fa-timunoshi-li 51