Cloud Dataflow で Cloud SQLからBigQueryにサーバーレスにデータ連携する

取引先で、Cloud SQL(Postgres)からBigQueryにアプリケーションのデータを連携させたいという話があって、いろいろ調べたのでまとめる。 最初はEmbulkとか使えばいいんかなと思ったけど、基本サーバーサイドはGAEしか使ってない状況でEmbulkをどこで動かそうか…って感じだったので、GCPのマネージドサービスであるCloud Dataflowを活用することにした。*1

アプリケーションの環境は以下のような感じ。

  • スマホアプリを提供している
  • Firebase Auth / Analyticsを使用している
    • Analyticsの情報はBigQueryに連携させている
  • APIサーバはGAE上にたっている
    • DBはCloud SQL(Postgres)を使用している

GCPのデータ処理関連のマネージドサービスについて

GCP上でデータをBigQueryに投入しようと思ってグーグルで調べるとCloud Composer、Cloud Dataflowという2つのサービスが出てくると思う。最初はこの2つの使い分けがよく理解できなくて混乱したのだけど、以下のようにユースケースが異なっているという理解をした。

  • Cloud Composer
    • マネージドなApache Airflow
    • Apache Airflowの公式ドキュメントAirflow is a platform to programmatically author, schedule and monitor workflows. とあるように、あくまでワークフローを管理するもの。
    • もちろんCloudSQL => BigQuery連携のジョブを書くこともできるけど、単発のジョブのために使うのはちょっとオーバーキルっぽいし、GKE上で常に動かすことになるのでややコストがかかる
  • Cloud Dataflow
    • マネージドなApache Beamの実行環境
    • Apache Beamは公式ドキュメントimplement batch and streaming data processing jobs that run on any execution engine. とあるようにデータのバッチ・ストリーミング処理を行うためのライブラリ・実装

というわけで複数ステップからなる複雑なデータ処理を行うならCloud Composerを使い、そうでなければCloud Dataflowを使えば良さそうという結論に自分はなった。もし今後複数のジョブの依存関係が出てきたら、そのときにCloud Composerを使って、Cloud Dataflowのジョブをいい感じにマネジメントすればよさそう。

Cloud Dataflowについて

自分は最初勘違いしてたんだけどCloud Dataflow自体はあくまで実行環境なので、それ自体にジョブを登録しておいて定期実行するとかそういった機能はない。ただ処理のテンプレートをGCSにアップロードしてそれを使ってジョブを起動させることはできるので、Cloud Scheduler / Cloud Functionsと組み合わせると定期バッチ処理の仕組みがサーバーレスで実現できる。これについては後述する。

Cloud Dataflow のテンプレート

上述したようにCloud Dataflowはテンプレートという機能があり、事前に作成したテンプレートを使用してジョブを実行することができる。 例えばGoogleが提供する jdbc to Bigquery のテンプレートを使いたい場合には以下のように必要なパラメータを渡してあげることで条件を変えて実行させることができる。ちなみにCloud DataflowからCloud SQLにつなぐ場合には、Cloud SQL側でprivate IPを有効にして、同じネットワークから実行してあげればよい。

gcloud dataflow jobs run <your job name> \
    --project=<your project id> \
    --gcs-location gs://dataflow-templates/latest/Jdbc_to_BigQuery \
    --region=asia-northeast1 \
    --parameters \
driverJars=gs://<your-bucket>/postgresql-42.2.6.jar,\
driverClassName=org.postgresql.Driver,\
connectionURL=jdbc:postgresql://10.7.xxx.xxx:5432/xxxx,\
query='select * from users',\
outputTable=<your_project_id>:<your_data_set>.users,\
bigQueryLoadingTemporaryDirectory=gs://<your_bucket_nanme>/bq/tmp_dir/,\
username=user,\
password=password

Cloud SQL => BigQuery連携がこれで事足りる場合にはこれでいいんだけど、このテンプレートには以下のような制限がある。

  • BigQuery側に予めテーブルとスキーマの設定を済ませておく必要がある
  • APPENDしかできないので、アプリケーションのデータのように定期的に更新のかかるデータを連携できない
  • 一つのジョブで1クエリ => 1テーブルしか連携できない

