読者です 読者をやめる 読者になる 読者になる

ハウテレビジョン開発者ブログ

『外資就活ドットコム』を日夜開発している技術陣がプログラミングネタ・業務改善ネタ・よしなしごとについて記していきます。

Selenium WebDriverで、新規会員登録フローのE2Eブラウザテストを自動化してみた。

どうも。エンジニアの@bumcruです。

Qiitaの「Selenium/Appium」アドベントカレンダー9日目の記事です。

去る10月に行われた開発合宿、今年のテーマは「自動化」でした。
テーマの範囲内で、個々人が自由に好きなものを作るわけですが、

僕が選んだお題は「Seleniumでのブラウザテスト自動化」です。

続きを読む

【開発合宿幹事向け】合宿企画の下準備工程を全て公開します。【合宿準備編】

f:id:incase:20151020011431p:plain

どうもこんにちは。
エンジニアのvsannaです。

前回の記事では、10/16(金)から10/18(日)にかけて行った合宿の様子を画像中心にお届けしました。

今回は事前準備編として、幹事様に参考になりそうな情報をとりまとめています。

これから企画をしなくては...と頭を抱えている3ヶ月前の私のような方はぜひご一読ください!

負債、返済するしかない。

howtvでは現在、技術的負債の返済に本腰をいれてとりかかっています。

サービスの稼働開始から5年が経ち、腐った時代にそぐわなくなってきたコードが無視し得ない程度にたまってきました。

アプリケーション構成の歪み・未使用コードの放置・秘伝のタレと化した手作業工程、開発チームのモチベーション低下...

より安定した良いサービスを作り続けるためにも、このタイミングでいままでの負債に真正面から向きあおうと、技術顧問に伊藤直也氏(@naoya_ito)を迎え、開発体制の立て直しを始めてはや3ヶ月。

そろそろコードそのものと向き合うときが来たのではなかろうか...となった頃合いに、「あ、そういえば今年もやる?開発合宿。」というメンバーの一声で、開発合宿の開催が決まりました。

今年のテーマは「自動化」

昨年から始まったこの開発合宿ですが、昨年のテーマは「スマホアプリ開発の知見を得る」でした。
(昨年の様子は「ハウテレビジョンのメンバーでアプリ開発合宿に行ってきました!」からどうぞ)

さて今年のテーマはどうするかとチームで考えた結果、上述した背景もあって負債返済のいちテーマである「自動化」を採択しました。

How To Become A Hackerにもある通り、同じ問題を二度解くような無駄はいやですし、退屈と単純作業は悪と思っている我々エンジニアは自動化を好む生き物です。

異論も特に無く、テーマは自動化で決定に。

事前準備が楽しい

f:id:incase:20151020013359p:plain おおまかな流れ

0. まずは昨年の振り返り

昨年の振り返りを活かすべく合宿のKPTTを見なおしてみます。

f:id:incase:20151020013507p:plain

  • 2泊3日
  • 集中できる環境づくり
  • 開発以外にかかる時間の極力排除
  • 事前の段取り設計

あたりが重要そうですね。

なお昨年の参加者にヒアリングすることは重要かつ効果的です。
参加者の声を聞いておけば大体のつまづきポイントを最初から弾くことができるでしょう。

1. 他社の調査

他社さんの開発合宿風景も調査します。
予算(泊数と単価)、場所、アクティビティ、その他コツの4点を中心に調査しました。

この辺りからドキュメントを放り込む場所としてGitHubに新しくそれ用のレポジトリを作成しました。
後々便利なので作っておいて正解だったと思っています。

f:id:incase:20151020013535p:plain

なお、その際には以下のブログを参考にさせていただきました。

実際の調査段階では他社さんの予算をつかめなかったことが残念です。
なお今回当社の合宿費用総額は最後にまとめて公開してしまいたいと思います。

2. 参加メンバーにプロダクトマネージャーの追加

当初は純粋な開発合宿として参加者はエンジニアに限定して進めていたところ、プロダクトマネージャー(以降PM)も参加したほうがいいんじゃない?との声があがり検討の土台に上がってきました。

プログラミングの経験がそこまで深くはないPM陣がコードを書いている姿を見ていると、我々エンジニアの姿勢も自然と正されるような気分になりました。話の幅も広がりますので非常におすすめです。

PM陣の課題は、

  • データ分析の幅を広げるということでSQL徹底特訓
  • 動かしている感じのするコードを、ということでクローラーの実装

の二択で用意しました。

4. 宿の決定

お値段 × 開発環境の二軸で選択し、湯河原のおんやど恵さんに決めました。

f:id:incase:20151020013628p:plain

最初に場所の選定から入りましたが、移動距離が長すぎるとそれだけで疲れるとの声から電車で1.5時間圏内の候補地を5つ(鬼怒川、湯河原周辺、千葉、奥多摩、長野・軽井沢)ほどピックアップ。

その中から、

  • must
    • 会議室などの作業場を借りられる
    • 通信環境完備
    • 温泉がある
    • 一人あたり一泊13000円を超えない
  • nice to have
    • 開発環境の更なる整備 ... タップ、スクリーン、プロジェクタ、ホワイトボードなど
    • 周辺環境の充実 ... コンビニ、アクティビティ施設
    • 明光風靡
    • 食事が美味しい
    • 温泉24時間

の条件をみたすものをゆるく探した結果約30件弱ほどの宿がmust条件にマッチ。(もっとあるかも)
nice to haveをすべて満たすところはお値段的に少々厳しかったりと諸々検討した結果、おんやど恵さんにお世話になることになりました。

決め手は【開発合宿モニタープラン】ブログを書いていらっしゃるエンジニアの方限定!ご協力内容により最大50%off!というこちらの記事。

実績として多くのweb企業が利用しているにもかかわらず、ブログを書くととんでもない割引がきくとのことで、予算を預かる幹事としては大変うれしい内容です。

しかも開発合宿専用のプランであって、サイトQ&Aもしっかりこちらの疑問を抑えている作り。

