note iOSアプリで利用していたAPIライブラリを統一した
こんにちは。noteでiOSアプリの開発をしているかっくんです。
この記事は「noteのみんな Advent Calendar 2021」21日目です。
振り返り
そういえば昨年もAdvent Calendarで何か記事を書いたなと思って見てみると同様に負債の返済をしていました。
この記事も例に漏れず負債を返済したという内容の記事なのですが、これはAdvent Calendarの宿命かもしれないですね。
アプリの歴史
noteのiOSアプリの歴史は意外と古く、2014年ごろから存続しているアプリで運用開始して7年が経過しています。
それだけ歴史があるとコードも古いものから新しく書いたものまで色々と入り混じってきます。
特に古くから存在するObjective-Cのコードは依存も多く、消すことは不可能なのでは?と思ってしまうほど複雑に絡み合っています。
この記事ではその複雑な依存の一部であるAPIを呼ぶ処理に利用していたライブラリを一つに統一したという内容を書いていきます。
どうしてライブラリを統一するのか
普段アプリを開発している人ならわかると思いますが、そもそもAPIを呼ぶライブラリが2つ以上存在すること自体がやばいですよね。ざっと思いつくだけでも
書き方が統一されていない
認証の処理が複雑
テストが書きづらい
etc…
といったデメリットが思いつきます。
さらに、元々利用していたライブラリはAFNetworkingというもので、Objective-C製です。
noteのiOSアプリではこちらのライブラリを拡張して利用していました。
そして、後からSwift化の対応を進める中でAPIKitも並行して利用されるようになったという経緯があります。
今回ライブラリを統一しようと踏み切ったきっかけとしては、API側で新たな機能を入れる必要があり、それが全APIに影響を及ぼす可能性があるためでした。
それをアプリ側で対応しようとすると次の図のようなことをする必要が出てきました。
こういったことをしようとするとAFNetworkingでは対応が辛く、Swift製で拡張性も高く、コードの見栄えもいいAPIKitに統一するのが現実的だろうと思い対応を進めることにしました。
どう対応したのか
どうしたと言っても愚直に対応しましたとしか言えないのが辛いところですが、既存のAFNetworkingを拡張して利用しているクラス名を検索して一つずつ対応を進めました。
(お恥ずかしい話ですが)Objective-Cのコードにはテストが皆無なのがより辛みを増幅させていました。
今回の該当コードを大まかに分類すると以下のような感じになります。
VIPERのInteractorでラップしている
Swift製のViewModel/DataSourceクラスが利用している
Objective-C製の専門クラスが利用している
Objective-CのUtilクラスでラップしている
一番手を出しやすいのはVIPERのInteractorでラップしているコードなので、まずはここから着手しました。
総量としてもこの処理が一番多かったので、この対応が終わるだけでもかなりの進捗が出せました。
次に手を出しやすいのはViewModelやDataSourceになっている箇所です。元々Objective-Cで書かれていたコードを単にSwift化されているだけの画面に多く見られます。
こちらは前述したInteractor化した段階でprotocolと実装の分離が済んでいることが多いので既にInteractorがある場合にはコンストラクター・インジェクションやセッター・インジェクションを利用してDIをするようにしてテストを書きやすく変更しました。Interactorが無い場合には新たに書き直して同様にDIができるように対応しました。
次のObjective-C製の専門クラスについてはまず、クラス自体をSwiftで書き直しました。その上でInteractorが無いものは作成してDIができるように対応を進めました。
一番厄介なのはUtilクラスです。これは非常にたくさんの画面で利用されており、Utilクラス自体をSwiftで書き直すことは現実的ではありませんでした。
今回はAPI呼び出しを行なってる処理をクラスで分離して、その中にInteractorをDIするような設計で進めました。
結果
結果としては掲題にもあるのですが全てのAPIの呼び出し処理をAPIKitに統一することができました。
また、追加の効果としてはObjective-Cのコードが減らせ、更にテストコードが増やせてよかったです。(全てのテストコードが書けたわけでは無いですが、今までテストが皆無だったところにテストを入れることができたという感じです)
まとめ
これぞ正に技術的負債と呼べるような負債を解消することができました。
但し、まだ全APIに影響する処理の実装ができていないので安心はできません。
また、Objective-C製のモデルとSwift製のモデルがまだ共存していたり、技術的負債が残っています。
引き続き、負債を解消しながら、新しい機能のカイゼンを続けていきます。
この記事が気に入ったらサポートをしてみませんか?