読書会(アジャイルソフトウェア開発の奥義)第7回議事録

[ 戻る ]


java 読書会 <http://www.javareading.com/bof/>

BOF in 高津区民館 第 4 会議室 at 2005/04/14 10:00 - 17:00

出席者(敬称略)

        前

    開始 →
    +---------------+↓
    |        |
    |    机   |
    |        |
    +---------------+
    ↑       ←


中島, 根本, 吉村, 岡沢, 高橋(徹)
栗野, 亀井, 岩永
金井, 藤井, 野辺, 奥, 高橋(智), 吉本, 山澤
村山, 村上

朗読者: 岩永, 村上, ?(根本/吉村), 吉本
書記: 栗野

本 : 「アジャイルソフトウェア開発の奥義」

==

すこし、人数がぶりかえした
    やっぱり、宣伝をした効果が .. ?
    シーサー ML での宣伝 ?
        会合(シーサの Source を読んで J2EE を勉強しよう)が重なっている
            シーサーの会合と日程がぶつかっている..
                宣伝効果がないのでは ?
                    もともと、メンバがかぶっていないから..

[自己紹介]

概要 ( 初めての方がいらっしゃるので.. )
    基本は 10:00 から
    # 実は、会場は 9:00 から借りており、9:00-10:00 では番外をしている

    最初は、自己紹介
        初めての方は、是非、読書会を知った切っ掛けを..
            # 最近、人数がへってきていたので..人数をふやすための参考に..

    読み手を選出
        途中で、質問があったら、その場でする

    書記
        途中であった、議論を箇条書にして、あとで ML に投げる

    5:00 終了なので、その後は、有志で、飲み会などを..

# 以下、略

==

# p. 358
# 22.3 から

==

