RareJob Tech Blog

レアジョブのエンジニア・デザイナーによる技術ブログです

レッスンルームのチャットUIを MessageKit に差し替えたときのツラミとレガシーコードとの向かい方

お疲れさまです。 APP/UI チームの玉置です。

最近のマイブームは鬼滅の刃(きめつのやいば)です。
ツイッターのタイムラインで鬼滅の刃のワンシーンを見てしまい「おっ、刀がメインのアニメか!」と思ってNetflix で動画を見始めたのがきっかけです。
当時の動画のワンシーンは登場キャラの善逸くんが雷の呼吸「雷の呼吸 壱の型 霹靂一閃」を解き放って敵キャラを瞬殺したシーンです。
善逸くんのキャラが「るろうに剣心」の十本刀の「宗次郎」にとても似ていてそのシーンだけで気に入ってしまいました。
(* 善逸くんは宗次郎のキャラとは全然違います)

そんなこんなで動画を見つけた日は善逸くんの上記のシーンまでの動画を徹夜で観ていました。

さて、そんな話しは置いとくとして今日は先月ずっと行っていた
レッスンルームのチャットのデザインで使っていたライブラリのリプレイス作業をずっと行っていました。
そして、やっと今月リリースできそうなのでその当時に色々思うことがありましたので文章化してみました。

リプレイスする前に使っていたライブラリについて

リプレイス前に使っていたライブラリは「JSQMessagesViewController」という名称のものです。

github.com

2016年頃まではチャットアプリでごく一般的に使われていた有名なライブラリです。
こちらのライブラリですが2016年に大体の開発が終了してしまって2017年1月で完全に開発がストップしてしまいました。

f:id:qed805:20190929184418p:plain
github_commit_log

現在は非推奨となっています。
レアジョブアプリはライブラリ管理でcocoapodsを採用しているため、ターミナルでpod installをした際にこのライブラリが非推奨というワーニングが表示されます。

f:id:qed805:20191014183045p:plain
depricated_JSQMessagesViewController

今はチャットライブラリで有名なものとして「MessageKit」というOSSがあります。
チャットアプリを開発する場合は自作するかこちらのライブラリを使うことが一般的になっています。

github.com

今回はこの「JSQMessagesViewController」からの脱却をメインに書いていきます。

リプレイスするきっかけと足枷になったこと

本当はすぐにでもJSQMessagesViewControllerを脱却したい気持ちがありました。

その理由を挙げるだけでも

  • 2017 年から公式が非推奨
  • 公式からのサポートが得られない
  • 事業的にリファクタリングよりも新規機能の開発が優先
  • リファクタリングのコストを支払っても利益が出ないため報われない
  • リプレイスにかかるコスト(工数見積が定かではない)
  • iOSのライブラリ管理ツールである「CocoaPod」からdepricatedというワーニングが表示

などの要因がありました。
また、当社にはカスタマーサポートの部署があり(以下、CSと省略します)、CSよりユーザー様から
「講師側から長い文章が送信されると最後の1行が途切れている」という問い合わせを受けていました。

f:id:qed805:20191014184124p:plain
最後の1行のメッセージの空白

この問題に対して臨時対応を5月頃に実施して解消されているはずでしたが今年8月にも別のユーザー様から同じような問い合わせを受けてしまいました。

そのため使っていただいているユーザー様のためにもできるだけ早くこの問題の根本原因を解消しなければならないと思い、
チームのタスク的にも8月までに必要なタスクを終えて9月は1ヶ月丸々リファクタリング期間を頂いたのでこれを機会にチャットUIライブラリを差し替える業務に本格的に着手することにしました。

リプレイスする上でのツラミ

実際にライブラリのリプレイスをすると決意してからが大変です。
今回のライブラリは「レッスンルーム」に直接影響を与える箇所ですのでデグレに気をつけなければなりません。
その他、個人的に感じたリプレイスする上でのツラミは

  1. 開発メンバーに申し訳ない感
  2. iOSのキーボードが意図通りに表示してくれない
  3. 差し替えたあとにiPad横画面でデグレが起きる

という三点でした。

それぞれ解説していきます。

開発メンバーに申し訳ない感

こちらはリプレイス云々とは関係ありませんが事前に工数見積をしていても全てが事前に見積もれる訳ではありません。
特に今回のようなレアジョブアプリのメイン機能である「チャット」のデザインだと寧ろデザイン崩れやデグレが発生している方が問題になります。
つまり既存仕様を全て正確に新しいライブラリで再現する必要がでてきます。
ただしどうしても新しいライブラリで「再現できない機能」はチームメンバーやプロダクトオーナーに相談して捨てることは可能だと思っています。

デグレ」と「捨てて良い機能」の定義はタスクや機能によって違いますが、
今回の定義では「事前に把握しているかどうか」です。

それはそうとして話しを戻しますが
今回のような見え方や挙動がだいたい同じデザインだと、作業中も私の中ではタスク全体として「達成感」はあまり感じられませんでした。
着手前と着手後で表向きとしては成果物が「同じ」ですので事業にインパクトを直接与える作業ではないのであまり楽しくなかったんですよね。

