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

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割以上を単一のリスク資産に賭けるのは逆効果だということが分かります。

マネージャをマネジメントする。

マネージャと呼ばれる職種の人はどこの組織にもいます。いわゆる中間管理職の人々です。個人の人格は別にして、彼らには組織上の機能の要請から、共通の行動原理があります。マネージャは例外なくこの行動原理にしたがって動きます。特に優秀なマネージャであるほど原理に忠実に動くものです。そのため、マネージャというロールの人々は行動の予測がしやすい; 別の言い方をすると御しやすい人々だと言えるでしょう。マネージャをマネジメントするのは、サラリーマンスキル(コンピテンシというやつ)の一つで、彼らをコントロールできた方が楽に仕事ができるようになります。

今回は、私が長年の観察により発見しましたマネージャの行動原理を挙げまして、マネージャを御する方法を考えてみたいと思います。

マネージャは自分の立場を守る。

全ての管理職は自分の立場を守ること、つまり保身を最も優先します。自らの責任範囲で悪いことが起こらないことに最も注意を払って、仕事をやり過ごすことに注力します。それがミッションなのだから当然です。一般社員と比すればマネージャは責任感が高いでしょう。また、マネージャはもっと上の人に一般社員より遥かに厳しく詰められます。責任は責任範囲の中にしか生まれませんので、責任範囲を守ることに執着するのは自然なことでしょう。

一方で、責任範囲の外にはあまり興味がないものです。例えば、事業の利益や会社の利益、あるいは人類の利益になんかは、一般社員と同程度によそごとだったりします。前の会社でマネージャが「こんな泥船の部署……」と言ってたのには、それはお前の責任やろと思ったりしましたが、マネージャというのはそういうものです。

基本的にマネージャは自分の立場を守ることしか考えない――これが第一原理です。マネージャは組織上の部署の機能に忠実です。内心は別のことを思っていても、立場的に立場を守るようにしか動けないものです。不自由と言っていいかもしれませんが、大人には不自由が好きな人が結構います。制約条件の中でうまく立ち振る舞うことによろこびを感じる人、要するに出世志向の強い人です。また、しばしばいる考えの読みづらい冷徹なマネージャも、おおむね頭の中にあるのは自分の立場のことだけです。覗いたことはないものの、その仮説でもって説明できなかった場面には未だ出会っていません。

マネージャが部下のことを慮るときも、それは立場上やっているだけと考える方がよいです。部下の利益も彼らにはよそごとです。彼らはわれわれの人生になんて興味はない。彼らは親ではありません。部下が自分の立場を守るのに有用か、あるいは有用にするのにはどうすればよいのかにしか興味がないと考えた方が、彼らとは付き合いやすいでしょう。

一般社員として仕事をするときも、マネージャの立場を守るのに有益になるように仕事をするのが、彼らには喜ばれます。天下国家のためなることであっても、彼らはそれを仕事とは認めません。「2つ上の役職の立場に立って考える」というのが、サラリーマンとしての上手な立ち振る舞い方だと言われていまして、マネージャにとって有用に働くのが平社員にとっては楽な生き方です。

マネージャは受動的である。

組織にはトップダウンボトムアップというのがあって、大体のマネージャはボトムアップを好みます。上がってくるレポートを聞くだけ、これをやっていいですかという相談に承認するだけ、稟議書に判子を押すだけ、といったやってきた情報に相槌を打つ仕事をボトムアップと呼んでいます。ボトムアップで来るものに対して頷いて、たまに思いつきで適当にコメントを返すというのが楽ですよね?君臨すれども統治せずといった感じでしょうか。元よりマネージャのロールとして、承認フローやレポートラインの中継以外の役割を求められていないという場合もあろうかと思います。それは彼らが好んでそうしたのとそれでうまく回った結果そうなったのでしょう。

