読者です 読者をやめる 読者になる 読者になる

shobylogy

叩けシンプルの杖

NullabilityとGenericsを使って既存のObjective-Cアプリの開発速度を上げる

WWDC 2015でSwift 2.0が発表されましたが、それに合わせて、Objective-Cに新しいシンタックスが追加されました。

NullabilityとLight Weight Genericsです。*1

これらのシンタックスはSwiftとの相互利用性を向上させるために導入された物ですが、これらのシンタックスを用いることで、既存のObjective-Cコードの可読性を上げ、チームでの開発速度を上げることができます。

概要

  • Nullabilityとは
  • Light Weight Genericsとは
  • Nullability、Light Weight Genericsの使い方
  • 使うべきか悩ましい所
  • まとめ

Nullabilityとは

nullable、nonnull、という二つの指定子を用いて、変数がnilを取りうるかを記述することができます。

nonnullを付けた変数にnilを代入するコードがあると、ビルド時にwarningが出ます。

実行時の挙動は何も付けていない場合と変わりません。

Light Weight Genericsとは

NSArray、NSSet、NSDictionaryのみ、Genericsがサポートされました。

Genericsで指定したタイプと異なるオブジェクトをセットするコードは、ビルド時にwarningが出ます。

実行時の挙動は今まで変わりません。例外を投げてクラッシュするような事もありません。

Nullability、Light Weight Genericsの使い方

Objective-CにおけるNullabilityやLight Weight Genericsは「インターフェースの可読性を上げる」ことを目的にして使うのが良さそうです。 型付けを目的に使うには少し力不足のように感じます。

インターフェースの可読性を上げる

propertyやメソッドの引数、戻り値など、インターフェースに関する部分の可読性を向上させることができます。 特にAPIClientや、Modelなど、複数のエンジニアが触れる箇所はメリットが大きいように感じます。

例えば、APIClientに、item_idのArrayを渡して、ItemModelのArrayを取得するメソッドがあったとします。

- (NSOperation *)fetchItemsWithIDs:(NSArray *)ids completionHandler:(void (^)(NSArray *, NSError *))completionHandler;

何を渡していいのか、何が返ってくるのか良く分かりませんね。実装を見に行って、何を渡すべきか、何が返ってくるのか見る必要があります。

新しいシンタックスを使うとこう。

- (NSOperation *)fetchItemsWithIDs:(nonnull NSArray<NSNumber *> *)ids completionHandler:(void (^)(NSArray<ItemModel *> *, NSError *))completionHandler;

これなら、インターフェースを見ただけで、nilでない数字のidのArrayを渡すこと、結果としてItemModelのArrayが渡ってくることが分かります。

このような形で、実装者以外のエンジニアにも、使い方をきちんと伝えられるのは大きなメリットです。

使うべきか悩ましい所

実際に使ってみて、ローカル変数には、NullabilityやLight Weight Genericsを使うのは適切でないように感じました。 可読性が逆に落ちてしまったためです。 ただでさえ長いObjective-Cの変数宣言がさらに長くなり、読むのがつらくなってしまいました。 また、コレクションに何がどうやって入るのか前後を読めばすぐ分かるため、付加情報の提供としてもメリットがあまり無いように感じました。

まとめ

NullabilityやLight Weight Genericsを使うと、インターフェースの可読性を上げ、チームでの開発を効率的に進めることができます。 シンタックスが長いため、下手に使うと逆に読みづらくなってしまう可能性があるので注意が必要です。

*1:NullabilityはXcode6のタイミングでサポートされていましたが、きちんとしたドキュメントが提供されるのはこのタイミングが初です