メソッドは関数ではないのだが

Clean Architecture を読んでいて、クラスおよびメソッドのことを、関数あるいはサブルーチンの一種としているような記述があって、やや気に障りました。

具体的には、単一責任原則の説明のところでして、

f:id:fjkz:20181013154747p:plain

上の絵のように Employee というクラスにいろんな機能を集めたら、太っちょになります。

f:id:fjkz:20181013155919p:plain

そのため、このように機能を切り出したらよいでしょうとあります。

最初に巨大化するようなクラスを定義してしまったら、こういう関数っぽいクラスに切り分けるのも仕方ないことと思います。しかし、この設計がきれいとは思えないです。手続きを頑張ってクラスの中に書いたら、余計に汚くなるように思います。世の中そんな仕事ばかりです。

普通のオブジェクトは手続きよりも、むしろデータ構造を記述するものです。普通に作ったら、欲しいデータごとにクラスがあって、それらに対する操作するがメソッドになるはずです。多分以下みたいになるのではなかろうか。

f:id:fjkz:20181013161306p:plain

なお、本には Clean Architecture といって、ドメインモデルが定義された設計についても、ちゃんと書いていることは補足しておきます。

疎結合の正体見たり

モジュールが疎結合になっているとか密結合になっているとか、業界にいますとよく聞きます。モジュール間の結合度の定義を発見したのでメモしておきます。

モジュール A の モジュール B に対する結合度 C_{AB} は以下の式で定義できます。

C_{AB} =  - \sum_{h  \in H_{AB}} \log  \big( 1 - P_h \big)

ここで、 H_{AB}AB に対して持つ仮定の集合、P_h は仮定 h が成立しなくなる確率です。

要するに、これは情報エントロピーを用いて結合度を定義しようとしていまして、C_{AB} は0以上の値を取り、結合度の値が大きいほどモジュール間の結合が密となります。

そもそも、モジュール間の結合度というものが定義されていなかったので、その定義を発見したことに意味があります。

さらに、この定義が便利なのは有名な設計原則を説明できてしまうことです。以下のようなものを聞いたことがあると思います。

  • デルメル原則
  • リスコフの置換原則
  • ハリウッド原則
  • 驚き最小の原則

これらはだいたい同じことを言っています。依存する側が持つべき仮定のことを仕様といいまして、依存する側はできるだけ少なく、覆ることがなさそうな仮定の上でシステムを作れと言っています。結合度 C は、仮定の数が少なく、仮定が成立し続ける蓋然性が高いほど、小さくなります。

簡単のために原則でない例から挙げていきますと、REST API でシステム間を疎結合にしたマイクロサービスとか良くいいますよね。API 仕様が安定で、HTTP プロトコルが廃れる可能性が低ければ、結合度 C は小さくなります。逆に、システム間で、データベースやソースコードを共有していたりすると、それらが変わる可能性は高いので、C が大きく密結合になります。

他にも、Java の標準ライブラリに密結合しているとは誰も言わないのは、Java はサービスの寿命が続く限り使い続けることができて、Java の標準ライブラリは安定していて変わる心配をする必要がないからです。一方で、 Kotlin が廃れる可能性は高いので、Kotlin で作ったアプリは Kotlin と密結合だと言ってよいでしょう。

原則に戻りますと、デルメル原則は別名で最小知識の原則といいまして、結合度 C の定義でいうところの、仮定の数を少なくしましょうという法則です。仮定の数が少なければそれだけ疎結合になります。

リスコフの置換原則・ハリウッド原則についても、これらはインターフェース仕様にのみ依存して、実装が変わっても動くように作れといっています。インターフェース仕様は安定していて、変わる可能性は低いので、 P が小さくなり、疎結合が実現できます。一方で、不安定なインターフェース仕様だと、余計に密結合になってしまうでしょう。

驚き最小の原則も、要するにびっくりしない仕様は普通の仕様なので、安定しているから、それに依存すれば疎結合だよねという意味です。

他の例を上げれば、バグがあって、バグを回避するように奇妙な細工をしたら、バグを改修された動かなくなります。バグが直らないという不確かな仮定の上に作られているので、結合度は大きいです。あるいは、他のライブラリの private な変数をリフレクションで覗いて、それにロジックに組み込むという正気を疑うコードを昔見たことがあります。当然のように相手のバージョンが上がったら動かなくなってましたが、これも不確かな仮定の上に作られた密結合な作りです。

設計を評価するのに、今回発見した結合度の定義は大変有用性が高いように思います。

ビジネス向けの製品は嫌い

