patorashのブログ

方向性はまだない

赤ちゃんの子育て中にあったらいいものリスト

注意:この記事はまだ書きかけですが、公開してます。随時更新予定です。

twitterのフォロワーさんたちで子供が生まれた人がチラホラおりましたので、短い育児経験ながら、子育て中にあったほうがいいものとか、これは買うのやめとけ!(別の買え!)というもののリストを作ってみようと思います。なお、これは私の主観が入っておりますので、ご了承ください。

買った方がいいもの

ベビーシート

まずオススメなのは、マムズキャリーです。これは車に乗る人のみになりますが、めちゃくちゃ重宝しますのでオススメです。

注意点としては、子供のサイズ的に1年間しか使えないのですが、1年しか使えないからと言ってベビーシートの選択肢から外すのは勿体無いです。むしろ1年後に他のチャイルドシート・ジュニアシートを買った方がいいと思います。

持ち運びできる

カゴのような構造なので、持ち運びできます。ちょっとした移動くらいだったら、ベビーカーに移して…とかしなくてもそのまま運べちゃう!うちでは、病院に行くときや外食するときはこのまま運んでます。外食の場合は、お座敷でも大丈夫な分、ベビーカーよりもいいかもしれません。

また、赤ちゃんが寝てしまっても、マムズキャリーを外してそのまま移動できるから、ほぼ起こしてしまう心配がありません。家に帰ってきても寝ていたら、そのまま家に運んで、起きるまで置いといてます。

最高にコスパいい

6,000円くらいで買えます。うちは西松屋で買いました。正直、ベビーシート、チャイルドシートってどれがいいのかすごく迷うし、しかも高いものはかなり高いです。これ買って1年間を過ごしている間に大いに迷ってそれから次のチャイルドシートを買うのがいいんじゃないか?と思います。私はチャイルドシートにもなるジュニアシートを買えばええんやで」という育児の先輩方のアドバイスに従って、そうしました。

抱っこ紐

抱っこ紐もいろんな種類というか、いろんなブランドがひしめき合っていて、さらに高い…。高いやつは確かにモノはいいのですが、比較しているとだんだんわからなくなってきます。最終的にうちはこれにしました。

コスパがいい!

1万円以下だけれど作りはしっかりしています!ホールド感もよく、安定性がしっかりしていて、他の有名ブランド品と遜色ないと思って決めました。

両手が使えるようになる

実はこれの前にもっと安い肩掛けの抱っこ紐を使っていたのですが、安定感がよくなくて、結局腕が自由に使えなくて困ったことがありました。

抱っこしていないと赤ちゃんが泣くときは、こういう抱っこ紐をつけて部屋を練り歩くというだけでも結構泣き止んでくれます。そういうときに両手が使えるってのは重要なことで、泣き止ませながら他のことができるわけです。私の場合は抱っこ紐をつけて部屋の中をウロウロしながら読書してます!

コードレスクリーナー

はっきり言っちゃうと、ダイソンのコードレスクリーナーがいいです。普通の掃除機にも使えるし、ハンディクリーナーにもなるし、吸引力はすごいので、他のハンディクリーナーを別で買うくらいなら、ダイソンでいいと思います。ダイソンならなんでもいいというわけではなく、オプションをなるべく多くつけて買いましょう。布団用とハンディ用は必須です。

サッと掃除できることが重要!

コードレスがいいのは、掃除したいところだけサッと掃除できることです。コード付きだと、やる気がたまらないとなかなかできません。赤ちゃんが寝る周辺だけ、布団用のヘッドでガーッと掃除して、他は気になるところをチョコチョコと…くらいでいいのです。

あと、成長してきて幼児用のおやつを与えるようになると、おやつの食べカスとかがそこら中に散らばります。そういうときにも、コードレスクリーナーはサッと掃除できるので助かります。

車の中も掃除できる

コードレスクリーナーの強みは、車の中も掃除できることです。チャイルドシートの周りは本当にめちゃくちゃおやつのカスだらけになります。そんなときにもダイソンのおかげで綺麗に掃除できています。

保温調理器

保温調理器は子育て世帯じゃなくてもオススメできますが、子育て世帯はマジであったほうがいいと思います。うちはシャトルシェフを使っています。あまりに便利なので、友人の赤ちゃん誕生祝いにシャトルシェフを贈ったほどです。

ずっと火の側にいなくてもいい