自分は以下のような形でアプリケーションDBからBigQueryへデータを連携させたかったので、自分でカスタムのテンプレートを作って対応することにした。

  • 予めジョブ側に定義したYAMLにクエリ定義とBigQueryのスキーマ定義を書いてデータを連携させたい
  • 更新のあるデータがあるので、毎回データは洗い替えたい
  • 複数のクエリ結果を同時にBigQueryに連携させたい

Cloud Dataflowのテンプレートを作る

カスタムのテンプレートを作成するにあたっては以下のドキュメントが参考になる。

テンプレートの作成  |  Cloud Dataflow  |  Google Cloud

しかしApache Beamを理解して1から処理を実装するのは結構ハードルが高いので、Googleが提供するテンプレートをカスタマイズしていくのがよさそう。Cloud Dataflowのコンソールから選択できるテンプレートは以下のGitHubのRepositoryで管理されている。

github.com

例えば、今回やりたいことの参考になりそうな JdbcToBigQueryのコードは以下。 DataflowTemplates/JdbcToBigQuery.java at master · GoogleCloudPlatform/DataflowTemplates · GitHub

JdbcToBigQuery.java を参考に1から処理を書いてもよかったのだけど、このクラス自体がリポジトリ内の他のクラスにかなり依存していたので、ちょと横着だけどリポジトリ自体をフォークして以下のようなYamlを用意しておけばクエリ結果をBigQueryに書きだせるようなクラスを新たに作成した。

- query: "select * from users"
  output_table_name: users
  fields:
    - name: id
      type: INT64
      mode: REQUIRED
    - name: avatar_url
      type: STRING
      mode: REQUIRED
    - name: nick_name
      type: STRING
      mode: REQUIRED
    // パイプラインを作るところの抜粋 
    ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
    mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);

    List<BigQuerySchema> bigQuerySchemas = mapper.readValue(
            new File(Resources.getResource("schema/bigquery/app_schema.yaml").getPath()),
            new TypeReference<List<BigQuerySchema>>(){}
    );

    bigQuerySchemas.stream().forEach(schema -> {
      pipeline
              .apply(
                      "Read '" +  schema.getQuery() + "' from JdbcIO",
                      DynamicJdbcIO.<TableRow>read()
                              .withDataSourceConfiguration(
                                      DynamicJdbcIO.DynamicDataSourceConfiguration.create(
                                              ValueProvider.StaticValueProvider.of("org.postgresql.Driver"),
                                              options.getConnectionURL())
                                              .withUsername(options.getUsername())
                                              .withPassword(options.getPassword())
                                              .withConnectionProperties(options.getConnectionProperties()))
                              .withQuery(ValueProvider.StaticValueProvider.of(schema.getQuery()))
                              .withCoder(TableRowJsonCoder.of())
                              .withRowMapper(JdbcConverters.getResultSetToTableRow()))
              .apply(
                      "Write to BigQuery: " + schema.getOutputTableName(),
                      BigQueryIO.writeTableRows()
                              .withoutValidation()
                              .withCreateDisposition(BigQueryIO.Write.CreateDisposition.CREATE_IF_NEEDED) // テーブルがなければ作成する
                              .withWriteDisposition(BigQueryIO.Write.WriteDisposition.WRITE_TRUNCATE) // 既存のテーブルを消して書き込む
                              .withSchema(schema.getTableSchema())
                              .ignoreUnknownValues()
                              .withCustomGcsTempLocation(options.getBigQueryLoadingTemporaryDirectory())
                              .to(new CustomTableValueProvider(schema.getOutputTableName(), options.getOutputDataset())));
    });

    // Execute the pipeline and return the result.
    return pipeline.run();

ValueProviderというものの概念がなかなか難しかったのだけど、Apache Beamでは RuntimeValueProviderStaticValueProviderNestedValueProvider の3つのValueProviderがあり、パイプライン作成時(テンプレート作成時)とパイプライン実行時に参照できる値が区別されていて、パイプライン作成時にエラーにできるものはエラーにするような設計思想になっているようだった。

ちなみに、テンプレートはPythonで記述することもできるのだけれど、RDBの読み込みに現時点では対応していない(公式でないライブラリで提供しているものはある)、SDKPythonの2.7しか対応していないということで、Javaを選択した。

beam.apache.org

テンプレートは以下のようなコマンドでGCSにアップロードできる。自分はCloud Buildを使って、masterにマージされたら自動でアップロードされるようにCIを設定した。

