2019年上半期のiOSアプリ開発振り返り

2019年も残すところあと6ヶ月。上半期はどんな感じでiOSアプリ開発をやってたかっていうのを書いておきます。

SwiftUIとかCombineとかそういった話題はありません。

開発用ツール

XcodeGen

デメリットはあるもののXcodeGenが圧倒的に便利です。
しかし、すぐにXcodeGenを使いたかったかというとそういうわけでもありませんでした。

なのでXcodeGenをチームで採用しようというのは難しい判断になりそうですね。

もう少し細かく、自分の気持の移り変わりとしては次のような感じです。

XcodeGenの存在知る(知っても別にコンフリクト慣れてるからなーという気持ち)」

XcodeGenを試してみる(うーむ、まあ長所が短所を超えているな、くらいの気持ち)」

「複数人のプロジェクトでXcodeGenを運用する(短所をカバーする圧倒的な良さがあるやん!という気持ち)」

という感じで結局導入してみたら長所が短所を圧倒的に超えてました。

長所

長所を並べてみると

  • Xcode関係
    • SchemeConfigurationの仕組みを知ることになる
    • わざわざSchemeで設定を変えるみたいな変なことやっててもConfigurationに差し替え可能
    • Scheme間やConfiguration間の設定値の差分がコードなのでわかりやすい
    • ファイルが実ファイル順で並ぶので細かいことを気にしなくて良くなる
    • マルチモジュールでも構成が把握しやすい
  • git関係
    • プロジェクトのファイルがコンフリクトしなくなるので気にしなくて良くなる
    • 自分が複数ファイルを先に追加してコミットする際にもそのプロジェクトファイルを分割するという作業がない

短所

こういうとき、短所を言えないとちょっとあやしいですからね。短所を無理やり考えてみました。

  • 実ファイルからXcode上のグループを作るため、例えばテストターゲットのファイルをプロダクション用のファイルと同じディレクトリに入れられない

この短所は長所でもあります。例えば「テストコード用のファイルなんて別でまとまってるほうがいい」「実ファイルとXcode上のファイルが間違って配置して混乱したら困るからそれを防げてる」とも言えます。

他の短所を無理やり出してみると

  • includeしていくxcconfigファイルのinclude順や構造が分かりづらいかも

一つのBuild Configurationに1つのxcconfigを指定するため、自前のxcconfigから複数のincludeしていかないといけない。cocoapodsのxcconfigをincludeするのもそのうちの一つですが、ちゃんと整理して全共通用のBase.xcconfig作ったりDebug.xcconfig/Release.xcconfigを作って無駄がないように導入したくなるわけです。

これはまず表を作って設定ファイルを階層的に整理していくのがいいと思います。

あとまあ、ブランチを変更した際にファイルが異なっていることがあると確実にXcodeGenを実行しないといけないというのも短所かもしれません。

なのでこれの解決のために、git hooksでcheckout時に常にXcodeGenするようにしてます。cocoapodsでpods installをhooksに入れてたのと同じですね。

その他: 一部の設定を変更するぐらいならSchemeでやるべきではないがXcodeGenならそれも面倒でもない

他にはScheme関係。

これはもう根本的な前提の話なんですが、例えば通信先のホスト名など、プロジェクト内の変数を入れ替える場合にConfigurationで分けてよって思うわけです。これたまにSchemeで分ける人がいてそれめちゃくちゃ面倒なのでしょうと。

基本的にSchemeっていうのは複数のConfigurationを保持できるわけです。

Apple公式のSchemeのコンセプト
を引用してみると

An Xcode scheme defines a collection of targets to build, a configuration to use when building, and a collection of tests to execute.

で、
そういった大がかかりな仕組みでわざわざ変数書き換えるためにSchemeを使うっていうのはオーバーなわけですよ。

でもどうしてもSchemeで変数の書き換えを分けたいんだったら、まあXcodeGenでやるとそういうのも差分わかりやすいよねってことです。Configurationで分ければいいとは思うけど。

mint

mintはバージョン固定できるのが特徴です。例えばXcodeGenのバージョンをチームで揃えたりするのにラクですね。brewで特定のバージョンにするっていうのは難しいですが、mintは特定のバージョンをインストールするのも、特定のバージョンで実行するのもラクです。

mint run yonaskolb/XcodeGen@1.2.4 # run 1.2.4

https://github.com/yonaskolb/Mint