22.3 再利用・リリース等価の原則 (REP)

    給与システムを再利用をするには ?
        できる部分とできない部分がある
            PayrollDomain などは Okey だが..

    再利用は Package 単位での再利用になる ( class を一つだけということはない )
        なぜなら、Package には、凝集性があるから
            Package の一部を使おうとすると、他の部分も必要になる

        Package は、互いに関係ある(閉鎖性)というだけでなく、
            「一緒に再利用される」という観点で、まとめるべきである。

    # 一つの Package を使う時に、他の Package をひきずるのはよくない !!

    もし、Pacakge の一部だけを抜き出すと..
        Package のリリース構造に悪影響を与えることになる
            Pacakge の管理が大変になる

        # 例 : Package 内の自分が利用していない 
            => Code の変更があった場合も、管理作業 (Test など) が必要になる

        => これがいやだと、Copy を作ってしまう
            これは、実質上、再利用と呼べない (むしろ「二重苦」になってしまう)

    Package は、再利用可能な単位で作成する必要がある
        => 再利用単位でない Package は、
            リファクタリング(パッケージ構造の変更)が必要となる
            # 本書では、実際に、パッケージ構造に対する変更を行っている
                => Transactions class を再利用できるようにした

    Q. 図の違いは ? ( 22.2 と 22.3 )
        A. Transactions class を他の package から切り出して、
        新しい pacakge を作っている点

    Package をいじることにより、新しい抽象 Layer ができた
        メリット : 保守性と、再利用性は向上する
        デメリット : Package 構造が複雑になり関連もふえた
            => 適用は慎重に ( 必要にならなければやらない )

            再利用をする者が少なければ、パッケージ構造はそのままで..
                多くなったら、構造を変更することを考える

    Q. 1 パッケージ、1 jar (DLL) 化という話は ?
        A. 前回も話題になった
            Domain 単位 ?
            普通、リリース単位で jar を作る

    Q. ここで Package といっているのは Package 図上 (論理的な構造) ?
        A. リリース単位といっているので、おそらく jar/DLL の話 (つまり、物理的な構造)
        Q. ここでは論理的な話をしているのでは ?
            A. 折角 java の話をしているんだから、具体的な業務レベルでのプラクティスも知りたい
            p.320 ( 全再利用の原則 )
                1 パッケージ 1 jar の形が良いという結論では ?

            変更された場合に、影響された範囲をできるだけ狭くしたい

            Q. 下層が変更されたら、結局依存関係があるので、同じでは ?
                A. java だったら I/F が固定されているので、Okey
                    C++ はあぶないかも ?
                A. (jar 内の.. ) Manifest で頑張るとか ?
                A. 依存関係は、IDE で頑張る
                    jdepends を使うとか .. ?
                    # リフレクションを使ってなければなんとか自動化可能かも..

            A. 結局 Library 関係の変更の影響はまぬがれない
                => このために、Maven が ..

            Q. この本では、疎な構造を仮定しているので .. ?
                A. java は pacakge = name space なので.. ?

            Q. 業務では、巨大な jar を作るのが普通 ?
                自分の所では jar を作らず、ばらばらに公開している..

                A. 開発 Group によって、方針が異る
                    自分の所では、グループがいくつかあって..
                        リリース単位で 1 DLL
                        1 group / 1 pacakge / 1 dll / 1 so ?
                            結果的に so は結構沢山ある
                    開発フェーズでは、細かく分けた方がよい ?

                    # Mail で送れる size
                    #    2M をこえると駄目
                    #    .exe も駄目
                    # 送るときに、拡張子をかえて送れる..
                    #    最近の spam filter は厳しい..

            Q. 開発人数が少いので、全部 1 jar に ?
                pacakge 単位だから.. ?
                A. 会社が複数あると jar を 1 つにできない

        # 論理的な構造と物理的な構造の mapping 方法が欲しい

        Q. この Class は寿命が短いから、Pacakge かはずすなど、自動化できないの ?
            A. 実際に Profiling すれば、できるんじゃないか ?
            Q. 翌日みると、いつのまに pacakge が増えていたりして .. ?

        Q. リリースの単位で jar をまとめようとすると、なんらかのパターンがあるのでは ?
            A. 設計の話ではなく、リリース観点での話かも

            例 : 相互参照しない class は package を分けるとか ?
                パッケージングパターン
                リリースパターン
                    version 管理
                    source directory tree
                        開発 Directory パターン
                            => Maven
                            jar の位置の名前まで決る
                                楽だけど、カスタマイズは面倒

            # 原則じゃなくて、プラクティスが欲しい
                現在は、Project 単位なので、今後は、なんとか統一をしたいと思っている

            Q. 粒度の問題を持ち出す場合、対象の内容が解らないと分割はできない...
                A. 会社など、形式的な粒度は、いくつかあるが..
                    # 論理的な話でなく、開発者の都合も入っている

                Q. アジャイルは、この開発者以外の都合による構造がなくなっているのでは ?
                    # アジャイル的には個々 Project 単位でもしょうがない ?

                    Q. 本では理想な状況しか考えていない
                        A. 実際の所ではどうなっている
                            理想でない状況での奥儀とは .. ?

                        Q. 裏奥儀 ?
                            WF Model での .. ?

        Q. 事前に jar 化する範囲を決定するという発想が間違い ?
            A. この本では、「打たれてから决める」仕組み
                事前に決定してはならない !!

        Q. アジャイル計画パターン ( by アジャイル評議会 )
            A. 適用経験があるが.. 打たれる度に傷がひろがった ( 悪例.. )

        Q. pacakge を作らず、最後に tool にまかせるのは ?
            A. 自動判定の Logic をつくれば.. ?

==

22.4 結合とカプセル化

    class のアクセスコントロール(export するかどうか)と同様に、
        pacakge にも、アクセスコントールとカプセル化を行う必要がある。
        ( p.338 抽象度と安定度の関係 )

        抽象度が高い => Pacakge 内の Interface が多い

        # pacakge は主系列にのっていることが望ましい

    公開をしなければ、不容易な結合をさけることができる ( カプセル化 )

==

22.5 尺度(メトリック)

    パッケージ ( モジュール ) の様々な性質を尺度を与えて測定する
        計ることができないものは、コントロールできない !!
            => 尺度をきめて、きちんと計り、コントロールする

    # 機械的に、計ることもできるが、手動でも難しくない

    本書では、具体的に適用可能な尺度を紹介している ( これは、実績のあるもの )

==

22.6 payroll application の尺度

    全体としては、良好だが.. 一部問題のあるものがある
    頻繁に変更される class があり、他がそれに影響を受けるのは、望ましくない

    Classification は、良くない

    Q. 図 22-7 の矢印の後と前の数字は ?
        A. 各々の package の「使う、使われる」の依存関係 ( class の個数 )
            例 : payroll class はいっぱい使われている ?

        Q. これらが、機械的にできるなら...
            その後で、必要なら、会社毎に..
            A. 本当は、設計の段階で分割してから、会社に業務を分けるべきなのだが..
                設計をしないから、きちんと分けることができない ?

        Q. jdepends では絵が出るの ?
            A. Yes

        Q. 前回は、Pacakge 内の話では ?
            A. 今回は、Pacakge の間の話 ?

        Q. jdepends は、あくまでも、java の物理的な package 構造に

        Q. java の pacakge は tree ?

        Q. 図には、「数」より、「太さ/色」を図示した方が..
            A. 朝きたら、「あなた D が小さすぎ..」とかいわれたり..

            クルージングの時に、jdpends の結果を流す
                「貴方、主系列から離れていますよ..」とか


