大規模なiOSアプリの画面開発を効率化するために動作確認用ミニアプリを構築する

こんにちは、モバイル基盤部の大川(@aomathwift)です。

iOSアプリの開発途中で画面のレイアウトなど僅かな変更を確認したい場合、最も確実な方法はアプリをビルドして該当の画面まで手動で遷移して確認する方法です。

この方法は特別なセットアップが必要なく単純明快な確認方法ですが、効率の面で問題があります。例えば一番の問題として挙げられるのがビルド時間の長さという問題です。アプリ開発の規模が拡大していくと、ちょっとした変更でもビルド待ちの時間が無視できないものとなっていきます。

本稿では、クックパッドアプリの開発において、機能単体で動作するミニアプリを構築して、プレビューサイクルを改善した取り組みについてお話しします。 f:id:aomathwift:20200731184036p:plain

iOSアプリの動作確認における問題点

クックパッドアプリの開発は、開発規模の拡大によって、ビルド時間の改善が大きな課題になっていました。 そこで、最近はその問題を解決すべく、大きなアプリを複数のモジュールに分け、分割してビルドできるようなマルチモジュール化に取り組んできました。

詳しくは2019年のCookpad Tech Confでの講演、「 〜霞が関〜 クックパッドiOSアプリの破壊と創造、そして未来」をご覧ください。

f:id:aomathwift:20200731184155p:plain これは、マルチモジュール化が活発化した2019年9月から2020年6月まで、同一のマシンで計測した平均ビルド時間を集計したものです。 このマルチモジュール化の取り組みの結果、一回あたりのビルド時間が徐々に改善されてきているのがわかります。

しかしながら、小さな変更を確認したい場合やレイアウトを調整したい場合を考えると、まだまだストレスを感じる長さです。

また、新規のモジュールは、アプリを起動してからそのモジュールの機能や画面への接続が出来ていない状態から開発を始めます。 そのため、開発するモジュールの画面への遷移を先に実装することが必要です。

これをすべて同じ開発者が担当しているなら然程問題ではないかもしれませんが、この起動画面からの導線部分の実装とモジュールの開発を別の開発者が行っていた場合、モジュール開発を担当する人は仮の画面遷移を実装するなどの余計なコストが生じてしまいます。

Sandbox - 機能ごとに動作するミニアプリ

f:id:aomathwift:20200731184247p:plain
TechConf2019より引用

クックパッドのマルチモジュール化では、レシピの表示画面や、検索結果画面など、1機能に関連するいくつかの画面を1つのモジュールとして扱っています。この単位をFeature Moduleと呼んでいます。

Feature Moduleの導入により、アプリ全体をビルドせずとも、部分的にビルドすることができるようになりました。

これらのFeature Moduleはframeworkとしてクックパッドのメインターゲットでimportして利用しますが、先に述べたような動作確認における問題を解決するため、Feature Moduleを単体のアプリとして動作可能にしたのがSandboxアプリです。

以降、この部分的にビルドするSandboxアプリに対して、アプリ全体を結合してビルドするアプリは本体アプリと呼ぶことにします。

Sandboxアプリのメリット

本体アプリをビルドするより速くビルドできる

このSandboxアプリのわかりやすい恩恵は、本体アプリよりも極めて短い時間でビルドが終わる点です。

同じ少量の差分のビルドにかかる時間の計測結果を比較すると、本体アプリのビルドでは平均約20秒かかるのに対しSandboxアプリのビルドでは約5秒で済みます。 単純計算でビルド時間を1/4に抑えられるということになります。

実際のビルドの様子を見ても、Sandboxがものの一瞬で起動できることは一目瞭然です。

f:id:aomathwift:20200731184359g:plain
本体アプリのビルド
f:id:aomathwift:20200731184538g:plain
Sandboxアプリのビルド

Viewのレイアウトの僅かな値を変更して差分を確認したいときなどでも、ストレスなく開発することが可能になりました。

確認したい画面にすぐ辿り着ける

クックパッドのように機能の多いアプリでは、アプリトップから開発している画面にたどり着くまでがやや面倒な場合があります

また、決済終了後の画面など、表示する条件が複雑な画面も存在しています。

そこでSandboxアプリを利用すると、確認したい画面を一番最初に、好みの条件で起動することが出来ます。

