月別: 2016年1月

MVC再考 (1)

どの文献を参照しても共通していること

  • ユーザーインターフェースを持つアプリケーションを Model/View/Controller の3つにの部分に分離する

解釈が難しい点

  • モデル・ビュー・コントローラの責務と関係
    • 特にコントローラの責務
    • コントローラとビューの関係性
  • 各プラットフォームにおいて、上記の責務をどう実装に落とし込むのか
    • ほんとうにビューとコントローラは分離できるのか?
    • そもそもビューとコントローラを分離する利点は?

分離とは?

Model-View-Controller に分離するパターンを見ていくが、クラスに分割するだけが分離に相当するわけではない

  • サブルーチン・メソッド
  • クラス
  • パッケージ
  • モジュール

MSDNのMVC記事まとめ

MSDNの記事がわかりやすかったのでまとめた

背景

  • コンピュータシステムの多くは データ を取ってきて、 ユーザ に表示する
  • ユーザがデータを変更したら、 データストア の内容を更新することもある

そのため、データストアとUI間のデータの流れに目がいきがちであり、パフォーマンスのため、またはコード量を減らすために、しばしばその処理を密結合にしてしまうことがある。

このアプローチには2つ問題点がある。

  • UIはデータストアと比較して頻繁に変更が入る傾向にある
  • 複雑なアプリケーションでは、単にデータストアからデータを送受信するだけでなく、複雑なビジネスロジックが存在する傾向にある

問題

ドメインロジックとUIの変更をそれぞれ手軽に独立して行えるようにするためには、Webアプリケーションをどのようにモジュール化すれば良いのだろうか

前提

問題を解決する際に、次のようなことを考慮する必要がある

  • UIロジックはビジネスロジックに比べて頻繁に変更が入る傾向に有る
    • 特にWebアプリケーションにおいては顕著
    • 例えば、新しい画面が追加されたり、すでに存在するページのレイアウトが変更されたりすることが多い
    • したがって、サーバー側に処理をまとめたシステム(シンクライアントシステム)は、アプリケーションを再配布しなくて済む
    • プレゼンテーションコードとビジネスロジックがひとつのオブジェクトとして結合している場合、UIだけを変更したくてもビジネスロジックを含んだオブジェクトを変更しなければならない
    • これはUIの些細な変更であっても、エラーを誘発したり、再テストが必要だったりすることを意味する。
  • 場合によっては、アプリケーションは同じデータを異なる形で表示することがある
    • 例えば、アナリストはスプレットシートを好み、マネージャは円グラフを望むことがある
    • またそれらを同時に表示することも十分に考えられる
    • もしユーザがデータに変更を加えた場合、すべてのビューに反映されるべき
  • デザインと複雑なビジネスロジックを作る作業は全く異なるスキルであり、両方のスキルを持ち合わせる人は滅多にいない
    • そこで、これらの作業はバラバラに実行できることが望ましい。
  • プレゼンテーションはデータソースからデータを取得し、データをフォーマットして表示する
    • 表示されたデータに応じてユーザーはなんらかのアクションを行い、そこからうまれた変更を反映させるためにビジネスロジックへ制御が渡る
  • WebアプリケーションはHTTPのステートレス性の上で、異なるアクションを実現しなければならない
  • UI層のコードは、ビジネスロジックと比較して、デバイスに依存する傾向にある
    • したがって、もしプラウザベースのアプリケーションからモバイル端末などに移植したい場合はUI層のコードを置き換える必要がでてくる
    • UIに関するコードとビジネスロジックを分離しておくことは、移植を素早く行えるようにしたり、移植後のビジネスロジック層のエラーを減らしたりすることに役立つ
  • UI層のテストは難しくて、実行に時間がかかる傾向にある。したがってUI層と直接結びついているコードを減らすことはテスタビリティ向上につながる。

解決策

