スクラム開発に関して

アジャイルとは?

アジャイルとは価値があるものを生み出すために
より良い開発方法を見つけ出そうとしている状態
それ以外の時はアジャイルではない。
スクラムだろうがXPだろうが
より良い開発方法を見つけ出そうとしている時は
アジャイルであり、それ以外はアジャイルではない

アジャイルソフトウェア開発宣言

アジャイル宣言の背後にある原則

スクラムとは?

スクラムは何を解決してくれるフレームワークなのか?

  • 開発効率向上
  • 状況の変化に強い
  • 成長できる

そういったフレームワークではありません。
そういった効果があったとしてもそれは、そのチームが努力した結果でしかありません。
スクラムは下記のことしかできません。

スクラムが有効なのは?

スクラムは、下記のような単純なものや既に実現方法が明確に決まっているものには向きません。

  • 実現内容が単純な場合
  • 実現内容が変化しない場合
  • 実現方法が明確に決まっていて、失敗する可能性が小さい場合


そのプロジェクトが単純なほどウォーターフォールなどが向いています。
また、スクラムチームの生存期間が3ヶ月以下の場合はスクラムで進めても効果が薄い
(統計データー的にスクラムチームが学習したものが活用されるのが3ヶ月経過してから)。
上記以外ならスクラムはほぼ有効に活用できる。

Working Agreement

スクラムのルールとしては、まだ入っていませんが、現在、ルールとして入れるかを検討中ですが、
Working Agreementと言われるものがあります。
Working Agreementとはチームルールを全員で議論して、その決めたルールを明文化します。
このルールは、全員が納得した内容でなければなりません。
スクラムマスターは、この時、議論がカオス化しないようにきをつける必要があり、
議論内容の質と時間のバランス(指標的なもので判断)をとりながら
全員が納得した内容になるようにしなければなりません。
議論がカオス化しない為に
スクラムマスターはチーム内で議論が発生した時に合意形成をとるルールを組込むようにチームに求めるべきです。
チームは議論内容の質と時間のバランスをみて、チームとしてどのラインで判断するかを決めるべきです。
その為にスクラムマスターは議論内容の質と時間のバランスを数値化して可視化できる必要があります。
Working Agreementを作成する時の注意事項としては、下記のようなものがあります。

  • アクションに繋がらないスローガンのようなものはダメ。(例:相手を尊重する、等)
  • ルールは具体的に、判断できるようなものを目指す。計測できることが望ましい。
  • ルールを決めるためのルール、ルールを変更するためのルールなども決めておく。

Working Agreementの例

  • 問題&課題が発生して、30分以内で個人で解決できた場合でも情報は共有
  • 1つのPBLは最大で2日間ぐらいのサイズに設定(20時間前後ぐらい)
  • 1つのToDoタスクは2時間以内に設定
  • 取ったToDoタスクが完了した場合は、実績時間を記入
  • 取ったToDoタスクには、アカウントを明記
  • コードカバレッジは80%以上
  • メンバーの開発時間は1人1日4時間(4時間以上作業しても問題ない)
  • 理解度の指標は[1:全く理解出来てない/2:明確でない箇所がある/3:説明出来る]とする
  • 議論の指標は[1:まだ議論したい/2:ほぼ同意出来る(少し納得できない部分がある)/3:同意できている]とする
  • 仕様や技術的なことに関しては理解度の指標をチーム平均で2以上になるようにする
  • 議論をし尽くしたかは議論の指標をチーム平均で2以上になるようにする
  • 議論が発生したら最初の30分で発散し、残り30分で収束する(時間:理解度:議論のバランスを調整)
  • ルールの決定及び変更は、議論が発生した時のルールを適用

スクラムをはじめる前に

スクラムをはじめる前にスクラムを活用することを組織的に合意を取った方がいいでしょう。
合意を取る相手としては、部長,本部長やステークホルダーなどになると思います。
但し、いきなりスクラムを適用すると何かがよくなりますとかは言わない方がいいでしょう。
スクラムを適用したとしても改善するかはスクラムチーム次第となるので、スクラムの思想をインプットしながら、事例や課題感などを元に話すのがいいと思います。
また、プロダクトの認識合わせをやった方がいいと思います。
認識合わせの方法としてはインセプションデッキなどを活用するといいと思います。

スクラムのルール

3本柱

Transparency(透明性)

現在の状況が全員に対して可視化されていること。
また、チームルールや開発手法なども全員が納得して共通理解を持っていること。

  • 進捗状況を全員が共有している(完了/未完了?完了の場合は作成物は?)。
  • プロセスの用語を全員が理解している(誰に聞かれても明確に説明できる状態)。
  • 開発手法に関して全員が納得して共通理解を持っている(誰に聞かれても明確に説明できる状態)。
  • チームルールに関して全員が納得して共通理解を持っている(誰に聞かれても明確に説明できる状態)。
  • 作業内容に関しての完了の定義を全員が共有している(誰に聞かれても明確に説明できる状態)。

下のような曖昧な状態は、認められない。

  • もうすぐできます。
  • 90%ぐらいです。
  • こんな感じで開発するんですよね。
inspection(検査)

成果物やプロセスを検証することで、変化を検知します。
また、 新しい開発手法や改善などの取り組みに関しても検証します。

  • 成果物は、想定通りなのか?
  • 取り組んだ改善方法は、想定通りの効果が出たか?
  • 新しい開発手法は、想定通りの効果が出たか?
Adaptation(適応)

プロセスの不備が許容値を超え、成果となるプロダクトを受け入れられないと判断された場合、
プロセスやその構成要素(仕様や開発手法及び改善への取り組みなど)を調整する必要がある。
調整はできるだけ早く行い、これ 以上の逸脱を防がなければいけない。

  • 実を元になんらかの調整や改善を行います。
  • 誰にでも明確に理解できるもの(数値化されているなど)で、全員が納得し共通理解を持っているものを適応させて行きます。
  • 根拠が曖昧なものを元に適応することはありません。

責務と役割

プロダクトオーナーとしての主な役割

プロダクトオーナーは、開発チームから生み出されるプロダクトの価値の最大化に責任を持つ。
組織・スクラムチーム・個人によって、その方法はさまざまである。
プロダクトオーナーは、プロダクトバックログの管理に責任を持つ 1 人の人間である。
プロダクトバックログの管理には、以下のようなものがある。

  • プロダクトバックログアイテムを明確に表現する。
  • ゴールとミッションを達成できるようにプロダクトバックログアイテムを並び替える。
  • 開発チームが行う作業の価値を最適化する。
  • プロダクトバックログを全員に見える化・透明化・明確化し、スクラムチームが次に行う作業を示す。

必要とされるレベルでプロダクトバックログアイテムを開発チームに理解してもらう。
上記の作業は、プロダクトオーナーが行う場合もあれば、開発チームが行う場合もある。
いずれの場合も、最終的な責任はプロダクトオーナーが持つ。
プロダクトオーナーは 1 人の人間であり、委員会ではない。
委員会の要求をプロダクトバックログに反映することもあるだろうが、プロダクトバックログアイテムの優先順位の変更については、
プロダクトオーナーと相談しなければいけない。
プロダクトオーナーをうまく機能させるには、組織全体でプロダクトオーナーの決定を尊重しなければいけない。
プロダクトオーナーの決定は、プロダクトバックログの内容や並び順という形で見える化されている。
異なる要求の作業を開発チームに強制することは誰にもできない。

スクラムマスターとしての主な役割

スクラムマスターは、スクラムガイドで定義されたスクラムの促進と支援に責任を持つ。
スクラムマスターは、スクラムの理論・プラクティス・ルール・価値基準を全員に理解してもらえるように支援することで、その責任を果たす。
スクラムマスターは、スクラムチームのサーバントリーダーである(訳注:メンバーが成果を上げるために支援や奉仕をするリーダーのこと)。
スクラムマスターは、スクラムチームとやり取りをするときに役に立つこと/立たないことをスクラムチームの外部の人たちに理解してもらう。
スクラムマスターは、こうしたやり取りに変化をもたらすことで、スクラムチームの作る価値を最大化する。

