woshidan's loose leaf

ぼんやり勉強しています

ユーザーストーリーマッピング 13章から18章を読んで

上記の本を読んでいて、13章から18章まで各章ごとに印象に残ったことをメモりました。

13章 オポチュニティから始める

  • 浮かんだばかりの大きなアイデアはエピックと呼んだりオポチュニティ(作者はこちら)と呼んだりする
  • オポチュニティはすべて構築するのではなく、詳細に検討して先へ進むかボツにするか再考するか決める
    • その手法として、オポチュニティキャンバスがある
  • やるべきことがロードマップに載っているものでも誰のために何をなぜ作るのかについて会話を行おう
  • ストーリーマッピングでジャーニーマップを作ってホットスポットからオポチュニティを探す
    • ジャーニーマップに暗黙の前提がないか暴き出す手法としてリハーサル・リ・マッピングがある
  • オポチュニティはすべて受け入れたとしてもダメ

14章 ディスカバリーを介して共通理解を築く

  • ディスカバリーは構築ではなく学習のための仕事でオポチュニティに対し、問題の形、価値、利用可能性、実現可能性を問うて答えていくプロセス
    • 議論する製品や機能の細部はすべて小さなストーリーのタイトルになる
  • ディスカバリーの4つの基本的なスタイル
    • イデアの枠組みを作る
    • 顧客とユーザーを理解する ... 工程としてシンプルなペルソナを共同で作ったりする
    • ソリューションのイメージを描く
      • ソリューションをマッピングする
      • ソリューションのUIを言葉と絵にして共通理解を築く
      • チーム全体でユーザーエクスペリエンスのイメージを思い描くためのアプローチとしてデザインスタジオというものがある
      • 完全性をチェックする
      • 技術的な課題をチェックする
      • 「どうなるゲーム」をする
    • 最小化とプランニング
      • 捨てたアイデアの方が多いくらいでなければディスカバリの仕事を正しくできていない
      • ビジネス戦略を用いて、ターゲットユーザーと顧客を選び、彼らの目標とアクティビティと用いて機能を選ぶ

15章 ディスカバリーによる検証された学習

  • 私たちはほとんどの機能追加の際、成果を出せないリリースをしてしまう
    • それなのに、昔は素晴らしいアイデアだと肉づけることや素晴らしいリリースだったことに見せかけることに手間をかけていた
  • デザイン思考を使おう
    • 「その製品のユーザーになると、実際どう感じるものなのか」を理解するため、課題についてユーザー、顧客と「共感」しよう
    • 共感フェーズで学んだことからこれから重点的に取り組む「特定の人々」および「特定の問題」を「定義」しよう
    • 定義フェーズで定義した問題に対するソリューションの「アイデア」を意図的に複数「創出」しよう
    • シンプルな「プロトタイプ」を作ってソリューションを研究し、顧客とユーザー自身が評価できるくらいまでプロトタイプを改良しよう
    • ユーザー、顧客の問題が本当に解決できるソリューションかどうかを「テスト」しよう
      • 動くように見せかけるフェイクを使っても問題解決に役立つかのテストに使える
  • デザイン思考はビジネスニーズとターゲットとする人々をはっきりさせなかったり、調査と理解のために時間をかけすぎたりすることで簡単に失敗するプロセスになる
  • リーンスタートアップ思考では、製品全体のプランを立てるのではなく最も小さいプロトタイプを作るように努力する
  • ディスカバリーの段階では構築段階とストーリーの使い方に大きな違いがある
    • 構築段階: 共通理解をきちんと構築する。ソフトウェアの構築のために細部に入り込み二週間程度のタイムスパンで開発期間を十分正確に見積もれるようにする。
    • ディスカバリー(&検証された学習)段階: シンプルなプロトタイプをサッと作れるように小さい部品を数日から数時間で素早く作ろうとしている。ほとんどのアイデアは失敗する。