つまりXcodeGenやるならmintも入れるかなとは思います。

SwiftFormat

swiftlintも使いますが、それはそれとしてSwiftFormatも使っています。

gitのpre-commitのhooksに設定していて、commitするたびにcommitしたファイルを対象にSwiftFormatが動作しています。

GitHub DesktopというMacのクライアントにはUndo機能があるため、コミットしたファイルに変更があるとSwiftFormatの変更点を確認しすぐUndoしてコミットメッセージそのままコミットし直すという感じです。

3ヶ月に一回くらいSwiftFormatのルールを見直すっていうのが良いと思っています。

SwiftFormatmintでインストールして使うのがいいと思います。

フォーマットルールのページは分かりづらいんで貼っておきます

https://github.com/nicklockwood/SwiftFormat/blob/master/Rules.md

リアクティブプログラミングフレームワーク

RxSwiftは使うが限定的に使う

  • RxSwiftは使う場面は入力イベントが複数あって出力も複数あるときと限定してます
    • つまり通信結果を表示したいだけの画面などはRxSwiftは使わない
  • おそらく世の中の大半のプロの方たちにも、Rxの概念は難しいと思います。チームでやっていく際にもコードレビューのことを考えたら逆に時間がかかる
    • そうなるとテストコードを書いてないRxSwiftのコードなんてかなり恐ろしい

参考の本: RxSwift研究読本

一緒に開発するメンバーがリアクティブプログラミングについて、共通の見解を持つため絶対外せないのが「RxSwift研究読本」じゃないかと思います。

RxSwift研究読本1

RxSwift研究読本2

RxSwift研究読本3

関数型プログラミングのチュートリアル

Rx公式の関数型プログラミングのチュートリアルっていうのがあります

http://reactivex.io/learnrx/

すでにRxがわかっている人からしたら、Rxが採用する関数型プログラミングのアイデアってこれだよなーという感じです。それを知らない人からしたらちょっと意味がわからないかもしれない。「なぜforEachからmapとかfilterを作ってんの?」って気分になるかもしれないですが、その小さな部品を作ってまた組み合わせていく、それがRxが採用する関数型プログラミングのアイデアなわけです。これはちょっとRx慣れてからやるといいと思います。

テストコード

どのような対象にテストコードを書いているか

なるべくViewControllerは(難してく)テストしたくないので、ViewControllerに処理を集めず、必然的にViewModelPresenterに対してテストコード書いています。

現状、テストコードの利点はだいたい次のように捉えていて

  • 不安解消
    • コードをレビューしただけで仕様を満たしてるんか?
    • 運用されているコードは正常に動作するんか?
    • 不具合修正後に対応できたんか?
  • インタフェースや再利用性の確認
    • 自分が作ったモジュールをテストコードで再利用して見直す
    • ライブラリは正しく使えてるか

しかしこのメリットに対して、時間的コストをかけすぎるとメリットに対してバランスが悪くなるとは思います。
例えば一つの機能に対するテストコードを書くときに2時間以上かけない、という制約がないと、無駄にテストコードを書いてしまったり、なんかそもそもテスト対象が複雑すぎるということに気づくきっかけになるはずです。

また、どんなコードを書けば上記の不安が解消するのかという根本を考えずにテストコードを書こうとするとかなり大変なことになります。具体的には単体テストで済む話なのに結合テストをしてMockをたくさん作らないといけないと思い込む、とかです。

Quick/NimbleXCUnitを使うかの選定についてはQuick/Nimbleが使いたけりゃやったらいいと思っています。単体テストでもQuick/Nimbleの表現力は魅力的なので、XCUnit使ってコメントを散りばめるぐらいならQuick/Nimble使えばいいと思います。

その他、このテストコード無駄だなーと自分では思っても、テストコードの書き方を他のメンバーに示すコードとして意味がある場合もあります。または明らかに無駄だなーと思って書いてるとミスに気づくこともあるのでまあメリットもある。
もしくは無駄なほどテストコード書いていると、そのときはじめて時間をかけないということにたどり着けるかもしれない。
...というのが上半期の感想です。

おわりに

今年後半どうなっていくかわからないんですが、年末にはまたこっからどうなったかがあれば書いてみたいと思っています。

9月はiOSDC2019で「自作して理解するリアクティブプログラミングフレームワーク」が採択されたので話す予定です。どんなことをを発表するのかの細かいことはまた違う記事にしておきます。