破いて捨てたノート

Webやテクノロジーやそれ以外に関する思いつき

価値仮説とユーザーヒアリングによるユーザーファーストなものづくり

身の回りで沸き起こる開発に関する議論を、効率よく質の高いものにするために考えたことのメモです。

きっかけ

  • C社やW社、I社の方の開発の進め方に関する話を聞く機会があり、感銘を受けた
  • UIや機能の是非に関する議論は難しく、これまでの開発でうまく進められないことが多々あったため、より良い方法はないかと模索していた

身の回りで沸き起こる既存の議論の問題点

「○○がわかると△△だから、ユーザーにとって有益なはずだ」

  • ○○を知りたいというユーザーが実際にいたの?
  • ○○を見せたいのはわかるけど、見たいと思うユーザーがいなかったら誰にも使ってもらえないよな...

「☓社がやっているから(海外で流行っているから)、弊社も○○をやろう」

  • ☓社のユーザーと弊社のユーザーは同じなの?ユーザーが抱えている問題は同じ?

「ユーザーが○○な機能を欲しいと言っているので、早く開発してリリースしたい」

  • その発言の裏にある問題の本質を見極めるべきでは?それは本当にいま最優先で取り組むべき?

個人的に感じた問題点をまとめると...

  • ユーザーは○○したいはずだという妄想に基づいて議論が進んでいる気がする
    • 本当に想定する課題を持ったユーザーがいるのか、ユーザーはその課題の解決を熱望しているのか、といったことを確かめた方がよいのではないか
    • = ユーザーヒアリング をした方がよいのでは
  • ○○させたいという作り手のエゴによって議論が進んでいる気がする
    • 人間のアイデアや想定が的外れであるというのはよくあることだ
    • Microsoft でさえアイデアのうち、想定通りの改善につながったものは 3 分の 1 であると言われている from 『リーン顧客開発
    • = ユーザーヒアリング をした方がよいのでは
  • ロジックが人によってバラバラ
    • 例1: 私は○○したいと思ったから、△△であるべきだ
    • 例2: ユーザーが○○をほしいと言っているから実装しよう
    • 同じ前提知識と目指すべき方向性を持った人が、同じロジックで議論したほうが効率がいいのではないか
      • C社やI社は意識的にそうしている?
    • = C社やI社で活用されている 価値仮説 を用いれば、効率よく効果的に議論が進むのでは?

きっと俺たちには、"価値仮説" と "ユーザーヒアリング" が必要だ

価値仮説 とは?

スタートアップでは最初に、「提供する製品やサービスが本当に価値のあるものかどうか」を確認していく活動を続けます。その仮説を「価値仮説」と呼んでいます。

その仮説を定義するため、C社では下記のフォーマットを用いているそうです。

フォーマット

(プラスα)変化する指標

(プラスα)MVP

MVPとは?

"Minimum Viable Product"の略。 リーンスタートアップの著者 エリック・リース 氏曰く、

MVPとは、(Build-Measure-Learnの)フィードバック・ループ1周を回せる『必要最低限の労力』+『最低限の実装時間』バージョンの製品

だそうだ。 リスクや投資を最小限に抑えた実用最小限の製品により、想定する仮説の検証を行うことが目的である。

ここはかなり工夫できるところで、例えば Twitter で呟き、フォロワーのFav数やretweet数などの反応を見るというのもひとつの手である。

価値仮説 のメリット

  • エンジニアは自分が作りたい機能ありきで考えてしまいがちだが、本来重要であるはずのユーザーの抱えている課題について、強制的に考えさせられる
  • チームメンバーに共有する前に、フォーマットを通して文章に落とすことで、事前にロジックの穴を補完できる
  • 論点が整理されるため、議論が効率的になる
  • C社やI社などの開発現場で実際に活用されており実績がある
  • ロジックを組み立て、ユーザーヒアリングを行いその価値を確認することは一見コストが高いように思えるが、妄想によってユーザーに不要なものをつくることに時間を掛けてしまうより圧倒的に生産性が高い

価値仮説 がない開発

  • ロジックがバラバラであったり、論点が散漫になってしまい議論に時間がかかる
    • 時間が掛かっているからといって、プロダクトのクオリティに繋がっているとは限らない
  • リリースをしたが、何が改善されたかわからない
    • リリースで解決する課題が不明確だと、ユーザーにとってプラスだったかマイナスだった把握できない
  • ユーザーの課題や行動に関する学習がないので、ユーザーへの理解が進まない