16章 リファイン、定義、構築

  • カード - 会話 - 確認の3つのCのうち、最後のCに到達するために最後の最良の会話(ストーリーワークショップ)を行う
  • ストーリーワークショップに参加すべきなのは通常は以下の3~5人
    • 開発者
    • テスター
    • ユーザー
    • UIデザイナーやビジネスアナリスト
  • 会話に参加するかどうか、チームメンバーにオプトインを認めよう
  • ストーリーワークショップは具体的に何を作るのかという質問に答えることに集中する
    • その中で分割とスリム化を行うが、ストーリーの分割方法としてグッド・ベター・ベストゲームという手法がある
  • デリバリーの状況を確認するためにストーリーマップを活用する
    • マッピングされたバックログのストーリーをタグをつけて進行状況を示す
    • 議論している機能を使ってユーザーが実行する3つか4つのステップだけをマッピングする(シンプルなマップを使う)

17章 ストーリーは実際にはアステロイドに似ている

  • ストーリーは少しずつ、タイミングよく分解していかなければならない
    • オポチュニティでは、ストーリーが誰のためのもので、彼らが解決したい問題は何か、その仕事が会社の事業戦略に沿ったものか、といった方向性の議論が中心で、それでも膨れ上がったオポチュニティを分解することはある
    • ディスカバリーでは、誰がどのようにしてプロダクトを使うのかの具体的な内容を議論するため、何度も分解を行う
    • 開発戦略のプランニングでは、リスクがどこにあるかを議論する。学習を念頭において岩を砕く
    • 次の開発サイクルのプランニングでは、完成したことを確認する方法について意見を一致させる。一つのストーリーが一つの合意を満たすようにするために、ストーリーをさらに分割することになる場合がある
  • バックログをクリーンにするため、小さなストーリーを一つにまとめる
  • 機能についてのストーリーを語るために必要なだけマッピングをする

18章 構築するすべてのものから学ぶ

  • チームプロダクトレビューおよびリフレクション ... 開発チーム内でイメージしたものを望む品質レベルで計画した通りの期間内に構築できたか評価する
  • ステークホルダープロダクトレビュー ... 社内の興味を持った人々を呼んでチームとして行った議論、二者択一について理解してもらう
  • ステークホルダー、顧客、ユーザーには異なる「十分」の基準がある。それが満たされた時、その相手とソフトウェアのレビューを行おう
  • ユーザーにショーアンドテルをするのではなくテストをしてもらう
  • 新機能にユーザー観察の時間や利用状況を追跡できるようなメトリクスを仕込もう
  • リリース後に加えた改良は最も価値がある

ユーザーストーリーマッピング 7章から12章を読んで

上記の本を読んでいて、7章から12章まで各章ごとに印象に残ったことをメモりました。

7章 より良いストーリーテリングのために

  • 以下のようなシンプルなテンプレートを使って会話を始めよう(以下のテンプレートでストーリーに書かれている内容の理解が十分なわけではない)
    • [ユーザータイプとして]、私は[これこれの結果を得る]ために、[これこれを]したい。
  • バックエンドやセキュリティ問題についてのストーリーは難しいものになることがあったり、ストーリーのテンプレートに収めるのに難しいアイディアもある
    • そういうときはストーリーのテンプレートに従わなくてもいい
  • 誰が、なぜ、何を、どのくらいの期間で、など詳細についてもきちんと話をしよう
  • 話すべきことはたくさんあるので、話を思い出すのに役立つものを必ず記録しておこう

8章 カードに書かれていることがすべてではない

  • すべてのストーリーについて、様々な人の間で様々な種類の会話が行われる
  • ストーリーは図書館のカード目録のようなもので、ストーリーのカードの他にどこかにどんどん増え続けている情報があることがわかっている
    • ストーリーに本当に書かれているものは何か
      • 短いタイトル
      • 簡単な説明
      • ストーリー番号
      • 見積り、規模、または予算
      • 価値
      • メトリクス
      • 依存関係
      • 状況
      • 日付
  • 共通理解を築くのにホワイトボードの前でポストイットという武器を持って頭を突き合わせて話をする以上の方法はない。リモートでもカメラやウェブカメラを利用したりそれ用のツールを使おう
  • 計画した仕事の進行状況の順位付け、追跡、分析にはツールを使おう

