susunshunのお粗末な記録

お粗末に丁寧に生きる

エンジニアだけで企画・開発・分析全てを遂行するチームを立ち上げた話

この記事はRecruit Engineers Advent Calendar 2018 - 13日目の記事です。

前書き

本記事は個人的な見解を示したものであり、所属する組織を代表するものではありません。内容には留意しておりますが、もし不適切な内容や誤りがあれば、私個人当てにご指摘のコメントをいただけますと幸いです。

超概要

  • カットオーバーから数年経ったtoCサービスにおいて、エンジニアオンリーのチームで企画・開発・分析、プロダクト改善のサイクル全てを担うチームの立ち上げを行いました
  • 開発しか知らない僕らがよりよい価値を世に届けるために、企画や分析方面への染み出しを行う中での泥臭い取り組みや、やってみて分かった知見を共有します
  • 経験ベースで築いてきた知見なので、理論を踏まえてなかったり、原理原則とは乖離する箇所もあるかと思いますが、温かい目で見守ってくださると幸いです

話さないこと

KPIを爆改善して圧倒的成果を挙げた話

話すこと

事業をグロースさせるための、仮説検証プロセスの装着を地道に、泥臭く行ってきた話

目次

仮説検証チームの爆誕

企画・開発・分析全てを担うチームとは

私が担当しているプロダクトはカットオーバーから数年が経過し、そこそこのユーザー数を抱えています。

これまでは、競合と対比して明らかに不足している(競合劣位となっている)機能の装着をメインとしてきたものの、競合との大きな差分が無くなったいま「これから何を目指すべきか」「どのような価値をユーザーへ提供していくか」を模索している段階でした。

そのような背景の下、「何が正解なのか」「どこがサービスのボトルネックなのか」に対する答えが無い中で、エンジニアオンリーのチームで仮設検証を高速で回し、プロダクトの磨き込みを行うことを目的に、チームが爆誕しました。

おっしゃ!やったるぞ!!という息巻いたものの、ここから多くの課題と向き合い、時には泥臭い取り組みをしつつ、チーム自体の改善を重ねていくことになります。。。

そもそも僕らはエンジニアである

最初に集まった3人は多少経歴の差異はあるものの、皆開発を生業としてきたエンジニアです。 そこで2つの課題が浮上しました。

その1:まず開発以外のことが分からない
  • 仮説を立案し、コードとしてデプロイすることで世に放ち、その仮説をどのように評価するのか、まるで分からない
  • なぜなら僕らは開発しかやってこなかったのだから
その2:そもそも権限委譲されない
  • 開発チームがいる一方で、企画やプロデューサー等、プロダクト改善を担ってる先人達がもちろんいる
  • いきなり以下のようにはならない
    • ワイ「自分で施策考えて開発して仮説検証回していきたいぞい!!!」
    • 偉い人「OK!!!!!!!!」
  • なぜなら僕らには開発スコープ以外の実績が無い。実績もなければ信頼もない

これらの課題にまずは取り組んでいくことになります。

仮設検証型チーム構築のSTEP

BMLプロセス

仮説検証という表現をここまで使ってきましたが、実際にはBML(Build-Measure-Learn)のプロセスを意識してプロセスの改善を行ってきました。以降、BMLになぞらえて話を進めていきます。 ここでは詳細な説明は割愛させていただきますが、 雑にWikipediaのリンクを貼っときます。 Lean startup - Wikipedia

気になる方はリーン・スタートアップあたりを読むと良いかもしれません。 amzn.asia

段階的なプロセスの磨き込み

開発以外ド素人な僕らが立派にBMLを回していくために、以下のような段取りでプロセスの磨き込みや、知見の獲得をしました。

f:id:susunshun:20181212214649p:plain ※ここでいう企画/プランナーはWebサービススマホアプリおける施策(機能追加/改善等)を考える人のことを指しています

それぞれのSTEPについて、以降掘り下げて説明していきます。

STEP1:As-Isプロセスの可視化

地道に紐解いていく

そもそもカットオーバーから数年経ったプロダクトなので、既にプロダクト改善の活動は当然行われています。しかし、仮説立案〜リリース・効果測定の一連のプロセスが不明瞭で、そこをまず可視化し、現状を踏襲するところから始めました。

段階的な権限委譲

結論としては、一連のプロセスを可視化した上で、1個ずつ知見を蓄え、権限委譲していくことになります。

f:id:susunshun:20181211015218p:plain

こう図に示してみると綺麗に事が進んでいるように見えますが、実際には泥臭い取り組みの数々でした。そのうち何個かをピックアップしてご紹介します。

徹底的な競合研究

いざ仮説を立てようとしても、中々出てきません。というのも、意外と自分のプロダクトのこと、はたまた競合のことを全然分かっていなかったからです。従って、自社・競合のプロダクト研究を一番最初に取り組みしました。

