ITANDI TECH BLOG

イタンジのスタッフブログです。イベントや技術情報などを発信しています。

プロダクトロードマップとは巨大なフレームワークの表層部分

この記事はProduct Manager Advent Calendar 2016の23日目のエントリーです

横澤です、本年はお世話になりました。来年もよろしくお願い致します。

プロダクトマネジメントの勃興】 本日はプロダクトマネジメントにおけるプロダクトロードマップの位置付けについて思うところがあったので書いてみました。ここ二、三年くらいでしょうか、プロダクトマネジメントという単語、というか概念が流行ってきている感があります。プロダクトマネジメントとは何か?プロダクトマネージャーは何をする人か?まだプロダクトマネジメントで消耗してるの? 的な事が各所で語られているのを見かけます。

プロダクトマネジメントにおけるプロダクトロードマップという業務】 私の理解ではプロダクトマネージャーの重要な役割の一つにプロダクトロードマップ(PRD:ProductRequirementDocと呼ばれる事もあるようですが以下PRMと略します)をアウトプットしてメンバーの指標とする役割があると認識しております。ですが、プロダクトロードマップのお手本というのはあまり見た記憶がありません。冷静に考えてみればその会社のPRMが見られるという事は、サービスの方向性やセグメントとかフェーズ認識とか会社や事業として重要な思念が色々と見えてしまうのでカジュアルに公開する訳にはいかない様な気がします。

とは言え作ろうと思ったら試しに見てみたいので色々とググったのですがこんな資料を発見しました。シンプルisベストという事でしょうか。他にもガントチャート型の例なども見かけましたが、個人的には「マイルストーンを大きめな粒度で描いたスケジュール表」という受け取り方をしています。分かりやすさという意味ではこのシンプルさは良いのでしょうけど、これだけ見せられて納得感があるのか?というのがどうも腑に落ちないところでした。

【プロダクトロードマップの背後に潜むコンテキストの重要性】 丁度昨年度の始め辺りに上に書いたようなモヤモヤした気持ちを持ちつつもググって調べたフォーマットや独自の考えを用いてPRMを作成したのですが、モノの見事に失敗しました。結構な時間と気合を入れてそれっぽいアウトプットをしたのですが、結果としては現在のプロダクトと乖離しているので仕事としては失敗したと考えています。失敗した理由を改めて考えてみると大きく分けて3つの理由があったと振り返っています。

  • 提供する機能は明確に記載されているが、それがもたらす価値についての記載が希薄だった

  • 最終的には文章と画でアウトプットされたが、そこに至るまでの分解されたKPIや数字の関係性が抜け落ちていた

  • 細かく書きすぎ且つ、一つ上のレイヤーで抽象的にまとめられておらずスッと記憶されない

おおざっぱに言うとメンバーに公開する際の圧縮率が足りてないのと、最終アウトプットに至る途中資料の作り込みが足りないという結論を得ました。良いPRMというのは高度に抽象化されたMVCフレームワークみたいなイメージで、普通にWEBアプリを作る上では必要最低限の規約を理解すれば充分で、より深掘りしたくなった際には、複雑ながらも全体を通して一貫性のあるクラス構造によって支えられていて、読み進めるウチに入口であった規約の背後に潜む思想がより強靭に理解されるようなモノだと考えました。つまりRuby on RailsみたいなPRMは良いPRMだろうという事です。

【事業計画とPRMは表裏一体】 そんな事を考えている中、今年もPRMを作る機会がありました。反省を活かして凝縮されたシンプルな作りを目指すのですが、どうも納得する水準に達さない出来のままに、途中で会社全体の事業計画を作る業務に移りました。事業計画にはマイルストーンとして「この事業(≒プロダクト)はこのタイミングでこんな事が実現されている」みたいな事を書きこんでいたのですが、それを見て「PRMの一枚裏にあるコンテキスト資料とは事業計画なのではないか?」という考えが頭をよぎりました。その考えを辿った結果、会社のミッション>事業を通して実現したいビジョン>サービスやプロダクト個別の事業計画(ビジネスモデルやKPIツリーが含まれる)>PRMというレイヤー構造として理解でき、それぞれの資料の繫がりを自分の中で整理する事ができるようになりました。