9章 カードは始まりに過ぎない

  • アジャイル開発サイクルのモデル ... 5つのC
    • Card
    • Conversation
    • Confirmation ... ここまでがカードの3C
    • Construction(構築) ... 議論の場で記録したメモや写真を見て細部を思い出しながらチームはソフトウェアを作る
    • Consequences(結果) ... 作ったものを最初はチームとして次にビジネスステークホルダーとともに評価し最後に顧客、ユーザーとのテストで評価する
  • 構築時に議論の中でできた同じ見取り図を構築のメンバーが頭の中に持っている必要がある
    • ストーリーの詳細を誰かに渡してソフトウェアを作ってもらおうとしてもうまく行かないししてはならない
  • ストーリーを理解している人とストーリーを語るために集めた情報があればストーリーを共有するのにかかる時間は大幅に短くできる
    • ストーリーを形にするための効率的な議論や意思決定のために全員は必要ない
  • ソフトウェアが完成したら品質について話し合う
    • ユーザーエクスペリエンスの質/機能の品質/コードの品質
    • 自分たちが作り上げたものに変更を加えなければならない点を見つけてしまった場合
      • 私たちは合意した通りのものを作ったか?
      • 合意した通りのものを作ったとしてそれを見た結果何か変更を加えるべきか?
  • ユーザーの横に座ってユーザーがあなたの製品を使っているところを見た方がいい
  • 学ぶことを計算に入れてプランを立てる必要がある

10章 ケーキのようにストーリーを焼く

  • ストーリー(デリバリー可能で、評価可能なものを表現したストーリー)を開発チームに持っていくとデリバリータスク(ストリーの実現に必要な作業を表現する)ができる
    • デリバリータスクの詳細を話すのではなく、誰がなぜそれを使うのかを話題にする
  • ストーリーが表しているソリューションがコストのかかりすぎるものなら目標達成に近づく別のソリューションを検討しよう
  • ストーリーが大規模な場合、早いうちに進行状況を評価、確認できる小さなプランのものに分割しよう

11章 岩を砕いていく

  • 立場によって適切なサイズのストーリーの規模は変わる
    • ユーザーの視点から見た適切なサイズのストーリーは、ニーズを満たすストーリーだ
    • 開発チームの視点から見た適切なサイズのストーリーとは、ビルド、テストに数日しかかからないストーリー
    • ビジネスの視点から見た適切なサイズのストーリーは、会社が業績を上げるのに役に立つストーリー
  • エピックは(開発者から見て)分解することが必要だとわかっている大きなストーリーだが、ビジネス、顧客、ユーザーから見て適切なサイズのストーリーである
  • 分解したストーリーをテーマというかたまりを使ってまとめよう
  • ストーリーの岩を砕いていくサイクル
    • 新機能、新製品、既存機能の改良などのアイデア(オポチュニティ)に名前をつけて、オポチュニティバックログに入れる
      • 誰が何をなぜを深く議論してそれぞれのアイデアについてボツにするか先に進むか決める
    • 前進するアイデアを深く掘り下げて、できる限り小さく価値のあるものを作ることを追求する(ディスカバリー段階)
    • ソフトウェアをビルドするために、細部を開発チームと話をしてストーリーをさらに分割する
    • 構築中も細部を埋め、作成中のものにフィードバックするために会話を利用する
    • 作られた部品をスプリントレビュー(スプリントレトロスペクティブ)で最初の評価をする
    • 意味のある量の動くソフトウェアを顧客、ユーザーとともにテストして学習する
    • ビジネスステークホルダーとともに評価を行い、進捗状況を見える化しておく
    • 測定とユーザーとの面談を通じて、目標としてきた結果が得られたかどうかを正確に把握する

12章 岩を砕く人

  • 優れたプロダクトオーナーは、自分が良い判断をするために必要な人々を周りに集めているが、決定はプロダクトオーナーが行う
  • プロダクトオーナーが率いる小規模な組織横断チームがプロダクトディスカバリーの仕事を取り仕切る
  • プロダクトリーダーがいない場でもストーリーをめぐって無数の会話が交わされても構わない
  • ストーリーワークショップ(何を作るかについて具体的に決定を下す最後で最良の会話)には、テスター、製品ディスカバリチームのメンバー、開発者の一人が必要だ
  • プロダクトオーナーは簡単な仕事ではないので、ビジネスピープルに押し付けるのではなく、ビジネスピープルを手助けするプロデューサーを見るけることをお勧めする
  • ストーリーマッピングは、大きなストーリーを小さなストーリに分解するために役立つ方法の一つ
    • 「製品を使う人々」と「何があれば彼らに成功をもたらすことができるのか」を会話の中心に置きながら進めることができる

