第5回 カジュアル Swift 勉強会を開催しました #cswift

カジュアル Swift 勉強会

2016年2月6日に『カジュアル Swift プログラミング勉強会』の第5回目を横浜の青葉台で開催しました。


に、横浜市青葉台の 青葉台レンタルスペース で『第5回 カジュアル Swift プログラミング勉強会 』を開催しました。

この会で大事にしたいと思うことは、次の2つです。

もともとそんな談義を楽しむことを目標に掲げて開催していることもあってか、おかげさまで楽しい時間を過ごさせて頂いてますけれど、今回はさらに談義が好きそうな方々が新参されて談笑にさらに花が咲いた心地がしました。談笑の輪の中にただ耳を傾けるのが好きな人も歓迎です。

普段以上に盛り上がった心地

そんな談義は勉強会後の懇親会を超えて、今回はさらにその後に有志で集まった珈琲タイムも普段のまったりリズムとは違って白熱し、もしかしてみんな疲れ果てていないか少し心配しつつ、楽しい時間を過ごせて嬉しい限りでした。

さて、そんな勉強会も終わってそのまま過ぎてしまうのはもったいないなと思って、そんな会の中で出会った事柄や感じた出来事について、記念に綴っておくことにします。

雪ミク?

今回は、つい先日に開催された iPhone Dev Sapporo 勉強会 を訪れたときの帰りにばったり雪ミクさんに出会ったので、みんなのお土産に買って帰ることにしてみました。

こういうアイテムを好む人たちが集まる会なのか自信がなかったのですけど、本気度を感じる綺麗なキャラクターグッズでしたし、初音ミクさんなら本人でなくてもその友人に欲しがる人は絶対いるはず、そう思って買って帰ってみたのでした。

そしてみんなで、アイテムごとに希望者で別れてジャンケン勝負をしたのですけど、ミルクキャラメルが一番人気という会のメンバーがとっても素敵でした。雪ミクさんのミルクキャラメル、優しい甘さでとっても美味しいです。そしてハンドタオルも一騎打ちで白熱していて良い感じです。

と、そんな感じで Swift 勉強会なのに突如ぜんぜん違うことを始めてすみません😏 次回からは Swift に一途に参りますので、どうぞご安心くださいませ。

開催の観点から

とりあえず今回の勉強会では、会場費の集金を休み時間にしてみることにしました。

今までの勉強会の終了時に集めていて、いつも時間のギリギリまで話が盛り上がってしまって最後にバタバタしてしまうことが多かったのですけど、各自の都合の良いタイミングで持ってきてもらえたことで運営の負担も軽減したし、おかげで終了時間ギリギリまで安心して、たっぷり談笑を楽しむことができました。

そしてそんな場面の中で、よく存じている顔ぶれからも、会場費を届けてくれるのと合わせて名前を申し出てくれるところが、とても嬉しく感じたりしました。

自分が苦手とするところもあるのでしょうけど、なかなか顔を覚えられなかったり、顔は覚えてもアカウントと結びつかなかったりとかして、こういう時って失礼をしないかとか、けっこう緊張するんですよね。そんなところをさりげなく支えてくれる気がして、とてもありがたい限りでした。

可変値変数 var を極力避けることの模索

さて、そんな勉強会で自分は、可変値変数 var をクラス規模で極力避けるための事前知識と称して、それを模索するために必要になりそうな事柄を基本的なところから整理してみることにしました。

可変値変数 var を極力避けることを模索するための事前知識 #cswift from Tomohiro Kumagai

内容的には Swift の大きな特徴の1つでもある2種類の変数についてのおさらいと、そこから何を感じてどう汲み取っていったらいいか、みたいな話です。

いろんな事柄を紹介することを重視して、ややこしい話もまぜつつ、その場その場で補足説明を加えていけばいいかなと思って組み立てたので、今回はスライドだけ見ても捉えにくいかもしれません。

要所

とりあえず押さえておきたいところとして、次のものを挙げてみました。

時間いっぱい

これを受けて、前回の勉強会の中で生まれた『クラス規模で var を極力減らしてみよう』という課題をみんなで考えてみたいなと思ったのですけど、事前知識だけでたっぷり1時間話してしまって、実際にみんなで試みてみるまでには至りませんでした。

また別の機会にみんなで考えてみるのも面白そうと思いつつ、ともあれ問題提起と予備知識の紹介まではできたので、ひとまずの目的達成とみてもいいのかなとも思いました。