【何が言いたいのか】 開発メンバー等に共有するPRMのフォーマットはやはりシンプルに凝縮されたフォーマットが望ましいと思います。ただ、PRMが産み出されたコンテキストについては、メンバーが知りたいと考えた時にどこまでも深掘り出来て、最終的にはそれが会社のミッションやビジョンという最上位レイヤーから繋がった概念である、と理解できる設計になっている事も重要だと考えています。プロダクトマネジメントをする上ではUXデザインであったりビジネスデザインであったりと考慮すべき領域が多岐に渡るのですが、それぞれがどういうレイヤー構造で企業思念に結びついているのかをもやもやしながらも少しは理解を進歩出来たと思う一年でした。

ちなみにイタンジでは共にプロダクトの成長を楽しんでいけるメンバーを絶賛募集しております。

来年もどうぞよろしくお願い申し上げます。

crawleraを使ったクローリングの最適化

これは日本情報クリエイト Engineers Advent Calendar 2016の24日目の記事です。 元日本情報クリエイトのエンジニアなのでOB枠として参加させてもらいます!

日本情報クリエイトは宮崎で不動産系の自社プロダクトを開発し、日本全国に販売している会社です。 九州にUターンを考えている方、九州の南のほうにお住まいのエンジニアの方、転職先としておすすめです。

はじめに

皆さんクローラー作ってますか? 以前こちらにも書きましたがscrapy + scrapy cloudを使うと簡単に安定稼働するクローラーを構築できます。 今日はscrapy cloudを提供しているscraping hubが展開しているもう一つのサービスcrawleraをご紹介します

crawleraとは

英語ですがここのページに記載されています。 https://crawlera.com/

簡単にまとめると以下の様なことを実現出来るクローラー専用のproxyサービスです

  • 数千のIPプールを介してのリクエス
  • 50カ国以上のIPが利用可能
  • 130種類以上のステータスコード、またはキャプチャを含むバンの自動検出
  • 自動再実行及び、遅延処理でリクエストを抑制してバンを防ぐ
  • HTTPとHTTPSをサポート

便利ですね、ipの付け替えやバンの検出及び自動再実行を自前でやろうとするとそれなりにコストがかかりますがその辺をまるっとやってくれます。

使ってみよう

以下の物が必要です。

  • scrapinghubのアカウント
  • クレジットカード(crawleraは無料版がないため料金の支払いが必要です)

https://scrapinghub.com/にアクセスしてアカウントを作成し、crawleraを契約してください。

crawleraのアカウントを作る

Create Accountをクリックします

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-12-24-14-53-46

アカウント名を入力してリージョンを選択します。 ここで選択したリージョンのIPアドレスが使用されます。 allを選択すると各国のIPプールの中でIPを付け替えてくれます。 今回は日本を選択します。

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-12-24-14-58-49

作成するとOverviewが表示されます、ここではcrawleraでリクエストしたものがどれくらいバンされたり失敗したのかやどこのサイトにどれくらいアクセスしたのかをグラフで確認出来ます。 また残り何回リクエスト出来るかもここで確認出来ます。

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-12-24-15-03-16

使ってみる

作成したcrawleraアカウントの設定画面にcurlを使ったコマンド例があります、これをコマンドラインに貼り付けて実行してみます。

curl -U [API KEY]: -x proxy.crawlera.com:8010 http://httpbin.org/ip

するとリクエスト元のIPアドレスjsonで返ってきます。 試しに何回か実行すると毎回違うIPが返ってくることがわかります、crawleraさんがちゃんとプールされたIPの中から毎回違うIPをチョイスしてくれてますね。

実行後実行したアカウントをcrawleraの管理画面から選択するとリクエストの履歴を見ることが出来ます。 client ipから実際にリクエストで使ったipレスポンスタイム等必要な情報を全て見ることが出来ます。

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-12-24-15-16-35

また各行のResp. Timeにマウスオーバーするとどれくらい遅延を入れたかが表示されます。 crawleraさんが自動で遅延処理を入れてくれていることが分かります。

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-12-24-15-21-35

後は今使っているクローラーのproxyにcrawleraを指定すれば完了、簡単ですね。 scrapyをお使いの場合は専用のライブラリが用意されているのでpip installして設定するだけです。 詳細はこちらに記載されています。

https://doc.scrapinghub.com/crawlera.html

終わりに

いかがでしたか、crawleraを使うと拍子抜けするほど簡単にクローリングを最適実行する環境とダッシュボードを手に入れることが出来ます。 ただ実際に稼働しているクローラーに入れたところパフォーマンスが1/3まで低下してしまいました。 これはcrawleraが自動で遅延処理を入れてくれるのはいいんですが15秒とか平気で遅延させるためです。 パフォーマンスが求められるクローラーの場合はただ入れるだけだと大変なことになるので同時リクエスト数を増やす等のチューニングが必要です。