Model-View-Controllerパターンは、ドメインモデル、プレゼンテーション、ユーザーからの入力に対するアクションの3つのパートに分離をする[Burbeck92]。

  • Model: モデルは状態に応じたアプリケーションドメインの振る舞いを扱い、主にControllerからの操作に応じて状態を変化させる。
  • View: ビューは表示される情報を扱う
  • Controller: マウスやキーボードなどのユーザからの操作を解釈して、モデルやビューに適切に伝える

mvc

  • ビューとコントローラーはモデルに依存してよい
  • モデルはどちらにも依存してはいけない
    • これにより、モデル層とプレゼンテーション層のビルドやテストをバラバラに行うことができるようになる
  • ビューとコントローラーの分離はリッチクライアントアプリケーションでは二の次となる
    • 実際のところ多くのUIフレームワークではひとつのオブジェクトにビューとコントローラーの責務をおいているものが多い
    • 一方、Webアプリケーションにおいてはビュー(ブラウザ)とコントローラー(HTTPリクエストをさばくサーバーサイドコンポーネント)は明確に分かれている。

Model-View-Controller はUIロジックとビジネスロジックを分離するための基本的なデザインパターンである。有名であるがゆえに、多くの間違った説明がなされている。

特に Controller は色々な文脈で異なる説明がなされている。ただし、Webアプリケーションにおいてはビューとコントローラーは明確に分かれているために、こういった曖昧さを解消するためには丁度良い。

passive型 MVC

Steve Burbeckは、In Application Programming in Smalltalk-80: How to use Model-View-Controllerの中で passive 型と active 型の2種類の MVC のかたちについて説明している。

passive型MVCはあるコントローラがモデルを排他的に制御するときに用いることができる。コントローラはモデルを変更し、ビューにモデルが変更されたので内容を更新する必要があることを伝える。このやり方だと、モデルはビューやコントローラと完全に独立した形になり、モデルはビューに変更を伝える手段がない状態になる。HTTPプロトコルなどがこのパターンに合致する。ブラウザがサーバーから更新を受け取るための、この上なくシンプルな方法である。ブラウザはユーザからの入力に応じてビューを表示するが、サーバー上のデータの変化を検出することはできない。ユーザが明示的に更新を問い合わせる必要が有る。

passive

active型 MVC

active 型はコントローラが関わらなくてもモデルの状態が変化する際に用いられる。このモデルの変化は他の入力ソースからデータの変更が発生してしまう場合に起こりうる。基本的にはその変更はビューに反映されるべきである。電光掲示板を作るときにはこうしなければならないだろう。表示内容に変更があった場合、データ取ってきてビューに反映させる必要がありそうである。

しかし、MVCパターンを用いる大きな目的のひとつに、モデルとビューを分離するというものがあったことを思い出そう。モデルがビューに変更を通知するとなると、ふつうにやれば依存関係が発生してしまう。そこでGoFのObserverパターンを思い出そう。これはオブジェクト同士の依存を避けつつも、変更を通知することを実現するデザインパターンである。それぞれのビューはObservarインターフェースを実装して、モデルを購読する。モデルが変更されたら、登録されているすべての observer に通知を行うという仕組みになる。このやり方はしばしば、publish-subscribe と呼ばれる。モデルはビューに関する情報は一切必要としない。たとえば、メニューのオプションを使えなくする必要があるなど、コントローラーがモデルの変更通知を必要とする場合、すべてのコントローラはobserverインターフェースを実装する必要がある。また、たくさんのビューがある場合、それぞれ異なる領域ごとにモデルを定義し、各ビューは関心のあるモデルのみを subscribe すると良いでしょう。

mvc

activemvc

もたらされる影響

