なぜSwiftでDIが流行っているのか

結論としてはテストを簡単にするためです。 DIでなくても簡単にする方法はあります。 この記事では、DIすることによってテストが簡単になる理由を説明します。

偽物によるテストの容易性の向上

 あるアプリを手動で正しく動いていることをチェックするとしよう。多くのアプリは外部の状態に依存しています。サーバーや時間、ユーザーの操作などです。アプリがちゃんと動いていることをチェックするために、それぞれがちゃんと動いていることを確かめたり、状態を確認しながらチェックをする必要があります。チェックを行うために、外側の環境の不安定で一向にアプリのチェックが進まない事は良くある話です。

 実際の開発を行うときは、手動でのチェックは極力避けていると思います。テストコードを書いてCIで自動テストを実行しています。1日のうちで何度も自動テストを行うのに外側の不安定な環境に依存していてはテストが失敗し、自動テストの効果が十分に発揮できません。

 本物の代わりに偽物を使って、テストを行えば安定したテストを行うことができます。例えば、必ず決まった値を返すサーバーのようなものや、同じ時間を返す時計、ユーザーのような操作をするロボットを使うことです。

テストダブルによるオブジェクトの置き換え

 話を小さくして、オブジェクト単位の話です。

 オブジェクトもアプリと同じように別のオブジェクトに依存しています。別のオブジェクトもさらに別のオブジェクトに依存しています。自動テストを行うときに、本物のオブジェクトを使ってテストをすると数十のオブジェクトを状態をセットアップしなければいけない時があります。テストのための準備するコードが実際にテストを行なっているコードより圧倒的に長くなるのは本末転倒です。テストしたい対象に焦点を当てたコードの方が良いテストです。

 偽物のオブジェクトを使うことによって、本物より早くセットアップできれば、テストしたい対象に焦点を当てたテストコードを書くことができます。この偽物のオブジェクトをテストダブルと言います。

Swiftによる型チェック

 偽物のオブジェクトに置き換えればテストが簡単になるという話をしてきましたが、Swiftでは少し面倒な問題があります。

 Swiftは強い型付き言語であり、最適化をしなければ実行時の型チェックも行われる言語です。変数の型が構造体の場合はその構造体のオブジェクトの必要になり、クラスに依存している場合はそのクラスかそのクラスを継承しているクラスのオブジェクトの必要がありです。無理矢理に型を誤魔化しても変数に代入しても実行時エラーになります。つまり、普通にコードを書くとテストダブルは使えず、常に本物のオブジェクトを使うしかありません。これは、テストを行うときに巨大なセットアップが必要なオブジェクトが存在し、テストを困難にさせます。

プロトコルによるテストの容易性の向上と実体の喪失

 変数の型をプロトコルにすることで、プロトコルを実装しているオブジェクトなら何でも代入することができます。テストダブルが使えるため、意図した動作をテストが用意になります。その代わりに、変数の依存をプロトコルにすることによって、本物の型がわからなくなってしまいます。テストしやすくするためには仕方ないことだったとは言え、このままではアプリを為すことができません。

オブジェクトの注入(DI)

 アプリとしての形を為すためにプロトコルでの依存している本物のオブジェクトを解決する必要があります。本物のオブジェクトを解決するためのパターンがDIなのです。DIによって、アプリとしての形を保ちつつ、テストしやすいコードを書くことができるのです。

 DIの実装方法はいくつかあり、DICやCakeパターンなどがあります。実装方法については自分で調べてください。

更新できなければ淘汰されるiOSアプリ

2020年12月7日に更新

最近の事情

UIWebViewの完全廃止

 UIWebViewはiOS8以降に非推奨になっていたが新規アプリの申請を終了する予定でした。2020年末以降に延長した。今のところ未定となった。 WKWebViewに移行しなければいけない。依存しているライブラリに組み込まれている可能性があるので、今一度確認した方がいいだろう。iOS15では完全に使えずに実行時にクラッシュになるかもしれない。 developer.apple.com

Apple Push Notification Serviceのアップデート

 古いプッシュ通知の方法が使えなくなる。2021年3月31日に延期になりました。新しいプッシュ通知の方法を使うように切り替える必要がある。 developer.apple.com

Xcode12でのビルドが必須

 2021年4月末からXcode12でのビルドする必要がある。必然的に下記のOSで変更になったUIの挙動に対応した状態にしておかなければ、意図しない挙動になっている可能性がある。 * iOS 14 * watchOS 7 * tvOS 14

https://developer.apple.com/ios/submit/ iOS14対応をまとめてみた - Qiita

UIAlertView

 UIAlertViewはiOS8以降に非推奨となっている。申請時に注意されたという話も聞くこともありUIWebViewと同様に禁止になる日もそう遠くない。

Swiftが基本

 Swiftが2014年に発表され5年経過した。新規に開発アプリや追加機能はSwift以外にありえない状況になった。Objective-Cは淘汰され、既存のアプリはSwiftに移行しなければ採用はでき辛くなって行っている。Objetive-CからSwiftに移行するにあたってもそれができるエンジニアがいなければ移行できないし、予算と時間が必要になる。長い目で見れば今すぐにSwiftに移行した方が良い。そうでなければ、アプリのアップデートを諦めて低予算運用に切り替えた方が良い。