ビジネス向けやエンタープライズ向けといって売られている製品に、会社員をしていますとよく出会います。特に IT ベンダーはこれらの言葉を好んで使います。しかし、私はそういったビジネス向けの製品を好ましく思っていません。

ビジネス向けと特別に言わなければならないほど、ビジネスとは偉いものなのだろうかと疑問に思います。BI -- Business Intelligence という単語は変な言葉です。ビジネスには元々知性がなかったのでしょうか。悲しいかな、あえて BI と言わなければならないように、大方の会社では当て推量で意志決定が行われているのが実態でしょう。ビジネスというものの程度の低さにもどかしさを、私はむしろ覚えているのに、これはビジネス向けの製品で特別なものだと言われますと戸惑うのです。

また、どんな道具であっても用事を済ませるために、つまり仕事をするために作られています。ビジネスだけが仕事ではないです。ビジネス向けとついていない製品であっても仕事で使えるように作られています。JavaEE -- Java Platform, Enterprise Edition というものがありますけれども、Spring だって Struts だって Seasar だって当然のことながら仕事で使うために開発されました。使うべきかどうかは、道具としての完成度の問題で、別の話です。

むしろ、ビジネス向けと言われたら、ビジネスにしか使えないのかと低く見てしまいます。ビジネス向けは、逆にそれ以外ものと比べて、要件が緩いように思っています。ビジネス向けとして売られている製品は、品質が低くないですか。会社で使わされる製品は、我々が私生活で使用している製品より、高価格なのにも関わらず、品質の水準が低いように思います。例えば、社内システムは特注品はもちろんのこと、パッケージや SaaS あっても、私生活で使うウェブサービスと比べて、ダサくて遅くて使いくくないでしょうか。欠陥や障害も多い。もちろんイケているのもありますが、イケてなくても許されます。なぜなら、ビジネスなら使う人に我慢させることができるからです。コンシューマ向けであれば、消費者は厳しいので、良くなければすぐに使ってくれなくなります。ビジネス向けとコンシューマ向け要求される品質のレベルに大きな差があります。もちろん、ビジネスに特有の要件というものはありますので、それを解決してくれる製品は必要です。仕事なので我慢して使います。

ビジネス/エンタープライズは、マーケティング用語です。特に意味もない、なんとなく分かった気にさせる言葉です。それで売れるならマーケティング用語であっても積極的に使うべきだと思っています。しかし、ビジネスを卑しいとまでは言いませんが、特に偉いものでもないと思っている人には、ビジネスという言葉でマーケティングされても通じません。

やりたいことをするのにどうして許可がいるのだろう

あなたは何がしたいのですか?

よく聞かれます。私はこの問いが理解できない。シェンロンなのでしょうか?

お前の望みを言え。

これなら分かります。俺を不老不死にしてくれとでも答えましょうか。でも、何がしたいの、と聞く人は私の願いを叶えてくれるわけではない。そんな能力もない。では、いったい彼らは何を尋ねているのでしょうか?

「私が」やりたいことをあなたが訊いてどうするのでしょう?だって、あなたにやってほしいことではなくて、私がやりたいことですよ? どうして「私が」やりたいことをするのに、誰かの許しがいるのでしょうか?

やらせてあげる。

という言葉も聞いたことがありますが、これもよく分からないのです。セックスの話ではありません。セックスは相手の許しが要ります。ここで言っているのは、私の行動の話です。やらせてあげるという人は、本当にただやらせてくれるだけで、やるのは全部私であり、別に協力する気はない。でも、恩着せがましく、成果は奪う。多分彼らは封建的な考えを持っていて、やらせてあげるだけで、何かをして与えているつもりなのだと思います。個人の自由を認めていないならば、やりたいことを尋ねる理由は分かります。

しかし、現代では個人の自由は保証されています。自由なんて与えて貰わなくても、元よりあるはずです。人が何かをするのに、政府からの免許が必要なこと以外は、許可なんて要らない。実際、個人的にやりたいことがあったら、行動力さえあれば何でもできる。やりたいことがあったら、訊かれなくてもやっているはずだし、やるべきだと思うのです。例えば、海外で働きたいという人がよくいますが、やればいいじゃんとしか思いません。パスポートもって行きたい国に行けよと。やっていないとしたら、そんなにやりたいと思っていない。あるいは、違うことをさせられていて時間が取れないだけです。やりたいことを訊くなら、帰らせてくれたらいいのに。

私はやりたいことはやっている。できないことは元よりやりたいなんて思わないし、林の中の象のように静かに生活していたいので、それで思いつくようなことは大抵やっている。やりたいことはやっているので、何がしたいと訊かれても困るのです。