22.6.1 オブジェクト Factory ( p.368 )

    なぜ、Classification は、良くない ?
        => インスタンスを作成しなければならないので...
            # インスタンスを作る時にその Class が必要 !!
    逆に、他の場合は抽象インターフェース経由での利用なので、Okey
        # ようするに、他の Class のオブジェクトを間接的に利用するようにする
        #    作成は Factory 経由
        #    利用は 抽象クラス / Interface 経由


22.6.2

    Q. TransactionFactory という新しい Package を分けた ?
        A. I/F は変らない, でも、実装はころころ変るから、分けた ?
            => DEP

    Q. Transaction I/F もどこかにあるよね.. ? ( どこなんだろう ? )
        A. 個々のパッケージに分散してそうだけど..
        図 22.2 の PayrollDomain の中にあるのでは ?

        # 名前が変。どうすれば .. ?

22.6.3 オブジェクト Factory の初期化

    Factory は初期化が必要
        どこで、行う ? => main で行うしかない
            このために main の結合度は最悪になる ( 避けられない )
                => 無視するという方針
        # どうぜ、main は、毎回 test するので、問題ない

    Q. 初期化を main に埋め込むのはよくないのでは ?
        設定ファイルで頑張るとか..

        Q. java なら Okey だけど、C++ だと..
            技術的には、可能だけど...
            # reflection じゃないけど.. 動的に class を load する仕組はある
            ## Meta Class とか ? ( 限界があるのでやりたくない.. )

        A. この程度なら、main にハードコーディングしても Okey
            言語的な要因 ?
            必要になったら..
            汎用性とのトレードオフ

22.6.4 パッケージについて再考

    トランザクションを二つのパッケージに入れたので、二重構造になっている
        => 複雑すぎ

    パッケージ構造は単純に ?

    Q. 「機能面より、トランザクションを軸に分割したほうがよい」というのはどう言う意味
        一般的 / この場合だけ ?
        # トランザクションがなかったらどうする ?

        A. これまでは、機能別だったが、それをトランザクションに分けたら、今回はたまたま良くなった、ということ ?

    Q. パッケージの中にパッケージがはいっていることはある ?
        A. あるかも ?
        Q. でも、図の中は、パッケージにはクラスしかはいっていないが ..

    Q. パッケージの中にパッケージは許されないのか ?
        A. UML 的には問題ないが..

        この例ではない
            Name Space は別々にする必要が .. ?

        A. 言語へのマッピングは考えていないのでは ?

        Q. Tool で Class を作成すると、パッケージの中にパッケージが入る ?
            A. 話が発散しないように単純化している ?

        Q. パッケージの中にパッケージをいれることにどんな意味が.. ?

        Q. 敢て、ネストにせずに展開する理由がしりたい

        [宿題] Source Code をみましょう。

        Q. パッケージ名がぶつかったら ?
            A. 管理者がいるので..

            A. リリース単位としての Package を考えるならば..
                ネストした Pacakge はリリース単位でないのでは ?
                リリース単位 = jar であれば、ネストはありえない

                Q. jar の中に jar を入れても、参照されないし..

        Q. 本当に、こうして依存の影響は小くなったのか ?
            19 個の Class がはいるパッケージができたんじゃ、影響があっちこっちに、及ぶんじゃないの ?
            A. この 19 個は、結局ふらふらと変更されるものばかりはいっている。
            逆に、個々に分離しても意味がない。
                => パッケージマネージメントのコストを下げるために、(凝縮度がないのにも拘らず)まとめた..


