「リーン顧客開発」という本を読んだ

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

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

積んでた本をちゃんと読んだ。 前回読んだときは、想像していた中身とちょっと違っていて、最初の数十ページ読んで積んでしまっていた。しかし、改めて読み直してみると現在会社でやっているユーザーインタビューに対してかなり知見を与えてくれそうな本だったので、一気に読んだ。

どんな本?

「顧客開発」というタイトルから、サービスのファンを如何につくるかみたいなマーケティング的な話を想像してしまっていたんだけど、中身はそういう感じではない(なので前回読んだときは途中でやめてしまった)。顧客と対話することで、どんな課題やニーズがあるのか、そもそもその顧客は作ろうとしているサービスのユーザーになってくれるのか、みたいなものを如何に見極めるかという話だった。

この本の殆どの部分は「ユーザーインタビューをどんな風に行ったらいいか」ということに割かれている。ユーザーインタビューで聞くべき質問から、インタビュー対象の見つけ方、どれくらいインタビューを重ねればいいかなど結構具体的だ、本のタイトルから自分はもっと心構えがどうといった抽象的な話が多いのかと思っていたので結構意外だった。

学び

「ユーザーの言うことをそのまま実装してもダメ。本当の課題が何か考えよう」みたいな話はよくあるし自分も思う所だけど、ユーザーとの対話を通して如何に課題を引き出すか・見つけるか、みたいな視点をあまり意識したことがなかったので新鮮だった。

自分はユーザーインタビューで得られた意見に対して「尤もな意見だけど少数派なのではないか」「不満は感じてないと言っているけど、システムに慣れてしまっただけなのではないか」みたいなことをよく思っていたし、どう判断すればいいのかよく分からないなと思っていたんだけれど、そこについてもこの本は色々書いてくれている。

結局は漫然とユーザーインタビューをしていても駄目で、「自分たちの持っている仮説を検証する」という心構えでインタビューの対象者選びをして繰り返しインタビューをしていかないと、得られるものも少なくなってしまうんだなと思った(これはどういう意図のユーザーインタビューだったかにも依るとは思うけど…)。

MVPについてはこの本のメインの部分ではないだろうけど、様々なパターンについて具体例を交えて書かれていて結構参考になる。「最終的な製品をどうするか決めて、MVPとして出すためにカットできる機能を検討する」は「よく耳にする起業家の間違い」とはっきり書いてあってアッ…ってなった。

まとめ

ユーザーインタビューにしてもMVPにしても、「どんな仮説を検証したいのか」ということがはっきりしていないと、それ自体が目的化してしまいそうなので気をつけたいと思った。リーンに開発していくぞ。

RubyエンジニアがGolangのどんなところに挫折して、どんな風に再挑戦したかという内容でLTをしてきた

LTしてきた

【Go言語LT大会! 「最近、Go言語始めました」の会】でLTしてきました go-beginners.connpass.com

speakerdeck.com

内容について

大体内容は前にブログで書いたような話で、 これからGolangを触る人向けに自分はこういうところで挫折した / 再挑戦してうまくいったよって話をした。

suzan2go.hatenablog.com

要約すると以下のような感じ

  • Golangで他のRuby(or 他のオブジェクト指向言語)のやり方を持ち込んでもうまくいかない事が多いよ
  • Golangの色んな先人の知見(ブログやGitHubソースコード)を参考にしたほうがいいよ
  • 書く量を少なくするためのハックよりも愚直に書いた方がいいコードになる気がするよ(個人の感想です)
  • 一度Golangの書き方に染まってみるときっと楽しくなってくるよ!

感想

  • インフラエンジニアっぽい人が多くて、アプリケーションエンジニアはあんまりいなかった印象でした(実際どうだったかは分からない)
  • Webアプリ作る時に参考にしたリンクが結構需要ありそうだったので、もうちょっとそっち方向でまとめればよかったなと思った。
  • ゲスト講演者のtenntennさんの標準パッケージ紹介が普通に勉強になった。Golangちょっと分かった気でいたけど標準パッケージでも全然知らないことの方が多かった。
  • 標準パッケージの内容読むの役に立つよって人が多かった。自分も読んでみようと思った。
  • 一緒に行った同僚の前職の後輩の人がいてビビった。更にびびったのはその人が自分のことを知っていてブログも読んでいるという事実。いぇーいXXXさん見てるー!?
  • 資料作っていると実は自分がよく分かっていないことが分かっていい。曖昧な知識で発表するのがアレだったので今回の発表内容は結構ふわっとした感じにしてしまったけど、次はもうちょっと突っ込んだ話をしていきたい。

現場からは以上です。

Railsでももっとカジュアルにapp/models配下にクラス作っていいんじゃないかなーと思っているんだけどどうなんでしょうか