ReduxとReact Routerの相性が悪いのでrouterを一から書いてみた

こんにちは、エンジニアの建三です。

Reactと一緒に使うRouterと言えばReact Routerですよね。しかし僕のReact+ReduxアプリにReact Routerを導入してみると、どうも思うようにいきませんでした。

Reduxは"Single Source of Truth"をモットーにしており、Reduxのstoreがアプリのstateを全て管理しています。しかしReact Routerを使うと、React Routerがrouteを管理しReduxがそれ以外を管理するというぎこちない感じになります。

React Routerの代わりを探す旅に出た

そんなぎこちなさをGoogleにぶつけてみると、同じような考えを持ってる人が沢山いました。React Router v4が出た時のHacker NewsではReact Routerの批判のコメントが多く見られ、代替案が多数提示されました。

React Router以外のRouterを調べてみると沢山出てきますが、どれも使い方がイマイチ分からなく断念...

するとこのブログで「そもそもroutingにlibraryなんているの?」というのが書かれており、読んでみました。早速試してみると少しのコードでrouterが自分で作れ、「これでいいじゃん」と思いました。

ただ先ほどのブログでは色んな詳細が省かれており、Reduxの話が全くされていません。Reduxの話はこちらのブログが参考になりました。一つ一つのrouteをreduxのアクションにしてしまおうという非常にシンプルな方法です。RouteをJSXで定義するReact Routerに比べこちらの方がフレキシブルだししっくりくるなと思いました。

Routerを作ってみよう!

必要なlibraryはhistoryだけです。これはブラウザーWindow.historyとほぼ同じAPIですが、ブラウザーによる違いをなくすために、Window.historyを直接使わずこっちを使います。React Routerもhistoryを使っています。

まずはインストールします。

$ npm install --save history

次にメインのrouterを作ります。基本的な使い方は上記のリンクを参照して下さい。 URLが変わる度にhistory.listenが呼ばれます。 location.pathnameがその名の通りpathになるので、それを好きなように処理してReduxにdispatchします。

import createHistory from 'history/createBrowserHistory'
import store from '../store.js'

export const history = createHistory()

function handleNavigation(location, action) {
  // e.g., 'examples/123/' => ["examples", "123"]
  const pathList = location.pathname.split('/').filter(o => o !== '')
  // examplesをrootに指定
  const path = pathList[0] || 'examples'

  else if (path === 'examples') {
    store.dispatch({type: 'ROUTE_EXAMPLES'})
  }
  else if (path === 'guide') {
    store.dispatch({type: 'ROUTE_GUIDE'})
  }
  else if (path === 'projects') {
    store.dispatch({type: 'ROUTE_PROJECTS'})
  }
}

handleNavigation(history.location)
history.listen(handleNavigation)

reducerでそれぞれのアクションを処理します。ただのstatic pageの移動だったら以下のようにrouteを変えるだけで十分ですが、勿論ここで他のstateを変えることが出来ます。

function reducer(state, action) {
  switch (action.type) {
    case 'ROUTE_EXAMPLES': {
      return {
        ...state,
        route: 'examples',
      }
    }
    case 'ROUTE_GUIDE': {
      return {
        ...state,
        route: 'guide'
      }
    }
    case 'ROUTE_PROJECTS': {
      return {
        ...state,
        route: 'projects'
      }
    }
    // ...
  }
}

そしてrouteによってコンポーネントを切り替えます。

import React from 'react'
import store from '../store.js'
import { Link } from './my-router'

import Examples from './Examples'
import Projects from './Projects'
import Guide from './Guide'

function getChildren(route) {
  if (route === 'projects') {
    return <Projects/>
  }
  if (route === 'examples') {
    return <Examples/>
  }
  if (route === 'guide') {
    return <Guide />
  }
}

const App = React.createClass({
  componentDidMount: function() {
    store.subscribe(() => this.forceUpdate())
  },
  render: function() {
    const state = store.getState()
    const route = state.route
    const children = getChildren(route)

    return (
      <div>
        <nav className="navbar navbar-default">
          <div className="container-fluid">
            <div className="navbar-header">
              <Link to='/' className="navbar-brand">Geeklish</Link>
            </div>

            <div className="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
              <ul className="nav navbar-nav">
                <li><Link to='/examples'>Examples</Link></li>
              </ul>
              <ul className="nav navbar-nav">
                <li><Link to='/projects'>My Projects</Link></li>
              </ul>
              <ul className="nav navbar-nav">
                <li><Link to='/guide'>Guide</Link></li>
              </ul>
            </div>
          </div>
        </nav>

        {children}

        <footer>
        </footer>
      </div>
    )
  }
})