価値仮説 を補完する ユーザーヒアリング

上記の価値仮説を補完するためにユーザーヒアリングを行うべきと考える。 価値仮説フォーマットで想定するユーザーが、想定する欲求や課題を持っているか、その課題が解決されることを熱望しているか(お金を払ってでも使いたいと思ってもらえるか)をユーザーヒアリングで確認する。 妄想ではなく、実際にユーザーの声を聞くことが重要。

よくある疑問

将来の製品アイデアの話をしたら、アイデアだけ盗まれてしまうのでは?

基本的には、インタビュー時に製品アイデアを話すことはない。話をするのは、製品やサービスによって解決したいユーザーの課題について。

ユーザーヒアリングは時間がかかるので、非効率ではないか?

価値仮説を明確にし、ユーザーヒアリングを行うプロセスの中で、想定に一つでも誤りが見つかれば、開発工数を大幅に節約できる。 多くの時間を投じて開発した末に誰も使ってくれないことに比べれば効率がよい。

統計的に有意な人数のユーザーヒアリングを行うことは難しいのでは?

有効なユーザーヒアリングのサンプル数については、現在勉強中です。 ただ、妄想を基に開発を進めるよりは、2~3人でもユーザーヒアリングを行いその事実を基に開発を進めた方が、リスクは低いのではと考えている。

「大事なこと」

参考

リーン顧客開発 ―「売れないリスク」を極小化する技術 (THE LEAN SERIES)

リーン顧客開発 ―「売れないリスク」を極小化する技術 (THE LEAN SERIES)

表参道.rb #1 を開催しました

主催者の一人として 表参道.rb #1 を開催しました。

50名近い規模のイベント主催は初めてですし、ましてや Rubyコミュニティ なんて畏れ多い。とにかく不安だらけでしたが、たくさんの方にお集まりいただいて、安堵しています。LTもおもしろい内容のものが多く、会場も盛り上がっていた様子でした。
参加くださった方、LTをしてくださった方、会場提供いただいた Sansan 様、本当にありがとうございました。

omotesandorb.connpass.com

LTした

Rails で React と ES6 を使いつつ、Server-side Rendering するという話をしてきました。もっとイケてるやり方あれば教えてください!

speakerdeck.com

次回以降について

表参道.rb は、毎月第一木曜日の開催を予定しています。

次回は 7月2日(木)、株式会社 grooves にて開催を予定しています。イベントは connpass にて公開予定です。イベントページをオープンしたら #omotesandorb などで告知しますので、皆さまのご参加をお待ちしております。

第1回は50人規模でのLT大会という形式でしたが、今後もこの規模・形式で行うかは未定です。
"コミュニティ" である以上、参加者もその場の一員であり、一緒に場をつくっていると感じてもらえるようにしたいと個人的には思っています。より良い形式を模索中ですので、こんな風にやるとおもしろいかも!といったご意見は絶賛お待ちしております。

また、第3回以降に会場を貸していただける会社様を募集しております。ご協力いただける方は #omotesandorb もしくは @yachibit までご連絡いただけると幸いです。

Qiita/Qiita:Team Meetup #12 での会話の雑なメモ

楽しかったです、Qiita/Qiita:Team Meetup。 Increments社の方からお話しを伺えて、とても勉強になりました。

以下は、飲みながら話したことの雑なメモです。

  • Reactのテストはどうしてるか
    • みんな好きなの使えばいいじゃん?
    • Mocha + power-assert + jsdom + sinon とかでやってる
    • ビュー層はUI修正の影響を受けて壊れやすいのでテストは薄くしている
    • ドメイン層のテストはしっかり書く
  • Jestの微妙な点
    • ベースのJasmineのバージョンが古い(1.3を使っているが最新は2.3)
    • requireしたモジュールは全部モックするとかキモいし、それだったら自分でモックする
  • React重い
    • VirtualDOMでやりたいことを実現するだけなら、こんなに重い必要はない
    • Reactは120 KBと重いので、ユーザーにそれをダウンロードさせるだけの価値があるか考えて使ったほうがいい
  • デザインの進め方について
    • ユーザーヒアリングの結果など前提知識をチームで共有する
    • クックパッドの価値仮説のようなフレームワークを使うなどして、チームが同じロジックで話すようにしている
    • Incrementsではとにかくロジカルであることが求められる
    • やったほうがいいことは山ほどあるが、本当にやらなければいけないことのみにフォーカスするようにしている
  • Qiita:Teamが機能追加のロードマップを出さない理由
    • ユーザーヒアリングを重視しており、その結果から予定していた機能を変更したり、リリースしないという判断をすることもあるため

