書評:アジャイル開発とスクラム ~顧客・技術・経営をつなぐ協調的なソフトウェア開発マネジメント~

はじめに

  • ビジネスにスピード感が求められる環境、ビジネスが不確実で先読みすることが難しい環境では、ビジネスを作る側と技術を担当する側で協力してソリューションを考える必要あり。
  • そして、すばやくリリースしてユーザーを獲得すること、ユーザーの反応を見ながらソフトウェアを追加・改変していくことが求められる。

第1部 アジャイル開発とは何か、スクラムとは何か

第1章 アジャイル開発とは何か?

  • ビジネスのスピードに追随するという目的だけではなく、自律的なチームや組織を作るという手法としてもスクラムが注目。自分たちで決めながら動く自律したチームを作ることが、生産性を上げる鍵となっている。
  • 期間を短く区切って優先度の高い機能から実装することを繰り返すことで、最後にならないと動くものが見えないリスクを軽減するとともに、ユーザーや顧客のフィードバックを取り入れながら開発する。
  • 協調とコミュニケーションスタイル、顧客と開発チームのゴールの共有関係、柔軟な計画変更の考え方、現場の開発者のモチベーションなどの価値観を重要視。

第2章 なぜ、アジャイル開発なのか?

  • ITのゴールは仕様を満たすことではなく、ビジネスとしての効果を上げること
  • すばやくユーザーや顧客のフィードバックを得ることで、ムダな機能を作ることを防ぎ、市場投入スピードを上げ、ビジネスの投資対効果を高める。

第3章 スクラムとは何か?

  • 予見的なプロセスではなく経験的なプロセスであり、実際にやってみた結果を見ながらチームを適応させていく。
  • 効果的に実践するためには、スクラムチームを含む組織全体が「コマンド-コントロール」型から「リーダーシップ-コラボレーション」型の自立した組織に変わる必要がある。

第4章 アジャイル開発の活動

  • プランニングポーカー
    • 複数人の意見で見積もることで、見積もりの精度が向上する。
    • 開発者が自身の意見を話すことで、いろんな考え方を知ることができるという学習効果もある。
  • 朝会
    • チームは自分の仕事に透明性を持って参加することが重要。
    • 独りぼっちでそれぞれに与えられた仕事をこなしているのではなく、共通のゴールに向かって何かを一緒に生み出していくプロジェクトの一体感を毎日作る。
    • 現在のプロジェクトの状況(バーンダウンチャートなど)を壁などを使って見える化し、チームで共有すると、朝会の効果が上がる。
  • 振り返り
    • チームが抱えている問題点を共有し、自分たちでできる解決策を見つけ出し、それを行動に移す機会にすること。これにより多くの場合効率もよく、モチベーションも引き出せる。
    • すべてチームが自律的に運営することがとても重要で、外部から押し付けられた解決策はうまく行かない。
    • 振り返りがうまく回りだすと、チームはどんどん自分たち流のやり方を獲得することができ、チームが自律的になっていく。
  • タスクかんばん
    • 可視化によるちーうの協調支援と透明性の確保が主目的。
    • タスクかんばんを見れば、全員が以下の観点でスプリントの状況を確認でき、スプリントのゴールに向かって全員が自律的に行動できる。
      • ずっと動いていないタスクはないだろうか?
      • 何か障害があるのではないか?
      • 今回のスプリントは予定通りにいくだろうか?
      • 誰か手の空いた人が助けるべき人はいないだろうか?
  • バーンダウンチャート
    • バーンダウンチャートを全員で更新し、確認する運用にすると、現状をメンバー全員が共感を持て、そこから行動につなげられる。

第2部 アジャイル開発とスクラムを実践する

第5章 スピード時代に独自のアジャイル手法 ワンチームマインドで挑むリクルート

第6章 小さく始めて浸透させる ~楽天による組織改革

  • トヨタ生産方式に「あるべき姿を求めて改善し続ける人間集団をつくる」という考えがあるように、仲間を信じること、仲間に任せること、仲間を応援すること、といった人間中心の環境を作ることが重要。
  • チームみんなで、より高みを目指し、お互いを奮い立たせ、励まし合い、「努力していこう」と継続的に勇気づけること。これこそが、アジャイル開発のすべて。

第7章 「IT新市場」におけるアジャイル開発に取り組む富士通の挑戦

  • 「短い時間で提供しなければならない」という制約が、本当に必要なものだけを提供→フィードバック→必要なものだけ提供、というループを回した。「小さく速いループ」が「思い込みを排除し、短期間で最大の効果を得る」のに役立つことを学んだ。

第3部 アジャイル開発とスクラムを考える

第8章 竹内・野中のスクラム論文再考

  • 新製品開発という速さと柔軟さが求められる場面では、様々な専門性を持った人が一つのチームを組み、ラグビーのように開発の最初から最後まで一緒に働くことが求められ、人とチームを重視し、彼らに自律的に動ける環境を与えることでブレイクスルーが起こりやすくなると同時に、製品化までの時間が短くなる
  • 自分の人生にもっとエネルギーと創造性を感じて、チームですごいソフトウェアを作り出す仕事を、わくわくしながらやれる環境作りが生産性や品質向上につながる。

1.不安定な状態を保つ

  • 最初に綿密な計画書や指示があるわけではなく、チームは自由な裁量と同時に、困難なゴールを目指す。
  • プロジェクトの開始時にすべての要求を固定することができないため、要求を固定するよりも、人を中心にしたコミュニケーションと協働でプロジェクトを前に進める。
  • 要求のリストは、順位付けられた「バックログ」として管理されるが、このリストは時間とともに変化していき、常に不安定な状態といえる。

2.プロジェクトチームは自ら組織化する

  • チームは不安定な環境から自己組織化し、対話の中で自律状態を作り出す。
  • 自己組織化されたチームの状態は、「チームが自律しており」、「常に自分たちの限界を超えようとし」「異種知識の交流が起こる」という特性がある。

3.開発フェーズを重複させる

  • 開発フェーズを重複させることで、メンバーは専門分野を越えてプロジェクト全体に責任感を持つようになる。
  • 分析、設計、実装、テストという開発フェーズが重なり、メンバーは分析者、設計者、実装者、テスターという専門の垣根を取り払って一つのチームとなる。
  • 仕様書ではなく、対面のコミュニケーションを基本に情報を伝達し合いながら問題解決する。文書ではなく、「人」が情報を運んでいる。

4.マルチ学習

  • メンバーはグループ全体として学習し、さらに専門を越えて学習する。
  • 「多層学習(個人、グループ、組織、企業といった複数のレベルで学習が起こること)」と「多能力学習(別々のスキルを持った人が集まることで、専門外の知識についての学習が起こること)」をマルチ学習と呼ぶ。
  • 多層学習では、プロジェクト内の学びは、個人とグループという二層で起こる。特に全員が同じ体験を通して学んでいることが重要で、個々の学びの総和ではなく、その体験の中で交わされた会話や議論を含めて、グループ全体があたかも一つの生命体のように獲得した学習が成果だといえる。