スクラムマスターはプロダクトオーナーを支援する

スクラムマスターは、さまざまな形でプロダクトオーナーを支援する。

  • スクラムチームの全員がゴール、スコープ、プロダクトのドメインを可能な限り理解できるようにする。
  • 効果的なプロダクトバックログの管理方法を探す。
  • 明確で簡潔なプロダクトバックログアイテムの必要性についてスクラムチームに理解してもらう。
  • 経験主義におけるプロダクトプランニングについて理解する。
  • 価値を最大化するためのプロダクトバックログの調整方法をプロダクトオーナーに把握してもらう。
  • アジャイルを理解・実践している。
  • 必要に応じてスクラムイベントをファシリテートする。
スクラムマスターは開発チームを支援する

スクラムマスターは、さまざまな形で開発チームを支援する。

  • 自己組織化・機能横断的な開発チームをコーチする。
  • 開発チームが価値の高いプロダクトを作れるように支援する。
  • 開発チームの進捗を妨げるものを排除する。
  • 必要に応じてスクラムイベントをファシリテートする。
  • スクラムがまだ完全に適用・理解されていない組織環境で、開発チームをコーチする。
スクラムマスターは組織を支援する

スクラムマスターは、さまざまな形で組織を支援する。

開発チームとしての主な役割

開発チームは、各スプリントの終了時にリリース判断可能な「完成」したプロダクトインクリメントを届 けることのできる
専門家で構成されている。
「完成」したインクリメントは、スプリントレビューに必要 である。
インクリメントを作成できるのは、開発チームのメンバーだけである。
開発チームは、自分たちの作業を構成・管理するために、組織から体制と権限を与えられている。
その相乗効果によって、開発チーム全体の効率と効果が最適化される。
開発チームには、以下のような特徴がある。

  • 自己組織化されている。
  • プロダクトバックログをリリース判断可能な機能のインクリメントに変える方法は、誰も(スクラムマスターでさえも)教えてくれない。
  • 機能横断的である。インクリメントを作成するスキルをチームとしてすべて備えている。
  • ある人にしかできない作業があったとしても、スクラムにおける開発チームのメンバーに肩書きはない。
  • テスティング、アーキテクチャ、運用、ビジネス分析のような専門領域であっても、スクラムは開発チームのサブチームを認めていない。
  • 開発チームのメンバーに専門能力や専門分野があったとしても、最終的な責任は開発チーム全体が持つ。
開発チームの規模

開発チームに最適な人数は、小回りが利く程度に少なく、1 つのスプリントで重要な作業が成し遂 げられる程度に多い人数である。
開発チームのメンバーが 3 人未満の場合は、相互作用が少なく、 生産性の向上につながらない。
また、開発チームの規模が小さいと、スキル不足が原因でリリース 判断可能なインクリメントを届けられない可能性もある。
メンバーが 9 人を超えた場合は、調整の 機会が多くなってしまう。
また、チームの規模が大きいと経験的プロセスが複雑になり、有益ではな くなる。
スプリントバックログの作業に携わらないのであれば、プロダクトオーナーとスクラムマスタ ーはこの人数に含まない。

マネージャーとしての主な役割

  • コマンドコントロールモデル(外部から指示して作業をしてもらう形態)ではない。
  • チームがどのプロダクトやどのプロジェクトに関わるかを決定する。
  • 明確なゴールを定め、このゴールが目的と方向性をチームに与える。
  • ビジネス上のニーズや制約とのバランスをうまく取ったチームを作る。
  • チームの構成を変更した方がチームのパフォーマンス及び組織全体を改善できると判断した場合、チーム体制を変更できる。
  • チームが自己組織化する為に責任(権限)をチームへ委譲する。
  • チームが実現したことに対して、チームに考えさせて、チームに責任を持ってい対応してもらうように促す。
  • チームに対して、ヒントを提示したり、質問したり、課題を提示したりしてチームをサポートする。
  • チームメンバーのモチベーションを高く維持できるように環境を作り出す。
  • チームメンバーが常に何かを学び、スキルセットを磨き続けられるような環境を作り出す。
  • 機能エリアに関する知識を有し、機能エリアにおける一貫性を保ったり、メンバーを指導したりする。
  • アジャイルの価値と原則を受け入れ理解して、周囲にアジャイルの価値を広める。
  • チームの問題及び課題がチームとして解決できるレベルを超えている場合はスクラムマスターと協力し、障害を取り除く。
  • 各部門と社内調整しやすいように環境(全体をアジャイルの原則に合わせていく)を作り出す。
  • 社外と社外調整しやすいように環境(全体をアジャイルの原則に合わせていく)を作り出す。
  • 予算の確保及び管理をする。
  • 必要な人材を採用する。
  • 評価や報告をアジャイルの価値や原則に見合ったものにする。

成果物

Product Backlog

プロダクトに必要なフィーチャ・機能・要求・要望・修正がすべて並べられた一覧です。
プロダクトオーナーは、プロダクトバックログの内容及び、並び順に責任を持っています。
プロダクトバックログの見積もりは、チームが行います。
プロダクトバックログのアイテムはユーザーストーリー形式で書く必要はありませんが、ユーザーストーリー形式で書かれるケースが多いです

  • ユーザーストーリー(としてが欲しい。なぜならだから)
  • 1つのアイテムにアクセプタンスクライテリア(受け入れ基準)を1つ以上定義する。
  • 1つのアイテムにやらないことも必要なら定義する。

  • WHO
    • ユーザーロールを意識しますが、必ずそれにしなければならないわけではありません。
    • 外部システムやAPI又は、コンポーネントでも問題はありません。
  • WHAT
    • どういった機能を明確に定義します。
    • 曖昧な表現や言葉はNGです。
    • 誰でも理解できるものでなければなりません。
  • WHY
    • 価値を明確に定義します。
    • 曖昧な表現や言葉はNGです。
    • 誰でも理解できるものでなければなりません。

ユーザーストーリーを適切なサイズ(機能の最小の単位)にまとめるのは難しく、慣れが必要です。
ユーザーストーリがINVESTの条件を満たしているならそれは良いユーザーストーリです。
INVESTとはユーザーストーリーの条件を満たす略語です。

  • Independent(依存がない又は少ない)
    • アイテムがそれぞれ独立していること。
    • 依存関係(前後も含む)は排除。
    • 依存度が高いと見積が難しい。
  • Negotiable(交渉可能)
  • Valuable(価値がある)
    • ステークホルダーにとって価値がある。
    • ビジネス(会社)にとって価値がある。
    • チームにとって価値がある。
  • Estimable(見積可能)
    • 見積可能。
    • 見積できるぐらいの粒度。
  • Small(最小単位)
    • 適切な大きさ。
    • 十分に分割されている。
  • Testable(テスト可能)
    • テスト可能。
    • 受入テストを定義可能

ストーリーは、INVESTの条件を満たして、幾つかのストーリーを組み合わせると1つの機能になるようにする。

特別なストーリーに関して

  • ドキュメントのストーリー
    • アジャイルだからドキュメントを作らないわけでないので、他のストーリーと一緒でこれもストーリーとして予定に入れておく。
  • 非機能のストーリー
    • パフォーマンス、拡張、安定性はいわゆる非機能要件であり、これらもストーリーとして予定に入れておく。
  • バグのストーリー
    • バグが発生することがあるので、チームがバグを発見したら、これもストーリーとして予定に入れておく。
  • スパイクストーリー
    • プログラマーがそのストーリーを実装するのに必要な技術についてよく知らない場合がある。
    • その調査のためのストーリーを作成する(ポイント設定は0ポイント)。


