スクラム開発を始めるときに自分がやったこと

この記事は suusan2go Advent Calendar 2019 - Adventar の2日目の記事です。

今年の前半にお手伝いしていた某社で、スクラム開発の導入をしました。自分が開発チームに入ったタイミングでは、カンバンツールを使って週次で振り返り(KPT)とタスクの状況確認が行われており、特定のチームはなく大きめな機能開発については案件ごとに非エンジニアも含めたチームが組まれているような状況でしたが、以下のような課題感を強く持ちました。

  • 同じタスクがいつまでもカンバンに残り続けていて、リリースサイクルが遅い
  • エンジニア間で機能開発のコンテキストが共有されていないので、レビューコストが高い
  • 1ヶ月以上の期間開発されたのに、仕様変更やビジネス上の都合により結局リリースされないものがある
  • これらの問題を解決・改善していけるような仕組みがない

この状況を改善するためにスクラム開発の導入を進めたのですが、どんなふうに始めていったか自分の振り返りも兼ねて、またこれから始める人の参考になるようにまとめておきます。

スクラム開発始める前編

現状の課題感を言語化する

既に箇条書きで当時感じた課題を書いちゃってますが、自分の課題感はリリースサイクルが遅い というところから始まっていて、それを徐々にWikiにまとめて言語化していきました。スクラム始めよう!となると全てがスクラムで解決できそうな気がしますが、言語化してみると例えばリリースサイクルが遅いというのは実は単純にプロセスの問題だけじゃなくて、デプロイフローの問題やアプリケーションの品質の問題だったりチームのサイズの問題だったりということが見えてきます。スクラムで何を解決しようとしているのかというのをハッキリさせる意味でも、一度何が問題なのかを文章にしたのは良かったです。

期待値調整をちゃんとやる

期待値調整というと語弊があるかもしれませんが、スクラム開発をやるにあたって「スクラムをやればこれが解決します!」という言い方はしないように心がけました。そこの期待値だけが高くなっちゃうと、「スクラム始めたけど全然見積もり通りいかない / リリース早くならないじゃん」みたいな感想を持ってしまう人が出てくるからです。スクラムのプロセスを踏襲したから何かが良くなるわけじゃなく、計画・振り返りのサイクルのなかで自分たちで良くしくんですよと言う伝え方を心がけました。

  • スクラム開発のプロセスをやったから今の課題が解決するわけじゃないですよ
  • スクラム開発でわかるのは「いまなにができていないか」ですよ
  • 課題を解決するのはスクラム開発じゃなくて自分たちですよ
  • 少しずつチームで改善していきましょう

こういうコミュニケーションを心がけていたので、スクラム開始後も自然と「振り返りで改善していきましょう!」という雰囲気ができていたのかなと思います。

スクラム開発始めるとき編

インセプションデッキをやる

インセプションデッキはアジャイルサムライで紹介されているプロジェクトの全体像を示すためのドキュメントです。ドキュメントというと誰かリーダー的な人が作って配布するようなイメージを持つかもしれませんが、ワークショップ的にチームで集まって作っていくことに意味があるものだと自分は思っています。

インセプションデッキのテンプレートは以下からダウンロードできます。 github.com

割と新規ビジネスとか新規事業とかを念頭にテンプレはつくられている感じがするので、適宜差し替えて使いましょう。例えば既存のプロダクトがあってチームを作っていく場合には、エレベータピッチとかは不要かも。自分はチーム名を考える項目を入れたりしました。 The Agile Inception Deck | The Agile Warrior

自分はインセプションデッキのなかでも 我々はなぜここにいるのか俺たちのAチーム の項目が好きです。自分も自分でやってみるまではインセプションデッキやることにどこまで意味があるのか懐疑的だったんですけど、今までやった全てのチームで「チームの目指すゴールが明確になる」「何を重視するかという価値観が揃う」感覚があり、何よりチームとしてやってやるぞ!という気持ちになったのでチームのキックオフにはお勧めです。

とりあえず最初はスクラムガイドに書いてあるとおりやる

これよく言われてるやつですが、まずは守破離の守ということで、スクラムガイドの内容をカスタマイズしたりせずやりました。個人的に、まずはカスタマイズせずにやってみることで良かったのは、「これは何のためにやってるんだっけ?」というのをスクラムガイドに求めることができたことかなと思います。特にスクラムで開発を始めた当初は「これは何をしていく会だっけ?」とか、「これは何のためにやっているんだっけ?」という疑問・質問が多発するので、そんなときにスクラムガイドをもとに説明できます。またとりあえず型通りにやってみることで、スクラムガイドで目指していることをチームで体系的に理解できていく感じがしました。

まとめ