MVCのもたらす恩恵

  • 複数のビューをサポートできる: モデルとビューが分離されているため、モデルからビューへ直接の参照は存在しない。したがって、同時に同じデータを様々なビューで表示することができる。これはWebアプリケーションにおける複数のページは同じモデルオブジェクトを使っていることがあることからもわかるだろう。またユーザがページの見た目を変更できるようなWebアプリケーションの存在からも理解することができるだろ。そういったページは同じモデルから得られた同じデータを、異なる方法で表示することができている。
  • 変更に強くなる: UIはビジネスロジックと比較して変更が生じやすい。ユーザは異なる配色やフォントやレイアウトを好むかもしれないし、デバイスに特化したインターフェースを望むかもしれない。モデルがビューに依存していないので、新しいビューのセットをシステムに追加しても、モデルは何の影響も受けない。結果として、変更の影響はビューだけに限られる。この部分をさらに細分化したパターンとして Page Controller と Front Controller というパターンがある。

MVCのもたらす弊害

  • 複雑になる: MVCパターンは遠回りなやり方であり、システムを複雑にする。またデバッグの難しいイベント駆動なコードベースになる傾向にある。
  • 頻繁な更新に対するコストが大きい: モデルとビューを切り離すことは重要だが、決してモデルがビューの存在を無視してよいということではない。モデルが頻繁に更新を行うような場合、ビューにそれを反映させるコストは大きなものとなるだろう。特にグラフィカルなユーザーインターフェースにおいては顕著になる。このような10教科ではビューは描画に失敗することもあるだろう。したがってモデルを作成するときにはビューを念頭に置くことは重要だ。場合によってはモデルの複数の変更をまとめてビューに通知するなどということも必要なはずである。

Document-View パターン

Model-View-Controllerの責務分離は行ったまま、ViewとControllerを結合 したものを Document-View パターンとよんでいる。今日の、多くのGUIプラットフォームではこのパターンが用いられている。VC++のMFCなどはこのパターンの実例のひとつになる。

単一責任の原則(SRP)

Single Responsibility Principle(単一責任の原則)は、Tom DeMarco の “Structured Analysis and Systems Specification” と、Meilir Page-Jones の “The Practical Guide to Structured Systems Design” で説明されている。この原則は次のようなものだ。

クラスを変更する理由は複数存在してはいけない

なぜこうする必要があるのか?

 役割が単一なクラスの仕様要求が変化した場合、その変更部分は浮き彫りになり、どのように変化したのかわかりやすい。これは、ほとんどの人が納得するはなしではないだろうか。

 しかし、役割が複数あると、その1つ1つが変更理由になってしまう。複数の変更理由によってクラスが変更されると、変更部分がぼやけてしまう。また、ある理由により変更した部分が、他の役割に影響してしまい、連鎖的に変更が必要になるなどといったケースが生じうる。これは もろい設計 にあてはまる。もろい設計がソフトウェア開発にどんな影響を及ぼすかは、前に書いた記事を参照されたい。

役割とはなにか?

 「役割=変更理由」と定義している。この判断が非常に難しいケースも多々有る。

変更の理由が変更の理由たるのは、実際に変更の理由が生じた場合だけである

 変化の兆候がないのにSRPを含めた原則を適用するのは賢明ではない。原則を適用することを目的にしちゃいけないというのは、いつも気に止めておかなければならないなぁと思います。

結合している役割を見つけそれらを分離する作業は、ソフトウェア設計の本質である

 非常に身にしみる言葉。

どのように分離するのか

たとえば、次のようなモデムインターフェースを考える。

 最初の2つのメソッドは接続の開始と終了、すなわち接続管理の機能を持つ。後半の2つのメソッドはメッセージのやりとりに用いる。この2つの役割を分離すべきかどうかは今後このアプリケーションがどのように変更されるか次第。たとえば接続管理の機能が影響を受けるような変更がはいる場合は、sendrecv のみを呼び出しているクラスをリコンパイル、リロードしなおさなければならない。もっとも単純にこの状態から打破するには、以下のように分離すればよい。ModelImplはその場しのぎではあるが、すべての依存関係が解消しているはずだ。