上記にLinkコンポーネントがありますが、これも基本的なものであれば簡単に作れます。React Routerと同じAPIにしています。

import React from 'react'

const isLeftClickEvent = (e) => e.button === 0
const isModifiedEvent = (e) => !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey)

export const Link = React.createClass({
  handleClick: function(event) {
    if (event.defaultPrevented || isModifiedEvent(event) || !isLeftClickEvent(event)) {
      return
    }
    event.preventDefault()
    history.push(this.props.to)
  },

  render: function() {
    let props = Object.assign({}, this.props)
    props.onClick = this.handleClick
    props.href = this.props.to

    return (
      <a {...props}>{this.props.children}</a>
    )
  }
})

たったこれだけでrouterの完成です!

大規模なアプリになるともっとちゃんとしたコードを書かなければいけないですが、最初のうちはこれで十分です。

上記に書いた通りhistory APIブラウザーに入っており、それを使うだけで誰でもrouterが作れます。やはりフロントエンドエンジニアはブラウザーを知ることが重要だなというのを今回学びました。

僕が作ってるアプリはまだrouteが複雑じゃないし、ほぼSingle Page Applicationなので、このまま自家製routerを使っていきます。

Reactを使ってる方には是非一度routerを自分で作ることをオススメします。数時間で書けますし、React Routerや他のroutingのlibraryをより理解出来るようになります。

参考資料

https://news.ycombinator.com/item?id=12511419 http://beautifulcode.1stdibs.com/2016/09/20/redux-url-router/ http://jamesknelson.com/even-need-routing-library/ https://github.com/mjackson/history

Hamburger Menu VS Tab - 有名なアプリ15個のUIを調査!

icons_no_borders

こんにちは、エンジニアの建三です。最近はデザインの仕事が主になってきています。新規事業のモバイルアプリのプロトタイプをSketchInvisionでせっせと作る日々です。それに伴いUIデザインを最近勉強し始めたんですが、デザインってすごく面白いですね。

このモバイルアプリですが、素早く顧客のフィードバックを得る為にWebviewを使ってくれという指示がありました。Webviewというのは、アプリ上でWebページを表示するものです。FacebookとかTwitterのリンクをアプリでクリックすると、ブラウザーに飛ばずに、FacebookTwitterのアプリ内でWebページが見れますよね。要するにモバイルウェブサイトをWebviewで表示してアプリ化しようというものです。これだとアップデートする度にAppleGoogleに申請する必要がなくなります。

このアプローチを取る場合、iOSAndroid用に別々のUIを作るのが難しくなります。OSによってCSSを切り替える事は出来ますが、大幅な変更は面倒そうだし、それで開発期間が延びたら本末転倒です。

iOSAndroidの一番顕著な違いは、ナビゲーションの方法です。iOSはタブを使うのが一般的ですが、Androidだと「ハンバーガーメニュー」と呼ばれる左上の3本線のボタンを押してメニュー画面を開くのが一般的です。どちらかに絞りたいんですが、iOSハンバーガーは不自然だしAndroidでタブも不自然なのではという気がします。ただ普段僕はiPhoneしか使いませんし、普段使ってるアプリでもそんなにデザインに気を使った事がないのでどっちにすればいいか分かりません。

そこで、巷の有名なアプリはiOSAndroidでどっちのナビゲーションを採用してるか調べる事にしました!

対象のアプリは僕のiPhoneに入ってるアプリの中で有名なもの15個。

僕のNexus7にそれらを全部インストールしてAndroidも確かめました。

ナビゲーションのバリエーションは大きく分けて4つあったので、それぞれに分けて見てみましょう。

iOS - タブ、Android - ハンバーガ

対象アプリ: Dropbox, Trello, Evernote

これは一番僕が予想していたパターンです。

Dropbox

dropbox

Trello

iOS

trello_ios

Android

trello_android

Evernote

iOS

これはタブと呼ぶのかどうか微妙なラインですが、どちらかというとタブなのでこのカテゴリに入れました。

evernote_iphone

Android

evernote_android

iOS - ハンバーガー、Android - ハンバーガ

対象アプリ: Inbox, Google Calendar, Google Map, Slack, Uber, Kindle

これはGoogleのMaterial Designを使ったアプリが中心になります。

Inbox

inbox

Google Calendar

iOSだけになりますが、Androidもほぼ同じです。

google_calender

Google Map

Androidもほぼ同じです。