1日1プロダクト、1時間の枠の中で、メンバー3人で顔を合わせて徹底的にアプリを触りまくります。その中で思ったことを共有したり、自社と他社の差分を徹底的に洗い出して、その差分がどのような効果をもたらすか、どのような意図があるのかを考察していました。

f:id:susunshun:20181209160305p:plain

2週間で仮説100本ノック

競合研究で知識をインプットする傍ら、こちらでアウトプットの鍛錬を徹底的に行います。

仮説立案・企画スキルの醸成を目的として、ひたすら施策を考えまくってひたすら事業責任者にレビューして貰いました。

今思うと最初に持ち込んだ施策は、仮設の筋が悪く、てんで方向違いなものばっかりでセンスの欠片もなかったかと思いますが、事業責任者やプランナーさん達のご指導の下、何回も壁打ちしているうちに、勘所が掴めてきたかと思います。

As-Isプロセスの可視化

こういった取り組みを経て、仮説立案〜リリースまでの一連のプロセスを可視化及び整備をしていくと共に、各プロセスを独力で担えるようになりました。

ここで整理したのは以下です。

  • 各プロセスのINPUTとOUTPUT
  • 関連するセレモニー(会議)
  • そこらじゅうに散らばってる関連ナレッジ(先人達の知見が色んなところに落ちている)

f:id:susunshun:20181212193429p:plain

これをベースとして、次はプロセスの「改善」を進めていくことになります。

STEP1.5:As-Is課題の抽出

ようやくAs-Isのプロセスを遂行できるようになった僕らは、一定期間このプロセスに従ってプロダクト改善を実施しました。そして次なる課題を発掘するために、以下に分割して振り返りを行いました。

  • 僕らがAs-Isのプロセスを遂行できているか
  • As-Isプロセスの課題は何か
  • 各課題のTo-Beは何か
  • その差分を埋めるアプローチは何か

この振り返りを経て、次なるステップに進むことになります。

f:id:susunshun:20181212194239p:plain

STEP2:Learnの質向上

見えてきた課題

STEP1を経て、仮説立案〜リリースまでを独力で遂行できるようになりました。 しかし、BMLを繰り返し行う中でも、特にLearnが質が浅く、次なる仮説につながらないという課題が浮上してきました。

リリース後に効果測定を行って、狙った数値が改善されたものの、「良かったね!...で、次はどうする?」という状況です。

そこでLearnの質を向上させるために、3つの打ち手を講じることになります。

  • KGIの見直し
  • ABテスト基盤の拡充
  • 分析設計の型化

チーム目標の見直し

ここまで話には出していなかったですが、チーム目標としてはLTVを置き、それを向上させるべく日々改善を回していました。(チームの目標設定に関しては今回触れませんが、数値目標を置くよりもOKRを設定し、そこから落とし込んだ方が良かったかもということを今振り返ると思ったりします。)

つまり、LTVに寄与するプロダクトの改善ポイントを探し、施策に落とし込み、それをリリースした結果から学びを得ようとしていましたが、何せLTVはKPIツリーで考えるとだいぶ上位の指標です。

これにより以下の問題が発生しました。

  • 施策毎にアプローチするKPIが異なり、学び・知見が集約されない
  • 短期的な利益を得る施策に落ちがち
  • 大きい指標にすぐアプローチするためには、大きい施策を打たざるを得ない力学が働き、これによって仮説検証スピードが低下する

等々の問題を解消するために、チーム目標の粒度を一段落とし、フィードバック得やすくしました。

ここでは担当プロダクトの詳しいことは述べられないのですが、イメージとしては以下です。

f:id:susunshun:20181212200626p:plain

ABテスト基盤の導入

施策の効果測定はリリース前後での各種CVRの比較を行っていましたが、前後比較は曜日や季節・広告等の影響を排除した効果測定ができず、改善されているかどうか分からないということがしばしば発生していました。

ここでようやくABテスト基盤を導入するに至ります。

お恥ずかしながら、うちのプロダクトではABテストを柔軟に行える仕組みが無く、ABテスト1回に費やす開発コストが大きかったため、Firebaseを導入しABテストを実施しやすい環境を整備しました。

分析設計の型化

仮説を考え、施策を打って、さぁ効果測定だ!と息巻いたものの、実は見たい指標が取れていなかったり、そもそも「何の数字」が「どれだけ」、「どうなったら」成功なのだろうか、と思ったことは無いでしょうか?

僕のチームではこういうことがしばしば発生していました。 そこで仮説を考え、その開発に入る前に分析設計というフェーズを明示的に置き、その中で以下を整理していました。