Product Backlog作成時の注意点
プロダクトバックログを書くスピードは1つにつき1分です。
それ以上掛かってしまう場合は、事前の情報収集が足りてない可能性があるので、プロダクトバックログを書く場合は、
事前の情報収集は十分にしておく。
情報収集が足りてないと開発チームに悪い影響が出てしまう。
スプリント中は開発者からの質問が多いので、情報が足りなく即座に答えられないと不要な議論が発生したり、
開発チームが待ち状態になるなどの弊害が発生してしまいます。

Sprint Backlog

スプリントで達成しなければならないゴールを実現する為の作業がすべて並べられた一覧です。
開発チームはスプリントでどこまで達成するかを決定する責任を持ちます。
スプリントで達成するプロダクトバックログのアイテムを決定後、それをインクリメントに実現する為の方法を決めます。
決めた方法を実際の作業(タスク)に細分化します。
チームはどのようにスプリントゴールを達成し、どのように期待されるインクリメントを作成するかを
プロダクトオー ナーとスクラムマスターに説明できなければなりません。

Sprint Backlog作成時の注意点
スプリントが停滞するようなもは、スプリントバックログには入れません。
そのスプリントで達成しなければならないプロダクトバックログのアイテムの設計や検討及び技術検証などは、
スプリント開始前に明確なっている必要があります。

上記に記載しているようにスプリントが停滞するようなもの(設計や検討及び検証など)はスプリントには含めない。
そう言ったもは前スプリント中にProduct Refinementを取り入れるなどしてクリアにしておく方がいいでしょう。

Impediments List

プロジェクトでのポジティブ、ネガティブなことを記載するリスト。
但し、個人攻撃をするようなデリケートな問題は慎重に扱う必要があります。
スクラムマスターは、インペディメントリストの内容の内容及び、並び順に責任を持っています。

セレモニー

Sprint Planning Meeting

  • スプリントでなにを実現するかを明らかにする(チームとPOがそれをコミットしている状態)。
  • 実現方法が明確になっている(設計が完了している)。


Sprint Planning Meetingの注意点
ラニングできるものは仕様が明確であり実現方法(設計的な部分)が明確あり完了定義が明確なものに限ります。
このプラニングではこのスプリントで達成しなけれならないゴールに対して、どう作業していくことで達成するかをプランニングするべきです。

Daily Scrum Meeting

  • チームが学習したこと共有する。
  • 前回から今回までの間の内容を共有する。
  • 今回から次回までに何を行うのかを共有する。
  • スプリント内外の気になることを共有する。


Daily Scrum Meetingの注意点
このタスク終わりましたや次はこのタスクやります的な共有に終始している状態はあまり良くありません。
チームが設定したその日のゴールに対して自分が作業した部分がうまくいったのか?
うまくいった理由は?
いかなかったのか?いかなかった理由は?
などを共有するべきです。
また、スクラムマスターはチームがゴールを意識してそれに向かって進んでいる状態であるか判断できなければなりません。
その為にスクラムマスターは下の3つをチームに対して問うべきです。
前日に設定したチームとしてのゴールを達成したのか?
達成していないならそれを阻害した原因はなんなのか?
今日のチームとしてゴールはなんなのか?

Sprint Review Meeting

  • チームがリリース判断可能な完成したプロダクトインクリメントが完了条件(Doneの定義)を満たしているかを確認する。
  • 必要ならチームがステークホルダー(実際利用するユーザーがベスト)の前でデモを行う。
  • スプリントで約束されたことの内、実現できたこととできなかったことを明確にする。
  • プロダクトを実際操作しさらに良くできないかを議論する。


Sprint Review Meetingの注意点
プロダクトオーナーは誰よりもプロダクトを使い倒して、その良し悪しを把握している必要があります。
PBLの完了条件を満たしているかはそのPBLを完了した時にプロダクトオーナーはプロダクトを触って確認するべきです。
Sprint Review Meetingで全てのPBLの完了条件を満たしているか確認している状態は、それはプロダクトオーナーの怠慢でしかありません。
それが出来ていないとプロダクトを実際操作しさらに良くできないかを議論する本来の目的が達成出来ない弊害が出ます。
その為、プロダクトオーナーはスプリント中に常にプロダクトを触って、チームに関わっていくべきです。

Sprint Retrospective Meeting

  • スプリントで約束されたことの内、実現できたこととできなかったことを明確にする。
  • プロダクトを実際操作しさらに良くできないかを議論する。


Sprint Retrospective Meetingの注意点
スクラムチームの振り返りは、チームとしての働き方又は個人としての働き方に関して、振り返るべきです。
この機能が終わったからよかったとかこの手法を知れたのがよかったなどのレベルで議論しても意味がありません。
なんらかの課題に対してチームとしてどう動いてどうだったのか?や個人としてどう動いてどうだったのか?などを議論して
次はどう働き方を改善(変える)するかを考える必要があります。

Product Refinement Meeting

  • 追加や変更されたもの内容確認や見積もりなど。
  • スプリントの中長期的な話。
  • スプリントの5%~10%ぐらいのコスト。


Product Refinement Meetingの注意点
プロダクトオーナーがチームにアイテムの見積もりを依頼する場合、
そのアイテムはチームが確認した時に実現方法(設計的な部分)を明確できる状態にしておく必要があります。
また、チームが実現方法を議論していく中で多くの質問にプロダクトオーナーとして回答できる状態でなければなりません。

セレモニー以外のもの

Sprint

スクラムの中心はスプリントである。
スプリントは、利用可能なリリース判断可能なプロ ダクトインクリメントを作るための、1 か月以下のタイムボックスがある。
スプリントは、開発作業を 行う連続した期間である。
スプリントが終了すると、新しいスプリントが開始される。

  • スプリントゴールに悪影響を及ぼすような変更を加えない。
  • 品質目標を下げない。
  • 学習が進むにつれてスコープが明確化され、プロダクトオーナーと開発チームの交渉が必 要になる可能性がある。

Stop a Sprint

スプリントが停止すること。
競合他社が同様のプロダクトを先にリリースして、優位性が確保できない場合や資金が尽きてしまった場合などがある。

Product

プロダクトバックログに記載されているアイテムの1つに対して必ず1つ以上定義する。
チームに開発したプロダクトがユーザーやクライアントに受け入れてもらえるかを考える機会を与える為に存在する。
また、やってはいけないことを必要なら記載することもできる。

Acceptance Criteria

プロダクトバックログに記載されているアイテムの1つに対して必ず1つ以上定義する。
チームに開発したプロダクトがユーザーやクライアントに受け入れてもらえるかを考える機会を与える為に存在する。
また、やってはいけないことを必要なら記載することもできる。

Definition of Done

プロダクトバックログアイテムやインクリメントの「完成」を決めるときには、全員がその「完成」の 意味を理解しておかなければいけない。
スクラムチームによってその意味は大きく異なるが、 作業の完了についてメンバーが共通の理解を持ち、透明性を確保しなければいけない。
これは、スクラムチームの『「完成」の定義』と呼ばれ、プロダクトインクリメントの作業が完了したかどうかの評価に使われる。
スクラムチームのDoneの定義の例としては、下記の様なものがあると思います。

Doneの逆のUndoneというものがあります。
Doneは、毎スプリント完了しているものなので、例えば、初期の頃のスプリントでは、単体テスト結合テストしか完了できたいとしたら、
それ以外は、すべてUndoneとなります。
Undoneは、未完了の作業のことを指します。
Undoneが多いとスケジュールが遅延したり、想定しないリスクが増大します。
Undoneを通常のスプリントで解消できなくなる状況になってしまったら、
Undone作業のみを実施するためだけのリリーススプリントという特殊なスプリントを実施しなければならくなります。
このUndoneは、技術的負債と言われます。
Undoneを解消するとその項目は、Doneに入りますが、毎スプリントごとに最小のコストで解消できてないとDoneには入れられません。
このUndoneを戦略的にどうするかの責任は、プロダクトオーナーになります。
スクラムマスターは、プロダクトオーナーをサポートしながら、Undoneを減らせるようにチームに働きかける必要があります。