oymhIIrAIqnELN19B4bqpaZCoqlDKQZcqbOeJirBqR1ApaWiqWJoYbAJopGqkMgvk3BXEfppWOgJIpBpyy0QKZ8JSpGAylAj589BYZBpqa7QWEQbbnP0D29RO5EZgwlWcv-IckkPMv2Zm8La59eS0000

 テスト主導の開発方法に従えば、設計に怪しい兆しが現れる前に、複雑な役割を持ったクラスは分離されるはずだ。なぜならば、複雑な役割をもったクラスのテストを書くのは非常に難しいからだ。しかしそれでもなお、「硬さ」や「もろさ」を感じる場合には FacadeProxy などを使ってリファクタリングするとよいそうだ[要確認]。

余談

 アジャイル開発の奥義を読むまでは、この原則の名前からして、なぜ「クラスの役割は複数存在してはいけない」という内容ではないのかという疑問を持っていた。読んだ結果自分なりには、「変更」という観点に立ったときにはじめて「役割」ごとに分離する必要がでてくるから、「クラスを変更する理由は複数存在してはいけない」と主張しているのではないかと思った。

 たしかに役割は1つのほうが、見通しがよいかもしれないが、複雑にはなる。変更がとうてい生じないような場所に関して、無駄に分離してコードを複雑にする必要がないという意味を込めたい場合、たしかに「クラスを変更する理由は複数存在してはいけない」のほうがよい言葉だと感じた。この解釈自体は、完全に自分が読んだ感想なので、なにか間違っているなどの指摘がある方はコメントいただけるとありがたい。

アジャイル設計の本を読んでいる

 SOLID原則良いなぁ(←適当)…と思いつつ、それが書かれているアジャイルソフトウェア開発の奥義を読んでいなかったので、最近ちらちらと読み始めた。開発プロセスのあたりにはあんまり興味がわかないので、さらさらと軽い感じに読み飛ばしている。開発プロセス関連のはなしはなるほどなぁとは思うし、全員が内容を理解した上でやっていくと意味はありそうなんだけど、現実的にそんなことは起こり得ないと思っていて、学習コストが必要になる開発プロセスに意味はあるのか…とか偉そうなことを思っている。まあそんなことはどうでもよくて、第2部からのアジャイル設計の部分は本当に参考になるなぁ…と思いながら読んでる。

注意:この文章はポエムです

アジャイル設計とは?

 本によると、アジャイルはソフトウェアを少しずつ開発する手法だそうだ。基本的にラビットハウスでは完成させたソフトウェア(完成とは…という話になるが)を納品するようなお仕事ではなく、ソフトウェアを少しずつ拡張していくスタイルなので、まさに合致している。

腐敗するソフトウェアの兆候

 さて、そんな「少しずつ開発していく」スタイルの場合に、どうやってソフトウェアを設計できるのだろうか?という問いが冒頭にくる。少しずつ開発するとしても、最終的な目的は大きなソフトウェアを保守可能な状態で動かすことにあるので、その段階まで持っていけるような状態を各工程(アジャイル言葉ではイテレーションとかよんでるっぽい)で踏んでいかなければならない。それを阻む要素として次のような項目が挙げられている。

  1. 硬さ: 設計変更が困難
  2. もろさ: 設計が壊れやすい
  3. 移植性のなさ: 設計の再利用が困難
  4. 扱いにくさ: 正しい設計をするのが困難
  5. 不必要な複雑さ: 行き過ぎた設計
  6. 不必要な繰り返し: マウスを使いすぎ
  7. 不透明さ: 整然としない表現

 なるほど、たしかにという気持ちになる。こういった構造を作らないための原則として、有名なSOLID原則が紹介されている

  1. 単一責任の原則(SRP: Single Responsibility Principle)
  2. オープンクローズド原則(OCP: Open-Closed Principle)
  3. リスコフの置換原則(LSP: Liskov Substitution Principle)
  4. 依存関係逆転の原則(DIP: Dependency Inversion Principle)
  5. インターフェース分離の原則(ISP: Interface Segregation Principle)

 設計に関するいろいろな本がでているが、基本的にまずこれを守れてない上でそういうものを取り入れようとしても、かえってカオスになるケースのほうが多いのではないかなぁと個人的に感じている。まあ採用しているアーキテクチャなど状況によりけりでしょうけど。とはいえ、ソフトウェアのうまくいっている部分に無理やり、この5原則を適用しにかかるのはやめなさいという忠告も書かれている。そういう部分にはいろいろ変更がくわわってカオスになってきてから、原則に則ってリファクタしても遅くないと思うので、なるほどなぁ…と思った。こいつらについては、別記事で個別にみていく。