やりたいことはやっているので、それに介入される方が煩わしい。やりたいことやっていたら楽しいけれども、その過程や結果にあーだこーだ言われたら楽しくなくなるものです。

手の届く範囲は自由にしているのに、何がしたいのかという問いに答えてしまったら、自由は与えられるものだというのを認めることになりませんか。それは精神の自由を手放すことで、私はそれが嫌なのでしょう。

シェルスクリプトのキモいところ

シェルスクリプトインタプリタを作ろうかと、シェルスクリプトの仕様を調べています。気持ちの悪い仕様をいくつか見つけました。仕様書*1を見ながら、dash で試しました。

丸括弧と波括弧のふるまいが違う。

丸括弧はサブシェル、波括弧はコマンドのグルーピングをするための似たような文法ですが、ふるまいが異なるので戸惑います。

$ (echo hello)
hello

丸括弧はコマンドの前後にスペースも要らず、丸括弧内のコマンドが実行されます。

$ {echo hello}
{echo: not found
$ { echo hello }
Syntax error: end of file unexpected (expecting "}")
$ { echo hello; }
hello

しかし、波括弧はコマンドの前にスペースか改行をを入れて、コマンドの後ろにはセミコロンか改行を入れる必要があります。波括弧は優先順位が低くてコマンド名や引数として見なされてしまいます。きっと、波括弧は「あとづけ」なのでしょう。

リダイレクトだけでコマンドになる。
$ >abc
$ ls abc
abc

リダイレクトだけでコマンドとして成立します。

引数とリダイレクトは順不同である。
$ echo a 1> A b 2> B 3> C c
$ cat A
a b c
$ ls
A  B  C

引数とリダイレクトを混ぜてもよい。

$ 1> A echo 1 2 3
$ cat A
1 2 3

リダイレクトはコマンドの前に持ってくることもできます。

条件式の末尾に & が使える。

シェルスクリプトの if 文の条件式はただのコマンドですが、その中でバックグラウンドジョブを作る & が使えてしまいます。

$ if false& then echo hello; fi
hello
$ 
[1] + Done(1)                    false

この場合、条件式は真になります。

関数定義に if 文、 for 文、 case 文などが使える。

シェルスクリプトの関数の中身は通常、波括弧でくくったグループで書きます。

func() {
    echo hello
}

実は、丸括弧で書くこともできます。

func() (
    echo hello
)

ここまではそんなに驚かないのですが、if 文、for 文、while 文、case 文などを関数の定義の後ろにいきなり書いても正しいです。

func() if true; then
    echo hello
fi

func() for i in 1; do
    echo hello
done

 func() case A in 
    A) echo hello
esac

dash だと、単コマンドでも関数を定義できました。bash は無理でした。POSIX の仕様的には bash の方が正しそうです。

func() echo hello
関数定義にリダイレクトが付けられる。

どこで使うのだろう?

func() {
    echo hello
} > /dev/null

ケリー基準

ケリー基準という、賭けに投じるべき額の総資金に対する割合を与える式があります。次のような問題があったとしましょう:

  • 賭けに勝つと掛け金の r 倍が利益になる。賭けに負けると掛け金分が損失となる。賭けに勝つ確率は p である。総資金の一定の割合 f を賭け続けるする。このとき、最も資産が効率よく増える割合 f* は?

答えは以下となります。

f:id:fjkz:20180721103719p:plain

分子は賭けの収益率の期待値です。期待値が正でない賭けを何度もする価値はありません。一方、分母はいわゆるオッズであり、賭けの手堅さを示しています。リスクの大きい大穴を狙うなら総資金に対して大きな割合を賭けてはならないということをケリー基準は教えてくれます。

さて、リスクとリターンを最適化するということが金融工学の目的ですので、このケリー基準は資産運用にも使えそうに見えます。リスク資産(株や債権)をどれぐらい持つことがもっとも効率のよい運用になるのでしょうか?

そこで株式バージョンのケリー基準を計算してみました。なお、 Kelly criterion - Wikipedia に書かれている結果と私が導出している結果は異なっていて、私の結果の方が複雑です。おそらく私が幾何ブラウン運動の過程を理解しておらず、抜けている仮定があるからと思われますが、大筋は一致しています。

投資をするときは利益を期待して投資をします。期待利益率を r とします。配当や物価の上昇、企業の成長による株価の上昇による利益をここでは期待利益率とします。

