Github Pages + Jekyll でハマったこと
はじまりは Processing の成果物を蓄積する場所としてのシンプルな Github Pages を想定していたが、 Github Pages が Jekyll を推奨していたこともあり、久々に触ってみることにした。
そうしたら思いの外ハマってしまったので、そのログを残しておく。
問題1: _layouts が見つからない
概要
いつもの調子で下記のように打ってみたのだが、
bundle install --path=vendor/bundle --jobs=4 bundle exec jekyll new .
下記のようなエラーが出てビルドできない。
$ bundle exec jekyll build Configuration file: /Users/tomohiro.zoda/git/github.com/zdogma/zdogma.github.io/_config.yml Source: /Users/tomohiro.zoda/git/github.com/zdogma/zdogma.github.io Destination: /Users/tomohiro.zoda/git/github.com/zdogma/zdogma.github.io/_site Incremental build: disabled. Enable with --incremental Generating... Build Warning: Layout 'post' requested in _posts/2016-08-07-welcome-to-jekyll.markdown does not exist. Liquid Exception: The included file '/Users/tomohiro.zoda/git/github.com/zdogma/zdogma.github.io/_includes/icon-github.html' should exist and should not be a symlink in about.md
jekyll new した時に作られるべき _layouts
が存在しない...?
前に jekyll 使った時はこんなところでハマらなかったような...泣
解決方法
Github Pages 側の公式ドキュメントに導入方法があったので読んでみる。(最初から読んでおけという話)
Setting up your GitHub Pages site locally with Jekyll - User Documentation
bundle exec jekyll new . --force New jekyll site installed in /Users/octocat/my-site.
force オプションが必要だったらしい。
すでに存在するディレクトリに jekyll の初期設定を展開する時には必須なのだそうだ。
If the existing directory isn’t empty, you’ll also have to pass the --force option like so jekyll new . --force.
問題2: Invalid date でフォーマットエラー
概要
またもビルドで落ちる。
$ bundle exec jekyll serve Configuration file: /Users/tomohiro.zoda/git/github.com/zdogma/zdogma.github.io/_config.yml Source: /Users/tomohiro.zoda/git/github.com/zdogma/zdogma.github.io Destination: /Users/tomohiro.zoda/git/github.com/zdogma/zdogma.github.io/_site Incremental build: disabled. Enable with --incremental Generating... ERROR: YOUR SITE COULD NOT BE BUILT: ------------------------------------ Invalid date '<%= Time.now.strftime('%Y-%m-%d %H:%M:%S %z') %>': Document 'vendor/bundle/ruby/2.3.0/gems/jekyll-3.1.6/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb' does not have a valid date in the YAML front matter.
なにか余計なものを見に行って落ちているようで、これはすぐに解決策が浮かんだ。
解決方法
_config.yml
に下記を追記する。
exclude: [vendor]
vendor/bundle 以下に gem を入れている場合、ビルド時にそこを読まないように除外してやる必要がある。 除外含めた _config.yml の書き方は下記に詳しい。
Exclude Exclude directories and/or files from the conversion. These exclusions are relative to the site's source directory and cannot be outside the source directory.
ビルド成功
なんとか上記を踏まえて、ビルドできるようになった。
$ bundle exec jekyll serve --watch Configuration file: /Users/tomohiro.zoda/git/github.com/zdogma/zdogma.github.io/_config.yml Source: /Users/tomohiro.zoda/git/github.com/zdogma/zdogma.github.io Destination: /Users/tomohiro.zoda/git/github.com/zdogma/zdogma.github.io/_site Incremental build: disabled. Enable with --incremental Generating... done in 0.273 seconds. Auto-regeneration: enabled for '/Users/tomohiro.zoda/git/github.com/zdogma/zdogma.github.io' Configuration file: /Users/tomohiro.zoda/git/github.com/zdogma/zdogma.github.io/_config.yml Server address: http://127.0.0.1:4000/ Server running... press ctrl-c to stop.
これでこちらの Github Pages も使えるようになったが、こちらでも記事を書くとこのはてなダイアリーと重複するため、 基本的に Github Pages は Processing など動くものを載せるところにしようと思う。
Kindle の Highlight を Evernote に同期するスクリプトを書いた
ことはじめ
Kindle の Highlight 機能、便利ですよね!
特にビジネス書や小説などで、後で振り返りたい内容・表現に対してラインマーカーの如く Highlight を残している方も多いと思います。
かくいう私自身も Highlight をたくさん残しているのですが、せっかく残したものの「これ、いつ見返せばよいのだろう...」という根本的な疑問がありました。
これまで読んだ本の中には積極的に読み返したい本もあればそうでない本もあるわけで、アプリでいちいち Highlight を確認するのは辛いし、 一応 Web にも自分の Highlight をまとめてくれている場所はあるのですが、毎回アクセスするには認証もあったりで大変です。
https://kindle.amazon.co.jp/your_highlights
ということで、「自分の Kindle の Highlight を Evernote にバッチで保存するようなスクリプトを書けばいいじゃん!」ということで、書きました。
実行すると、Evernote にこんな感じのノートブックが作られます。
(タイトルの先頭の★は、その本の中での Highlight 箇所の数です)
これで電車の中でも Highlight を読み返しやすいですね!
本題
使い方
1.README の Install を読み、必要なミドルウェアをインストールします。
需要がどれくらいあるかわからなかったので、 Web アプリケーションにはしていません。
Ruby で書いたスクリプトをそのまま叩く(バッチの場合は cron などはお任せ)という不親切仕様ですがご勘弁を...。
2.env ファイルを用意します。
env ファイルとは、環境変数を定義するための設定ファイルで、 dotenv という gem を使って読み込みを行っています。
今回動かすスクリプトで必要な設定は下記3つです。
# kindle で登録している amazon アカウントのメールアドレス AMAZON_MAIL_ADDRESS=xxx@xxx.xxx # kindle で登録している amazon アカウントのパスワード AMAZON_PASSWORD=xxxxxxx # Evernote のデベロッパートークン EVERNOTE_DEVELOPER_TOKEN=xxxxxxxxxxxxxxx
上2つの amazon 系は特に説明は不要かと思いますが、いちばん下の Evernote の developer token に関しては、下記の URL にアクセスして取得してください。
https://www.evernote.com/api/DeveloperToken.action
これらを .env というファイルに書き込んで、下記の階層に置いてください。 下記のようになっていたら OK です!
$ tree -a . ├── .bundle │ └── config ├── .git │ ├─ /* 省略 */ ├── lib │ ├── evernote.rb │ └── kindle.rb ├── log │ └── .gitkeep ├── .env ├── .gitignore ├── Gemfile ├── Gemfile.lock ├── README.md └── kindle_evernote.rb
3.Evernote 側で受け口となるノートブックを作成します。
KindleHighlights
というノートブックを Evernote 側で作成してください。
ちなみにノートブック名はスクリプトの中で決めうちで指定していますので、変えていただいても OK です。
(ノートブック作成部分もコードで書いとけよというツッコミは受け付けません←)
4.ruby のスクリプトを叩きます。
README の Usage にある通りです。
bundle exec ruby kindle_evernote.rb
log/ 以下に進捗含めたログを吐くようにしているので、下記のような感じで別のウインドウで確認しながらやっていただくと捗るかもしれません。
less +F log/xxxxxxxx
解説
Kindle の情報を取得する部分
下記のサイト様の情報を参考にさせていただきました。
基本的に処理の流れは同じで、違いといえば追加で「Highlight の(本の中での)場所」も取得していることくらいです。
あと、タイトルなどでノイズが紛れ込んでいた場合に除く処理もちょこっと足しています。
qiita.com
ただ、やはりスクレイピングということで、HTML の構造が変わると取得できなくなるなどの脆弱さを孕んでいるので、しれっと動かなくなったらすみません。
def highlights_for(asin) sleep 0.3 page = @mechanize_agent.get("https://kindle.amazon.co.jp/your_highlights_and_notes/#{asin}") highlights = page.xpath('//div[@class="highlightRow yourHighlight"]').map do |e| { text: e.xpath('span[@class="highlight"]')&.inner_text || '', location_href: e.css('a')&.attribute('href')&.value || '' } end { title: page.search('span.title').text.gsub(/\(Japanese Edition\)|\n.*\z/, ''), author: page.search('span.author').text.gsub(/\A by /, '').strip, highlights: highlights } end
Evernote でノートを作成する部分
こちらは本家のドキュメントに則って書きました。
機能要件として、スクリプトを打つたびに新しくノートが作られるのは嫌だったので、
すでにノートが存在すれば update、まだノートが無ければ create という形で処理を分けています。
ノートの存在確認のために一度 findNotes をするのですが、その時に一意に検索できるように ASIN をキーワードにしています。
コードとしてはこのあたりです。
kindle-highlights/evernote.rb at master · zdogma/kindle-highlights · GitHub
おわりに
ざーっと書いたため、いろいろ不親切な部分があると思いますが、もしよかったら使ってみてください!
ドキュメントの不備などあればコメントいただけると助かりますー!
ではでは!
1からNまでの素数の数を数える標準ライブラリ Prime を読んでみる
ことはじめ
とある機会に「1からNまでの素数の数を数えよ」という問題を解こうとした時に、最初に下記のように書いた。
(2..number).each_with_object([]) { |num, primes| sqrt_primes = primes.select { |prime| prime < Math.sqrt(number) } primes << num if sqrt_primes.none? { |prime| num % prime == 0 } }.count
ベンチマークを取れば歴然だが、下記のように N が大きくなると処理時間が大きくなる。 結果、テストケースを所定の時間内にクリアできないという状態に。。。
user system total real number = 10 0.000000 0.000000 0.000000 ( 0.000045) number = 100 0.000000 0.000000 0.000000 ( 0.000342) number = 1000 0.010000 0.000000 0.010000 ( 0.012887) number = 10000 0.660000 0.000000 0.660000 ( 0.671416)
ぱっとチューニングのアイデアが思い浮かばなかったので、素数判定のロジックを調べていると、どうやら標準ライブラリに Prime というものがあるらしい。 下記のようなコードを書いてベンチマークを取ってみると...
require 'prime' numbers.each { |number| Prime.each(number).count }
user system total real number = 10 0.000000 0.000000 0.000000 ( 0.003707) number = 100 0.000000 0.000000 0.000000 ( 0.003185) number = 1000 0.010000 0.000000 0.010000 ( 0.002970) number = 10000 0.000000 0.000000 0.000000 ( 0.002980)
こちらだと余裕でテストケースをクリア。 なんとも悔しい気持ちになったので、Prime の実装を読んでみることにした。
本題
Prime の実装は下記にある。
ruby/prime.rb at trunk · ruby/ruby · GitHub
Prime では、下記のように each の引数に与えた数字までの素数を返す。
[56] pry(main)> Prime.each(100).to_a => [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97] [57] pry(main)> Prime.each(100).class => Prime::EratosthenesGenerator
素数の判別方法にはいろいろなやり方があるが、Prime でデフォルトで採用されているのは「エラトステネスの篩(ふるい)」と呼ばれているアルゴリズムである。 wikipedia によると、下記のように実装されるらしい。
- ステップ 1
- 探索リストに2からxまでの整数を昇順で入れる。
- ステップ 2
- 探索リストの先頭の数を素数リストに移動し、その倍数を探索リストから篩い落とす。
- ステップ 3
- 上記の篩い落とし操作を探索リストの先頭値がxの平方根に達するまで行う。
- ステップ 4
- 探索リストに残った数を素数リストに移動して処理終了。
詳細な説明は省くが、実際に該当のアルゴリズムを実装しているのは下記の部分。
def compute_primes # max_segment_size must be an even number max_segment_size = 1e6.to_i max_cached_prime = @primes.last # do not double count primes if #compute_primes is interrupted # by Timeout.timeout @max_checked = max_cached_prime + 1 if max_cached_prime > @max_checked segment_min = @max_checked segment_max = [segment_min + max_segment_size, max_cached_prime * 2].min root = Integer(Math.sqrt(segment_max).floor) segment = ((segment_min + 1) .. segment_max).step(2).to_a (1..Float::INFINITY).each do |sieving| prime = @primes[sieving] break if prime > root composite_index = (-(segment_min + 1 + prime) / 2) % prime while composite_index < segment.size do segment[composite_index] = nil composite_index += prime end end @primes.concat(segment.compact!) @max_checked = segment_max end
おわりに
最近競技プログラミングの勉強を始めているが、やはり数学への理解がかなり重要で、直感で消費メモリ・処理時間がイメージできるまで頭を慣らしたい。
今回はとりあえずアルゴリズムの内容がわかったので、次回、自分のアルゴリズムとの差分と処理時間の差が生まれた要因をもう少し突き詰めてみようと思う。
ruby で継承と委譲の使い分けを考える
ことはじめ
継承と委譲に関して、それぞれなんとなく理解はしているものの、どう使い分けるのがよいのか、イマイチ実感が湧いていなかったので、整理がてらブログに書いてみます。
それぞれの定義
継承
既存の親クラスの構造(属性や振る舞い含む)をまるごと受け継ぎ、新しいクラスとして再定義する。
委譲
特定の振る舞いを別のクラスのメソッドに委ねる。
具体例で考える
継承、委譲の使い分けを、具体例を使いながら検討していきます。 ここでは、下記のようなエンジニアマネージャのクラスを考えます。
class EngineerManager def initialize end # エンジニアに共通する振る舞い def code end def debug end def test end # マネージャに共通する振る舞い(ただし assign は許可しない) def coach end def motivate end # 社員に共通する振る舞い def eat(type = 'lunch') end def attend(meeting_type) end end
ここで想定するエンジニアマネージャは、下記のようなロールだとします。
- エンジニアとしての振る舞いをする
- マネージャとしての振る舞いをする
※ただし、他のマネージャ職のメンバーとは異なり、アサイン組み替えの権限はない - 社員としての振る舞いをする
基本的な方針としては、下記の記事にもあるように、「is-a」の関係が綺麗に成り立つ場合は継承を使うのが良いと僕も思います。
継承は安易に用いると容易に複雑化し、バグの温床になりえるものの、その系において "よく" 抽象化された親クラスのもとで継承関係を作ることができれば、とても強力に機能すると思います。
例えば今回の例だと、エンジニアマネージャは社員の部分集合であるため、継承を用いてよいケースだと考えます。 社員に対して認められる振る舞いや属性は、漏れなくエンジニアマネージャも備えるべきです。
逆にエンジニアやマネージャに対してはそうではなく、それぞれの一部の振る舞いがエンジニアマネージャにも備わっているという状態であるため、まるごと受け継ぐ継承は不向きです。 エンジニアマネージャは "(エンジニアやマネージャが担う振る舞いのうち)どの振る舞いができるか" にのみ焦点を当て、その処理の具体的な内容は関知しない、という状態にします。
上記の思想のもと、下記のように実装してみました。
class EngineerManager < Worker extend Forwardable def_delegators :@engineer, *%i( code debug test ) def_delegators :@manager, *%i( coach motivate ) def initialize(name) @engineer = Engineer.new # Engineer.find(name: name) @manager = Manager.new # Manager.find(name: name) end end class Worker def initialize end def eat(type = 'lunch') puts "#{type} を食べました" end def attend(meeting_type) puts "#{meeting_type} に出席しました" end end class Engineer def initialize end def code puts 'code を書きました' end def debug puts 'debug をしました' end def test puts 'test をしました' end end class Manager def initialize end def coach puts 'コーチングしました' end def motivate puts 'モチベートしました' end def assign puts 'アサイン組み換えしました' end end
bob = EngineerManager.new('Bob') puts bob.code # => code を書きました puts bob.attend('朝会') # => 朝会 に出席しました puts bob.coach # => コーチングしました puts bob.assign # => undefined method `assign' for #<EngineerManager:0x007fe6ec8e3a70>
おわりに
なんとなく具体例を考えてみると思考が整理された気がします。
まだまだ思考実験の域を出ていないので、ツッコミなどありましたらぜひお願いします!
参考サイト
gsub! sub! でパターンにマッチしなかった場合 nil が返る
ことはじめ
AtomPub で引っ張ってきたブログテキストに手を加えて別のアプリケーションで表示させようとしていた時に、表題の件でややハマりました。
ハマり時間は数分だったものの、割と想定外な内容だったので備忘も兼ねてメモしておきます。
本題
パターンにヒットする場合
[1] pry(main)> "abc".gsub(/a/, "") "bc" [2] pry(main)> "abc".gsub!(/a/, "") "bc"
いずれもレシーバ自身に対して置換を行った処理後の文字列を返しています。
これは想定通り。
パターンにヒットしない場合
[3] pry(main)> "abc".gsub(/d/, "") "abc" [4] pry(main)> "abc".gsub!(/d/, "") nil
gsub!
もレシーバ自身を返してくれるかと思いきや、ここは nil が返ります。
AtomPub から返却されるのが本文全体の String なので、特定のタグがあったら変換、などをしていたのですが、
たまたまそのタグが使われていない記事があって、すっからかんになってしまい、焦りました。
おわりに
ドキュメントを読めば書いてあるので、ちゃんと読んどけよ、という話ではあるのですが、
他の select, select! とかの関係性からの推測で判断すると結構ハマるような...。
組み込みの関数とかで勘違いして前提を見誤ると、テストの漏れ等にもつながってしまうので、
ちゃんとドキュメントを読んでコードを書きましょう、ということですね。
参考ドキュメント
画像形式 [ JPEG, PNG, GIF, BMP, WebP ] について調べてみた
ことはじめ
サイト高速化のための手段をいろいろと考えていたのですが、 今自分が関わっているサイトだと、画像をいっぱい使っているということもあり、画像圧縮が一つの選択肢になりそうでした。
とはいえ画像の種類もそんなに知らないし特徴の理解も怪しいので、まずは基本的な画像形式について調べてみよう、というのがこの記事の趣旨です。
意外と画像形式を横並びに見る機会って少ない気がするので、よかったら見てみてください。
目次
各形式の紹介
JPEG
名称
拡張子
.jpg/.jpeg
特徴
- 圧縮画像(不可逆)のため、画質が劣化する
- 画像を8×8ピクセルの正方形ブロックに分割して画像の変化の情報を抽出して、その一部を捨てている
- http://funini.com/kei/math/jpeg.shtml
比較的データが軽い
1677万色対応
- 圧縮方法の観点から、色種類の多い画像に適している
- デジカメの写真のほとんどはこのファイル形式
PNG
名称
拡張子
.png
特徴
- 圧縮画像(可逆)のため、画質が劣化しない
- 1677万色対応
- 比較的データ容量が大きい
GIF
名称
- GIF(ジフ)
- Graphics Interchange Format
- 以前 Unisys 社が特許を持っていたことにより、ライセンス権などの特許問題があったが、現在では特許の有効期限は切れている
- Graphics Interchange Format
拡張子
.gif
特徴
- アニメーションを設定できる
- 圧縮画像(不可逆)のため、画質が劣化する
- 256色対応
- 写真には不向きで、ロゴマークやイラストのように境界がはっきりとしている画像に適する
BMP
名称
- BMP(ビットマップ)
- ピクセルを用いた画像表現広汎を指す
- より狭義な技術用語としては、「ビットマップ」の用法をモノクロ2値画像に限定し、カラーやグレースケール階調画像を含める場合はピクセルマップ、ピクスマップ(pixmap)と呼ぶこともある。
拡張子
.bmp
特徴
- 非圧縮画像のため、画質が劣化しない
- RLE(Run Length Encoding)
- データが重い
- 古典的かつ単純なデータ圧縮を用いているため、圧縮率はそれほど期待できない
- 1677万色対応で高画質
- Windows標準の画像形式
WebP
名称
- WebP(ウェッピー)
- 米Googleが開発しているオープンな静止画フォーマット
- GooglePlay の画像とか
- 詳しくは下記
拡張子
.webp
特徴
- 独自の圧縮技術
- 一通りの基本機能を持つ
- 未対応のブラウザ多し
おわりに
圧縮方法の可逆/非可逆の違いくらいは知っていましたが、その方法により向き不向きな画像があるとか、カバーしている色の数が違うなどは初耳で新鮮でした。
上記は本当に基本的なもの+αですが、他にも JPEGmini など新しいフォーマットも普及しつつあるらしいので、また別の機会で整理してみたいと思います。
参考サイト
- 画像拡張子一覧!軽いファイルや画質の違いは?PNG・JPG・BMPなど | サラリーマンの副業はインターネットビジネスのアフィリエイト@アフィ活のすすめ
- WEB画像について−GIF・JPEG・PNGの特徴
- 最適な画像の書き出しは、JPG, GIF, PNG、どれを使うべきか (その画像形式でいいですか?)|Web Design KOJIKA17
- WebP – Webを速くするためにGoogleがやっていること Make the Web Faster 01 – | HTML5Experts.jp
追記 2015/07/09
拡張フォーマットとかで、可逆圧縮の JPEG とかもあったりするらしいです。
あとは PNG をあえて非可逆圧縮したりとか...いろいろあるんですね。
スクラム実践入門 を読んでみた
ことはじめ
今自分が所属している開発チームでは、発足当初から「スクラム」に則った開発を進めています。
当初は極めて少人数のチームだったこともあり、導入後も特に困難なく開発を続けていたのですが、チームの規模や事業の状況が変わるにつれて、だんだんとうまくいかないケースが増えてきました。
そんなこんなで悶々としていたところ、下記の書籍を会社の先輩に紹介してもらいました。
スクラム実践入門 ── 成果を生み出すアジャイルな開発プロセス (WEB+DB PRESS plus)
- 作者: 貝瀬岳志,原田勝信,和島史典,栗林健太郎,柴田博志,家永英治
- 出版社/メーカー: 技術評論社
- 発売日: 2015/03/18
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (3件) を見る
読んでみると、目からウロコな情報が詰まっていて、正直感動しました。
特に自分のような「スクラムやってるけど、ちゃんと体系立てては知らない」「他のチームだとどのように取り組んでいるのか知りたい」という方にはとてもオススメです。
今回は、その中でも自分的に「へぇ〜」と思った箇所について、ネタバレにならない程度に簡単に紹介します。
なぜ「スクラム」と呼ばれるの?
そもそもスクラムとは、「スクラムガイド」と呼ばれるドキュメントにより下記のように定義された、ソフトウェアの開発プロセスを指します。
スクラム(名詞):複雑で変化の激しい問題に対応するためのフレームワークであり、可能な限り 価値の高いプロダクトを生産的かつ創造的に届けるためのものである。
出典: スクラムガイド
http://www.scrumguides.org/docs/scrumguide/v1/Scrum-Guide-JA.pdf
スクラムとは読んで字の如く、ラグビーのスクラムのことですが、なぜそのような名前になったのでしょうか?
現在スクラムと呼ばれているその開発手法は、1986年に「ハーバード・ビジネス・レビュー」誌に寄せられた竹内・野中論文に由来しており、その論文の中では、新製品開発の方法は大きく下記2つに分類されていました。
スピードと柔軟性を求められる現代の新製品開発の現場では、従来のリレー競走型の開発プロセスよりも、ラグビー型のアプローチを採用すべきだ、という趣旨で、ホンダの製品開発スタイルがベストな事例として紹介されているとか。
興味ある方は下記のWebサイトで原文が読めるそうなので、ぜひどうぞ。
なぜ作業を「時間」で区切るの?
いわゆるウォーターフォール型の開発だと、「Aという機能を◯月△日までに作る」など、成果物ベースでスケジュールを立てるのが基本だと思いますが、スクラムだと Sprint という期間、つまり時間で区切ります。
これはなぜなのでしょう?
スクラムによる問題解決の思想の原点は「経験主義」にあります。
スクラムは、経験的プロセス制御の理論(経験主義)を基本にしている。経験主義とは、実際の経験と既知に基づく判断によって知識が獲得できるというものである。スクラムでは、反復的かつ漸進的な手法を用いて、予測可能性の最適化とリスクの管理を行う。
出典: スクラムガイド
http://www.scrumguides.org/docs/scrumguide/v1/Scrum-Guide-JA.pdf
スクラムでは、解決すべき複雑で変化の激しい問題に関して、事前に万全な計画を立てて取り組もうとはしません。
時間によって作業を区切り、時に方向を修正しながら少しずつ成果物を積み上げ、最終的な成果物に近づけていく、というアプローチを取ります。
それがスクラムガイドにある「反復的かつ漸進的な手法」ということなのですね。
スクラムのキーワード
本書の中で紹介されているスクラム系のキーワードを並べてみました。
興味あるものについては本書を手に取って確認してみてください。
ロール
- プロダクトオーナー
- 開発チーム
- スクラムマスター
成果物
イベント
- スプリントプランニング
- リファインメント
- デイリースクラム
- スプリントレビュー
- スプリントレトロスペクティブ
プラクティス
おわりに
スクラムという手法が広く取り入れられるようになってからしばらく経ち、導入している企業も増えていると思います。
ただ、スクラムを実際に取り入れてみるとしみじみと感じるのですが、スクラム自体はとてもよくできた手法ではあるものの、どんなチームにも紋切り型で当てはめるだけでベストな成果が出る魔法のような手法というわけではなく、それをきちんとワークさせるためには、しっかりと各 Sprint を振り返り、改善を重ねていく根気と実行力が必要です。
そんな時にとても助けになるのは、実際にチームに適用したときの経験談や対処法だったりして、そのあたりもこちらの本にしっかりまとまっています。
どんなチームでも悩みどころはだいたい似通っているようで、結構ドンピシャな内容が載ってたりしますので、ぜひご一読をおすすめします。