phpmentors-jp / mpdosaka

マルチパラダイムデザイン読書会
28 stars 0 forks source link

第3章 可変性分析 #3

Open iteman opened 9 years ago

iteman commented 9 years ago

前章では、共通性(commonality)について詳しく調べてきた。多くのソフトウェアパラダイムの根底には2つの主要な設計上の思考方向(demension)があるが、共通性はその1つである。例えばC++のような言語では、共通性を実現することが可能である。本章では、パラダイムのもう1つの設計方向、すなわち、あるパラダイムにおいて類似している要素がどのように異なるかを示す設計方向を対象にする。ファミリ構成員間には、無限と言っていいほどの相違があるかもしれないが、ドメインの持つ可変性(variability)をパラメータ化することによって、抽象の「計り知れない威力」を発揮させることができる。ここでは、C++で共通性と可変性を実装するという側面から、可変性分析について述べる。また、ドメイン構造を単純に図示することのできる可変性依存図(variability dependency graph)を紹介する。 ― 新装版 マルチパラダイムデザイン p.71

hidenorigoto commented 9 years ago

負の可変性の話と、 https://twitter.com/esumii/status/561996511358107648 の「円-楕円問題」

「円を楕円のサブクラスにすると、『楕円を横に伸ばす』メソッドがあったら、円も実装する必要があって困る(意訳)」 これだからオ…いや何でもないです

  • 人間の自然な感覚で、「円」と「楕円」のどちらが「一般的」なのか。
  • 数学的な定義(円は、楕円の一種である)と反対になっているのではないか
  • 負の可変性を認めれば、素直に解決できるのではないか
iteman commented 9 years ago

可変性と共通性の関係

3.1 可変性:生の芳香 (p.71)

共通性が設計の骨格であり、骨組みを形成するものなのに対して、可変性は血肉であると言える。アーキテクチャから考えれば、共通性分析はアーキテクチャを永らえさせるものであり、それに対して可変性分析はそのアーキテクチャを利用し得る形に仕立て上げるものということになるだろう。

具体的な例を挙げると、ドメイン特化言語が可変性を表現し、その背後にあるドメインコンポーネントが共通性を表現するということになる。

iteman commented 9 years ago

可変性と共通性次元の関係

3.1 可変性:生の芳香 (p.72)

アプリケーションドメインの構造は、同一の次元軸に沿って可変させることができる。その軸を決めるのが共通性である。

選択された共通性の設計次元によって可変性の特性が定まるということだと思う。

iteman commented 9 years ago

可変性分析の実施タイミング

3.1 可変性:生の芳香 (p.72)

可変性分析と共通性分析の両者で共通性カテゴリの用語を使用するので、この2つのアクティビティは同時に実施されるべきだろう。

iteman commented 9 years ago

共通性分析と可変性分析の成果物

3.1 可変性:生の芳香 (p.73)

ドメインエンジニアリングは共通性分析と可変性分析を支援する。そしてその際に、共通性、可変性、バインディング時期、デフォルト、ドメイン関係を把握するための記法を利用する。共通性分析と可変性分析の成果物は、その記法で表現された成果の集合に成る。可変性分析を終えた段階で、多くの場合、これらの成果物を下位レベルの設計(クラスと関数プロトタイプを書くこと)への直接の入力とすることができる。

具体例は第9章 共依存ドメイン 9.3 例:状態遷移マシン pp.252-259を参照のこと。

iteman commented 9 years ago

正の可変性

3.3 正の可変性と負の可変性 3.3.1 正の可変性 (p.74)

メッセージサイズとヘッダフィールドの内容に関する可変性は、メッセージをメッセージたらしめる共通性からは独立している。メッセージは、ヘッダに空のフィールドがあろうとも、依然としてメッセージである。1バイトの本体を持っていようと、256バイトの本体を有していようと、1個のメッセージとして、自由に活動することができる。しかし、ヘッダフィールドのフォーマットとメッセージ本体のサイズは、重要な可変性になる。このような可変性は、その基となる共通性のモデルに影響を与えないので、メッセージにそれ自体の定義を洗練させるような何かを「追加する」ことになる。著者は、これを正の可変性(positive variability)と呼んでいる。この可変性のために、メッセージをメッセージたらしめるベース仕様に対して項目が追加されることになるが、そのオリジナルの仕様は何ら損なわれることがないからである。

iteman commented 9 years ago

負の可変性

3.3 正の可変性と負の可変性 3.3.2 負の可変性 (p.75)

メッセージは必ず本体を持つのだとすると、メッセージ本体のサイズを限定するのは可変性である(ここでは、本体のフォーマットはメセージの設計に無関係であると仮定している)。メッセージの大半が本体を持つが、持たないものも存在するのであれば、可変性が共通性の仮定を破壊することになる。つまり、我々が「メッセージ」の意味であると定義するものの根底にあるとした想定を、可変性が否定するのである。これを負の可変性(negative variability)と呼ぶ。負の可変性は正の可変性とはまったく異なるものである。

