リファクタリングを文化にする 〜組織が技術的負債と向き合うワークショップ〜

皆さんこんにちは。 CTO-Office の香川とEC開発-Bグループの竹原です。

11/28に 和田卓人氏(id:t-wada)を講師としてお招きしてテストとリファクタリングのためのワークショップを開催いたしました。 技術者正社員のうちプログラミングをすることの多いメンバー全体の約1/3にあたる総勢53名が参加しての開催となりました。

本記事ではまず第一弾としてワークショップの概要や目的、全体の流れについて簡単にご紹介いたします。 また第二弾(2024年1月公開予定)では、運営とワークショップの問題の作問に関わったメンバーにそこでの学びや実践について紹介いただきます。

開催に至った経緯とMonotaRO DOJO

まず今回のワークショップの開催に至った経緯と MonotaRO DOJO についてご説明します。

MonotaRO DOJO とは

このワークショップはMonotaRO DOJOという研修プログラムの一環で開催されました。 DOJOでは、アジャイル研修や業務モデリング研修などを行っており、今回は テストとリファクタリングに焦点を当てたものとなっています。

社内の課題とワークショップの目的

MonotaRO はサービスを提供開始してから20年になり、それを支えるシステムも古いところでは15年以上同じコードベースに改修を重ねています。 その間に事業やシステム、組織などさまざまなものが拡大し変化してきましたが、特に組織については現状様々なバックグラウンドを持ったメンバーが開発に携わっています。 また創業当初から15年以上に渡って改修を続けられてきたシステムには、やはりアーキテクチャやコードのクオリティといった観点から改善の余地が多くあります。 ですが、バックグラウンドや既存システムの知識などが異なるメンバー間では、改善の優先度や進め方などの前提が揃いにくく、継続的に改善をすすめるには様々な課題がある状態でした。

tech-blog.monotaro.com

今回のワークショップを含むDOJOの目的は、そういったバックグラウンドの異なるメンバーを含む組織全体で、改善を行っていくための共通認識を形成し、改善のための具体的なスキルを組織として獲得することです。

開催経緯

もともと先述のような課題感と目的のもと、我々がシステムや業務の改善をすすめる上で必要になる「ソフトウェアエンジニアリングスキル」の一覧を定義し、それぞれに対して研修コンテンツを用意しようと考えていました。 当初は社内メンバーだけでこの「ソフトウェアエンジニアリングスキル」の一覧を決定しようとしていましたが、異なるバックグラウンドを持つメンバーが共に働くための共通認識とするには、より一般的で広範な視点を取り入れることが重要と考え、すでにご支援いただいていた和田卓人氏に相談しました。