測定対象の整理

  • Why・・・何を検証したいのか
  • What・・・どの指標を見るのか
  • Where・・・データソースはどこか(DBから見るのかアクセス解析ツールから見るのか、それは現在取得できているのか)
  • How・・・比較方法は何か(前後比較/ABテスト等)、算出方法は明確になっているか
  • When・・・いつ測定するのか(リリース直後、3日後、7日後等)

f:id:susunshun:20181209232207p:plain

アクションの整理

  • いつ
  • どの指標が
  • どうなったら(上がる、下がる、横ばい)
  • どうする(測定を継続、切り戻す、測定終了/どう解釈するか)

f:id:susunshun:20181209232321p:plain

STEP3:BMLの高速化

BMLを「高速」に回す

これまでの取り組みで、ようやくBMLサイクルを回せるようになりました。(もちろん回すこと自体が目的ではないですが)

次なる課題として、以下に多くの学びを得るか、学びの量を「質✕回数」と定義すると、質の面はSTEP2に示した通りのアプローチを行いました。つまり次は回数へのアプローチを行います。

定常モニタリング基盤の構築

定常モニタリングの狙いは以下の2つです。

  • 分析の自動化
  • 健康状態の可視化

分析の自動化

これまで効果測定における分析作業は、全て手動でSQLを叩くという苦行のような作業を行っていましたが(リアルガチで苦行だった)、ここでようやく分析の自動化を行うことになります。

健康状態の可視化

何か施策を打った際に、KPIは小さい指標から先に効果が出て、より大きい指標へと波及していきます。 それらの分析として自分が認識している範囲内であれば、これまで通り手動でSQLを叩き効果を見るということができますが、予期せぬ箇所まで影響が及んでいることも時にはあるかと思います。

もしくは施策直後には大きく影響が出ていないが、じわじわと影響を及ぼしていることも考えられるでしょう。

施策の効果測定という側面でだけでなく、仮説を立案する際に「どこかボトルネックになっているのか」を特定するためのフックとして、プロダクトの健康状態が常に可視化されていることが望ましいです。

定常モニタリング構築のSTEP

これだけで記事一本書けちゃうくらいなので詳細な説明は割愛しますが、定常モニタリングも最初は手動のSQLから初め、不確実性を排除しながら徐々に構築していきました

f:id:susunshun:20181212204300p:plain

フロー効率を重視したプロセス構築

開発プロセスの話は欠片もしてこなかったのですが、ここに来てようやく考え始めました。

この取り組みはまだやり切れていないのと、「フロー効率」でググれば素晴らしい知見が沢山出てくるので、ここも今回は割愛させていただきます。

終わりに

長々と綴りましたがいかがだったでしょうか? グロースハック、仮説検証、BML、最近ではよく聞く言葉になりましたが、その裏には泥臭いこういう取り組みもあるよ、という事例を今回紹介させていただきました。

ここではプロセスに偏った話をしましたが、僕らは正しい問題にフォーカスして理想のプロダクトを作り上げることでユーザーに良い思いをして貰いたいお気持ちで、このような取り組みをしています。

より良いコードを、よい良いシステムを作り上げていく一方で、正しい問題にフォーカスしてムダなコードを書かないためとも解釈できるこのような取り組みも、僕らエンジニアのやりがいなのかなと思う最近です。

APPEND

まだまだ書きたいことがあるのですが、もうキリが無いのでその他トピックに関して軽く補足して終わりとします。

既存チームとの棲み分け

僕が担当しているプロダクトでは、元々はプランナーと開発が明確に分かれており、プランナーは施策を考え、開発チームがひたすら開発する、という一般的なスタイルでした。

そんな中、うちのチームと既存のチームでどう棲み分けてやっていくべきかということを考えました。

包括的に言うと、我々のチームはSoE、既存の開発チームはSoR的な思想に基づき、棲み分けすると良いのかなと感じております。

f:id:susunshun:20181212212544p:plain

SoEとSoRについては@i2keyさんの↓のスライドが1億倍分かりやすいし造詣が深いです。

www.slideshare.net

そのような分けの中で、我々はBMLを回しながら不確実性を落としにいき、ある程度のところで大きく踏み出す施策を、既存チームにバトンタッチして開発してもらう関わり方を考えています。

プランナーとの棲み分け

「エンジニアだけでもう良いじゃん」

「もうプランナーはいらなくない?」

このようなチームをやっているとよく聞かれることです。 しかし、僕はプランナーは必要だと言うことを声を大にして言いたいです。

というのも僕らのチームでは、不確実性を落とすという側面から仮説検証を小さく踏み、結果として施策の大きさが小さくなるため、1回の施策あたりで検討することも少なく、プランナーとして求められるスキルもそこまで多い訳ではないです。(もちろん仮説の構築にあたって、目先の施策だけ見てる訳ではないですが)