mvn compile exec:java \
     -Dexec.mainClass=com.github.suusan2go.dataflow.templates.AppDbToBigQuery \
     -Dexec.args="--runner=DataflowRunner --serviceAccount=dataflow-jobs@<project_id>.iam.gserviceaccount.com \
                  --project=<project_id> \
                  --stagingLocation=gs://<your_bucket>/staging \
                  --templateLocation=gs://<your_bucket>/templates/AppDbToBigQuery"

Cloud Scheduler / Cloud Functions を用いたDataflowジョブ定期実行の仕組み

前置きがだいぶ長くなったけど、上記で準備したテンプレートとGCPのサービスを使えば、連携ジョブを定期実行させることができる。

f:id:suzan2go:20190704152555p:plain

  • 事前準備
    • Cloud Dataflowのテンプレートを作成する
  • 処理
    1. Cloud SchedulerがCRONの時間に従いトピックにメッセージを発行
    2. pubsubをトリガーに設定したCloud FunctionsよりCloud Dataflowのジョブを API経由で実行
    3. ここで事前準備で作成したCloud DataflowテンプレートのGCSパスを指定する
    4. Cloud Dataflowでテンプレートを元にジョブを実行
    5. ジョブが失敗した場合にはStackdriver Alertingで設定したポリシーにより、Slackにアラートを通知

Cloud Shceduler からCloud Functionsを実行する

Cloud Scheduler からCRONを設定すればよい。HTTPでCloud FunctionsのURLを叩くようにしてもいいし、pubsubを使っても良い。自分はpubsubを使った。 f:id:suzan2go:20190704171533p:plain

Cloud FunctionsからCloud Dataflowのジョブを実行する

なかなかCloud Dataflow をキックするAPIが見つからなかったのだけど、以下のブログが参考になった。 medium.com

const { google } = require("googleapis");
const dataflow = google.dataflow("v1b3");

const BUCKET_NAME = process.env.BUCKET_NAME;
const DB_URL = process.env.DB_URL;
const DB_USERNAME = process.env.DB_USERNAME;
const DB_PASSWORD = process.env.DB_PASSWORD;
const PROJECT_ID = process.env.GCLOUD_PROJECT;

module.exports.appDBtoBQ = async (event, context) => {
  const jobName = `appdb-to-bigquery` ; // Dataflowでは同名のジョブは同時実行できないので、常に同じジョブ名にしておけば意図しない重複実行を防げる
  const tmpLocation = `gs://${BUCKET_NAME}/tmp`;
  const templatePath = `gs://${BUCKET_NAME}/templates/AppDbToBigQuery`;
  const request = {
    projectId: PROJECT_ID,
    requestBody: {
      jobName,
      parameters: {
        connectionURL: `jdbc:postgresql://${DB_URL}`,
        outputDataset: `${PROJECT_ID}:app_db`,
        bigQueryLoadingTemporaryDirectory: `gs://${BUCKET_NAME}/bq/tmp_dir/`,
        username: DB_USERNAME,
        password: DB_PASSWORD
      },
      environment: {
        tempLocation: tmpLocation
      }
    },
    location: "asia-northeast1",
    gcsPath: templatePath
  };
  return google.auth
    .getClient({
      scopes: ["https://www.googleapis.com/auth/cloud-platform"]
    })
    .then(auth => {
      request.auth = auth;
      // 元のブログではdataflow.projects.templates.launchになっていたが、regionを指定するときには 
     //  dataflow.projects.locations.templates.launchにする必要があった
      return dataflow.projects.locations.templates.launch(request);
    })
    .catch(error => {
      console.error(error);
      throw error;
    });
};

Cloud Dataflow のジョブ失敗をStackdriver Monitoringで監視する

ジョブの失敗をどう検知するかというところで自分は結構困っていたのだけど、 Stackdriver Monitoring を使えばかなり簡単に実現できた。 具体的には以下のように dataflow.googleapis.com/job/is_failedというズバリなメトリクスがあるのでそれをStackdriver Monitoringで監視してあげればよい。

f:id:suzan2go:20190704172433p:plain

EmailやSlack等への通知も設定できて、Slack通知は以下のようになる。

f:id:suzan2go:20190704172818p:plain

まとめ

