問題解決はじめにソフトウェア設計についてのポエム。それも、ドメインが短期的なサイクルで大きく変化をしてしまうような領域での。僕が携わる領域、つまりメディアサイトでのSEO施策を反映するシステムでの経験を念頭にしている。結論から言えば、ビルド・アンド・スクラップを可能にしようという話です。「変化の激しく脆いドメイン」とは?問題の解決策のコアとなる部分が頻繁に変わるドメインのこと。プロダクトのライフサイクルよりも早く変わるドメインのことを指したい。僕が携わっている「Webメディア」というのも、この変化の激しく脆いドメインに当たると思う。Webメディアにおける開発では、SEOやUXについて考慮することは避けることはできない。SEOやUXは頻繁に変わるGoogleのアルゴリズムやユーザの嗜好によって正解が変わっていく。一年前に正解だったものが、次の年にはただの技術的負債になっている可能性すらあるからだ。何?少なくとも僕が表す文脈で言えば「問題領域」と訳されるもの。domain」と表されているものを指している。作ることを目標とする工程である。Wikipedia』よりドメインや責務の賞味期限を考えて切り分ける設計をするとき、私たちはドメインに横たわる概念を責務として表現している。*1「決済」というドメインの中には、「買い物の合計額を計算する」「クレジットカード会社との取引を仲介してくれるサービスへ通信をする」などといった責務があるという具合に。したドメインや責務には賞味期限がある。変わりやすさを基準に概念に境界を引いていく環境や状況というのは常に変化をするもので、それにともなってある時に問題だったものが問題ではなくなり、その解決策も解決策ではなくなってしまう。時間だけでなく場所を変えるだけでも、問題が変化してしまうことさえある。解決策が技術的負債となって襲いかかってるくることも...。和暦は日本ローカルな紀年法で世界では使われていない。日本で展開しているサービスで生年月日を表現する際に、その表現の解決策として和暦を使っていたとする。そのサービスが運良く成功して海外展開をしようという時、その概念に依存して構築されたシステムは技術的負債になるかもしれない。このような変化によって発生する技術的負債に対処するためには、概念の変わりやすさを基準にして設計を考えるといい。ここで「変わりやすさ」を基準に、変わりやすいものを脆い、変わりにくいものを堅いとする。ある概念を表現しようとするとき、概念を掘り下げて境界を引き脆い責務と堅い責務を切り分けましょうという話。することで、堅い責務を表現したモジュールを脆い責務の変化の影響から守れる。*2つまり、脆い責務によって発生するシステム改修の影響を最小限にとどめることができる。先にあげた例で説明すると「和暦は時間の表現方法の一種類に過ぎないので、時間を表す責務と切り分けて考えると良い」という話。時間を表す責務は堅く、時間の記法である和暦の責務は脆い概念にあたる。和暦は天皇の交代という短めのサイクルで変化が起こることがわかる脆い概念なので。コードに落として考えるとしたら、時間classと時間表現classを別々にすると良い、という感じだろうか。class、あるいはダックタイピングの利用を検討すべきだと思う。時間表現interfaceでアプリケーション内における時間表現の概念を定義して、それを実装する和暦表現classで計算して出力するという具合だ。脆い概念を堅い概念に依存させるそして、切り分けた2つの責務を組み合わせて元の概念の表現しようとするときは、脆い責務を堅い責務に依存させたほうがいい。コード上の変更の影響は結合によって発生していて、その影響は依存関係によって各モジュールへと伝播していくので。これも具体的に説明する。時間という概念を表す時間class、時間表現の1つである和暦表現classがいるとしよう。Rubyの擬似コードで表すならば、以下のように設計できる。end汎用的な時間表現を西暦の時間classにもたせて、和暦表現が必要なタイミングのみに変換をするように設計する。することで、和暦表現classに新しい年号を追加するというイベントが発生しても、変更の影響範囲は和暦表現classとその利用箇所にだけとどまる。時間classを利用している箇所には、変更の影響が及ばないはずだ。時間class自身も、便宜上の理由で西暦を使っていて、時間表現でないと言ったら嘘になる。いえ、時間を表現するためには何かで時間を代表させる必要があり、そこで西暦を選んだのは国や時間が変わっても使われているだろうという見込みが高いからだ。和暦に依存する場合に比べて変更が発生する回数少ない堅い設計になるはずだ。賞味期限の早いものは「捨てやすく」しよう賞味期限が切れたモジュールは、開発の邪魔になりがちである。いわゆる技術的負債となっていることが多い。無意味だけれど、なぜか動き続けているロジック一部の機能はほしいけれど、そこまで大きい必要がない過剰に高機能なclassメディア側では見えていないのになぜか残っているコードgrepにたくさん引っかかる謎の動いていないコード...etcこうした技術的負債は、回り回っていつか自分の足を撃ち抜くような事故に至る可能性がある。した技術的負債によって、プロダクトのコード量が無駄に増え、変更の影響範囲が拡大し開発工数を増やすこともある。その存在自体が割れ窓理論的にコードの治安も悪くしがちなため、早急にご退場を願ったほうがよい。Wikipediaとはいえ、そうした技術的負債も過去では金脈だった可能性もあり、様々な施策で利用されて巨大なモジュールと化し、簡単には捨てられない可能性がある。技術的負債を捨てやすい設計にするためには、不要になる確率の高いモジュール(以下、脆いモジュール)の依存関係を最小限に抑える設計をすることだ。脆いモジュールとは、変化の激しい領域で設計されたものであることが多い。それは上で説明したような脆い概念の領域だ。社内システムで職場のルールを実装する場合がここに当たるだろうか。ある年に作られたルールが、次の年には撤回されている可能性すらあるはずだ。脆いモジュールの依存関係を最小限に抑えるとは、「依存性逆転の原則」に従うことである。Wikipediaというのも具体的な概念ほど脆い傾向があるため。具体的な概念に依存する必要がある場合は、それが変化することを前提にするとよい。具体を直接使うのではなく、その抽象に依存するように設計するということ。総務に備品の購入の申請をする社内システムがあるとしよう。入力フォームで必要事項を記入し申請ボタンを押すと、備品の購入ルールに基づいたチェックが走ると考えてほしい。そこで、ルールチェックclassと、個々のルールを表現した申請ごとの上限額ルールclassや金額の参照元の入力ルールclassなどがあると想像してほしい。classあるいはダックタイピングとして定義をして、それに依存するということだ。Rubyの擬似コードで表すならば、以下のように設計できるだろうか。その結果を#valid?で返すというダックタイプと考えた。endend...こうすることで、ある年にルールが増えたり消えたりしても、ルールclassを追加したり削除をしたりするだけで済む。ルールclassを利用する側である備品購入ルールチェッカーclassのロジックを変更する必要はない。*3最後にこの僕の考えは以下の書籍がベースになっている。非常にオススメなので、本屋などでお手にとっていただければと思う。見る*1:「そもそも責務ってなんだよ」という方にオススメの記事。巻之二*2:モジュールという表現は、各プログラミング言語におけるclassやpackageなどのひとかたまりのコードを表している。関連記事2019-09-30退職をしてNAISTの修士課程に入学します※これはポエムであり、自分語りです。時系列順に書き連...2019-08-13ジョブ理論を読んだけれど、読み甲斐のある一冊だったジョブ理論を読んだ。バズってる記事への便乗記事。思い立ってCourseraの機械学習コースを修了した。はてなブログProWebエンジニアやってます。sudoを使えないLinuxのユーザがPackageを管理するための魔法の杖NAISTに入学してからもうすぐ3ヶ月が過ぎます。Base"とはなにか、そしてその可能性。NAISTに入学して一ヶ月が経ったので近況報告。退職をしてNAISTの修士課程に入学します月別アーカイブスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。