一方で、前述のSoR的案チームで扱うような施策は単純に規模が大きいです。大きいというということは検討することが膨大にあります。

  • マーケットをより踏まえた要件の検討
  • 売上影響レベルでの効果予測
  • 法務観点でのリスクチェック
  • 投資決裁
  • そもそも僕らよりも圧倒的にビジネスに詳しい

などなどです。これらを僕らが開発の傍らでできるとは到底思えません。 つまり取り扱う施策によって棲み分けるべきということです。

そういった理由でプランナーは必要不可欠だし、リスペクトしております。

SIerからWeb系に転職したのでこれまでを振り返ってみる

転職しました

9月いっぱいで3年半務めたSIerを退職して某Web系の企業に転職しました。

同じ趣旨の記事を幾度となく見ていますが、一旦ここまでのエンジニアライフを整理しよう!ということも兼ねてブログに書こうと思い立った次第。

SIer時代

まずは前職を振りかえってみます。

就活

エンジニアとして「一般消費者の生活をより楽しくするサービスを作ること」を志して大手SIerへ、今考えると俗に言うWeb系は何故か視野に入っておらず、SIer一本で就活してました

1年目

半年間のなが〜い研修を経て、配属されたPJはなんとCOBOL。エンジニア人生を詰む前に転職しようと決意。(※COBOLは良い言語です)
と思った矢先にとあるWebサービス保守案件に転属。退職するまではずっとここの案件主軸で携わっていくことになります。

PL(プロジェクトリーダー)の先輩が年末に退職してしまったこともあり、すぐにリーダーみたいなポジションにつくことに。
とはいえ知識不足、経験不足は否めず、周りの先輩方やパートナーさんに助けて貰いながらなんとかやってこれました。

2年目

正式にPLになりました。PMの先輩が別案件に移動する構想があり、徐々にPMにシフトし始める。

また、この年から社内ハッカソンが開催され、「SIerハッカソンなんか余裕やろ」と思い参加するも惨敗
susunshun.hatenablog.com

3年目

PM(※社会的事情により体制図上はリーダ)っぽいことをしつつ、余裕が出てきたこともあり他案件に自分から飛び込んだりアサインされたりして兼務をし始める。この頃から「プログラマーよりもマネジメントやビジネス企画の方が適性があるかもなぁ」と思い始める。

そして去年惨敗したハッカソンでリベンジ成功
susunshun.hatenablog.com

既に「SIerは今後衰退してく」という確信はあったものの、転職という選択肢はまだ頭になく、SIerが生き残るためにはどうすれば良いかを考えていました。
会社の都合で受けさせられた斎藤昌義さんのITソリューション塾に3ヶ月程通い、これに影響を受けた面もあると思います。
blogs.itmedia.co.jp

4年目

会社のパンフレットにデカデカと載ったり、数百人の自社エンジニアの部署の前で講演したりと、何かと前に出る機会が多くなってきました。
講演では「イノベーションを起こすためにはどうすれば良いか」をテーマにディスカッションしました。
社員一人一人に意見を発信できる数少ない機会だったので、SIerのビジネスモデルにおける構造的問題には極力触れず、「これからはSIもサービスを打ち出していかなければ苦しい時代。せめて最新のITニュースくらいはチェックして、みんなで発想の幅を広げていこうぜ」ぐらいの、かなり敷居の低い話をしたつもりだったのですが、周りの反応では「やっぱりお前は一味は違うな、お前に任せた!」みたいなフィードバックをもらいました。

ここで「自分ではこの会社を変えられない」という確信を得るとと共に最大のモチベーションダウンを喰らいました。

またSIerは「システムを作ること」を生業にしている会社であり、「どのようなサービスを作るか」は顧客に依存しています。こういった事業特性から「自社サービス」に対する羨望みたいのが膨らんできた時期でもありました。

こうして転職に踏み切ることになります。

転職活動

転職活動を始めた矢先に友人の紹介で、最大手の外資系IT企業(日本法人)から製品サポート部隊のオファーが来ました。ゼロベースで受けたらまず入れないような企業です。

何回かの面談もつつがなく進んだのですが、入社決断を告げるメールを打っている途中で突然手が止まってしまいました。そこから「自分の本当にやりたいことって何だっけ?」を二週間もの間、自問自答し続けることになりました。(この時期は悩みすぎて情緒不安定でした。。。)

散々悩み抜いた結果、自分がIT業界に飛び込んだ理由は「一般消費者の生活をより楽しくするサービスを作ること」と原点回帰し、オファーされている職種とは乖離していたこともあり、二度と無いチャンスではありますがオファーを断りました。ここが人生の分岐点だと思いますし、今後もそうあり続けると思います。