見積もりに関して

見積もり精度

人間の特性
  • 未来を予測する能力は低い
  • 絶対値での見積をする能力は低い
未来を予測する能力は低い

未来になればなるほど予測する精度が落ち当たらない。

  • 絶対値での見積をする能力は低い
  • 床から天井まで何センチメートールですか?
  • この紙は何平方メートルですか?
  • 床から天井まで、このダウンボール箱何個分ですか?
  • この紙は、あの紙の何倍ですか?
  • 絶対値での見積より相対値での見積の方が誤差が少ない。

スクラムでの見積方法

見積は、未来になればなるほど見積精度が落ちます。
また、時間をかなり掛けても見積精度が100%になるようなことはありません。
逆に見積精度が落ちる場合もあります。

スクラムでの見積もり方法は2つあります。

  • 相対見積
  • 絶対見積

プロダクトバックログの見積方法

プロダクトバックログには、見積方法は、相対見積(ポイント)になります。
プロダクトバックログの1つ1つのアイテムにポイントを付けていきます。
ポイントは、そのアイテムの難易度などではなく、作業量によって決定されます。
プロダクトバックログは、3つのエリアを定義します。

  • 詳細なエリア
  • 荒いエリア
  • その他のエリア

プロダクトバックログに設定した詳細なエリアと荒いエリアの2つエリアは、2:8法則で最大ポイントを設定します。
2:8の法則
ほとんどの現象は、2:8ぐらのばらつきがあります。
全体の2割が優れたものなら、残りの8割の状況で優れた効果が出るといったものです。

詳細なエリアは、スプリントで達成していくアイテムが入るエリアです。
荒いエリアは、詳細レベルまで落とし込めていないアイテムが入るエリアです。
その他のエリアは、見積できるレベルになっていないか?気にしないものが入るエリアです。
詳細なエリアの最大ポイントの設定と基準となるアイテムを決めます。
見積は、基準となるアイテムと比べて他のアイテムはどれぐらいか?で相対的に見積をします。
また、詳細なエリアが最大2ポイントの場合、荒いエリアは、その4倍の8ポイントが最大になります。
プロダクトバックログのアイテムの中で、その粒度を超えているものは、この時点で分割してどちらかのエリアに入れるか、
分割できない場合は、その他のエリアに入れるか判断します。
プロダクトバックログのアイテムの見積(ポイントを設定)の方法は、いろいろありますが、プランニングポーカーでやることが多いです。
まず最初に中ぐらいのアイテムを1個選択して、プランニングポーカーでポイントをつけます。
そのポイントが基準となるポイントになります。
残りのアイテムはその基準ポイントからみて大きいか小さいかでプランニングポーカーでポイントをつけます。
プランニングポーカーに関して
プランニングポーカーは、あるアイテムのポイントを全員がカードを出し合いポイントを決定するやり方で、
出したポイントに差異があった場合、最大の人が理由を発表後、最小の人が差分を発表して、認識の違いを確認します。
最大と最小の人以外は、発言することはできません。
認識の違いを確認したら再度、全員がカードを出し合います。
3回実施して一致しない場合は、全員の合計値の平均とします(基準となるアイテムの場合は全員が一致するまでやる)。

投資利益率(ROI)の見積方法

プロダクトバックログのアイテムの投資利益率の見積の方法は、プランニングポーカーでやることが多いです。
まず作業量の見積時に決めた基準となるアイテムに対して価値をポイントとしてつけます。
残りのアイテムはその基準ポイントからみて大きいか小さいかでプランニングポーカーでポイントをつけます。
投資利益率は価値ポイントを作業量のポイントで割ると算出されます。
この投資利益率を参考に優先順位をつけます。

プロダクトバックログの優先順位

プロダクトバックログの優先順位はプロダクトオーナーが投資利益率(ROI)を参考にして設定することが多いです。
投資利益率(ROI)以外の要素(リスクや開発側の提案など)などでも優先順位を設定することもありますが、
プロダクトオーナーは開発チームの作業とプロダクトの価値を最大化する責務があるので、
どうすれば価値が最大化するのかを考えて優先順位を設定します。

スプリントバックログの見積方法

直近のスプリントで達成しなければならないプロダクトバックログのアイテムに関して、
それを達成する為の作業内容を洗い出し、絶対見積で見積を行います。
直近の作業内容が詳細になればなるほど見積精度が良くなると言われているので、
スクラムマスターは、1つのタスクが0.5時間から1時間以内に収めることを目指します。

見通しを立てる

プロダクトバックログを3〜6ヶ月分(イテレーションが2週間なら6〜12回ぐらい)を作成したら見通しを立てることができます。
開発チームがある程度、成熟している場合は、そのチームが1回のイテレーションで何ポイント消費できるか把握できているので、
プロダクトバックログの合計ポイントをチームの消費ポイントで割れば、ざっくりした見通しを立てることが可能です。
例えば、プロダクトバックログの合計ポイントが300ポイントで開発チームが消費できるポイントが20ポイントなら
イテレーションの回数は15回になります。
しかし、新規チームの場合は、まだチームとして成熟していないので、開始時点では見通しを立てることができないかもしれません。
チームが成熟して自立的に動けるようになるのが3ヶ月ぐらいかかると言われています。
その場合は、何回かイテレーションを回して、統計情報(ベロシティとかバーダウンチャートとかタスク及び時間の消費状況など)を収集します。
その収集したものは実績値なので、そのチームがどれぐらいポイントを消費できるか把握できるので、その時点で見通し立てることが可能になるはずです。
見通しは、ポイント(作業量)を基準に立てます。
プロダクトバックログの合計ポイントと開発チームの消費ポイントで判断します。
ただし、プロダクトバックログは常に変化する為、POは随時、見通しを見直す必要があります。

メトリクスに関して

ベロシティ

スクラムチームは、ベロシティは測定します。
それは、スプリントで、スクラムチームがどれくらいの量の作業を行えるかわかるからです。
その情報があるとプロダクトオーナーは、そのプロダクトの見通しが立てられるし、
チームの状況を把握したり、どれだけのものを達成したか把握できるなどのメリットがあります。
スクラムマスターは、チームのベロシティが最大のところで、安定するようにしなければなりません。
チームのベロシティが最大値を基準に-2ポイントまでの範囲に収まっているなら安定していることを意味します。
また、チームメンバーがなんらかの都合で、数日いない場合でもチームは、ベロシティを下げないように考え行動しなければなりません。
スクラムマスターとチームは、ベロシティを最大のところで安定させる責任があります。

ベロシティで生産性を測れるのか?問題

ベロシティは生産性(パフォーマンス)を測る指標ではないということがSCM達の見解となっている。
また、いろいろなスクラムの書籍等にもベロシティの誤用やアンチパターンとして記述されています。
認定スクラムマスター研修でも生産性ではないとの認識。

  • ベロシティは見積のサイズで、なんらかの単位があるわけではない。
  • チームによりストーリーでつけるポイントの粒度が違う。
  • チームにより粒度が違うポイントを元に他チームと比較しても意味がない。

もし生産性を測定する必要があるなら、多くのパラメーターを取る必要がある。

  • ベロシティ
  • タスクの状態(タスク別にToDo/Doing/Doneの数)
  • Done率
  • リードタイム(機能ができるまでの時間)
  • リリース数(新機能とバグ対応のリリース数及び、その時間)

これ以外にも数値する必要なものがあるかもしれない。

ベロシティ以外のメトリクス