GCPのマネージドサービスを組み合わせることで、CloudSQL から BigQueryへのデータ連携をサーバーレスで実現することができました。自分はこれまでこういった分析基盤の利用側だったのですが、いざ自分で作ってみると知らないことや分かってなかったことが多くて(特にBigQueryの型とか更新制限とか…)、これまで基盤を作ってくれた方は頑張ってたんだなぁという気持ちになりました(こなみかん)。

参考にしたブログ

Cloud Dataflow がテンプレートにより気軽に使えるサーバーレスのサービスに進化した話 - google-cloud-jp - Medium

サーバレスにバッチ処理をしよう!@GCP | キャスレーコンサルティング株式会社

nouhau/dataflow/example/multi-source-multi-sink at master · gcpug/nouhau · GitHub

How to kick off a Dataflow pipeline via Cloud Functions

Apache Airflow で作る GCP のデータパイプライン @ 酔いどれGCPUG 2017/11/28

リレーショナル データベースから BigQuery に ETL を実行する  |  ソリューション  |  Google Cloud

*1:GKEとか立ってるんだったらKubernetesのCronJobとかでEmbulkを動かすのが楽そうな気がしている。

エムスリーを退職してフリーランスになっていました

TL;DR

  • 2019年2月にエムスリーを退職してフリーランスになっていました。
  • お仕事の相談お待ちしています。

何で今更書くの

www.m3tech.blog

2月に前職のRailsアップグレード記事と見せかけた退職エントリを書いていたのだけど、ちゃんと書いてなかったので改めて書きます。 辞める月に某異常にTwitterでフォロワーの多い機械学習エンジニアの方が入社して隣の席にいたので、「俺もnoteで退職エントリ書いて有料にして売りますよwww」とかイキってましたが機を逸したのでやめます。

エムスリーでは何をやってたの

レガシーシステムのリニューアルを中心にKotlin / Nuxt.jsとかやっていて、その後はAI機械学習チームというところで、新規事業の機械学習部分以外のアプリ / インフラをやったり、次の機械学習基盤の調査のためにGKE使ったCI / CDのPOCを作ったりしていました。

employment.en-japan.com

AI機械学習チームはCS強い人が集まっていて、そういう環境で働いたことがなかったのでめっちゃ刺激的でした*1。最近は外から見てもますます存在感が出てきてほんとすごいなーと思います。昨日も「エムスリーは機械学習強いですよねー」と言われてビビりました。

また採用関連のあれこれをやる採用チームというところにも所属していて、自分は主にテックイベントのスポンサーとか、エンジニアが働きやすくなるようなツールの導入なんかを頑張ってました(Slackとか)。自分が入社したときには「おいおい2017年にこの環境はまじかよ……」みたいなところも正直ありましたが、今はWEB系企業としてはそんなに悪くない感じになってるんじゃないでしょうか。自分がめっちゃやりましたみたいな書き方になりましたが、謙遜とかではなく自分の貢献はSlackやデファクトなツール類をいくつか使えるようにしたくらいで、西場さんを筆頭に色んなチームや人のやっていきで少しずつ改善されていきました。

会社としてめちゃくちゃROIを重視する文化で大変な面もあったんですが、そういう環境でもがいたおかげでエンジニアとして視座はかなり上がりました。根がテキトーな人間なので、バランスがよくなったと言えるのかもしれません。

フリーランスになって今は何をやっているの

基本これまで働いたことのある人がいる会社、あるいはそこから1ホップくらいの知り合いがいる会社で以下のようなことをやっています。

去年の11月に二人目が生まれたので「子供が生まれたからフリーランスになったんですか?」とよく聞かれたんですが、別にそういうわけではなりません。ただ、働いてみるとフリーランスの働き方のほうが色々と都合がよい事が多くて、少なくとも下の子が離乳するまではフリーランスでやろうかな〜と思っています。とはいえそんなに長く続けるつもりもなくて、関東IT健保の任意継続が切れるまでには、また普通に正社員として働こうかなってかんじです。

お仕事の相談お待ちしています

WEBアプリケーション開発に関することなら大体できますが、雑にやれることを書くと以下のような感じです。

  • 結構やれる
  • まあまあやれる
  • あんまやったことないけど今やってる
    • Flutter