一回これを目にしてからはさくさくとこちらに決まりました。

幹事としては、

  • 開発に必要な準備一式を任せられる上に
  • 東京に近く
  • お値段安い

この三点セットはなかなかありがたいのではないでしょうか。

一方で、サイトにもある通り、食事のグレードは若干下がるようです。(気づきませんでした。)
このあたり事前に社内での優先度を確認しておクと良いかと思います。

私達の場合は温泉と集中できる開発環境が第一義だったので問題なく決まりました。

5. あとは細かい調整

ここまで決まれば後は細かい調整を残すのみです。

  • 各メンバーに開発合宿開催の正式アナウンスを行って気分を上げていく↑↑
  • 宿、電車の手配
    • 行き帰りには特急踊り子を利用しました。早くて安いということで文句なしです。
  • 細かいスケジュールを設定し、GitHubに旅のしおりとしてアップ
    • 開会の儀、閉会の儀はあると気分が締まります。
    • 朝食、夕食の時間はきっちり決めつつ、お風呂や昼食は自由にというコンセプト。
  • 各参加者に事前に個別にとりかかるテーマとその準備しておくべき工程をGitHubにあげてもらう

f:id:incase:20151026205700p:plain - 予算を確保する - 思いつきにくいところですと、タクシー代、酒代、昼食費、レッドブル・コーヒー代、(表彰が有れば)商品代などを予め計上しておくと便利です

こんなところでしょうか。

おわりに

だいぶ長くなりましたが、そんなこんなでようやく合宿です。。

合宿の手配で重要だと振り返って思う点を書き出してみました。

最後に先ほど宣言したとおり、総費用を公開して終わりとしたいと思います。

参加人数は13名です。
右列単価は単純に総額を13で割った額になっています。

項目 費用 単価 備考
宿泊費 226,000 約17,400 割引後の値段です。2泊でこのお値段。
交通費 106,800 約8,150 往復の値段
飲酒 20,000 約1,540 これを上回る分は各自個人支出(割り勘)
景品代 30,000 15,000 * 2 blu-ray2本 と高級マウス
レッドブル・コーヒー 10,000 約770 ※amazonで箱買いすればよかった...

※おんやどめぐみさんが館内でレッドブルを購入できるように手配してくださいました!

以上です!!

こちらも非常に長い記事となりましたが、最後までご覧頂きましてまことにありがとうございました!

また次回の合宿も楽しみにしたいと思います。

@vsanna

【画像57枚】開発合宿にいってきたぜ!【合宿当日編】

どうもこんにちは。
エンジニアのvsannaです。

今回の記事では、10/16(金)から10/18(日)にかけてhowtv開発陣で行った合宿についてまとめたいと思います。

飲んで騒ぐ様子から一人ひとり徹夜の開発で倒れこんでいく様子まで写真中心にお楽しみいただけます。

他のチームで開発合宿をするご予定のある方や、その雰囲気を知りたい!という方にぜひご一読いただければと思います。

幹事様の参考になりそうな情報をまとめた事前準備編は次の記事からどうぞ!

1日目 飲み会

集合

f:id:incase:20151020021608j:plain 集合場所は品川・東京・現地の3パターンでむかう。 f:id:incase:20151020021631j:plain Naoya氏がこちらを見つめる。朝食はパン。 f:id:incase:20151020021756j:plain 特急踊り子号にのって出発! f:id:incase:20151020023019p:plain 東京集合組の様子。

行き

f:id:incase:20151020021938j:plain テンションが上がるCTOと若干引いてるディレクター f:id:incase:20151020023241p:plain 行きの電車内で下調べしたり論文書いたりしているメンバーも。まじめか。

到着!

f:id:incase:20151020022246j:plain 無事駅到着。傘を置き忘れたことにこの3秒後に気づく。 f:id:incase:20151020030434j:plain きれい、可愛い、安い

昼飯

f:id:incase:20151020023519p:plain 昼食は駅前の珈琲館alcaffe。食べログが見当たらず不安。 f:id:incase:20151020023812p:plain 料理は美味しい。磯の香うどん美味しかったです。

宿の様子

f:id:incase:20151020031420j:plain 宿に到着! 門構えの写真撮り忘れた... f:id:incase:20151020024307j:plain エントランス. フロントではハーゲンダッツを購入可能(ポイント高い) f:id:incase:20151020024717j:plain 階段を上がると... f:id:incase:20151020024731j:plain 雰囲気ある光景。 f:id:incase:20151020024930j:plain 更に進むと... f:id:incase:20151020024811j:plain 更に奥へ... f:id:incase:20151020024942j:plain 湯河原なのに「両国」 f:id:incase:20151020024957j:plain 開発部屋到着! f:id:incase:20151023204249j:plain スクリーン大きい f:id:incase:20151020025234j:plain プロジェクターはHDMIとディスプレイポートが接続可能。でも要確認です。 f:id:incase:20151020025246j:plain ホワイトボード完備。でも2枚あると議論用にも使えてよかったかも。 f:id:incase:20151020025318j:plain 小物も準備OK

開会の儀式

f:id:incase:20151023204139j:plain いよいよ開会 f:id:incase:20151023203353p:plain CTO「ちゃちゃっといいもの作ってみよう。」 顧問「挨拶w」

開発

f:id:incase:20151020025655j:plain 開発... f:id:incase:20151020025747j:plain 開発......

夕食

f:id:incase:20151020031006j:plain 夕食のお時間となりました f:id:incase:20151020031018p:plain 美味しそうな食事の数々 f:id:incase:20151020031850p:plain お酒もすすみます f:id:incase:20151020031136j:plain ボス陣も暖気してきた様子

10時から飲んで...

3部屋で臨みましたが部屋割りを飲み部屋1部屋・就寝部屋2部屋の割り振りとしました。 飲み部屋を一部屋持つことでそこでは気兼ねなく飲み語らうというルールを設けられ、寝たい人と飲みたい人でうまいことすみ分けが出来たようです。