ユーザーストーリーマッピング 0章から6章を読んで

上記の本を読んでいて、0章から6章まで各章ごとに印象に残ったことをメモりました。

0章 まず最初に読んでください

  • 言葉で表現された文章が正確な製品の実態を示すものではない
  • ストーリーを用いるときは、ストーリーを作ること自体ではなく絵や写真も用いて「共通理解」を築くことが大切
  • アウトプットを最小限に抑えて、最大限の成果とインパクトの獲得を目指す

1章 全体像

  • ただ単にストーリーを作っていくとその粒度の差から開発可能な粒度に揃えると全体像が見えなくなってしまう
  • ストーリーマッピングでは、1つのストーリーを掘り下げる前に全体像としてどのようなストーリーがあるか明らかにする
    • その過程で思考の穴が見つかりやすくなる
    • 複数のユーザーのストーリーが見つかることもある
  • ストーリーマッピングでは、ストーリーの全体像を作ってから詳細や代替案を考えていく

2章 作るものを減らすためのプラン

  • いつでも作る量に対して、時間や資源は少なすぎる
  • 複数のチーム間で共通理解を深めたりチーム間でタスクに漏れがないか確認するためにストーリーマッピングを用いることができる
  • マップの最上部がバックボーンと呼ばれ、バックボーンがマップを体系化する
  • ユーザーが必要とすること(成果)が生まれるリリースを切り出し、リリースの優先順位の基準に成果を用いよう
  • MVPは、仮定を証明または反証するために作れる、あるいは実行できる最小のものである

3章 より早く学ぶためのプラン

  • 大きなアイディアをオポチュニティとして扱い、オポチュニティの枠組み(そもそも何か/顧客は誰か/ユーザーは誰か/彼らはなぜ製品を使いたいと思うか/なぜ私たちはそれを作るのか)の枠組みを確認する
  • 顧客開発パートナーと話をして、解決しようとしている問題が本当にあるか確かめよう(その結果によってオポチュニティは変化する)
  • ソリューションをイメージするためにプロトタイプを作り、ユーザーに見てもらおう
  • 人々が実際に毎日それを使うことを選んだときに証明は得られる
  • minimum未満のものを作ってviableになるまで開発パートナーに対するリリースを繰り返す
  • その時々ごとに利用することができ学ぶことがあるような形でリリースをしよう
  • MVPに向かう過程でさまざまなツールやテクニックを使って行っていることをプロダクトディスカバリーと呼ぶ
    • 目標は自分が正しいものを作っているかどうかをできる限り早く学ぶことだ

4章 時間通りに終わらせるためのプラン

  • マップは会話の助けに必要な分だけ作ればよい
  • 最良の見積もりは、自分が何を見積もっているのかを本当に理解している開発者から出てくるので開発チームと共通理解を築く必要がある
  • 機能の最後まで道をつなげるスライス(歩くスケルトン)、それをもっと良くするスライス、機能を磨けるだけ磨くスライスを分ける
  • 作るのにどれだけかかったか測定することで多少は見積もりを正確にできる
  • リスクの多いプロジェクトの場合、リスクストーリーを追加することで状況を可視化できる
  • インクリメンタル戦略(個々の部品を順に完成させていく)とイテレーティブ戦略(下書きから徐々に構図や色を変更していく)
  • イテレーティブ思考で評価し、インクリメンタル思考で追加し続けよう
  • リリースバックログを製品全体に関わる基礎的な機能や基本的なユーザー行動、リスクの高い部分に注力する序盤、仕上げの部分を埋めていく中盤、リリースを磨く終盤に分ける