5.柔らかなマネジメント

  • 無管理でも強い管理でもなく、自主性を尊重した「柔らかなマネジメント」が重要である。
  • 「自己マネジメント」、「相互マネジメント」、「愛情によるマネジメント」の三つを総称して、「柔らかなマネジメント」と呼ぶ。
  • 「オープンな仕事環境作り」、「開発が進行していく中で、リズムの違いをマネジメントする」、「失敗を自然なこととして受け入れる」などがポイント。

6.学びを組織で共有する

  • 過去の成功を組織に伝える。もしくは意識的に捨て去る。

第9章 スクラムと知識創造

  • スクラムはスプリントによって獲得・創造した知識(要求に関する知識、ユーザに関する知識、作り方に関する知識)を「動くソフトウェア製品の成長」と「スクラムチームの成長」という、2つの形で蓄積していく活動。
  • 目に見える事象と、その背後にある関係性までを読み、その場で適切な判断を下し実行することを実践知と呼び、実践知を持ったリーダーを実践知リーダと呼ぶ。
  • 形式知(ビジョンや原則)だけでも暗黙知(現場の実行力)だけでもなく、両者を行き来できるリーダーがアジャイル開発で必要なリーダーシップ。
  • 実践知リーダーリップに必要な6つの能力
    • 「善い」目的を作る能力
    • 「場」をタイムリーに作る能力
    • ありのままの現実を直観する能力
    • 直観の本質を概念に変換する能力
    • 概念を実現する能力
    • 実践知を組織化する能力

まとめ

  • 僕個人の意見だと、スクラムをやる一番の価値は、自律的なチームや組織を作るだと思う。これさえできれば、本来の目的であるビジネスとしての効果を上げることの一番の近道だと思う。
  • これの根拠として、組織の成功循環モデルで言われているグッドサイクルは、関係の質を高めるところから始め、関係の質を高めるとは、相互理解を深め、お互いを尊重し、一緒に考えることである。と言われているためである。
  • 組織の成功循環モデルの詳細は、ネットで調べてください。
  • ということで、やっぱりスクラムをやるなら、チームビルディングがすげー大事になってくるので、次はチームビルディングに関する本を読もう

以上。

【.NETのエンタープライズアプリケーションアーキテクチャ】の第二部 アーキテクチャの考案 まとめ

概要

第5章 ドメインアーキテクチャの発見

  • ソフトウェアには、現実の世界を正確に映し出すことが期待される。
  • ソフトウェアアーキテクトは、ソフトウェアが現実の世界のどの部分をモデリングしているかを理解する必要がある。
  • その部分はビジネスドメインであり、それぞれに理想的なアーキテクチャ(階層化アーキテクチャやヘキサゴナルアーキテクチャなど)を必要とする複数のビジネスコンテキストを含んでいるかもしれない。

5.1 ドメイン駆動設計(DDD)の本当の付加価値

  • DDDは、特定のビジネスドメインに関する知識を噛み砕き、それを忠実に反映したソフトウェアを作成するためのもの。
  • ビジネスドメインは、企業が業務を行う方法であり、組織、プロセス、実務、人々、言語に関連している。
  • ビジネスドメインが存在するのは、コンテキストの中であり、非常に似ているビジネスであっても、コンテキストが異なる可能性がある。

DDDの利点

  • DDDを使用する上で肝心なのは、その本当の価値がどこにあるかを理解し、それを利用する方法を学ぶこと。
  • DDDの分析部分は、ビジネスドメインのトップレベアーキテクチャを境界付けられたコンテキストで表現する方法を定義。
  • DDDの戦略部分は、特定された境界付けられたコンテキストをサポートするたのアーキテクチャの定義に関連。
  • DDDの本当の付加価値は、ビジネスコンテキストの境界を定義するために分析部分を使用することにあり、その後、境界付けられたコンテキストのいずれかを実装するために戦略部分が利用される。

DDDを使った分析

  • DDDの分析部分は、ユビキタス言語境界付けられたコンテキストという2つの関連する要素で構成。
  • ユビキタス言語は、プロジェクトの関係者全員が使用する言語ユビキタス言語は、最終的にクラス名やメソッド名で使われる。
  • 境界付けられたコンテキストは、ドメインの様々な領域のうち、独自のユビキタス言語を持つために別個に扱ったほうが効果的な領域を表すDDDの用語。ビジネスドメインはどれも複数のコンテキストで構成され、コンテキストにはそれぞれ論理的な輪郭がある。
  • DDDの分析部分を表すためによくコンテキストマッピングという表現が用いられる。ソフトウェアアーキテクトの視点からドメインを俯瞰的に定義し、サブドメインとそれらの関係を明らかにし、戦略的な決断を下すのに役立つ。

戦略的なモデル設計

  • さまざなな境界付けられたコンテキストを定義したら、それぞれに最適なサポートアーキテクチャを決定する必要がある。
  • 最適なサポートアーキテクチャを選択する基準は、今のところソフトウェアの寿命がどれくらいかに基づく。寿命が長ければ、ドメインモデルのパターンを採用する価値がある。現時点のドメインモデルパターンだと、ドメインのモデルを中心に設計された階層化アーキテクチャをDDDが提案している。

5.2 ユビキタス言語

ユビキタス言語の目的

  • ビジネスの言語から開発の言語への翻訳を手配し、専門用語をビジネスor開発のコンテキストに合わせて調整していると、時間がかかり、途中で抜け落ちてしまう可能性がある。
  • ユビキタス言語の目的は、すべての関係者がすべてのレベルで使用する共通用語を定義すること。
  • 共通用語があれば、ビジネスのコンテキストから開発のコンテキストへ概念の翻訳する必要がなくなり、明確さが促進され、仮定しなければならないことが最小限に抑えられる。

ユビキタス言語の構造

ユビキタス言語を定義する方法

  • ユビキタス言語は、聞き取り調査や話し合いの中から現れ、徐々に最終的なカタチをなしていく。
  • 言葉が期待どおりに伝わり、構築中のシステムの現実を忠実に表すようになるまでに、改良や調整が何度も必要になるかもしれない。

言語とモデルの同期

  • ドメインモデルで使用される言葉とユビキタス言語の言葉を常に反映させるべき。
  • ビジネスコンテキストに属さない技術的な詳細(オブジェクトインスタンスとか、テーブルからデータを取得するとか)は、実装の内側に埋め込み、開発者どうしの技術ミーティングでのみ取り上げ、ビジネス側の人々との正式なコミュニケーションに含まれないようにすべき。これがユビキタス言語の本質。

5.3 境界付けられたコンテキスト

  • 境界付けられたコンテキストとは、独自のユビキタス言語とアーキテクチャを必要とするアプリケーションの領域のこと。
  • 別の言い方をすれば、境界付けられたコンテキストの境界内では、ユビキタス言語は1つであり、境界付けられたコンテキストは他の境界付けられたコンテキストとの間に関係を持つことができる。