繰り返し起動したい画面は一覧になっていて、ここから選択して表示することができます。

f:id:aomathwift:20200731184643g:plain

先に述べたように、まだアプリ起動時の画面からの導線が出来ていない画面のデバッグも容易に可能です。

Sandboxアプリの実現方法

上記のようなメリットを得られるSandboxアプリを実現するために、解決しなければならない問題がありました。

一つは、本体アプリでは多くの外部ライブラリに依存していますが、ビルド速度向上のためにできるだけこの依存ライブラリの利用を避けなければいけないということ、 もう一つは、Feature Module内の画面から、別のFeature Module内の画面に遷移するケースがありますが、このためには検証に必要ないモジュールのビルドも必要になるため、これもまた避けなければならないということです。

これらを考慮した上で、画面遷移やネットワークリクエストといった副作用を本体アプリに近い形で提供する工夫が必要になります。

そこで、クックパッドアプリでは Dependency Injection を利用した副作用を取り出すためのオブジェクトを用意し、これを経由して各画面から副作用を呼び出せるようにしています。 この仕組みをEnvironmentと呼んでいます。

これを利用し、Sandboxアプリではスタブ可能なダミーの実装を注入することで、本体アプリに影響を与えずに副作用を実現できるようにしました。

これによって、例えばネットワークリクエストも実際にリクエストを送るのではなく、予め用意したデータを注入して表示することができるようになっています。

f:id:aomathwift:20200731184817p:plain

Sandbox用のターゲットは各Feature Moduleごとに作成し、ターゲットごとにビルドすることでモジュール単位でのミニアプリの起動を実現しています。

Sandboxアプリを開発者に快適に利用してもらうための工夫

Sandbox用のコードはできるだけ自動生成する

Sandboxアプリを動かすためのコードは実際のプロダクションコードとは別に実装する必要があります。

画面の実装自体はプロダクションコードを参照するとはいえ一つのアプリとして立ち上げるわけですから、データのスタブやEnvironmentの実体の注入などそれなりにコードを記述する必要があります。

この手間が障壁となり、導入当初はSandboxアプリを利用せずアプリ全体をビルドするという開発者が多い状況でした。

そこで、Sandboxアプリのセットアップを簡単に行えるよう、コード生成の仕組みを用意しました。

コード生成にはGenesisというSwiftで実装されたOSSを利用しています。 これは、同じくSwiftで実装されたテンプレートエンジンであるStencilを利用し、簡単な設定とテンプレートを用意すれば、ソースコード生成の仕組みを実現できるツールです。

options:
  - name: sceneName
    question: Sandbox scene name?
    description: new Sandbox scene name to generate. (e.g. RecipeDetails).
    type: string
    required: true
  - name: moduleName
    question: Destination target?
    description: module name to generate new sandbox scene for. (e.g. RecipeDetails)
    type: string
    required: true
files:
  - template: AppDelegate.swift.stencil
    path: "{{ moduleName }}AppDelegate.swift"

例えばこのようなコード生成定義を書いて、オプションとして作成したいSandboxのモジュール名や画面の名前を与えると、以下のテンプレートファイルの中で展開されます。

@testable import {{ moduleName }}
import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    private let environment = StubbableEnvironment()
    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        window = UIWindow(frame: UIScreen.main.bounds)
        
        // Inject Scenes to RootTableViewController
        let rootViewController = {{ sceneName }}ViewBuilder.build(environment: environment)
        window?.rootViewController = rootViewController
        window?.makeKeyAndVisible()
        return true
    }
}

そして、この定義に基づくコード生成スクリプトを実行すると、自分であれこれコードを書かなくとも、Sandboxを生成したいモジュール・画面の情報が反映されビルドできるようになります。

$ ./scripts/generate-sandbox
[14:00:14]: Welcome to Sandbox Scene generator
[14:00:14]: What target do you want to make sandbox for
1. MyFeature
2. MyAwesomeFeature
?  1
[14:00:22]: Enter new Sandbox Scene name to generate. Upper camel case is recommended. (like RecipeDetails)
MyFeatureDetail
[14:00:40]: Generating MyFeature/MyFeatureDetail
[14:00:40]: $ /path/to/ios-cookpad/scripts/mint run Genesis genesis generate /path/to/ios-cookpad/templates/SandboxScene.yml --destination /path/to/ios-cookpad --option-path /var/folders/p7/g0t6l0zx00sbdxxrnm7wq8d80000gp/T/options20200714-98239-1lwms1g.yml
[14:00:40]: ▸ Generated files:
[14:00:40]: ▸   Sandbox/MyFeature/MyFeatureDetailSandboxScene.swift
[14:00:40]: ▸   Sandbox/MyFeature/AppDelegate.swift