硬さ

 ソフトウェアのちょっとした変更が難しい、1行の変更をしようとすると芋づる式に変更箇所が膨らむということを、硬い設計とよんでいる。これって要はその一行に他のモジュールが依存しているのと変わらないので、結局のところモジュールに分割している意味がないってことな気がする。そうならないようにちゃんと考えて書けよ〜ってことなんでしょうね。

もろさ

 1つの変更により他の多くの部分が壊れてしまう傾向のことを、もろい設計というらしい。そういった箇所は、ソフトウェアの部品としての抽象化に失敗しているということを指すのではないかなと思った。

移植性のなさ

 他のシステムでも役に立つ部分を含んでいるのに、その場所から切り離すことが困難・リスクをともなうような状態。これも機能の抽出に失敗してしまっているときに起こるようなことかなと解釈した。移植するかしないかはともかく、移植できる状態にあることは良いことだとも思う。ただ他のシステムでも役に立つが、移植可能な状態にするのがあまりにも厳しいものはあると思うので、そういった部分はまた別の話かなぁとも思う。難しかったり前例がなかったりする実装はそうなってしまいがちなのはしょうがないと思う。バランスが大事。

(ソフトウェアの)扱いにくさ

 設計構造を保持するやり方が難しく、これまでの設計とは違うが圧倒的に簡単に機能を追加したり変更したりできてしまう場合、そのソフトウェアは扱いにくい。これは非常に重要だと思っていて、難しい設計技法とかをあたまのいい人たちが頑張って取り入れても、そこに追っついていける人が開発メンバでなければ、思想のまったくことなる実装が入り組み、余計複雑なソフトウェアを生み出してしまうと思う。同じ設計手法を用いるとしても、その考え方を理解して、やり方を揃えていけるのであればきっとうまくいくのではないかなと思う。そうでない場合は失敗するだろう。当然のことのはずだけど、新しいことを覚えて感動しているときには、こういうバランス感覚を忘れてしまいがちになるはずで、気をつけなければならない。

(環境の)扱いにくさ

 開発環境がクソゴミで非効率なことを指す。コンパイルに時間が掛かる場合に、設計を維持できないとわかっていてもモジュール分割してしまうみたいなこと。差分管理システムへのコミットに時間が掛かるようなことも例として書かれていた。まあgit使ってる分にはよほどなことがない限りこんな感じにはならないかなと思う。モジュール分割については、もうちょっと考えないと本のいっていることの意味が理解しきれない。そもそもコンパイル時間を減らすことを直接の目的としてモジュール分割するのはどうなんだろうか?あたまが悪いので自分には判断がつかない。

不必要な複雑さ

 設計している時点で不必要な要素が含まれている設計のことを指す。これ気をつけないとやってしまいがちですよね。結局あとから手直しするハメにあったり、つかわれることがないまましれっと削除コミットをしたり。このようなことをすると不必要にソフトウェアは複雑になるそうだ。たしかに分かるような、分からないような。不必要なコードをコミットするのは読み手にとっては非常につらみを増やすだけだが、それがソフトウェアの複雑さに結びつくかどうかの部分が自分の中であんまりはっきりとイメージできないので、これからも継続的に考えていきたい。

不必要な繰り返し

 同じようなコードが繰り返しでてくる。読み手がつらい。こういうコードのレビューをしているとき、推敲されていない文章(この記事のように…)を読んでいるかのようでつらい気持ちになる。このリポジトリはお前のブログじゃねえんだよという気持ちにさせないように、ちゃんと自分の書いたコードは推敲しないといけない。でもこれを応用すれば、嫌いなレビュワーを苦しめることができるということか…(嫌いなレビュワーとは…)。そしてこれを放置していると複雑さにつながると思う。