ベロシティ以外にもメトリクスを取った方がいい場合があります。
但し、メトリクスを取る場合は、チームが必要だと思うものにするべきです。
メトリクスを取っているだけでは意味がありません。
そのメトリクスをチームが活用できるものを取るべきです。



自律的なチームとは?

自律的なチームとは、下記の特性を持っています。

  • 明確なゴールを持ち、ブレない方針を持っている。
  • チームの方針について議論できる。
  • チームに個人として結果をフィードバックできる。
  • どの領域で自分が役立つか考え(バウンダリー)行動する。
  • 一瞬(0.1秒)で現状を把握して、判断して行動する。
  • チームがチームを管理する(スクラムマスターは管理者ではない)。
  • 個人は、生産性を向上する為、自ら考え努力する。

チームがチームを管理しながら改善を行いチームとして成長して行きます。
また、個人としても成長します。
スクラムマスターは、そのような自律的なチーム2ヶ月で作り上げなければならない。
スクラムマスターは、自律的なチームを維持(守る)する必要があります。

自律的なチームを維持(守る)するということは?
スクラムマスターは、なんらかの理由で、メンバーがいなくなったりしても安易にチームに人を追加しません。
スクラムマスターは、誰かが新たしく入って来たとしてもその人を安易にチームに追加したりしません(プロジェクトは一緒でも自律的なチームとその人と分けて考える
スクラムチームに人を追加するということは、一度、スクラムチームが解散したことを意味します。
その場合、新しいスクラムチームになるので、自律的なチームが持つ特性を最初から構成しなおします(2ヶ月ぐらいかかる)。
プロダクトオーナーやスクラムマスターは、そのコストを掛けてもチームに人を追加するか判断しなければなりません。

スクラムが成立している状態とは?

スクラムが有効に活用されているかを判定する必要がある場合があります。
例えば、育成や研修など、ある程度、コストを掛けてスクラムを導入支援を行っているケースなどは
マネージャーやCTOなどに説明責任があったりします。
もちろん、スクラムマスターはスクラムが成立していることを把握していなければなりませんし、必要なら可視化する必要もあります。
スクラムチームの成果物としては主に下記の3つしかありません。

  • Product Backlog
  • Sprint Backlog
  • Impediments List

3つの成果物を元に説明できるとしたら下記の様なことだと思います。

  • 達成したプロダクトバックログの価値
  • 達成したスプリントバックログの価値
  • 達成したインペディメントリストの価値

但し、下記の様に第三者が判断可能となるように定量的に示す必要があります。

  • スプリントごとにどのくらいの価値ある機能ができているかを定量的に示す
  • スプリントごとにどのくらいの価値ある作業ができているかを定量的に示す
  • スプリントごとにどのくらいの価値ある改善ができているかを定量的に示す

メトリクスのところで、少し記載しましたが、定量的に関しての例としては下記の様なものが必要かもしれません。

  • ベロシティ
  • スプリントごとのバーダウンチャート
  • スプリントごとのタスクの状態(タスク別にToDo/Doing/Doneの数)
  • スプリントごとのプロダクトバックログアイテムのDone率
  • リードタイム(機能ができるまでの時間)
  • リリース数(新機能とバグ対応のリリース数及び、その時間)
  • インペディメントリストの状態(増減値)

最後に

スクラムに関して、個人的に再整理したものなので、私が所属している組織とは何にも関係ありません。
個人的なものなので、内容には責任を持てません。

CloudFoundryへSpring BootアプリケーションをPush

CloudFoundryへアプリケーションをPushする方法に関して簡単に書きたいと思います。
利用する環境はPivotal Cloud Foundryになります。
自分で試したい場合は、下記のサイトでアカウント作成して、OGとSPACEを作成してください。
Pivotal Account
OGとSPACEの簡単な説明は下記に書いておきます。
ORG
個人または複数の開発者が共通で利用するものです。
例えば、組織の単位でORGを作った場合は、その組織に所属している人達は、それにアクセスでき、
リソース、アプリケーション、サービスの可用性、カスタムドメインなどが共有されます。
SPACE
すべてのアプリケーションやサービスは、ある一定のスコープに置かれます。
例えば、組織の単位でORGを作った場合は、少なくとも1つのスペースが必要です。
スペースは、ユーザーにアプリケーションの開発、展開、保守のための共有場所へのアクセスを提供します。
各スペースの役割は、特定のスペースにのみ適用されます。

ORG,SPACE以外にもいろいろあるんですが、詳しい内容は下のリンクを参照するのがいいと思います。
Orgs, Spaces, Roles, and Permissions | Pivotal Docs

Cloud Foundryは基本的にはCloudFoundry CLというコマンドラインベースで操作されます。
f:id:chronos_snow:20161123225054j:plain

簡単な説明は終わりにして、
今回は、Spring BootのRestのアプリケーションをデプロイしてみようと思います。

Javaをインストール

下記のサイトからJavaをダウンロードします。
Java SE - Downloads | Oracle Technology Network | Oracle
Mac用のものを選択してダウンロードしてインストールします。

Gradleをインストール

下記のサイトからGradleをダウンロードします。
Gradle Distributions
ダウンロードしたら下記の要領でインストールします。

mkdir project
cd project
unzip gradle-3.2-bin.zip
mv gradle-3.2-bin gradle

環境変数の設定

ZSHの設定ファイルにパスを通します。

vi .zshrc
export GRADLE_HOME=${HOME}/project/gradle
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home
export PATH=${PATH}:${JAVA_HOME}/bin:${GRADLE_HOME}/bin

MacにHomebrewをインストール

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

CloudFoundry CLIインストール

CloudFoundryを操作する為にはCloudFoundry CLIが必要になります。
アプリケーションをデプロイしたり、アプリケーションの状態を確認するなど
このCloudFoundry CLIで全て行うことができます。

brew tap cloudfoundry/tap
brew install cf-cli
brew update && brew upgrade cf-cli

CloudFoundryへログイン

CloudFoundry CLIのインストールが完了したらログインできるか確認します。

cf login 
API エンドポイント: https://api.example
Email> <アカウントID>
Password> <パスワード>
認証中です...
OK

CloudFoundryへアプリケーションをPUSH

サンプルのRestサービスアプリケーションとして下記のものを利用します。
github.com
アプリケーションはGradleプロジェクトベースになっています。
また、CloudFoundryへPUSHする為の設定として下記のmanifest.ymlで設定を定義しています。

applications:
- name: cf_sample_service
  memory: 512M
  instances: 1
  path: build/libs/cf_sample_service-1.0.0.jar
  buildpack: https://github.com/cloudfoundry/java-buildpack.git
  stack: cflinuxfs2

CloudFoundryへアプリケーションをPUSHする場合は下記のようにすればPUSHできます。

git clone https://github.com/chronossnow/cf_sample_service
cd cf_sample_service
./gradlew build
cf target -o <ORG> -s <SPACE>
cf push

Java Virtual Machine調査方法

Java Virtual Machinenの構成

JVMとOSの領域があります。
JVMはPermanentとHeapがあります。
Permanentはクラスやメソッドなどのメタデーターがロードされる領域になります。
Heapはクラスのインスタンスが格納される領域になります。
JVM以外はOSの領域がありCヒープとSヒープがあります。
CヒープはJavaから利用されるOSライブラリーなどのネイティヴなものがロードされる領域になります。
SヒープはJavaスレッドが格納される領域になります。

f:id:chronos_snow:20161002234440p:plain

各領域に関して

JVM Permanent クラスファイル(メタデーター)がロードされる領域
JVM New Eden 新しいオブジェクトが作成された時に最初に格納される領域
JVM New Survivor From Scavenge GCが発生してTo領域にあるオブジェクトで生存しているものはこの領域に移動
JVM New Survivor To Eden領域が満杯になるとScavenge GCが発生してオブジェクトがこの領域に移動
JVM OLD Scavenge GCが32回発生しても生存しているオブジェクトはこの領域に移動(FullGCで消える)
OS Cヒープ Javaから利用されるOSライブラリーなどのネイティヴなものがロードされる領域
OS Sヒープ Javaスレッドが格納される領域

JVMパラメーターに関して

パラメーター 概要
-Xmx Javaヒープの最大サイズを設定。単位はバイ
-Xms Javaヒープの初期サイズを設定。単位はバイ
-XX:MaxPermSize Permヒープの最大サイズを設定。単位はバイ
-XX:PermSize Permヒープの初期サイズを設定。単位はバイ
-Xmn New領域の初期値および最大値を設定。単位はバイ
-Xss 1スタック領域の最大サイズを設定。単位はバイ
-XX:NewRatio New領域に対する Old領域の割合を設定(2を設定した場合は、New領域とOld領域の割合が、1:2になる)
-XX:SurvivorRatio Survivor領域のFromとToに対するEdenの割合を指定(8を設定した場合は、Eden/From/Toの割合が、8:1:1になる)

Javaプロセス番号確認

[user@localhost]$ sudo su - root
[root@localhost]# sudo -u <アプリケーションアカウント> jps -v
20167 Jps 
15149 sample.jar -Xrs -Xms2048m -Xmx2048m ← この先頭の番号がJavaのプロセスID

ガベージコレクション統計データーの表示(-gcutilオプション)

[root@localhost]# sudo -u <アプリケーションアカウント> jstat -gcutil -h20 <JavaプロセスID> 1000
S0       S1      E           O        M          CCS       YGC   YGCT      FGC    FGCT      GCT  
0.00   0.00  80.09   2.36  97.77  95.62     52    10.822    52   19.085   29.907
0.00   0.00  80.09   2.36  97.77  95.62     52    10.822    52   19.085   29.907
0.00   0.00  80.09   2.36  97.77  95.62     52    10.822    52   19.085   29.907
0.00   0.00  80.09   2.36  97.77  95.62     52    10.822    52   19.085   29.907
0.00   0.00  80.09   2.36  97.77  95.62     52    10.822    52   19.085   29.907

列の見方は下記の内容を参考にして見てください。

概要
S0 Survivor 領域 0 の使用率 (現在の容量に対するパーセンテージ)
S1 Survivor 領域 1 の使用率 (現在の容量に対するパーセンテージ)
E Eden 領域の使用率 (現在の容量に対するパーセンテージ)
O Old 領域の使用率 (現在の容量に対するパーセンテージ)
P Permanent 領域の使用率 (現在の容量に対するパーセンテージ)
YGC 若い世代の GC イベント数
YGCT 若い世代のガベージコレクション時間
FGC フル GC イベント数
FGCT フルガベージコレクション時間
GCT ガベージコレクション総時間|

ガベージコレクション統計データーの表示(-gcオプション)

[root@localhost]# sudo -u <アプリケーションアカウント> jstat -gc -h20 <JavaプロセスID> 1000
S0C            S1C             S0U   S1U   EC                EU                 OC                  OU              MC           MU           CCSC      CCSU      YGC   YGCT      FGC   FGCT      GCT  
262144.0 262144.0  0.0    0.0   1572864.0 1262368.5 1048576.0   24778.0   47488.0 46427.5 5760.0 5507.9     52   10.822  52     19.085   29.907
262144.0 262144.0  0.0    0.0   1572864.0 1262368.5 1048576.0   24778.0   47488.0 46427.5 5760.0 5507.9     52   10.822  52     19.085   29.907
262144.0 262144.0  0.0    0.0   1572864.0 1262368.5 1048576.0   24778.0   47488.0 46427.5 5760.0 5507.9     52   10.822  52     19.085   29.907
262144.0 262144.0  0.0    0.0   1572864.0 1262368.5 1048576.0   24778.0   47488.0 46427.5 5760.0 5507.9     52   10.822  52     19.085   29.907
262144.0 262144.0  0.0    0.0   1572864.0 1262368.5 1048576.0   24778.0   47488.0 46427.5 5760.0 5507.9     52   10.822  52     19.085   29.907

列の見方は下記の内容を参考にして見てください。

概要
S0C Survivor 領域 0 の現在の容量 (KB)
S1C Survivor 領域 1 の現在の容量 (KB)
S0U Survivor 領域 0 の使用率 (KB)
S1U Survivor 領域 1 の使用率 (KB)
EC Eden 領域の現在の容量 (KB)
EU Eden 領域の使用率 (KB)
OC Old 領域の現在の容量 (KB)
OU Old 領域の使用率 (KB)
PC Permanent 領域の現在の容量 (KB)
PU Permanent 領域の使用率 (KB)
YGC 若い世代の GC イベント数
YGCT 若い世代のガベージコレクション時間
FGC フル GC イベント数
FGCT フルガベージコレクション時間
GCT ガベージコレクション総時間

モリープール世代及び領域容量の表示(-gccapacityオプション)

[root@localhost]# sudo -u <アプリケーションアカウント> jstat -gccapacity -h20 <JavaプロセスID> 1000
NGCMN         NGCMX         NGC             S0C             S1C            EC                  OGCMN         OGCMX          OGC               OC                 MCMN  MCMX            MC            CCSMN  CCSMX          CCSC     YGC   FGC
2097152.0 2097152.0 2097152.0 262144.0 262144.0 1572864.0  1048576.0  1048576.0  1048576.0  1048576.0       0.0 1091584.0  47488.0  0.0        1048576.0  5760.0    52    52
2097152.0 2097152.0 2097152.0 262144.0 262144.0 1572864.0  1048576.0  1048576.0  1048576.0  1048576.0       0.0 1091584.0  47488.0  0.0        1048576.0   5760.0    52    52
2097152.0 2097152.0 2097152.0 262144.0 262144.0 1572864.0  1048576.0  1048576.0  1048576.0  1048576.0       0.0 1091584.0  47488.0  0.0        1048576.0   5760.0    52    52
2097152.0 2097152.0 2097152.0 262144.0 262144.0 1572864.0  1048576.0  1048576.0  1048576.0  1048576.0       0.0 1091584.0  47488.0  0.0        1048576.0   5760.0    52    52

列の見方は下記の内容を参考にして見てください。

概要
NGCMN New 世代の最小容量 (KB)
NGCMX New 世代の最大容量 (KB)
NGC New 世代の現在の容量 (KB)
S0C Survivor 領域 0 の現在の容量 (KB)
S1C Survivor 領域 1 の現在の容量 (KB)
EC Eden 領域の現在の容量 (KB)
OGCMN Old 世代の最小容量 (KB)
OGCMX Old 世代の最大容量 (KB)
OGC Old 世代の現在の容量 (KB)
OC Old 領域の現在の容量 (KB)
PGCMN Permanent 世代の最小容量 (KB)
PGCMX Permanent 世代の最大容量 (KB)
PGC Permanent 世代の現在の容量 (KB)
PC Permanent 領域の現在の容量 (KB)
YGC 若い世代の GC イベント数
FGC フル GC イベント数

メモリダンプ確認方法

[root@localhost]# sudo -u <アプリケーションアカウント> jmap -dump:format=b,file=heap.bin <JavaプロセスID>
[root@localhost}# jhat heap.bin ← http://<ホスト名>:7000でアクセスできる。

メモリダンプテキスト出力方法

[root@localhost]#  sudo -u <アプリケーションアカウント> jmap -histo:live <JavaプロセスID> > heap01.txt

Cヒープ内容出力方法

[root@localhost]# ps -aux | grep 'java'
root     13386  0.0  0.0 175120  1532 ?        S    Sep21   0:00 sudo -u sample nohup /usr/local/jdk/bin/java
sample    13387  0.2 74.9 5969548 3036976 ?     Sl   Sep21   5:05 /usr/local/jdk/bin/java -Xms3072m -Xmx3072m -Xmn2048m
[root@localhost]# gcore <プロセス番号>
Saved corefile core.13386
[root@localhost]# strings -a core.13386 > core.txt
[root@localhost]# sort core.txt | uniq -c | sort -nr | less > data.txt

Redis Clusterに関して

Redis Clusterを試しに組んでみたので、その簡単な構築方法。

Redisインストール

Redis Clusterの場合6ノード必要(master : 3台/slave : 3台)になります。
また、Masterを3台のみで構成することも可能です。

[user@localhost]$ sudo su - root
[root@localhost]# cd /usr/local/src
[root@localhost]# wget http://download.redis.io/releases/redis-3.2.4.tar.gz
[root@localhost]# tar -zxvf redis-3.2.4.tar.gz
[root@localhost]# mv redis-3.2.4 ../redis
[root@localhost]# cd ../redis
[root@localhost]# make

Redis設定ファイル

[root@localhost]# cd /usr/local
[root@localhost]# mkdir redis_cluster
[root@localhost]# cd redis_cluster
[root@localhost]# cp ../redis/redis.conf .
[root@localhost]# vi redis.conf
daemonize yes
bind 0.0.0.0
port 7000
cluster-enabled yes
cluster-config-file /usr/local/redis_cluster/nodes.conf
cluster-node-timeout 5000
appendonly yes

Redis Server起動

[root@localhost]# cd /usr/local/redis_cluster
[root@localhost]#  /usr/local/redis/src/redis-server ./redis.conf

Redis Clusterの構成はRedis Serverは6ノードでMasterは3ノードでClusterを組みSlaveは3ノードの構成で検証します。

ノード IP ポート 尾行
redis01 172.20.100.10 7000 Master
redis02 172.20.100.11 7001 Master
redis03 172.20.100.12 7002 Master
redis04 172.20.100.13 7003 Slave
redis05 172.20.100.14 7004 Slave
redis06 172.20.100.15 7005 Slave

6台のRedis ServerでClusterを構成

[root@localhost]# /usr/local/redis/src/redis-trib.rb create 172.20.100.10:7000 172.20.100.11:7001 172.20.100.12:7002 172.20.100.13:7003 172.20.100.14:7004 172.20.100.15:7005

Redis Cluster確認

[root@localhost]# /usr/local/redis/src/redis-cli -c -p 7000
127.0.0.1:7000> set foo bar
 -> Redirected to slot [12182] located at 172.20.100.11:7001
 OK
 172.20.100.11:7001> set hello world
 -> Redirected to slot [866] located at 172.20.100.10:7000
 OK
 172.20.100.11:7001> get foo
 "bar"
 172.20.100.11:7001> get hello
 -> Redirected to slot [866] located at 172.20.100.10:7000
 "world"
 172.20.100.10:7000>

Angular2での外部APIの呼び出し方法に関して

Angular2系でのの外部APIの呼び出し方法に関して書きたいと思います。
Angular2系では下記のHTTPクライアントがあるのでそれを利用します。
angular.io
Angular1系ではhttpとresourceの2つのクライアントがありましたが、
Angular2系はこのHTTPクライアントで行います。
これを利用するればJSONマッピングなど比較的に簡単に行うことができます。
簡単な実装方法を下記に書きます。

メッセージ格納クラス

APIからのJSONマッピングするクラスを作成します。
Angular1系の時は単純にそのままJSONを扱ってましたが(クラスぽい定義で扱うこともできる)
Angular2系からJSONマッピングするクラスに値を格納するようにします。
SONをマッピングするクラスはJSONの各要素を格納するエリアの定義及び
コンストラクターで要素の値を受けてエリアに値をセットするようにします。

export class Message {
        messageId : string;
        message : string;
        constructor(
                messageId : string,
                message : string) {
                this.messageId = messageId;
                this.message = message;
        }
}
メッセージサービスクラス作成

APIの呼び出しを行うサービスクラスを作成します。
APIの呼び出しはAngularのHttpとRXJSのObservableを利用します。
非同期通信で利用できるものが2つあります。
1つはObservableです。
もう1つはAngular1系からあるPromiseです。
Promiseは1リクエストの非同期処理を扱うもので
連続リクエストの非同期処理や遅延処理やキャンセルなどはできません。
Angular2からはPromiseではなくObservableを利用します。
Observableは連続リクエストの非同期処理や遅延処理やキャンセルなど
Promiseではできないことも可能になっています。

import { Injectable } from '@angular/core';
import { Headers, Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Message } from './message';
@Injectable()
export class MessageService {
        private messageUrl = '/message_service';
        constructor (private http: Http) {}
        getMessage(): Observable<Message> {
                return this.http.get(this.messageUrl)
                        .map(response => response.json() as Message)
                        .catch(this.handleError);
        }
        private handleError(error: any): Observable<any> {
                console.error('An error occurred', error);
                return Observable.throw(error.message || error);
        }
}
モジュール定義

NgModuleに設定を行います。
AngularのHttpModuleを利用するのでimportsに設定して宣言します。
また作成したMessageServiceをprovidersに設定して、アプリケーションでDIできるようにします。

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpModule, JsonpModule } from '@angular/http';
import { AppComponent } from './app.component';
import { MessageService  } from './message.service';
@NgModule({
        imports: [
                BrowserModule,
                FormsModule,
                HttpModule
        ],
        declarations: [
                AppComponent
        ],
        providers: [
                MessageService
        ],
        bootstrap: [
                AppComponent
        ]
})
export class AppModule { }
コンポーネント設定