といった経緯を経てWeb系に絞って転職活動を始めたわけですが、私はかなりの安定志向です。本当は転職もできれば避けたい所です。前職に不満があり転職に踏み切ったものの、給与が高ければ不満をごまかして残っていた可能性も充分に考えられます。

なので転職するからにはそれなりの企業に入らなければ、という無駄なプライドがあり、ベンチャーは視野にありませんでした。結果的に自分が魅力的だと思えるWebサービスを最も多く提供しているとある企業の面接を受け、採用いただいた次第です。
ちなみに私はほぼ開発未経験なのですが、運良く希望していた内製開発部隊に入ることができました。

今振り返って見ると、ここで不採用だったらまだ前職で働いていたかもしれないですね。。。

これまでの業務から得た知識、スキルを最大限に活かすならば他の部署の選択肢がありましたし、面接でもそのポジションをゴリ押しされましたが、敢えて未経験領域(※)である開発へ飛び込んだ理由は後述します。

※家で勉強したりはしていましたが、仕事で開発した経験はほぼ皆無でしたので。。。

何故開発に飛び込んだか

これまで家でアプリを作ってみたり、ハッカソンでプロトタイプを作ったり、と開発の真似事はやっていたものの、業務として開発(コーディング)を経験したことはありませんでした。

将来的にはPMに戻ることを視野に入れていますが、良いPJ運用をするためにはその中身を知っておくことが私の中で重要度が高く、最大の理由であります。
(開発を経験せずに、マネジメントやディレクションに特化したタイプもいますが)

あとは適性は無いと分かっていてもプログラミング楽しいしね、自分がコーディングしたシステムを一度で良いからリリースしてみたいよね。

転職して2ヶ月が経ち。。。

プログラマーということでほぼゼロからのスタートです。最初に行われたスキル評価を行う面談でも、「新人と同等レベル」という評価を下されました。

配属されたPJで開発が始まりましたが、足を引っ張ってばかりの毎日です。

でも後悔はしていません。数年間という短期間ではあるものの、プロジェクトマネジメントに従事してきた手前、いま自身がプログラマーとして行っている作業がPM時代の経験とリンクし気付かされることが多く、今後PLやPMに戻った際に従来よりも良いPJ運営をできるだろうなぁ、と思います。

あとやっぱりプログラミング楽しい!

最後に

転職はしないに越したことはないです!

たまに「転職した俺マジ上昇志向」みたいな安直な人を見かけますが(これをファッション転職と呼んでいます)、転職は成功を約束されたものではないです。当たり前のことですね。

付け加えると、完全に一人で仕事している人(もしくはそう思い込んでいる人)ならば良いですが、環境を変えるということはリスクになります。
その界隈の有名人でも無い限りは社内で築いてきた人脈、信頼関係がリセットされるためです。

エンジニアは開発歴からスキルを明確化しやすく、次の職場でもそいつはどういうスキルを持っているのか、を理解されやすいので他の職種よりは幾分マシかもしれませんね。

私はそういったリスクよりも、自分のやりたいことが上回ったため転職に踏み切りました。

最後に、転職活動自体にメリットはあったか、というと「あります」。

転職活動を行う際に自分のスキルセットを整理したり、自己分析をしたり、これまでの自分を棚卸しをしました。これは今後転職しないにしても定期的に見直すべきことだと感じています。
また、自己分析の一貫ですが「自分のやりたいこと」を改めて振り返ることができ、今後の身の振り方にも影響を与えていくと思います。

いまは勉強の毎日ですが、一段落ついたら転職後のことについてまた、書きたいと思います。

それでは、皆さんも良いエンジニアライフを!

CodeIQ夏の陣に行ってきたメモ

CodeIQ夏の陣に行ってきました

僕はプロジェクトの都合で平日は抜けれないことが多いので、勉強会やセミナーに行きたいと思うものの行けてなかったのですがビッグなイベントが土曜にあるということで行ってきました。

atnd.org

以下メモ書きをほぼそのまま書きますが、内容に多少のズレがある可能性はご承知くだされ。

エンジニアサバイバル

ruby始祖まつもとゆきひろさんの講演。遅刻しましたorz

・生き残る上で大切なこと

  • ゴールを設定:漠然としてると運任せにせざるをえない
  • ルールを理解
  • 本当のルールを把握する:騙されてない?前提を履き違えてない?
  • 問題解決:エンジニアの本懐

・エンジニアの問題解決プロセスは他分野にも応用できる
ex)憲法改正はプルリク的な

・許可を求めるな謝罪せよ!!
やってもいいですか?という問いは上司的には辛い(責任が伴うので許可を求めて欲しくない)
やっちゃおう!!ダメだったら謝ろう!

・生産性が高いと大抵の問題は解決する
とはいえそれを実現するためにはある程度の裁量権が必要。組織としてそういう仕組みが必要。