ダークモード対応

 iOS13以降ではダークモードが使えるようになりました。今のところ、ダークモード非対応の不利益はおりません。おそらく、2,3年のうちにアップデート時に必須になる可能性がある。ダークモードだけでなく3つ目4つ目のカラーモードを設定できる想定で対応を行なった方が良いだろう。 developer.apple.com

SwiftUI

 今のところ移行するノウハウすらない状態。  いつか移行するために情報収集や移行するためのコードのリファクタリングを行なっておうた方がいいかもしれない。

過去にあった淘汰の歴史

Sign in with Apple

 2020年4月末からサードパーティログインのみで認証が完結するアプリには Sing in with Apple が必須になります。GoogleFacebookTwitterのアカウントでログインできるのであればAppleのアカウントでもログインできるようにする必要があります。

独自のサインインシステムや特定のシステムに直接サインインするクライアントアプリなどは、Sign in with Appleを実装する必要はありません。

https://developer.apple.com/news/?id=03042020d

マルチタスク対応

 没入型の体験を提供するアプリでない限り、iPadではマルチタスクに対応していない場合は2020年4月末からアプリの申請が通らなくなる。

 「没入型の体験を提供する」が何を持って、提供していると言えるかは動画内で語られてはいないが、主にゲームを主にターゲットにしていると思われる。 iPad専用アプリの場合は程度大きい画面サイズを想定していることがあるが、今後はそうも行かなくなる。 あらゆるサイズを想定したレイアウトを組む必要がある。

 同時にiPhoneサイズにも対応するのが良いだろう。

https://developer.apple.com/ios/submit/

Google Analyticsの統合

FabricはFirebaseに統合されることに伴って、 Google Analyticsは廃止される。早くFirebaseまたは代わりのサービスに移行する必要がある。

12ヶ月の猶予ということから2020年10月ごろには完全にデータが削除されると予想される。

https://support.google.com/analytics/answer/9167112?hl=ja

Fabricの統合

FabricはFirebaseに統合されることに伴って、 Fabricは2020年3月31日に廃止される。Firebaseにアプリを移行する必要がある。

Firebase

iPhone5対応等のディスプレイサイズの増加

 iPhone4S までは3.5インチとiPad 9.7インチのディスプレイサイズしか存在していなかった。「Androidはあらゆるディスプレイサイズがあって大変だなぁ」なんて呑気に話していた物だった。iPhone5が発売されて、ほどなくして4インチの画面サイズのサポートが必須になった。縦480ポイントであることを前提にしたレイアウトの組み方をしていたアプリは改修を余儀なくされた。当時はオートレイアウトもなくViewの位置を左上からの位置を計算を行って配置を行っていたため、それなりに大変だった。

 iPhone6や6+が登場してiPhone系の端末を4つのサイズをサポートすることになった。この頃にはオートレイアウトができており、オートレイアウトへの移行が必要に迫られることになになった。その後iPadでもiPad Proの登場やマルチタスク対応があった。今後は画面サイズが動的に変更され、あらゆるサイズが存在しうることを前提として開発を行っていく必要がある。

arm64対応必須

 2015年2月1日、arm64に対応していないアプリはストアから削除されることになった。対応としてはただ追加するば終わりという物だったため更新のあるアプリはほとんど何もすることもなくアップデートしれば終わりではあった。ほとんど更新されていなかったアプリがごっそりと消えた。amr64e対応必須はありえる。

デザインの変更

 iOS7にスキューモーフィズムからフラットデザイン変更があった。iOSでは時々多いくデザインが変更されていくため、それに合わせて修正を行っていく必要がある。

まとめ

 iOSアプリは新しいアプリを作ったら1年以内に儲かる目処を立てて更新を行っていく必要がある。

参考

https://developer.apple.com/app-store/review/guidelines/

個人目標を給料査定に使ってはいけないっぽい

OKRの本とかre:Work とかを読んでいて、個人目標を給料査定に使ってはいけないと言うことに気がついた。

会社の目標は挑戦的なものが好ましい。

無謀ではないが実力の上限ギリギリなものが目標として好ましい。やる気を出して新しいことに挑戦することよって、革新的な成果を期待している。 OKRでの目標設定では60〜70%程度の達成率で成功とするので、立てるべき目標はかなり高めだと言える。

個人目標も挑戦的である必要がある

個人目標は会社やチームの目標と自分のキャリアプランなどとすり合わせつつ立てる必要がある。この目標も会社の目標の一部を担ってもらっているだけに挑戦的なものを要求せざるおえない。もちろん、個人の能力や考えのあるので本人が納得の行く目標を立てて、モチベーションを上げてもらう必要がある。