値と状態という観点で見たオプショナル

そんな自分の発表の中で、値と状態という観点で見たときのオプショナルに対する印象の変化に我ながら興味をそそられたので、スライド内にも書いてあることですけれど、その辺についてここでも軽く紹介しておきたいと思います。

値という観点で見たオプショナル

まず、値という観点でオプショナルを見たとき、オプショナルは「その値がないかもしれない」という意味になる気がします。

これって一般的なオプショナルに対するイメージになると思うのですけど、値を得ようとしたときにその値が得られないとしたら、軽微でもそれってある意味、異常な状態です。そんな状態をいつまでも長引かせることなく、速やかなオプショナルの解消が大事になってくるかなって思います。

状態という観点で見たオプショナル

これが状態という観点になると、オプショナルに対する印象がずいぶん変わって、さきほどの値のように「無いかもしれない」というよりは「無い状態が存在する」みたいに、むしろ存在することに注目が行く印象がします。

継続的に何もない状態というのも普通にありえて、あたいの時みたいにないこと自体が肯定的に受け入れられます。ただしそれを参照した瞬間、継続的な状態はその瞬間の値に置き換えられ、この時からは値がないということが異常なこととして捉えられる風に変わるように感じました。

Swift Protocol and Selector

そして @TachibanaKaoruさん からは Swift Protocol and Selector という題材で発表が行われました。

プロトコル拡張のおさらいや、それを使ったログ出力機能の実装案、そしてプロトコル拡張で実装した機能が performSelector を使った動的呼び出しに対応していないという話が見所でした。

Objective-C の動的実行は切望

この議題でみんなとたっぷり1時間ほど話ができたんですけど、そう、プロトコル拡張による実装が Objective-C の動的実行に対応していないところ、自分もすごく関心を寄せるところです。

これができれば Swift を用いた iOS/OSX アプリ開発の可能性が大きく広がる予感がするのですけど、何かとこれに阻まれてしまって、いまひとつ理想的な形になってくれないもどかしさがあります。


それでも何か打つ手はないかと @objc の指定を試してみたりもしたんですけど、確か以前にいろいろ試してみていた時には Segmentation Fault で落ちたりとかしていた記憶があるので、この辺りの実装はまだ間に合っていないのかなという感触もしたりしていました。

もし想像通りに単に間に合ってないなら逆に期待が持てるとも言えるわけで、個人的にもこの周囲の今後の展開がとても楽しみなところです。

これが齎す可能性って計り知れないような気がして、自分も引き続き気にしてみたいと思います。

プロトコル拡張が保存型プロパティを持てないことについて

そんな話題の中で、プロトコル拡張に保存型プロパティを定義できないことについての話題が出ましたけれど、これについては個人的には今のところそれでいいのかなって思ってます。

プロトコル拡張で値を保存する場所を作って実際に保存するという行いがとても具体的すぎるように思えて、プロトコルの世界観とはズレてきてしまうように思えるのがその理由です。

それよりは保存する場所がどうだとかはプロトコルには関与させないで、プロトコルには単純にどんなプロパティが必要かを規定し、それに具体的な保存場所を与えるかどうかはプロトコルを適用する型の側で決めるのが自然なように感じます。

protocol ImageCacheable {

	var cache: [NSImage] { get set }
}

final class ImageListController : ImageCacheable {

	var cache: [NSImage]
}

プロトコルで具体的に決めすぎてしまうと何かとそれに縛られてしまいますけど、単純に存在と性質だけのアプローチなら、それこそ期待通りの振る舞いを実現できるなら保存型でも計算型でもよくなりますし、プロパティ自体を型で縛らずプロトコルを活用すれば、例えば画像キャッシュ的なものならストレージの在り方そのものから、適用先の型の裁量で実装できるようになります。

プロトコルを型に適用する時にも、適用して、必須になっているプロパティをひとつ定義してあげればそれだけでプロトコル拡張で実装されている機能を使って勝手にそれが操作されるようになるので、こんなスタイルでやってみると、プロトコル拡張で保存型プロパティを持つことの価値が案外それほどでもないようにも思えてきます。

新しいセレクター指定

もうひとつ @TachibanaKaoruさん の話題の中に Swift 2.2 から採用される新しいセレクター の話があって興味をそそられました。

例えば NSViewControllerdoSomething: という名前のメソッドを実装したときに、これまでの Cocoa フレームワークでは Selector を文字列リテラルから生成して使う方法がとられていました。

let selector = Selector("doSomething:")