qiita-kobito-meetup12.peatix.com

Rails + React + ES6 のためのアセット環境構築

結論

Sprocketsの動作を維持しつつ、npmやgulpなどのモダンなパワーも取り入れた、いいとこどりな環境を構築してみた。

やりたいこと

  • SEOのため、Reactでserver-side renderingをしたい
  • JSコードをES6で記述したい
  • 既存のCoffeeScriptのコードも共存させたい(後ほど書き換える予定)
  • npmやgulpといったモダンな環境でアセット管理をしたい
  • browserifyを使いたい
  • Sprocketsが実現している機能は維持したい

そもそもSprocketsは何をしているか

周知のことでしょうが念のためおさらい。

  • ファイル毎の依存関係の管理
    • application.jsなどのマニュフェストファイルがやってること
  • altJSのコンパイル
  • アセットのminify
  • アセットの連結
  • アセットファイル名にMD5フィンガープリントを挿入

Sprocketsの問題点

  • JSライブラリをラップするgemに依存する
    • 使いたいライブラリがあるのにgemがないから使えないということが起きる
    • gemのメンテナンスが遅れ、古いバージョンのライブラリを使わざるを得なくなる
  • 似たようなgemが乱立していて混乱する
  • jadeテンプレートのようなものをbrowserifyなど使ってrequireして埋め込むとかできなくてツラい

Sprocketsのメリット

  • development環境の場合、アセットは個別のファイルとして、マニフェストファイルの記載順に読み込まれる
    • 元のJSファイルを参照しながら開発できる
  • あるファイルを弄った時は再読み込みをするだけでそのファイルだけ再コンパイルされて上手く更新してくれる
  • WebブラウザにキャッシュされたアセットファイルはMD5フィンガープリントが変更されることでいい感じに無効になる

サンプルアプリ

https://github.com/yachibit-sandbox/react_with_rails_and_gulp

ポイント

  • Server-side renderingをするためreact-railsを使用する

処理の流れ

  1. jsxはfrontend/javascripts配下にES6で記載していく(ディレクトリは仮)
  2. gulpとbabelでES6をES5にトランスパイルする
    • ファイルが変更されたら自動トランスパイルされるよう設定しておく
  3. 2.で生成されたjsをapp/assets/javascripts/componentsに配置する
  4. 3.で配置されたjsをsprocketsに読み込む
    • 読み込まれるようにマニュフェストファイル(application.js)を記載しておく

Deploy

だいたいこんな感じで動くと思います。

namespace :deploy do
  namespace :npm do
    task :install do
      # npm install
    end
  end

  namespace :assets do
    task :build do
      # npm run build
    end
  end

  before 'deploy:assets:precompile', 'deploy:assets:build'
  before 'deploy:assets:build', 'deploy:npm:install'
end

npmモジュールのreactではなくreact-railsを使用したのはなぜか?

react_component helperを使いたかったから。 通常、ReactでServer-side renderingをする際、renderToString(もしくはrenderToStaticMarkup)を使用して、ReactElementをHTML文字列として出力する。ここで出力されたHTML文字列を元に、サーバー側でviewを生成するが、JSの世界のHTML文字列をRailsのviewとしてうまい具合に表示させるのは面倒だった。react_component helperを使用すればそれが簡単に実現できるので、react-railsを使用することにした。

今後の展望

参考文献

入門 React ―コンポーネントベースのWebフロントエンド開発

入門 React ―コンポーネントベースのWebフロントエンド開発

ES6を導入したいRailsエンジニアの覚書き

選定候補

ES6はいつ勧告されるの?

  • 2015年6月予定
    • つまり、仕様はまだ固まっていない(が、ほぼほぼ固まっていると言って良いと思われる)

ES6の機能

ES6とCoffeeScriptの機能比較

es6featuresに記載される機能のCoffeeScriptでの実装状況を一覧表にしてみました。