例えば、時間のかかる煮込み料理(カレーやおでんとか)を作る際は、焦げないようにするためにずっと鍋の側にいなければなりませんが、そうはいっても赤ちゃんが寝返りしだすと、ちゃんと呼吸できているか見ないと危険です。なのであんまり長時間台所に立つのは難しいところですが、保温調理器は材料を入れて沸騰したら密閉するだけであとは放ったらかしにできるので、赤ちゃんの側にいられる時間が増えます。

それに、なんといっても時間が作れるところがいいです。昼食作りのときに夕食分の材料も一緒に切っておいて、煮込んで放置しておけば、それが夕食になるので、夕食作りの時間がカットできます。子育て中はいかに自分の時間を確保するかが大事なので、料理にかかる時間が減らせるのはいいことです。

ちなみに、長時間煮込む際にかかるガス代や電気代(IHの場合)もかからなくなるので、長期間で考えると家計にも優しいです。

離乳食作りに最適

うちは子供の離乳食用のお粥を作るときにシャトルシェフが本当に、本当に、大活躍しました。離乳食のお粥は、まずは10倍粥、次に5倍粥、次に3倍粥…のように、徐々にお粥の濃度を濃くしていきます。しかし、水分が飛びすぎたり焦げたりして本当に難しいです。そんなとき、シャトルシェフで沸騰してから放置しておけば、水分が飛びすぎたり、焦げる心配が一切ありません。特に、焦げは保温後に加熱してないのだから、絶対に焦げません。シャトルシェフでお粥を大量に作って、冷凍保存はよくやっていました。

また、他の離乳食でも同様に使えます。離乳食は柔らかめにしないといけないので、長時間煮込まなければなりません。このときも、沸騰したら保温調理器に入れて30分〜1時間放置。これで柔らかい離乳食ができます。

保温調理器は台所のルンバ的存在

ルンバは自動お掃除ロボットですが、これは別に時短にはなりませんが、自動でお掃除してくれますね。シャトルシェフも同様、時短にはなりませんが、自動で調理してくれる、そんな存在です。ルンバはそこそこなお値段しますが、シャトルシェフは大きさにもよりますが1万円以下で買えます。1万円程度で調理にかかる時間を大幅に削減でき、かつ煮込み料理が美味しくでき、しかも光熱費が減らせるので、一石三鳥ですよ!

続きはまた後で

時間ができたらまた書いていきますのでお楽しみに。

Railsのエラー画面の謎挙動にハマッた

Railsのcontrollerで、トランザクションを使っているところで、rescueブロックの処理が書いてあるのにそこに辿り着けていない現象に遭遇しました。

悩んでいることをチャットワークに書いたら、同僚の @kazuhisa1976 さんが、小さいRailsアプリを作って検証してくれたのですが、そこで面白い挙動が見つかりました。

検証環境を作る

小さいRailsアプリを作る

まず、小さいRailsアプリを作ります。

rails new sample
cd sample
bin/rails g scaffold User name:string
bin/rails db:migrate

Userモデルにvalidationを加えます。

class User < ApplicationRecord
  validates :name, presence: true
end

UsersController#createで、検証のためにトランザクションを使ってみます。保存に失敗したら、root_pathにリダイレクトするという設定です。

class UsersController < ApplicationController
  # 省略
  def create
    @user = User.new(user_params)
    ActiveRecord::Base.transaction do
      @user.save!
    end
    redirect_to @user, notice: 'User was successfully created.'
  rescue => e
    redirect_to root_path
  end
  # 省略
end

Railsアプリを起動しておきます。

bin/rails s

これで、とりあえずの検証環境は出来上がりました。

検証する

正常系

まずは、nameを入力して投稿してみます。

f:id:patorash:20180519084703p:plain

当然ながら成功。

f:id:patorash:20180519084744p:plain

異常系

次は、nameを何も入力せずに投稿してみます。nameが空なので、@user.save!が失敗して、root_pathにリダイレクトされるはずです。

f:id:patorash:20180519084635p:plain

おおっと!リダイレクトされませんでした!rescueブロックに辿りつかずに、@user.save!ActiveRecord::RecordInvalidが発生していると言われました。私が遭遇した現象と全く同じ!

f:id:patorash:20180519084959p:plain

原因を探る

エラー画面のWebコンソールで、実験してみましょう。

f:id:patorash:20180519085705p:plain

はい。実はこのRailsアプリには、root_pathが定義されてません。それが原因です。例外の情報が入っている変数eもあることから、rescueブロックには実は辿りついています。

そうなんです。rescueブロックで発生したエラーの原因を表示せず、元の例外が発生した原因を表示してしまうということです。

修正する

このRailsアプリでいえば、routes.rbでroot_pathを定義してあげれば、直ります。

Rails.application.routes.draw do
  resources :users
  root to: 'users#index' # root_pathを定義
