良いアーキテクチャを採用することについて、それを採用することによるメリットを計測したり説明するのが難しいとよく耳にします。これから、そのメリットは通常考えられているよりも素晴らしいものであることを示します。
このtry! Swiftの講演では、実践的で、良いアーキテクチャを導入することがどのように日々の作業を楽にするのか、実例を用いて紹介します。私なりのSwiftにおけるiOS向けクリーンアーキテクチャの解釈で、 他のViewControllerの既存のユースケースを再利用 したり、逆に別のバックエンドを使用することもできるなど、アーキテクチャがどのように役に立つのかをお見せします。また、このアーキテクチャがどのようにテスタビリティに役立てられるかを簡単に説明します。
イントロダクション (0:00)
この講演では、以下3つの項目をお話しします。
- 良いアーキテクチャから得られる 強大な力
- ライブコーディングによる シナリオ
- 話したことの まとめ
良いアーキテクチャにより得られるもの (1:34)
良いアーキテクチャによって得られる強大な力や、メリットについてから始めましょう。
最初のメリットは、 繰り返しが少なくなること です。もしアプリに同じコードを1回以上書くなら、そのコードはどんどん悪くなっていくでしょう。なぜなら、このコードを悪く書くチャンスが2回もあるからです。同じバグを2回直さなくてはなりません。同じコードを2回以上書くための時間も必要になるし、そんなことはしたくないと思います。時は金なりです。
良いアーキテクチャによって、 再利用性 も得られます。再利用性は違うアプリで同じクラスを再利用できるということです。急いでいたり、クライアントワークなどにはは特に向いていると思います。
また、 メンテナンスがしやすく なります。なぜなら、クラスの責務が他のオブジェクトから分離されるので、なにかよくないことが起きた時、どのオブジェクトに責任があるのかがわかり、バグがどこにあるのかがわかります。責務を分離すればするほど、アプリのデバッグがしやすくなります。
また、より テストがしやすくなり 、バグが減らせるのがいいですね。まるで開発の聖杯のようです。例えば、今後更新されなくなる可能性のある永続性フレームワークから独立させたかったり、フレームワークのひとつから独立させるなら、アプリは変更に耐えうるものとなるでしょう。そうでなければ、その末永く使っていたくて、新しくてキラキラしたフレームワークに適合させるために、アプリ全体を書き直す必要があるでしょう。
最後に、アプリへの変更の要望が頻繁にあったり、この新たな状況にアプリを適応させることができるならば。もし良いアーキテクチャがあれば、その新たなユースケースをとても早く加えることができます。これがあなたの利益になり、会社の利益になります。
お金に興味がない人がいることもわかっています。信念のためにやるのです。だからあなたを雇っているのです。することに対して情熱的なのはわかっています。なので、良いコードを書くことにプライドがあるのです。
良いアーキテクチャから得られる3つの強大な力をお見せしましょう。
Super Reusablility (4:54)
ひとつ目は、再利用性です。しばらくアプリを開発していると、色んなアーキテクチャのパターンを使っていることでしょう。MVCやMVP、MVVMなどを。
これらのクラスはたった3つのグループなのに、アプリにおける責任は重いです。なので、ほとんどの場合、クラスはひとつ以上の責務をもっていることになります。
何かクラスから切り離したいものがあるので、どこかにプレゼンテーションロジックをもつことになります。ひとつ以上のView Controllerでロジックを再利用したいからです。違うクラスにあるなら、再利用できます。
また、データソースも一つ以上使うことになるでしょう。その場合、競合が発生したときにオブジェクトの処理方法についてキャッシュしたり、調整を行いたいと考えています。だからあなたはこの責務を別のレイヤーに持ちたいと思うはずです。
また、時にはCore Data Extensionとして書かれているビジネスロジックも、使っている永続性Frameworkから完全に分離されていることが重要です。
Super Independence (6:41)
2つ目の強大な力は、依存性です。これがおそらく一番クールで強大な力です。これは、依存性反転の原則に基づいています。
依存性反転の原則は高レベルのコードは低レベルのコードに依存すべきではないということを示しています。なので例えば、永続性のフレームワークをコードに用いる、すなわちネットワークに存在しており、オブジェクトをパースしているなら、それは間違いなく良くないことです。
そうではなくて、やりたいことは、抽象化させて、依存させることです。あなたのクラスをその抽象化したクラスに依存させて、フレームワークを実装するようにします。これは少し複雑に聞こえますが、これを行う方法を学ぶと、本当に簡単で、非常に強力な方法です。
Super Testablility (8:01)
3つ目の強大な力は、テスタビリティです。テスタビリティは多くの場合で、 依存関係を明示的に設定する必要があります 。これが良いことなのは、コードの依存関係が何であるかを理解し、適切に対処する方法を知っているからです。
また、依存性注入を楽にすることも重要です。通常、特にStoryboardを使用している場合は、View Controllerが作成されるため、StoryboardとControllerに依存関係を渡す必要があるので、ちょっと難しくなります。
また、他のすべての原則からも恩恵を受けるだけでなく、オブジェクト指向設計に適用できる他の設計原則も得られます。
次はシナリオに進むので、できれば動画のライブコーディングを見てください。
シナリオ1 (9:21)
最初のシナリオは再利用のロジックについてです。優秀な開発者を選ぶためにデザインしたアプリを用いています。これは優秀な開発者を採用するための実際のスキルを知るために、インタビューをするアプリです。
これは2つのスキルにもとづいています。Emacsに関する知識と、カフェインが飲めるかどうかです。この2 つのスキルに基づくことで、我々の秘伝のタレにより、プログラマを評価することができ、その人を雇うに値するかを知ることができます。
プログラムマネージャーがこのアプリケーションを再利用するように指示していて、お気に入りビューのステータスを変更を行うときは、Detail View ControllerからではなくTable View Controllerから行うというユースケースを用いているとしましょう。
長押しを検出して、お気に入りのステータスを変更するように指示されています。これは、クリーンアーキテクチャによるものです。あるエンティティがあります。このケースでは、プログラマだけがいて、これが処理しているエンティティになります。
ビジネスロジックをカプセル化しているユースケースがあります。新しいユースケースを生成するためのユースケースファクトリーもあります。Presenterや、処理しようとしているオブジェクトのプロバイダであるEntity Gateway、そしてViewがあります。
Viewでは、Viewの追加を参照し、View Controllerを追加します。なので、Connectorも持っています。Connectorは、遷移とナビゲーションを担当し、依存関係を注入します。
まず最初にやるべきことは、長押しを認識してそれを処理するメソッドを1つ追加することです。長押しが発生している場所から情報を取得するだけで、これが起こる正しい行を探し、Presenterに通知します。この場合、Viewはだいたい役に立たないからです。
そして、Storyboardでは、長押しのGestureRecognizerを、今まで定義してきたメソッドと接続します。私は、長押しのGestureRecognizerを使用するRecognizerの1つとして、Table Viewを接続します。
ここで、Table Viewから渡されるイベントを処理する責務があるPresenterに目を向けましょう。この場合、これはList Presenterになります。なので新しいメソッドを追加しましょう。これは、前に呼び出されたメソッドです。これは長押しを処理するためのメソッドで、使っているデータのIDを使用します。
最後に、新しいユースケースを生成する必要があります。そこで、このメソッドに渡された行でIDを取得してから、ユースケースを作成し、ユースケースファクトリを使用して、タプルでパラメータを追加しています。
ユースケースを実行します。ユースケースはプログラマのお気に入りの状態を切り替えます。最後に、Table Viewのデータを更新するために、完了したことを通知します。
Presenterで起こっているユースケースについて、追加情報はないことに注意してください。Presenterは知りません。ユースケースはプロトコルを実装しているので、Presenterでこの3ステップだけを使ってこのユースケースに行くことになります。
シナリオ2 (16:16)
2番目のシナリオは、いくつかの永続性フレームワークに惑わされた場合のバックエンドの置き換え方です。
定義されているプロトコルがあり、興味を持っている操作があります。これらのメソッドは非同期で、新しいプログラマを作成することができます。IDによってプログラマーを取得し、開発者のリストを取得し、それらを更新することができます。
バックエンドの一種であるVFrameを使ってこれを実行するのに必要なのは、この新しいバックエンドの新しいファイルを実際に作成して、すべてのコンテンツを追加することだけです。長いファイルかもしれませんが、そのほとんどはとても簡単です。バックエンドでこのメソッドが必要とすることを実行するだけです。
今回は、CloudKitを使用するつもりですが、プロトコルに従っていて、プロトコルに漏れがなく、このフレームワークが提供する特定のオブジェクトを使用していなければ、他のものでも動くでしょう。
アプリの残りの部分で変更する必要があるのは、AppDelegateに移動し、Entity Gatewayをメモリリポジトリで作成する代わりに、このCloudKitリポジトリのインスタンスを作成するだけで、それは実行できるはずです。
ここのバックエンドは他と異なっています。データが違っていて、それでもナビゲートしたり、人物のステータスを変更したり、そこにあるものを変更したりすることができます。
シナリオ3 (19:50)
3つ目のシナリオはテストに関することです。みなさんに示したこの例は、およそ1600行で、シナリオの中で書いたものを除いて、すべてのテストを書いています。247個のテストがあり、正常に動作するはずです。すべてがテストされるべきですが、ここで一緒に書いたものもあります。
それで、カバレッジをみると、私たちが最後に変更した3つのもの、すなわちプログラマ、Table View Controller、メモリリポジトリ、つまりData PopulationとCloudKitリポジトリを使用していないものすべてです。
これらは、ここですべてテストされています。つまり、まだ書かれていないアプリについても、アプリはすべてテストできます。
Summary (21:30)
まとめになりますが、アーキテクチャはみなさんにとって良いものだと思っています。巨大なエンタープライズのアプリだけでなく、みなさんにです。なぜなら、そのメリットは、小さなアプリでさえ享受されるからです。
1つのView Controllerしかないアプリをつくったり、メンテナンスをしていく予定がないなら、多分今日の話は気にする必要はありませんが、それより複雑になるものは、アーキテクチャのことをちょっとでも気にしてもらえたらと思います。
やみくもにアーキテクチャを適用するのではなく、意思決定の背後にある原則を学ぶべきです。やみくもにアーキテクチャを採用するのは間違った方法だと思っています。あなたが使用するこのアーキテクチャのプログラムの、このデザインのルールがどこから来るのかをわかっている必要があります。
あなたはいくつか デザインパターン を学ばなければなりません。有用なアーキテクチャを実装することは有益です。たとえば、ユースケースファクトリはデザインパターンであり、ユースケースの数とそこでやっているプレゼンテーションロジックの残りの部分との間に独立性を担保しています。
最初から最高のアーキテクチャにコミットする必要はありません。これらすべての手順は徐々に適用することができ、各イテレーションでアプリを改善できます。だから、あなたも強大な力を得ることができます。その力はとても役に立つことになるはずです!
About the content
2016年9月のtry! Swift NYCの講演です。映像はRealmによって撮影・録音され、主催者の許可を得て公開しています。