iteman commented 9 years ago

ファミリ、レンジ、可変パラメータ、ドメイン

3.4 ドメインと可変性レンジ (p.77)

ファミリ

1個のファミリとは、特定の設計ニーズに適い、1個の「仮想的なマシン」によって生産可能な構成員の集まりだと考えよう。

レンジ

そのマシンが生産可能であるファミリ構成員の全体を指して、レンジ(range、値域)という用語を用いる。

可変パラメータ

ここで述べているマシンは、入力、ノブ、スイッチ、レバーを持ち、それらにより構築しようとするファミリ構成員の特性を制御することができる。この入力を可変パラメータ(parameter of variation)と呼ぶ。

ドメイン

ドメイン(domain、定義域)という用語は、1個のファミリのすべての可変パラメータに対する正当な値の組み合わせ、あるいは、その可変パラメータのうちの限定されたいくつかのものに対する正しい値の組み合わせを示している。

iteman commented 9 years ago

可変性と同値集合、不特定形

3.4 ドメインと可変性レンジ (p.77)

共通性分析によって、重要な共通性を把握しようと考えるのが常である。それにより、再利用が促進されるからである。しかし、可変性を疎かにしてよいとは考えていない。疎かにするのではなく、それに規則性を与えたいのだ。数多くの可変性を同値集合(equivalence)に抽象化することができるのであれば、少数の単純なパラメータですべての可変性を記述できる望みが持てる。この同値集合自身は、3.2節で注意を喚起しておいたように、そのドメインの共通性における不特定形(an anonymous form)になる。これは抽象の1種であるが、ソフトウェアファミリをその構成員の持つ共通性から形作る際に用いる抽象とは別物である。少し飛躍したアナロジではあるが、これは、自然界が共通の遺伝形質を共有する種を形成し、同じ種に属する各々の個体の可変性を管理している方法と似ている。

3.2節の該当箇所は以下のとおり。

共通性自身が可変性のヒントになることも多い。例えば、以下のような共通性を考えてみよう。

TextEditingBuffersであればどのようなものでも、何らかのワーキングセットアルゴリズムを持つ」

間違ってはいけない。これは共通性である。そして、可変性が存在する箇所を指し示している。TextEditingBuffersは、どのようなワーキングセットアルゴリズムを持つかという点で変化する。意味のある可変性は、大部分がこの手のカテゴリのものである。

ここではワーキングセットアルゴリズム同値集合かつ不特定形である。ステートマシンで考えると、「UserFSM(共通性:集約した振る舞い、p.255)は、1つ以上のState(不特定形)を持つ」ということになる。State共通性であるが、可変性を管理している。

iteman commented 9 years ago

設計のツボ

3.4 ドメインと可変性レンジ 3.4.1 例:Text Editing Buffers (p.78)

可変性ドメイン集合は設計の「ツボ」である。適切なドメイン集合の組を可変パラメータに代入することにより、ソフトウェアの設計としてのファミリ構成員の生成を制御することができる。優れた設計であれば、プログラミング言語を用いてその共通性が適切に表現できるが、可変パラメータをどのように表現するかにも、設計の良し悪しがかかっている。

iteman commented 9 years ago

バインディング時期

3.5 バインディング時期 3.5.4 バインディング時期の候補 (p.80)

ソースコードに埋め込まれる共通性と異なり、可変性はどこかのタイミング(時期)でバインディングしなければならない。

3.5 バインディング時期 3.5.5 例 (p.82)

可変性分析を実施する際に、各々の可変パラメータに対して、バインディング時期を把握しなくてはいけない。それによって、設計を活かす適切なプログラミング言語の要素を選択することができるだろう。

springkuma commented 9 years ago

同値集合

数多くの可変性を同値集合(equivalence)に抽象化することができるのであれば、少数の単純なパラメータですべての可変性を記述できる望みが持てる。

同値集合 = 感覚的にいうと「ほぼ同じような仲間たち」、数学的な定義は「反射律・対称律・推移律の3つを満たす関係」

確かに同値集合として可変性を抜き出せるのであれば、上手く抽象化できてるといえる。

iteman commented 9 years ago

デフォルト

3.6 デフォルト (p.82)

デフォルトは、可変パラメータがアプリケーションに影響を与えることがあまりない場合に有効である。

影響の大きなパラメータについては、アプリケーション側で明示的に指定する方が好ましいだろう。

後方互換性のためのデフォルト

私自身の経験では、リリース済みのソフトウェアに新しい可変点を追加した際に、後方互換性のためのデフォルトを用意することがよくある。

ドメイン特化言語の文法定義によるデフォルト値:

