初めに
kintoneチームの前田です。 kintoneはサーバーサイドがJavaで書かれていて、最近ではこれが結構な分量になっており開発上の障壁となっています。 その解消のため、機能毎にコードを分割して管理するコード分割という取り組みを進めています。 コード分割については以下の記事で紹介されています。
この度kintoneのアプリ設定機能のコード分割が完了しました。 アプリ設定機能は主にアプリの管理者が使う管理用の機能です。 kintoneのコア機能の一つでコード量も比較的大きな部分になっています。 分割完了後のコードの詳細や分割以降の取り組みについては、JJUG CCC 2024 Fallにおいて発表させていただきました。
今回の記事では、このような大きな機能のコード分割を完了させることができた要因について紹介します。 コード分割作業は、その機能を担当するチーム内の自律的な意思決定により、新規機能開発もしながら片手間に続けられていました。 大きな改善活動はマネージャーなどを巻き込み人と時間を集中的に投下するイメージがあるように思うのですが、今回のコード分割はそれと真逆です。 そこで、コード分割の完了にどのような要因があったのかチームメンバにヒアリングしました。 このヒアリングにより分かった要因を紹介しようと思います。
コード分割が始まってから終わるまで
アプリ設定機能のコード分割が始まったのは2022年10月からです。 2022年10月に、コード分割を複雑な機能に対して行うトライアルプロジェクトが始まりました。 この時に複雑な機能として選ばれたのがアプリ設定機能でした。 トライアルプロジェクトについても上述のブログ記事で紹介されています。
アプリ設定機能を担当しているチームは、kintoneチームでは「⚙チーム」という名前になっているので、以降も⚙チームと呼びます。 プロジェクト終了後も、⚙チームは毎日17~18時の一時間をコード分割の作業に当ててコード分割を続けました。 kintoneチームは通常の新機能開発の時間の他に、個人の改善活動を自由に行うことのできる時間があります。 ⚙チームのプログラマのうち3人が、この改善活動の時間のうちの一時間をコード分割に使う選択をしました。
アプリ設定機能は一つの大きな設定機能があるわけではなく、アクセス権の設定やカテゴリ設定など、たくさんの小さな設定機能の集合体です。 このような各種設定機能は全部で20弱あります。 コード分割は、今はアクセス権の設定を分割しよう、それが終わったらカテゴリ設定を分割しよう、というように、一つの設定ずつ進めていきました。 一つの設定を分割するには、一日一時間を使ってだいたい二週間ほどかかりました。
このような形でコード分割を毎日少しづつやり続けた結果、コード分割が最初に始まってから二年弱経過した2024年8月に、アプリ設定機能のコード分割が終わりました。 コード分割により分割された、アプリ設定機能を構成するコードの行数は約5.5万行でした。 これらのコードが現在では他の機能と独立して管理されるようになっています。
どうして一日一時間か
まず、新規機能開発をゼロにしてコード分割だけ行うことはできません。 アプリ設定機能はkintoneのコア機能であり、今でも頻繁に機能修正がなされているため、これが止まってしまうとビジネスに大きな悪影響を及ぼします。 したがって、コード分割をやるにしても新規機能開発と並列して、言わば片手間に行うことになります。
また、一日一時間ではなく、通常の新規機能開発タスクと同等に扱うやり方、 つまりアクセス権のコード分割をプロダクトバックログアイテムとして扱い、このアイテムに業務時間の全てを使う、 というようなものも試したことがあったのですが、これはやらなくなりました。 その理由はコード分割による負担が大きすぎるためだったようです。 コード分割では複雑化したコードの処理をくまなく追いかけ、分割できるレイヤーを見つけたり、 それができそうになければコードのコピーをしたりと、難しい意思決定をしなければなりません。 負債となったコードに触れ続けこういった意思決定をするのは一日一時間が限界ということでした。
このことは、ちょっと話がそれますが、負債を速く返済するには返済を早く始めたほうがいい、ということを意味しているのではないかと思っています。 というのも、コード分割は一日一時間が限界となっていたように、負債の返済速度には限界があるかもしれないためです。 アプリ設定機能のコード分割は2022年に始まって終わるまで2年弱かかりましたが、 例えば2012年に始まっていればコードも少なかったので半年かからず終わっていたかもしれません。
コード分割が完了した要因
コード分割が終了した後、コード分割が完了した要因について⚙チームにヒアリングしました。 ヒアリングした結果、どうやら以下の要因が浮かび上がってきました。
E-1: 一日一時間をコード分割に使うことができた
改善時間の確保は欠かせません。 というのも、改善時間なしに改善活動を行うことができないからです。 ⚙がコード分割をしている間は緊急の割り込みタスクなども特に入らず、改善時間を削らないといけない状況にはならなかったようです。 加えて、3人がモブプログラミングで取り組むことのできる状況だったため、一人が休んだとしても分割を進めることができました。
E-2: コード分割を継続できた
分割が終わったのは、一日一時間の分割作業を毎日継続できていたからです。 そこで、どうして継続できたのか、途中で飽きなかったのかについてヒアリングしました。
E-2-1: メリットを実感できていた
コード分割にメリットを感じており、それで継続できていたとのことでした。 コード分割により、自分達の担当するコードの可読性が上がり複雑度が下がっていくこと、目に見えてきれいになることが実感できていたようです。
新規機能開発においても影響範囲の把握が容易になる等のメリットを実感できていました。 コード分割をしていたメンバは新規機能開発も行っていて、その中では変更に対する影響範囲の確認が必要になります。 コードが分割されてない部分では呼び出し元のメソッドを芋づる式に辿っていくことになるので依存が追いづらいのですが、 分割されている部分ではパッケージレベルで明確に依存が切れているので、影響範囲の把握が容易になったようでした。
E-2-2: 月一の進捗確認があった
進捗確認ではこの一か月でどこまで進んだか、次の一か月でどこまでやるか、何か妨げはないかを確認していました。 それにより、例えば、先月と今月とで分割が終了した設定が増えていないということが判明した場合、 何か問題がないか (長期休みに入って人が足りない、作業が難しい機能だった) 確認でき、対処できるようにしていました。
⚙チームがコード分割に取り組んでいる間は毎月この進捗確認を行っていました。 アプリ設定機能は20弱ある小さな設定機能の集合体になっているので、 この一か月で2つ完了して合計15個まで積み上げた、残りあと5つだ、というような会話を毎月交わしていました。 このように進捗確認でゴールに近づいていることが実感でき、それが継続につながったようです。
E-3: 難易度が高すぎなかった
作業難易度が高すぎると、チーム内の改善時間だけでは手に負えなくなってきます。 実際⚙チームでコード分割ができるようになったのは、2022年10月のコード分割プロジェクトでコード分割の経験を積んだ後からでした。 このプロジェクトより以前にも⚙チームではコード分割にチャレンジしていましたが、 コードが難しいため改善時間の中で分割後の形を作ることができず、進んでいない状況でした。 プロジェクト終了後は参加メンバがプロジェクトでの経験を⚙チームに持ち帰ることで、チーム内の改善時間で分割を進められるようになりました。
E-4: 作業に慣れていき難易度が下がった
分割を続けていくうちに慣れていき、分割作業の難易度は下がっていきました。 それにより、それほど気負うことなく分割作業を進めることができるようになりました。 この点も、2年弱という長い間コード分割をし続けることができた要因になると思います。
アプリ設定機能は20弱ある小さな設定機能の集合体になっているので、 アプリ設定機能のコード分割とは小さな設定の分割の繰り返しです。 さらに、各設定機能の分割はどれも似たような作業になります。 実際、こちらのスライドにあるカテゴリ機能の分割後のコンポーネント構成と、こちらの記事にあるAPIトークン機能の分割後のコンポーネント構成は、ほとんど同じ構造になっていることが分かります。 このように似たような分割作業の繰り返しが作業の慣れにつながり、分割作業の難易度が下がっていきました。
『BIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?』という本では、エンパイア・ステート・ビルという高層ビルが驚異的な速さで完成した要因の一つとして、反復による上達が挙げられています。 エンパイア・ステート・ビルでは各階の設計を可能な限り同一に設計したおかげで作業員が同じ作業を反復することができ、これが上達につながりました 1。 アプリ設定機能の分割でもこれと同じことが起きたのだと思っています。
E-5: 同じメンバが作業をしていた
同じメンバがずっと固定で最初から最後まで分割を進めていたことも、 E-1からE-4に対してプラスに働いていたようなので、要因として挙げられると思います。 同じメンバがコード分割を続けることで、コードや作業に対する認識がメンバ間で揃います。 それにより、E-2-1で述べたコード分割のメリットはメンバ全員で認識が取れていましたし、 E-4で書いたような分割作業の慣れや練度向上にも寄与しました。
以上が、ヒアリングにより浮かび上がってきた要因になります。 ⚙チームがコード分割をしている最中は以上の要因がずっと揃っていました。 そのため、チーム内の片手間的な活動であっても大きな機能の分割を達成できたのだと考えています。
要因の応用
上記の要因はコード分割以外の大小さまざまな改善活動に適用できるように思います。 kintoneチームでは領域毎にサブチームを作り、それぞれ独自で新規機能開発や改善活動を行っています。 ⚙チームもこのサブチームの一つです。 サブチームの改善活動の進捗が滞っているとしたら、上にあげたE-1~E-5のどれかが欠けている可能性が高いです。 どれが欠けているか判明したら、それを補うアクションを設定すれば進捗の回復が期待できるはずです。
さらに、改善活動のあり方も幅広く考えられそうにも思います。 改善活動はサブチーム内で自律的に行えるものから、サブチームを超えたプロジェクトチームを組んで行うものもあります。 上に挙げた要因により、どういう改善の場合はどういう形態で進めればいいのか考えやすくなるように思います。 例えば難易度が高めの改善を進める場合、 まずは難易度を下げるような活動をサブチームを超えて有識者を交えたプロジェクトで行う、 それが終わったらサブチーム内に持ち帰って進めてもらう、というような進め方も考えることができるようになります。 このようにより効果が見込める進め方を考えることができるのではないかと思います。
改善活動だけでなくチームのあり方を考えることにも有用ではないかと思っています。 技術的な難易度が高い新機能を開発する場合も上記のようなプロジェクトチームを組むことがあります。 それにより難易度の高い機能もリリースされている一方で、プロジェクトチームを組むことにより安定させていたサブチームの構造が壊れてしまうという問題も生じています。 難易度を理由にプロジェクトを組んだ場合、別の言い方をすればサブチームには何等かの能力が不足しているということを意味していると思います。 そこで、もしサブチームの能力不足を補うようなアクション (学習を行う、専門家をサブチームに入れる) を設定することができれば、通常のタスクとして扱うことができるようになるかもしれないと考えられます。
また、逆コンウェイ戦略の実装についても学習が進んだように思います。 アプリ設定機能に⚙チームが割り当てられていたように、kintoneチームではkintoneの各機能にチームが割り当てられています。 このような方針でチームの役割分担を行ったのはチームトポロジーで紹介された逆コンウェイ戦略を狙ってのことでした。 チームをあらかじめ理想の構造にしておくことで、一部コードがそのような状態になりました。 すなわち、逆コンウェイ戦略でいわれていたことが起きていて、E-1~E-5はその要因にもなっていたのではないかと考えられます。
終わりに
⚙チームは片手間ではありながらも毎日少しづつコード分割を続けることで、最終的に自分達が担当するアプリ設定機能全体のコードを分割し終えることができました。 これは同時に、大きな成果を上げるには人と時間を集中投下する以外の方法があることを示したのではないかと思います。 当然、人と時間を集中投下することも一つの手段ではありますが、⚙チームのような進め方も手段の一つになると思います。 今回手段の点が二つできたことで、その間にも無数の手段を考えられることができるようになりました。 今後も最適と思われる手段を取って大きな成果を達成していきたいと思います。
- BIG THINGS どデカいことを成し遂げたヤツらはなにをしたのか?, p177↩