これが Swift 2.2 からは、文字列ではなく次のようにセレクター指定ができるようになるとのことです。

let selector = #selector(ViewController.doSomething(_:))

将来の Swift 2.2 で対応の見込み

勉強会の中でも試してみたんですけど、Swift 2.2 が採用されたとアナウンスされた Xcode 7.3 beta 3 ではまだできない様子でした。

ただ、勉強会終了後に Swift.org で公開されている Xcode Swift Development Snapshot February 8, 2016 で試してみたところ、新しい #selector 方式の記載ができるようになっていました。


試してみた感じ、今のところはどちらの書き方もできるようになっていて、どちらも同じ Selector インスタンスが作られるようです。旧来の書き方をした場合には Fix-It 機能で自動修正できるようになっていました。

そしてこれらの大きな違いは、存在しないメソッドのセレクターを生成しようとした時に、旧来の方はビルド時に警告として検出されるのに対し、新しい書き方ではエラーとして検出されるところです。どちらも通知されるので間違えても気付けないことはないですけれど、新方式ではより安全に間違いを検出できるようになっていました。

そしてきっと新方式なら自動補完などもされるのだろうなと思いますけど、少なくとも自分が試した環境ではそもそもの補完機能が正しく動いてくれなかったのでまだ分かりません。

プロトコル拡張のメソッド動的呼出は無理そう

そういえばこの話題に行き着いたのは、上でも記したプロトコル拡張のメソッドを performSelector で呼び出せないかが発端だったので、新セレクターを使ってそれを実現できるかも調べてみることにしたのですけど、それは今のところは無理そうでした。

まずはシンプルに、プロトコル拡張で実装したメソッドを #selector で指定してみます。

protocol Protocol {
    
}

extension Protocol {
    
    func doSomethingExtension(text: String) {
        
    }
}

class ViewController: NSViewController, Protocol {