ES6の主な新機能 CoffeeScriptでの実装の有無 メモ
arrows 引数や括弧を省略可能
classes Coffee: 括弧なしで関数を呼べる, ES6: getterとsetterが使える
enhanced object literals {foo: foo}の省略記法はCoffeeにも実装済
template strings
destructuring
default + rest + spread
let + const ×
iterators + for..of ×
generators CoffeeScriptではfunction*は不要、yieldを呼び出すだけ
unicode ×
modules browserifyなどがこの問題を解決している
module loaders ×
map + set + weakmap + weakset ×
proxies ×
symbols ×
subclassable built-ins ×
promises × bluebirdjQuery.Deferredなどを使用すれば可能, ただしjQuery.DeferredのDefferdとPromiseは正確には別物
math + number + string + array + object APIs ×
binary and octal literals
reflect api ×
tail calls ×

ref: es6features

余談: サンプルコード

サンプルコードを載せておくので雰囲気を感じてください。 1文字でも短く書きたいという人は、CoffeeScriptの方が好きかもしれません。

CoffeeScript

class Person
  constructor: (@firstName, @lastName) ->

  name: ->
    "#{@first_name} #{@last_name}"

  setName: (name) ->
    names = name.split " "

    @firstName = names[0]
    @lastName = names[1]

blake = new Person "Blake", "Williams"
blake.setName("Blake Anderson")
console.log blake.name()

ES6

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  get name() {
    return this.firstName + " " + this.lastName;
  }

  set name(name) {
    var names = name.split(" ");

    this.firstName = names[0];
    this.lastName = names[1];
  }
}

var blake = new Person("Blake", "Williams");
blake.name = "Blake Anderson"
console.log(blake.name);

refs: Replace CoffeeScript with ES6

ES6のブラウザ実装の対応状況

ES6をプロジェクトで使うには?

主な方法は3つある。

  1. ES6がサポートされているブラウザのみをサポートブラウザとする

  2. Polyfillを使用する

  3. トランスパイラを使用する

Railsでbabelを使う

Sprockets で使う方法

sprockets-es6あたりのgemを使えばよさそう。 ただ、あまりStarが集まっていなかったりするので、このやり方を試している人が少ないのかもしれない。

ref: Ruby Toolboxで「es6」と検索した結果

gulp などで使う方法

だいたいこんな感じでgulpfileを書けばいけそう。 @yachibit が試してみたvanilla appも参考になるかも。

var gulp = require("gulp");
var sourcemaps = require("gulp-sourcemaps");
var babel = require("gulp-babel");
var concat = require("gulp-concat");

gulp.task("default", function () {
  return gulp.src("src/**/*.js")
    .pipe(sourcemaps.init())
    .pipe(concat("all.js"))
    .pipe(babel())
    .pipe(sourcemaps.write("."))
    .pipe(gulp.dest("dist"));
});

ref: http://magazine.rubyist.net/?0050-ECMAScript2015

ライブラリのサポート

標準JavaScriptでサポートされているライブラリがCoffeeScriptやES6で使用できるとは限らない。 ES6は標準なので、将来的にはCoffeeScriptと比較するとES6関連のライブラリの方が充実する可能性が高いと考えられる。

学習コスト

CoffeeScriptを採用する場合

  • 既存のメンバーや世間のRailsエンジニアはCoffeeScriptに慣れているのでCoffeeScriptを使用する際の学習コストは殆ど無い
  • CoffeeScriptに慣れていないメンバーがジョインする際に学習コストが発生する可能性がある
  • 既存の書籍やライブラリのサンプルコードは普通のJavaScriptで書かれることが多いため、脳内コンパイルする必要がある

ES6を採用する場合

  • ES6を覚える必要があるが、基本的にはJavaScriptなのでそれほど難しくはないと思われる
  • 標準仕様なので、新規にジョインするメンバーも使える可能性が高い
    • 勧告前なのでそれほど普及しているわけではないと思うが

既存コードの活用

  • gulpとbabelをうまく使えば、CoffeeScriptで書かれたコードとES6で書かれたコードをそれぞれ別々でES5にトランスパイルすることが可能なので、共存させることも可能

まとめ

個人的にはES6を推したい

ES6を推したい理由

  • ES6は大規模開発をしやすくする機能や、関数型プログラミングの概念が取り入れられているため、よりモダンな開発が可能となる
  • 標準仕様であるため、ライブラリのサポートや書籍等の情報がES6に優位に進んでいくと思われる
  • gulpやbabelの力を借りれば、既存のCoffeeScriptのコードも活用することができる
  • babelはReactとの相性がいい
    • babelにはJSX transformerが同梱されている