f:id:incase:20151020042742j:plain

このあとは就寝。(開発とは全く無関係の話題で熱くなっている図)

2日目 開発

宿の風景その2

f:id:incase:20151020040149j:plain 売店。ここでレッドブル置いて欲しいですな。 f:id:incase:20151020040220j:plain 何故か目を離せないあじミラー。 f:id:incase:20151020040322j:plain 中庭がきれい。 f:id:incase:20151020040334j:plain 足湯があります。 f:id:incase:20151020040349j:plain 足ふきタオルも準備万端。5回は入りました。

開発

f:id:incase:20151020031219j:plain ここからが本番

昼食

f:id:incase:20151020034208p:plain 近所に食べログ3.5以上のラーメン屋が。 f:id:incase:20151023204557p:plain 道のりが遠い f:id:incase:20151020033718p:plain ついた! f:id:incase:20151020033837p:plain 思わず唸るワンタンチャーシュー麺の美味しさ。チャーハンも注文して分ける。

tabelog.com

王ちゃんに出くわしたことでこの開発合宿の魅力が数段増したことは間違いありません。 もしこの近辺で合宿される際にはぜひ食べによってみてください。

なお席数は多くなく最大12人が座れる広さ。かつ人気店ですので事前に予約しておくことをおすすめします。 3日目の昼にも行きましたが予約で入れませんでした...

夕食

f:id:incase:20151020034403j:plain 午後の開発をすっ飛ばして夕食 f:id:incase:20151020035332p:plain 最後の晩餐で気合を入れ直します。

開発は夜を徹して行われる

f:id:incase:20151020040022j:plain 夜の足湯 f:id:incase:20151020040442j:plain 集中力が高まります。 f:id:incase:20151020040510j:plain ボス陣coding. 直也さんレッドブル飲み過ぎて眠れなくなる。 f:id:incase:20151020035937j:plain 午前三時 f:id:incase:20151020035941j:plain 午前四時

3日目 成果発表

いよいよ発表!

f:id:incase:20151020042356p:plain 各自3日間の成果を発表

表彰

f:id:incase:20151020043921p:plain 直也賞と大西賞を用意しました。 f:id:incase:20151020044001j:plain 大西賞はSeleniumでテスト自動化を導入した@bumcru0310. 最高級マウスが商品です(完全にCTOの趣味)
直也賞はzabbixを導入した@xyz_i. シュタゲとあの花のblu-rayが贈られます(羨ましい...) f:id:incase:20151020044027j:plain なんだかんだ唯一の集合写真

ぶらり湯河原

f:id:incase:20151020044221j:plain 3日の昼、帰りがけに王ちゃんに寄るも予約で入れず崩れ落ちる大人たち f:id:incase:20151020044458j:plain ソフトクリーム食べながら山道を下る f:id:incase:20151020044503j:plain 散歩の後は冷たいのでさっぱりと

後日 振り返り

合宿後、早速KPTTの振り返りを行いました。 その内容を公開して前編の締めとしたいと思います。

良かった点

  • 2泊3日だと、1日目はお酒を入れて懇親もあり、2日目はお酒なしで丸一日がっつり開発にあてることができてよかった
  • インターン生と仲良くなれた
  • 電車で行くと車に酔わないので良い / 東京から電車で移動できると楽
  • 去年よりも宿が綺麗 / 部屋がひろかった / 宿がきれい。料理もちょうどよかった。
  • 王ちゃんがいた
  • naoyaさんが居た / KOMONが来た。/ なおやさんの指摘がいい
  • 温泉で疲れが取れた
  • 昨年よりも時間管理がゆるく、自分のペースで開発できた / 時間の使い方に裁量があったのがよかった。
  • 宿が空いてたのでゆったりできた。
  • 1日目、アニメの話で夜更かししすぎた。
  • 風呂入り放題
  • 【部屋割り】先に1部屋を飲み部屋として、先に寝る人から他2部屋で寝ていき、最後まで残った4名が飲み部屋で寝るという、フレキシブルな運用はよかった
  • 成果発表会はよかった
  • ちゃんと寝た
  • 足湯がある

改善できる点

  • 設備/環境関連
    • モニタがあるとよい
    • 会議室以外のWiFiが欲しかった(会議室はとてもよかった)
    • 腰がいたい / 椅子を事前に見定めたい / 座り方を研究する
    • 少しの間でいいので、一人で開発できる部屋があるとよかった。 / いろんな場所で開発したい(会議室、ラウンジ、足湯、部屋) / 一人で開発したい
    • レッドブルやビールを冷やしておける冷蔵庫 / アイスボックスを用意すると便利
    • コーヒー飲み放題の用意をしておく
    • コンビニが近いとよい。少し遠い。
  • 事前準備関連
    • 当日にOSアップデートというチャレンジ
    • 事前準備が足りなかった(環境構築にだいぶ時間がかかった)
  • 企画、幹事関連
    • githubに事前に投げた「事前にやること」が機能してなかった
    • ランチの計画が無かった(ランチ難民化した)
    • 夕食会場で隣の人と話すぐらいしかできなかった。もうちょっと小さいグループに分けたほうが良いと思う
    • 合宿あけにリリースが入ってしまった。代休が遠い。(合宿直後にAWSへ移行しました。)
    • 各自負担と会社負担とが交じると精算が面倒
    • 鍵の管理方法を明確にしておくとよかった。
    • みんな開発に集中していて、雑談したり困ったときに話しかけるタイミングをつかめなかった
  • その他
    • 1日目、アニメの話で夜更かししすぎた。
    • naoyaさんレッドブル禁断症状発症

おわりに

合宿記事当日編は以上です!!

非常に長い記事となりましたが、最後までご覧頂きましてまことにありがとうございました!

引き続き、予算や事前の準備、宿選びにこだわったポイントなどをまとめた事前準備編(comming soon...)を幹事様向けにご用意しております。 そちらもぜひ!