    override func viewDidLoad() {
        super.viewDidLoad()

        let selector = #selector(Protocol.doSomethingExtension(_:))

そうしたところ #selector の行のところで次のエラーメッセージが表示されました。

Argument of '#selector' refers to a method that is not exposed to Objective-C

どうやら Objective-C 互換のメソッドでないとプロトコル指定ができない様子です。そんなエラーメッセージは Fix-It 対応になっていたので自動修正を行ってみると、プロトコル拡張のメソッド定義に @objc が自動で付与されたものの、今度は自動修正された行で次のエラーが発生しました。

@objc can only be used with members of classes, @objc protocols, and concrete extensions of classes

そこでプロトコルに @objc を指定してみたのですけど、そうするとプロトコル拡張だけではプロトコルが要求する機能の実装を満たせなくなり、プロトコルを適用したクラスに改めて実装を記載しないといけなくなる様子でした。


そんな様子から、今のところプロトコル拡張で実装したメソッドをセレクターで呼び出すまではできなそうな印象でした。

それさえ実現できるようになれば、Cocoa フレームワークにおけるデリゲートや Cocoa Bindings などの様々な振る舞いを拡張ひとつで型にもたせられるようになるはずなので、そうすれば Swift の良さを Cocoa フレームワークでも活かせる可能性が高まるはずなので、今後に期待を持ちたいところです。

アプリのアーキテクチャーパターン

そして @royskimJPさん からは、アプリのアーキテクチャーパターンについて今一度目を向けてみよう、みたいなお話でした。

MVC (Model View Controller)、MVP (Model View Presenter)、MVVM (Model View ViewModel)、VIPER (View Interactor Presenter Entity Routing) といった何かと耳にする言葉が登場し、それについてみんなであれこれ談義に花が咲きました。

自分はプログラミング歴は長いものの、ずっとほぼ一人でやってきたせいかこういったアーキテクチャーパターンの話にはほとんど無知で、興味深く聞かせていただいたのですけど、そういえば View Controller の肥大化って何が問題なんだろう、みたいなそもそも的なことを思ったりしました。

そう、よく MVC の話を聞く時って「View Controller を肥大化から守る」みたいな言われ方をするように感じたんですけど、例えば viewDidLoad の肥大化とかならまだしも、必ずしも Controller 自体の肥大化がどこまで問題になるのか、調べてみても「破綻するから」みたいな理由で、いまひとつ納得するには足りないように感じます。

今回の話を聞いていて思ったのは、肥大化するというのは実際のコード量というよりは、MVC という枠組みを想定していながら役割を超える機能が Controller に搭載されがちで、それによって整然とした論理が破綻する、みたいな感じなのかなとも思えたりしました。

プロトコル

そしてなんか、話を聞いてイメージしたのがプロトコルでした。

プロトコルは、あることを実現するために必要な振る舞いを規定するものだと思うのですけど、そこには振る舞いが書かれているだけで実体については関与しない、つまり例えば MVC とかで主張されている気がする「直接操作しない」「独立性を維持する」みたいなのととても相性が良いように感じました。

プロトコルを規定して、プロトコルのインターフェイスだけを使って相互に関われば、依存性はコントロールできそうですし、実際のコードは分離されなかったとしても、アーキテクチャーとしては綺麗に分離できるかもしれない。それに加えてプロトコル拡張を活用すれば、もしかすると肥大化しない巨大な Controller もありえたりするかも、とか思ってみたりしました。

DebugLog プロトコル

そして話を聞いていて、ひとつ前に @TachibanaKaoruさん の話に出てきた DebugLog プロトコルの話を思い出してみたりしました。

これはプロトコルとプロトコル拡張を使ってデバッグログ出力用の振る舞いを規定し、それを例えば ViewController に適用することで、デバッグログを出力できる能力が ViewController 自身に備わる、というものですけど、これが ViewController に機能をもたせているかと考えた時に、必ずしもそうとは言えないような気がします。

普通に考えられるほどデザインパターンの知識は持っていないのですけど、もしデバッグログをとるとなると、普通なら DebugLogManager クラスとかを作ってそこに命令を発行することになるのかなと思うのですけど、もしかするとそうやって DebugLogManager に依存するよりは、プロトコルとして取り込んでしまって自分がログを出力できる能力を身につけてしまった方が、全体として疎結合なコードになったりするかもしれないなとも思ってみました。

NSNotificationCenter

ところで、どう言った流れでその話になったか忘れたのですけど、例えば Flux とかのパターンを使うことで状態変化を予測しやすくなるという話があったのですけど、ストアの状態変化を監視するところを見たときに、これって NSNotificationCenter と何が違うんだろう、と感じたりしました。

NSNotificationCenter といえば、無闇に使うと手に負えなくなる(予測不能)みたいな印象があるので、それとそっくりな監視を使って予測しやすくなるというのはどういうことなのだろう。


とりあえず、それは余談なのですけれど、そういえば以前に自分が NSNotificationCenter を Swift で使うにはどうしたらいいかみたいなことを想像して発表した資料があったのを思い出しました。

着目点としては、主体を NSNotificationCenter ではなく NSNotification と Observer にしてみたらどうなるんだろう、といったお話です。

NSNotification in Swift #cocoa_kansai from Tomohiro Kumagai

自分の中ではなかなかうまく仕上がったように思うのですけど、こうすることによって NSNotificationCenter を全く意識しなくても、通知の授受を行えます。そんな機能は今の常識で考えるなら ViewController が全て持っていることになると思うんですけど、それによって NSNotificationCenter との依存関係が強まっている感じもなくて、肥大化しているという観点からも、必ずしもそうとは言えないのかなと思えてみたり。

今回のデザインパターンの話を聞いていて思ったんですけど、何かとそれぞれの役割をオブジェクトが担っているようにも見えて、もしかしてオブジェクト指向を大前提にしたパターンなのかな、とか思ってみたりしてみました。

意外と決め打ち?

ところで、今回の談義の中で出てきた事柄について @s_takeさん から悲痛な叫びが聞こえてきたり。

自分は Swift ってちゃんと体系的に言語が組み上げられている印象だったので、言語レベルで決め打ち実装されているところにとっても驚きました。

Swift 2.2 から実装されるタプルの6つの要素までの比較実装も、それぞれのパターンの比較演算子を標準ライブラリで実装しているだけだったりして、もっとこう、タプル内のすべての要素が Equatable だった場合は Equatable なタプルになるとか、そういう振る舞いであって欲しかったように思います。

Swift は美しいというのは過大評価だったのかなと、ちょっと残念にも思ってみたりしました。個人的に Swift のリテラル周りはとっても綺麗に作られている印象なので、他のいろんなところでもそうあってくれたら楽しいのになと思います。

おしまい

そんな感じで、たっぷりと頭を使わせてもらった楽しい勉強会でした。今回はいつにも増して談笑好きな人が集まった心地がして、とっても盛り上がって嬉しい限りでした。

次回もまた、どうぞよろしくお願い致します!