end

まとめ

rescueブロックで例外が発生すると、大元の例外の情報を基にエラー画面が作られてしまうので、rescueブロックに辿り着けないようなエラー画面が表示されたら、rescueブロック内にブレイクポイントを置いて1つ1つ検証していくのがいいです。恐らく、今回と同様に変数かメソッドの定義がないなどが原因です。

自分のエラーの原因も、メソッドがないことが原因でした。 作った当初はRails3か4くらいで、paramsがHashを継承していたのですが、Rails5にアップグレードして(今使ってるのは5.1.4)Hash継承ではなくActionController::Parametersになった影響で、mapメソッドがなくなっていました。

似たようなコードを書くと、以下のような感じ。

# users_paramsはfields_forで作られた配列のデータ
def update
  ActiveRecord::Base.transaction do
    users_params.each do |id, values|
      user = User.find id
      user.assign_attributes values
      user.save!
    end
  end
  redirect_to users_path
rescue => e
  @users = users_params.map do |id, values| # ここでundefined method
    user = User.find id
    user.assign_attributes values
    user.valid?
    user
  end
  render :edit
end

参考情報はこちら。

qiita.com

そこで、以下のように修正。

rescue => e
  @users = users_params.to_h.map do |id, values| # to_hメソッドを挟む
    # 略
  end
  render :edit
end

今回は管理画面側のため、網羅的にテストを書いていなかったことが気づけなかった原因だったので、例外時のテストも追加しておこうと思います。

仮説の検証の仕方が確認できた

GWにブックオフで買ってきた本の1冊。アウトプットの質を高めるとあったので、買った。がむしゃらにアウトプットしていてもなかなか質は上がらないよなぁ〜という気持ちだったので、ちょうどよかった。

アウトプットの質を高める 仮説検証力

アウトプットの質を高める 仮説検証力

仮説を立てる際に心がけたいこと

ついついテクニックに走りがちになるらしいのだけれど、とりあえずたくさんのデータがあればなんかわかるだろう…みたいな感じだとよくない。

目的を明確にする

なんのために仮説を立てるのかをはっきりしておかないと意味がない。無意味な計算を繰り返す羽目になる。

仮説の精度は準備で決まる

しっかりとしたデータの整理などをしておけば、おのずと精度は上がる。時間がかかりやすいところではあるけれど、不十分なデータで仮説を立て始めるほうが、時間を浪費する。

周囲と同じ仮説を出していては意味がない

ある程度の傾向が出てくると、みんな似たような仮説を立てるけれど、同じ仮説を立てて安心していてはいけない、と書いてあった。「自分ならではの仮説が立てられないようでは、新しい価値を生み出せない」というメッセージに、確かになぁ〜!と思わされた。誰でも立てられるような仮説は機械学習がやってくれるようになるだろうし、オリジナルの視点を持つことが人間の価値を高めることになりそう。

仮説の検証法は2種類

仮説の検証法は以下の2種類あるとのこと。

  1. 実験型検証
  2. 裏付け補強型検証

仮説は実験して検証するものという認識が強かったので1の実験型検証が普通かと思っていた。PDCAのDとCに当たるものだ。しかし、実験を行うのは時間的なコストや金銭的なコストがかかるので何度も行うのが難しいものが多い。

裏付け補強型検証は、PDCAのPに当たるもので、仮説の精度を高めようというものだ。仮説の精度が高くなければ、結果の要因があやふやになりやすい。

本の中では、例え話で、旅行の計画が順当なものかを検証するようなものと書かれていた。無謀なスケジュールを立ててしまったら旅行に支障が出るため、前もって情報を集め(移動時間は正しいか、美術館はその時間で回れるのか等)本当にそのプランで旅行できるかを検証しようということだ。

定量データと定性データ

仮説を立てるには、まず裏付けとなるデータが必要になる。そのデータは

  • 数値化できる定量データ
  • 数値化できない定性データ

である。

定量データは、来客数とか売上高、市場シェアなど。定性データは、アンケート結果など。基本的にどちらか一方だけではダメで、両方を使っていく模様。

定量データから仮説を立てるには?

まずは必要なデータだけに絞り込むことが大事という。とにかくデータを集めればいいというものではない。このあたり、機械学習の本でも同じことが書いてあった。まぁ機械学習もデータを元に傾向を見て仮説を立てて、インプットが仮説の通りかを検証してアウトプットするものだもんなーと思った。

仮説を立てる前にすること
  • 集約
    • MECE(漏れなくダブりなく、データを分類する)
    • 因数分解(足し算・引き算・掛け算・割り算)
  • 指標化(比較する際に必要)