なので自分が楽しくないことにひたすら挑戦していたので(おまけに事業の売上に貢献していないことも含めて)
メンバーにその感覚が伝わってそうでリプレイス中はずっとメンバーに申し訳ない気持ちで一杯でした。

このツラさを解消できるKPTでいうところ、「Try」があればいいなと思いました。
そのためチーム全体が楽しくレガシーコードと向き合える方法があればリファクタリングが楽しいものになるんだろうなと思いました。

  1. iOSのキーボードが意図通りに表示してくれない

後述する内容ですがリプレイス先の「MessageKit」のInputBarAccessoryViewがうまく意図通りに動いてくれなかったため、全ての挙動を既存仕様に合わせることが難しかったです。
特にキーボードの表示・非表示の制御がiPhoneiPadに関わらず大変で着手中ずっとキーボードの制御に苦しめられました。
レアジョブアプリではチャットのviewがメインのViewControllerにCotainerとして乗っている設計でchildViewControllerになっています。

(main) RoomViewController > MenuViewController > ChatViewController (child)

という設計になっています。

この場合は ChatViewController で MessageKit のInputBarAccessoryViewを表示しようとすると初期表示時にInputBarAccessoryViewが画面外に隠れてしまう現象が起きます。

f:id:qed805:20191014193557p:plain
InputBarAccessoryViewが画面下にあるので表示されない

このような問題にも対応しなければなりませんでした。

念の為、この問題を解消するのに参考になったページを張っておきます。

github.com

github.com

  1. 差し替えたあとにiPad横画面でデグレが起きる

最後のツラミとして、今年5月頃に私が開発したものですがiPadのレッスンルームを横画面にも対応したのですが、MessageKitがそのあたりもいい感じに補正してくれると期待していたところ見事にそれを裏切ってくれました。

iPhoneでだいたい既存の同じ挙動になることを確認してからデグレ起きなかったらいいなと淡い期待を持っていましたが、

単純にJSQMessagesViewControllerからMessageKitに差し替えてもiPadを横画面にすると既存と全く同じ挙動にならなかったのです。
ライブラリリプレイスの本実装の調査前の段階である程度工数見積をしましたが、
iPad横画面ではその当時確認していませんでした。できなかったこともありますが。
そのため実際にこれを改修する前にデザインが崩れてしまう現象のパターンを洗い出して再度工数見積を行いました。

着手前に見積もっていた工数も残りわずかというか使い切ってしまいましたので、
恐怖に思いながらiPad横画面でのデグレ箇所の工数見積をしていました。

想定外のデグレ工数はメンタルに良くないですね。

実際のリプレイス作業

ということで長々と書いてしまいましたが、ここで実際にライブラリをリプレイスしたときに行った手順を復習します。

ライブラリ自体の調査と挙動の調査 (工数見積まで)

  • アプリの既存の動きの調査
  • MessagesKit自体のデザインの調査
  • MessagesKitがどこまで柔軟に対応できるか
  • 試しimport でどれだけのデグレが発生しているか

実際にライブラリをimportする (実際に着手開始)

  • MessageInputBar が使えず、InputBarAccessoryViewが必要
  • どのバージョンのInputBarAccessoryViewを使えばいいのか情報が少ないのでその調査を行う

そのためcocoapodのPodfileは下記のようにInputBarAccessoryViewをimportしました。

  pod 'MessageKit'
  pod 'InputBarAccessoryView', '4.2.2'

ハマリポイントの改修 (想定外の対応)

  • ChildViewControllerでは初期表示時にInputBarAccessoryViewが表示されない
  • レッスンルームを一つのViewController で管理できるかの調査 (既存設計を大きく変える方法の調査)
  • メインのViewController で becomeResponder()を読んでinputBarを意図的に表示させたときの調査 (既存設計を踏襲する場合の調査)
  • iPad横画面でのデグレの対応

上記のような流れになりました。

レガシーコードと向き合った感想と気をつけるべきこと

今回はレガシーコードではなくライブラリのリプレイス作業について解説してみました。
新規事業だとガンガン突き進めて事業にもインパクトを与えられますがレガシーなものを新しいものに書き換えるようなリプレイス作業は見た目が変わらないので作業していてもなかなか辛い部分がありました。

ですがレガシーコードは綺麗にせずにそのままにしておくと将来の負債となったりメンテナンスできなくなって「ゼロから作り直し」になったりする非常にセンシティブな部分でもあったりします。
現場によってはプロジェクトのソースコードを「1から作り直し」になってしまった所もあるのではないでしょうか。
モバイルアプリは最初の1,2年は開発していてとても楽しいですがさらに長く運用していると様々な要因で昔のレガシーコードが影響して開発スピードが著しく遅くなってしまう傾向がありますね。

またAppleGoogleSDKが年々新しくなって昔のソースコードがいきなり非推奨になったりします。
なので、時間がある時にできる限りソースコードを綺麗にして保守性を上げる開発体制が一番安全かなと思いました。

今回のチャットUIを新しくしたことでレアジョブアプリを使って頂いているユーザー様により快適にレッスンルームをご利用頂けると思うと開発者として報われる気持ちになりますね。

ということで長文になりましたがぜひレッスンルームを使って頂ければと思います。