基本リモートで働きたいので「週5フルで会社来てくれ!!!」みたいなのは無理ですが、たまに打ち合わせは対面でやりたいーみたいなのは対応できます。 直近は結構埋まってしまっているのですが、まずはDMでご相談いただければと思います。

twitter.com

単価は大体以下の本でいうシニアエンジニアくらいとなっております。

booth.pm

最後に

エモい退職エントリが読みたい / 書くぞと散々言っていましたが、特に当たり障りのない内容になりました・・・・・・

*1:XXXX(WEBフレームワーク)のXXXはどういうアルゴリズム使われてるんですか?とか聞いて来る人はじめてみた

車を買った

車を買った。

地元では車は生活必需品だったが、首都圏では何かしらの公共交通機関が基本的に徒歩圏内にあるし普通に生活する分には車を買う理由がないように思う。もともと車にはそんなに興味がなく、このまま関東で暮らすなら車を買うことはないかもなーと思っていたのだけれど生活上ないと困るようになってしまったので、購入することにした。

なぜ車が必要になったか

二人目の子供が生まれたのが大きい。子供が一人のときはまだよかったのだけれど、二人になると子供を抱っこして出かけて家に帰ってくるだけで疲れ果ててしまう…*1また子供2人を抱えてバスや電車に乗るのはとてもしんどい。二人目の子供が生まれてから家族で買い物にいくのがかなり大変になってきてしまったので、車を購入することを決めた。

何を買ったか

いわゆるVOXYとかALPHARDとかデカめのミニバンはもう5〜6年運転していない自分にはきつそうだし、普通のセダンタイプやコンパクトカーでは収納スペースに不安がある…ということで、TOYOTAのSIENTAとHONDAのFREEDに絞った。最終的には義父の知り合いで懇意にしているTOYOTAの販売店の方がいたこともあり、SIENTAに決めた。

車の購入手続きって色々申請とかしないといけなくてめちゃくちゃ面倒な印象を持っていたけど、基本販売店の方が自宅に書類も持ってきてくれたし手続きも代行してくれたので、書類に記入とハンコしてお金を振り込んだりするだけで手続きが済んだ。

買ってみて

これまで子供を連れて電車でいけるショッピングモールに行くと自宅に帰ってくるころにはヘトヘトになっていたのだけど、車なら子供を連れて移動しても体力を残したまま自宅に帰ってくることができた。

またこれまで公共交通機関では行きにくい場所には当然ながら足が遠のいていたのだけど、車で移動できるようになってかなり行き先の選択肢が広がった。

あとこれは結構驚いたのだけど、車を運転することが結構好きになってきた*2。最近は休日になると理由をつけてどこかにドライブに行きたくなっている!子供も出かけるの楽しいみたいなので、買ってよかったなーと思っている。

あと最近の車の進化すごい。自分が過去に乗っていたのは安い軽自動車だったので当たり前なのだけど、スマホとつながったり便利な機能がたくさんついていて、ロボットに乗っているようで楽しい。

まとめ

二人目の子供が生まれてから必要に迫られて車を買ったのだけど、車楽しい。でも今年の家庭の収支は大赤字なので(当たり前)、お仕事もっと頑張らないなーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

*1:3歳の方は行きは自分で歩いてくれるけど、帰る頃には疲れて抱っこモードになる

*2:上達したとは言っていない

認定スクラムマスター(Certified ScrumMaster)を取得した

いまお手伝いしている会社でスクラム導入を支援していて、自分もスクラムマスター(兼開発者)をやっている。 これまでにスクラムに関する本はいくつか読んできたし実戦経験もあったが、改めてスクラムについて深い理解を得たいと思い認定スクラムマスター研修(以下、CSM研修)に申し込みをした。

研修について

私が受講したCSM研修はMichael Jamesさんという方が講師で(基本は英語だが日本人のAgileコーチの方が通訳してくれる)、3日間というスケジュールで研修が行なわれた。 研修を受けるだけで無条件でCSMに認定されるわけではなく、以下のようなプロセスを踏んで初めて認定となる。

  • CSM研修を3日間受講する
  • CSM研修でオンライン受験資格があることを認められる
  • オンライン試験をパスする