@vsanna

追記

最終日におんやど恵さんのアンケートに「宿内でレッドブルを買えると非常に助かります」と書いたところ早速宿内でレッドブルを販売開始していただけたようです! f:id:incase:20151024174958p:plain 合宿終わって3日以内の対応とは恐ろしいスピード....  大変お世話になりました!

ユーザーの行動パターンをグラフで視覚化する方法

はじめに

データアナリストのn_maoです。

BtoCなWEBサイトやスマホアプリ、リアル店舗の小売業など多くのビジネスでは、ユーザー行動を正しく分析することで、継続率や売上げの向上につながる重要な示唆を得ることが可能です

ユーザー行動分析の中で、あるページからあるページへの遷移確率を算出したり、特定のユーザー群(例えば、多くのお金を払ってくれるユーザー達)に特徴的に見られる行動パターンなどを列挙することがあります。

しかし、多くのWEBサイトでは大量のページやアクションが存在し、それらの組み合わせ(パターン)となるとさらに膨大な数となるため、全てのユーザーの全行動を視覚的に把握するのは困難です。

意味のある分析を行うためには、「適切な課題設定」「欲しい結果を得るためのデータの加工・抽出」「適切な解析手法の選択」「解釈を行いやすいような視覚化」など、様々な工夫が必要となります。

今回はその中でも、行動パターンの視覚化を行う方法に焦点を当て、私が良く使うグラフ表現方法の基本形をまとめてみました

次節以降で順に見ていきます。

有向グラフによる視覚化

ページ間の遷移は、順序関係をもつ系列データのため、有向グラフによる視覚化が可能です。

有向グラフとしてはSankey Diagramネットワークグラフの2種類の手法を紹介します。

Sankey Diagram

シンプルな例を、Google chartを利用して描いてみました。

図1. ページ遷移を視覚化したSankey Diagramの例

f:id:n_mao:20150928121727p:plain

図1では、ノードが1ページを表し、エッジの太さで遷移頻度を表しています。

Sankey Diagramは、ページ遷移の様子をとてもシンプルに表現できる良い手法です。

Google Analytics(GA)でも行動フローとして利用されていますね。

ただし、この図はループやサイクルがないことに注意してください。

つまり、A -> AやA -> B -> Aのような遷移は表現できません。

また、ノードの位置が同じだからといって、特に意味はありません。

図ではAとFが同位置に描かれていますが、これは同じグループに属しているとか何かしらの順序が同じという意味ではなく、 配置上都合が良かっただけです。

綺麗に揃っていることで誤解を招きやすいので注意してください。

GAの行動フローは(おそらく)この辺りの特徴を踏まえ、セッション開始からの遷移数という情報を与えるという工夫を行っています。

図2. GAの行動フローの例

f:id:n_mao:20150925224450p:plain

GAの行動フローでは、ノードの位置と、セッションからの遷移数を合わせています。

この図で最も注目してほしいポイントは、この図のハイライトされたルートを辿っていくと、2番目の接点の位置に「/」が再度登場していることです。

また、最初の通過地点に「/archives」があるにもかかわらず、2番目の接点にも3番目の接点にも「/archives」があります。

Sankey Diagramはサイクルが表現できないはずなのに、なぜこんなことが起こるのでしょうか。

おそらく、グラフを生成する際、同じページでもセッション開始からの遷移数が違えば別のものとして区別しているのでしょう。

つまりこの図では、「/archives」からの遷移の全体像ではなく、あくまでセッション開始から1遷移後の「/archives」からの遷移といった、部分的な情報であることに気をつけて解釈してください

※部分的な情報だから悪だというわけではないです。目的に応じて正しく利用し、正しく解釈しましょう。

ネットワークグラフ

ループやサイクルを含む行動パターンを視覚化したい場合には、以下のようなネットワークグラフで表現すると良いでしょう。

以下の全ての図はgraphvizを利用して描いています。

図3. ネットワークグラフの例

f:id:n_mao:20150928190441p:plain

エッジの向きは遷移の向き、エッジの太さは遷移数を表しています。

サイクルがある分、Sankey Diagramより少しごちゃごちゃしていますね。

ページの階層構造など、何かでグルーピングできる場合は、位置を揃えてあげると見やすいです。

図4. 階層を揃えたネットワークグラフの例

f:id:n_mao:20150928190305p:plain

味気ないので色もつけましょう。

図5. 色もつけたネットワークグラフの例

f:id:n_mao:20150928211526p:plain

これで見やすくなりました。

この図はGAとは異なり、セッション開始から何遷移目かといった情報は無く、(対象データの)すべてのページ遷移の傾向を確認することが可能となります。

ただし、Sankey Diagramでもネットワークグラフでも、長さ3以上のパターンの表現は難しいです。

例えば図4では、「/」から「コラム一覧」への遷移数と、「コラム一覧」から「コラムA」への遷移数はそれぞれ確認できますが、「/」から「コラム一覧」へ遷移し、かつその後「コラムA」に遷移した数は表現できません。

解決策としては、エッジを分けたり、非連結グラフにすることが考えられますが、その場合グラフサイズを小さくしないと複雑になりすぎるのでおすすめできません。

何か良い方法ないでしょうか?

無向グラフによる視覚化

ページの遷移は順序を持っていますが、必ずしも順序を考慮した方が良いわけではなく、順序情報を除いた方が良いケースも多々あります

そういった場合は無向グラフで表現しましょう。

以下ではネットワークグラフ二部グラフの場合の表現方法、そしてクラスやノードの影響力などを考慮した少し高度なグラフ表現方法について述べます。

ネットワークグラフ

まずはネットワークグラフです。

図6. ネットワークグラフの例

f:id:n_mao:20150928192413p:plain

有向グラフの場合と同様、階層を揃え、コンテンツカテゴリーで色分けしています。

上図では有向グラフと違い、サイクルは集約された1本のエッジになっています。

向きがないことでさっぱりしましたね。