いくら赤べこの張り子人形のように頷いているだけを好んでいても、うなずくだけでは済まない問題がボトムから上がってくることもあるかと思います。しかし、それはそんな厄介事を上申する奴が悪いのです。「なんでなんだ」と詰問すれば、問題を引き受けずに投げ返すことができます。再び前の会社の話で、ゼネラルマネージャ級の人が「重大な障害が起きてしまいました。起こした人は反省してください。」と言ってました。確かに彼らの立場からしたら、問題は自分のあずかり知らぬところで「起きる」もの・下々が「起こす」ものでしょう。でも、そんなスタンスで僕らに話されても、何も変わらないのだろうと思ったものです。

偉い人は、座って待っていたら、下僕たちが問題の解決策を持ってきてくれて、実行してくれることを期待しています。いわゆるマイクロマネジメントは疲れますので、やりたくないのです。意思決定もしたくないし、頭を使うこともしたくない、指示も出したくない。報・連・相でいうところの相談は嫌がる。言ってしまえば、彼らはマネジメントなんて仕事はしたくないのです――これが第二原理です。一般社員のわれわれは、これを理解する必要があります。

そして、マネジメントをしたくないマネージャのために、われわれは「忖度」をしなければなりません。言わずとも知らないところで勝手に問題が解決しているというのが偉い人にとっては理想的な状態です。上官が何も言わないのに下官と意思疎通がとれるのは、忖度という高度なコミュニケーションを下官がとっているからです。大学にいた頃に、助教の人が「先生はこうおっしゃるだろう」とか「先生がおっしゃったことの真意はきっとこうだろう」と、教授の思いを憶測して動いていました。当時は忖度という言葉を知らなかったから、シャーマンになって教授の霊を憑依させているんだと揶揄しておりました。人間には、他の人の思いを脳内でシミュレーションできるという能力があります。面白いことに現実の上司と脳内の上司のいうことに大きな齟齬はありません。私たちは、現実の上司の意向に加えて、脳内の上司の意向に従って、働くべきなのです。脳内上司に忠実な人が有能なスタッフとされます。

マネージャは不確実なものを嫌う。

報・連・相のうちの相談は嫌がったとしても、権限と責任の範囲内での意思決定をすることはマネージャの仕事です。われわれとしてもスタンプラリーをクリアするために、判子を押してもらう必要があるので、彼らに意思決定をしてもらう必要があります。

判を押す人から見ますと、確実に正しい答えであることに対しては判を押しやすいものです。サイコロを振って1以上の目が出ることを保証してくださいと言われて、それを認めるという判断をするのは容易です。一方で、確実でないことを判断するのは難しいことです。サイコロを振って1の目がでることを保証しろと言われても、それを認めることはできません。6の目が出たらどうするのでしょうか。テメーそんなものに判を押しやがってと責められますよね。明らかに誤った判断をしないというのが、責任というものです。現実は、理想的なサイコロの目と違って、確率など計算できない種類の不確実さを持っています。これに対して判断を下すことは難しいことです。

そのため、マネージャは不確実な状況下で意思決定をするのを嫌がります――これが第3原理です。こういうときには、意思決定をしないという判断がしばしば行われます。つまり現状維持、問題の先送り、負債の繰り延べです。ポイントは、これらが結果として誤った判断だとしても、意思決定をしていないので、責を負うことはないということでしょう。そもそもマネージャには明らかに誤った判断をしてはならないという職責はあっても、結果に対する責任ないですから。

正しいことの蓋然性が高い解、つまり明らかに正しい答えを認めないというのは、明らかに間違った判断ですから、マネージャは立場上これを拒絶するわけにはいきません。われわれとしては、明らかに正しい答えを用意しておいて、マネージャがただうなずくだけで良いようにお膳立てするべきです。彼らが一緒に悩んでくれて彼らから答えが見つかるなんてのは期待せずに、彼らが頭を使わないようにするのが正しいです。