研修はチームで行うワークショップ形式のトレーニングが多く和気藹々と行なわれたが、研修を終えればかならず受験資格がもらえるわけではないようだ。以下のような注意が申し込みページにものっていたし、申込み後のメールでも送られてきた。

  • 全時間受講が義務づけられております。遅刻や早退、途中退室は無条件で認定できません。
  • パソコンや携帯電話の使用等、ルール違反は認定できません
  • 本トレーニングでは、受講中の能力をもとに評価し、オンラインテスト受験資格(=認定候補者)を付与しますので、積極的な能力アピールを必要とします。参加するだけでは認定となりませんのでご注意ください

とはいえ、よっぽど受講の態度が悪かったとか消極的だったとかでなければ、受験資格はもらえるのではなかろうか。ただ過去取得した人の話だと、遅刻して受験資格が与えられなかった人がいたり、レポートを追加で提出することを求められたりということはあったようだ。

学んだこと

スクラムの具体的なやり方については、LeSS (Large-Scale Scrum) など知らないこともあったが、70%くらいは既に知識としては知っていた内容ではあった。この研修で良かったのは、具体的な方法論というよりは、スクラムの考え方、原則などをアジャイルソフトウェア開発宣言なども交えながら、ワークショップ形式で実体験として学べたことだ。講師の方が初日に「皆さんのこれまでの経験をunlearnする魔法があればスクラムマスター研修は1日で終わります」と言っていたが、まさに3日間かけて従来型のマネジメント・プロセスの考え方をunlearnしてもらっていた感じだった。

頭では認識していたものの、実は実践できていなかったなと気付かされたのは以下。

  • ソフトウェア開発は複雑で予想の難しいカオスな領域の仕事であることを認識する
  • ある程度の曖昧さ・不確実さを受け入れる

そして何となく思っていたものが言語化されたのは以下。組織の中の個人が自分の行動をROIで図ることに対して違和感がすごかったのだけど、きれいに言語化された感覚がある。

  • 不確実性の高い分野では生産性より学習を重視する

そしてこれはスクラムの話じゃなくてアジャイルマニフェストの一文ではあるけど、以下。特に最近バックログを必要以上に詳しく書いてもらおうとしたり、新たなプロセスを組もうとしていたのだけど、反省した。ただ対話することが一番の解決の場合も多いのだ。

  • プロセスやツールよりも個人と対話を

スクラムではどんな組織構造になっているべきか、featureチームとcomponentチームを対比して説明・ワークショップがあった。マイクロサービスが流行っているが、どういう開発組織が良いのかということを考える機会になった。マイクロサービスを志向する会社でも、 componentチームになっていて依存関係が爆発していて、開発効率が上がってないという事例はありそうだなと思った。

自分の参加した会がたまたまそうだったのかもしれないが、SIer / コンサル系から来てる人が多く、プロダクト開発ではなくプロジェクトマネジメントを期待して研修に来ている人がとても多かった気がする。そもそも今ウォーターフォールで…とか、開発はベンダーに投げてて…みたいな人が結構多くて、現場でスクラムどうしてるみたいな話が他の参加者とあまり出来なかったのは少し残念だった。 *1

まとめ

この研修は結構お高い*2のだけれど、これからスクラムやっていく人や、スクラム始めたけどピンと来ていない人、マネージャーなど開発組織づくりに関わっている人は、一度受けてみることをオススメします!

*1:ただ、そういう人たちも、最終日になると「組織を変えて行かなきゃ!」みたいな姿勢になっていたのが印象的だった。

*2:自腹で30万はなかなかキツかった

「Measure What Matters 伝説のベンチャー投資家がGoogleに教えた成功手法 OKR」を読んだ

流行ってるので読んだ。

内容について

著者であるジョン・ドーアというGoogleに投資した投資家が、Intel で学びGoogle含む投資先の企業に伝えたOKRという手法についての本。

それぞれの企業が OKRをどのように活用したのかというケーススタディを中心として、OKRはどのように設定するべきかやOKRをどのように運営するかという話が展開されていく。どちらかというと経営層の立場から、OKRを組織にどのようにインストール / 運用するか、という話が多い。そのため1社員として、どのようにOKRを設定するべきかのようなHow Toを期待すると面食らうかもしれない。

感想