比較する際に気をつけること

どう比較するか(HOW)、何と比較するか(WHAT)をちゃんと意識すること。

どう比較するか
時系列比較
時系列の比較は基本中の基本。昨年度との売上の比較など。
自分なりに設定した基準と比較
昨年度の売上の110%を基準として、それとの比較など。
外部の比較対象との比較
同業者の売上の伸び方との比較やシェアの比較など。ベンチマーク
何と比較するか
目的に沿ったデータと比較
分析の目的に合ってないデータだったら、比較する意味がない。どういう意図で作られたデータかが大事。
できるだけ同じものと比較
これは、外部の比較対象との比較のところの話。実力差や規模の差がありすぎるものと比較しても、意味のある仮説はなかなか立てられない。同規模で調子がいいもの、同期や1つ上と先輩などをベンチマークとするとよい
数値自体には意味がない

例えば、シェアが13%、みたいな数値があったとして、ここから何が読み解けるかというと、何もわからない。数値は他者や、時系列での過去との比較を行わないと意味がなく、また、比較して読み取れる傾向などが見えて、初めて意味が出てくる。データ比較で使われている縦軸・横軸に注目する。

定性データから仮説を立てるには?

定性データは準備が9割。記事やアンケートなどの定性データは分析にはそのまま使わない。ちゃんと下ごしらえを行うこと。定性データ同士で共通点や相違点を整理する。

定性データには特性がある

例えば、アンケートでいえば、回答者の年齢、性別、職業、身長、体重、趣味などがわかれば、それらで切り分けることができる。それらを特性という。本の中では、新作弁当のアンケートでは男女での違いがあった。男性は「ボリュームが少ない」、女性は「量がちょうどいい」など。これらを特性なしで判断すると、どっちが正しいかわからなくなる。お弁当のターゲットを男性にするか、女性にするかなどの判断材料となる。

アンケートなどのヒアリングを行った際の回答は、定性的データで、回答者の主観が入ってるので網羅的ではなかったりするのだけれど、アンケートも数があれば共通部分がでてきたり、回答者の属性で分類できたりする。

データの意味を浮かび上がらせるように整理する

データを整理して満足になってしまいがち。目的は整理したデータから意味を読み取ること。

定性的なデータの比較

意識するところは3つ。

比較対象としているデータは仮説を立てる目的に合っているものか?
漠然と比較しない
特性ベースで比較する
特性ごとの共通点・相違点を見つけていくことで方向性が生まれる。
意味を読み取る
  1. 全体の共通点から意味を読み取る
  2. 一部の共通点から意味を読み取る
  3. 意外な相違点を捉える

読み取ったら、一言でまとめてみるのがいいらしい。

定量データと定性データを組み合わせて仮説を立てる

どちらも使っていく。定量データで全体的な傾向をつかみ、掘り下げていくときに定性データを使っていく。定量データで見られた傾向に、定性データで肉付けを行っていき、仮説をより強固なものにしていく。

事例では、X社の代理店の売上の推移(定量データ)と、代理店の担当者とX社の営業へのヒアリング(定性データ)が使われていた。定性データの特性は、代理店の規模感と、代理店におけるX社製品の売上成長率・シェアなどなど。この事例での定量データ、定性データのまとめ方は非常に参考になるなと感じた。

裏付け補強型検証

裏付け補強型検証は上のほうでも説明したのだけれど、実験しにくい仮説の精度をまず上げるために行う。 裏付けのない仮説は仮説ではない。単なる思いつき。

仮説の精度を確認する
  • そもそも言いたいことがあるか
  • 目的・問題意識に沿ったものか
  • 漠然とした内容になっていないか(精度の高い仮説は具体性が命)
  • 裏付けの精度はどうか(量・偏り・信頼性)
補強するべきポイントを明らかにする
なにが不足しているか、偏りがあるか、など。具体的に。
入手するべきデータを明確化する
定量データ、定性データの構造化を行い、欲しいデータを定義する。
データを入手する
  • 入手したいデータを考える
  • 具体的な入手方法を考える
  • 代替案を考えておく
入手したデータで補強して仮説の精度を高める
仮説の修正を行う。

どこまで検証を進めるか

際限のないことなので、時間を区切って進めるか、インパクトのある仮説ならば満足する精度だと思うまでやる。

実験型検証

試行錯誤の検証はこちら。実験型検証は日々、みんながやっていることと同じ。しかし、「これで失敗したから同じ失敗はしないようにしよう」みたいなレベルに止まることが多いので、もう一段階高い視点を持っておく。

実際に行う場合に気をつけること