5章 あなたはもうやり方を知っている

  • タスクは短い動詞句で構成され、目標を達成するためにすることを表している
    • ユーザータスクはソフトウェアを使う人々が目標達成のためにしているタスク
  • ゴールレベルの概念を使って、小さなタスクを一つにまとめたり、大きなタスクを分割したりしよう
  • ストーリーのマッピングは、ナラティブフローを使って左から右へ向かう
  • 細部、代わりのタスク、変種、例外などはマップの縦方向に入る
  • 目的ごとにタスクをアクティビティという形で集約する
  • アクティビティと大まかなタスクがストーリーのマップのバックボーンを形成する
  • 特定の目標を実現しやすいようにタスクをスライスする
  • ユーザーが将来、製品を届けられたときに振る舞う将来のマップと現在の振る舞いについてのマップがある

6章 ストーリーについての本当のストーリー

  • 私たちは同じドキュメントを読むことができるが、違う理解をする
  • ストーリーという名前は、どのように書くべきかではなくどのように使うべきかについて付けられた名前だ
    • ストーリーの思想は語ることにある
  • ロン・ジェフリーズの3つのC ... スローリーのプロセスの説明
    • Card ... ソフトウェアに望むことをインデックスカードに書いていく
    • Conversation ... 集まってどのようなソフトウェアを作るかについて豊かな会話を交わす
    • Confirmation ... ソフトウェアが完成したことをどのように確認するかについて意見を統一する
  • 製品全体、あるいは既存の製品に加えたいすべての変更を記述しているカードの山のことをプロダクトバックログと呼ぶ

Ransackで関連モデルの検索を行う

Ransackでは特定のモデルのカラムだけでなく、そのモデルと関連する他のモデルのカラムでも検索を行うことができる。

例えば、Userモデルに1対多で紐づくCommentモデルのcontents属性で検索したい場合

<%= search_form_for(@q, url: user_search_path) do |f|
    <%= f.search_field comments_contents_cont %>

逆に、Commentモデルに多対1で紐づくUserモデルのname属性で検索したい場合

<%= search_form_for(@q, url: comment_search_path) do |f|
    <%= f.search_field user_name_cont %>

となる。

User<=(1対多)=>UserGroup<=(1対多)=>Group

といった関連のモデルがある場合、

class User < ApplicationRecord
  has_many :user_groups
end
class UserGroup < ApplicationRecord
  belongs_to :user
  belongs_to :group
end
class Group < ApplicationRecord
  has_many :user_groups
end

以下のようにして、Groupの属性からUserを検索することもできる。

<%= search_form_for(@q, url: users_path) do |f| %>
  <%= f.search_field :user_groups_group_name_cont %>

生成されるクエリは以下のような感じ。

  def index
    @q = User.ransack(params[:q])
    binding.pry
    @users = @q.result
  end