不透明さ

 わかりにくいモジュールのこと。他人が見て、わかりずれえなってところはこれに該当するんじゃないだろうか。モジュールという言葉はJavaのパッケージ的なものだけでなく、普通にサブルーチン、クラスレベルを含んだ話だと解釈した。書いている本人はわかったつもりだけど、誰かが読むと意味不明なのは、日本人の書く英語のようなものなのかなぁと思う。

アジャイルな設計とはなんなのか?

 アジャイルな設計とは、プロセスやイベントではなく、ソフトウェアの構造や可読性を向上させるために、原則・パターン・プラクティスを継続的に適用する行為だそうだ!(意識たかそう!!!)そのための原則とかパターンが8章以降に書かれているので随時まとめていきたい。

乱数生成を純粋化する

乱数の生成についての簡単な例を見てみよう。scala.util.Random が用意されているのでそれを使えば簡単だ。

nextInt メソッドは呼び出しのたびに返ってくる値が異なる。呼び出しのたびに rng の状態が遷移していることが想像出来る。たとえば、ランダム性を利用したメソッドのテストを書こうとした場合、テストを再現可能にする必要があるが scala.util.Random では難しそうである。仮に乱数ジェネレータを直接扱うとしても、ジェネレータの状態を揃えてあげる必要がある。こういった状態に対処するために、副作用を使用しないという原点に立ち返ろう。

純粋関数型の乱数生成

状態を遷移させるのではなく、新しい状態を返すという気持ちでやっていく。乱数ジェネレータの場合は、ジェネレータの nextInt を呼び出すと、値と新しいジェネレータを返すという感じになる。もちろん、もとのジェネレータは状態遷移しない。したがって、もとのジェネレータの nextInt を何回呼び出しても、同じ値と新しいジェネレータが返ってくる。コードで表現すると次のようになる。

こいつは以下のような挙動を示す。

見ての通り、nextInt は純粋な関数になった。

ステートフルなAPIと向き合う

乱数生成の例で見たようなことと同じような方法で、すべてのステートフルAPIは純粋化できる。基本的には状態を遷移させるのではなく、値と新しい状態を返してやるという方針になる。ただし普通にこれをやってみるとボイラープレートが多くて辛い気持ちになるだろう。たとえば RandomGenerator に対していろんな便利関数を定義してみる。同じことばっかりやっているように見えないだろうか?

すべて RandomGenerator => (A, RandomGenerator) な関数になっている。「状態を遷移させるのではなく、値と新しい状態を返してやる」という方針が関数に明確に現れてきている。この部分は繰り返し出現するのですこし抽象化しよう。type を使って RandomGenerator => (A, RandomGenerator)Rand[A] というエイリアスを張り付ける。すると見なれた mapmap2 などの高階関数が定義できて、かつそれを用いて上で定義した関数などを実装できるようになる。

にゃんぱす祭り りぴーとなのん♪♪

のんのんびより スペシャルイベント「にゃんぱす祭り りぴーとなのん♪♪」夜の部に参加してきました。当日は16:30ごろに会場の日比谷公会堂入り。物販は列に並ばずに買えた。良い。

それにしても、にゃんぱす祭りなのになんで思いっきり都心の日比谷で開催しているんだろうか。もしかして日比谷って、田舎なのん?まあそんなことはどうでもいいとして、座席2階だったんだが、公会堂の2階席はつらい。足元のスペースが狭い、椅子が硬い、ステージは見えない、音響は悪い。イベントスペースとしてはちょっと辛みのある会場ですなぁ…。

そんなこんなではじまったにゃんぱす祭り。半月ちょいぶりに村川梨衣さんの姿を直接拝見できてよかったです。あいかわらずの元気で真面目なりえしょんをみることができた。あとあやねるはあざとかわいい。