できるだけ実際のアプリに近い挙動になるようにする

Sandboxアプリでは、マルチモジュール化での依存関係の問題により、他のモジュールにある画面に遷移することはできません。

基本的に一つの画面をプレビューすることを想定しているSandboxアプリでこの画面遷移を厳密にプレビューできるようにする必要はありませんが、スムーズな動作確認ができるように、簡易的なViewをモックとして表示できるようにしました。

これにより、本体アプリとほぼ同じ挙動を想定した動作確認をすることができるようになっています。

f:id:aomathwift:20200731190028g:plain

この機能は、先に述べたコード生成により自動で実装されるほか、自分で実装する場合も一つのイニシャライザメソッドを呼べばセットアップできるように整備されています。

今後の展望

先日のWWDC2020で、SwiftUIの新しいPreview機能についての発表がありました。

https://developer.apple.com/videos/play/wwdc2020/10149

昨年発表されたXcode Previewsは、SwiftUIで構築した画面を、Xcode上でリアルタイムに確認できるような仕組みです。

今回のアップデートでは、プレビュー中にサンプルデータを流し込んで利用したり、Xcode Previewsによって起動した画面を実機上でインタラクティブに操作しながら確認したりする機能が加わり、今まさにSandboxアプリで実現していることがXcode Previewsで実現できるようになります。

加えて、Dynamic TypeやダークモードのPreviewなどの機能とも併せることで、より効率的に開発を行うことが可能になるでしょう。

現在、クックパッドアプリの画面はほぼUIKitで実装されたものですが、新しい機能の実装にSwiftUIを利用できないか試しているところです。 来る新しいXcode Previewsが利用可能になる日に向けて、SwiftUIによるView実装への移行と共に、プレビュー機能全体をXcode Previewsを利用したものに移行していく必要があると考えています。

既存のUIKitによる実装に関してはXcode PreviewsとSandboxアプリの機能を併せて利用したものを試行しながら、プレビュー確認環境全体の改善を進めていく予定です。

Xcode PreviewsとUIKitの併用については、メルカリさんが下記の記事で自社の事例を紹介しています。

まとめ

この記事では、クックパッドアプリにおけるSandboxアプリを利用した動作確認の効率化について紹介しました。

開発効率を上げるために、スピーディーで快適な動作確認環境は必要不可欠です。

クックパッドでは、より便利なプレビュー機能への改善を一緒に行っていただけるエンジニアを募集しています。

RailsアプリケーションのCIにDynamoDB Localを導入した話

こんにちは、事業開発部 サーバーサイドエンジニアの堀江(kentarohorie)です。

今回はRailsアプリケーションのCIにDynamoDB Localを導入した事例をご紹介します。

広告入稿システムとCI

クックパッドでは自社製の広告入稿システム・配信サーバーを運用しています。また広告の一部はDynamoDBを利用したアーキテクチャで入稿・配信されています。詳細は以前の記事「広告配信サーバーにおける DynamoDB Accelerator (DAX) 活用事例の紹介」で紹介されています。この入稿・配信のうち、広告入稿システムのCIに対してDynamoDB Localの導入を行いました。

広告入稿システムのCIではブランチへのpush、またはmasterへの変更をトリガーにCIサーバー上でスクリプトが実行されていました。CIサーバーにはMySQLやPostgreSQLの環境が用意されており、スクリプトが実行されるとサーバー上のDBを初期化してrspecが実行されていました。多くのテストでそれらのDBを利用したテストが実行されていましたが、DynamoDBに関しては実際のDBを使用できていませんでした。

そのため、DynamoDBを利用している箇所ではAWS SDK DynamoDBClientのput_itemやdelete_itemなどのメソッドを一つ一つstubしたテストが書かれていました。これは例えばDynamoDBを利用したコードが増えたり、その箇所を間接的に利用する必要があるコードが生まれた場合に、DynamoDBの利用を気にしながら必要に応じて都度stubするといった作業が必要になるということです。
例えば以下のようなstubがit句毎に書かれていました。