パネルディスカッション

お題を以下から拾ってディスカッションする形式ですか
github.com

印象に残ったお題をピックアップして書きます。

勉強会に参加することを是とするか

・勉強に行く時間あるなら勉強しよろ、という意見もある
・自分の関心に火を付けに行く
・自分の達しているレベルが相対的にわかる

僕としては勉強会は知識のインプットの場ではなく、刺激を受ける場所であったり、
今回の夏の陣みたいにお祭りに乗っかっとけわっしょい!的な認識が強いので
「勉強」という捉え方はあまりしてないです。

それは技術力の低さや勉強を怠ることへの言い訳に聞こえてしまうかもしれませんが、エンジニアの技術力は知識量だけでは測れないと思っていますし、もっというとエンジニアの有能さは技術力だけではないと思っています。

ディスカッションの中でもスパッと結論が出てる訳ではなかったので、これは個々で定義して認識しておくことでしょう。

技術をどこまで追うべきか

・サービスの会社はテクノロジーオンリーの会社ではないので、新しい技術をどこまで追うべきか
・とはいえ技術の相対的な敷居が下がった
・デザイナーがエンジニアの領域に、その逆もしかり
コモディティ化するのでハイレベルを求めた方がよい?
・新しいもの楽しそうだし追いたいじゃん?

これは難しい。。。
定量的な答えは出ないとおもうので「ちょうどよい」線引きをしてバランスを取ることが大事ですね。

生産性ってどう?

・残業して成果をあげることが褒められる文化よくない
・日本企業はそもそも生産性を上げる取り組みをしていない
・最初から作り込まずに、抜くところは抜こう(海外のサービスはそこがうまい)
・生産性とクリエイティブは二律背反
・第二のビルゲイツビルゲイツじゃないし、日本のシリコンバレーシリコンバレーではないからそういうのやめよう
・クリエイティブな時間を持つために生産性をあげよう

とはいえ”筋肉”

・筋肉こそ最強
・SoftSkillsにも書いてある
・そこでアニメヨガ(from きゃんちさん)

筋肉は陳腐化しないしね、間違いないね。筋肉こそ唯一にして絶対的な答え。

とはいえ筋肉は単なるネタではなくて、ハードワークを良い状態でこなすためには健全な肉体が必要ということです。

参加してみて

今回はCodeIQですので、転職イベントという側面もあり既に転職先が決まっている僕としては申し訳ない気持ちはありましたが、著名人方の話を直接伺えたり、他社のエンジニアとお話しさせていただいたりと、普段イベントに参加できていないので良い刺激を受ける場でした。

転職後はある程度は自由が利く身になる(はず)なので、積極的にこういった場に顔を出していきたいと思います。

いつかこういう場でLTをやってみたい。。。そしてきゃんちさん可愛い。。。

Web SQL DatabaseでexecuteSqlした後に何か処理する

前回の記事の続きでWeb SQL Databaseを使ってみた。

susunshun.hatenablog.com


が、executeSqlでselectを実行する際、その結果はコールバックで受け取る必要があるのでここもネックになってます。

不都合があったのでその対応メモ。
monacaアプリの中でAngularJSを使ってます。

やりたいこと

  1. DBが無ければ生成
  2. DB検索
  3. 結果をscopeにぶちこむ
  4. バインド(自動)

の順で処理します。

対応

1,2が非同期処理なので、何も考えずに書くと1→2の処理順が担保されません。
なので1,2はpromiseを使って同期しちゃう。3は2の中に入れちゃう。

 module.controller('AppController', function($scope) {
    // DB生成
    var createDatabase = function(){
        return new Promise(function(resolve, reject) {
            // タイムアウト値の設定は任意
            setTimeout(function(){
                console.log('Start createDatabase');
                var db = window.openDatabase("Database", "1.0", "TestDatabase", 200000);
                if(db.version == ""){
                    console.log('not exist db');
                    // DB無いので作ります
                    db.transaction(
                        function(tx){
                            tx.executeSql('DROP TABLE IF EXISTS TestTable');
                            tx.executeSql('CREATE TABLE IF NOT EXISTS TestTable (id unique, name)');                            
                            
                            // テストデータを叩き込む
                            tx.executeSql('INSERT INTO TestTable VALUES (1,"てすとでーた")');
                        }, 
                        function(){
                            // 失敗時
                        }, 
                        function(){
                            // 成功時
                        }
                    );
                }else{
                    console.log('exist db');            
                }
                console.log('End createDatabase');
                resolve();
            },100);
        });
    };

    // 検索
    var selectDatabase = function(){
        return new Promise(function(resolv,reject){
            setTimeout(function(){
                console.log('Start selectDatabase');
                var db = window.openDatabase("Database","1.0","TestDatabase",200000);
                db.transaction(
                    function(transaction){
                        transaction.executeSql('SELECT * FROM TestTable', [], querySuccess, errorCB);
                    }, 
                    function(){
                        // 失敗時
                    }, 
                    function(){
                        // 成功時
                    }
                );                    
                console.log('End selectDatabase');
            },100);
            
            var querySuccess = function(tx,results){
                console.log('Start query');
                
                // *************************
                // クエリ成功時の処理をかく(results → testdata)
                // *************************
                                
                // scopeの更新と反映
                $scope.testdata = testdata;
                $scope.$apply();        // ★
                console.log('End query');
                resolve();                    
            };
            
            var errorCB = function(err) {
                console.log("Error occured while executing SQL: "+err.code);
            }
        });
    };

    createDatabase().then(selectDatabase);
 });