google_map_ios

Slack

slack

Uber

Androidもほぼ同じです。

uber

Kindle

iOS

kindle_ios

Android

OLYMPUS DIGITAL CAMERA

iOS - タブ、Android - 上タブ

対象アプリ: messenger, facebook, Twitter, Youtube

これはAndroidの場合タブが上に来るパターンです。

messenger

iOS

messenger_ios

Android

messenger_android

facebook

iOS

facebook_ios

Android

facebook_android

Twitter

iOS

twitter_ios

Android

twitte_android

YouTube

iOS

youtube_ios

Android

youtube_android

iOS - タブ、Android - タブ

対象アプリ: Airbnb, Instagram

僕の予想に反して、AndroidでもiOSと同じようにタブを使っているアプリがありました。

Airbnb

iOS

airbnb_ios

Android

airbnb_android

Instagram

instagram

まとめ

色んなバリエーションがあり、答えは一つじゃないというのを実感しました。タブは1タップで画面を切り替えられるので便利です。一方でハンバーガーメニューは、SlackのチャンネルやKindleのチャプターの様に多くのものを入れるのに向いてます。またGoogle MapやUberの様に地図がメインのアプリでもハンバーガーメニューが好まれるようです。

新規事業のアプリでは両方のプロトタイプを作ってみた結果タブの方が良いという意見が上がっています。最終的にどちらになるかは出来上がってからのお楽しみですね!

Androidの戻るボタン

おまけにAndroidの戻るボタンがどう処理されるかも調べました。ほとんどのアプリは戻るボタンが予想通り動いたのですが、幾つかのアプリが予想と違う動きをしました。以下のアプリの動作で戻るボタンが効かずにアプリが終了しました。

  • Google Calendar - 1日、1週間、1ヶ月などの表示の切り替え
  • Slack - チャンネルの切り替え
  • Dropbox - FilesからPhotosへなど、メニューの切り替え
  • YouTube - 上タブの切り替え

Google CalendarとSlackに関してはホーム画面を切り替えてるイメージなので何となく分かりますが、DropboxYoutubeは意外でした。アプリが終了しても開き直せばいいだけなので大した問題ではないのですが、戻れるに越したことはないと思います。

最後に

イタンジではプロトタイピングからコーディングまで何でもやりたいデザイナー・エンジニアを募集しています!

Twilio × Lambda × API Gateway で PRIMARY HANDLER FAILS を制御する

イタンジエンジニア、濱田です。

今回は、twilioを使っているサービスに障害が発生したときに、slackに通知したり、twilioにかかってきた電話を転送する仕組みを、aws lambda と aws api gatewayで実現する方法についてお話します。

背景

弊社では、twilioを使った自動応答サービスを展開しています。 このサービスに障害が発生したときに、次の3つを行う必要があります。 (この場合の障害は、サービスで起こったもので、twilio先生の障害ではありません。)

  1. そもそもの障害の検知
  2. twilioの050番号にかかってくる電話を、クライアントの03番号等に安全に転送してあげる
  3. 転送が行われたかの通知

1番目の検知は、様々な方法があるのでここでは割愛します。 2番、3番を実現するために、PRIMARY HANDLER FAILS を使う方法がありますよね。

かつては、サービスに障害が起きた時のために電話番号毎に作ったxmlファイルをs3に置き、そのurlを設定していました。 これでは、転送先の電話番号がクライアント毎に異なるため、大量のxmlの管理が発生してしまいます。 しかも、転送の通知をSMSに通知する設定をしており、社内の担当者が変わった時には、全てのファイルのSMSの送信先を変更するという作業が伴うものでした。

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-12-07-19-06-17

そこで、aws lambda と aws api gatewayを使って、 

  1. twilioの転送結果をslackに通知して、エンジニアチーム全員で監視
  2. 障害発生時のアクションも、gateway側に設定して、一括管理

することにしました。

構成

今回の構成です。

cloudcraft-web-app-reference-architecture-1

ネットワーク設定等妥協して、lambdaと api gatewayが2セットあります。。。。

  • PRIMARY HANDLER FAILS に 設定される api gateway の endpoint
  • 上記のend pointから実行されるlambda1: slack通知と、転送先の電話番号のような情報を返す
  • lambda1が叩く、転送先の電話番号のような情報を取得するための、api gate way の endpoint
  • 転送先の電話番号のような情報を、RDSから取得して返すlambda2

実際のコード

lambdaの使い方、api gatewayの使い方、そして RDSから情報を取ってくる api gateway と lambdaの部分は省略します。