[1] pry(#<UsersController>)> @q.result
  User Load (1.8ms)  SELECT "users".* FROM "users" LEFT OUTER JOIN "user_groups" ON "user_groups"."user_id" = "users"."id" LEFT OUTER JOIN "groups" ON "groups"."id" = "user_groups"."group_id" WHERE "groups"."name" LIKE '%グループ%'

参考

qiita.com

メールの仕組みとDNSのMXレコードについて

ちょっと仕事で調べることがあったのでメモ。

メールサーバには2種類があって、MTA(メール転送サーバ)とMUA(メールユーザエージェント)があって、メール転送サーバはDNSが持っているMXレコードのアドレスのサーバにメールを転送する。

このメールを転送していくことをメールをリレーするといったり、メールリレーと言ったりする。この用語はSendGridなどのサービスを利用しているとエラーメッセージとして出てくるので覚えておく必要がある。

sendgrid.kke.co.jp

MXレコードというのは、メールサーバのアドレスのことであるが、http://example.comtaro@example.comといった具合にドメイン部分( example.com )が同じとき、同じ管理者が管理しているんだろうな、ということは予想されるが、メールサーバとウェブサーバは違うサーバになっているということがよくある。

ということでWEBサーバのアドレスとドメインの対応はAレコード、メールサーバのアドレスとドメインの対応はMXレコードとしてDNSに登録する。

hp-shizuoka.jp

メール転送サーバのプロトコルSMTPMUAの主なプロトコルはPOP, IMAPなので、MTAとMUAとではなく、SMTPサーバ、POPサーバとして呼ばれていることがある。

www.kagoya.jp

メールサービスのプロバイダは迷惑メール扱いされていないか、送ったメールが開封されていないか、エラーになるメールアドレスが多くないかといった事象をもとに迷惑メール判定を行う。

baremail.jp

迷惑メール判定に引っかからないようにメールサービスのプロバイダにホワイトリストとして登録するなどの方法がある。

RansackでRailsの検索を楽に作る

Railsで開発していると検索フォームを作成することがよくあると思います。 今日は、そのときよく使われるRansackについてまとめておこうと思います。

基本的な使い方

  def index
    @q = User.ransack(params[:q])
    @users = @q.result
  end

のように特定のパラメータが入った q というリクエストパラメータのキーを渡すと部分一致検索や冒頭一致検索をしてくれます。 なお、resultメソッドの結果に対して、includesやpagingを利用することもできます。

Ransackのフォーム

Railsでフォームを作成するときはform_with(一昔前はform_forやform_tag)を使いますが、Ransackで上記の特定のパラメータが入った検索フォームを作るときは、search_form_for を使います。

そして、検索用のキーには f.search_field を使います。

<%= search_form_for @q do |f| %>

    <%= f.label :name_cont %>
    <%= f.search_field :name_cont %>

    <%= f.submit %>
<% end %>

部分一致検索

あるキーに対し部分一致検索を行いたい場合、 f.search_fieldxxx_cont を渡します。

    <%= f.label :name_cont %>
    <%= f.search_field :name_cont %>

複数の属性に対して同時に部分一致検索を行わせることができて、その場合、

    <%= f.label :name_or_mail_cont %>
    <%= f.search_field :name_or_mail_cont %>

のように _or_ で属性間を繋ぎます。

冒頭一致検索

あるキーに対し冒頭一致検索を行いたい場合、 f.search_fieldxxx_start を渡します。

    <%= f.label :name_start %>
    <%= f.search_field :name_start %>

冒頭一致検索も複数の属性に対してcontの場合と同様に同時に冒頭一致検索を行わせることができます。

    <%= f.label :name_or_mail_start %>
    <%= f.search_field :name_or_mail_start %>

sort_linkで属性の値によってソートを行った結果を出す

また、Ransack gemでは、sort_link というヘルパーを使って、指定した属性で並び替えた結果を出すリンクを簡単に生成することができます*1

<%= sort_link(@q, :name) %>

参考

github.com

*1:sort_urlヘルパーでurlだけ生成することも可能です

Rails6.1になってコントローラのテンプレート指定に拡張子をつけることが推奨されなくなった

Rails 6.1以上になってCSVなどをダウンロードさせるコントローラのアクションに

def download
    render(
      csv: 'users_list',
      template: 'users/download.csv.ruby'
    )
  end

のように書いているとRSpecの実行時に

DEPRECATION WARNING: Rendering actions with '.' in the name is deprecated: users/download.csv.ruby (called from download at ./app/controllers/users_controller.rb:14)

のように注意されるようになりました。これに対応するには、

def download
    render(
      csv: 'users_list',
      template: 'users/download'
    )
  end

と直せばよいのですが、それだけだと今度は views/users/download.csv.ruby が存在していてもダウンロード時に対応するフォーマットのテンプレートが存在しないというエラーになってしまいます。

なぜかというと、デフォルトではダウンロード時のリンクで

<% link_to 'ダウンロード', download_users_path %>

としたとき、ダウンロードのフォーマットはtext/htmlになっています。コントローラに拡張子を書いていたときはその拡張子に沿ってテンプレートを探してくれていましたが、コントローラから拡張子の指定をとるとデフォルトの設定が優先されます。なので、 users/download.csv.rubycsvのファイルが存在していても探しにいくのはtext/html形式のファイルなので見つからない、ということになります。

text/csv 形式のファイルを探しに行ってもらうためにはダウンロードリンクを用意するときに、

<% link_to 'ダウンロード', download_users_path(format: :csv) %>

と、URLヘルパーにformat属性の指定を行えばよいです。こうすると、コントローラに拡張子を書かなくともテンプレートで用意した拡張子のファイルを探しに行ってくれるようになります。このフォーマットはconifg/routes.rbで

resources :users do
  get :download, on: :collection, default: { format: :csv }
end

のようにconfig/routes.rbの方でも指定できます。

参考

railsguides.jp