株価は期待とは別にまるでランダムかのように上がったり下がったりします。今回は株価にはランダムで、トレンドもなく、動きが予想できないような動きがあるとします。ボラティリティと呼ばれるような変動です。単位期間に σ の割合で株価が上がるか下がるかを、それぞれ 1/2 の確率で、するとします。なお、 σ > r > 0 です。運が良い場合に株は r+σ の利益率、運が悪い場合に株は r-σ と負の利益率となります。

株に一定比率 q で投資をするとします。株価が上がれば一部を現金に変え、株価が下がれば追加で投資をして、総資産に対する株式の割合を一定に保つとしましょう。このとき運がよいシナリオでは、単位期間後の総資産は (r + σ + 1) q + (r0 + 1) (1 - q) となります。運が悪いシナリオでは、単位期間後の総資産は (r - σ + 1) q + (r0 + 1) (1 - q) と σ の符号が逆になります。ここで、r0 は無リスク資産の利益率です。国債や銀行の定期預金の利率です。

単位期間後の総資産の期待値は f:id:fjkz:20180721134208p:plain です。何回も試行したときの、利回りの話をしているので、ここでは算術平均でなくて幾何平均とするべきです。

これが最大となる q (=q*) が今回欲しい値なので、微分値がゼロとなる q を求めると、 f:id:fjkz:20180721134746p:plain となります。

ケリー基準と同様に期待値をリスクで除した割合が、最適な割合となりました。(幾何ブラウン運動を仮定して導出した方が、q* = (r - r0)/ σ ^2 ときれいです。)

記号だと味気ないので値を入れてみましょう。

無リスク資産の利率は 0.05 %とします。株に期待できる利益率は 5 % でしょうか(数値の感覚が有無のが素人と玄人の違いですが、素人なのでよく分かりません)。ボラティリティは 20% ぐらいですか?このとき q* は 1 を超えるので、全ての資産を株に投資するべきという結論になります。そうであれば株価はもっと高いはずなので、5 % の利益を期待するのは多すぎるようです。

期待される利益を 3 % としますと、q * = 0.6 です。無限回の試行を仮定していて、リスクが過小評価されていますので、実際に総資産の 6 割も投資するのはリスクが大きすぎるように思います。しかし、どんなに欲張っても資産の 6割以上を単一のリスク資産に賭けるのは逆効果だということが分かります。

IBM Watson の性格診断で遊んでみた

IBM が Watson というブランド名で AI っぽいサービスを展開しています。以前から気になっていました性格診断のツール、Personality Insights で遊んでみました。

下のページからデモができます。日本語にも対応しています。

f:id:fjkz:20180625024535p:plain

このブログに書き留めている駄文を食わせて、私の性格を診断してもらいます。分量が多いほうがもっともらしい結果が出るそうなので、2017年・2018年に書いた記事をつなげて入力してみます。全部で20000字程度です。

結果として総評・具体的な好みの有無・集団の中での位置を示す数値が返ってきます。

f:id:fjkz:20180625025559p:plain

また、サンバーストチャートで可視化した結果も返します。

f:id:fjkz:20180625025727p:plain

なんでも、私は――

  • 個性のビッグファイブ中では Openness (経験への開放性)が非常に高く、知的で反権威的で冒険心が強い。また独断的で自分はなんでもできると思っている。

  • 価値観としては、自分の成功や快楽には興味がなく、現状維持にも変化にも関心がなく、唯一周囲の人の役に立つことだけが価値だと思っている。

  • 欲求としては、社交的に陽気にしたいという要求が全くなく、物事が秩序立って整理されていることを求めているそうです。

自己認識と異なるところがありますが、少なくとも文章に書いている内容とは一致しているように思います。なかなかすごいですね。

文章からどのように個性を計算しているのでしょうか?まさか文章を読んでいるわけではないと思われます。きっと単語に分割して、それぞれの単語が個性の要素に対して持つベクトルを足し合わせているのでしょう。おそらく仕組みとしては、そこまで難しいことはしていないように思われます。難しいのは精度を上げることなので、その点では完成度が高いと言えるでしょう。

これが何に使えるか?マーケティングでしょう。性格診断の結果と顧客の行動に関連があることが明らかになれば、いろいろとマーケティング施策が打てそうです。ただ、性格診断の結果と顧客の行動を突き合わせて、両者の関係を調べることができる会社なんて、日本に5社もないでしょう。また、ほとんどの場合、明らかになることは元々その会社が知っていたことか特に有益でないことではないかと思います。面白いけれども、これを商用に使わせるのはなかなか大変なのではないかと思いました。