コンポーネントコンストラクターにMessageServiceをDIします。
ngOnInit()の中でDIしたMessageServiceを利用してAPIを呼びします。
このngOnInit()は初期値を設定する場合などに利用するもので、
コンポーネントが呼ばれたら自動的にこれが呼ばれるようになっています。
APIの結果はJSONマッピングクラスのMessageに格納されます。
HTMLで{{ message.messageId }}など定義しとけば格納されている値をHTMLで表示できます。

import { Component } from '@angular/core';
import { MessageService  } from './message.service';
import { Message } from './message';
@Component({
        selector: 'my-app',
        template: '<div>{{ message.messageId }} : {{ message.messageName }}</div>'
})
export class AppComponent {
        errorMessage : string;
        message : Message;
        error : any;
        constructor(private messageService : MessageService) { }
        ngOnInit(): void {
                this.messageService
                        .getMessage()
                        .subscribe(
                                message => this.message = message,
                                error =>  this.errorMessage = <any>error);
        }
}

Angular2のQuickStartをやってみた

Angular2のRC5がリリースされました。
そろそろ次ぐらいが安定版のリリースになる気がします。
Angular2からTypeScriptベースに変更されています。
Angular1系と比べかなり変わっているので、移行はかなり厳しそうです。
Angular2のQuickStartをやってみました。
angular.io
それとGulpやWebPackも一緒設定してみました。