自分なりのこだわりを持つ

仮説の中でも、ここに注意してみよう、これを意識した行動をしてみようなど、具体的な違いを作っておくと後で検証しやすい。

結果だけでなくプロセスを考慮する

結果だけにフォーカスすると、ただ運が良かっただけなのに勘違いしてしまうことが多い。重要なのは再現性があることなので、プロセスが大事。なので、その仮説が成立するプロセスを具体的にイメージしておくことが大切。上の「自分なりのこだわりをもつ」ところは、このプロセスの中で意識することになるのだろう。

プロセスの中にこそ、改善点が埋もれている。

結果の検証

問題点が解消したかどうか
前より改善したのか、そうでもなかったのか。
実験による副作用はどうか
何かをするということは、他のことが起きる。Aが売れた結果、Bが売れなくなった等。
目的の達成度はどうか
問題点が解決しても目的が達成されない場合もある。(Aが売れなかったという問題は解消されたが、Bが売れなくなって目的の売上アップはできなかった等)

実験を繰り返す

  • 実際に効果があるのかを確認
  • なんども行うことで傾向を見る

異なる実験を行う

  • 目的は変えないこと!
  • 意図を明確に変える
    • どの観点に効果がある、ないかを掴むことができる
  • 現状や以前の実験との違い・差分を意識する
    • 同時に複数のものを変えないこと
      • 何が原因かわからなくなるから

うまくいった(いかなかった)要因を把握する

プロセスを具体的にイメージして実験したとしても、うまくいく場合とうまくいかない場合がある。期待したプロセス通りに物事が運ばなかった場合もある。そのあたりの要因を把握する。

  • 他の要因を探る
    • たまたまうまくいった場合
      • 当日イベントが近所であってお客さんが多かった等
      • 景気がよくなってきていた等
    • 逆もしかり。たまたまうまくいかなかった場合
  • 改善ポイントを掴む
    • 次に似たようなことをするときに活かせる

要因の捉え方

  • 自分の立てた仮説は正しかったか
  • 想定通りに仮説を実行できたか
  • 裏付けに見落としはなかったか
    • 責任を自分のせいにして変にいじけないこと
      • 想定外のことは起きる時は起きる
      • 誰だって見落とすことはある
  • 他の要因はなかったか
    • コントロールできる要因
      • 情報の共有など(連絡していれば防げたこと等)
    • コントロールできない要因
      • 天候・集客など

実験結果を活用する

実験結果がうまくいった場合は、似たような場面があれば精度を向上させることができる。他の仮説にも応用できるところを探していく。仮説自体の応用や、プロセスや考え方を応用するなど。

うまくいかなかった場合は、改善ポイントを探して、他の仮説に活かすことができる。

感想

検証といえばPDCAのC(Check)だろうと思っていたのだが、裏付け補強型検証でPの段階でもやるもんだとわかったのがよかった。たぶん、普段から知らず知らずのままやっていたとは思うけれど、とりあえずDoしちゃおうぜ!みたいなことは結構あったと思う。回転速度の早いPDCAならそれでも振り返りできるのでいいのだろうけれど、AIや機械学習の技術が一般化してくると、Pの裏付けが今後は大事になっていくと思う。

また、成功体験が運が良かっただけなのに勘違いしてしまうというのは本で読んだことがあるが、それもちゃんと考慮してプロセスが期待通りだったか、他の要因はなかったかを検証するという視点が書かれているのはよかったと思う。逆もしかりで、たまたま運が悪かっただけというのもあるけれど、運だったのか、計画が杜撰だったのか、その辺りはちゃんと裏付けしていかないといけない。

本のまとめみたいな記事になってしまったが、自分の中でフワッとやっていたことなので要点を整理しようとしただけで長くなってしまった。仮説はアップデートできるし、ブログ記事もアップデートできるので発見があったら更新しとこうと思う。

部分インデックスでミスった話

新たにカラムを追加することになり、その条件が

  • Null許可
  • ユニークであること
  • ただし論理削除を考慮する

となったので、アーハイハイ、部分インデックスですねと思って設定していて、テストもしていたのだけれど、考慮漏れがあったので自戒を込めて書いておきます。

部分インデックスとは

インデックスの条件にwhere句を使うことができるやつです。

よくあるパターンでは、メールアドレスで登録されたユーザーがユニークになるようにしてあるけれど、論理削除を考慮する場合などで使われたり、上位500件のデータのみにインデックスを貼りたいとか、そういうときに使います。

-- 論理削除されていないユーザーでメールアドレスがユニークであること
CREATE UNIQUE INDEX
  email_idx_deleted_at