it "..." do
  expect(dynamodb_client).to receive(:delete_item).with(
    hash_including(
      table_name: "table_name",
      key: { pk: "product_key" },
    )
  )

  expect { subject }.to change { ... }.to(false)
end

こうした状況の中でDynamoDBを利用している箇所で、stubせずともテストを書けるようにしようというモチベーションがありました。

DynamoDB Local導入に必要な環境を整備

DynamoDB Localの導入にあたっては執筆時点で3つの方法がAWSで紹介されています。

  • Apache Mavenリポジトリとして利用
  • Java環境を用意して実行
  • Dockerイメージを利用

これら方法のうち、Dockerイメージを利用してDynamoDB Localを導入しました。理由は全社的にCodeBuildの利用が推進されており、CodeBuild上でDockerを利用してCIを回すという事例が社内に既に多く存在していたためです。CodeBuildはAWSが提供するCI/CD用ビルドサービスであり、Androidアプリ CIをCodeBuildに切り替えた事例などクックパッドでは広く活用されています。

上記検討の後、まずは既存のビルド部分をCodeBuildに置き換え、Codebuild上のDockerでテストを実行できる環境を用意しました。ビルド部分の置き換えはJenkinsのCodeBuildプラグインを利用しました。次に社内で用意されているCodeBuild用Dockerイメージをベースに広告入稿システムのDockerイメージを作り、MySQLやPostgreSQLを利用する処理はスクリプトを用意してdocker-compose up時に実行されるようにしました。具体的にはDBの初期化やrspecの実行などです。

f:id:kentarohorie:20200721123459p:plain
Before

f:id:kentarohorie:20200721123513p:plain
After

この置き換え作業では、既存のCIと比べた場合に可能な限りCI時間が長くならないことを意識して進めました。CodeBuildに置き換える場合これまでになかったDockerイメージのビルドや立ち上げといった工程が増えるためにCI時間が長くならざるをえません。しかしCI時間は短ければ短いほうが良いので、許容できる程度までCodeBuildでのCI時間を縮める必要がありました。

具体的には以下の工夫を行いました。

  1. CodeBuild上でのDockerイメージビルドはキャッシュを利用する
  2. docker-composeでマウントするファイルを可能な限り減らす

広告入稿システムはRailsで動いており、ビルド時間でネックになっていたのはnode_modulesとgemのインストール工程でした。当初はCodeBuildのS3キャッシュを利用してnode_modulesとgemをキャッシュする方針で作業を行っていました。しかしその方法ではnode_modulesとgemファイル群をCodeBuildサーバー(コンテナの外)に持つ必要があり、docker-composeでマウントする必要のあるファイルが多くなり結果コマンド実行時間が遅くなるという問題が発生しました。

次にDocker Layer Cacheを利用する方法を試しました。はじめはCodeBuildで用意されている「ローカルキャッシュ」のDocker Layer Cacheモードを利用していましたが、ライフスパンが30分程度と短いため、CIの稼働頻度が30分に一度回るほどは高くない広告入稿システムではあまり恩恵を受けれませんでした。

そこで最終的に、ECRを利用してDocker Layer Cacheすることになりました。具体的にはCodeBuildのPOST_BUILDフェーズでECRへDockerイメージをpushし、次のBuild時にそのイメージをキャッシュとして利用する、というようにしました。

phases:
  pre_build:
    commands:
      - ....
      - docker pull "${REPO}:latest" || true
      - ...
  build:
    commands:
      - ...
      - docker build --tag "rspec" --tag "${REPO}:latest" -- cache-from "${REPO}:latest" -f Dockerfile .
      - ...
  post_build:
    commands:
      - ...
      - docker push "${REPO}:latest"
      - ...

DynamoDB Localをテストへ導入

CodeBuildへの置き換えが完了した後はdocker-compose.ymlにAmazonが公式に配布しているDynamoDB Localイメージを組み込み、テスト時にそれを読み込むように設定しました。具体的にはAWSのconfigをアップデートする処理をテスト実行前に読み込むようにしました。広告入稿システムのテストでは他にAWSリソースを使用していなかったため、DynamoDBリソースに絞った設定はしませんでした。