やりたいことその2

  • CRUD処理はfactoryでまとめたい(controllerに書きたくない)
  • select処理の後、$scopeに値をセットし、$scope.apply()をしたい(上記★の箇所)

つまりselect → 結果をセット → 反映の順番を担保したい

ということでCRUDはfactoryで書こうと思ったのですが問題が。。。

問題箇所

いろいろ試した結果、factory経由で$scopeの値をコントローラ間で引き継ぐことはできるが、factory内で$scope.apply()が効かなそう(合ってるのかな?)

とはいえ、factoryの処理(ex. select処理)完了を待ってcontroller側の処理($scope.apply())を行えれば良いので、factory側の処理とcontrollerで同期したいところですが、うまい方法が見つからず(›´ω`‹ )

機能的にはlocal storageでも問題無いのでそちらに移行しようか検討中

しかしmonaca IDEだとだいぶデバッグが辛いですね

余談

いまmonacaアプリはonsen UI + Angular1系で作ってるんですが、昨日Onsen UIがAngular2系に対応したとのこと!!
Angularは1と2で全く別物と聞いているので近いうちに試したいところ(どうせならIonic使いたい)

onsen.io

monacaでデータベースを使う

monacaアプリでデータベースを使いたい!

ということでデータの永続化について調べた(ノ゚ω゚)ノ*.オオォォォォォォ

いろいろ選択肢があるよう(ノ゚ρ゚)ノ ォォォ・・ォ・・ォ

どんなアプリ

  1. 読みたい本をストックするアプリ
  2. 読みたい本リストをデータベースに保存したい
  3. なのでそんなリッチな機能はいらない

選択肢

  1. Web SQL Database
  2. Indexed Database API
  3. Local Strage
  4. SQLite(ネイティブから直接使う)
  5. Web APIで外だし
Web SQL Database
  • リレーショナルデータベース
  • 内部的にはSQLiteを使っている
  • W3Cは2010年に仕様の策定を中止(仕様が特定の実装(SQLite)によっちゃうので)
  • 多くのブラウザで実装されている

Web SQL Database

Indexed Database API
  • キーバリューストアー型
  • Web SQL Databaseの代わりにW3Cが仕様の策定に注力してる
  • インデックス貼れるので検索が高速
  • 普及に難あり

Indexed Database API

ご参考までに比較記事
thinkit.co.jp

LocalStorage
  • キーバリューストアー型
  • データベースというよりはデータを「保存すること」を目的にしていると思う
  • 逆に言うとシンプルなので扱いが簡単

Window.localStorage - Web API インターフェイス | MDN

SQLite(ネイティブから直接使う)

GitHub - litehelpers/Cordova-sqlite-storage: A Cordova/PhoneGap plugin to open and use sqlite databases on Android, iOS and Windows with HTML5/Web SQL API

Web APIで外だし
  • Web APIで外だしして、必要時にアプリから呼び出せばよくない?
  • アプリ内でデータを保持しないので都度APIを呼び出す必要がある

どうしましょ

読みたい本リストを保存したいだけなのでLocalStorageで充分な気がしますが、とりあえずリレーショナルデータベース使いたい。(キーバリュー使ったことない)

何年か前にネイティブアプリを作ってた時にSQLite使ってたので、慣れてるCordova-sqlite-storageを、と思ったのですが、私はmonaca無料プランで開発してるのでプラグインの導入はできず。

ではWeb SQL Databaseか、と思いましたが6年も前にW3Cが放棄してるのか。。。どうしよう、と思っていたところ、「HTML5-ハイブリッドアプリ開発入門」に以下の記載が!

標準化されない機能を使うには不安があるかもしれませんが、iOSAndroidで利用されているレンダリングエンジンであるWebKitにはすでにWebSQLが実装されており、WebKitからWebSQLが取り除かれる予定はないと開発者によって明言されています。

[iOS/Android対応] HTML5 ハイブリッドアプリ開発[実践]入門 (Software Design plus) : 久保田 光則, アシアル株式会社 : 本 : Amazon.co.jp

ならばよかろう、ということでWeb SQL Databaseを使うことにしました_( _・ω・)_

monaca IDEのgithub連携でgitignoreする

今日軽くつまづいたのでメモ

monaca IDEで.gitignoreが編集できない

monaca IDEからgithubに連携しているソースコードAPIキーを使っている箇所は、
pushした後に

cont API_KEY = 1234567890

から

cont API_KEY = 【APIキー】

という風に毎回githubで直接編集していたのですが、なんともイケてない。
APIキーだけ別のファイルに書き出してそいつをignoreすればいいっしょ!と思い、monacaで.gitignoreを作成すると

f:id:susunshun:20160615224613p:plain

というダイアログが出力されてmonaca IDEからは編集できない、ファイルの表示もされない、でもファイルの実体はあるっぽい。
(commit & push したらgithubに.gitignoregが追加されていた)

対応

ということでmonaca IDEgithub連携しているソースに対してignoreしたい場合は以下手順で対応。

  1. githubで.gitignoreを作成、編集 & commit
  2. monaca IDEでpull
  3. monaca IDEでignoreするファイルを作成

とするとcommitしても差分で出てきません

f:id:susunshun:20160615230339p:plain

monaca開発でのAPIキーの扱いについて

現在頭を悩ませているのがAPIキーの扱いです。

今回のようにgithubAPIキーを公開したくないだけなら、

  • APIキーを別ファイル(JS)で外だし
  • 別ファイル(JS)をAPIキー使う処理で読み込む
  • 別ファイル(JS)はignore

で終了です。

でもビルドしたアプリを公開するとなるとどうでしょうか。
monacaのメインはあくまでもhtml、JavaScriptなのでchromeデバッガでデバッグできてしまいます。
つまり”別ファイル(JS)”もロード先のhtml/JSをデバッガで見れば判明してしまいます。

もっというとJS以外のファイルに設定を保持したとしても、APKファイルを解体すればファイルの内容ってみれちゃいますよね確か。。。

対応としては、APIキーを使用する処理をサーバーサイドに寄せて(web API)にしてmonacaで作ったアプリから呼び出せば良いのですが、monacaで完結させる良い方法はないですかね。。。(クライアントサイドでAPIを呼び出すwebアプリも同様)

everNoteにストックしたノートをtwitterにリマインドする

日頃の情報収集や調べごとで気になった記事はevernoteにストックしてるんですが、実際のところ後から見ないことが多い。。。

するとこういうことがよく起こる

あのメソッドでどう使うんだっけ?と思って調べる

あれこの記事見たことがある?

_人人人人人人人人人人人人人人人人人人_
> evernoteにストックしてた     <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^^Y^Y^Y ̄

ということでevernoteからランダムでノートを取得してtwitterにリマインドするbotを作りました。
f:id:susunshun:20160530004920p:plain

evernoteAPIを使う

evernoteAPIを使うには会員登録が必要です

ホーム - Evernote Developers

会員登録をすると、テスト環境でAPIにアクセス可能なAPIキーが貰えます。

実装は公式リファレンスに詳しくかいてあるのでほぼそのままコピペ
Rubysinatra)を使います

Getting Started with the Evernote API - Evernote Developers

コピペで実装
everApi/everApi.rb at master · susunshun/everApi · GitHub

OAuth部分はこんな感じです
f:id:susunshun:20160530003941p:plain
f:id:susunshun:20160530003952p:plain
f:id:susunshun:20160530004002p:plain

JSONでノートの内容を返してくれるようになりました。

$ curl http://localhost:4567/random
{"title":"【vim】行番号の表示・非表示","url":"http://qiita.com/spyder1211/items/c5dd49a3a799bd146599"}

botでリマインド

hubotを使います。
herokuでshをキックしてそこからhubotのscriptを動かします。

#!/bin/sh

export HUBOT_TWITTER_KEY="XXXXX"
export HUBOT_TWITTER_SECRET="XXXXX"
export HUBOT_TWITTER_TOKEN="XXXXX"
export HUBOT_TWITTER_TOKEN_SECRET="XXXXX"

export HUBOT_NAME="susunshun_o"

// hubotを動かす
bin/hubot -a twitter --name susunshun_o

もしくはherokuに直接環境変数を設定してもよいです。
qiita.com


hubot本体は以下
shushubot/everTask.coffee at master · susunshun/shushubot · GitHub

かんせいーいヽ(´▽`)/
f:id:susunshun:20160530002755p:plain

いまはtwitterの閲覧頻度が多いのでtwitterにリマインドするようにしていますが、hubotを生かしてslackやその他チャットツールと連携してもよいかもですね。
(やるかわかんないけどそのためにevernoteAPIを独立させた)