ON users(email)
WHERE deleted_at IS NULL;

これってemailカラムは普通NOT NULL制約があるので通常はこれでも大体いけますし、Railsのバリデーションでもvalidates :email, presence: trueにしているので、空文字が入ることはありませんでした。

そう、空文字です。

空文字によるエラー

先ほどの条件のカラムをtokenという名前のカラムとします。最初は全く同じ条件で部分インデックスを定義していました。

CREATE UNIQUE INDEX
  token_idx_deleted_at
ON users(token)
WHERE deleted_at IS NULL;

Railsのバリデーションの条件は、以下の通り。

validates :token, allow_blank: true, uniqueness: { scope: :deleted_at }

これで大丈夫かなと思っていたのですが、フォームから空文字が送られてきていて、tokenが空文字のデータが2つ入ることができずにエラーが発生。

テストでは重複NGなことと、論理削除済みならば重複OKであることなどは検証していたのですが、空文字の考慮が抜けていました…。

空文字をOKにする

一通りどうしようか悩みました。

  1. フォームから空文字がきたらparams[:user][:token]を削除する
  2. 空文字を登録できるように部分インデックスを修正する

1で行こうかとも思ったのですが、SQLで直接空文字を入れられたら同じことが起きるので、2のほうを選びました。

CREATE UNIQUE INDEX
  token_idx_deleted_at
ON users(token)
WHERE
  deleted_at IS NULL
  AND
  token != '';

今後は気をつけようと思います。

オープンセミナー岡山2018に参加してきた

5月12日(土)に開催されたオープンセミナー岡山2018に参加してきました。

okayama.open-seminar.org

今回のテーマは「エンジニアの生存戦略と働き方」で、どういう現場で働いている方であろうと参考になりそうなテーマです。

当日のツイートはtogetterに纏められています。

togetter.com

共通していると感じたこと

だいたいの講演者の方の生存戦略として共通していたことは、「自分を売り込むこと」をちゃんとしていることだったと思います。

ソニックガーデンの@jnchitoさんの場合は、「オブジェクト志向をやってます!」とアピールしたことで、そういう案件にアサインされたことや、転職の際に読んだ本のリストを作ってアピールすることで勉強熱心さを伝えていました。

NHN Japanの@S_O_F_Scienceさんの場合も、資格を取りまくってアピールし、他の社員と比較されたときに目立つ点を作っていたこと。

イーネットワークスの@maeponさんも「何か手伝いますよ」というところから登壇し、そこから「頼んだらやってくれる人」になっていったこと。

@llminatollさんの場合は、SNSでのテストマーケティング自体が調査だけでなく、自分を売り込むことにつながっています。

GitHub@ikeike443さんの場合は、GitHubの求人が出たときに、日本の商習慣に詳しい自分は必ずGitHubに貢献できると、英語がしゃべれないけれど猛アピールして、英語が喋れないGithubberとしてジョインされたと言われていました。

農業を始めたひらさんも、他の農家さんと話すことでノウハウを得たり、土地を借りたり農業機械を譲ってもらったりというのは、売り込んだ結果だと思います。

ただアウトプットするだけでなく、戦略的に他者にそれを気づいてもらえるようにして、勝ち取っているわけです。

与えることで生まれる好循環

与えること(アウトプットすること)で何が生まれるか?それは信頼です。@maeponさんの言葉を借りると、「知ってもらうだけじゃダメ、『これを頼める人』になる」ということです。

「頼める人」になれば、そのコネクションを活かして仕事や執筆の依頼がくるようになるわけですね。@maeponさんや@llminatollさん、@jnchitoさんもそれが執筆につながったのだと思います。

生きろ!好きを守れ!

これもまた結構共通してたと思います。要はワークライフバランスとかの話ではあるかと思うのですが、自分というリソースを消費しすぎると体を壊しますし、家族やチームにも迷惑をかけることになりますし、なにより自分が楽しくない。優先順位をつけて、身の丈にあった継続性を守ることで、自分の「好き」を守りつつ取り組むことができます。ひらさんの話(農業)でも規模拡大をして様子を見た後、縮退することで身の丈を知ると言われてました。

@maeponさんは転職の際、元々はフリーランスになるつもりだったけれど、個人活動を認めてくれるという条件で入社したことで、「好き」を守りつつ、「好き」を仕事に活かしてます。

@llminatollさんはWebデザインと絵と教育に対する情熱とのスキルミックスで「好き」を活かす道を見つけてます。