次にテスト実行時にDBが初期化されるようにしました。 広告システム関連で使われているDynamoDBにはdynaというgemを利用したDB初期化の仕組みがあります。 dynaはDynamoDBをDSLで管理できるものです。したがって、テスト実行時のDB初期化はdocker-compose up時に走らせるscript内にDB初期化を行うdynaコマンドを実行することで達成しました。

最後に、広告入稿システムのテストでDynamoDBに関するstubを外していく作業を行いました。これでDynamoDB LocalのCI導入が完了しました。

導入結果

DynamoDB LocalをCIに導入することで以下を達成できました。

  • DynamoDBに関する処理のstubを考えずにテストが書けるようになった
  • DynamoDBに関するテストコードを、各人の環境で実行できるようになった
  • DynamoDBを利用したコードの保守性を向上させることができた
  • DynamoDBやClientの仕様変更に耐えやすいテストになった

導入後、DynamoDBに関する最初の作業としてDynamoDBのクライアントgem aws-sdk-dynamodbのアップデート作業を行いました。specではstubせずにDynamoDB Localにアクセスしているのでテストが通った結果に安心感を持つことができ、導入によるメリットを実感しました。

最後に

以上、広告入稿システムのCIにDynamoDB Localを導入した事例をご紹介しました。

クックパッドにはユーザーが触る画面を改善しているサービス開発領域や、収益を支えている広告領域など、様々な領域でエンジニアが活躍しています。そしてそれらの領域ではエンジニアを随時募集しています。興味を持っていただいた方のご応募をお待ちしております。

新卒採用: https://info.cookpad.com/careers/new-graduates/

キャリア採用: https://info.cookpad.com/careers/jobs/

エンジニア社内留学制度を利用してAndroidアプリ開発を体験した話

こんにちは、事業開発部でデータ分析やデータエンジニアリングをやっている佐藤です。最近の楽しみはクックパッドマートで買ったコーヒー豆を挽いて淹れることです。

今日はクックパッド社内で実施されているエンジニア社内留学制度について紹介します。

エンジニア社内留学制度とは

エンジニア社内留学制度は「異動をすることなく短期的に他の部署でその部署の仕事をする制度」というもので2019年4月に作られました。 この制度は異動をせずに視野を広げたり自分のキャリアを考えるための制度であり、普段自分が関わらない技術や分野に対して新しいチャレンジをする機会を提供するための制度です。

エンジニア社内留学制度を利用することで、最大2ヶ月の間もとの部署の仕事から離れて留学先部署の業務に取りかかれます。これは全エンジニアが利用可能な制度です。
この制度の概要は上記のとおりですが、制度を利用して留学させる・受け入れる側を含めた関係者の狙いは下記のようなものとなります。

  • 留学生側
    • 他部署の業務に取り組むことで、視野を広げ、技術や分野において新しいチャレンジをする機会とする
  • 留学元部署
    • メンバーの目線を広げ、技術や分野の違うチャレンジをするなど成長の機会とする
    • 他部署の業務を詳細に知る社員を増やすことで、留学終了後もより円滑に協力できるようにする
  • 留学先部署
    • 短期的な開発リソースの確保
    • 自部署の業務を詳細に知る社員を増やすことで、留学終了後もより円滑に協力できるようにする

この制度が作られた後、サービス開発を行う部署から技術基盤の部署へのエンジニア留学が何件か実施されました。 自分はこの制度を利用して5月〜6月の2ヶ月間モバイル基盤部でAndroid留学を行いましたので、以降の内容ではそのAndroid留学に関して書いていきます。

Android留学の流れ

当記事の冒頭に書いたとおり、自分は普段は事業部でデータ分析やデータ整備作業などを主務として行っていました。 そんな自分が今回エンジニア社内留学制度を使ってAndroid開発に関する知識を身に着けようと思った動機はおおまかに下記の3つです。

  1. Androidエンジニアが足りないということで丁度モバイル基盤部がAndroid留学を募集してた(下記の図を参照)
  2. 部署でデータ分析をしているうちにモバイルの知識が必要になってきた
  3. Android留学を一回しておくと今後iOSで同じようなことをしたくなったときの取っ掛かりにもなりそう

