2013/02/28
システムの非平衡状態
昨日のエントリで、システム中のあるユニットを変更した時に、それに依存する部分を全部一気に変更するのでなく、システムを動かしながら徐々に変更を伝搬してゆく、という運用について触れたんだけど、具体例を書かなかった。というのは現場で出てくる具体例って色々なしがらみに依存して話が難しくなってることが多くて、そこらへん説明するのも冗長だってのと、個別のケースについて何とかしようと思えばどんな道具を使っても「頑張れば何とかなる」ってことが言えちゃうんで。実際の言語の使用感ってのはその「頑張る」をどのくらいに感じるかってところに帰着するんだけど。
それと、ある言語でプログラムする時はその言語で考えるから、その言語で書きづらい事態というのをそもそも想定しないというか、無意識にそういうスポットを避けられるように設計する。なので「こういうのが書きづらいじゃないか」と言われると「確かに素直には書けないけどそもそもそういうのを書きたいと思わないし。どうしても必要なら無理すれば書けるからいいんでない?」って感想になっちゃうことが多い。
そんなわけで、「変更」とか「不平衡」とか聞いても人によってイメージするものが違うんで、話がややこしくなるってのはある。
まあそれでも敢えてひとつ、単純化した例を考えてみよう。
プロジェクトメンバーを管理する。メンバーはidと名前と所属セクションを持つ。
data Section = Research | Production | HR | Management deriving (Show) -- Member id name section data Member = Member Int String Section deriving (Show)
あらゆるシステムがこのデータ型を前提に組まれている。
ところがある時、「複数のセクションに所属するメンバー」というのがありえることがわかった。
つまりMember
の定義は本来こうあるべきだったのだ。
data Member = Member Int String [Section]
これが正しいモデルなので、最終的には全てのコードをこちらに収束させたい。
でもMember
を使ってるシステム全てを一斉にアップデートすることはできない。
一部の、どうしても複数セクションを扱いたいユニットだけには複数セクションを見せて、
それ以外のユニットについては、複数セクションに所属するメンバーは
「そのうちのひとつのセクションだけが見えてればいい」とする。
(一応優先順位があって、最優先のものが見えるようにする。)
さてどうする。
Haskellだとどうするんだろ。MemberEx
みたいな別定義にしといて、
既存のコードに対しては MemberEx -> Member
とか
Member -> MemberEx
なアダプタを噛まして対処するのかな。
慣習がよくわからない。
CLOS系なら変える必要があるのは一ヶ所だ。こういう元コードを:
(define-class <member> () (id :init-keyword :id) (name :init-keyword :name) (section :init-keyword :section) )
下のように変えておけば、メンバーが一つのセクションだけに所属すること前提のコードと
複数セクションを見るコードが混在した不平衡状態のまま運用を続けることができる。
change-class
メソッドも書いとけば、
動作中のコードにロードして動かしつづけることもできる。
(define-class <member> () (id :init-keyword :id) (name :init-keyword :name) (sections :init-keyword :sections :init-value '()) ;; for the backward compatibility - remove after migration is completed (section :allocation :virtual :slot-ref (^o (car (~ o 'sections))) :slot-set! (^[o v] (set! (~ o 'sections) (cons v (delete v (~ o 'sections)))))) )
まあ静的型でも「フィールド直接アクセス禁止して常にアクセサ経由にしとけばいいじゃん」とは言える。その意味では程度問題。当初からどのくらいこういった事態を見越して書いとくかって話になる。
それに、「別定義にしてアダプタを噛ませとけば、後から直してゆく時に直すべき箇所が見つけやすいだろう。やっぱり静的型がいい」って考えもあるだろう。
あるいは「sectionとsectionsの関係がill-definedで、こんないいかげんなシステムは既に崩壊してる。このシステムの存在自体がバグである」という立場もありだろう。(自分は「え〜これとそれはone to manyって最初に念押ししといたじゃないですか〜なんでいつの間にかmany to many前提になってるんです〜?」みたいな話がありすぎる環境にいたから、バイアスがかかってると思う。)
結局何がメリットかってのはどの立場を取るかで変わってくるから、「××がメリットなんだ!」という記事は「俺はこういうケースで楽をしたいんだ!」という主張と読むべきなのかもしれない。
ちなみに上のように変えた後で、「いや、やっぱsectionはひとつで良かったわ。戻しといて。」ってなることも、よくある。
Tag: Programming
nobsun (2013/03/01 06:18:54):
jmuk (2013/03/01 06:53:52):
shiro (2013/03/01 09:08:24):