基本構成

Angular2の基本的なディレクトリ構成は下記の構成です。

angular2-quickstart
 |-app
 |-gulpfile.js
 |-index.html
 |-package.json
 |-style.css
 |-tsconfig.json
 |-typings.json
 |-webpack.config.js
パッケージ管理の設定

利用するパッケージ管理する為にnode.jsのnpmを利用します。
npmでは利用するパッケージ管理用の設定ファイル(package.json)を作成します。

{
  "name": "angular2-quickstart",
  "version": "1.0.0",
  "scripts": {
    "start": "/usr/local/bin/gulp && /usr/local/bin/gulp connect ",
    "postinstall": "typings install",
    "typings": "typings"
  },
  "license": "MIT",
  "dependencies": {
    "@angular/common": "2.0.0-rc.5",
    "@angular/compiler": "2.0.0-rc.5",
    "@angular/core": "2.0.0-rc.5",
    "@angular/forms": "0.3.0",
    "@angular/http": "2.0.0-rc.5",
    "@angular/platform-browser": "2.0.0-rc.5",
    "@angular/platform-browser-dynamic": "2.0.0-rc.5",
    "@angular/router": "3.0.0-rc.1",
    "@angular/router-deprecated": "2.0.0-rc.2",
    "@angular/upgrade": "2.0.0-rc.5",
    "systemjs": "0.19.27",
    "core-js": "^2.4.0",
    "reflect-metadata": "^0.1.3",
    "rxjs": "5.0.0-beta.6",
    "zone.js": "^0.6.12",
    "angular2-in-memory-web-api": "0.0.15",
    "bootstrap": "^3.3.6"
  },
  "devDependencies": {
    "browser-sync": "^2.14.0",
    "concurrently": "^2.0.0",
    "connect-history-api-fallback": "^1.3.0",
    "gulp": "^3.9.1",
    "gulp-connect": "^5.0.0",
    "gulp-webpack": "^1.5.0",
    "lite-server": "^2.2.0",
    "proxy-middleware": "^0.15.0",
    "ts-loader": "^0.8.2",
    "typescript": "^1.8.10",
    "typings": "^1.0.4",
    "url": "^0.11.0"
  }
}
コンパイル設定