向きに意味がなければシンプルに無向グラフで表現した方が伝わりやすいでしょう。

二部グラフ

また、例えばどのような属性のユーザーがどんなページを見ているか?といったように、「属性」と「ページ」という2つのグループに分けられ、かつ同じグループのノード同士が結ばれない場合は二部グラフであるため、グループでまとめてあげるとスッキリします。

まずは何の工夫もなく描いてみました。

図7. 二部グラフを下手に描いた例

f:id:n_mao:20150928212811p:plain

見にくいですね!

グループでまとめて上手に表現してみましょう。

図8. 二部グラフを上手に描いた例

f:id:n_mao:20150928200108p:plain

左が属性、右がページグループです。

どの属性カテゴリーとどのページが接続関係にあるのかが分かりやすくなりました。

対称性をもつランク付きパス図

以下は応用例なので参考程度に。

例えば、継続的に利用してくれるユーザークラス(継続クラス)と、最近利用してくれなくなったユーザークラス(休眠クラス)という2つのクラスにどのような行動パターンの違いがあるのかを確認したい場合、所属クラスや各クラスへの影響度合いなどを考慮するとより直感的に捉えることが可能となります。

図9は、おなじみのUCI machine leaning repositryのbreast cancer datasetを使用して、各クラスにのみ特徴的に出現したパターンを列挙し、視覚化した図です。

図9. 対称性をもつランク付きパス図

f:id:n_mao:20150928201235p:plain

以下では、パターンを構成する要素をアイテムと呼ぶこととします。

左(rank1〜3)が「再発しなかった患者クラス」、右(rank-1〜-3)が「再発した患者クラス」にのみ出現したアイテムを表し、ランク0に両方のクラスに出現するアイテムを位置させています。

ランク0以外のランクは、アイテムが所属するパターンの影響力の総和を、クラスごとに均等3分割したものです。

自己ループは、パタン長1で出現したことを表しています。

このように表現することで、各クラスに対するパターンの影響度を、アイテムレベルで直感的に把握しやすくなります。

終わりに

今回は、ユーザー行動を視覚化するいくつかのグラフ表現方法についてご紹介しました。

うまいグラフ表現を行うことで、鋭い洞察が行えるようになったり、かっこいいプレゼンを行うことができるようになるので、 ぜひトライしてみてください。

もちろん、これらの表現が全てではありませんし、最後の図9のように既存手法にひと工夫加えることで、より直感的な把握が可能になります。

大事なことは、何の情報が必要で、何が不要なのかを正しく取捨選択し、目的にあった表現方法を考えることだと思います

そのために引き出しは多い方が良いですね。

ということで他にも面白い視覚化方法がありましたら教えてください。

それではまた!

なぜ DI が好きなのか PHP / Laravel でやってみた

夏はとにかく苦手、夏生まれの@KJ_BACCHUSです。 外出なんてしてたまるかと自宅で何かやろうと思いたった今日この頃。 Webエンジニアとしての知識が乏しいのでスキルアップを目的にアプリを作成しようと思います。 当社にはスマホアプリエンジニア(主にAndroid)としてjoinしたのですが、Webアプリも携わるようになってきたのでWebの勉強をしようと決意したという感じです。 いろいろ手広く業務出来るのはスタートアップならではの醍醐味。非常にやりがいを感じる日々です。

言語/framework 選定

さて、なにでアプリを作ろうかなと。 だれもが悩み、また楽しい行程の1つであろう言語の選定です。 とは言え私はPHPで決定です。 当社既存サービスがPHPを使用している且つ私はPHPを使ったことがないので、勉強という名目のため1択です。 楽しい行程即終了です。。。 しかし、Frameworkは好きなものを選ぼう!と色々調査することに。

Laravelをチョイス

馴染み易そう!という印象を受けたので決定しました。 慣れないWebアプリ/PHPをやるならまずは自分のやり易いコーディングができるのが一番と考えました。 ということで、どういった所に惹かれたのかを書いていこうと思います。

惹かれたワード

  • DI ← 影響力強し
  • ディレクトリ構成が自由
  • 開発スピード重視のフレームワーク

DIが好き

ほぼこれに尽きます。 まず当社Androidアプリ開発において、DI(依存性注入)しているという背景があります。 Android開発者なら、Dagger(当社アプリでも使用)を使用しているという方が多いのではないでしょうか。 Laravelなら、ちょっとそれに似た感じでコーディングできそうという期待が膨らみました。

なぜDIが好きなのか?

DIはjavaのフレームワークではよく使われるようになってきていると思います。 テストが書き易くなると言うのが大方の意見でしょう。DIで検索すると「テスト」という言葉がよく見受けられます。

それはまさにその通りなのですが、私が好きな理由としては疎結合なコードが書けるというところです。 まぁそれが「テストし易い」ということと直結するのですから意味は一緒かもしれませんが。。。

ただしDIコンテナを使用すれば必ずしも「疎結合」「テストし易い」コードになるわけではないので勘違いしてはいけません。 DIを駆使して開発していくには、抽象化と上手につき合っていく必要があります。

そういった意味でDIコンテナを使用して開発する事は、「疎結合」なコードを書く訓練になると感じています。

つまりDIを使用して「疎結合」なコードにしようという姿勢が好きなのです。

抽象化(interface)

「疎結合」なコードにするために「抽象化」が大切と述べましたので例を挙げてみます。

before

<?php

class HolidayOfManA {
    public function wakeUp() {
        return '8時起床';
    }

    public function breakfast() {
        return '朝食は食べない';
    }

    public function mainActivation() {
        return '家でゲームをする';
    }

    public function dinner() {
        return '夕食はパスタを食べる';
    }

    public function goToBed() {
        return '23時就寝';
    }
}

?>
<?php

class HolidayOfManB {
    public function wakeUp() {
        return '6時半起床';
    }

    public function breakfast() {
        return 'トーストを食べる';
    }

    public function mainActivation() {
        return '映画館に行く';
    }