22.6.5 最終的なパッケージ構造

    # 良くなった

    A. Transaction, Payroll などは凝集度が下るが、他の部分がよくなるので..
        A. 数字だけみていてもだめ ( 意味を考える.. )
        A. Library の方が、凝集度高めで
        A. Applcation 側の方が、(雑多のものが多くて)凝縮度が低い

            Q. パッケージパターンは今後の発展を期待 ?
                A. なくてもすむし.. (遅れてる分野も..)
                    A. 保守とか、パッチスケージュールとか後から利いてくる
                    A 発展の余地もあり、java では Maven ?

                    Q. Version の話なんか入ると大変
                        A. apt の build コンフリクトが..

                    A. jar の中に multi verion になっていて..
                        必要な class を load する

                    A. 複数のプロセスで、一つの JVM を共有仕組がある
                        Q. Tiger から ? ( MAC OS 1.3 の JDK からはいっている )
                            A. jar を memory mapping しておいて、class load の速度を速くするという仕組は、以前からあった。
                        Q. shared archive ( text を共有 ? class の flash [変更の反映] はどうするの ? )
                        A. System Class とか変更されないものだけなら flash は不要

                    A. Memory Image を Dump して、再利用
                        A. emacs / TeX も同じ

                    Q. Serialize は違うか ?

                Q. アンチパターンしかないかも ?

                Q. commonds / util などは.. ?

                A. Factory につく言葉は具体的なもの
                    A. CommonFactory はだめ
                    A. でも、自分で作る時には名前がないので..

22.8 結論

    分割は必要
        ちいさければ、Source 単位、おおきければ、何らかの分割構造が必要 


==

5 部
23 章 Composit パターン

def Composit パターン
    一つのメッセージを送るだけで、複数のオブジェクトにメッセージを送る場合に利用

    # Proxy パターンに似ている

23.1 Composit パターンの例 ( Composit Command )

    Command パターンとの相性がよい
        Command パターン自身は 1 to 1
        Composit パターンとの組合せによって 1 to n にできる
            元の仕組はまったく変更する必要がない点が重要

24 章 Observer パターン

    「デザインパターン完成された形だと思う」ことは、間違い
    「デザインパターンを意図的に取り込む」のは勧めない
        => リファクタリングの結果として、「たまたま」デザインパターンになった
            => そこで、初めてデザインパターンにそった名前に変更する
            # デザインパターンが、システムに「回帰」する

24.1 デジタル時計:問題設定

    最初の例 : ビジーループの形 => 無駄 ( 変化しない時刻を表示する必要はない )

    プログラムを改良する前に、テスト環境を作る ( テストファースト !! )
        Test の為に、Mock Object を作る

    誤殖 : 「を」=>「と」

        テストを考えたら、新しい I/F (設計上の分離) ができた

    Clock Driver を設計するには ?
        効率的な方法 ( ポーリングをさけるに ) は、
            dirver から timer ではなく
            timer から driver を呼ぶような..

        Q. 何をしたいのか .. ( わざとらしい.. )
            # 結果がわかっていて無理やり
            Mock が必要な理由は ?
            A. 個々の単体テストを別にしたいので、相手方の Mock 必要
            A. 24-1 は、ClockDriver の Test をしている

        Q. Interface がでてくるのは必然 ?
            A. 必然とは思えない ( Eclipse の問題 ? )

    ClockDriver の Test Case をつくっている (24-1)
        ClockSource が ClockDriver に(直接)依存するという問題がある
            => 望ましくない
                新しい I/F を作り、この依存関係を切離す
                    ClockObserver Interface

    (更に改良) 一つの TimeSource を、複数の TimeSink で共有する仕組を入れる
        => 間接参照が二つ ( 本当に必要 ? )
            => TimeSink そのものに ClockObserver で実装する
                => ClockDriver は不要 !!
        # リスト 24-6

    TimeSource の仕組を、Clock に要求するのは変 ?
        => C++ ならば、多重継承がつかえるが..
        => Java は裏技をつかう
            図 24-10

    # 話をもどして..
        オブザーバーパターンの push/pull モデルの違い
            # 名前が落つかない..
            push から pull へ変換する ( 図 24-11 )

24.2 結論

    パターンを思いつたら、直に適用する ? / 少しずつ進化させる ?
        => 後者の方法が望ましい
            => 書き換えを
                途中で止める
                他の方向に行く
            といった、可能性を消してはいけない
            # むりやりパターンに当て嵌めてはいけない

24.2.1
    ダイアグラムは、
        他人のために示すには重要 ( 保存しておく )
        自分(達)のための場合は捨てちゃって良い

    Q. 結局、実装は ?
        どこかで、OS から時刻を取り出すために.. Polling が必要なのでは ?

        A. 過程を示すことがポイントなので、実装にはふれていないのでは ?

        Q. 多重継承の必要性は ?
            C++ ?
            A. java の問題点をいいたかった ?

        Q. TimeSource I/F も不要では ?

        Q. java.util.observal は Class ? Interface ? が問題だったけ ?
            A. ちがうかも