Railsのプロジェクトやってると、app/models には ActiveRecord だけ、それ以外のオブジェクトは app/services とか app/forms層みたいなところに定義しないといけないと思っている人がそれなりに多い気がする。

個人的には app/models 配下に責務を分けたActiveRecordでないクラスを作っていくのはむしろ積極的にやるべきだと思っている。むしろそうしないとXX層みたいなものを導入したとしても、本来モデルの振る舞いとして表現されるべきものが手続き的に書かれてしまったり、新しく導入したXX層の処理がファットになっていってしまったりするのではなかろうか。(ActiveRecord のクラスと、そうじゃないプレーンなRubyクラスが app/models に交じるのが気持ち悪いという意見はまあ理解できるけど)

たとえば

たとえば以下のようなクラスがあったとする。

class User < ApplicationRecord
  def nanka_fukuzatu_na_shori
    if user.hoge?
       private_na_method_a
       private_na_method_c
    else
       private_na_method_b
    end
  end

  private

  def private_na_method_a
     # なんかの処理
  end


  def private_na_method_b
     # なんかの処理
  end


  def private_na_method_c
     # なんかの処理
  end
end

見るとnanka_fukuzatu_na_shoriprivate_na_method_a~c は明らかに関連をもつひとまとまりの処理なので、こいつらを実行する実態はUserクラスではないところにあっても良さそうな気がする。

これを User::NankaFukuzatsuNaShoriHandler を作って、そちらに責務を分けてみる

# app/models/user/nanka_fukuzatu_na_shori.rb
class User:: NankaFukuzatsuNaShoriHandler
  attr_reader :user

  def initialize(user:)
    @user = user
  end

  def perform
    if user.hoge?
       private_na_method_a
       private_na_method_c
    else
       private_na_method_b
    end
  end

  private

  def private_na_method_a
     # なんかの処理
  end


  def private_na_method_b
     # なんかの処理
  end


  def private_na_method_c
     # なんかの処理
  end
end