目標の度合いと給料査定を連動させる

 目標を達成したら給料が上がり、しなかったら給料が下がるような会社だったとしよう。大抵の人は明らかに達成可能が目標を立てようとします(毎日適時に出社するとか)。全くもってアホらしい目標にしかなりません。メンバーもモチベーションは上がらないし、挑戦的とは程遠いものになってしまいます。  難易度が高ければ高いほど給料の上がり幅が高いような会社だったとしよう。それでも大抵の人はまぁまぁな目標を立て用途します(今回達成した9割くらいの目標とか)。そこそこの目標になりそうです。今まで通りにやっていれば達成できるようなものになりそうです。  達成したかに関わらず挑戦した内容による会社だったとしましょう。目標と関係ありません。給料査定と連動しているしないと明言してあげた方がいいでしょう。

Googleではどうしているのか

re:Work 公正な給与制度を設計し運用する を読む限りでは、職業に応じて市場価値によって決めるとあります。転職しても同じくらいの給料で働いていると思える会社であれば、転職のリスクは下がりそうです。

個人目標設定

1年程度前から弊社では個人目標設定が義務付けられるようになった。この制度は、四半期に毎に目標を立てて、達成度合いによって半年毎に給料に反映されるというものです。

どういう目標を立てるべきか

 弊社だとOKRを設定している。OKRは簡単に言えば今期の会社の目標です。全社のOKRを達成するために部毎のOKRを立てて、部のOKRを達成するためにチーム毎のOKRを立てて、チームのOKRを達成するために個人目標を立てることになる。

 チームの目標を達成するためとはいえ、個人個人は得意不得意があるため、ある程度担当が割り当てられる。ただし、1人が目標を達成できなくてもチームの目標が達成できるようにしなければ、部のOKRが達成できず、引いては全社のOKRが達成できなくなってしまう。そこで、それぞれの個人目標の一部をオーバーラップさせるように個人目標を立てるようにする必要がある。

 社員は会社の都合だけで一方的に押し付けられた目標を立てても、それぞれが成長したい方向性に沿ってないとモチベーションが下がる。方向性を汲み取った上で全体で整合性のある個人目標を設計していき、合意をとる必要がある。

個人目標の合意をとる

それぞれの方向性を常に把握する必要がある。目標面談があったりするが、その時にやりたい多い人や全くない人がいるし、その時の体調が悪かったり、ハイテンションになっていたりもする。そういう場合は適切な目標が立てれない場合が多い。1回だけ目標面談だけで汲み取ることはほぼ不可能とも言っても良い。

達成を支援する

個人目標と言っているが実際に個人で達成することは難しい。少し難しい目標を立てているのである程度の支援が必要がある。オーバーラップさせている人でもいいし上司でもいい。少なくとも目標の進捗確認は定期的に行うべきではないかと思う。

目標を公開すべきか?

現状はされていないが、個人的には公開された方がいいのではと思う。互いに支援ができないし、チーム開発での最適行動から外れることを行なった場合に「個人目標のため」と言われると何ともできなくなる。

北欧行っている5日目

日本食が恋しくなってきた。

 

持って行ったけど必要なかったものについて書こうと思います。

 

現金

全く使うことなかった。全てクレジットカードで支払いができた。野外マーケットや公衆トイレでさえクレジットカードが使えた。クレジットカードの限度額さえ気を付けていれば、持って行く必要はなさそう。

 

トイレットペーパー

紙ヤスリのようなものは使いたくないと言うことで持って行ったものの一度も使うことなく途中で荷物がいっぱいになって捨てました。

 

ボードゲーム

暇つぶしのために持って行きましたが、ツアー中は暇なんてないし、バス移動やホテルではさっさと寝てしまっていたので不要でした。

 

コート

北欧は寒かったり暑かったりする予報だったので念のため持って行きましたが、一度も使わなかった。日が当たると暑く、影に入ると寒かった。現地の人たちは半袖だった。

 

大型モバイルバッテリー

携帯4回分を充電できる大型のバッテリーを持っていたが毎日充電していたので不要だった。一度も使っておらず只々重りだった。せいぜい携帯一回分を充電できるようなもので十分だ。

北欧に行っている3日目

現地時間の22時ですがまだ明るい。フィンランドです。

 

フィンランド式サウナの話をしようと思います。ホテルにあったから行ってきた話です。

 

サウナ発祥の地のフィンランド。各家庭にサウナがあるとかないとかいうレベルでサウナが一般的らしいのです。当然のようにホテルにもサウナが備え付けられています。

 

ホテルのサウナには、水とタオル2枚と水着を持ってバスローブを着て行くべきだった。日本のサウナにはサウナを出たところに給水設備が備えられていることが多いが、フィンランドだと期待しすぎない方が良い。水道水は飲めるらしいけど少し怖い。

サウナには全裸で入るが、併設されているプールには水着が必要。サウナに入るとプールに飛び込みたくなるので持って行った方がいい。できれば前述の理由で着脱しやすいものが好ましい。

 

日本の方が本格的ではないかもしれないが良いところがある。適当な場所に給水施設があったり、出てきたところにコーヒー牛乳が売ってたりする。この体験は他ではなかなかない。