現実はきれいではないので、不確実なものです。現実をそのまま反映したら、きれいでない判断材料になります。そういうのは持って行ってはいけません。いい感じに抽象化して、筋が通っている情報であるようにきれいにしなければなりません。具体的な「正しい」情報が欲しい人は、元より一次情報にあたりますので、それをしない人はそもそも正しい情報なんて求めていません。彼らの要望に合わせて、クリーニングされた情報を渡してあげるのが、親切です。


悪意をもって長々と書いてしまいました。個人の人格は別として、マネージャという役は好きではない。理想的なマネージャは機械化が可能だとすら思っているし、彼らを機械化するように動くのが理想的なサラリーマンなのではないかと思っています。理想的なサラリーマンは、結局コンサルタントや官僚のようになってしまうのでしょう。

また、仮に間違ってマネージャにさせられてしまったら、私もマネージャの行動原理にしたがってロボットのように動くのだと思います。飼い犬とはつらいものです。

接点 t を見つける

現実はおそらく一つなのだろうけれども、どの断面で切り取るかによって見え方は全く異なるものになります。人の知性では世界をそのまま認識することはできず、何かしらのフィルターを通して世界を見て解釈します。フィルターとはフレームワークパラダイムやモデルと言い換えてもよいでしょう。生きていますと世界をもっと合理的に解釈できるような新しいフィルターを見つけたり、これまでのフィルターでは解釈しきれないような新しい事象に出会ってフィルターが外れたりします。このときが生活していて最もよろこびを得るときだと、私は思っています。

「接点 t 」とは、高校数学で2次関数・3次関数の数曲線の接線を求める問題の有名な解法のことで*1、この解法を初めて学んだときに狐につままれたような気持ちでした。接点 t はこちらが勝手に置いたもので、それを通る接線なんて存在するかどうかも分からない virtual なものです。しかし、方程式に解が存在したとき、接線が実在するものとして現れる。ないのにあるとはどういうことだ?解があることが存在するということなのだという新しい視点に、世界がひっくり返えるような驚きを感じました。

学びのよろこびとは、できなかったことができるようになるとか、生活の役に立つとか、実学としてのよろこびもあるものの、世界の見え方が変わる以上のよろこびには未だ出会ったことがありません。狭い視野から見た既存の世界を維持するために働いている人々は、一体何が楽しくて生きているのだろうと不思議に思ったものです。学びを否定し、変化を嫌がる――そういう人が社会のほとんどを占めていると知ったことも、強烈なパラダイムシフトでした。

数の世界よりも、今では人間の世界の方が面白いです。数学はきれいになるように作っているからきれいなのですが、社会は複雑で汚いです。一見複雑な社会や人が、理にかなって見えるフィルターを発見するのが、楽しい。社会や人に関しては「物語」と呼ぶのが適当でしょうか。社会や人が合理的でなければならない必然性はどこにもなく、社会や人を統べている一般法則なんてきっとないのでしょう。それでも、人間の悲喜こもごもを見て、そこに物語を見出すのは無上のよろこびなのです。

社会にはいろんな人がいます。均質でない人々が集まると、衝突があったり、化学反応といわれるような思いもよらない結果になったりします。事件が起きる現場では人は思いもよらない動きをします。人は間違うし、裏切ります。そういう現場に居合わせたいものです。

また、物語を見たいがために、デスゲーム的なもの・スタンフォード監獄実験・ミルグラム実験みたいなものを主催することを夢想します。もちろん犯罪でも悪事でもないことが前提です。私はきっと社会実験がしたいのでしょう。バンク*2という会社の実験的な試みを見て、羨ましく思います。あのサービスを始めてから彼らの世界観はきっと大きく変わったでしょう。

新しいパラダイムを見つけるというのは偉業です。他者の世界観を変えるようなパラダイムを見つけたいものです。世の中の人は世界が変わって見えることを求めていないのかもしれませんが、社会というのは変わり続けているので、それを合理的に解釈できる新しい枠組みが必要です。商売も新しい枠組みに嵌ったビジネスが成功しているのだと思います。ただの趣味であることに加えて、実利的な目的のためにも、俺の「接点 t 」を見つけたい。