@ikeike443さんは、ソフトウェア化している現代社会において、エンジニアのできることが広がっている=エンジニアには幅広い選択肢が広がっているといいます。ひらさんが言われていた、「仕事は嫌でなければなんでもいい。好きを守れ」というふうに考えると、いろんな業種への転職でも、エンジニアの経験はどこでも活用できるかと思います。

まずやってみる、の前に

やってみるという行動力は重要だけれど、その前にまず3C分析と言われていたのが@llminatollさん。勢いで記事にしてみたものの、思ったより反応が悪かったりしたので、3C分析とテストマーケティングをするようにしているそうです。

キャッチアップはどのくらいか?

記事を書くだけでなく、技術のキャッチアップにも同様のことが言えそうです。@jnchitoさんも、全ては追いきれないのでしばらくは様子を見る、楽しくないと続かないし身に付かないと言われてました。これは本当にそうだなと思います。とりあえずやってみた系のやつ、すぐ忘れてしまうので…。

ただ、特定の技術で突出したい!ほとんどまたやっている人がいないからこれでテッペンをとるんだ!というときには(先行者利益を目指すということ)、分析してもしょうがないかなと思います。

@jnchitoさんのあのラジオのお便りコーナーみたいなの、面白かったのでまたやってもらいたいですね。いろんな人のバージョンで見てみたい(聞いてみたい?)です。

とはいえ、やってみるのも大事

謝罪ファーストでブログにできそうなら行動してしまうというClassMethodの@kongmingtrapさんの話も面白かったです。福岡からスターエンジニアを輩出したい!という目的でどんどんイベントを開催してエンジニア発掘の機会を作っているというアグレッシブさは見習いたいところです。

生存戦略の指標

@jnchitoさんが「基本戦略を考える」で言われていた「評価基準を社外に置く」で、

  • 社外でも通用するか
  • 5年後でもやっていけるか
  • いざというときにそれを証明できるか

というのは、エンジニアであれば意識しておきたいところです。

社内での評価のみだと「井の中の蛙」になりかねず、社外ばかりに目をやるのは組織の一員としてちゃんと会社とその顧客に貢献できているのか?という点においてよくないことだと思います。

スキルミックスを意識する

@llminatollさんと@ikeike443さんが言われていたスキルミックスにより希少価値を高めることは、そのまま自分の市場価値を高めることにつながっていること思います。生存戦略において、今のスキルでミックスできないか?を考えることと、5年後を見据えてスキルを身につけていくというのも戦略的に使えると思いました。

まとめ

生きろ!

現在、自分は育児休業中で、家事・育児をしつつ多少の仕事をするという日々を送っているので、@jnchitoさんの仕事と家族サービスのバランスを考えるというあたりの話は本当に共感でした。最近は自分も朝活するようにしています(時々二度寝しますが)。

今回は運良くじゃんけん大会で勝って、チーム開発実践入門 ~共同作業を円滑に行うツール・メソッド (WEB+DB PRESS plus)をいただきました!読んで勉強したいと思います!

とてもいいセミナーで参考になりました。講演者の皆さま、そしてオープンセミナー岡山のスタッフの皆さま、ありがとうございました。 f:id:patorash:20180512181033j:plain

最後に

オープンセミナー岡山2018は、私が所属している株式会社リゾームがプラチナスポンサーをしていました。

www.rhizome-e.com

今回はスポンサーセッションで弊社代表の中山が講演しましたが、弊社は仲間を募集しております。私が所属しているグループはRuby on Railsで自社サービスの開発を行っていますが、講演でも言っていたようにMicrosoft系の技術を活用しているチームもありますので、もし弊社にご興味がある方は以下のGreenのサイトからご連絡ください!

https://www.green-japan.com/job/58045?case=login

もしくは、SNS経由で弊社の社員まで連絡してくださっても構いません。よろしくお願いします!

月毎の累計を行うクエリ

先日、年毎の累計を行うクエリについての記事を書きました。

patorash.hatenablog.com

すると、「月毎のデータも欲しいです」と言われたため、そちらもやってみました。

集計関数を使うと月のデータが歯抜けになる問題

前回のクエリを改修すればすぐできるだろうと思っていたのですが、月毎で集計すると、データの登録が全くない月などもありまして、歯抜けのデータが作られました。以下のような感じ。

SELECT 
  date_trunc('month', created_at)::date AS "月",
  COUNT(*) AS "月間登録数"
FROM foos
GROUP BY date_trunc('month', created_at)::date
ORDER BY "月" ASC;
月間登録数
2013-06-01 10
2013-08-01 10
2013-09-01 10
2013-11-01 10
2013-12-01 10

2013-07-01と2013-10-01が抜けてます…。これでは欲しいデータになりません。