    public function dinner() {
        return '夕食は親子丼を食べる';
    }

    public function goToBed() {
        return '24時就寝';
    }
}
?>
<?php
class ScheduleController extends AppController {

    public function view() {
        $holidayManA = new HolidayOfManA();
        echo $holidayManA->wakeUp();
        echo $holidayManA->breakfast();
        echo $holidayManA->mainActivation();
        echo $holidayManA->dinner();
        echo $holidayManA->goToBed();
    }
}
?>

上記の「HolidayOfManA」「HolidayOfManB」クラスはそれぞれ、男A、男Bの1日の行動を返すクラスです。 「ScheduleController」クラスのview()メソッドでは、男Aの1日の行動パターンを表示しています。

現状のview() メソッドだと、メソッド内で「HolidayOfManA」クラスのインスタンスを生成しているため密結合なコードと言えます。

これを「疎結合」にするために「HolidayOfManA」「HolidayOfManB」クラスから共通処理を抽出し、「抽象化」します。 そして、ここからLaravelのDIの機能を使用して記述していこうと思います。

after

<?php namespace MyProject\Humans;

interface HumanLifecycleInterface {
    public function wakeUp();

    public function eat($timezone);

    public function mainActivation();

    public function goToBed();
}
<?php namespace MyProject\Humans\Eloquent;

use MyProject\Humans\HumanLifecycleInterface;

class HolidayOfManA implements HumanLifecycleInterface {
    public function wakeUp() {
        return '8時起床';
    }

    public function eat($timezone) {
        if ($timezone == 'morning') {
            return '朝食は食べない';
        }
        else if ($timezone == 'night'){
            return '夕食はパスタを食べる';
        }
        return '';
    }

    public function mainActivation() {
        return '家でゲームをする';
    }

    public function goToBed() {
        return '23時就寝';
    }
}

?>
<?php namespace MyProject\Humans\Eloquent;

use MyProject\Humans\HumanLifecycleInterface;

class HolidayOfManB implements HumanLifecycleInterface {
    public function wakeUp() {
        return '6時半起床';
    }

    public function eat($timezone) {
        if ($timezone == 'morning') {
            return 'トーストを食べる';
        }
        else if ($timezone == 'night'){
            return '夕食は親子丼を食べる';
        }
        return '';
    }

    public function mainActivation() {
        return '映画館に行く';
    }

    public function goToBed() {
        return '24時就寝';
    }
}
<?php namespace MyProject\Controllers

use MyProject\Humans\HumanLifecycleInterface;

class ScheduleController extends AppController {

    protected $lifecycle;

    public function __construct(
        HumanLifecycleInterface $lifecycle) {

        $this->lifecycle = $lifecycle;
    }

    public function view() {
        echo $this->lifecycle->wakeUp();
        echo $this->lifecycle->eat('morning');
        echo $this->lifecycle->mainActivation();
        echo $this->lifecycle->eat('night');
        echo $this->lifecycle->goToBed();
    }
}

HumanLifecycleInterfaceが「抽象化」したinterfaceです。 共通の振る舞いを抽出したファイルになります。

「ScheduleController」のview()メソッドでインスタンスを生成することはせずに、コンストラクタでクラスを注入しています。 これがDI(依存性注入)です。

ある人の1日のスケジュールを表示する「ScheduleController」クラスは、誰のスケジュールかを知る必要がないという考え方です。 コンストラクタで注入するクラスが変更されることで、表示されるものが切り替わります。

変更しなければならないクラスが独立されるので、「疎結合」なコードとなりました。

では一体どのように実体を注入するのかというと...

app配下のconfigにあるapp.phpのprovidersに以下を記述します

<?php

return [
    'providers' => [

        'MyProject\Providers\HumansServiceProvider',

    ]
];

そして下記のHumansServiceProviderクラスにてHumanLifecycleInterfaceに注入する実体を記載します。 そのため、ここで実体を切り替えることができます。

この場合だとHolidayOfManAが使用されることになります。

<?php namespace MyProject\Providers;

use Illuminate\Support\ServiceProvider;

class HumansServiceProvider extends ServiceProvider {
    public function boot(){}

    public function register() {
        \App::bind('MyProject\Humans\HumanLifecycleInterface', 'MyProject\Humans\Eloquent\HolidayOfManA');
    }
}

※この例ではコンストラクタインジェクションですが、Laravel5にはメソッドインジェクションというものもあります。

いかがでしょうか。Android開発でDIを使用している方は、そっくり!!と感じたのではないでしょうか。 私はまさに、この方法にかなり惹き付けられました。

コード設計の概念

「抽象化」ができるようになると、プログラムの構成についても色々と思うところがでてきます。

各役割を明確化し、処理間の依存度を低くする。 そのためにインターフェースが存在する。

こう考える事で、本来のオブジェクト思考な開発が思い出されるのではないでしょうか。

図で表記すると以下のようなイメージです。

※APIアクセスする時の構成をイメージしています。

f:id:KJ_BACCHUS:20150807092238p:plain

フレームワークを使用していたことで、MVCで作成しなければいけないと囚われがちになっている考えが変わると思います。

もしも、「MVCで分割する」って結局どうすればいいの?とカオスになっているのであれば、「抽象化」を通して晴れやかになるかもしれません。

「抽象化」により依存度を低くした結果が「MVC」であって「MVC」で作成するのかどうかは開発者次第になるのではないかと。 つまり必ずしも「MVC」にしようと意識するのではなくて、「疎結合」なコードにしようと心がけるようになるのではないでしょうか。

おわりに

結局本記事ではLaravelのに機能ついてはあまり触れれませんでした。。。 ほとんどDIについてで終わってしまいましたので、今後Laravelの機能についてもっと書いていければと思います。

スマホエンジニアがWebアプリの設計を考えたらこうなったと捉えていただければ幸いです。

Slack WebAPIでナイスなフォーマットのメッセージを送る

こんにちは。xyz_iです。