<?php
...
class Configuration implements ConfigurationInterface
{
    ...
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $treeBuilder->root('phpmentors_pageflower')
            ->children()
                ->arrayNode('conversation')
                    ->addDefaultsIfNotSet()
                    ->children()
                        ->scalarNode('request_parameter_name')
                            ->defaultValue('CONVERSATION_ID')
                            ->cannotBeEmpty()
                        ->end()
                        ->scalarNode('session_storage_name')
                            ->defaultValue('_pageflower_conversations')
                            ->cannotBeEmpty()
                        ->end()
                        ->booleanNode('end_on_next_step_of_end_page')
                            ->defaultFalse()
                        ->end()
                    ->end()
                ->end()
            ->end();

        return $treeBuilder;
    }
}

この例のブーリアン型のパラメーターend_on_next_step_of_end_pageは新たに追加したものであるが、デフォルトでこれまでどおりの動作をするような値(false)を設定している。パラメーターrequest_parameter_nameおよびsession_storage_nameのデフォルトは、_アプリケーションに影響を与えることがあまりない場合_に該当する。

利用頻度によるデフォルト

3.6 デフォルト (p.83)

プロダクトコードがデバッキングコードほど頻繁に生成されないのであれば、デバッキング状態をオンにすることをデフォルトとしないするほうがよいだろう。そのようにしたほうが、開発者の労力を減少させることができる。

If we turn on the #define, then we can generate a production version. If production versions are much less frequent than debugging versions, then it's appropriate to leave debugging on in the default case. That makes less work for the developer.

デフォルトを表現するソリューション要素

3.6 デフォルト (p.82)

C++には、デフォルトを表現するのに役立つ言語要素が備えられている。例えば、デフォルト引数、基底クラスのメンバ関数、デフォルトテンプレートパラメータなどが有効である。C++では、共通性/可変性分析により把握したデフォルトが直接表現できることも多い。

私自身の最近の傾向としては、デフォルト引数はあまり使わずに、前述したようなドメイン特化言語レベルのデフォルトを使うことが多い。

iteman commented 9 years ago

ドメインとレンジ

3.7 可変性テーブル (p.83)

TextEditingBuffersには、出力型、キャラクタセット、ワーキングセット管理技法、デバッキングコードの持たせ方というドメインにレンジがあることがわかる。このテーブルの列は、レンジを持つドメイン、そのレンジのバインディング時期、デフォルト値を表す。

可変パラメーター(可変性ドメイン)出力型データベースとした場合にできるアプリケーション、RCSファイルとした場合にできるアプリケーション、…がドメインに対するレンジとなる。

iteman commented 9 years ago

ドメイン間の関係と可変パラメータ

3.8 可変性の落とし穴 (p.84)

2つのドメイン間に関係があるというだけでは、片方のドメインがもう一方のパラメータになるということにはならない。すべてのドメインが、可変パラメータの組に確実に関係したものになっていることが必要なのである。

springkuma commented 9 years ago

負の可変性のソリューション

負の可変性のソリューションで以下を検討してみたいです。

http://en.wikipedia.org/wiki/Policy-based_design

マルチパラダイムデザインの後に上梓された本でModern C++ Designで紹介されているパターン。#ifdefを使うよりもエレガントな解法なのかも。

6章で検討すべきテーマなのかもしれません。

iteman commented 9 years ago

ドメイン分割による負の可変性の実装

3.11 要約 (p.87)

合理的理由があって負の可変性を導入する場合には、ドメインをサブドメインに分割すべきである。それができないときには、#ifdefといったあまり汎用的でないソリューションを考慮に入れることになる。

負の可変性のソリューションとして、#ifdefキャンセルを伴う継承(参考: http://www.vincehuston.org/cpp/inheritance.html )が紹介されているが、要約によるとドメイン分割(例えばクラスの分割)によって負の可変性を消滅させることが推奨されているようだ。

3.3 正の可変性と負の可変性 3.3.2 負の可変性 (p.76)

strrecvfdメッセージの使用の半分はKERNELであって、残りがそうでなはない場合には、fpSTRRECVFDの共通性ドメインの主要コンポーネントだと主張するのは難しい。代替案として、この構造を2つのドメインに分割することも考えられる。その場合にはおそらく、ファイル記述子のためのSTRRECVFDドメインと、ファイルポインタのためのSTRRECVFPドメインに分割することになるだろう。このように分割すると負の可変性は消滅することになる。

iteman commented 9 years ago

可変性分析とモデル駆動設計

3.11 要約 (p.87)

ここでは、可変性に関連してドメインとそのレンジについて調べ、さらにバインディング時期、デフォルトについても考察してきた。これらは、可変性分析で最も重要となる特性項目である。可変性分析の結果をまとめたテーブルを用いることによって、このような特性を把握することができる。さらに、この分析構造に対応させて、C++コード構造を考え分析構造に合致させることも、このテーブルにより可能になる。

ドメイン駆動設計の重要な原則であるモデル駆動設計は、問題ドメインの構造に合致した解決ドメインの構造を設計することであるといえる。

kumamidori commented 9 years ago

https://github.com/phpmentors-jp/mpdosaka/issues/3#issuecomment-84231810

20150323081947_trimmed