OKRについて「野心的な目標としてObjectiveを、それを図る指標としてKey Resultsを決める」くらいの認識しかなかったし、過去職場に導入されたときもOKRを導入することで何かが良くなるなんていうことには懐疑的だった。しかしこの本を読んで、それは自分がOKRを「個人の目標管理手法」くらいにしか捉えていなかったからなんだなと気がついた。OKRは最終的には個人も設定はするものの、根本は「組織として何にフォーカスして、何にコミットするのか」を明確にするということなんだなと思う。

だからOKRを元にどう組織を運営していくのかということが重要で、個人がどうOKRを立てたらいいかといった話はOKRの一部に過ぎない(もちろん適切に設定することは大切)。だから組織として何にフォーカスするかというOKRの設定無しに、個人がそれぞれ勝手にOKRを設定してもあまり意味がない(これまでの目標管理とあまり変わらない)ということが分かった。 OKRを実践するには、適切なOKRの設定だけでは全く不十分で「これはKRのXXXに寄与するからやろう」とか「これはどのKRにも寄与しないんじゃないか?」みたいな会話が現場でできる必要があるんじゃないかと思う。

OKRはあくまで組織として大きな成果を出すための手法なのだということを理解すると、OKRでよく言われる以下の項目がだいぶしっくりくるようになる。

  • 全メンバーのOKRは共有されている必要がある
  • OKRを給与評価と連動しない

上述したとおり、適切なOKRの設定方法みたいなHow Toを提供してくれる本ではないのだけれど、1社員の立場で自分の立てるOKRはどういうものが望ましいのかということのエッセンスはつかめた気がする。 自分の目標というよりも、自分の役割の中で何をすれば会社のOKR達成につながるか、と捉えてOKRは設定したほうがよいのだろうなー

2018年の振り返り

2018年にやったことの振り返り。年末に書いていたのだけど熱を出して寝てたので年が明けてしまった・・・

大まかな仕事としてはこんな感じ。平行して採用関連の仕事や、他チームの支援なんかもやっていた。

  • 1-6 月 レガシーシステムのリニューアル (Kotlin + Spring Boot + Nuxt.jsなど)
  • 7-11月 機械学習チームに異動しての画像認識を使った新サービス開発(Rails + Vue.js + Flask + TensorFlowなど)
  • 12月 2人目が生まれたので育休

仕事

レガシーシステムリニューアルやった

上半期の振り返りに大体書いた。自分は主軸を機械学習チームに移したが、もともとのチームでちゃんと機能開発などできている状態なのは嬉しい。 suzan2go.hatenablog.com

機械学習チームに異動した

7-11月に機械学習チームに異動していた。とはいえ自分自身は機械学習をやっていたわけではなく、機械学習を使った新サービスの機械学習部分以外を全部やっていた感じ。全体のアーキ設計からAWS等のインフラ、アプリケーションの実装まで、機械学習そのもの以外のところは全部やれたので楽しかった。機械学習を活用したアプリケーションだと、メモリがめっちゃ食うとかGPU使わないと遅いとか普通のWEBアプリとは違う考慮ポイントが沢山あって設計のしがいがあった。

前述したとおり機械学習そのものは触らなかったのだけれど、機械学習エンジニアの作ったモジュールを動かしたり、 TensorFlowが動く環境作ったりするのはそれだけで面白い。AWSで環境をTerraformで作るところも、機械学習エンジニアの作ったモジュールを組み込んだPythonAPIサーバを作るのも、ユーザー側画面のRailsも、そのフロントのVue.jsも、ほぼ自分一人でやってたので、途中は死にそうだったけど、PM / 事業責任者がMVPを理解してくれていて仕事がやりやすかった。

他チームの支援した

他チームでレガシーシステムのリニューアルやっているところがちょっと炎上していたので、プロジェクトの支援を一ヶ月くらいやっていた。具体的には以下のようなことをしていたと思う。

上述の機械学習チームでの新サービス開発、イベントでの登壇など重なっていて正直キャパオーバしていて、あまりちゃんと支援できなくて申し訳ないなという気持ち。。。それでも一緒にやってもらえて助かったと言われたのが救い。

採用まわり

採用そのものというより、イベントのスポンサー関連の仕事が多かった気がする。ノベルティ作ったり、ブースの対応なんかはだいぶ知見が溜まってきていて、自分が関わらなくても普通に回るようになっているのが嬉しい。Vue Fesのスポンサーで、会社のロゴが入ったビールを、Vue.js公式Twitterで取り上げてもらえたのは、最高だった。