( nanka_fukuzatu_na_shori とかいう適当な名前で書き始めてしまったので User::NanakaFukuzatuNaShoriHandler#perform みたいにしちゃったけど、HandlerPerform みたいな抽象的な名前は避けたほうが良さそう)

Userクラスはこんな感じになる。

class User < ApplicationRecord
  def nanka_fukuzatu_na_shori
    nanka_fukuzatu_na_shori_handler.perform
  end

  private

  def nanka_fukuzatu_na_shori_handler
    @nanka_fukuzatsu_na_shori_handler ||= User::NankaFukuzatsuNaShoriHandler.new(user: user)
  end
end

基本的にはこんな感じで責務を分割していって、あるモデルの振る舞いとして定義するのが微妙なものだけそれこそXXX層みたいなの作ってやるのがいいんじゃないかと最近は思うんだけど、各社どうなっているんだろう。

  • Rails Wayから外れるので止めたほうがよい
  • Concern使えば?

みたいな意見はありそうかなと思っています。

参考文献

rubyblog.pro

qiita.com

あなたが成功したいならプライドを飲み込み、外に出ていって、自分が馬鹿に見えるのを恐れないようにしなければならない

最近(もう一ヶ月くらい前)、今更ながらソフトスキルズという本を読んだ。

SOFT SKILLS ソフトウェア開発者の人生マニュアル

SOFT SKILLS ソフトウェア開発者の人生マニュアル

この本場が話題になったのは去年の前半くらいだったと思うんだけど、買った後ちょっと読んで、忙しくなって積んでしまっていた。 あらためて読んだんだけど、タイトルにもした一文が自分的にはいい話だったのでブログにしておく。

あなたが成功したいならプライドを飲み込み、外に出ていって、自分が馬鹿に見えるのを恐れないようにしなければならない

結構自分は「自分をよく見せようとしすぎる」ところがあるなーと思っていて、そういう気持ちが何となくイベントにでて発表したりといったところに億劫になっていた気がする(あんまり失敗したくない・・・恥かきたくない的な気持ち)。

自分は影響されやすいので、この本を再度読み始めた直後に会社にお誘いのあったイベントに登壇してみることにした。 (以下が資料) speakerdeck.com

上記の資料はまあ正直フロントエンドガチ勢の人からするとそんなに参考にならないないようだった気がするし、 反省会というタイトルに引っ張られすぎて辛い内容を盛り込み過ぎたなぁと反省するところも多い。 あと結構当日までビビってて行きたくねーと回りに言いまくっていたりしたw

でもイベント終わったあと色々情報交換したいということで話に来てくれる人がいたり、 他の勉強会とかでお会いしたときに話掛けてくれる人がいたりして、今は登壇してよかったなーと思っている。 (Wantedly経由のお話しませんか的なやつの数も気持ち増えた)

【再掲】あなたが成功したいならプライドを飲み込み、外に出ていって、自分が馬鹿に見えるのを恐れないようにしなければならない

自分が成功しているとはまだとても言えないけど、外に出ていってみることで、色々分かることとか、広がるチャンス的なものがあることはかなり実感できた。今後もイベントがあったら登壇していきたい。とりあえず来週は、最近はじめたGo言語のイベントに出てみることにする。

最近Golangを触っている話

今更ながら趣味でGolangを触り始めた。家庭内アプリ用のAPIサーバとしてGolangを絶賛書いている。アプリはReact Nativeで書いていて、それはまた別の機会に書くことにしよう。

実は一年前くらいにもちょっと触っていて以下のような本を読みつつ、簡単なアプリケーションを作ろうとしていた。

Go言語によるWebアプリケーション開発

Go言語によるWebアプリケーション開発

スターティングGo言語 (CodeZine BOOKS)

スターティングGo言語 (CodeZine BOOKS)

が、ちょうど仕事が忙しくなる時期と重なってしまったり若干モチベーションが落ちてしまったので、最近まではRailsにずっぷりだった。

Golang楽しい

一年ぶりに触り直してるんだけどとても楽しい。前回多少学習していたという貯金が効いている説、この1年で自分が成長している説などあるけど、明らかに前回触ったときより楽しい。 具体的には以下の辺が。

  • gofmt、golint… などで書き方をかなり強制されるので迷わず書ける。
  • ので、どうロジックを書くかといった部分に集中できる。
  • フルスタックなWAFのようなものはないので、自分で色々設計について考えられる(考えなければいけない)
  • (これは完全に自分の個人的な感想)ちょっと書く行を減らすためのハックより、愚直に書くことが好ましい雰囲気があるきがしていて、愚直に書けばいいやーという気持ちになる
  • 「それ標準パッケージでできるよ?」といったマッチョな思想があるきがしていて、ベストプラクティスを追い求めなくてよい(と、いいつつ、 echogorm を使っているけど…)

ここからは静的言語ならどれでもそうなんですが

  • コンパイルが通れば、大体動くという安心感
  • エディタ上で型、引き数が補完されるので、一々リファレンス眺めなくてよい

SIでJavaやってたときも同じメリットはあったはずなんだけど、全然思い出せないし楽しいと思ったことあんまりないな。なぜだ。

なぜ一年前はあんまり楽しくなれなかったのか

たぶんGolangRubyっぽいことやろうとしていた。Golangにはクラスがなくて構造体しかない。で、構造体を利用して、オブジェクト志向っぽく書く方法はいくつかあるにはあるけど、Rubyと同じような作りで書けるわけではない。なのに一年前はRuby(というかRails)のような書き方をしようとして、色々調べた結果うまく書けずそこでやる気が失われてしまった部分はあると思う。

Goに入ればGoに従え

今回はアプリケーションを書き始める前に、GitHubでいくつかrepositoryを見てみたり、いくつかブログを読んだりして、みんなどんな書き方をしているのか見て回っていた。そのおかげで、Golangではどう書くのかーというところをある程度インップットできたと思う。GolangGolangらしく書くことで、楽しくなったきた気がする。

Golangからの学び

Golangで今更ながら型の有り難みを噛みしめるようになった。エディタの型補完や、コンパイルが通ったときの安心感とか。 型のある言語からRuby/Railsに来た人が「型がないのが怖い」的なことを言う理由がちょっと分かった。自分がJava => Ruby に行った時には型がなくて怖いなんてことは思わなかったんだけど何で今更こんな感覚を持っているんだろうな・・・。Golangで書くようになって、インターフェース的なものを前より意識してプログラミング書くようになった気がする。

React NativeでJS書くときもflowをちゃんと使うようになった(前は使っていたけど面倒になってやめてしまった・・)。ライブラリの選定も「これくらいなら自分で書けばいいかー」という思想になってきた。

まとめ

お気づきの通り、Goに入ればGoに従え を言いたかっただけの記事です

最近アプリケーションの設計するときに気をつけてること

最近、機能の設計をレビューしたり話し合ったりするときに、うん・・・?ってなることがあって、でも駄目な理由をうまく説明できなかったのでちゃんと言語化してみる。ちなみにRailsの話です。

DBには事実だけを記録するようにする

色々開発してきて思ったのは、テーブルに状態を持たせるようにするとあっという間に複雑度が増してしまうということ。 status カラムや hoge_flag みたいなカラムを持つこと自体は全然否定しないけど、本当にそれが最適なのかは慎重に考えた方がよいと思う。

これは例ですけど、会員申し込み => 何か審査 => 会員登録完了 みたいなフローのアプリケーションを作る時に、会員情報のテーブルを1つだけ作りstatusapproved_at みたいなカラムを突っ込んで、申し込み状態と申込み完了状態を アプリ側で頑張って判定しようとしている例はまれによくある。

こうすると何が辛いかというと、他のレコードから関連を辿って参照しようとしたときに常にレコードのカラムの状態を気にしないといけなくなってしまう。それに申し込み時の情報と、会員登録後に必要になる情報は必ずしも一致しないはずなので、作ったときは同じだとしても後々拡張するときに辛くなってくる。また、会員情報にDB上のユニーク制約をかけたくなっても掛けられないのでアプリケーションでかけるしかなくなる。(そしてアプリケーションで掛けた制約は結構簡単にすり抜ける…)

こういうときは事実が何なのかに着目すると、きれいに設計ができると思う。今回でいうと申込み というテーブルと 会員情報 というテーブル二つに分けてしまう。そうすれば上記にあげたような懸念はスッキリ解決する。 同じようなカラムが二つのテーブルに別れることを懸念するかもしれないけど、本来違うものを同じテーブルに押し込むことのデメリットの方が大きい。

同じような理由で論理削除もよく考えたほうがよいと最近は思っている。削除という状態を追加するよりも、素直にそのテーブルからデータは消してしまい、必要な情報だけ履歴的に別のテーブルにコピーしておいた方がアプリケーションをシンプルに保つ事ができるとおもう。

安易にHashを作らない

Rubyはダックタイピングなのでそんなに厳密にやってもしょうがない」みたいな話は一定理解するし、そういうゆるさがRubyのいいところだと思いつつも、巨大なHashを作ってそれを色んな所に引き回したりするのは結構最悪だと思うようになった。Hashに何が入っているか、何のkeyを持つべきなのか実装を全部追わないと分からないからだ。

そしてHashが巨大化していくると、そのHashを操作するための実装がそのHashを引き回す側に出てきたりしてあっという間に良くない感じになっていく。

何かを作る場合も、ハッシュではなく、クラスを作ってそこに attr_accessor を定義したほうがよいと思う。そうしておけば、クラスを見ればどんな値を持つべきなのかすぐに分かる。それに、値の中身を書き換えたり、デフォルト値を与えたり、変換したりといった処理をそのクラスに押し込めていくこともできる。

まとめ

最近考えたことをまとめてみた。定期的にこういうの考えて吐き出しておきたい。

メンターになって1on1をやることになったので「ヤフーの1on1」という本を読んだ

ヤフーの1on1という本を読みました。

ヤフーの1on1―――部下を成長させるコミュニケーションの技法

ヤフーの1on1―――部下を成長させるコミュニケーションの技法

何で買ったのか

新卒の子のメンターになって、1on1を週次ですることになったので。今までもマネージャーの人と1on1は普通にしていたけど、そもそもどうやってやるものなのか自分自身よく知らないなと思って買ってみた。

感想

ヤフーの宣伝的な要素が結構多いのかなーと思ったけど、中身はおもったよりも参考になった。1on1といっても組織によっても位置づけは当然異なるんだろうけど、相手に「自分で考えて学びを得てもらう」ことが大切っぽい。なので上司やメンティーの立場から、安易に相手の考えを否定したり、こちらから答えや意見を出してしまうのは基本的には望ましくない。相手に考えてもらい、自分で課題ややりたいことに気づいてもらうことが大切ということだった。

自分自身のこれまでの1on1を振り返って、「◯◯さんはどう思う?」みたいな質問を何度も返されることがあって、「いや、こっちはあなたの考えを知りたいんだけど・・・」と思うことが結構あったんだけど、それは今思えば自分で考えて答えを出して欲しい、みたいな思いもあったのかもしれない(確認したわけではないので違うかもしれない)。相手の意図はわからないけど、何というか自分で考えずに相手に委ねようとしていた部分があったなーと思ってちょっと反省した。

で、実際にやってみて

予想以上に、「相手に考えてもらう」ように会話を進めるのって難しい。これまで普通に話してるときは意識してなかったけど、結構相手の意見を聞く前に自分で意見を言ってしまったり、自分の思う答えを先に出してしまおうとしていたことに気がついた。

そして実際に相手に考えてもらうように1on1を進めていくと、「A」だと思っていたやりたいことは実は「B」だった、とか「C」が自分の課題と思っていたけど実は「D」の方が課題だった、みたいなことが結構クリアになってくる。コレは自分が「A」と聞いたときに、先輩目線で適当なこと伝えていたら出てこなかったことだと思うので素直に驚いた。

マネージメントみたいなこと、正直全然興味なかったんだけど、これはこれで結構面白いなーと思ったのでした。(1on1がマネジメントと言えるのかは分からないが…)