月データを生成する

Postgresqlには、generate_seriesという便利な関数があるので、これを利用して基準の月データを作ってみましょう。

SELECT
  generate_series('2013-06-01','2013-12-01', '1 month'::interval)::date AS month
ORDER BY month ASC;

結果は以下の通り。

2013-06-01
2013-07-01
2013-08-01
2013-09-01
2013-10-01
2013-11-01
2013-12-01

これに対して、JOINしていきます。

基準の月データに対してJOINする

あとは前回と同様、対象月以前のデータを連結するという条件でJOINします。

SELECT
  months.month AS "月",
  SUM(foos.created_count) AS "累計登録数"
FROM (
  SELECT
    generate_series('2013-06-01','2013-12-01', '1 month'::interval)::date AS month
) months
LEFT OUTER JOIN (
  SELECT 
    date_trunc('month', created_at)::date AS month,
    COUNT(*) AS created_count
  FROM foos
  GROUP BY date_trunc('month', created_at)::date
) foos ON months.month >= foos.month
GROUP BY months.month
ORDER BY months.month ASC

結果は以下の通り。

累計登録数
2013-06-01 10
2013-07-01 10
2013-08-01 20
2013-09-01 30
2013- 10-01 30
2013-11-01 40
2013-12-01 50

集計関数を使うと歯抜けになりがちなデータも、これでバッチリですね!

年毎の累計を行うクエリ

担当しているサービスのマスタデータにて、年毎にどれ位の登録数が増えていっていたかを見たいと言われたのでSQLを組んでみたのだが、なかなか思いつかなかったのでメモを残しときます。

年毎の累計とは

以下のような感じで、年間登録数と、累計登録数を使いたいという場合の話です。

年間登録数 累計登録数
2013 100 100
2014 100 200
2015 100 300
2016 100 400
2017 100 500
2018 100 600

年毎の登録数を出す

年間登録数はサクッとGROUP BY date_part('year', created_at)で出せます。

SELECT 
  date_part('year', created_at) AS "年",
  COUNT(*) AS "年間登録数"
FROM foos
GROUP BY date_part('year', created_at)
ORDER BY "年" ASC;
年間登録数
2013 100
2014 100
2015 100
2016 100
2017 100
2018 100

ここで、累計どうすればええんや…と悩んでしまいました。

過去のデータをJOINせよ!

まずは、全く同じデータをLEFT OUTER JOINして、条件にA.year >= B.yearとします。 Postgresqlgenerate_series関数を使って、年を生成し、そこに先ほどのデータをINNER JOINして、条件にA.year >= B.yearとします。

SELECT
  A.year AS "A.年",
  B.year AS "B.年",
  B.created_count AS "B.年間登録数",
FROM(
  SELECT generate_series(2013,2018) AS year
) A
INNER JOIN (
  SELECT 
    date_part('year', created_at) AS year,
    COUNT(*) AS created_count
  FROM foos
  GROUP BY date_part('year', created_at)
)  B ON A.year >= B.year
ORDER BY A.year ASC

すると、以下のような感じに…。

A.年 B.年 B.年間登録数
2013 2013 100
2014 2013 100
2014 2014 100
2015 2013 100
2015 2014 100
2015 2015 100
2016 2013 100
2016 2014 100
2016 2015 100
2016 2016 100
2017 2013 100
2017 2014 100
2017 2015 100
2017 2016 100
2017 2017 100
2018 2013 100
2018 2014 100
2018 2015 100
2018 2016 100
2018 2017 100
2018 2018 100

基準の年(A.year)以前の年のデータを全てINNER JOINで連結します。 あとは、GROUP BY A.yearを行い、B.年間登録数をSUMで集計すればOK!

以下が、完成形のSQLです。無駄なSELECTなどは削除してます。

SELECT
  A.year AS "年",
  SUM(B.created_count) AS "累計登録数"
FROM (
  SELECT generate_series(2013,2018) AS year
) A
INNER JOIN (
  SELECT 
    date_part('year', created_at) AS year,
    COUNT(*) AS created_count
  FROM foos
  GROUP BY date_part('year', created_at)
) B ON A.year >= B.year
GROUP BY A.year
ORDER BY A.year ASC

これで、累計データが取れました。

累計登録数
2013 100
2014 200
2015 300
2016 400
2017 500
2018 600

晩御飯を食べてる時に、妻に相談したら、ヒントになる話が得られたので、助かりました。

2018-05-11 追記

Postgresqlgenerate_seriesで年を生成すると、万が一その年のデータが存在しない場合にも歯抜けにならなくて済むのでそうしました。