TypeScriptコードはコンパイルが必要です。
そのコンパイル時にコンパイルオプション及びコンパイル対象のTypeScriptコードの指定などの
設定をまとめた設定ファイル(tsconfig.json)を作成します。

{
	"compilerOptions": {
		"target": "es5",
		"module": "commonjs",
		"moduleResolution": "node",
		"sourceMap": true,
		"emitDecoratorMetadata": true,
		"experimentalDecorators": true,
		"removeComments": false,
		"noImplicitAny": false
	}
}
Typingsの設定

TypeScriptには型定義というものがあります。
その型が記述されているものが型定義ファイル(〜.d.ts)です。
一般的な型定義ファイルは下記のGitHubリポジトリにあります。
https://github.com/DefinitelyTyped/DefinitelyTyped
利用する型定義ファイルを管理するものがTypingsです。
Typingsは利用する型定義ファイルをまとめた設定ファイル(typings.json)を作成します。

{
	"globalDependencies": {
		"core-js": "registry:dt/core-js#0.0.0+20160602141332",
		"jasmine": "registry:dt/jasmine#2.2.0+20160621224255",
		"node": "registry:dt/node#6.0.0+20160807145350"
	}
}
WebPackの設定

WebPackとはアプリケーションに必要なJavaScriptCSSなどのリソースの依存関係を解決して
配布できる形にしてくるビルドツールです。
WebPackのビルド定義を行うビルド設定ファイル(webpack.config.js)を作成します。

module.exports = {
	entry : './app/main.ts',
	output : {
		filename : './bundle.js'
	},
	resolve : {
		root : [ './node_modules' ],
		extensions : [ '', '.webpack.js', 'web.js', '.js', '.ts' ]
	},
	module : {
		loaders : [ {
			test : /\.ts$/,
			loader : 'ts-loader'
		} ]
	}
}
Gulpの設定

Gulpとはサーバー設定やProxy設定及びリソースの圧縮などのタスクが定義できます。
Gulpのタスク定義は設定ファイル(gulpfile.js)を作成します。

var gulp = require('gulp');
var connect = require('gulp-connect');
var proxy = require('proxy-middleware');
var url = require('url');
var webpack = require('gulp-webpack');
var webpackConfig = require('./webpack.config.js');
gulp.task('ts', function() {
	return gulp.src([ './*.ts' ])
			.pipe(webpack(webpackConfig))
			.pipe(gulp.dest('./dist'));
});
gulp.task('index', function() {
	return gulp.src([ './index.html' ])
			.pipe(gulp.dest('./dist'));
});
gulp.task('css', function() {
	return gulp.src([ './styles.css' ])
			.pipe(gulp.dest('./dist'));
});
gulp.task('connect', function() {
  connect.server({
    root: ['dist'],
    port: 9000,
    livereload: true,
    middleware: function(connect, o) {
        return [ (function() {
            var options = url.parse('http://localhost:8080/service');
            options.route = '/service';
            return proxy(options);
        })() ];
    }
  });
});
gulp.task('default', [ 'ts', 'index', 'css']);
コンポーネント作成

Angular2はコンポーネント指向のJSフレームワークです。
そのコンポーネントは定義方法は下記のコードになります。

import {Component} from '@angular/core';
@Component({
	selector: 'my-app',
	template: '<h1>My First Angular 2 App</h1>'
})
export class AppComponent { }
モジュール定義作成

NgModuleは、コンポーネント、ディレクティブ、パイプ、サービスなどを一箇所にまとめて定義
してモジュールを宣言するものです。
基本的にこのモジュール宣言をアプリケーションには1つ定義する必要がありますが、
現状、宣言しなくとも書き方によってはアプリケーションは動きます。

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpModule, JsonpModule } from '@angular/http';
import { AppComponent } from './app.component';
@NgModule({
	imports: [
		BrowserModule,
		FormsModule,
		HttpModule,
		JsonpModule
	],
	declarations: [
		AppComponent
	],
	bootstrap: [
		AppComponent
	]
})
export class AppModule { }
エントリーポイント作成

アプリケーションを起動する為のエントリーポイントを作成する必要があります。

import "core-js";
import "rxjs/Rx";
import "zone.js/dist/zone";

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
index.html作成

最後にindex.htmlを作成します。

<html>
<head>
<title>angular2-quickstart</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
</head>
<body>
	<my-app>Loading...</my-app>
</body>
<script src="./bundle.js"></script>
</html>
起動方法
cd angular2-quickstart
npm install
npm start

第9回Jenkins勉強会に参戦

第9回Jenkins勉強会に参戦してきました。
jenkins.connpass.com

超簡単Pipeline講座
  • Jenkinsのパイプラインの概説
  • Jenkins1の時はbuild PipelineでGUIベースで定義することができた
  • GUIベースの定義はからり面倒で大変
  • Pipeline PluginはGroovyでコードベースで定義できる
  • 可視化の部分は有償だったがOSS化された
  • Jenkins2のPipelineはPipeline PluginでのGroovyのコードベースで定義していく

www.slideshare.net

実録!となりのJenkins2.0」
  • Jenkins1及びプラグインインストール
  • Jenkins1 Build PipelineでのGUIでJobのワークフローを作れる
  • デプロイなどの独自スクリプトはシェルなどで記述する
  • Jenkins1からJenkins2へのアップグレードは簡単
  • Jenkins1で利用したジョブやPipelineもそのまま引き継がれる
  • 後方互換性がかなりしっかりしている
  • GroovyでJobを繋ぎを記述できる
  • デプロイなどの独自スクリプトはGroovyで書ける
  • ソースのテンプレート機能もある
  • Groovyのコードをビジアル表示してくれる
  • ジョブ設定やGroovyのソースはjenkinsfileにもできる(GitHubで管理可能になったので移行が楽)
  • Clover等などの今まで利用したPluginはJenkins2 Pipelineスクリプトに対応しているなら使える

www.slideshare.net

「Jenkins 2を使った究極のpipeline ~ 明日もう一度来てください、本物のpipelineをお見せしますよ ~」
  • Job設定がコード化されて変更が楽になった。
  • Jenkins1 build PipelineよりJenkins2 Pipelineの方がビジュアル的に見やすくなっている。
  • Multi-Branch Pluginでプルリクがわかりやすくなった
  • Multi-Branch Pluginは自動でブランチに対応したジョブを作成してくれる
  • Multi-Branch Pluginはブランチを削除すると自動でジョブが消える
  • GitHub Organization Folder Pluginはプルリクのジョブも自動作成してくれる

www.slideshare.net