弊社ではチャットツールとしてSlackを使用しています。 メンバー同士のやりとりはもちろん、いろいろなイベントの通知先としてもとても重宝しています。 例えば、WebAPIを使い、Capistranoによるデプロイの実行時にSlack通知する方法のように使ったりもしています。

この記事は、Slack WebAPIでメッセージを投稿するとき、Message Attachmentsを使うといいことがありますよというお話です。

WebAPIにおけるメッセージ

Slackにメッセージを投稿する際、メッセージのフォーマットとして以下のような選択肢があります。

  1. プレーンテキスト
  2. Markdownテキスト
  3. Message Attachments

おそらく人間がSlackを使う場合は、1または2の書き方をすると思いますが、 githubなどの通知BOT(下の画像参照)を見てみると、より進んだ感じのメッセージになっていることがわかります。 このようなフォーマットで表示させるには、3のMessage Attachmentsを使います。

f:id:xyz_i:20150409095744p:plain

Message Attachments

Message Attachmentsは、メインのテキスト以外にもいろいろなメタ情報を含むことができます。 例えば、以下のようなものです。

  • pretext(概要などを入れたりする)
  • 著者(例えば、「ブログに記事が投稿されました」という通知の場合、ブログの作者)
  • タイトル
  • 画像

これらを決められた形のJSONフォーマットでWebAPIに送信することで、Slackがいい感じに処理してくれます。

やってみる

百聞は一見にしかずということで、とりあえずやってみます。

Incoming WebHooksを設定

https://○○○.slack.com/services/new(○○○は適宜変更してください。)にアクセスして、Incoming WebHooks欄のAddボタンを押します。

f:id:xyz_i:20150409102456p:plain

次の画面でチャンネルを選択すると、Webhook URLができていると思います。 それがAPIのエンドポイントになりますので、大事にメモしておいてください

メッセージの投稿

同じ画面にいろいろな説明と下のようなExampleがあると思います。

一度それを実行してみましょう。 (読みやすいように少し整形してあります。)

curl -X POST --data-urlencode\
  'payload={
    "channel": "#testroom",
    "username": "webhookbot",
    "text": "This is posted to #testroom and comes from a bot named webhookbot.",
    "icon_emoji": ":ghost:"
  }' \
  <Webhook URL>

okと返って来れば成功です。 以下のようなメッセージが投稿されていると思います。

f:id:xyz_i:20150409110532p:plain

Message Attachmentsで投稿

先ほどのcurlコマンドをベースに、メッセージの本文をMessage Attachmentsを使って書きなおしてみます。

curl -X POST --data-urlencode \
  'payload={
    "channel": "#testroom", 
    "username": "webhookbot", 
    "attachments": [
      {
        "fallback": "ブログに記事が投稿されました。(http://blog.howtelevision.co.jp/entry/2015/04/09/xxxxxx)",
        "color": "#36a64f",
        "pretext": "ブログに記事が投稿されました。",
        "author_name": "xyz_i",
        "author_link": "http://howtelevision.jp/",
        "title": "Slack WebAPIでナイスなフォーマットのメッセージを送る",
        "title_link": "http://blog.howtelevision.co.jp/entry/2015/04/09/xxxxxx",
        "text": "(ブログの冒頭や本文を全部入れても良いかもしれません。)"
      }
    ],
    "icon_emoji": ":ghost:"
  }' \
  <Webhook URL>

f:id:xyz_i:20150409110541p:plain

誰が何をしたかが明確に表せていると思います。 (画像ではわからないですが「xyz_i」という部分にもリンクがついています。)

今回はメッセージの本文がどう変わるかというところを強調したかったため、webhookbotという名前や:ghost:アイコンは変更していませんが、通知する内容によって適宜変更すると、より適切なメッセージにできます

まとめ

SlackのMessage Attachementsを使うことにより、メッセージをリッチにすることができます。 メタ情報が加わることでメッセージの情報量を整然と増やすことができ、色情報が加わることでひと目で何についての通知か(もしくは通知内容のステータスなど)認識できるようになります。

より良いSlackライフを!

データドリブンな組織を作るときにまず行うこと 〜我が社よデータ分析色に染まれ〜

はじめに

データ解析本部のn_maoです。

前回は高速集計ツールmコマンドのご紹介をしました。

前回のmコマンドの紹介の投稿

今回は趣向を変えて、社内に分析部隊をゼロから作り、データドリブンなサービス改善を実現するためにまず行うべきこと、意識することをまとめてみました。

これは実際にゼロから初めた私の経験に基づくものです。

1つのケーススタディとして読んでいただければと思います。

主張を大まかな流れに分類すると、

1. 分析環境を整える

2. 社員のデータに対する意識を高める

3. データ分析とサービス開発を結ぶ仕組みを作る

4. 小さな効果を体感してもらう

5. 現状を把握し、指標を作る

という感じです。

以下で各トピックの詳細について触れていきます。

1. 分析環境を整える

分析のためのサーバーを用意する

当然のことですが、念のため。

データ分析や集計を行っていると、どうしてもメモリやCPUに高負荷のかかる処理が発生します。

ここはケチらずに、分析を行うためだけに存在するサーバーを用意しましょう

分析用のデータベースを作る

そして、分析や集計業務を行いやすいように、分析用のデータベースを作りましょう。

サービスを行ううえで適したデータ構造と、分析を行ううえで適したデータ構造は異なります。

コツは、同じキーのデータセットはなるべくまとめることです。

ただし、毎回分割して処理をかけるようなことがあれば、同じキーでもあえて分割させて保存しておきましょう。

この辺は好みや実際に運用してみて、柔軟に変更してみてください。

図に表すとこんな感じです。適当ですみません。

f:id:n_mao:20150406142131p:plain

2. 社員のデータに対する意識を高める

最終的には、皆が自分で分析できるようになることが理想ですが、そうは言っても最初は何をすれば良いか分からないと思います。

まずは、日々のユーザーの動きであったり、売上げなどの成果がどのようになっているのかになるべく興味を持ってもらうところから始めましょう。