議論の当初では DORAの DevOps Capabilities (https://dora.dev/devops-capabilities/) などを参考にしようと考えていました。 これらはもちろんどれも重要なことですが項目数も多く、このままではメンバーの具体的な課題感とはギャップがあります。 実のある研修とするには、眼前の課題と向き合うためのメンバーのモチベーションを引き出し、着実にスキルを身につけるものになっている必要があります。

和田卓人氏を交えこのような議論を進める中で、実際に開発を行っているメンバーと共に研修を企画し進めることで、本当に今我々が必要としている「ソフトウェアエンジニアリングスキル」とそれを向上させるための取り組みの形が見えてくるのではないかというアイデアが生まれ、今回の研修を企画するという運びとなりました。

ワークショップの全体像と開催までの段取り

ワークショップの全体像

概要

研修は実践しながら学ぶことで身に定着させることを目的としたかったため、ワークショップという形式で行うことになりました。 monotaro.com のサービスの本番で実際に稼働しているコードの一つを題材として選定し、それに対しどうテストを書き、リファクタリングするかという形をという形式をとることにしました。 前半と後半の2パートからなり、前半でまず運営メンバーによるライブコーディングによって見本をみせ、後半から参加者自身でそのライブコーディングの続きという形でリファクタリングをすすめるということを行いました。

以下が実際のタイムテーブルになります。

タイムテーブル

タイムテーブルの通り、ほぼ一日をかけて行いました。 前半となる午前中は概要の説明とライブコーディングで実際にテストのカバレッジを確認、維持しながらリファクタリングを行うという見本の実施と解説、後半となる午後にはその続きを参加者でチームに分かれて行いました。

時刻 内容
9:30 開会式
 ・はじめに
 ・開催趣旨説明
 ・t-wada さん/作問チーム紹介
 ・本日の流れの説明
 ・t-wadaさん ショート講演
  ・「実業務コードを用いたソフトウェア開発研修」
9:45 必要な環境の説明
 ・実行環境確認
 ・テストの実行方法
9:50 コードの現状説明
 ・リファクタリングの内容
10:10 午前-ライブコーディング1
 ・責務の分離
 ・テストのサイズダウン
11:10 休憩
11:20 午前-ライブコーディング2
 ・リポジトリパターンの実装(コードの移植)
 ・ユニットテストのモック適用方法の変更
12:00 お昼
13:00 ワークショップの準備(参加者全員でやってみる)
 ・カバレッジの取得
13:15 午後-ワークショップ
 ・ライブコーディングの続きのリファクタリング
 ・t-wadaさんへの質問なども随時(オフラインにて)受付
16:30 作業内容の発表
 ・1チーム10分×4~6チーム
16:50 閉会の挨拶
 ・t-wadaさん
 ・作問チームメンバーから
17:00 午後の部 終わり
 ・クロージング
 ・アンケート

開催までの段取り

開催にあたっては様々な準備を行いました。その準備の段取りについても簡単にご紹介いたします。

段取りの全体
日程 実施したこと
6月 全体の構想
7月~8月 ワークショップの題材(MonotaROのコード)選び
9月~10月 実際にリファクタリングを行う
10月末 ワークショップのコンテンツとしてまとめ直し
当日開催のための準備(参加メンバーの決定やアナウンス、会場確保など)
11月~ 当日の説明だけでは不安なところを別途コンテンツとして用意し、勉強会として実施の準備
11月 上旬 コンテナ/Dockerまわり
11月 中旬 題材となるコードの概要の説明とワークショップで前提となる知識についての説明
11月 下旬 開催

ワークショップ題材をどのように決めたか

我々が日々感じている課題感として下記の2つがありました。

  • 不具合が怖くて変更したくない複雑性の高いプロダクトコード
  • 機能改修の際にテストコードの作成・修正に時間がかかる

和田卓人氏にいくつかのプロダクトコード・テストコードを見ていただく中で我々のコードの特徴としてプロダクトコードとの結合度の高いテストコードになっているという事が分かりました。いわゆる「リファクタリング耐性が低い」という状態です。これにはプロダクトコードの問題とテストコードが書かれた背景が関係していました。まずプロダクトコードとしては様々な処理を一つのクラスに書いている神クラスという状態。そこに対してユニットテストが書かれたのですが、プライベートメソッドに対してユニットテストを書きパブリックメソッドに対してはその先のプライベートメソッドや別クラス呼び出し部分を全てモック化するという方式が採用されていました。当時PythonのEOLの対応において前後比較のために作成されたのですが、とにかくカバレッジを100%にすることを目的として、プライベートメソッドも含めた各メソッドに対してテストを書いていくこの方式が対応しやすかったのだと考えられます。そのためプロダクトコードを変更しようとするとユニットテストも大量に修正する必要があり時間がかかる。ユニットテストが壊れるためリファクタリングしにくく、リファクタリングされることなく追加のコードが書かれていくためより複雑性が増していく。という前述の課題感に繋がっていたということです。 これを解決するため、どのように「リファクタリングを支えるテストにしていくのか」をワークショップのメインテーマとすることに決めました。

その他ワークショップとして考慮した観点は下記になります。(カッコ内はその観点を入れた意図)

  • MonotaROのレガシーコードによく見られる複雑性を複数種類含む(ワークショップ後に各チームのプロダクトコードで同様に実践してもらえる)
  • 全体のサイズとして大きすぎない(半日のライブコーディングである程度完成し、成功体験を得られるサイズ)
  • テスト環境はある程度そろっている(環境構築からとなると作問チームに負担がかかるため)

研修の様子

当日は和田卓人氏も含めすべての参加者は弊社の梅田サテライトオフィスに集まりオフラインで研修を実施しました。

ライブコーディング(午前パート)

和田卓人氏によるショート講演とその後、作問チームのメンバーのぺアプログラミングの形式でリファクタリングを実演していきました。この午前パートでは和田卓人氏と作問チームメンバーは会議室からZoomにて配信するという方法で実施しました。

ライブコーディング中にはSlackの実況スレッドにて参加者からの質問や和田卓人氏による解説など活発に議論が交わされました。メインテーマについての話題では共感と納得感で盛り上がりました。

リファクタリング実践(午後パート)

午後パートのリファクタリング実践では参加者が各チーム(2〜5名)に分かれてぺア/モブプログラミングの形式で午前パートの続きのリファクタリングを進めました。和田卓人氏と作問チームメンバーは各チームを回り疑問の解消などのサポートを行いました。リファクタリングのお題としては事前に作問チームで準備していたものや各チームで検討したものなど自由に設定してよいことにしていましたが、作業内容の発表においては各チームがそれぞれの視点で改善点を見つけ、クラス同士の依存を減らしたり、モデルを型定義するなど、リファクタリングとテストコードの作成を進めていました。

研修の結果

研修アンケートの結果

  • アンケートに回答いただいた全員が「よかった」と評価していただきました。
  • 特に今回のワークショップの内容を実際のコードで活かせそうかという点において90%以上の方が「活かせそう」と回答いただいており題材の設定は成功でした。
  • コメントの内容も作問チーム側で期待していた学びとなっており、想いは伝わったようです。

企画側の感想

実業務コードを使ったワークショップでしたので特にレガシーコードと戦っているメンバーには具体的な改善方法を理解いただけたと思います。アンケートでも各チームのプロダクトコードに対して活かせる内容だったという回答も多く、今回の研修で学んだ事を各チームがそれぞれの担当のプロダクトコードに当てはめて実践してほしいと考えています。(その為の次なるプランも検討中です。)触ることを恐れず普段の機能開発の一環で安全にリファクタリングしていけるよう、それを実現できるテストコードにしていくという取り組みに繋がることを期待しています。効果として現れるのはまだ先になるとは思いますが、アジリティの高い開発チームへの一つの糧になれば幸いです。

最後に

今回のメインテーマはリファクタリング耐性の低いテストコードに対してどのようなアプローチでリファクタリングをしていくのか、またリファクタリングを支えるテスト群にしていくのか、という点でした。これらの詳細についてはワークショップ実施レポート第二弾にてご紹介いたします。