まずslack通知と、かかってきた電話の転送先を返すlambdaです。 今回はpythonです。

# -*- coding: utf-8 -*-
import urllib
import json

def lambda_handler(event, context):
    slack_url = SLACK_URL
    # アカウント情報取得は省略
    ## resultに入っている
    # slackに通知する時の文言
    text = """=======================================
    なんかおかしいから、〇〇クライアントにかかってきた番号を転送したよ!
    Phone_number: {0}
    client_name: {1}""".format(event['param']['To'], result["client_name"])

    params = {"text": text, "channel": "#channel", "username":"tenso-shitayo"}
    f = urllib.urlopen(slack_url, json.dumps(params))

    # ”とかで囲う必要があった
    twilio_phone = '"' + result["phone_number"] + '"'
    to_phone = '"' + result["transfer_phone"] + '"'

    # ここで返した値を、gateway側で設定する。
    return {'twilio_phone':twilio_phone, 'to_phone':to_phone}

次にapi gateway

まず統合リクエストの本文マッピングテンプレートを、application/jsonに変更し、下記コードにします。 ここで、paramsをlambdaにわたす際の整形を行います。

{
  "param": {
#foreach( $key in $input.params().querystring.keySet() )
    "$key": "$input.params().querystring.get($key)"#if( $foreach.hasNext ),#end
#end
  }
}

次に統合レスポンスの、本文マッピングテンプレートをapplicaiton/xmlに変更し、下記コードにします。 ここで、twilioさんにやってもらいたいことを記述します。

今回は、転送と、転送先が全て通話中だった場合に、謝罪してもらっています。

#set($inputRoot = $input.path('$'))
<Response>
    <Dial callerId=$inputRoot.twilio_phone >$inputRoot.to_phone</Dial>
    <Say>"ただいまお電話が大変込み合っております。しばらくたってから、おかけ直し下さいませ。"</Say>
</Response>

最後に、メソッドレスポンスの、200のレスポンス文を、application/xml emptyモデルにしてデプロイ

後は、PRIMARY HANDLER FAILS に api gateway の endpointを設定しておけば、転送と、転送したことの通知をslackに通知してくれます。

まとめ

lambda と api gatewayを使えば、twilio の PRIMARY HANDLER FAILSの選択肢はどんどん増えて行く気がします。

後は、Serverless Framework等で管理できるといいのですが。。。。 それはこれからがんばります。

Reactを毛嫌いしてるが実は好きになりたい人へ

react_logoこんにちは、エンジニアの建三です。今までは機械学習に関する記事ばかり書いていましたが、実はフロントエンドも大好きです。

僕がWeb開発を始めた3年前はJS Framework全盛期だったので、JQueryをすっとばしてAngularから入りました。その後数々のLibraryやFramework(Ember, Backbone, Meteor, etc...)を試したのですが、どれも常に何かしらの不満を抱えていました。

2年前からReactの話を聞き始め、ちょくちょく触ってはいたのですが、どうもよく理解出来ず毛嫌いしていたんですね。 しかし最近個人プロジェクトを始めたのを機に、初めて本気でReactを勉強しました。そしたらなんと!やっと理解出来ました! Reactは理解出来ると面白いです。

正しい学び方をすればReactは理解出来ます。なので今回はReact歴3ヶ月の僕なりにReactを学ぶコツを書きます。昔の僕のようにReactを毛嫌いしてる人の参考になればと思います。

1. Functional Programmingを学ぶ

Reactの思想を理解するにはFunctional Programmingの知識が必要不可欠です。特にReduxはFunctional Programmingを使うしかないので、避けて通れません。LispHaskellClojureなど何でも良いので、Functional Programmingの基礎を身につけておくと後々楽です。

2. Javascript(ES6)を学ぶ

例えばAngularだと、htmlの中にループやif elseなどのロジックをガンガン埋め込めます。その時にng-repeatのような特別なsyntaxを学ぶことになります。なのである程度まではJavascriptを勉強しなくてもいけます。

しかしReactはロジックを全てJavascriptで書くので、あくまでJavascriptの延長です。つまりJavascriptを知らないと初っ端から「何だこれ意味わかんね」となります。そこで「Angularだったらもっと簡単なのに」と思ってしまうのはフェアじゃないですね。

逆にJavascriptを学べば、特別なsyntaxをあまり覚えなくて済みます。JS Frameworkの比較は炎上の元なので避けたいですが、これはReactの良いところだと思います。Angularだと、Javascriptを書いてるというよりAngularを書いてるような感じになるので、何か変わったことをしようと思った時に結構困ります。

