Swiftの世界的カンファレンス、try! Swiftが3月2日~4日の3日間にわたり、渋谷のサイバーエージェントのオフィスにて開催されました。
本イベントの興味深いセッションをいくつか、日ごとにレポートしていきます。まずは1日目のレポートです。
Laura Savinoさん「コードリーディングについて」
新しいコードを読み解くことを、私たちはしばしば行いますが、それはエネルギーと時間を消費します。Laura Savinoさん(@savinola)は、スラスラと新しい言語を読めるようにする方法と、進化についていく方法を話しました。
コードを解読することは大変!
コードを読んで、さらに解読するにはエネルギーと時間を要します。そのコストを下げるために意識しているポイントとして、Lauraさんは以下の3つを紹介しました。
- スラングを避ける
- 人間の言語におけるスラング、これは知っている人しか知らない表現です。プログラミング言語においてもスラングを避けることで、平易な文となり読みやすさを上げることができます。
- 過度な短縮系を避ける
- 過度な短縮系はすぐに理解できず、読むのにエネルギーを使う必要のある表現です。「書いた人にしか読めないコードはやめよう」と述べていました。
- カスタムオペレータを避ける
- カスタムオペレータもエネルギーが必要な表現です。
共感を大切にする
「なぜこのコードが読めないんだ?」とチームメンバーに対して思ってしまうこともあるかもしれませんが、それは自分が悪いという可能性もあります。そんな時は共感を持つ必要があると、Lauraさんは指摘します。相手にとって読めないのであれば「コード上でどこの情報が欠けているのか」を考える必要があります。
これまでに述べてきたコードの解読の必要性をなくすことで、コードに対する議論の余地がなくなります。Lauraさんは、「ほんのちょっとした部分であっても、チームメンバーにとって読みづらいコードがどこかに存在してしまうことは良くない」と述べていました。
Q&Aインタビュー
セッション後、LauraさんにQ&A形式のインタビューを行いました。
Q: セッションでも言及していましたが、C言語タイプのforループについて、プログラミング初学者にとってはfor-inよりもforループのほうが読みやすいのではないかと思います。これについてどのように考えますか。
A: チームの目標をどこに設定するかがカギだと思います。大切なのはセッションでも言及しましたが、共感です。その上で、チームの目標設定に対してチームメンバーにとってどんなコードにするべきかがわかるキーパーソンの存在が大切だと思います。良いコードも悪いコードも知った上で判断できる人は重要です。
Q: プログラマはこの種の話題が大好きだと思いますが、最近のホットトピックは何かありますか。
A: 若干VCにコードが寄りがちかもしれないけれどMVCモデルで作っていくのか、それとも小さなコンポーネントに細かく切り分けて作っていくのかという話題が最近ありました。それぞれにメリット・デメリットはありますが、チームメンバーが共感して納得できるところを探すことが大切でした。
Q&Aの回答にあったように「チームの目標をどこに設定するか」というのが重要です。コードを書く時にはチームでコーディング規約をまとめておいたり、だいたいは使い回ししたりということが多いよう思いますが、チーム結成時やスタートのタイミングで都度「今回のプロジェクトで意識するところはここだよね」という認識をチームで共有するタイミングを持ち、その都度書き方を改めていくということが大切なように思いました。なににおいても前提とすることをメンバーと共有するということは大切なので、今後より意識していこうと思います。
Gwendolyn Westonさん「平常心で型を消し去る」
型を明確にすることがSwiftらしいやり方であると気づいた時、同時に時には型を消す必要があると分かります。Gwendolyn Westonさん(@purpleyay)の講演では、型とは何か、型を消すことが何を意味するか、なぜそうしたいかについて解説しました。
型とはなにか?
型には2種類あります。「Concrete Type」と「Abstract Type」です。
Concrete Typeはインスタンス化できる型のことです。データを保持し、オブジェクト間でやり取りを行います。 Abstract Typeはインスタンス化ができず、データを保持したり具体的な処理を行ったりできません。抽象的な振る舞い、挙動を表すのがAbstract Typeです。
protocolでGenericsを使うには?
Gwendolynさんはポケモンを題材に説明していきました。サンプルコードはこちらです。
ポケモンの振る舞いを持つprotocol Pokemonがあって、そのProtocolに準拠したstruct Pikachuやclass Charmanderがあります。ここで、ポケモンごとに技のタイプが違うのでタイプを分けてインスタンス化することを考えます。その際にGenericsを使おうとしても、PokemonはProtocolなのでSwiftの言語仕様上、Genericsで定義できませんし、なによりProtocolはAbstract Typeなのでインスタンスを生成できません。そこで使用するのがどんな技のタイプのポケモンも扱えるclass AnyPokemonだと紹介。このAnyPokemonは型引数となるPokemonTypeの中身がどんな実装であれインスタンス化することができる特徴を持っています。ここが型消去の部分になります。そしてAnyPokemonのinitの中でattackメソッドの引数の型を固定する実装になっていると説明しました。
Q&Aインタビュー
セッション後、GwendolynさんにQ&A形式のインタビューを行いました。
このセッションの前は「Swiftは型が強い!」という認識がありました。そのため、できるだけタイプセーフに型を意識したコーディングをするように心がけていましたが、このセッションを聞いて型を意識したコーディングをするにはより型について知り、柔軟性をもった書き方をできるようにしていくことが大切であるということに気づきました。こんな書き方があるんだなと、勉強になりました。
Daniel Steinbergさん「文化を調和させる」
Swiftでアプリケーションを書くということはObjective-Cで書かれたアプリケーションをただSwiftに書き換えるだけでなく、Swiftの特徴や哲学を受け入れる必要があります。Daniel Steinbergさん(@dimsumthinking)の講演では、標準的なMVCで構成されたテーブルビューを使用したアプリケーションをSwiftに書き換えるところから始まり、よりSwiftらしいコードにするために、関数型プログラミング、オブジェクト指向プログラミング、デザインパターン、プロトコル指向プログラミングの考え方を適用していきました。
まずはいつものMVCから
例として取り上げたのは、UITableViewを用いてトランプゲームを実装するというものでした。 iOSではおなじみの方法、
- Hand(Model)
- TableView(View)
- HandVC(ViewController)
をUITableViewDelegateとUITableViewDataSourceを用いて、Object-Oriented Programming(以下OOP)で実装していきました。よく取り上げられるように、それぞれがFatなMVCモデルのできあがりです。
FPとPOPを取り入れる
ここからのアプローチとして重要なことは細かく役割を分けていくことで、具体的な書き換えが必要となる部分をできるだけ少なくしていくことです。
徐々にFunctional Programming(以下FP)とProtocol-Oriented Programming(以下POP)を取り入れていき、Swiftyなコードに書き換えていきます。ModelであるHandをclassからstructに書き換えて、FPの要素を取り入れます。オブジェクトはimmutableに、自身のコピーを生成して値を加工していくなどのアプローチです。 例としては以下のようなものです。
また、DataTypeというProtocolを定義します。DataTypeはカードの数やSelfを戻り値としたデータ操作を定義したProtocolで、Handがこれを採用します。Selfを戻り値として定義することで自身を返す形となるため、先述したFPとはとても相性の良いものになります。Protocolとしての振る舞いを切り出す点において、POPの要素をここに取り入れます。
DataSourceに関しても共通化できる処理をSourceTypeというProtocolにまとめて、デフォルト実装としてSourceTypeのextensionを書きます。
こうして順を追って処理を切り出していくと、書き換えが必要のないものとして以下の3つのProtocolができあがります。
- DataSource
- SourceType
- DataType
その結果、元々あったHandVCと、そして書き換えが必要なものとして上記のProtocolをそれぞれ採用した
ができあがります。
HandやHandDataSourceで定義していったProtocolに応じてトランプゲームの実装をするだけなので、書き換えなくてはいけない部分というのを最小限に抑えることができます。役割も細かく分けられているため、従来のMVCのようなFatな構造にはならないという利点もあります。
OOP, FP, POPの融合について
最後にDanielさんは、「今までのアプローチとしてはFatなMVCがよくありました。今回説明してきたようにOOPとFPとPOPの文化をそれぞれ取り入れて融合していくことで、これまでとは違った書き方ができるようになります。OOPだけでやるとかではなく、適宜FPやPOPも取り入れてやってみてください」と述べていました。
このセッションでは、Selfを戻り値としたFPとPOPの融合の部分が特に有用に感じました。復習としてこのセッションの内容を意識してTableViewを実装してみたりしましたが、TableViewの設計だけでこんなにも考えられることがあるんだとプログラミングの楽しさを再認識しました。
終わりに
今回この記事では一日目の3つのセッションを取り上げましたが、他にもPackage Managerやアプリ開発に関する話など盛りだくさんで贅沢なイベントでした。参加した人が広い視野で楽しめるイベントだったのではないでしょうか。
海外から参加された方も多くいらっしゃったので、日本と海外の違いや英語の壁を体感できるという意味でも有意義でした。来年もまた開催されるようでしたら登壇枠で参加したい心持ちです。
最後にイベントを運営してくださったスタッフの方々、登壇者の方々、そして盛り上げてくださった参加者の方々に心から感謝し、1日目のレポートを終了させていただきます。楽しいイベントをありがとうございました。
(2日目のレポートに続きます。)