ナノライプの生ライブ直接観れたのはびっくりしたなぁ…。いきなり機材が並び始めたのでもしやと思ったけど、よかった。ただ生バンドのあとに音源使って1期、2期EDをやるとちょっと音圧に物足りなさを感じざるを得ない感じでしたね。このあたりは会場のせいもありますが、にゃんぱすイベそろそろ公会堂以外でやってもいいんじゃないんでしょうか…。2期のアニメの出来は非常によかったのでイベントやキャンペーンのほうもぬかりなくやってくれると嬉しいなぁ…。今後に期待。夏すぎにはOVA的なサムシングもでるらしいので、期待は高まる…。

全体的にイベントの脚本自体は甘さというか、雑な感じはあった。のんのん本篇の内容をもっと絡めたコーナー作りをするような姿勢は欲しいかなぁと思いました。まあでも、りえしょんと一緒の現場で安心した気持ちで働いている佐倉綾音さんが見れてよかったので良しとします。

遅延リストを作る

FP in Scala 第5章読書会の予習。Streamの作成については、半年前くらいに記事にまとめた。

リストの操作と無駄な中間リスト

リストへのmapやfilter操作の評価は、模式的には以下のような感じで行われる。

中間リストが無駄に生成されているので、mapやfilterといった高階関数をつかって合成性をおとさずに、つまりwhileループに頼らずなんとかしたい。そんなときに非正格性(non-strictness)を使うとよい。ということで「ワンランク上のリストの構築のしかた」を探っていく。

正格関数と非正格関数

「ワンランク上のリスト構築」をする前に正格性について確認を行っておく。
正格性とは関数の特性である。非正格関数では、引数の1つ以上を評価しないという選択が可能で、正格関数では引数が常に評価される。

Scalaの if 制御構造は非正格の一例。array.isEmpty の状態に応じて、then または else のステートメントが評価されない。

正確には、条件パラメータについては常に正格であり、各条件分岐後のステートメントは非正格である。Scalaで非正格関数を記述するためには、引数の一部を評価されない状態で受け取ればよい。具体的には以下のようにできる。

評価されない式をサンクとよぶ。これを評価するためには、空の引数リストを渡せばよい。() => A は実際には Function0[A] 型のシンタックスシュガーになっている。上の if2 関数はさらに簡単に以下のように書ける。

どちらの構文においても、評価されずに渡される引数は、関数の本体ないで参照されている場所ごとに毎回評価される。これを避けるためには、lazy キーワードを使って値を明示的にキャッシュすればよい。

遅延リストを作る

非正格にする方法はわかっているので、あとはリストでやったことに手を加えてやれば良い。
データ構造の定義は以下のとおり。

これを用いて、冒頭で示したリストへの操作の効率化を図っていくことを考える。

コンストラクタに潜む非効率性

Consデータコンストラクタを直接呼び出した場合、評価が無駄に走ることがある。

無駄な処理を減らすためにはキャッシュをさせてやればよい。以下のようにスマートコンストラクタを定義する。

Empty のスマートコンストラクタには型推論を助ける狙いもある。これらを用いると以下のようにできる。

各種関数の定義

foldRightmap, flatMap などを定義する

評価のされ方

以上のようにして定義した Stream の評価がどうされるかを最後に確認しておく。

初詣に行ってきた

初詣に行ってきつつ、年末にふと買ってしまったパタヘネ本の2章を読んでいた。

算術演算

加算命令、減算命令はそれぞれ add, sub で、必要なオペランドは3つ。

データ転送命令

MIPSでは算術演算は必ずレジスタを用いて行われる。レジスタはハードウェアを構成する基本要素であり、高速で処理することができる。ただし、プログラミング言語の変数とは違いレジスタの数は限られている。そのため、MIPSマシンにはメモリとレジスタ間でのデータ転送命令が必要になる。メモリからレジスタへデータを転送する命令はロード lw と呼ばれる。逆にレジスタからメモリへデータを転送する命令はストア sw と呼ばれる。MIPSではレジスタ長は32ビットであり、これを語とよぶ。また語アドレスは4の倍数でなければならない(整列化制約)。