そしてReactのチュートリアルはほぼ全部ES6を使ってるので、ES6は必須です。ES6によってJavascriptが更にfunctionalになりました。例えばES5では変数をイニシャライズする時varを使いますが、ES6ではconstletが出てきました。これはScalavalvarに似ています。よく使うES6のコンセプトはそこまで難しくないのでサクッと学べると思います。

3. Reactを学ぶ

次にReactを学びます。大抵どのJS frameworkもオフィシャルのチュートリアルでは足りません。僕はDocumentationを読んだだけで理解出来ないので、本やネットのリソースを探します。その際に僕が一番重要視してるのが新しいかどうかです。Reactに限らずJS Frameworkは進化のスピードが恐ろしく早いので、6ヶ月前に書かれたものでも怪しかったりします。その点では、普通の出版社を通してる本は書かれてから出版されるまで何ヶ月もかかるので、フロントエンドを学ぶ媒体としてあまり向いていません。ビデオコースも同じようにバージョンの更新が不可能なので不向きです。

オススメは、頻繁にアップデートされるオンラインチュートリアルあるいはPDF Bookです。探しまくった挙句fullstack reactにたどり着きました。サンプルチャプターを読んで感動し速攻買いました。非常に分かり易くReactを説明してます。

4. Reduxを学ぶ

Reactで本格的なアプリを書く時はReduxはほぼ必須と言っても良いでしょう。ただ、Reactではどうしても無理だという時になって初めて使い始めた方が良いと思います。あくまでReactの基礎を知ってからじゃないと、ReactとReduxを同時に覚える事になり相当キツイです。

Reduxに関しても上記のFullstack Reactでかなり分かり易く説明しています。ReactとReduxを繋げるreact-reduxというものがありますが、僕は使ってません。おそらくもっとアプリが成長したら使うかもしれませんが、初めの段階ではメリットが感じられず余計なアブストラクションを導入するだけです。

5. 環境構築を学ぶ

Reactは環境構築が面倒なので、create react appを強くオススメします。これはFacebookが出してるBoilerplateなので、サポートがしっかりしていますしチュートリアルが豊富にあります。

create react appはwebpackというフロントエンドのmodule bundlerを使ってるので、webpackの事は少しは知っておく必要があります。https://github.com/verekia/js-stack-from-scratchがcreate react appを使わずReactの環境構築をすごく分かりやすく説明してるのでオススメです。

6. NodeとExpressを学ぶ

これは必須ではないかもしれませんが、バックエンドとのやり取りを説明してるものは大抵nodeとExpressを使ってるので、知っておいた方が良いと思います。

React Native

今イタンジの新規事業のアプリ開発でReact Nativeを検討しており、もくもく会を開くなどして社内のエンジニアが全員React Nativeに触れる機会がありました。まず気づいたのは、リソースが少ないという事です。React NativeでもReactを使うので、React Native専用のリソースが少ないのは当然と言えば当然です。

Reactは初めはWebだけのものでしたが、React Nativeが出てくるタイミングで、元々のReactをReactとReact DOMという2つのLibraryに分けました。なのでReactはコアの部分を指し、WebにもMobileにも使われます。Reduxも同じようにどっちにも使われます。なのでReact Nativeを学ぶと言っても実質Reactを学んでる事とほぼ変わらないです。どのReact NativeのリソースもReactとReduxを知ってる事を前提にしてるので、初めに上記のプロセスを踏む事をオススメします。

たまにReactを知らなくても直接React Nativeを学べるというのを見かけます。これは嘘なので無視しましょう。もし行けるとしても、結局Reactについて遅かれ早かれ学ぶことになります。そしてReactのリソースはWeb開発に関してのものの方が豊富にあるので、そっちでReactをマスターした方が楽です。

その他

Reactのエコシステムは巨大で、多くのLibraryが存在します。上記でも何度か話しましたが、必要ないものは使わないことをオススメします。そうじゃないとキリがないです。例えばBootstrapをReact用にしたreact bootstrapというものがあります。Bootstrapをコンポーネントとして使えるのでReactっぽく書けますが、こういう"React-X"ばかり使い始めるとどんどんFramework依存症になりよくないなと個人的に思います。コンポーネントは簡単に作れるので、Bootstrapを使って自分でボタンなどのコンポーネントを書いた方がReactの理解が深まるしデバッグもし易いです。

まとめ

Webの進化を追っていくのは楽しいのと同時にとても大変で、日々勉強していないとあっという間に置いて行かれます。しかも色んな新しいLibraryに振り回されやすいので、どのツールが必要なのか見極める能力を磨く為に日々精進してます。

