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