即値のオペランド

命令操作に定数を使用することが多いので、命令が用意してある。MIPSでは、負の定数も利用できるため即値減算命令は必要ない。

RxSwift2.0.0がリリースされた

この記事は 「RxSwift Advent Calendar 2015」1日目の記事です。

長らく開発の続いていたRxSwiftの2系がついにリリースされたようです。

今回もまあまあ変わっている部分があるようなので、beta4, 2.0.0-rc0, 2.0.0 あたりでの特に気になった変更点をまとめます。2.0.0もリリースされことですし、そろそろインターフェースも落ち着いてくることを期待しています。

Observable生成メソッド関連の変更

グローバルに定義されていた justfailWith などが削除され、Observableのstaticファクトリメソッドになっています。。また後者については、error(ErrorType) に変更されています。おもな変更を一応コードで書いておくと以下のような具合です。

just の変更点

find replace all just( to Observable.just(

failWith の変更

find replace all failWith( to Observable.error(

同様な変更

of(sequenceOfに変更), empty, create, zip, debounce, range, generate, interval など詳しくは この辺り をみると色々のってます。あとソースコードの diff も見ましょう。

Variable の変更

以前 VariableObseravble のインターフェースを持っていましたが、現在は asObservable() をかましてあげる必要がああります。Variable に対して、Observableの高階関数が直接使えなくなっているので注意が必要です。

MainScheduler.sharedInstance がいなくなった

MainScheduler.instance に変更

rx_controlEvents が rx_controlEvent に変更された

RxCocoa のほうの変更。find replace All で頑張ろう

その他

テスト向けの便利なライブラリ RxTests が増えたらしい。これについてはまた後ほど。あと VirtualTimeScheduler というものと HistoricalScheduler というものが増えたらしい。今後調べます。

おわりに

今年もRxSwiftを積極的に用いて、できればライブラリの開発にもContributeできれば良いかなぁと思っています。みなさんも便利で快適なライブラリ、RxSwiftを使って、胸がらんらん歌う開発をenjoyしましょう。

Rhodanthe* 元旦コンサートに行ってきた

17:50ごろ会場到着。

 開演10分前だけど、会場の外に大量の人間が…。案の定開演は15分くらい押しで始まる。国際フォーラムは座席が広くて会場としてはかなりいいなぁ…と思った。キャパは5000人ほどだそうで多分9割くらい座席埋まっていた。ホールA入り口から入場して階段を上ると、なんかの生演奏をやっていた。正月っぽい。

セットリストとかは以下のような感じ。

 振袖は種ちゃんが一番にあってた。まあ今回のイベント、個人的には田中真奈美さんのトークを見に行ったと言っても過言ではない。今回も本当にいいコメントだった。冒頭の挨拶でもいい感じのネタを仕込んできていたし、最後の挨拶もさすがだった。「去年はきんいろモザイクの”稼働”が多かった」という発言、非常に良い。田中真奈美さん非常によい…。これからも応援したい方です…。本人はいたって真面目に本心で話していると思うけど、発する言葉ひとつひとつの破壊力がおかしい。天才な気がするので、ラジオとかちゃんと追っていきたい。まなみん関連のツイートでお気に入りは以下のやつ。

  • https://twitter.com/Sangou3/status/682912834485796864
  • https://twitter.com/nknk398/status/682913241987600388
  • https://twitter.com/raitirel/status/682909848036442112
  • https://twitter.com/trainman_rize/status/682910195048005632

 そうそう、最後のほうの曲、生のビッグバンドが演奏してくれて、思いがけず元旦からビッグバンドサウンドが楽しめたのがとても良かった。でもスウィングの曲でサイリウムを表拍で振るのやめません?(提案)

良い元旦を過ごした。