価値仮説とユーザーヒアリングによるユーザーファーストなものづくり
身の回りで沸き起こる開発に関する議論を、効率よく質の高いものにするために考えたことのメモです。
きっかけ
- C社やW社、I社の方の開発の進め方に関する話を聞く機会があり、感銘を受けた
- UIや機能の是非に関する議論は難しく、これまでの開発でうまく進められないことが多々あったため、より良い方法はないかと模索していた
身の回りで沸き起こる既存の議論の問題点
「○○がわかると△△だから、ユーザーにとって有益なはずだ」
- ○○を知りたいというユーザーが実際にいたの?
- ○○を見せたいのはわかるけど、見たいと思うユーザーがいなかったら誰にも使ってもらえないよな...
「☓社がやっているから(海外で流行っているから)、弊社も○○をやろう」
- ☓社のユーザーと弊社のユーザーは同じなの?ユーザーが抱えている問題は同じ?
「ユーザーが○○な機能を欲しいと言っているので、早く開発してリリースしたい」
- その発言の裏にある問題の本質を見極めるべきでは?それは本当にいま最優先で取り組むべき?
個人的に感じた問題点をまとめると...
- ユーザーは○○したいはずだという妄想に基づいて議論が進んでいる気がする
- 本当に想定する課題を持ったユーザーがいるのか、ユーザーはその課題の解決を熱望しているのか、といったことを確かめた方がよいのではないか
- = ユーザーヒアリング をした方がよいのでは
- ○○させたいという作り手のエゴによって議論が進んでいる気がする
- ロジックが人によってバラバラ
- 例1: 私は○○したいと思ったから、△△であるべきだ
- 例2: ユーザーが○○をほしいと言っているから実装しよう
- 同じ前提知識と目指すべき方向性を持った人が、同じロジックで議論したほうが効率がいいのではないか
- C社やI社は意識的にそうしている?
- = C社やI社で活用されている 価値仮説 を用いれば、効率よく効果的に議論が進むのでは?
きっと俺たちには、"価値仮説" と "ユーザーヒアリング" が必要だ
価値仮説 とは?
スタートアップでは最初に、「提供する製品やサービスが本当に価値のあるものかどうか」を確認していく活動を続けます。その仮説を「価値仮説」と呼んでいます。
その仮説を定義するため、C社では下記のフォーマットを用いているそうです。
フォーマット
(プラスα)変化する指標
(プラスα)MVP
MVPとは?
"Minimum Viable Product"の略。 リーンスタートアップの著者 エリック・リース 氏曰く、
MVPとは、(Build-Measure-Learnの)フィードバック・ループ1周を回せる『必要最低限の労力』+『最低限の実装時間』バージョンの製品
だそうだ。 リスクや投資を最小限に抑えた実用最小限の製品により、想定する仮説の検証を行うことが目的である。
ここはかなり工夫できるところで、例えば Twitter で呟き、フォロワーのFav数やretweet数などの反応を見るというのもひとつの手である。
価値仮説 のメリット
- エンジニアは自分が作りたい機能ありきで考えてしまいがちだが、本来重要であるはずのユーザーの抱えている課題について、強制的に考えさせられる
- チームメンバーに共有する前に、フォーマットを通して文章に落とすことで、事前にロジックの穴を補完できる
- 論点が整理されるため、議論が効率的になる
- C社やI社などの開発現場で実際に活用されており実績がある
- ロジックを組み立て、ユーザーヒアリングを行いその価値を確認することは一見コストが高いように思えるが、妄想によってユーザーに不要なものをつくることに時間を掛けてしまうより圧倒的に生産性が高い
価値仮説 がない開発
- ロジックがバラバラであったり、論点が散漫になってしまい議論に時間がかかる
- 時間が掛かっているからといって、プロダクトのクオリティに繋がっているとは限らない
- リリースをしたが、何が改善されたかわからない
- リリースで解決する課題が不明確だと、ユーザーにとってプラスだったかマイナスだった把握できない
- ユーザーの課題や行動に関する学習がないので、ユーザーへの理解が進まない
価値仮説 を補完する ユーザーヒアリング
上記の価値仮説を補完するためにユーザーヒアリングを行うべきと考える。 価値仮説フォーマットで想定するユーザーが、想定する欲求や課題を持っているか、その課題が解決されることを熱望しているか(お金を払ってでも使いたいと思ってもらえるか)をユーザーヒアリングで確認する。 妄想ではなく、実際にユーザーの声を聞くことが重要。
よくある疑問
将来の製品アイデアの話をしたら、アイデアだけ盗まれてしまうのでは?
基本的には、インタビュー時に製品アイデアを話すことはない。話をするのは、製品やサービスによって解決したいユーザーの課題について。
ユーザーヒアリングは時間がかかるので、非効率ではないか?
価値仮説を明確にし、ユーザーヒアリングを行うプロセスの中で、想定に一つでも誤りが見つかれば、開発工数を大幅に節約できる。 多くの時間を投じて開発した末に誰も使ってくれないことに比べれば効率がよい。
統計的に有意な人数のユーザーヒアリングを行うことは難しいのでは?
有効なユーザーヒアリングのサンプル数については、現在勉強中です。 ただ、妄想を基に開発を進めるよりは、2~3人でもユーザーヒアリングを行いその事実を基に開発を進めた方が、リスクは低いのではと考えている。
「大事なこと」
参考
- Service development for users
- 新規事業やスタートアップで優れたプロダクトを作るときに使える Y Combinator などの考え方
- リーン顧客開発 ―「売れないリスク」を極小化する技術
リーン顧客開発 ―「売れないリスク」を極小化する技術 (THE LEAN SERIES)
- 作者: シンディ・アルバレス,エリック・リース,堤孝志(監訳),飯野将人(監訳),児島修
- 出版社/メーカー: オライリージャパン
- 発売日: 2015/04/25
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (2件) を見る
表参道.rb #1 を開催しました
主催者の一人として 表参道.rb #1 を開催しました。
50名近い規模のイベント主催は初めてですし、ましてや Rubyコミュニティ なんて畏れ多い。とにかく不安だらけでしたが、たくさんの方にお集まりいただいて、安堵しています。LTもおもしろい内容のものが多く、会場も盛り上がっていた様子でした。
参加くださった方、LTをしてくださった方、会場提供いただいた Sansan 様、本当にありがとうございました。
LTした
Rails で React と ES6 を使いつつ、Server-side Rendering するという話をしてきました。もっとイケてるやり方あれば教えてください!
次回以降について
表参道.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が機能追加のロードマップを出さない理由
- ユーザーヒアリングを重視しており、その結果から予定していた機能を変更したり、リリースしないという判断をすることもあるため
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を使用する
処理の流れ
- jsxは
frontend/javascripts
配下にES6で記載していく(ディレクトリは仮) - gulpとbabelでES6をES5にトランスパイルする
- ファイルが変更されたら自動トランスパイルされるよう設定しておく
- 2.で生成されたjsを
app/assets/javascripts/components
に配置する - 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を使用することにした。
- ref:
react_component
のコード
今後の展望
- 巷で速いと噂のLibsassを使いたい
- FluxまたはFRPのフレームワークを導入したい
- voronianski/flux-comparison
- Flummox: joker1007氏も使っているMinimal Flux フレームワーク
- Good bye Flux, welcome Bacon/Rx?
参考文献
- RailsGuides - The Asset Pipeline
- Sprockets再考 モダンなJSのエコシステムとRailsのより良い関係を探す
- Railsで昨今のJSのエコシステム(gulpとかそういうの)を使うにあたってこのようにしたというメモ
- 3 ways to integrate Ruby on Rails + React + Flux
- Gulp on Rails: Replacing the Asset Pipeline
- Gulp - a modern approach to asset pipeline for Rails developers
- npm で依存もタスクも一元化する
- Rails, React, Browserify - Packaging your React components
- Can't render browserified JS on server side #181
- なぜ僕は(2015年のフロントエンドで、makeではなく)gulpを選ぶのか
入門 React ―コンポーネントベースのWebフロントエンド開発
- 作者: Frankie Bagnardi,Jonathan Beebe,Richard Feldman,Tom Hallett,Simon HØjberg,Karl Mikkelsen,宮崎空
- 出版社/メーカー: オライリージャパン
- 発売日: 2015/04/03
- メディア: 大型本
- この商品を含むブログ (2件) を見る
ES6を導入したいRailsエンジニアの覚書き
選定候補
- CoffeeScript
- 現状使用している
- Railsとの相性がよい(デフォルトでサポートされている)
- ECMAScript 6(以下、ES6)
- 次期JavaScriptの標準仕様
ES6はいつ勧告されるの?
- 2015年6月予定
- つまり、仕様はまだ固まっていない(が、ほぼほぼ固まっていると言って良いと思われる)
ES6の機能
- es6featuresで概要を一覧できます
- Mozillaが出している非公式のES6ドラフト仕様書はこちら
- 「2015 年の JavaScript と babel の話」や「HELLO, ES6 ~これから迎えるJSのミライ~」もわかりやすかった
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 | × | bluebirdやjQuery.Deferredなどを使用すれば可能, ただしjQuery.DeferredのDefferdとPromiseは正確には別物 |
math + number + string + array + object APIs | × | |
binary and octal literals | ○ | |
reflect api | × | |
tail calls | × |
ref: es6features
余談: サンプルコード
サンプルコードを載せておくので雰囲気を感じてください。 1文字でも短く書きたいという人は、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つある。
ES6がサポートされているブラウザのみをサポートブラウザとする
- compatibility tableを見る限り現実的ではない
Polyfillを使用する
- ex: ES6-style Promisesのpolyfill
- 機能ごとにpolyfillを選定する必要があるためコストが高そう
- HTML5 Cross Browser Polyfills
- トランスパイラを使用する
- babel がデファクトスタンダード
- @joker1007 さんも個人プロジェクトで採用しているっぽい
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関連のライブラリの方が充実する可能性が高いと考えられる。
- ex: power-assert
- CoffeeScripで使用するにはespower-coffeeが必要
- ES6(babel)で使用するにはbabel-plugin-espowerが必要
- 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 までの考え方にはないモダンな機能が入っています。
おまけ
- AltJSの選び方フローチャートは試しにやってみると面白いかも
- es6fiddleを使えば、ブラウザ上でお試しできます
- GitHub の ATOM が CoffeeScript で書かれているのはどうなの?
- @yosuke_furukawa さんが開発されたES6の学習ツール tower-of-babel
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
- server side rendering使う?
- その他のソリューションを使う?
デザイナーとの協業
- jadeなどのテンプレートエンジンを使って、デザイナーがもう少し触りやすい方法を模索する
- 「協業を考えるよりデザイナーがReact覚えるほうが早いのでは」という意見もある
協業を考えるよりデザイナーがReact覚えるほうが早いという気が
— りんごちゃん (@_ringogirl) April 29, 2015
スケール可能なアーキテクチャ
- stateに依存する複数の要素を、階層構造を使わずに管理する必要がある
- 「Components階層間でpropsのバケツリレーになる前にFluxアーキテクチャを導入したほうがよい」
React.js を理解する上で重要な "Thinking in React" の抄訳になっている。あと、 Component 階層間で props のバケツリレーになる前に Flux アーキテクチャを導入した方が良いと思う。 http://t.co/pHkMYaKaUk
— Takuto Wada (@t_wada) March 16, 2015
- 規模が大きくなる場合は、Fluxの導入を検討する必要がありそう
- Flux実装の比較: voronianski/flux-comparison · GitHub
assets管理
- (Reactに限った話ではないが)JSのライブラリを同梱したgemを使う方式だとバージョンアップに追従しづらい
- JSはnpmのエコシステムで管理したい気持ちはあるけど、sprocketsが便利なのもわかる
- この辺を参考に適切な方法を探る必要がありそう
front endとback endのコードの重複
- (これもReactに限った話ではないが)front endとback endのvalidationコードなどの重複が発生しそうなのでなるべく避けたい
- Isomorphicの文脈で語られるようなこと?
規約を作った方がよさそう
- 子componentがstateを直接更新しないようにしましょう的なの
- 参考になりそう
入門 React ―コンポーネントベースのWebフロントエンド開発
- 作者: Frankie Bagnardi,Jonathan Beebe,Richard Feldman,Tom Hallett,Simon HØjberg,Karl Mikkelsen,宮崎空
- 出版社/メーカー: オライリージャパン
- 発売日: 2015/04/03
- メディア: 大型本
- この商品を含むブログ (2件) を見る
鮨物語
鮨には物語がある。
表参道の骨董通りにある江戸前寿司のお店「鮨 ます田」に訪問した。
序章
店主は「銀座すきやばし次郎」で9年間修行されているということで、前日に『二郎は鮨の夢を見る』で予習をした。
ますだフィッシュ
鮃
縁側
赤貝
赤身
中トロ
小肌
車海老
鯵
金目鯛 炙ってるかどうかかわからない程度に軽く炙ってあり、塩で頂いた。
蛤
雲丹
干瓢
玉子
やち「そう言えば、穴子はないんですね。最後に食べたいなと。」
ますだ「今日はネタがあまり良くなかったので...」
ますだ「ギリギリ出せるレベルのもので良ければ出せますが、いかがですか?」
やち「食べたいです」
うまいっ。これでギリギリ出せるか出せないかのレベルなのか。
- ジャンル:寿司
- 住所: 港区南青山5-8-11 BC南青山PROPERTY B1F
- このお店を含むブログを見る |
- (写真提供:ジエンダー)
- 鮨 ます田をぐるなびで見る | 表参道・青山の寿司をぐるなびで見る