f:id:ragi256:20200716142952p:plain
Android留学募集の様子

というわけで上長に相談し、次の目標を掲げての2ヶ月の社内留学が決定しました。

  • Android版クックパッドアプリのどの部分のコードでどうやってログデータを送ってるか把握する
  • Androidアプリのロギング処理をクライアント側で調査・デバッグできるようになる
  • 誰かが新たにロギング処理を仕込む際に、相談相手になったりコメントできるようになる
  • 今後もモバイル基盤部と協力してモバイルのログ周辺がより良くなるよう整備をしていけるようになる
  • モバイルエンジニアに依頼するばかりでなく自分でもログを仕込めるようになる

この時点でAndroidアプリ開発もKotlinもJavaも全く触れたこともありませんでした。完全に未経験の状態です。 このあたりの留学決定に関する流れは4月頭の1on1で相談したら即留学用チャンネルにinviteされ、3週間ほどの調整期間の後、留学を実施というスピード感でした。調整期間というのは元いた部署の仕事から離れても大丈夫なよう片付けるための期間だったので、特に何かしらの準備があったわけではありません。

やってみてどうだったか

留学期間で実際に着手したタスクは下記の4つでした。

  1. アプリ画面リファクタリングに伴うログ変更に関する調査と周知
  2. 古いコードのVIPER化
  3. モバイルアプリにあるロギング実装に関するドキュメント整備
  4. 旧ロギング実装のリファクタリング

各タスクについて個別に書いていきます。

1. アプリ画面リファクタリングに伴うログ変更に関する調査と周知

クックパッドが提供しているレシピアプリはiOS・Androidの両プラットフォームともにVIPERというレイヤードアーキテクチャを採用しています。このVIPERアーキテクチャ採用は2018年に決定したもので、今利用しているコードの中には旧アーキテクチャのままになっている箇所もあります。よって既存コードをVIPERのアーキテクチャに置き換える作業(通称VIPER化)が行われています。
最近行われたとある画面のVIPER化に伴って、意図せずログ送信内容が書き換わっている可能性が高いことがわかりました。そのため、その問題の調査と社内周知に留学初タスクとして取り掛かりました。実際にやったことはVIPER化の手順を追いかけ、ログ実装を読み、実際に送られたログデータの変化を確認するだけです。

2. 古いコードのVIPER化

初タスクでVIPER化の作業を追いかけて読んだため、Android開発の素振りとしてVIPER化に取り組むこととなりました。しかし、結論から言えばこのタスクは断念することとなりました。
理由は初めてのモバイルアプリ開発に対して、あまりに知識が足りなかったためです。開発するためのキャッチアップに時間を浪費してしまい、そのままでは定められた期間で留学の目的を達成することが困難と判断したためです。VIPERもそうですが、Rx・DI・マルチモジュール・Android知識など予め備えておくべき知識の諸々を学びながらの期間であったため、見てもらうためのPRの実装を作るまでに時間がかかってしまいました。初めてレシピアプリ開発に取り掛かる開発者も困らないようにと初学者用ドキュメントは整っており、それを読みながらの実装でしたがとにかく初めての概念が多いため覚えることがたくさんありました。
この点に関してはまずGoogle CodeLabsをやるのが良かっただろうというのが反省です。

3. モバイルアプリにあるロギング実装に関するドキュメント整備

VIPER化を断念した後、自分が何をするべきかを留学当初の目標に立ち返って考え、取り組むべき課題を考えることとしました。元々の目標の中心にあった「ログ周辺」の課題がなにかないか考えたところ、「レシピアプリ内で使われるロギングの実装がとっちらかっているように見えるのでなんとかしたい」という課題を留学期間中に感じていました。
そこで実際に取り組んだタスクがこのドキュメント整備と次の旧ロギング実装のリファクタリングです。
レシピアプリはiOS・Androidともに開発に参加しやすい状況を維持すべく、開発参加者への支援が手厚く用意されています。オンボーディングや開発者向けドキュメントなどがそうです。ですが、アプリから送られるログ周りに関しては専門家がいなかったため、包括的なドキュメントがありませんでした。 そこで留学という機会を利用して、レシピアプリ開発へ新規に参加するエンジニアでもロギング実装に困らないようなドキュメントを書きました。

4. 旧ロギング実装のリファクタリング

