スクラム開発に関して
アジャイルとは?
アジャイルとは価値があるものを生み出すために
より良い開発方法を見つけ出そうとしている状態
それ以外の時はアジャイルではない。
スクラムだろうがXPだろうが
より良い開発方法を見つけ出そうとしている時は
アジャイルであり、それ以外はアジャイルではない
アジャイルソフトウェア開発宣言
アジャイル宣言の背後にある原則
スクラムとは?
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
- 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)の見積方法
プロダクトバックログのアイテムの投資利益率の見積の方法は、プランニングポーカーでやることが多いです。
まず作業量の見積時に決めた基準となるアイテムに対して価値をポイントとしてつけます。
残りのアイテムはその基準ポイントからみて大きいか小さいかでプランニングポーカーでポイントをつけます。
投資利益率は価値ポイントを作業量のポイントで割ると算出されます。
この投資利益率を参考に優先順位をつけます。
見通しを立てる
プロダクトバックログを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というコマンドラインベースで操作されます。
簡単な説明は終わりにして、
今回は、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スレッドが格納される領域になります。
各領域に関して
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とはアプリケーションに必要なJavaScriptやCSSなどのリソースの依存関係を解決して
配布できる形にしてくるビルドツールです。
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