そのために、皆がデータを気軽に確認できる場所を作りましょう。

いわゆるダッシュボードというやつです。

最近よく開発されているBIツールを導入しても良いし、自社で1から作っても良いです。

個人的には、ダッシュボードとしては予測モデルや多変量解析などの機能が充実している高価なBIツールは必要ないと思っています。

3. データ分析とサービス開発を結ぶ仕組みを作る

さて、分析環境が整い、ダッシュボードも出来上がったら、そこからが分析者の本領発揮です!

分析者はここぞとばかりに良い分析をしようと張り切ります。

実際に客観的事実に基づいた有意義な分析結果が出て、それを現場に持って行ったとします。

分析者「こんな面白い結果が出たんですよ!」

   「ここ、改善しましょう!」

現場 「なるほどねぇ」

   「うん、そうだよね。ありがとう」

・・・・・・終わり!?

結局いつ改善されるんだ??

これ、意味あったのか??

このようなケースに陥ったことのある組織は多いのではないでしょうか。

以下ではそうならないように「意識すること」と「データドリブンな仕組み作り」について議論します。

意識すること

まずは一個人としての信頼を得ることです。これも当然ですが一応。

データ分析者は、実際に分析を行って、

「このサイトのここが良いんです!」

というだけでは意味がなくて(勿論それも重要ですが)、

「ここが問題だから、こんな改善をしてみてはいかがでしょうか」

と提案しなければなりません。

そして、その提案が通って初めて分析に意味ができます。

しかし、データ分析者というのは微妙な立ち位置です。

実際にサービスを作るエンジニアでもなければ、ディレクションもしていない。

営業もしていないし、ましてや社長でもありません。

そんな分析者の言うことに耳を傾けてもらうためには、

確かな分析スキルに加え、サービスのことを

  • どれだけ愛しているか

  • どれだけ考えているか

を日々伝えることが意外と重要になってきます。

そのためには、開発現場や営業の人と日々コミュニケーションをとることを心がけ、日々競合のチェックをすることを心がけましょう

もちろん、ちゃんとサービスを愛し、日々思いを巡らせましょう

仕組みについて

分析結果を開発に組み込み、高速なPDCAスパイラルを回すためには、ちゃんとした仕組みが必要です。

データドリブンにおいて重要なことは、データ至上主義に陥るのではなく、経験やセンス、勘も大事にしていくことです。

図で表すとこんな感じ。 f:id:n_mao:20150406153835p:plain

さらに、分析者が1人で企画まで考えるのではなく、皆で議論し解決策にたどり着くことも重要です。

以下の図は弊社で実践しようとしているPDCAサイクルの基本例です。 f:id:n_mao:20150406154117p:plain

もちろん目的はサービスが改善されることで、この流れを遵守することではないため、柔軟に調整していきます。

以下、各MTGの概要です。

①問題提起MTG

  • 目的:現状のサイトの問題点を議論、取り組む分析テーマを決める
  • 主催者:基本的にデータ分析者
  • 出席者:各部署から必須で1名の参加と、分析結果に興味のあるチームメンバー
  • 必要なもの:客観的事実に基づく問題や仮説が提起された資料
  • 補足
    • 時間を決めてメリハリをつける
    • 現状の共有だけでも定期的に開催する

②アイデア創出MTG

  • 目的:分析結果をもとに、どんな解決策があるかを議論する
  • 主催者:データ分析者
  • 出席者:各部署から必須で1名の参加と、分析結果に興味のあるチームメンバー
  • 必要なもの:
    • テーマに沿った正確な分析結果
    • サービスをより良いものにしたいというアツい想い
  • 補足
    • アイデアは思いつきレベルで構わない
    • 議論はなるべく発散させる
    • アイデアを発言する場であり、否定する場ではない
    • 時間を決めてメリハリをつける

③アイデア選別MTG

  • 目的:技術コストやインパクトの観点からアイデアを絞る
  • 主催者:データ分析者
  • 出席者:メインディレクター、メインエンジニア、メインデータ分析者
  • 必要なもの:アイデアリスト
  • 補足:
    • 選別するものがなければ開催しない
    • 多くても3つか4つに絞る
    • 選別基準は明文化する

④アイデア決定MTG

  • 目的:最高意思決定者により、アイデアを決定する
  • 出席者:意思決定者(PO)、メインディレクター、メインエンジニア、メインデータ分析者
  • 必要なもの:アイデアリスト

4. 小さな効果を体感してもらう

仕組みができたら今度こそようやく分析開始です!

しかしここでも1つ注意点があります。

いきなりホームランは狙わないでください。

分析環境がある程度整ったとはいえ、あなたの手元にあるのはまだ作り込みの甘いデータです。

データの性質もよくわかっていません。

そんななかで壮大な分析を行おうとすると、着地までにとても時間がかかることは目に見えています。

そもそも着地できるかどうか。

最初は手堅く小さな効果を出し、データ分析の効果を実感してもらいましょう

5. 現状を把握し、指標を作る

どんな分析をするにしても、目的が決まっていないと着地できません。

目的とは例えば、

  • 「当サイトにとって良いユーザーとは誰か」
  • 「当サイトの健康的な状態はどのような状態か」

などです。

これらを定量的に説明できなければ、分析は困難なものになります。

分析を本格的に開始する前に、ますは現状を調査し、指標を作りましょう。

さいごに

今回は分析の文化がない組織にデータドリブンなサービス開発を導入する際に注意したことを書きました。

サクッと書くつもりが、かなり長文になってしまいました。笑

これでようやく分析が開始できますね!

再度言いますが、これは小規模の会社の1ケースにすぎませんので、完全にこの形にあてはめようとせず、各組織で良いやり方を考えてみてください。

この投稿がきっかけとなって、データ分析者が実力を発揮できる組織が増えていってほしいなと願っています。

こんなことも気をつけたほうがいいとか、ご指摘あればコメントにてお願いします。