懸念点、課題

  • チームでのコーディングルール(変数宣言、プロトタイプベースのクラスは使わない等)
  • 既存の開発メンバーがES6を学習する必要がある
  • 好みの問題ではあるが、CoffeeScriptと比較すると、varや括弧等の記述が増えるため、コード量が増える

るびまでの @yosuke_furukawa さんのまとめが大変わかりやすかったので併記しておきます。

JavaScript に class や module の考え方が入り、適切な単位でモジュールとクラスを分割して設計することができるようになりました。また let や const で変数の生存範囲を限定する事ができるようになりました。これらの機能は大規模なアプリを開発する時やライブラリを作る際の助けになるはずです。
また、generator/iterator/Promise といった関数型プログラミングの概念が導入され、さらに末尾呼び出し最適化といった副作用を少なくする記述方法ができるようになりました。ES6 には ES5 までの考え方にはないモダンな機能が入っています。

おまけ

Reactを導入したいRailsエンジニアの覚書き

フレームワークの特徴(つらみ)を整理

only jQuery

  • Viewが状態を持ってしまう拡張やテストがしづらい
  • DOMを指定してViewの更新処理を書くのはつらい

Backbone.js

  • Viewの更新処理を手動で書かないといけないのはつらい
  • ModelとView間のイベント管理が煩雑になる
  • イベント地獄になりがち

2 Way Data bindingを使ったフレームワーク(AngularJS、Vue.js、Ember.jsなど)

  • コンポーネント毎に状態を持つとつらい
  • 大規模になってくると状態を管理するのが難しくなる
    • 単一方向データバインディング: データに対して、ビューの状態が必ず一意に決まる
    • 双方向データバインディング: データに対して、ビューの状態が一意に決まるとは限らない

refs:

Reactを導入するとなった場合に考慮すべきこと

Search Engine Crawlability

デザイナーとの協業

  • jadeなどのテンプレートエンジンを使って、デザイナーがもう少し触りやすい方法を模索する
  • 「協業を考えるよりデザイナーがReact覚えるほうが早いのでは」という意見もある

スケール可能なアーキテクチャ

assets管理

front endとback endのコードの重複

  • (これもReactに限った話ではないが)front endとback endのvalidationコードなどの重複が発生しそうなのでなるべく避けたい
  • Isomorphicの文脈で語られるようなこと?

規約を作った方がよさそう

入門 React ―コンポーネントベースのWebフロントエンド開発

入門 React ―コンポーネントベースのWebフロントエンド開発

鮨物語

鮨には物語がある。

表参道の骨董通りにある江戸前寿司のお店「鮨 ます田」に訪問した。

序章

店主は「銀座すきやばし次郎」で9年間修行されているということで、前日に『二郎は鮨の夢を見る』で予習をした。 f:id:yachibit:20150402223104j:plain

ますだフィッシュ

アイナメ f:id:yachibit:20150403190704j:plain

f:id:yachibit:20150403191030j:plain

縁側 f:id:yachibit:20150403191353j:plain

赤貝 f:id:yachibit:20150403191652j:plain

スルメイカ f:id:yachibit:20150403192145j:plain

サヨリ f:id:yachibit:20150403192436j:plain

赤身 f:id:yachibit:20150403192852j:plain

中トロ f:id:yachibit:20150403193232j:plain

小肌 f:id:yachibit:20150403193705j:plain

車海老 f:id:yachibit:20150403194352j:plain

f:id:yachibit:20150403194949j:plain

鳥貝 f:id:yachibit:20150403195423j:plain

金目鯛 f:id:yachibit:20150403195932j:plain 炙ってるかどうかかわからない程度に軽く炙ってあり、塩で頂いた。

f:id:yachibit:20150403200359j:plain

雲丹 f:id:yachibit:20150403200925j:plain

干瓢 f:id:yachibit:20150403201435j:plain

玉子 f:id:yachibit:20150403201800j:plain

やち「そう言えば、穴子はないんですね。最後に食べたいなと。」
ますだ「今日はネタがあまり良くなかったので...」
ますだ「ギリギリ出せるレベルのもので良ければ出せますが、いかがですか?」
やち「食べたいです」

うまいっ。これでギリギリ出せるか出せないかのレベルなのか。 f:id:yachibit:20150403202612j:plain

鮨 ます田

食べログ 鮨 ます田