コンテキストの発見

  • 新しいサブドメインを発見するための最初の手がかりは、既知の概念を表現するために新しい用語が使用されていることや、同じ用語に2つ目の意味があるこを発見したとき。これはサブドメインの重複を示唆。最初の決断は、それらのサブドメインを別々に扱う必要があるかどうか。
  • 組織の構造を反映したコンテキストが作成される場合が特に効果的。
  • 概念の重複が検出されたときに解決しなければならないのは、以下の選択肢のうちどれがより適切であるか。である。
    • すべてのエンティティを含んでいる単一の境界付けられたコンテキスト。(コンテキストは1つ)
    • 共通のエンティティを共有カーネルとして定義する別個の境界付けられたコンテキスト。(コンテキストは3つ)
    • 共通のエンティティの異なる定義を持つ別個の境界付けられたコンテキスト。(コンテキストは2つ)

コンテキストマッピング

  • 多くの場合、境界付けられたコンテキストの間には関連性があり、DDDのコンテキストマップは、設計中のシステムの全体図となる。つまり、各要素が境界付けられたコンテキストであり、それらの関連性を表現する。

コンテキストごとにアーキテクチャを定義する

名前 説明
階層化アーキテクチャ プレゼンテーション層、ビジネス層、データ層に基づく標準的な切り分け。
ドメインモデル プレゼンテーション層、アプリケーション層、ドメイン層、インフラストラクチャ層の4のレイヤーに基づき、DDDスタイルで設計された階層化アーキテクチャ。とりわけ、ドメインモデルが特殊なオブジェクトモデルと位置づけ。
コマンド/クエリ責務分離(CQRS) コマンド部分とクエリ部分を処理するための並列セクションを持つ2重の階層化アーキテクチャ。これらのセクションは別々に設計することが可能で、異なるサポートアーキテクチャを使用することが可能。
イベントソーシング CQRSにヒントを得て、単純なデータではなく、イベントのロジックに焦点を合わせた階層化アーキテクチャ

5.4 階層化アーキテクチャ

f:id:mmm-mao:20160228195404j:plain

プレゼンテーション層

  • プレゼンテーション層では、タスクを実行するためのユーザーインターフェースを提供する必要がある。
  • プレゼンテーション層に表示されるデータをビューモデルと呼ぶ。画面から送信されてバックエンドのアクションを開始するデータを入力モデルと呼ぶ。

アプリケーション層

  • アプリケーション層は、プレゼンテーション層の指示に従ってビジネスアクションを手配するレイヤー。
  • アプリケーション層は、ユースケースの実装を取りまとめる場所
  • アプリケーション層は、ドメイン層およびインフラストラクチャ層への参照を保持し、ビジネスルールをいっさい認識せず、ビジネス関連の状態情報を保持しない。

ドメイン

  • ドメイン層は、1つまたは複数ユースケースに限定されないビジネスロジック全体をホストするレイヤー。
  • つまり、アプリケーション層を組み立てた後に残ったビジネスロジックを全て含む。
  • ドメインモデルの最終目標は、ユビキタス言語を実装し、ビジネスプロセスが要求するアクションを表現すること。これらの点に関しては、何らかのデータを保持することよりも、何らかの振る舞いを提供することのほうに分がある。

インフラストラクチャ層

  • インフラストラクチャ層は、具体的なテクノロジに関するあらゆるもので構成される。
  • EntityFramuworkといったO/RMフレームワークによるデータの永続化や、ログ、IoCコンテナなど様々。
  • ただ、一番代表するコンポーネントは永続化のレイヤーである。

第6章 プレゼンテーション層

6.1 ユーザエクスペリエンスファースト

  • ユーザエクスペリエンスファーストは、ユーザ/システム間のやり取りとプレゼンテーションを中心に据えたソフトウェア設計アプローチである。

やり取りに着目する

  • ユースケース図を作成するところから始める。各ユースケースに必要な入力、各ユースケースが生成する出力に焦点を合わせるアプローチ。
  • データではなく、やり取りに焦点を合わせてスケッチを手直ししていくのが進むべき道。

第7章 伝説のビジネス層

  • 従来のデータ中心の3層構造の世界から、モデル中心の階層化された世界えの転換の正当性を示すとともに、実際に展開を図る内容となっている。

7.1 ビジネスロジックを構造化するためのパターン

Transaction Scriptパターン

Domain Modelパターン

  • ドメインモデルは、ビジネスドメインと、特にドメイン内のプロセスや振る舞いとデータフローを忠実に再現するモデル。
  • データベース構造をアプリケーションのクラスに置き換えただけのドメインモデルは、完全に的外れ。
  • ドメインモデルが何らかの機能に対する単なるAPIではなく、ビジネスに対するAPIであること。つまり、ドメインモデルの使い方を誤れば、ビジネスの私物化や一貫性のない矛盾したプロセスの実行につながる可能性がある。
  • ドメインモデルのクラスを保存する責務は、ドメインモデルの外側で、インフラストラクチャ層に接続されたリポジトリを通して処理。

【.NETのエンタープライズアプリケーションアーキテクチャ】の第一部まとめ

はじめに

  • .NETプラットフォームに関する、優れたソフトウェアアーキテクチャ(複雑さを制御し、保守性を維持)のベストプラクティスを説明。
  • 優れたソフトウェアアーキテクチャを実施するためには、ビジネスドメインを深く理解することが重要。

第1部 基礎

概要

  • ソフトウェアアーキテクチャの以下の基礎的な部分を取り上げ。
    • アーキテクトの役割。
    • ソフトウェアプロジェクトに独特の力学。
    • 最高品質のソフトウェアに変化させるテスト容易性や読みやすさの側面。

第1章 現代のアーキテクトとアーキテクチャ

1.1 ソフトウェアアーキテクチャとは何か

1.2 アーキテクトと呼ばれる人々

  • アーキテクトの主な責務は、以下の通り。

    • 要件の承認
    • システムのサブシステムの分解
    • テクノロジの特定と評価
    • 仕様の策定
  • アーキテクトはコードに大きく関わる立場にあり、アーキテクトはシステムの設計を考え出すが、一方でそれが正しく実装されるように開発者と緊密に協力する立場になる。

第2章 成功のための設計