3番目のドキュメント整備タスクと並行して、古いログ送信処理を置きかえる作業を実施していました。旧ロギング実装はアプリ開発からしてみれば何か大きく問題点があるわけではなかったため、誰にも気づかれずそのままとなっていました。しかし、実際に送信されたログを保守・加工・分析を行っている側では微妙に扱いづらいものであり、ログデータを利用する側(分析者やデータ整備者)ではちょっとした負債となっていました。この分析サイドからみた負債を解消することが、旧ロギング実装リファクタリングの目的でした。 こういった負債の指摘やリファクタリング作業やドキュメント整備はログデータを送る側からも利用する側からも扱いやすい、より良いログデータ環境を目指そうという意識付けにも繋がりました。データ基盤はは送信箇所や分析箇所などの特定の箇所の改善では使いやすくなりません。実際の利用フローに合わせ、足並みを揃えてトータルの改善をすることで多くの人から喜ばれるデータ基盤となります。

上記4つのタスクをひたすらにこなしているうちに気づけば2ヶ月が経過してしまい、エンジニア社内留学が終了となりました。留学自体は終わりましたが、自分自身がクックパッド社内でデータに関わるいちエンジニアであるということには変わりがないため、今回得た経験を活かして今後もデータ分析環境の改善に取り組んでいくつもりです。

エンジニア社内留学からの副産物的成果

実際にやってみたところ、予想していなかった副産物的成果がいくつかありました。自分としては「完全なAndroid初心者では手取り足取り教えてもらうだけになりそう」と思っていたのですが、留学をしてみたら意外と好影響もあったようです。

1. Android入門者用のドキュメントが改善された

初めてのAndroid開発に参加するため、レシピアプリに関する全ドキュメントに目を通すこととなりました。この際に疑問に思ったところは片っ端から質問をするようにしていたため、ドキュメントの不備・陳腐化した内容・分かりにくい説明などはどんどん修正されていきました。

2. ログに関する議論が活発になった

留学先のモバイル基盤部はお昼会という名のデイリーミーティングと、週次で行われる振り返りミーティングがありました。リモート期間中だったので1これらのミーティングは全てZoom越しに行われました。このミーティングで同僚の着手タスクの概要や進捗状況を把握するわけですが、こういった日々の会話の中で常にログデータの取り扱いに関する話に対して質問やコメントをしたりし続けていました。
折しも社内でログの取り扱いに関する話題が活発化しているタイミングで、そういった議論に関して「今こういう話が活発ですよ」「このチャンネルでこういう議論がかわされていますよ」という誘導を会話の中でし続けていました。
ロギングのドキュメント整備で話し合う機会もあり、「他部署ではログデータをこう取り扱っている」といった部署横断的な知識の提供に繋がりました。

3. 今まで方針の定まっていなかったロギング実装に関して、話し合いの場を設けて合意をとった

「やったこと」の3つ目に書いてあるとおり、留学後にこなした業務の中で「ロギングのドキュメント整備」がありました。このドキュメント整備ですが、今まで明文化されていなかったものをドキュメントに書き起こすだけで済むかと思いきや、そうではありませんでした。
これまで言語化されていなかったため、明確になっていたなかった点がいくつもあったのです。ドキュメントを制定するに当たり、同時にプルリクエストレビューで多くの人と意識のすり合わせがなされました。また、PRだけでは決まりそうにない、ロギング実装に関する大きな意思決定のため有識者会議を開くこともありました。
多くの人が関わるクックパッドのレシピアプリ開発の方針決定に関わることになるとは留学前には考えていもいませんでした。

終わりに

クックパッドでのエンジニア社内留学制度の紹介と、その制度を利用したAndroid留学体験を紹介しました。
社内で異動することなく、別分野のエンジニア業務を体験してみるのは新鮮なことでしたし、自分が取り組める業務の幅も広がったと思います。また、初心者かつ異分野エンジニアが留学してみると、留学ならではの好影響も与えられるという発見がありました。

留学を終了した証書
無事に留学修了証書をもらいました


  1. クックパッドでは新型コロナウイルス感染症の拡大に伴い、2月から全従業員を対象に在宅勤務を実施しています。在宅勤務に対する取り組み例はこちら。記事1記事2

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('https://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('https://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/