ソフトウェアのインターフェースについて考える
レゴのたとえ
編み物とレゴ
どこで読んだっけこれmiyamonz.icon
ここだ
レゴのインターフェース
あの粒粒の面
あれさえ同じなら、任意のブロック同士が、その面で繋げられる
境界は面で、ブロックの形状は自由である
似た存在として、マインクラフトが挙げられる
reducer
(state, action) -> state
state: 状態の変化を、関数で表現する
mutableなstateを、変化前と変化後を関数で表現する
actionによって、その変化のパターンを分岐する
jsの場合は、actions.reduce(reducer, initialStatus)このように書けたりする
トランスフォームにおける行列
translate, rotate, scaleといったものを行列として、単なる行列のスタックとして表現する
これは、型としてはreducerとほぼ一緒
いや、違うな。単に群を成しているだけだな
群はその演算でfoldできるからreducerになるというだけか
vimのテキストオブジェクトとオペレータ
ciw
change、 inner word
動詞と範囲を入力して、編集する
blender
adobeのレイヤーとマスク
レイヤーによって、複数のフレームを重ねて最終出力を作る
階層構造も取れる
マスクという概念を入れる
マスクはレイヤーの一種で、階層構造に入れることで、そのツリー内の範囲を狭めて親に結果を伝える
この階層内で、色調の調整などをする
↑ここらへんは、対象と操作、主語と述語、というペアのように見なせる
対象、というものがあるということは、対象全体は、なにか空間的な広がりがあるもので、その部分を対象と呼べる
テキストエディタならバッファとテキストの一部分
photoshopなら最終的な成果物の画像と、レイヤー
そもそも、概念がなんらかのcomposableなもの、とみなす、というところがある
photoshopの例だと、レイヤーというのは階層構造なので珍しくないが
マスクという概念が優れていた
マスク自体はシンプルだが、レイヤー概念と相性がよかった
宣言的UI
コンポーネントという単位
これは、htmlという階層構造、木構造を、コンポーネントの集合、結合で表現できるという視点がある
プログラムを関数で組み合わせてつくるという行為を、木構造でも同じようにそのまま実現できてる
pipe
標準入出力という行指向ストリーム
コマンドをパイプで繋げていく
A | B | C
なにか全体としてストリーム処理をする際、それを個別のコマンドに分ける
個別のコマンドもまたストリームである
個別のコマンドは、ストリームを流す以外のやりとりをしない
なんらかのデータは、行単位の集合であり、データの加工を行単位で行える場合に有効
スクリプト言語だと、mapとかfilterとか、配列に対する関数になる
関数型言語の知見を学ぶと良い
middleware
入力に対して出力を返すような概念
request と responseとか
2つのラインをまとめて、ミドルウェアという単位を作る
pipeと似ているが、処理の流れが折返している点が違う
→→→→↓
←←←←
ここまでの話をまとめると
作りたいものは、なんらかの部分の集合である、という前提がある
その部分を切断する方法、切断面という境界を見出す。(インターフェースは訳せば境界という意味だ)
切断された部分がどういう中身、形状?なのかを考える
その型を考えると、部分と部分の結合方法の演算が見えるはずだ
結合した結果も、同じ型になっているはず
数学で言うところの「演算について閉じている」というような性質になっていると良い
切断ができるということは、要素をプラガブルにできる
変更、修正したい箇所が、切断面を境界として、外部に影響しないで済む
パターンを分類すると
主語述語パターン
vim,
流れを分割するパターン
reducer
pipe
middleware
どちらにも入りそう
adobeのレイヤーとマスク
他のパターンがありそうだ
この2つも、厳密に言うと概念が直交してるわけではない
主語述語パターンも、その操作の組み合わせでスタックされ、reducerやpipe的な認識ができる
その操作が、ユーザ入力なのか、コンピュータ上のデータとして扱うのか、といったスコープや粒度の差かも
「流れ」というのは絶対に存在して、
主語述語パターンは、流れをゆっくりしたときの、流れの中の具体的な動作に焦点をしぼっている、と見れる
プラグイン的な話
event hook
さまざまなプラグインというのは、元のなんらかのフレームワークに対して、固有のイベントが有り、それにhookする形で処理を呼び出させる
rollupとか
そもそも、フレームワークがそういう仕組というパターンもある
これは、フレームワークのアーキテクチャ変更に弱い
凝集性を高めにくい、といった傾向を感じる
reactがclassをやめて関数コンポーネントに方針を変えたのもこれが理由だろう
が、めちゃ悪い概念というほどのものでもない
hooks
reactのhooks
これは、「レンダリング」というイベントを単一の特殊なイベントとみなした上でのevent hookのパターンの一種と言える
eventが単一なので、eventが複数あるがゆえのカオスは生じにくい
単一であるのでストリームとしてみなせて、メモ化したり、別のhookを呼んだり、composabilityが高い
ストリームとみなして、その内部では外部のことはあんまり気にしない点はpipeと似てる
ただし、callback関数などを露出してなんかしたりはするから、pipeのほうが簡素である
後で呼ぶべき処理を、setupの返り値として関数を渡す
subscribeとunsubscribeが同じオブジェクトから生えてるよりも、何かと良い
syntaxや型レベル等でやるもの
pythonのwith,
JSで新しく入ろうとしてるusing
RustのDropトレイト
c++のdestructor
goのdefer
スコープ等で区切られて、勝手に呼ぶので、呼び忘れがない分の安全性がある
ただし、cleanupタイミングがスコープレベルでない場合は、関数を返すのが適切だろう
useEffectとか
ここまでは、ソフトウェアのインターフェースについてだった
なにか大きなものを作るための、個別のモジュール、それらの結合方法
composableな筋の良いモジュールをどうやって捉えるか、という考えだったのかも
一般的にいうと、インターフェースはもうちょっと違う概念をさしてそうだ
スマホのインターフェースとか
ユーザインタフェースか
ユーザとソフトのインターフェースで、
ここは結合対象?が
モジュールとモジュールじゃなくて、
ユーザとソフトウェア
みたいな感じで考えた方がいい
なので、結合による演算が閉じるべき的な話が通じない
ユーザ、という存在が固定であるがゆえに、考えるべきことが少しfixされる
しかし、そこは、ユーザについて考えるというより、ユーザが作りたいもの、ユーザが触るべきものについて考えるべきか?
よくわからんくなってきた
組織のインターフェース?
そこらへんも考えたい
万物は流転する
常に変化し続けるものを、構造で捉えるのは難しい
不変、普遍なものを見つけると良い
螺旋のように変化するものもある
このときは、周期で区切る
時間軸という絶対的な、変化の軸がある
ここに周期性が見いだせると、その周期で切ることでインターフェースを見いだせるかもしれない