他には、リモートワークを始めるためのルールとかその辺の整理とかやったりした。他社と比べると、環境面ではまだまだというところも多いので改善していきたい。

この振り返りとは直接関係ないんだけど、他社のリモートワーク・副業の状況を表にしてみると、リモートワークはイメージほど認められてない(メルカリも調べた限りではやってないし、認めている会社も週1までとか制限が多い)けど、副業を認めていない会社は大手WEB系でも殆どなかったので驚いた。

育休

11月下旬に二人目が生まれたので、そこからすぐに育休をとった。一人目は特に育休はとらなかったのだけれど、二人目ということもあり取得した。一人目のときに比べて自分たちの育児スキルがあがっているということもあり、赤ちゃんのお世話は自体は一人目と比べるとだいぶ楽。上の子と下の子が同時にグズったときは本当辛いけど、上の子がだいぶお姉さんやってくれるようになってきたので、何とかなりそうな気がしてきた。2019年1月から復帰です。

登壇

2018年は意識的に登壇回数を増やした。 Kotlin Fest 2018、Vue Fes Japan 2018 Reject Conferenceといった100人以上の参加者がいる会場で発表できたのがよかったなと思う。JS、Kotlin、Rubyと3つのコミュニティで登壇できたの何気にすごいと思っている(自画自賛)

あとgRPC-Webについての資料が自分の資料では過去最高記録ではてブがついて嬉しかった。*1

roppongi.js

社内テックトーク

roppongi.js

meguro.rb

Kotlin Fest 2018

meguro.rb

Vue Fes Japan 2018 Reject Conference

登壇ではないけどエンジニアHubに取材してもらったりも。怖くてはてブのコメント見てなかったけど好意的なものが多くて安心した。

employment.en-japan.com

インプット

2018年の前半ではDDDに関する本を読んだりしたけど、読んだのは全体的にマネジメント・採用に関する本が多かった。特に読んでよかった本としては以下。

実践ドメイン駆動設計を読んだ - suusan2号の戯れ

ティール組織を読んだ - suusan2号の戯れ

「チームが機能するとはどういうことか」を読んだ - suusan2号の戯れ

「エンジニアリング組織論への招待」も読んだし面白かったけど、個人的には「ティール組織」の方を推したいと思います。

所感

技術的には本当に色々できた1年だったと思う。仕事でいろんな言語やFWを触ったことで、自分のなかで設計・実装のレベルを一つ上げられたような感覚がある。 また今までWEBアプリケーションのインフラ構築を一から自分でやった経験は仕事ではなかったのだけれど*2、Terraform使ってAWS環境を作るところを一通りやれたのはよかった。

一方で上に書いたことと微妙に矛盾するのだけれど、さらに自分が触ったことのない言語やFWを使ったWEBアプリケーションの開発を経験しても、現時点ではそれほど成長していけるイメージがない。もうすこし何かを突き詰めるか、全く別のことをやらないと行けない気がしている。そうなると自分が目指すべきはEMとか、SREとかになるのかなぁ。社内にげきつよ機械学習エンジニアがいるので、その人に師事して機械学習エンジニアを目指すのもありかもしれない*3

あとはこの1年で複数のプロジェクトを渡り歩いたので、もうすこし腰を据えてプロダクトに取り組みたいという気持ちもあったりする。今の所、これやってみたい!と思えるようなのは社内にはないのだけれど。

2019年の抱負

今年の抱負を書こうと思ったのだけど、仕事においては特に思いつかなかった。育休で一ヶ月以上家族と向き合ってるからかもしれない。

思いつかなかったけど、今年は車買わないといけない波動を感じているので、1.5ばんくし くらいもらえるように頑張りたいと思います。5000兆円欲しいです。

あとがき

下書きのまま年が明けてしまったので、2018年に書いた「今年」を「2018年」に置き換えるのがめちゃだるかった

過去の振り返り

suzan2go.hatenablog.com

suzan2go.hatenablog.com

suzan2go.hatenablog.com

suzan2go.hatenablog.com

*1:はてなブックマーク - フロントエンドエンジニアも知っておきたいgRPC - Speaker Deck

*2:既存の構成に何か追加 / 削除する程度はやったことあった

*3:ジョークです