2.1 ビッグ・ボール・オブ・マッド(BBM

  • BBMとは、大部分が構造化されておらず、コンポーネント間の依存関係がこっそり埋め込まれ、データとコードは重複だらけで、レイヤーと関心が明確に識別されていないシステムを指す。つまり特盛のスパゲティコードのこと。

  • BBMの兆候

    • 変更を加えたのが1つのクラスだったとしても、変更による影響は依存関係にあるクラスに伝わってしまう。
    • ソフトウェアに変更を加えると、あちこちが正常に動作しなくなる。

2.2 ソフトウェアプロジェクトの力学

  • ソフトウェアプロジェクトの成功または失敗を実際に決定するのは個人であり、個人どうしの実際のやり取りである。ただ、組織の構造や全体的な文化も、最終的な結果に影響を与える。

2.3 窮地を脱する

  • 新しい開発を休止して、出来の悪いコードをはるかに管理しやすいものに変える。
  • やっかいなコードを分離→分割して、やっかいな領域をできるだけ小さくする。
  • 複数レイヤーにまたがる自動テストを実施して、継続的なリファクタリングを習慣にする。

第3章 ソフトウェアの設計原則

  • システムを設計するときに最も優先しなければならないのは保守性
  • 保守性は、原則や一般的なパターンを採用したり、コードの明確さ、読みやすさ、テスト容易性に配慮するなど、様々な要因の結果。
  • この章は一般的なプラクティスをまとめている。

3.1 ソフトウェアの普遍的な設計原則

スパゲティコードからラザニアコードへ

  • ジャンプやリターンが複雑に絡み合ったGOTOベースのコードをスパゲティコードと呼ばれるようになった。
  • 構造化プログラミングを用いて、サブルーチンを使ってコードを分割し、再利用しやすいコードをラザニアコードと呼ぶ。
  • 設計はコーディングに先立つものではなく、コーディングと並行で実施。コーディングが進むに従い、理想的な設計が少しずつ明らかになり、早い段階でリファクタリングを実施。
  • 設計とコーディングをともに進化させると、簡単かつ安全に更新できるコードになり、保守性の高いコードとなる。
  • 凝集性は、論理的に関連のある操作を表す限られた数のメソッドで構成された、きわめて専門性が高いクラスを作成することを推奨。メソッド間の論理的な距離が広がった場合は、新しいクラスを作成する。
  • 結合性は、2つのクラスなど、2つのソフトウェアモジュールの間に依存する依存関係に度合を表す。モジュール間のやり取りは可能だが、明確に定義された安定したインターフェースを通して実施。
  • 結合性が低く、凝集性が高くなるように設計されたシステムは、読みやすく、保守しやすく、テストしやすく、再利用しやすいという要件をたいてい満たしている。

関心の分離

  • 関心とは、ビジネスロジックやプレゼンテーションといった、ソフトウェアの様々な機能のこと。
  • 関心の分離とは、一度に1つの関心に焦点を合わせること。

3.2 オブジェクト指向設計

  • オブジェクト指向設計の要点
    • 関連のあるオブジェクトをクラスに組み入れ、正しい粒度を判断し、責務を割り当てる。
    • 相互にやり取りするオブジェクトの結合性を最小限に抑える。
    • コードを再利用しやすくする。

関連のあるクラス

  • 要件とユースケースから素材を洗い出し、それらを関連のあるクラスの階層としてまとめる必要がある。
    • 顧客クラスは、名前・住所・誕生日が関連など。
  • 顧客が注文一覧を取得する振る舞いをどこに配置するか?。顧客クラスの一部になるのか?。答えは、クラスが設計されている論理的背景、設計に使用されているパターン、レイヤー間で達成可能な分離のレベル、開発者やアーキテクトのスキルと戦略的ビジョンによって決まる。

合成と継承

  • クラスの継承では、派生クラスは親クラスのコードを継承するだけでなく、コンテキストを継承し、そこから親クラスの状態に対する可視性を手に入れる。これにより、親クラスが変更されると派生クラスが動作しなくなる可能性がある。
  • オブジェクトの合成では、基底型のインスタンスを保持する新しいラッパークラスを作成する。ラッパークラスは、基底クラスのメンバーにアクセスしたり、振る舞いを変更することができない。ラッパークラスが基底クラスのどの部分をどのように公開するかを決める

オブジェクト指向のもう一つの勢力

  • 効果的なコードを確実に書くためには、開発者が以下3つの点に集中すべき。
    • 変化する可能性が高い部分を切り離す。
    • クラスが必要ではないことがある。関数があればそれでよい場合は関数を使用するだけでよい。
    • 現実の世界がモデルではなくイベントを表すことに注意する。イベントはまさにデータを運ぶもの。

3.3 開発ベクトルと設計ベクトル

SOLID原則

  • 単一責務の原則(SRP)

    • クラスを変更する理由は常に1つでなければならない。
    • コードを書くときには、クラスをできるだけシンプルに保ち、コアタスクに焦点を合わせるようにする。
  • 開放/閉鎖の原則(OCP)

    • モジュールは拡張に対して開いてなければならず、修正に対して閉じていなければならない。
    • 拡張に対して開いているとは、他の関連する機能を構築するためのベースを使用できること。
    • 修正に対して閉じているとは、他の関連する機能を実装するために既存のコードを変更しないこと。
    • OCPは、合成、インターフェース、ジェネリックといったプログラミングメカニズムを使用。
  • リスコフの置換原則(LSP)

    • 継承利用なので、パス。
  • インターフェース分離の原則(ISP

    • インターフェースの関数を最小限に保ち、肥大化をさせない。
    • ISPを正しく適用すると、インターフェースが何種類かの関数の集まりに分割され、各クライアントと本当に必要な関数の集まりがマッチングできる。
  • 依存関係逆転の原則(DIP

    • DIパターンやServiceLocatorパターンの理論的根拠となる原則。
    • DIPは、実装ではなくインターフェースへのプログラミングという原則の背後にある概念の形式化したもの。

コーディングベクトル

  • KISS(Keep It Simple, Stupid)

    • ソフトウェアの世界では、開発者が機能を追加しすぎる傾向にあるので、実装に含まれるロジックがどれ1つとして欠けてはならないシステムを作成すること。
    • 単純な言い方をすると、付け加えるものがないときではなく、取り除くものがないとき。が表現できたシステムのこと。
  • YAGNI(You Ain't Gonna Need It)

    • 機能を実際に必要なときに実装すること。
    • 必要になるかもしれないと予測して実装すると、コーディング、テストの量が増え、その存在自体が将来の拡張に対する足かせになるかもしれない。
  • DRY(Don't Repeat Yourself)

    • コードの重複を避ける
  • Tell Don't Ask

    • データを包み込み、振る舞いを公開すること。
    • 日常会話の具体的な例として、嫁から「今何してる?忙しい?」と聞かれるより、「ごみを出してきてー」と言われるほうがコミュニケーションの仕方。この考え方をオブジェクト間のやり取りに利用。

3.4 防御的プログラミング

  • 防御的プログラミングとは、入力が予想外のものであったとしても、ソフトウェアを予測可能な方法で動作させること。
  • 具体的には、事前条件・事後条件・不変条件を明確にする。 +事前条件は、メソッドの処理開始時に、メソッドが実行できるかどうかを判定する条件のこと。
    • 事後条件は、メソッドによって生成される出力と、オブジェクトの状態に対する変更のことで、メソッドから制御を戻すときに適用される条件のこと。
    • 不変条件は、コンストラクターやセッターなど、パブリックメソッドの実行中に変化しないクラスメンバーに適用される条件のこと。オブジェクトが論理的に矛盾した状態になるのを避けること。

第4章 高品質なソフトウェアの作成

  • ソフトウェアが使用されている間は保守が必要で、よいソフトウェアとは、効果的なリファクタリングに適したソフトウェアのこと。
  • リファクタリングの効果は、テスト容易性・拡張性・読みやすさの3つの要素と、デグレードの疑いがあるものをすべて捕獲するテストによって決まる。

4.1 テストしやすいコードの記述

  • ソフトウェアを自動的にテストすることの必要性が認識された結果、テストしやすいソフトウェアを記述するという重要な考え方が必要になった。
  • アプリケーションのロジックを左右する重要な決断が下される場所で、テストを重点的に行うべき。特にドメイン層を重点的に。
  • テスト容易性とは何か

  • テスト容易性とは、コードをテストするときの容易さ。

  • コードが期待どおりに動作するかどうかを明示的に、自動的に、繰り返し判断することが可能。
  • テスト容易性の原則を満たしていると、本質的にテストしやすく、読みやすく、理解しやすく、よって保守しやすいシステムとなる。
  • テスト容易性の原則は、以下3つの特性を定義。
    • 制御
      • ソフトウェアはどのようなパラメータが要求され、どのような戻り値が生成されるのかが明確になるような方法で作成する。
      • 依存関係を抽象化し、外部の呼び出し元からそれらを自由に注入できるようにするための手段を提供。
    • 可視性
      • テスト対象のソフトウェアの現在の状態と、ソフトウェアが生成できる出力を観察する能力として定義。
      • 要するに、メソッドの実行後に検証させる事後条件のこと。
    • 単純さ
      • テストしなければならないものが少ないほど、より確実で迅速なテストが可能となるため、きわめて凝集性が高い単純なコンポーネントはテストしやすい。

4.2 コードの拡張性に関するプラクティス

インターフェースに基づく設計

  • インターフェースは、2つのソフトウェアコンポーネント間で設定される取り決めに相当する。
  • クラスなどのソフトウェアコンポーネントで特定のインターフェースに対処できることを宣言すると、事実上、同じインターフェースをサポートする他のすべてのコンポーネントにも対処できる。拡張可能なコードはこの考え方の上に成り立っている。
  • すべてのクラスを拡張可能なクラスとして設計する戦略は、オーバーエンジニアリングとなる。そのため、本当に価値がある状況を見つけて、それに対処することが大事。

4.3 他人が読めるコードを書く

ソフトウェアの特性としての読みやすさ

  • コードが読みにくいということは、コードに手を加えている開発者がそのコードをよく理解していなければ、コードを良くするどころか悪くする可能性がある。
  • 読みやすさを向上させるための実用的なルール

  • 読みやすさの定義は、コメント・整合性・明確さの3つのルールとして定義。

    • コメントは、コードにおいて下される自明ではない決断を説明する文。が良いコメント。
    • 整合性は、コーディングガイドラインを設けて、社内全体で共通としていることが理想。
    • 明確さは、コードがすらすら読めるようなスタイルが適用されている。

第1部は、理論的な話で、ひたすら保守性が大事と言ってる気がするし、個人的には保守性が一番大事なので、すげー納得できた。 ただ、実際の開発現場だと、

  • 保守と意識した設計・実装する。
  • プロダクトを早くリリースする。

の2つのバランスを上手にとる必要があると思う。

第2部は実践的な話っぽいので、楽しみ。 僕の好きなDDDの話題もあるし。 以上。

書評:「究極のC#プログラミング 新スタイルによる実践的コーディング」のまとめ

「究極のC#プログラミング 新スタイルによる実践的コーディング」を読んだので、まとめてみました。 自分用のメモなので、適当にまとめちゃってますが。

3.新しい繰り返しスタイル

yield return

  • yield return 文yield break 文反復子ブロックと呼ばれている。
class Range
{
    private int from, to;

    public IEnumerator<int> GetEnumerator()
    {
        for (int i = from; i <= to; i++) yield return i;
    }

    public Range(int from, int to)
    {
        this.from = from;
        this.to = to;
    }
}
class Program
{
    static void Main(string[] args)
    {
        foreach (var i in new Range(0, 9))
        {
            Console.Write("{0}", i);
        }
    }
}
  • 反復子ブロックで意識すること
    • 反復子ブロックはすぐには実行されない
    • 実行されるのは、foreach文で列挙が開始された後
    • 反復子ブロック内でyield return 文が実行されると、その引数の値がforeach文に渡り、1回実行される
    • foreach文に指定された実行文(上だとConsole.Write)の実行が終わると、反復子ブロック内の続きが実行される。

5.null許容型

null許容型とは

  • 値型でもnullを保持できるようにする。
  • 値型の型名の後ろに?を付与するとnull許容型になる
private int? num

null許容型ができた背景

  • 参照型と値型が同じように扱えるため。
  • ただ、すべての状況において、値型にnullを許容してしまうと、実行速度低下や必要メモリ増加の悪影響が出る。
  • そのため、nullを許容したい場合だけに限定されることが可能。
  • 逆の言い方をすると、nullになることが絶対にありえない変数の型には使うべきではない。

6.ラムダ式(全編)

ラムダ式は上位スコープにアクセス可能

 static void Main(String[] args)
    {
        string message = "hello world";
        
        var action = new Action(() => { Console.WriteLine(message); });
        action();
    }
  • 必要とされるあらゆる情報を引数経由で渡さずに済むので、引数の肥大化を防ぐ
 static Action CreateAction()
    {
        string message = "Hello World";
        return () => { Console.WriteLine(message); };
    }

    static void Main(String[] args)
    {
        var action = CreateAction();
        action();
    }
  • こういうのもOK。
  • ラムダ式が上位スコープの変数を参照しているとき、その変数の寿命をラムダ式の寿命が尽きるまで延命される。

ラムダ式で継承を置き換える

ラムダ式に置き換えた利点としては、ソースコードに書き込む文字数が減り、楽ができ、間違いが混入する可能性も減る。

実際のラムダ式で置き換えたコードは、以下の通り。


class Person
    {
        public Person(Action sayMyName)
        {
            SayMyName = sayMyName;
        }


        public Action SayMyName { get; }


        public static Person createStringNamePerson(string name)
        {
            return new Person(
                () => Console.WriteLine(name)
            );
        }

        public static Person createCharNamePerson(char name)
        {
            return new Person(
                () => Console.WriteLine(name)
            );
        }
    }

    class Program
    {
        static void Main(string[] args)
        {

            Person[] persons =
            {
                Person.createCharNamePerson('L'),
                Person.createStringNamePerson("サンプル 太郎"),
            };

            Array.ForEach(persons, person => person.SayMyName() );
        }
    }

8. 部分クラスと静的クラス

部分クラス

部分クラスとは

  • クラス・構造体・インターフェースの宣言を複数のファイル等に分割できる

メリット

  • フレームワークによって自動生成されるコードとプログラマーが記述するコードをファイル分割できる。
  • 自動生成されるコードは、プログラマーが直接修正すると、危険なので、容易に書き換えられないようにすることで安全性が高まる。
  • 既存のソースコードを書き換えることなく、機能強化を実施できるため。

静的クラス

  • デザインパターンでいうところのシングルトンパターンと同じ。
  • クラス宣言の際に、staticキーワードを付けるだけ。
  • いわゆるユーティリティクラスとかで使われている
  • C#3.0で上記の専用の構文が追加された経緯として、特殊なクラスの使い方ではなく、頻出する典型的な使い方に変化。

11. フレンドアセンブリ

12.varによる変数宣言とコレクション初期化子

varキーワード

  • 「暗黙的に型指定されるローカル変数」を宣言するためのキーワード
  • varキーワードを付与する場合は、必ず変数宣言時に初期化する必要あり。
  • varキーワードの型は、常に同じなので、途中で入れ替えることは不可(宣言時がintで、stringを代入できない)

varキーワードを使う意図

  • クラス名が極端に長すぎてソースコードの読みやすさを損なっている場合
  • 同じ型名が2回書かれている場合
  • newを使わない初期化で使うべきかは微妙なところ。

verキーワードが使用できない場面

verキーワードを活用できる場面

13.自動実装と自動定義

自動実装プロパティ

通常のプロパティ定義

 class SomeClass1
    {
        private int a;

        public int A
        {
            get { return a; }
            set { a = value; }
        }
    }

自動実装されるプロパティ定義

 class SomeClass2
    {
        public int A { get; set; }
    }
  • 自動実装プロパティは、常にgetアクセサとsetアクセサの双方が必要。

オブジェクト初期化子

オブジェクトのフィールド・プロパティを初期化する手段

  • フィールドの宣言時に初期値を指定
  • コンストラクタで書き込む
  • オブジェクト初期化子を使う

オブジェクト初期化子の本質

  • private /readonlyなフィールドでは初期化できない
  • オブジェクト初期化子が、インスタンス作成中に実行されず、できてから実行されるため。
  • ただ、コレクションはreadonlyでも初期化子は利用可能。

14.拡張メソッド

概要

  • 既に存在するクラスに対して、そのクラスを変更することなく、メソッドを追加できる機能。
  • クラスを変更することなくということは、コンパイル済みのバイナリーを変更することなく追加できること。を意味する。
  • シールクラス(sealed)を拡張することも可能。

注意点

  • アクセス制御
名前 public protected private
部分クラス
継承 ×
拡張メソッド × ×
  • 既存メソッドの振る舞いを拡張メソッドで定義しても、差し替えることは不可能。
  • 拡張メソッドはオブジェクト外の存在である、オブジェクト内部に手を出すことができない。

拡張メソッドを使用すべきとき

  • 可能であれば拡張メソッドは使わないほうがいい。
  • 既存のクラスライブラリに対して、「このメソッドがあれば便利」というような状況の場合に使用する。
  • 例えばDatetime 型に対して、月末日を取得するメソッドを用意する場合など。

15.LINQとクエリ式

LINQのメリット

  • 簡潔で読みやすい(特に複数の条件をフィルと処理する場合)
  • 強力なフィルタ処理、並び替え、グループ化機能を最小限のアプリケーションコードで実現
  • ほとんど変更せずに、他のデータソースに移植できる
  • Parallel LINQを用いると、クエリを並行して実行可能

LINQを使ううえでの注意点

  • クエリ対象のコレクションの中身が変化しても、クエリオブジェクトを作り直す必要はない。
  • 逆に、ある瞬間のクエリ結果を保存しておきたければ、クエリオブジェクトを即座に列挙しておく必要あり。
  • どれほど膨大なデータがヒットするクエリであろうと、クエリオブジェクトを作成するだけなら、ほとんど時間はかからないし、メモリも消費しない。
  • どれほど膨大なデータがヒットするクエリであろうと、単にそれらを列挙するだけならほとんどメモリは消費しない。

【DDD Alliance! ドメイン駆動設計をやってみた 6つの現場からの報告】に登壇しました。

ddd-alliance.connpass.com

縁あって、DDD Allianceのイベントで発表させていただきました。 DDD Allianceの運営メンバーに感謝です。

今回の発表に向けて

DDDをやり始めて約2年経ち、その間に経験したことをまとめようと思ったので、

 ドメイン駆動設計によるサービス開発

という広いテーマに決めました。

ある意味、集大成的な位置づけですね。

 ※DDDはこれからもやるし、成長し続けるつもりですが。

ということで、話す内容としては

  • 設計・実装の考え方(ドメインモデルやコード例やDB設計な ど)

  • チーム環境の考え方(開発プロセスやチームビルディングな ど)

の2つにしました。

実際、資料を作っていくと、『チーム環境の考え方』のほうを注力してた感じでした。

これは、今現在、自分が悩んでいたり、工夫したりしているほうだったのかなっと思っています。

思い返すと、DDDをやり始めた頃や、DDDを広めていく活動の初期は、

『設計・実装の考え方』のほうを、めちゃめちゃ試行錯誤していて、

『チーム環境の考え方』は、置き去りになっていた感がありました。

最近はようやく2つのことをバランスよく考えて、行動できるようになったと思っています。

また、資料を作る過程で、自分が考えていることを整理していったんですが、自分でも意識していなかったつながりが見つかったのが、すごいよかったです。

具体的には、DDDの価値とDDDにおけるチームビルディングの価値がつながったところです。

この辺が、個人的には発表する機会を得られた時の価値かなっと思っています。

あと、初めて1時間という枠だったんですが、当然ながら、発表練習するのも1時間くらいかかるので、大変でした。

これって、みなさん、どう効率的に練習しているんだろうと不思議です。

発表資料

www.slideshare.net

Twitter

自分の発表に対して、気づきがあってよかった的なツイートが流れていたので、 発表した甲斐があったなっと実感し、いつかの機会にまた発表したいなっと思いました。

以下、僕が見つけたやつ。

まとめ

発表時にも話したんですが、これからは

  • CQRS

  • 非同期メッセージング

という2つの技術キーワードを追いかけてみて、DDDと組み合わせた時に、既存の考え方からどう変化するのかを模索しようと考えています。

まずは、CQRSのほうからやってみたいと思います。

ということで、次の発表機会はいつになるのかわからないっすけど、いつ声が掛かってもいいように、準備だけはしておこう!

書評:メンバーの才能を開花させる技法

メンバーの才能を開花させる技法

メンバーの才能を開花させる技法

  • 作者: リズ・ワイズマン,Liz Wiseman,グレッグ・マキューン,Greg McKeown,(序文)スティーブン・R・コヴィー,Stephen R. Covey,関美和
  • 出版社/メーカー: 海と月社
  • 発売日: 2015/04/22
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログ (1件) を見る

この本を読み終わったので、まとめます。

今回は、技術系の本ではなく、リーダーシップ・人材マネージメントの本です。

はじめに

リーダーの特殊能力

メンバーから限界以上の力を引き出す能力と定義されています。

ピーター・ドラッガーの主張

  • 20世紀の経営が果たした、もっとも重要で、これまでにない貢献は、製造業の労働力の生産性を50倍に拡大したこと。

  • 21世紀の経営が果たすべきもっとも重要な貢献は、知識労働とその従事者の生産性を上げること。

  • 20世紀の企業にとって、もっとも価値ある資産は、製造装置だった。21世紀の組織にとって、もっとも価値ある資産は、知識労働者とその生産性である

この本を読めば、ドラッガーの主張に応えられるリーダーとはどのような人かを把握できます。

本書の目的

読者の方を増幅型リーダーにすること。そして、あなたの周囲から天才を生み出し、より大きな貢献を引き出すこと。となっています。

1.なぜ、今「増幅型リーダー」なのか

リーダーの2つの類型

リーダーにとって大切なのは、メンバーの知識をどれだけ活用できるかと定義されており、うまく活用できるリーダーを増幅型リーダーと呼んでいます。

増幅型リーダーとその逆の消耗型リーダーの違いは、以下の通りです。

No 増幅型リーダー 消耗型リーダー
1 組織で働く人たちの知性と能力をフル活用する・限界以上に引き出すリーダー 組織で働く人たちの知性と能力を損なうリーダー
2 情報の流れはチーム全体で流動的で、何かの決定はメンバーに委譲する 情報の流れはリーダーからメンバーにしか流れず、全ての決定を自分自身で行う
3 自分自身は目立とうとせず、自分が有能かどうかも気にしない 自分を賢く見せようとするあまり、他人を愚かに見せる
4 天才を作り出す その人自身が天才

増幅型リーダーの効果

効果

メンバーを有能に、より仕事ができるようにメンバーを変えていくことです。

具体的には、

  • メンバーの能力を100%引き出し、伸ばす。

  • メンバーが出し惜しみをせず、自分の持てるすべての考え、創造性、アイデアを出し尽くし、仕事に必要とされる以上の努力とエネルギーと能力を自発的に発揮する。

  • より価値のある貢献をしようと工夫と努力をする。

などが挙げられています。

また、消耗型リーダーはメンバーの20%~50%の間で能力を引き出しているとアンケートの結果が出ているとのことです。

人材の有効活用

組織を成長させるための人材の考え方として、

  • 足し算モデル(経営資源を増やすことで成長を実現)

  • かけ算モデル(既存の経営資源を活用して成長を実現)

の2つがあります。

それぞれの論理を信じるリーダーは、次のような前提で行動します。

No 足し算モデル かけ算モデル
1 社員は働きすぎている 組織の人材のほとんどは十分に活用されていない
2 一番優秀な社員は限界にきている 正しいリーダーシップがあれば、すべての能力が活用される
3 したがって、さらに大きな仕事をやり抜くには、もっと頭数が必要 したがって、知性と能力は投資を増やさなくても増幅できる

この論理をうまく表現したものは以下です。

80人の社員が50人分の働きしかできない場合もあれば、500人分の働きをすることもある。

増幅型リーダーは、人材を有効活用することで、足し算の論理から抜け出せない競合他社に対する優位性を高めます。

増幅型リーダーの考え方

それぞれのリーダーの考え方は以下の通りです。

観点 増幅型リーダー 消耗型リーダー
人材管理 育てる 使う
失敗への対応 原因を探る 責める
方向の設定 挑戦させる 命令する
意思決定 相談する 決定する
ものごとの実行 支援する 支配する

増幅型リーダーの習慣

増幅型リーダーの考え方を実践するためには、消耗型リーダーにはない以下5つの習慣があります。

  • 才能のマグネット:才能ある人材を惹きつけ、最高の貢献を引き出す。

  • 解放者:自由でありながら、緊張感のある環境を作る。

  • 挑戦者:メンバーの力を伸ばす機会を与え、自分で方向を設定するように導く。

  • 議論の推進者:緻密な議論を通して健全な判断に導く。

  • 投資家:メンバーにオーナーシップを与え、彼らの成功に投資する。

これらの詳細は、次章以降で順次説明しています。

まとめ

増幅型リーダーは天才を作り、メンバーの知識を引き出し、組織の中に伝染力のある集合知を築きます。

その結果として、増幅型リーダーは消耗型リーダーの2倍の能力を手に入れます。

2.「才能のマグネット」としての技法

概要

才能のマグネットは最高の人材を手に入れます。チームメンバーは十二分に活用され、成長して、次の舞台に飛躍できるとわかり、多くの人材が増幅型リーダーの元に集まってきます。

増幅型リーダーによる引き寄せの好循環

増幅型リーダーの環境は、以下のような好循環が生み出されます。

  1. 一流のメンバーが十分に活用される。

  2. 超一流のメンバーと認識される。

  3. 市場価値が上がり、別のチャンスを与えられる。

  4. 「成長の場」という評判が立ち、一流のメンバーを惹きつける。(1に戻る)

4つの実践

1.どこにでも人材を探す
  • 多様な才能を認識する。

  • 組織の境界を超える。

2.各人の天賦の才を発掘する
  • メンバーの生まれ持った才能を探す。

  • 自分の才能に気づいて、意図的のその能力を発揮してもらうために、才能と特定し、本人に伝える。

3.能力を最大限に活用する
  • 人々にチャンスを与える。

  • スポットライトを当てる。

4.障害を取り除く
  • メンバー全員が自我を捨てて、チームとして働くこと。

  • リーダー自身がメンバーの妨げにならない。

3.「解放者」としての技法

概要

解放者は人々の最高のアイデアと仕事を引き出すような緊張感のある環境を作り出す。その結果、メンバーはもっとも大胆で素晴らしいアイデアを提案し、最善の努力を注ぐようになります。

3つの実践

1.居場所を作る
  • メンバーが貢献できる場所を作る。

  • メンバーを前面に押し出す。

  • 話すよりも聞く。

  • 一貫した行動をとる。

  • チャンスを平等に与える。

2.最高の仕事を求める
  • ベストを尽くしているかを聞き続ける。

  • コントロールできない結果よりも最高の仕事を求める。

3.素早い学びのサイクルを生み出す
  • 失敗を認め、共有する。

  • 失敗から学び続ける。

4.「挑戦者」としての技法

概要

挑戦者は自分の知識を超えて行動できるチャンスを人々に提示する。その結果、組織全体が挑戦を理解し、それを受け入れる集中力とエネルギーを持つようになります。

3つの実践

1.チャンスの種を撒く
  • チャンスの種を撒き、メンバー自身にチャンスを見つけさせる。

  • 組織の根底にある前提に疑問を投げかけ、既存の論理を突破するような問いを発する。

  • 新たな枠組みを示す。

2.挑戦を掲げる
  • 具体的に一つずつ進める。

  • 優れた質問をメンバーに与える。その質問は、ただ考えさせるだけではなく、もう一度自分の考えを省みさせる。

  • 目標に対する行動責任をメンバーに引き渡していく。

3.自信を植え付ける
  • 目標が手に届く範囲にする。

  • 道を示す。

  • 実行する人が計画する。

  • 小さな勝利を重ねる。

5.「議論の推進者」としての技法

概要

議論の推進者は人々を議論に引き入れ、それがよりよい決定につながり、理解と実行が進みます。

3つの実践

1.問題の枠組みを示す
  • 質問を定義する。

  • 「正しいメンバー」でチームを作る。

  • データを求める。

  • 決定の方法を示す。

2.議論を盛り上げる
  • 安全を確保する。

  • 厳しく突きつめる。

3.「開かれた決定」を徹底する
  • 意思決定プロセスを改めて明確にする。

  • 恐れず決定を下す。

  • 決定内容とその理由を知らせる。

6.「投資家」としての技法

概要

投資家は人に投資して責任を与え、リーダーがいなくても自分自身の力で結果が出せるようにします。

3つの実践

1.責任の所在を明らかにする
  • リーダーを任命する。

  • 最終目標への責任を与える。

  • 役割を広げる。

2.人的資源に投資する
  • 教えを導く。

  • サポート役を指名する。

3.最後まで責任を預ける
  • 責任というバトンは、必ずメンバーに渡す。

  • 終わりまでやり遂げる。

  • 目に見えるスコアボードを作る。

書評:C#実践開発手法

C#実践開発手法 (マイクロソフト公式解説書)

C#実践開発手法 (マイクロソフト公式解説書)

この本を読み終わったので、感想を書きます。

ちなみに、普段Javaで開発しているので、C#に特化した部分は、読み流した感じです。

導入

メインテーマ:アダプティブコードとは?

意味

コードを大幅に変更することなく、新しい要求や予想外のシナリオに対処する適応力のあるコードのことを指しています。

目的

要求は変化する可能性があるので、変更にどのように対処するかが、成功するソフトウェアプロジェクトかどうかの決め手になります。

そのため、アダプティブコードと表現されている適応力のあるコードが、これからは必要になってきます。

本書の内容

アジャイル開発を用いて、アダプティブコードを実装するためのプラクティスを紹介しています。

具体的には、デザインパターン、SOLID原則などの考え方をどう実現すればいいのか?をコードも含めて説明しています。

また、インターフェースという考え方を、しつこいくらいに説明しています。

なので、普段、インターフェースに馴染みのない人は、インターフェースの重要性が実感できると思います。

重要な章:2章 依存関係と階層化

全ての章を読みましたけど、「2章 依存関係と階層化」が一番重要だと感じました。

理由としては以下です。

  • この章が一番網羅的に説明されている。

  • 実際のプロジェクトにおいて、開発チームメンバー全員が理解すべき内容。

  • この章の考え方を基本にして、次章以降の各章が説明されている。

ということで、「2章 依存関係と階層化」をまとめていきます。

概要

依存関係の構造を理解していないと、あるモジュールの変更が、別の無関係に思えるモジュールで副作用となって現れることがあります。

そのため、アダプティブコードを実現するためには、依存関係を効果的に管理する必要があり、最も一般的なパターンに階層化があります。

依存関係の定義

依存関係は2つの概念間の関係であり一方が存在しなければ、もう一方が何らかの機能を実現できない、あるいは存在し得ないことを意味します。

以下の例だと、クライアントはサービスに依存しているということになります。

f:id:mmm-mao:20150802101026p:plain

依存関係の管理

概要

依存関係をうまく管理しないと、小さな妥協があっという間に全体的なアーキテクチャの問題に発展します。

そのため、依存関係を最初から正しく管理し、問題が入り込む余地がないように注意する必要があります。

不吉な匂い

依存関係の不吉な匂いの例として、「newキーワードを使ったオブジェクトの生成」がありました。

不吉な匂いの理由は以下です。

  • 実装を拡張することが不可能:依存元と依存先のどちらも編集しないで拡張することができない。

  • 依存関係の連鎖:依存先が依存しているモジュールも、依存元は暗黙的に依存していることになる。(次に出てくるEntourageアンチパターンのこと)

  • テスタビリティの欠如:依存先をモックに置き換えることができないので、依存元のテストが難しくなる。

この不吉な匂いに対する対応案として、依存性の注入(DI)が挙げられています。

※余談ですが、これからのフレームワークを選定で、依存性の注入をフレームワークがサポートしている。っていうのは必須の要件ですね。

Entourageアンチパターン

インターフェースに対するプログラミングを説明するときにありがちな間違いとなります。

内容としては、単純なものを1つ要求したはずなのに、余分なものまで全て引き連れてくるという望ましくない依存管理の管理を表しています。

例えば、以下のような関係の時に、コントローラパッケージだけビルドすると、データソースパッケージに暗黙的に依存しているため、結局ビルド後には、永続化の手段が把握できる状態になります。

f:id:mmm-mao:20150802102536p:plain

なので、このアンチパターンは、インターフェースと実装が同じパッケージに含まれている時に発生します。

そのため、インターフェースと実装は別パッケージに切り出すことが原則となり、具体的な手段が次に説明するStarwayパターンとなります。

Starwayパターン

クラスとインターフェースを構成するための正しい方法と説明しているパターンです。

このパターンを適用することにより、依存先はインターフェースが含まれるパッケージのみになり、暗黙的にも実装が存在するパッケージに依存しないことになります。

具体的なパッケージ図は以下の通りです。

f:id:mmm-mao:20150802103141p:plain

階層化

相互にやりとりしながらアプリケーション全体を構成する機能の水平レイヤーとしてコンポーネントを捉えることです。

コンポーネントは他のコンポーネントの上に層状に積み重ねられ、依存関係は常に下に向いている必要があります。つまり、一番下のレイヤーには依存関係がないということです。

僕は普段ドメイン駆動設計で開発しているので、ドメイン駆動設計の例だと、以下のような階層化になります。

f:id:mmm-mao:20150802103608p:plain

2章 依存関係と階層化のまとめ

ソフトウェアの安定性、適応性を長期的に確保するためには、依存関係を正しく管理できるかどうかにかかっています。

正しく管理するためには、全ての開発者が、所属しているチームの依存関係の方針を理解して開発することが重要になってきます。

そのため、依存関係の大切さや所属チームの依存関係の方針がいつでも観れる図をチームで共有することが大事です。

まとめ

本書は、アジャイルプロセス(※1)とアジャイルプラクティス(※2)の両方にフォーカスを当てているので、実際の開発する際に参考になる部分がとても多いです。

あと、実際のコードもたくさん出てきているので、写経しながら進めていくと、この本に書かれていることをより深く理解できると思います。

ということで、現場でアダプティブコードを実現したい方には、オススメです。

個人的には、「アジャイルソフトウェア開発の奥義 第2版」よりもこっちの本のほうが、今の時代に合った説明になっていると感じました。

  • ※1:アジャイルプロセスは、ソフトウェア開発チームがフィードバックを迅速に引き出し、それに応じて目標を切り替えるための方法を提案

  • ※2:アジャイルプラクティスは、同様に方向転換が可能なコードをソフトウェア開発チームが記述するための方法を提案