イタンジではReactに限らずJavascriptが好きでたまらないフロントエンドエンジニアを募集しています!

サービス毎にとっちらかったMySQLデータベースをfluentd経由でBigQueryに集約してDWH作っちゃうゾ★の巻

横澤です、平素よりお世話になっております。

昨今は機械学習とか人工知能というワードがバズっている影響もあり、ビッグデータとかDWH(データウェアハウス)というワードも関連して話題に上がりますね。 ビッグデータと一口にいってもその形態やフェーズは様々で、いきなり機械学習アルゴリズムを使って分析出来る綺麗なデータもあれば、フランケンシュタインの如く継ぎ接ぎをして何とか使えるレベルのデータになるかな・・というとっちらかったデータまで様々です。そして大体の場合はビッグデータと言っても後者の場合が多く、本日はそういうお話です。(機械学習とか分析の話は出てきません)

イタンジではtoC向けサービスのノマドVALUEを始め、toB向けにもぶっかくんノマドクラウドと様々なサービスを展開しております。そして、開発効率を高めるために基本的にはサービス間を疎結合にするべくデータベースも分断されて設計しております。(物件のデータベースなど、当初から共有を前提としたデータも存在します)

サービスが走り出す前に整合性の取れたデータ設計を出来ていれば「データ溜まってきたね、よーしパパ分析しちゃうぞー」というテンションにもなるのですが、時系列が揃わずに走り出したサービス間で整合性が取れている事は割りと少ないのではないかと思っていたりします。当初からワンプロダクトにフォーカスしているのならば設計しやすいのですが、イタンジの様に小規模ながらも様々なサービスを展開している会社ってどうしているのでしょうね。。。そういう会社のエンジニアさんとデータ周りについてお話してみたいです。

サービスが上手くいってお金もデータも溜まってくると「あれ?このデータってどうやってあのサービスのデータと整合性取るんだっけ?」という課題が浮上してきます。データ量が少なかったり、単純に結合出来るならばどうとでもなるのですが、ログデータのように一杯溜まってるデータとかを別サービスのデータと結合してフンフンとかなるとMySQL単体ではキツイ場面も出てきてしまいます。

%e3%82%bf%e3%82%99%e3%82%a6%e3%83%b3%e3%83%ad%e3%83%bc%e3%83%88%e3%82%99

という訳でBigQueryです。もはやfluentdやBigQuery自体はありきたりなネタですので、個別サービスの細かい説明についてはこの記事この記事なんかを参考にして下さいませ。イタンジでは一手目として、日々増える物件データとぶっかくんというtoBサービスのコールログデータを集約して分析できるようにしました。具体的には下記のような構成で特に難しい事はやっていません。

%e3%82%b9%e3%83%a9%e3%82%a4%e3%83%88%e3%82%991

実際に導入した結果、新たなサービスに繋がるかもしれないデータが取れるようになっています。当初は数千万同士のcross joinの結果を出してみようと考えていたのですが、BigQueryと言えどそれはさすがに無理ゲーだったので、バッチで回したり普通のjoinで上手いことやれる範囲を見つけています。「そもそも何をどうやったらcross joinが必要になるんだ?」という感想を抱かれるかと思いますが、かなり込み入った内部事情なので・・・詳しい事を聞きたい方は個別にご連絡下さいませ。

という訳でカジュアルに大きめのデータをぶち込んでも、分析の為に良い感じで構造化されたデータとして取得できる、という当初の目的はBigQueryである程度果たせました。また都度増えるデータについてもfluentdを使ってストリームインサートして増やし続けています。初期データ投入についてはCSVにdumpしてGoogleCloudStorageにアップしてimportしました。当初はローカルからimportしようとしてハマりました・・・BigQueryに大きめのデータをimportする場合はGCSを経由するとスムーズです。

最後にお金の話です、良いことづく目のBigQueryですが「でも、お高いのでしょう?」という疑問がわきます。ぶっちゃけ恐ろしく安いです。当然AWSのRedshiftも検討したのですが、料金面・速度要件を考えてもBigQueryが適切だったので選択しました。この辺りの技術分野も進歩が早いので、また違う構成が最適になるかもしれないですが取り敢えずはfluentd+BigQuery構成にしています。

イタンジでは「ログデータだけじゃ足りないでしょ、音声データも含めてデータレイクにぶち込みましょう!」というデータ解析基盤を進化させてくれるインフラエンジニアを募集しています!