24.3 Observer パターン

    定義は、図 24-12

    間接参照を利用して、直接の依存関係をさけることができる
        しかし、システムが複雑になって、わかりやすい

    push モデルと pull モデル
        pull モデル
            実装が容易
        push モデル
            複雑な監視対象を実現する場合は、こちらの方がよい

24.3.1 Observer パターンとオブジェクト指向の原則

    OCP が、Observer を後押し
    LSP も適用されている
    形式的には DIP に違反
        意味的には、Subject は抽象なので、その意味では DIP を満す
            実際に Subject を抽象化してもよい
    ISP も関係している..

==

    Q. C++ の pure virtual な method に実装ってどんな意味が ?
    A. pure virtual な Code は、sub class から使える
        「= 0」宣言は sub class に対して、実装を要求するための仕組
            # java の final の逆の意味 !!

        A. Inline な抽象デストラクタとか..
==

25 章
    # 無駄にパターンを適用してはならない !!

    Switch と Light のそれだけのシステムでも色々とある
        DIP, OCP への違反

25.1 Abstract Server

    Q. 「Abstract Server」 って初出 ?
    A. そうみたい ( Index によれば.. )

    Q. 有名なの ? GoF にある ?

    Q. Abstract Server の定義は ?
        A. 書いてないけど.. つまり、知っているのが当然ってこと ?

        [宿題] どこで出ているかを見付けて ML に流しましょう

        A. 図 25-3 が定義 ?

25.1.1 Interface の所有者

    Switchable は Switch に関連が強い
        論理的な接続(関係)の方が、物理的な接続(継承)より強い

        # このズレは、静的な型付け言語、固有の問題

    [誤殖] まもるべき「もの」ではない

25.2 Adapter パターン

    switchable と light を切離す ( SRP を守るため )
        => Light Adapter
            Light の I/F を switchable の I/F に変換

    Adapter のコスト
        高い => 乱用するな

25.2.1 クラス形式の Adapter

25.2.2 モデムの問題

    # 退化したメソッドは、LSP 違反の兆候..

    # 図 25-7 が理想だが、それが選べないとすると ..

    Adapter を使って解決する方法 (図 25-9)
        Adapter が、シミュレーションしている点で、変
            でも、他から隔離されているので許される

        # これって、一種の「裏技」かしら.. ?


25.3 Bridge パターン

    1 つの Tree 構造に、2 つ以上の自由度がある状況で役立つ
        A. かけ算を足し算にする仕組
            A. Class 構造は、静的なかけ算
            A. delegate は動的なかけ算

    Q. Bridge パターンというのは、二つの実装の間に割り込んでいるから ?
        図の 25-11 で..

        A. 二つの Tree の根を結んでいる (delegate する) ところが Bridge 的

    A. パターン配置でおぼえるので、くずされるのはいやだ

    Q. 図 25-10 と 図 25-9 は同じ ?
        A. 各々のメーカーが dedicatedModem を売り出したら ?
            仮定が変った

        Q. Bridge パターンはここだけでみた方が良いの ?
        A. Yes

    Q. この図では Factory がないので、良く解からない
        Q. 本当にこんな風に実装できるの ? ( なんか前提があるはず.. !! )
            # Windwos の Wizard が初期化して..


25.4 結論

    結局パターンの適用には得失がある。
        Bridge パターンは、特別な状況だけで使うべき (コストが大きい)
        # Adapter は、コストが小さい

==

26.1 Proxy パターン

    RDB を直接利用して Data を Table に Insert すると..
        SRP, CCP に違反
            => RDB と オーダーの概念が mix されている点が問題
        # DIP にも問題
            => Proxy パターンが答 (図 26-3, -4)
                三つの部分からなる

    Q. Clock の時は、Mock を使ったのに、DB の方は、何故、Mock でない ?
        A. DB が実際にあれば、Mock は不要かも ?
        Q. 単体テストするなら Mock が必要でしょう ?
            A. ここでは単体でのテストをする気がない
            A. 結局は、テストの対象となる本体が出てこないし...
        A. まあ、Proxy パターンを説明するためのものと割切る

    既存の二つ関係の間に、他の関係にしらせずに、何か ( proxy ) を入れることができる
        この方法の問題点は ?
            例外の処理を I/F の外に出した
            結果は、標準形と異る why ?
                ProductImp の実装が無駄なので省いたため
                    これは標準形から離れる理由になるし、これが自然

        効率も悪いが..
            本当に効率が悪いと解るまで、放っておこう !!

==

次回は p.433 から


[ 戻る ]