スクラム開発を始めて2ヶ月くらいのタイミングで契約を終了してチームから抜けてしまったので正直あまり偉そうに何か成果を語れるわけではないのですが、外から様子を見る限りとても強いスクラムチームになっているようで、自分のやったことが少しでも貢献につながっていれば嬉しいなと思っています。本記事では導入までをざっとポイントを絞って書きましたが、スクラム開発をこれから始めようとしている人たちの参考になれば幸いです。

参考文献

スクラム現場ガイド -スクラムを始めてみたけどうまくいかない時に読む本-

スクラム現場ガイド -スクラムを始めてみたけどうまくいかない時に読む本-

The Agile Inception Deck | The Agile Warrior

スクラムガイド

スクラムリファレンスカード

MacBook Pro (15-inch, 2018)のディスプレイが黄ばむようになったので修理にだしてた。

この記事は suusan2go Advent Calendar 2019 - Adventar の1日目の記事です。

suzan2go.hatenablog.com

この記事から3ヶ月も立たずに、今度はディスプレイが黄ばむようになってしまった。 状態としてはこんな感じ。

f:id:suzan2go:20191202170424j:plain

家に返ってきてリビングでMBPを触っていたときに、妻から「なんか画面焼け起こしてない??」と言われて気がついた。 「Night Shiftのオンオフを繰り返すと良くなる」なんていう情報もあり、そんなバカな…と思ったのだけど、試してみたら実際直ってしまったのは笑った。

仕事しているときはIDEの画面をMBPの画面で開きっぱなしにして、ブラウザやコンソールのログなんかを外部ディスプレイに映すというスタイルなんだけども、これで直るということはそのせいか・・・??と思ったけど、翌日また黄ばみ(しかも今度は反対側)が発生していたので、おとなしくApple Storeへ。

ジーニアスバーで

店員さんに見せたところ、以下のようなことを教えてもらった。

  • この症状はディスプレイの圧迫によって起こるパターンが多い
  • 特にMBPを頻繁に持ち運びする人によく見られる
  • リュックなどに縦で入れていた場合に、下側がこうなる場合が多い
    • かばんは下の方に物がたまるので、圧迫されやすいらしい

思えば、日によって黄ばみのでる箇所が違ったのだけど、たしかにかばんにいれるときの向きに依存していた。Night Shiftのオンオフするとよくなったように見えたのは謎だけど、圧迫が原因なら単純に時間経過でよくなっただけなのかもしれない。

今回もAppleCareに入っていたので無料でした。金曜の夕方にストアにあずけて、月曜の昼に自宅に返ってきました。

フリーランスになって、MBPを持ち運ぶ機会が激増したせいか、今年はMBPの不調が多くて困る… 懐古厨みたいな発言になってしまうけど、自分が大学院生のときに使ってたMBPは全然壊れなかったのになーというところまで書いて、そのMacも使い始めて二年目にHDDが不調になって取り替えたことを思い出した……

MacBook Pro (15-inch, 2018)のキーボードがバグるようになったので修理にだした。

ここ1〜2ヶ月、異常にtypoが増えて困っていた。

こちらの修理プログラムの対象であることは知っていたのだけど、一つ一つキーボードのキーを打っていっても再現しなく、ビックカメラAppleカウンターにもっていっても様子見ということになってしまっていた。

support.apple.com

あるときにキーの中心を外して打つと再現することが分かったので、速攻でジーニアスバーを予約して修理の依頼をした。

ジーニアスバーで

店頭でちゃんと上記の挙動が再現するかとても不安だったけど、無事再現。スタッフの方と話していると以下のようなことを教えてくれた。

  • バタフライキーボードの不具合はとても多い
  • 原因のほとんどは隙間にはいったホコリやゴミ、キーのすり減りが原因
  • 無償で交換可能だが同じ構造のものになるので、また同じ不具合が起こる可能性がある

修理にだした場合には1週間くらいかかるとのことだったが、木曜にだして土曜に戻ってきた。

キーボードの不具合をソフトウェア的に解決する

キーが二重に入力される問題についてはソフトウェア的に解決する方法もある。

github.com

github.com

自分はどちらも試したが、Unshakyのほうが高機能でキーごとに設定ができたりするので良さそうな感じだった。使わないときにくらべるとだいぶtypoは減ったものの、すり抜けて入力されてしまう場合もちょいちょいあり完璧というわけではないので、修理プログラム対象の場合には素直に修理にもっていくのがよさそう。

まとめ

ここしばらく本当にtypoが多くて自分がおかしくなったのかと心配になってたんだけど、無事?キーボードの不具合ということがわかってよかった。構造上また同じ問題がおこる可能性があるということなので、いままでAppleの純正のキーボードを使い続けてきたが、少なくとも仕事でコードを書くときには別のキーボードを使って行く気持ちになっている。

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万はなかなかキツかった