モブプログラミングでの実践と絶望
ここまで検討した方針の実現性を確かめるべく、和田、古川含め弊社の技術専門部隊数名で、実際にタウンワークのコードをモブプログラミングで改善してみる試みを行いました。
結果として当初の想定と異なり、数名で1時間コードに向き合ったものの、目に見える改善はゼロという状態になりました。既存のコードの影響が全く読めず、どこから改善したらいいのかもわからないといった、レガシーコードと対峙する上での現実を見せつけられました。
気づきと方針変更
このモブプログラミングをしたことで、手痛いながらも以下の通り有益なフィードバックを得ることができました。
- 影響範囲を局所化するためにリファクタリングをしたいが、そのために既存コードを全て置き換えるとなると、結局その影響範囲を読み切る必要があり、現実的ではない。新規フレームワークなどを導入すると最初の習得コストが増大してしまう。それよりも、小さいモジュールや画面の一部など、小さく部分的な箇所から改善活動を進める方が現実的である。
- 既存のコードをリファクタリングするのは、経験した通り非常に手がかかる。その割に、改善した部分が以後エンハンスされない場合もあり、あまり費用対効果が良くない。
このように、一般的なフロントエンドのモダナイズは「私たちにとって現実的でないのでは」と悟り、以下の通り方針を変更することにしました。
- 影響範囲の局所化を目指しつつ、部分的な置き換えができるようにする。
- 影響範囲の局所化をするために、HTMLのパーツなどはコンポーネント化し、局所化できる設計であることを担保するため、ユニットテストを記述する。
- 新規追加する機能やモジュールは必ず改善対象とする。
- 既存部分についても、今後のエンハンス対象として頻繁な改修が見込まれる画面は改善対象とする。
これを受け、改善活動の第一歩を踏み出すために必要となる、開発基盤の作成を行うことにしました。基盤の作成をする上では、実際の改善活動でしっかり活用できるかを確かめるため、試しに1つの画面を新しい基盤上で置き換え、実利用に耐えうるかを検討しました。
新基盤で導入した技術スタック
その際検討したことは以下の通りです。
ES6記法の導入(Babelを利用)
前述の通り「サーバーサイドの開発メンバーがフロントエンドの開発にヘルプに入れるように」という意図で、ES6記法を導入しClass構文などを積極的に利用するようにしました。基盤構築後、実際にサーバーサイド開発メンバーにこの基盤上で開発してもらったのですが、Javaの知識を持っていれば習得コストはあまりかけずにフロントエンドの開発を行えることがわかりました。
「controller」「module」「component」のレイヤリング
今回は、部分的な置き換えであることと、既存メンバーの習得コストの観点から、既成のフレームワークはあえて導入せず、代わりに緩めのレイヤー化を行いました。具体的には「controller」「module」「component」という3つのレイヤーを設け、それぞれ以下の役割を持つ処理を記述するようにしました。
- controller:画面全体のjsのフックなどを記載。複数のコンポーネントの橋渡し役を担う。
- module:画面と直接関係のないロジックの置き場。例えばhttp通信をする処理などはこの部分に記載する。
- component:画面のひとかたまりの要素。例えばチェックボックスが押された際の挙動などはここに定義する。
ユニットテストの導入
上記のmoduleとcomponentについては、影響範囲の局所化を狙っているため、ユニットテストをかけるようにしました。ユニットテストのテスティングフレームワークとして、Jestを導入しました。
静的解析の導入
ユニットテストに合わせ、静的解析としてESLintを実施するようにしました。これらはCI上で実行されるようにしています。
Agreedを利用したモックアップ作成
前述の通りタウンワークではバックエンドとフロントエンドで開発メンバーが分かれています。具体的な役割分担は、フロントエンド開発メンバーがHTML、CSS、JavaScriptで新たに追加される画面機能のモックアップを作成し、それをバックエンドメンバーがサーバーサイドの実装に取り込む、というものとなっています。そのモックアップを作成する際、通信部分については従来のテストサーバーを利用しており、時折開発に苦労することもありました。そこでこのタイミングでagreedというツールを利用し、通信部分についても併せて簡単にモック化できるようにしました。
agreedは、弊社がOSSとして開発しているCosumer Driven Contractを実現するためのツールです。モックサーバーとテストクライアントを兼ねているため、フロントエンド開発においてサーバーレスポンスのモック化を可能としてくれるのです。
このような対応を行った新基盤の構築、およびそれを利用したプロトタイピングをしてみたところ、実際の開発でも運用できそうであることが確認できました。そのため、ドキュメントやサンプルコードを整備した上で、本格的に通常開発に導入しました。
導入後の効果
新基盤の導入後は、日々のエンハンス開発においてモジュールを新規作成する場合、新基盤上で開発するようにしています。
ただし、課題もあります。画面遷移が絡み、その遷移のパターンに応じて画面の初期状態が変わるといった場合は、影響範囲が読み切れず手戻りを生んでしまうことがあるのです。対応として、まずは単一画面での影響を局所化して安全地帯を作り、それを徐々に広げていく形で展開することになると考えています。
しかし総じて一連の試みは、もともと課題として挙げられていた手戻りの数を大幅に削減することができました。
また手戻りの削減に伴い、開発メンバーから「安心してコードを変更できるようになった」「影響範囲に悩まされなくなった」といったポジティブなフィードバックも聞かれるようになりました。結果的に手戻りや工数といった面だけではなく、精神的な面でも良い効果をもたらすことができたのです。
まとめ
ここまで、タウンワークで取り組んできた、レガシーフロントエンドのモダナイズの取り組みについてご紹介しました。
これらの方法論は、あまり派手さや目新しさはなく、地道で小さな改善活動をコツコツと行ってきた内容です。しかし、歴史を積み重ねてきたレガシーコードにとっては、そのように少しずつコツコツと改善を進めることが現実的で、かつ効果が期待できる方法だった、というのが私たちが試行錯誤してたどり着いた結論でした。この事例が、同じように歴史あるコードの技術負債解消に寄与できることを願っています。
