タイミーの矢尻、須貝、razです。 ソフトウェアテストに関する国内最大級のカンファレンス「JaSST (Japan Symposium on Software Testing) ‘24 Tokyo」が2024/03/14、15の2日間にわたって開催されました。 jasst.jp 登壇時の様子 今回は我らがGo AkazawaとYorimitsu Kobayashiも登壇!その応援も兼ねてQAコーチ、エンジニア、スクラムマスターの3名が参加。世界中で開催されるすべての技術系カンファレンスに無制限で参加できる「Kaigi Pass」という制度を利用しました。 productpr.timee.co.jp 本レポートでは、印象に残ったセッションの内容を中心に、2日間の会の様子をお伝えします。 噛みしめるほどに味わい深い「Making Quality Tangible」 今年の1月に入社したばかりの駆け出しQAコーチの矢尻です。 毎年楽しみにしているJaSST Tokyoに今年もオンライン視聴で参加しました。 視聴したすべてのセッションが示唆に富んだ学び多きものでしたが、中でもインパクトの大きかった Gojko Adzic 氏による基調講演「Tangible software quality」 の感想をお話します。 「Tangible software quality」を直訳すると、「具体的なソフトウェア品質」となります。 このセッションでは直接的にテストできないソフトウェア”品質”をプロダクトに”作り込む”ためのマインドセットやモデルが紹介されました。 セッションの最後に紹介された5つの「Making Quality Tangible(品質を具体化するためのガイドライン)」は、哲学的で難解ですが、噛みしめるほどに味わい深いものでしたので私なりに意訳して感想に代えさせていただきます。 MEASURE PRESENCE, not absence(意訳:不在ではなく存在を測定せよ) 欠陥や問題点ではなく、実現された価値に焦点を当てることの重要性を強調されました。ポジティブな側面や魅力を評価することが、価値や魅力を感じるための鍵であると感じました。 Describe multiple QUALITIES(意訳:複数の質を記述せよ) 内容に忠実な感想ではありませんが、例えば生活の質(QOL)のように健康・経済的安定・教育・職業・家族関係・文化的充足感など様々な指標で構成され、どれか一つが満たされていれば幸福というわけではないということに似ていると感じました。 ソフトウェアも同様に、使うひとが幸せであるための多様な構成要素を要求される水準で満たすことが重要と受け取りました。 Trade-offs are a PRODUCT DECISION(意訳:トレードオフは製品の意思決定の一環である) 誰もがt_wada氏の「質とスピード」を想起したのではと思っています。 もちろん「質とスピード」の間のトレードオフは解決可能と私も思っていますが、ここでは網羅的なテストでリスクをゼロに近づけることではなく、どの品質特性がどの程度重要なのか重み付けをして、重要なものからバランス良くリソースを配分するのが重要と受け取りました。(「要はバランス」ですね) Shape priorities with a MODEL(意訳:モデルを用いて優先度を形成せよ) 製品の意思決定の一環として生じるトレードオフを判断する基準として勘は通用しません。ここでシンプルで有用なモデルとして「有用性」「差別化」「飽和点」から成るQUPER Modelと「マズローの5段階欲求モデル」が紹介されていました。 QUPER model for better requirements Redefining software quality VISUALISE and ACT(視覚化して行動せよ) もうこれは字面通り「収集したメトリクスを根拠に行動せよ」ということかと思います。 (そういえば最近「見える化」って聞かなくなりましたね) まさにタイミーでも価値あるソフトウェアを最速でデリバリーするためにチームトポロジー型の組織戦略を採用しています。価値に着目している点で同じ方向性のセッションだと感じましたので、今回紹介されたモデルやメトリクスは折に触れてチームで紹介し試していけたらと考えています。 異業種の品質保証から得られた学び 自動テストが好きなバックエンドエンジニアの 須貝 です。 JaSSTは初参加(オンライン視聴)でして、弊社の赤澤と小林の登壇を応援しようというのがきっかけでした。 全体を通して一番印象に残ったのはトヨタ自動車の長尾洋平氏による「 自動車のソフトウェア品質に関する現場の試行錯誤 」です。 自動車を制御するソフトウェアは数千万から数億行のコードからなっており、まずその規模と複雑さに驚きました。また、テストコードの品質にも規格があり、その質を担保するためにミューテーション分析などを活用しているそうです。 一方で実機テストの制約の多さに苦労されているとのことでこれは自動車ならではの悩みだなと思いました。テストのアプローチとしてQAが要件定義段階から関与するいわゆるシフトレフトを実践されている点も非常に興味深かったです。 また他のセッションですと「 音楽の世界から学ぶ、ソフトウェア品質 」は、プロ演奏者を招いて音楽とソフトウェアという無形のプロダクトの質について探る野心的な試みでした。 私はソフトウェアエンジニアという立場ですが、日々の開発では自身でもテストを行っているため、大変学びの多いイベントでした。 「アジャイル」「スクラム」が多く出てきたことに驚き QAやテスト界隈がどんな感じなのか気になったので参加しましたスクラムマスターの raz です。 私もJaSSTに初参加(オンライン)でした。正直なところ、社内で参加希望者を募るまで、存在も知らなかったのですが、参加できてよかったです。 私も印象に残ったのは、トヨタ自動車の長尾洋平氏による「 自動車のソフトウェア品質に関する現場の試行錯誤 」なのですが、須貝さんが感想を書いてくださってるので割愛しておきます笑。 色々な発表を見させていただきましたが、全体的な感想として「アジャイル」や「スクラム」といったキーワードがたくさん出ていたのが驚きでした。ソフトウェアエンジニアがアジャイルなプロダクト開発に変化していった中で、QA組織やQAエンジニアがその変化へ適応していこうとしているように感じました。 その中でも「品質」について「 誰のなんのための品質なのか 」を考えているのが、とても良かったです。発表の中には「本当にその考えでいいのか?」という議論の余地はあったかもしれませんが、顧客中心に品質を議論する活動、それを継続するのは素晴らしいことだと思います。 弊社でも「顧客のための品質」について、もっと考えていければと思います。 おわりに 弊社は今回ゴールドスポンサーとして初めてJaSST Tokyoに協賛させていただきました。次回以降もなんらかの形で貢献して一緒にコミュニティを盛り上げていければと思います。 タイミーのQA、ソフトウェアテストについてもっと知りたいという方はぜひカジュアル面談でお話しましょう。 product-recruit.timee.co.jp
はじめに 課題感・背景 使用しているBIツールについて BIツールの使用ボリューム感について やったこと:概要 やったこと:詳細 referenced tableにテーブル名ではなくdbtモデル名が入るようにしたことについて 各種アウトプットの公開設定をmeta情報として付与する方針としたことについて tagを追加してexposureの検索性を向上させたこと exposureのnameにシートとダッシュボードのタイトルを反映する方針にしたこと 今後の発展 保守運用の設計 カラムレベルリネージュ ✖️ exposure おわりに We're Hiring!! はじめに こんにちは。okodooonです!! データ基盤を参照したアウトプットが社内に溢れかえっていませんか? 弊社は追いきれていないLookerStudioやConnectedSheetがめちゃくちゃ溢れかえっていました。 そんな折、yoshidaさんの以下の記事を拝読いたしまして、今回の実装に至った次第でございます。 LookerStudioの記事 ConnectedSheetの記事 www.yasuhisay.info www.yasuhisay.info 面識ないですがこの場を以て感謝の意を表させていただきます!ありがとうございます! 課題感・背景 使用しているBIツールについて 弊社ではBIツールを数種類利用して、BigQueryデータ基盤上のデータを活用しています。 以下がその一覧とざっくりとした役割です。 Looker : 社内の主要な分析プロセスをカバーするセマンティックレイヤーを提供 LookerStudio : アドホックなレポーティング、Lookerでカバーしきれていない指標を用いたダッシュボード構築 GoogleスプレッドシートのConnectedSheet : スプレッドシート上でビジネスメンバーが作業する際のデータソースとしての使われ方 Redash : 元々LookerStudio同様の使われ方をしていた。ガバナンス向上とSSoT実現のために廃止作業中 Looker経由のアウトプットであれば、ソースデータに変更が発生したり社内の指標出力ロジックに修正が発生した場合に、ディメンショナルモデリング層で吸収したりLookerのContentValidator機能などでガバナンスを効かせることができます。 しかしBIツール側に直接クエリを書く形となるLookerStudioとConnectedSheetを用いたアウトプットの保守とガバナンスが問題となっていました。 BIツールの使用ボリューム感について こんな感じのクエリで調査しています。 SELECT DISTINCT JSON_VALUE(protopayload_auditlog.metadataJson, " $.firstPartyAppMetadata.sheetsMetadata.docId " ) AS sheet_id, FROM `example-project.bq_usage_logs.cloudaudit_googleapis_com_data_access_*` WHERE protopayload_auditlog.serviceName = " bigquery.googleapis.com " AND JSON_VALUE(protopayload_auditlog.metadataJson, " $.firstPartyAppMetadata.sheetsMetadata.docId " ) IS NOT NULL SELECT DISTINCT label.value AS report_id, FROM `example-project`.`region-xx`.`INFORMATION_SCHEMA.JOBS_BY_ORGANIZATION`, UNNEST(labels) AS label, WHERE label.key = " looker_studio_report_id " 過去半年にクエリが走ったConnectedSheetの数: 600個強 過去半年にクエリが走ったLookerStudioの数: 400個強 前述したロジックやソースシステム側の破壊的な変更への対応工数の観点以外にも、もう使われていないConnectedSheetに配信し続けている可能性などが考えられるため、まずはアウトプットを管理できる体制が必要であると考えました。 やったこと:概要 以下のような処理の流れを構築しました。 exposure登録情報を出力するviewをdbtで構成 以下の処理をweeklyで実行 viewの結果を取得してexposureのyaml形式に変換 アウトプット単位でexposureのyamlファイルを作成 未登録と変更があったexposureを登録するpull requestを作成 参考にしたブログから、弊社の運用に合わせて変更した点は以下です。 exposure単位でyamlファイルを作成する方針に変更しました referenced tableにテーブル名ではなくdbtモデル名が入るようにしました 各種アウトプットの公開設定をmeta情報として付与する方針としました tagを追加してexposureの検索性を向上させました exposureのnameにシートとダッシュボードのタイトルを反映する方針にしました 今回の実装によって以下のような形式のexposure用のyamlファイルが自動生成されます。 version : 2 exposures : - name : {{ ConnectedSheetタイトル }} _{{ConnectedSheetId}} label : {{ ConnectedSheetId }} type : dashboard tags : - shared_externally - spreadsheet url : https://docs.google.com/spreadsheets/d/{{ConnectedSheetId}} owner : name : test@example.com email : test@example.com depends_on : - ref('hogehoge_model') - ref('foo_bar_model') - ref('chomechome_model') meta : visibility : shared_externally やったこと:詳細 説明があるとわかりやすそうな部分の詳細を記載していきたいと思います。 referenced tableにテーブル名ではなくdbtモデル名が入るようにしたことについて 弊社はdbtモデル名とBigQuery上のテーブル名が一致しないため、INFORMATION_SCHEMAやaudit_logから取得したテーブル名をref関数化してもリネージュを作成できません。 そのため、dbtモデル名とBigQuery上の対応関係を取得するためにdbt-elementary実行時に生成される dbt_models テーブルを活用しました。 このテーブルは カラム名 内容 dbt_models.name dbtモデル名 dbt_models.alias BQテーブル名 dbt_models.schema_name BQデータセット名 dbt_models.database_name BQプロジェクト名 このような情報を持つカラム群を保持しています。 このテーブルを活用することでINFORMATION_SCHEMAが保持するBQテーブル名をdbtモデル名に変換してref指定することができています。 各種アウトプットの公開設定をmeta情報として付与する方針としたことについて https://support.google.com/a/answer/9079364?hl=ja google workspaceのactivityログを使うことで、LookerStudio,SpreadSheetの公開設定とタイトルを取得することができるので、それらを取得しています。 SELECT data_studio.asset_id AS report_id, data_studio.asset_name AS report_name, data_studio.visibility AS visibility FROM example-project.google_workspace.activity WHERE activity.data_studio.asset_type = 'REPORT' AND activity.event_name = 'VIEW' SELECT drive.doc_title AS sheet_title, drive.doc_id AS sheet_id, drive.visibility FROM `example-project.google_workspace.activity` WHERE drive.doc_type = 'spreadsheet' tagを追加してexposureの検索性を向上させたこと dbt exposureはmeta, owner, typeなどの情報を使って、dbt lsコマンドなどでアウトプットを一覧することができません dbt ls --resource-type exposure --type dashboard --owner example@example.com みたいなことがしたいのですができないです。 そのため、exposureに対して適切なtagを付与することで絞り込みができるようにしました! 今回は公開設定,アウトプット種別の二つをtagとして持たせました。 これによって 「xxx_modelを参照しているshared_externally設定にしているスプレッドシート一覧を出したい」という要望に対して dbt ls --select xxx_model+,tag:shared_externally,tag:spreadsheet --resource-type exposure このようなコマンドで出力ができるようになります exposureのnameにシートとダッシュボードのタイトルを反映する方針にしたこと Add Exposures to your DAG | dbt Developer Hub こちら公式Docにexposureのnameに指定するのはスネークケースにしてくださいという記載がありますが、なんとスネークケースにしなくても日本語名でも通ります!(名前をユニークにする必要はあります) そしてexposure.nameがリネージュ上で表示される名前なので、データリネージュの可視性を高めるためにLookerStudioとコネクテッドシートのタイトルをnameに含む形で設定している状態です。 LookerStudioID, SpreadSheetIDだけをnameにすると、このようにデータリネージュ上でどのアウトプットのexposureかぱっと見判断がつかないのですが {{タイトル}}_{{ID}} の形式にすることでデータリネージュ上の可視性を確保した形です。 今後の発展 保守運用の設計 アウトプットが全件自動で管理されるようにはなったことで、「ソースシステムに影響が起きた場合」や「算出ロジックに変更が生じた場合」の影響範囲は迅速に把握できるようになりました。 しかし使われていないことがわかったアウトプットに対してどのようにアクションしていくのか、フローが組めていない状態です。 管理ができるようになった上でどのように運用改善に繋げるのか。どのように削除やdeprecatedにしていくのか。あたりのフローはしっかりと組んで、ユーザーの目に触れるアウトプットの品質の最大化に努めていきたいです。 カラムレベルリネージュ ✖️ exposure dbt cloud enterpriseではカラムレベルのリネージュがexplore上で確認できるようになりました。 docs.getdbt.com 重要なアウトプットはBIツール側にクエリを書くのでなく、dbt側にそのアウトプット専用のマートを作成することで、カラムレベルでの影響範囲調査が可能となるのではと考えています。 before after この図でいうbeforeからafterの構成に変えることでマートまではdbtで管理されるようになるため、dbt exploreのcolumn level lineageで可視化することで、カラムレベルでのアウトプットへの影響範囲を確認可能です。 こうすることで、「このテーブルに何かしら変更を加えたら最大でどのくらいの数のアウトプットに影響があるんだろう」から「このテーブルのこのカラムを消したらどのアウトプットに影響があるんだろう」まで影響調査の解像度を上げることができます。 こういった理由から、アウトプット専用マート作成の取り組みを始められたらなと思っております。 (column level lineageは現状dbt exploreで見ることができるだけですが、もうちょっと使いやすくなって欲しいです) おわりに yoshidaさんの記事を参考に少しだけカスタマイズしただけで、課題となっていたアウトプット管理の問題を解決することができました! 運用面などまだまだ磨き込んでいきたい部分は多分にありますが、この実装を通して社内ユーザーのデータ活用体験の最大化に繋げていきたいです! アウトプットがいっぱい登録されました。(オレンジ色がexposure) We're Hiring!! タイミーではデータ基盤を一緒に開発してくれる仲間を募集しています! お力をお貸しいただける方いらっしゃいましたらご応募お待ちしております! product-recruit.timee.co.jp
こんにちは!タイミーのデータアナリストの@ yuya です。 2020年に スマホ ゲームを運用する企業へ新卒入社をし、イベントプランナー兼データアナリストとして活動。2社目に ECサイト を運用する企業でデータアナリストとして従事した後、2023年3月に3社目となるタイミーへ入社しました。入社からちょうど1年が経ったので、タイミーでのデータアナリストとしての働き方をこれまで自分が所属した企業と比較して、どうだったかについて振り返りたいと思います。 タイミーでの役割 まずは、私がタイミーでどのような役割を担っているデータアナリストなのかを記載したいと思います。 タイミーのデータアナリストチームは、大きく以下の3つの役割に分かれております。 プロダクトアナリティクス:プロダクトの機能開発に関わる分析 マーケティング アナリティクス: マーケティング に関わる分析 ビジネスアナリティクス:経営・事業活動に関わる分析 私は、ビジネスアナリティクスに所属しており、営業周りのデータ分析や店舗周りのデータ分析を主に行っております。 タイミーでの1年を振り返る オンボーディング期 入社直後のオンボーディング期は、社内のデータ構造を理解しながら、データ抽出を行う依頼をこなしておりました。 タイミーでは、前述した3領域に関わらず、全社的にデータ抽出や簡単な分析をデータアナリストに依頼できるフローが存在しており、そこの依頼を担当することで、アプリ関連のデータ、 マーケティング 関連のデータ、営業関連のデータなど、タイミー内に存在する様々なデータ構造を理解し、使いこなせるようになるよう努めていました。 個人的に、これまで営業が存在する企業に所属したことがなかったため、営業関連のデータに触れることが新鮮で、分析領域としても1つ広がっていく感覚があり、非常に面白みを感じていました。 また、多くのデータが分析しやすいように整備されており、クエリを書くのが楽だったのも印象的でした。 ビジネスアナリティクス領域に配属 オンボーディング期が終わると、ビジネスアナリティクス領域に配属となりました。 私が配属された直後は、すでに社内での連携部署が定まっており、連携部署との間で分析テーマを決めて分析に取り組んでおりました。 当初取り組んでいたテーマとしては、「店舗の 流入 経路別のLTVの分析」や「新規導入に至るまでのファネル分析」、「CPの効果検証」などのように、課題の特定や戦略に関わる部分の分析から施策の効果検証まで幅広く様々な分析を行っておりました。 初めて営業関連の分析に着手する中で一番苦戦したのが、「どのデータが使えるのか?」を明確にするところでした。 前職と前々職では、アプリや マーケティング のデータを分析しており、基本的に自動でデータ収集されている状況でした。しかし、営業関連のデータは、営業の方が手動でデータを入力しないといけないため、たとえデータとしてカラムが存在していたとしても、データを入力している人としていない人が存在していたり、チームによって若干運用方法が違っていたりしていたため、現場への確認が必要でした。 今あるデータからどんな インパク トが出せそうかを考えるのも大事ですが、そもそもどのようなデータをきちんと収集していくと良さそうなのか、それをどうやったらきちんと収集できるようになるのかを考えていくのも重要そうだなという気づきを得ました。 営業組織が変革し、連携部署を再検討する ビジネスアナリティクス配属から約半年後、営業組織が変革されるイベントが発生しました。 これを機に、改めて「データアナリストとして、どのような動き方をすると価値を最大限発揮できるのか?」を考えていくことになります。 こちらについて、まだ明確な結論は出ていないものの、現状の営業組織の解像度を上げる(どこでどのような人が関わり、どのように意思決定が行われ、どのように影響していくのかなどを明確にする)ことで、データアナリストとして インパク トを与えていける動きができそうかの仮説を一定立てられるところまでは来たかなと思っております。 これまで所属していた企業(チーム)が、20名程度と100名程度であったため、特に意識しなくてもどこで誰が何をしているか理解できていたのですが、タイミーのように組織も急成長を遂げ、規模も1,000人を超えてくるような大きな組織になってくると、きちんと現場の状況をキャッチアップしにいく動きをすることが重要なのだなと改めて気付かされました。 最後に これまで、時系列的にどのようなことを行っていたのかを簡単に紹介してきました。 タイミーは、現在サービスも組織も急成長中であり、環境が目まぐるしく変わっていっており、都度都度その変化に適応していく必要があります。そのため、チームとしても明確な型のようなものが存在しているわけではなく、常に「どのように動くことが一番 インパク トが出せるのか?」を考え、状況に合わせて柔軟に動き方を変えていく必要があるなと感じています。 これまで所属した企業では、良くも悪くも、データアナリストとしての動き方がすでに固まっており、教えられた動き方をするだけで、自然と インパク トも出せるような環境でした。そのため、組織として自分がどのように振る舞うことが一番 インパク トが出せるのかを考える機会があまりありませんでしたが、タイミーでは、日々そのようなことを考えるため、視野を広げる良い機会になったかなと思っております。 組織が急拡大する中で、カオスなことも多いですが、これまでにない経験から得られる学びや気付きが多く、タイミーに転職して良かったなと感じております。 We’re Hiring! 私たちは、ともに働くメンバーを募集しています!! データアナリストのポジション カジュアル面談 も行っていますので、少しでも興味がありましたら、気軽にご連絡ください。
イベント概要 2023年12月5日に「Next Year Con for SRE〜来年の登壇を応援する勉強会〜」と題してSREに関するトピックでタイミー、ココナラ、ビットキー、マジックモーメントの4社合同で勉強会を開催しました。 その中でタイミーバックエンドエンジニアの岡野さん( @Juju_62q )の講演をイベントレポートにまとめてお届けします。 チーム分割においていかれたアラートをチームで責任を持てる形に再設計した 自己紹介&想定聴衆 2020年にタイミーに入社し、現在では3年半ほどエンジニアをしている岡野と申します。 主にストリームアラインドチームの機能開発を担当しており、その一方でサイトリライアビリティエンジニアリングも行っています。 想定聴衆 「よくあるアラート」に困っているエンジニア 組織分割を考えているEMやCTO EnablingをやっていきたいSREs 今日お話しないこと どのようなアラートを設定すべきなのか アラートから繋がるオンコール対応周辺の話 アラートとFBサイクルとチーム 私が最も優れていると考えるアラート(右の図)は、問題が発生したら、エンジニアが問題を解決すると宣言し、リカバーするアラートです。理想的には、問題が自動的に解決することが望ましいですが、今回の話の範囲では、アラートの責務を超えていると捉え、理想的なアラートの形をこのように考えています。 次によくあるアラート(左の図)は、CPU使用率がN%を超えると、エンジニアが介入せずとも時間と共に回復したり、500エラーがy回を超えると何もせずとも回復するようなアラートです。このようなアラートは、時間が経過すると自然に解決し、次第に無視されがちです。 本来アラートはアクションを要求するための通知であるべきであり、アクションなしにアラートが鳴ることは無意味です。実際にタイミーにも、このような無駄なアラートが長期間存在していました。 現状、完全な解決には至っていませんが、タイミーがアラートを少しずつ改善した話を共有していきます。 タイミーではどのようにして「よくあるアラート」ができたのか 前提条件 1. 開発と運用を同じチームでやっていること タイミーでは、CTOが開発と運用を一つのチームで行うことを重視しています。CTOが好んでいるチームトポロジーの書籍では、「運用は開発への最大のフィードバック源である」と述べられており、私たちの組織でもこれを大切にしています。 2. エンジニアはアラートがなっていることを好ましく思っていないこと エンジニアはアラートが鳴る状況を好ましく思っていません。行動を起こすかどうかは別として、アラートが鳴っていること自体は好まれていませんでした。 3. エンジニアは機能開発以外にある程度の時間が使えること タイミーのエンジニアは、10%から20%の時間を技術改善に充てることができます。実際には、少なくとも10%の時間をこれに割り当てることが求められています。 2〜3年前、我々のチームは以下のような横割りの構造でした。 バックエンドチーム Webフロントエンドチーム モバイルチーム これらのチーム間では、バックエンドチームがアラートの設定を行い、障害経験を基にアラートシステムが構築されました。この時期には、ユーザー数も少なく、アラート対応の難易度も低めでした。赤く表示されるアラートに対しては、チーム文化として積極的に対応していました。 しかし、この横割り組織では、一つのチームだけで機能を完全に提供することが難しく、これが課題となりました。そのため、職能を横断する縦割りの組織構造への移行を進めました。この新しい形では、モバイルやWebフロントエンドなど、異なる専門分野のメンバーが同一チームに所属するようになりました。 ただし、この組織変更の際に、アラートシステムの見直しは行われず、バックエンドエンジニアが引き続きアラートの責任を担うことになりました。 アラートが鳴った際の反応はどうだったかというと、以下のような反応が一般的でした。 Aチーム「アラート鳴ってるけど、よくわからんな」 Bチーム「アラート鳴ってるけど、うちのチームとは関係無さそう」 チーム間で分断されていると、特定の機能についてどのチームが対応すべきかの判断が難しくなります。特に、人員が増加するにつれて、過去の経緯も失われ、このような問題は増えていきます。 いつも鳴ってるし今日も大丈夫だろう 『いつも鳴ってるし、今日も大丈夫だろう』という感覚が常態化すると、アラートが頻繁に鳴るようになります。アラートが放置され、対応が行われないため、アラートの数は増加の一途をたどります。 改善したいけどハードルが高そう 仮に意欲的なエンジニアが現れても、「何とかしたいが、どう変えればいいかわからない」という状況に陥りがちです。Aチームの同僚は協力的ですが、Bチームは相対的に距離があるため、意見を述べるのが難しいと感じることがあります。同じ会社に属していても、日常的に顔を合わせていない人に対し、合意を得る必要があるかもしれないという懸念が生じます。 なぜこのようなことが起こるのか なぜこのような状況が発生したのか、その原因を考察します。 アラートの作成は元々、バックエンドチームが責任を持って設定していました。当初、アラートに対するフィードバックはバックエンドチームに集中しており、このチームだけでアラートの削除や修正が行われていました。しかし縦割り組織への移行後、アラートに関するフィードバックは複数のチームに分散し、単一のチームだけでの削除や修正が難しくなりました。アラートに対する対応が不明確になり、長期間勤務している経験豊富なメンバーに相談することや、アラートに関する変更の承認を得るまでのプロセスが必要になることもありました。このように、フィードバックが機能しなくなった結果、アラートの数は増加し、特に新入社員にとっては理解しづらいものとなりました。この状況が、「よくあるアラート」の誕生に繋がったのです。 「よくあるアラート」を改善するためにしたこと 結論を述べると Aチーム・Bチームそれぞれにフィードバックと意思決定権を与えました。 具体的な行動 各チームで対応の必要があると思われるアラートを選んでもらう アラートに対してチームメンションをつける アラートはメンションのある単一チームで変更していいと周知する アラート対応に関する振り返りを実施 各チームで対応の必要があると思われるアラートを選んでもらう すべての問題を即座に解決するのは難しいため、Slackに「問題なし」または「問題あり、オンコール対応が必要」というコメントを残すことを最低限行うことにしました。このとき、多くのアラートのうち、選ばれなかったアラートは一旦すべて削除しました。 アラートに対してチームメンションをつける 次に、アラートに対してチームメンションをつけることにしました。以前はアラートにメンションがなく、全てのチャンネル通知をオンにする運用でしたが、これではどのチームが対応すべきか不明確でした。そこで、アラートにメンションを付与し、「このメンションのチームがオーナーです」と伝えるようにしました。 メンションのある単一チームで変更していいと周知する 次に、バックエンドのアラートに関しては、バックエンドチーム全体の許可がなければ変更できないと考えられていました。しかし、メンションのある単一チームでの意思決定による変更を推進しました。これにより、各チームは素早く意見を反映できるようになりました。 アラート対応に関する振り返りを実施 最後に、アラート対応に関する振り返りを実施しました。最初の改善はできるだけサポートするため、メンション付きのアラート対応について1ヶ月後に第1回の振り返りを各チームで行いました。これは、必要に応じて2回、3回と続けました。この流れで、チーム内での改善が少なくとも1回行われるところまで改善できました。 今、どのような変化があったのか 現在、アラートシステムにおいて以下のような変化が生じています。 アラートに反応する人やチームの増加 アラートに反応する人数やチームが明確に増えました。 アラートの定期的な変更や見直し アラートに対応しないと自分たちが困難な状況に陥るため、変更や見直しを定期的に行うようになりました。 Runbookの整備 チームごとにRunbookが整備され、アラート対応のプロセスが民主化されています。この分野にはまだ改善の余地があると感じていますが、良い変化が見られていると思います。 これらの変化により、「よくあるアラート」から徐々に脱出していると感じています。ただし、不要なアラートが多いことや、復旧の自動化がまだ十分ではないことは、今後の大きな改善ポイントです。 まとめ アラートは組織構造とFBを受ける人が不一致の場合に機能しなくなっていく アラートは単一チームで変更の意思決定ができないと硬直化する 組織が変わった際に、アラートの組織に合わせて変更するのが大切 最後に、アラートシステムのまとめです。アラートは、チームの構造とフィードバックが不一致になると、効果を失ってしまう可能性があります。フィードバックを受ける人々が明確でない場合、アラートの機能性が低下する傾向があります。またアラートに関しては、「単純接触効果」のとおり、日常的に顔を合わせる人々に対して意見を伝えやすいことが多いです。そのため、単一のチームで意思決定ができない場合、アラートシステムは硬直化しやすいと思われます。 結論、組織が変化した際には、アラートシステムの構造も組織の形態に合わせて変更することが重要です。 その他の方の発表も気になる方はこちら! www.youtube.com 少しでも興味を持っていただいた方は是非こちらからカジュアルにお話しましょう!
はじめに こんにちは、タイミーでバックエンドエンジニアをしている 新谷 、 須貝 、 難波 です。 2月10日に 広島国際会議場 で YAPC::Hiroshima 2024 が開催されました。タイミーはGold Sponsorとしてブース出展をしており、エンジニアが3名とDevEnable室が3名の総勢6名で参加させていただきました。 どのセッションも興味深かったのですが、この記事では我々が拝見したセッションのうち特に印象に残ったものをいくつかピックアップしてご紹介します。 なお、タイミーには世界中で開催されている全ての技術カンファレンスに無制限で参加できる「Kaigi Pass」という制度があり、エンジニアはこれを使って参加しております。詳しくは下記のリンクをご覧ください。 productpr.timee.co.jp 経営・意思・エンジニアリング speakerdeck.com 普段我々が行なっているソフトウェア開発の延長線上に CTO の仕事があるよ、という発表でした。経営者が物事をどう捉えているのかを垣間見ることができ、個人的にはベスト トーク でした。 ソフトウェア設計と組織設計が相似的な アーキテクチャ であるということは コンウェイ の法則などもあることから直感的に理解できましたが、事業設計とも相似的な アーキテクチャ であるという話はまだピンときていないのでまたどこかのタイミングでお伺いしたいと思っています。 また、意思が重要という話はプロジェクトを成功するためには強い意思を持つ推進者が必要不可欠という点で共感していました。ただ、プロジェクトが短期間で終わるものであれば良いのですが、ある程度期間のかかる類のものは個人の意思では難しいこともあるかと思っていて、そういったものはどう対処しているんだろうとも気になりました。 短期的成果の重力に負けないよう、これからのプロダクト開発を行なっていきたいと思います。 (新谷) 関数型プログラミング と型システムのメンタルモデル speakerdeck.com コンピュータ アーキテクチャ に近い手続き型プログラミングから 関数型プログラミング へメンタルモデルを変えていこう、という発表でした。私は普段 Ruby on Rails でアプリケーション開発をしていて 関数型プログラミング とは距離があるのでとても興味深く聞かせていただきました。 オニオン アーキテクチャ は DI ができるとかモックが可能とかが重要なのではなく、 手続き型言語 の考えに引き摺られがちな I/O の部分を業務ロジックから切り離し、業務ロジックに対して別の パラダイム を適用できるようにするのが本質という話を聞き、なるほどと勉強になりました。 一方、 関数型プログラミング が Web アプリケーションのバックエンドに本当に適用できるのかはまだイメージが湧いていないのが正直なところではあります。質疑応答で質問をさせていただいて RDB の書き込みに相当する I/O の部分は Repository 層に閉じ込めるという話は納得したのですが、Web アプリケーションは本質的に並行処理だと思っていて、リク エス トを処理している最中に状態が書き換わることをどうやって純粋な関数で表現するのかが気になっています。 懇親会で確定申告の話と一緒に質問しようと思っていたのですが残念でした… 「スマンな!確定申告の話はまた今度!」 と、便の都合で先にかえるnaoya氏 #yapcjapan pic.twitter.com/drogfb5b5Q — 941 (@941) 2024年2月10日 (新谷) 変更容易性と理解容易性を支える自動テスト speakerdeck.com 自動テストの目的は 信頼性の高い実行結果に 短い時間で到達する状態を保つことで、 開発者に根拠ある自信を与え、 ソフトウェアの成長を持続可能にすること という結論からスタートし、その結論に向かって一つずつ解説していく内容でした。 この目的は極限まで削れば「ソフトウェアの成長を持続可能にすること」だと私は思います。これだけだと飛躍があるので一つずつ順を追っていくと、まずソフトウェアの持続可能な成長には変更容易性(変更しやすい)と理解容易性(わかりやすい)が必要です(ないとツラい)。そして変更による既存機能への影響を知る手段のひとつに自動テストがあります。また、自動テストには既存コードの理解を助ける役割もあります。もちろんただ自動テストがあればよいわけではなく、 良い自動テスト が必要です。 ではどうすれば良い自動テストを書けるのかという話になるわけですが、ここで私が思い出したのは「 単体テスト の考え方/使い方」(Vladimir Khorikov 著、須田智之 訳)です。 この本の「4.1 良い 単体テスト を構成する4本の柱」で以下の4つの要素が挙げられています。 退行(regression)に対する保護 リファクタリング への耐性 迅速なフィードバック 保守のしやすさ 目的で挙げられた「信頼性の高さ」は「退行に対する保護」( 偽陰性 からプロダクション・コードを守るもの)と「 リファクタリング への耐性」( 偽陽性 の数を最小限に抑えるもの)であり、「短い時間で到達する状態」は「迅速なフィードバック」に相当します。そして「信頼性の高い実行結果に短い時間で到達する状態を 保つ 」ためには「保守のしやすさ」が欠かせません。つまり冒頭の二行に良いテストの条件がすべて凝縮されていたのです。 発表にあった「実行結果は情報」という指摘には良いフィードバックの重要性も感じました。また、 Google のテストサイズの話なども非常に勉強になりました。今回のセッションをきっかけに改めて自動テストの目的に立ち返り、自分たちがより根拠のある自信を持ってコードを書けるようにしていきたいと強く感じています。 最後に余談ですが、発表の中で気になったことを懇親会でtwadaさんご本人に直接質問できたのはオフラインイベントの醍醐味だなとしみじみ感じました。 (須貝) 非同期な開発体制を支えるドキュメント文化 speakerdeck.com 時差のあるメンバー同士でも適切にコミュニケーションを行うために Launchable, inc.で実際に行われている ドキュメンテーション の事例を紹介頂く内容でした。 発表の中で特に印象に残ったものを3つほど挙げさせていただきます。 フィードバックの平等性 検索性の意識 ドキュメントの型化 まず「フィードバックの平等性」についてです。組織にいるメンバーは多様であり聞いた話について素早く考えて話すことが得意な人もいればじっくり考えたい人もいます。また組織内 公用語 として使われている言語が 第一言語 でない人もいます。そういった場合に同期的な MTG でやり取りすると議題に対するフィードバックを行う人が偏る傾向があり、またフィードバックの観点も偏りがちです。非同期にフィードバックをもらうようにすることでこの課題の対策としているというのは良い視点だと思いました。なお、タイミーでも参加者が多い一部の MTG では議事録のドキュメントにフィードバックの欄があり、また MTG の録画を行うことで非同期にフィードバックを行いやすい運用をしていたりします。 次に「検索性の意識」についてです。ドキュメントをしっかり残すことは非同期か否かに関わらず非常に良い文化であり実践している組織も多いと思いますが、ドキュメントが増えると必然的に起きるのが検索性の悪化です。タイミーでは ドキュメンテーション にNotionを使用しているのですが、閲覧したいドキュメントがなかなか見つからなかったり、見つかったドキュメントが実は古いものだったといったことはどうしても発生します。その対策としてまず部門ごとにConfluenceのspaceを分けているとのことでした。他部門の情報が簡単に閲覧できるという透明性は重要ではあるものの、それは権限管理をしっかりやれば解決できることです。また積極的に アーカイブ (≠ 削除)を行うことでデフォルトの検索設定では検索にヒットしないようにするという話もあり、これはその通りだと思う一方でそれを組織文化とするのは一朝一夕では無いなと感じます。 最後に「ドキュメントの型化」についてです。ドキュメントが一定のフォーマットに準じて作られていれば書き手にとっては書くべき情報が漏れにくいですし、読み手にとっても慣れれば慣れるほど要点を理解しやすくなります。また適切なフィードバックを受けるための 30/60/90% framework for feedback についても勉強になりました。これはドキュメントのフェーズに対して適切なフィードバックを行おうというもので、普段から意識してはいたもののそういった名前が付いていたことは知らなかったので今後のコミュニケーションの際に使おうと思います。そして関連資料のドキュメントへの記載です。ドキュメントを書く際は何かしら参考にした別のドキュメントというものがある場合が多いですし、書き手にとっては自明でも読み手にとってはそうでない場合も多いです。こういった資料のリンクを書き手だけでなく、読み手も積極的にドキュメントに残していこうというのは今後より意識していきたいです。 (難波) 杜甫 々さんのキーノート あの日あの場にいたことを自慢し続けようと思います。 (須貝) おわりに YAPC は長く続いているイベントですが、今回エンジニアで参加したメンバーは初参加だったり9年ぶりの参加という感じでした。それでも YAPC の和やかな雰囲気と Perl に関係するテーマもそうでないものも受け入れている包容力で皆大変楽しむことができ、また勉強になったカンファレンスでした。 来年以降もまたスポンサーや参加ができればと思います。 最後にランチとして配られた広島名物のあなごめしの画像を貼って終わりとします。
イベント概要 2023年11月15日に「GENBA #1 〜RubyとRails開発の現場〜」と題してRuby/Railsでの開発に関するトピックでタイミーとエンペイ社合同で勉強会を開催しました。 その中でタイミーバックエンドエンジニアのpokohideさん( @pokohide )の発表「Railsアプリで秘匿情報を環境変数からCredentialsに移行した話」をイベントレポート形式でお届けします。 登壇者紹介 Credentialsとは Credentials は、Rails 5.2から追加された秘匿情報を管理するための仕組み※1 で、Rails 6から複数の環境をサポート※2 しています。 【主な登場人物】 暗号化ファイル: config/credentials/ .yml.enc 復号用の伴: ENV[”RAILS_MASTER_KEY”] or config/credentials/ .key 【セキュアな構成管理】 Railsアプリ起動時に Rails.env に対応する暗号化ファイルと鍵を参照し復号する 復号化が完了すると Rails.application.credentials 経由で取得可能になる 【暗号化と参照方法】 YAML形式 のファイルを暗号化(YAMLの構文に依存) ⇆ 復号 復号化された後は ActiveSupport::OrderedOptions を介してアクセス可能 fetch や dig が使える ▲Credentialsの例 ※1Add credentials using a generic EncryptedConfiguration class #30067 ※2Add support for multi environment credentials. #33521 Credentialsへの移行目的 Credentialsへの移行は、組織内での秘匿情報管理の責任を明確化し、デプロイプロセスを効率化することを目的としています。 手間の削減 以前はECSのタスク定義に環境変数としてパラメータストアのSecureStringを利用していました。秘匿情報を追加する際にパラメータストアに登録し、ECSタスク定義とアプリケーションコードの両方を変更する必要があり、手間がかかっていました。 責任境界の曖昧さ AWSリソースの管理はインフラチームが主導していましたが、その結果、責任境界が曖昧になることがありました。 ⇒ Credentials導入によって、秘匿情報の管理に関する責任の所在が明確になり、責任境界が明確化されました。 デプロイの難易度 複数の場所での操作が必要だったため、デプロイが容易ではありませんでした。 ⇒ Credentials導入によって、アプリケーションコードを変更することで秘匿情報を追加・参照できるようになるため、デプロイも容易になりました。 レビューの困難さ 独自の対話型CLIを使用してパラメータストアを操作していたため、プロセスのレビューが困難でした。 セキュリティの向上 ⇒ Credentials導入の副産物として、セキュリティ向上が挙げられます。RAILS_MASTER_KEYのみを管理することでパラメータストアの操作権限を削減でき、全体的なセキュリティレベルが向上しました。 Credentialsの安全性 Credentialsの安全性は、主に使用される暗号化アルゴリズムとマスターキーの管理方法に依存します。2023年時点で、AES-256-GCM暗号化アルゴリズムを用いた暗号化は、最も安全だといわれています。 しかし、最も重要なのはマスターキーの管理です。マスターキーが流出すれば、暗号化された情報が容易に解読されてしまう可能性があります。そのため、マスターキーの安全な保管とアクセス管理は非常に重要です。 管理方法については、ビジネスの環境やリスクに応じて慎重に検討し、適切なセキュリティ対策を講じる必要があります。 Credentials 移行の手順 移行の手順は、とてもシンプルです。 何を移行するか決める 移行対象の秘匿情報を全てCredentialsに追加する 少しずつ Rails.application.credentials に移行する 1. 何を移行するか決める まず、何をCredentialsに移行するかを決定します。アプリケーションの構造を分析し、環境変数をリストアップします。秘匿情報には、環境変数だけでなく、証明書、秘密鍵、Google Cloudの認証用JSONキーなどが含まれる可能性があります。 また、秘匿情報が本当にCredentialsへの移行が必要かを考えましょう。環境ごとの固有の設定であれば config_for を使用することで解決できるかも知れません。コンテナ化された環境やデータロックサービスのような動的に注入する必要がある情報や、頻繁に更新される情報は、Credentialsへの移行が適切かどうかを慎重に検討します。 2. 移行対象の秘匿情報を全てCredentialsに追加する 秘匿情報を一括でCredentialsに追加することをおすすめします。その理由は、暗号化ファイルのレビューが難しいためです。Credentialsへの移行前もレビューは難しい状況でしたが、暗号化ファイルを扱う現在も同様です。そのため、秘匿情報をまとめて移行し、Railsコンソールでリリース前に値が正しく一致しているか確認することで、プロセスがよりスムーズになります。 3. 少しずつ Rails.application.credentials に移行する Rails.application.credentials への移行は段階的に行います。このプロセスは、多くのプルリクの作成と対応を伴い、障害が発生する可能性もあります。実際に起きた一例として、全角スペースと半角スペースを間違えて登録し、参照時にエラーが発生しました。秘匿情報のファイルレビューは通常、Syntax Highlightが効かない素のVimなどで行われるため、特に細心の注意が必要です。 タイミーでは技術改善のために割り当てられる時間が全体の約20%で、この時間を利用してCredentialsへの移行作業を行いました。全体としては約5ヶ月の期間を要しました。もし環境が異なれば、移行にかかる時間は1ヶ月程度に短縮可能かもしれません。移行の過程では、ステージング環境と本番環境で同じ秘匿情報を使用していたこともあり、そのような点にも対応しながら作業を進めました。 Credentials移行時のTips 1. config.require_master_key 設定を有効にする Railsアプリケーションを起動する際には、Credentialsのマスターキーが必須です。マスターキーがないとアプリの起動に失敗する設定を有効にしておくと良いでしょう。 2. エディタの指定 暗号化ファイルの編集にはエディタの指定が必須なので用意(Dockerを利用している場合はemacsなどでもOK) 3. エスケープ文字の扱い 秘匿情報にエスケープ文字が含まれている場合は、ダブルクォーテーションで囲むことが推奨されます。暗号化ファイルがYAML形式に依存しているため、YAMLの構文規則に従う必要があります。 4. 改行の利用方法 秘匿情報に改行を含めたい場合は、パイプなどのYAMLの構文を利用します。 5. 外部サービスとの認証方法を変更する 外部サービスとの認証方法も変更しました。具体的には、以前は秘匿情報をファイルから読み込んでいた認証方法を、Credentialsで管理する形式に変更しました。 6. バイナリデータの取り扱い YAML形式はテキストベースのデータ形式であり、バイナリデータの直接的な扱いには向いていません。特に、証明書などのバイナリデータをCredentialsで管理する際は、事前にBase64でエンコードする必要があります。アプリケーションでは、このエンコードされたデータを取得し、適切にデコードして使用します。データの識別を容易にするために、YAMLファイル内でエンコードされた値には base64_encoded というプレフィックスを付けると便利です。 7. 秘匿値をコンソールで非表示にする Railsコンソールを使用する際、デフォルト設定では秘匿値が表示されてしまうことがあります。(Rails 7.1からは、この秘匿値を非表示にする機能が標準で実装されています。)この変更によって、Railsコンソールから秘匿情報が誤って露出するリスクを軽減できます。 8. SECRET_KEY_BASEを Credentials に移行 Secretsは Rails 7.1から明示的に非推奨化 されたため、SECRET_KEY_BASEを Credentials に移行しました。各環境の credentials.yml に SECRET_KEY_BASE を移行すればOKなはずです。Rails 5.1以前で secrets.yml を使用して秘匿情報を管理していたアプリケーションの場合、移行プロセスは少し複雑になる可能性があります。 9. SECRET_KEY_BASE_DUMMYの活用 Rails 7.1から SECRET_KEY_BASE_DUMMY が導入 されました。これは、SECRET_KEY_BASE の代わりにダミー値を自動的に設定する SECRET_KEY_BASE_DUMMY です。assets:precompile 実行時に SECRET_KEY_BASE が必要ない場合でも、エラーが発生することを防げます。 10. Heroku Data for Redis これはタイミーではなく個人のアプリでの経験ですが、 Herokuで運用、Heroku Data for Redisを利用してる個人アプリのREDIS_URLをCredentialsに移行したらRedisに接続できなくなりました。自分で管理していない環境変数などを移行する場合は注意しましょう。 移行の結果 Credentialsに移行した結果、下記のような成果を実感しています。 ただし、依然としてレビューが大変です。データが暗号化されているため、プルリクエストを出しても差分が分からず、暗号化ファイルのdiffを確認するには公式の bin/rails credentials:diff を利用できますが、Railsの実行環境からgit操作が必要です。一般的な環境ではないかもしれませんが、当社では開発環境にDockerを使用し、ホスト側でgit操作を行っています。そのため、コンテナにgitを導入する検討をしています。 記事の発表やその他の発表が気になる方はこちら! www.youtube.com 少しでも興味を持っていただいた方は是非こちらからカジュアルにお話しましょう! product-recruit.timee.co.jp
イベント概要 2023年11月15日に「GENBA #1 〜RubyとRails開発の現場〜」と題してRuby/Railsでの開発に関するトピックでタイミーとエンペイ社合同で勉強会を開催しました。 その中でタイミーバックエンドエンジニアの正徳さん a.k.a 神速さん( @sinsoku_listy )の発表「Railsアプリと型検査」をイベントレポート形式でお届けします。 登壇者情報 Railsアプリと型検査 RBSの基本 RBSとは RBS(Ruby Signature)は、Ruby 3.0から導入された言語機能で、Rubyのコードに型情報を追加し、型検査と入力補完を可能にするための言語です。RBSファイルの拡張子は .rbsで、通常はプロジェクト内の sig/ ディレクトリに配置されます。 RBSのメリット RBSの主なメリットは「型検査」と「入力補完」の2つがあります。 型検査とは 型検査には、Steepと呼ばれるツールがあります。Steepを使用すると、RBSの定義に違反するコードを検出する役割を果たします。例えば、関数に指定された引数の数が実際の呼び出しと一致しない場合、エラーが検出されます。この型検査は、Rubyコードを実行する前に問題を発見できます。 下記は型検査(Steep)の実行例です。 入力補完とは VS Codeに soutaro.steep-vscode 拡張をインストールすると、RBSファイルを読み込んで、Rubyコードの入力補完が賢くなります。 IRB v1.9.0で、RBSを使った入力補完がサポートされました。入力補完を有効にするには、gem install prismコマンドでprismをインストールし、IRBを起動するときに-r prismオプションを指定します。 タイミーの導入事例:実際の手順 ここまで一応RBSの基本の話だったんですけど、弊社が実際に導入事例を紹介したいと思います。 RBS導入のきっかけ RubyKaigi 2023やメドピアのブログを読んだことから、RBSの導入への意欲が高まりました。 実際に試してみると、型チェックを無効にして、入力補完に重点を置くことで、比較的簡単にRBSを導入できることが分かりました。すぐに社内での調整を行い、方針を策定しました。 社内の開発者に質問してみたところ、RBSを完全に書くことには乗り気ではないものの、重要な部分だけを一部記述したいというニーズがありました。 しかし、それを別のファイルに書くのは少しつらいという声も聞かれました。 そこで元々弊社で使用していた Yard(ヤード)のドキュメントを活用し、重要な部分に型情報を明示し、コメントからRBSを生成して活用するアプローチを考えました。 実際にプロジェクトで検証した結果、うまく機能しそうだったため、「入れてみてダメだったら消そう」というノリで、試してみることになりました。 1. Gemfile に rbs_rails, steepを追加します 2. Steepfileを追加し、既存の型検査エラーは無視する 3. rbs_collection.yaml を作成する Ruby公式で管理されている rbs-gem-collection というリポジトリに、有志の方が提供している情報を利用し、rbs_collection.yaml ファイルを作成します。 4. RBSを生成するRakeタスクを追加する 様々なコマンドを個別に実行するのは手間がかかるため、一度にタスクを生成できる「RBSセットアップ」という独自のコードを作成しました。 このコードは、rbs-gem-collection からRBSをダウンロードし、自社のプロダクトのコードを解析し、適切な雛形を生成し、全てのクラスとメソッド名が含まれたRBSを生成できるものです。 5. .gitignore でディレクトリを無視する RBSは生成されるものとして扱っているため、 .gitignore ファイルでこれを無視するように設定します。 6. RBSの定義エラーを回避するために最小限の型を書く これまでの作業で、多くの型情報を生成できましたが、やはり一部の型情報は自動生成できない場合があります。そのような場合、手動で最小限の型情報を記述することで、エラーを回避します。例えば、Active Admin など一部のジェムは公式の型情報が提供されていないため、自社で型情報を記述する必要があります。ここまで実施し、RBSの文法エラーがない状態にプロジェクトを持っていきます。 まとめ:最小限のRBSで入力補完に型を使用できる RBS + Sord の導入方法 Sordというジェムを使用しヤードドキュメントからRBSコマンドの型を生成します。 まずSordを導入し、Rakeタスクでsordを実行します。このとき sord のバグは、GSub で書き換えるとうまくいくことがあります。 この手順で、 bin/rails rbs:setup を実行するとRBSが生成され、入力補完が賢くなる世界を作ることができました。 ちなみに、RubyMine や VS Code を使用していると、入力補完が賢くなるケースがあるようです。 型検査の課題 タイミーにおける型検査の課題は、Steepの型定義が少ないため、誤検知が発生する可能性があること、 また、特定のファイルのみを無視することができないため、段階的な導入が難しいことが挙げられます。 実際にどれくらいエラーが検出されるか検証をしてみると、656件ありました。ほとんどが誤検知ですが、そのなかで3件ほど面白いエラーがありましたのでご紹介します。 型検査で見つけたコード例1 型検査では、nilチェックが甘いため、ハーストした後にnilが来る可能性があることを考慮せず、IDなどの値に代入してしまうケースがありました。 型検査で見つけたコード例2 タイミーでは、ハッシュから銀行コードを取得する際に、全銀コードがない場合、nilが返されます。このときエラーを検知してしまいます。これは、Steepが全銀コードが正しい値しか渡されないことを前提としているためです(全銀コードが存在しないケースを想定できていない) 型検査で見つけたコード例3 足し算と掛け算をするときに、右の値をぼっち演算子を使うのですが、このときNilエラーが発生します まとめ 今後、開発がさらに進化し、堅牢なコードを手軽に書ける世界がやってくるかもしれません。特に、入力補完の文脈で型検査を導入することは導入ハードルが低く、Railsアプリケーションの開発に大きな価値をもたらす可能性があります。明日からでも是非、Railsアプリ開発に型検査を取り入れてみてください。 記事の発表やその他の発表が気になる方はこちら! www.youtube.com 少しでも興味を持っていただいた方は是非こちらからカジュアルにお話しましょう! product-recruit.timee.co.jp
タイミーでバックエンドエンジニアをしている新谷 id:euglena1215 です。 今回は社内で決めたコーディングルールに強制力を持たせるために CustomCop を作った話を紹介します。 背景 タイミーの Rails アプリケーションには /app/services ディレクト リがあり、 Service クラスが存在しています。 これまで社内で Service クラスは、なるべく使わない方が好ましいものの、どんな時に使っていいかは特段明言されていない状況でした。 その結果かは分かりませんが、一部の機能では Service クラスを多用し Service クラスが Service クラスを呼んでいるなど複雑になっており、コードリーディングの負荷が高まっていました。 この現状に課題感を持った @rhiroe が以下のような問題提起を行いました。 この問題提起を受け、チーム横断の技術領域ごとのトピックについて話し合う MTG で今後の Serivce クラスの運用方針は以下のように決まりました。 Serviceクラスは基本的に積極的な利用は推奨しない。 Service クラスは Controller や Sidekiq Worker から呼ぶものと位置付ける。それら以外から呼びたくなった場合は Model の作成を検討すること。 方針についてバックエンドエンジニア全体に周知は行われましたが、あくまで「きちんと覚えておきましょうね」に留まり、仮に実装者とレビュアーが思い出すことができなければそのままマージされてしまいます。 そのため「このルールを 機械的 に適用できるといいよね」という話があり、用途に合わせた CustomCop を作ることになりました。 特定のsuffixを持つクラス以外からのサービスクラス呼び出しを警告する cop 早速ですが、CustomCop の実装をまるっと公開します。 # frozen_string_literal: true begin require ' rubocop ' rescue LoadError return end module CustomCops # 特定のsuffixを持つクラス以外からサービスクラスを呼び出した場合に警告します。 # AllowSuffix は config パラメータで設定できます。 # # @example # # bad # # AllowSuffix に Service が含まれていない場合 # class SampleService # def call # Service2Service.new.call # end # end # # # good # # AllowSuffix に Service が含まれている場合 # class SampleService # def call # Service2Service.new.call # end # end # class AllowServiceCallClassSuffix < RuboCop :: Cop :: Base MSG = ' 特定のsuffixを持つクラス以外からサービスクラスを呼び出すことはできません。%<suffixes>s のみが許可されています。 ' # ① 許可されている Suffix を持つクラスの定義かどうか # ② クラス定義の中で更にクラスかモジュールを定義しているかどうか # この cop で重要なのは最も深いクラス定義での情報なのでネストしているものは無視(≒許容)する def_node_matcher :define_allow_class? , <<~ PATTERN { (class (const ... #allow_class_name_suffix?) ...) (class const ... {class module}) } PATTERN # (send (const nil? #service_class_name?) :new ...) => FooService.new(...) # (send (const cbase #service_class_name?) :new ...) => ::FooService.new(...) # (send (const const #service_class_name?) :new ...) => Bar::FooService.new(...) def_node_matcher :call_service_class? , <<~ PATTERN (send (const {nil? cbase const} #service_class_name?) :new ...) PATTERN # on_class はクラス定義が行われた時に呼び出されるメソッド def on_class (node) # 許容されるクラスであれば無視する return if define_allow_class?(node) node.each_descendant( :send ) do |send_node| # サービスクラスの呼び出しをしていれば警告する add_offense(send_node, message :) if call_service_class?(send_node) end end private # AllowSuffix で指定した suffix を警告メッセージに加えたかったので上書きしている def message format( MSG , suffixes : allow_suffixes.join( ' , ' )) end # call_service_class? マッチャで使っている def service_class_name? (name) name.to_s.end_with?( ' Service ' ) end # define_allow_class? マッチャで使っている def allow_class_name_suffix? (name) allow_suffixes.any? { |suffix| name.to_s.end_with?(suffix) } end def allow_suffixes # `cop_config` で rubocop.yml で指定した設定を取得できる @allow_suffixes ||= cop_config[ ' AllowSuffix ' ] || [] end end end rubocop.yml には以下のような記述を行います。 CustomCops/AllowServiceCallClassSuffix : AllowSuffix : - Controller - Worker どんな cop かを軽く説明します。 rubocop.yml で指定した AllowSuffix を suffix に持つクラスからの Service クラスの呼び出しを許容し、それ以外のクラスからの呼び出し時には警告を出します。 タイミーでは、Service クラスに XXXService.call のような特異メソッドを用意せず、 XXXService.new.call というように インスタンス を作成した上で呼び出すことが通例となっているため XXXService の new メソッドが呼び出されたことを検知しています。 ここは、各社の通例に合わせてもいいですし、任意のメソッドを呼び出したことを検知しても良いと思います。 また、 service_class_name? メソッドではクラス名の suffix が "Service" かどうかをチェックしていますが、ここを変更すれば Service クラス以外にも適用可能です。 Model, View, Controller 以外のレイヤを採用している Rails アプリケーションであれば、Service クラス以外でも呼び出し箇所を制限したいことがあるかもしれません。 結果どうなったか 上記の CustomCop をタイミーの Rails アプリケーションに導入した結果、違反している箇所が 67件 見つかりました。違反しているファイルを rubocop_todo.yml から眺めてみると、Model から Service を呼び出しているケースと Service から Service を呼び出しているケースが半々くらいのようです。 2024/01/24 時点では、導入したばかりでこれらの違反を解決するための動きは取れていません。 ですが、増やそうとすると RuboCop に怒られるのでこれ以上増えることはないのではないかと考えています(そう信じています)。 タイミーのプロダクトは 1つの モノリス な Rails アプリケーションの上で動いています。その中での67件が多いか少ないかはみなさんの判断にお任せします。我々はこれが伸びしろだと捉え、がんばっていこうと思います。
はじめに 私自身の事例 日々の学習・研究時間の確保 育児との折り合い パートナーや家族のサポートの重要性 日々の学習や研究の効率化 効率的な勉強法や研究の進め方の文献 社会人の特権のツールへの投資 ストレス管理と心の健康 タイミーという最適な環境 育児への支援制度 自己研鑽への支援制度 DSグループでの働き方 まとめ はじめに こんにちは、株式会社タイミーのデータエンジニアリング部データサイエンス(DS)グループ所属の貝出です。 私は現在タイミーで働きながら、育児しつつ、社会人大学院(修士)に通っています。今回のブログでは、仕事・育児・社会人大学院をどう調整して進めていくかについて書いていきたいと思います。 私自身の事例 簡単な私のプロフィールとしては、以下となります。 妻と一歳の息子の三人家族 妻は2023年度までは育休を取得予定 タイミーで週5リモートワーク勤務 JAIST博士前期課程社会人コースの社会人大学院生(2023年4月から) となります。 もともと大学時代では別分野を専攻していたということもあり、業務を進める上で情報科学の知識や研究経験が十分でないことに課題を感じていた私は、妻の後押しもあり、2022年2月頃に社会人大学院への進学を決意しました。研究室の先生や前職の同僚の助けもあり、無事にJAISTに入学することができました。 ただ、入学することよりも修了することの方が何倍も大変であり、そのためには、育児と仕事をこなしつつ、日々の学習や研究を進める必要がありました。 日々の学習・研究時間の確保 社会人大学院生は、通常の大学院生に比べて圧倒的に時間が足りなくなります。それに加え、育児によりさらに時間がなくなります。そのため、どうにか工夫をして時間を捻出する必要がありました。 時間を確保するアプローチとして、個人的には以下をとっています。 育児との折り合いをつけ、時間を確保する 日々の学習や研究を効率的に進める 育児との折り合い 基本方針としては、子供が寝ている間に学習・研究時間の確保が可能です。そのため、 朝5時に起き、子供が起きるまで集中的に時間を確保する 子供の寝かしつけが終わってからの時間を確保する ができます。私の場合は、早朝の 5:00~7:00 と、夜の 21:00 ~ 22:30 のあたりを確保しています。ただ、子供が6:30ぐらいに起きることもあるので、そのときは早めに切り上げたりしています。 パートナーや家族のサポートの重要性 あとは、週末や休日の仕事がないとき、妻に子供を見てもらっている時間に、学習・研究時間を確保します。ただし、ここについては家庭内で十分コミュニケーションを取り、妻の理解を得ることが必要です。また、夫婦間でバランスが崩れないように調整することも必要です。 自分が子供を見る時間は、一緒に公園や近所の公民館に行き、妻のフリーの時間をなるべく確保できるように努力しています。最近は歩けるようになって、すごく楽しそう! 日々の学習や研究の効率化 時間を確保するアプローチの2つ目として挙げた、「日々の学習や研究を効率的に進める」を実施するために、 効率的な進め方に関する文献を調査し、実践する テクノロジーを活用したツールに惜しみなく投資する を行っています。 効率的な勉強法や研究の進め方の文献 効率的な勉強法や研究の進め方ってそもそもどうやんの?というところを現役の学生になったつもりで再度勉強しました。参考になった本としては、以下の本があります。 「勉強法のベストセラー100冊」のポイントを1冊にまとめてみた。 研究の育て方: ゴールとプロセスの「見える化」 卒論・修論研究の攻略本:有意義な研究室生活を送るための実践ガイド 学習については、「(1)こまめに復習をする と (2) 覚えたことをアウトプットする(口に出す、空で説明する、書く)」を大事にしています。あとは、時間を決めて集中できるようにして取り組むなど。 一年目は講義に集中していたため研究はあまり進んでいないですが、先程挙げた本を参考に研究の効率化も進めればと考えています。 社会人の特権のツールへの投資 社会人と現役の学生の最大の違いは時間とお金だと思っており、社会人は時間がない分、仕事で稼いだお金を使って自身の学習への投資が可能になります。 私のケースだと、論文読みやノートのために iPad Air を購入しました。便利なアプリとしては以下を利用しています。 Good Note 6(電子ノート) Paperpile(論文管理ツール) Kindle(本) これらのツールを用いることで、ノートや本、論文を持ち歩かなくても、どこでも学習や論文読みが可能になります! Good Note 6 は、空白のノートだけでなく講義のスライドも読み込めるので、デジタル上でスライドに書き込めるところがとても便利です。 Paperpile は論文管理ツールですが、講義の Class Note や PDF形式の教科書として読み込んでも便利です。例えば、目次や式の番号をパースしてくれて、リンクとして飛べるようになっているので、読む効率が上がります。自分の認識している範囲だと、Good Note 6にはこの機能がないので、使い分けています。ペンやマーカーなどの書き込む機能については、Good Note 6の方が自由度が高いですね。 ストレス管理と心の健康 日々の限られた時間の中で、仕事と育児、それから社会人大学院とたくさんやることがあり、生活に余裕がなくなってしまい、知らないうちにストレスを溜めてしまうことがありました。それが原因で、眠れなかったり、いらいらしたりしてしまうこともありました。心の健康を保つためにもストレス管理に注意する必要があります。 私が気をつけるようにしていることは、 1,2 時間ぐらい机で作業した後は、10分ぐらいふらっと散歩したりストレッチしたりする。 頭が疲れて回らない場合は、ぼーっと10分ぐらい何もしない、何も考えない(瞑想といえば瞑想)。 眠いときは遠慮せずに寝る 定期的に家族内や友達のイベントを作って、全力で楽しむ ジムに行ったり、ジョギングをしたりなど、定期的な運動の習慣を作る 1日の最後は夫婦でおしゃべりをして、リラックスする です。 また、学習や研究がどうしても予定通りにいかないことがあります。子供が熱で体調を崩したり、急遽別の予定が入ったりなど。また、自分のタイムマネジメントがうまくいかず、思ったように学習や研究が進まないこともあります。 そのようなときは一旦無理なスケジュールを引いている状態を認識して、緊急度と重要度のマトリクスを作成し、優先度の低いものからは撤退するようにしています。やっぱり無理なものは無理なので。 タイミーという最適な環境 さて、これまでは育児や大学院での過ごし方などプライベートに関する話がほとんどでしたが、冒頭にも書いた通り、タイミーでは育児や自己研鑽への支援制度があり、私のような技術職には大変ありがたい環境となっています。 育児への支援制度 タイミーでは産休・育休とは別に以下の制度があります。 出産休暇:配偶者が出産する際、産休・育休とは別に、出産当日までの間で3日間の特別休暇を付与(有給) 子の看護休:子どもの看護を目的に、子ども1人につき年間5日付与(子ども2人以上は10日が上限) corp.timee.co.jp 自己研鑽への支援制度 また、タイミーではエンジニアの市場価値向上につながる成長支援、学習支援、機会提供、生産性向上に資する取り組みも実施しています。そのための組織として DevEnable 室を設立し、「TDE10(Timee Dev Enable)」という、エンジニアの進化のための10の施策が進められています。 DSグループでの働き方 DSグループでは、フルリモート勤務も可能であり、フレックスタイム制(コアタイム12:00~16:00/所定労働時間8時間00分、休憩60分)であるため、個人の状況にあわせて働き方を調整することができます。実際に、保育園に通っているお子さんがいる社員は、保育園へのお迎えの時間にあわせて就業時間を調整していたりします。 まとめ 今回の事例では、私のケースが育児と社会人大学院の両立というレアなケースでしたが、タイミーでは働きながら育児や自己学習に取り組む社員がたくさんいます。当社は多様な働き方が可能な職場環境を提供し、柔軟でサポートが充実している条件のもと、異なるバックグラウンドやライフスタイルを持つ方達が活躍しています。 現在、タイミーではデータサイエンティストやエンジニアなど、一緒に働く新しいメンバーを積極的に募集しています! また、気軽な雰囲気での カジュアル面談 も随時行っておりますので、ぜひお気軽にエントリーしてください。↓ hrmos.co hrmos.co
自己紹介 部署紹介 一日の流れ 朝のルーチン: 午前中の仕事: 9:00~11:00 フォーカス課題の分析 11:00~11:30 データアナリスト全体のデイリーミーティング 11:30~12:00 他のメンバーのクエリレビュー 昼休憩: 午後の仕事: 13:00~13:30 依頼タスクのヒアリング 13:30~14:30 依頼タスクの対応、納品 14:30~16:30 フォーカス課題の分析 16:30~17:00 定例ミーティング(部署連携の持続PJT) 17:00~18:00 採用面接 18時から中抜け(あるいはそのまま退勤): 20~21時以後: 20:00~20:30 面接の議事録完成、評価の完了 勤務体系 We’re Hiring! 自己紹介 こんにちは、タイミーのデータアナリストチームの一員、胡です。 私の日本でのキャリアは約10年前、早稲田大学院でMBA取得を目指して来日したことから始まりました。 学位取得後、開発ベンダー企業でエンジニアとしてキャリアをスタートし、その後中小企業でシステム統括の責任者、製造業のベンチャー企業での経験を積みました。 これらの職場で、データに関する多くの課題に直面し、自らの手で社内のデータ環境を整備することもありました。 この経験が、データアナリストとしてのスキルを磨く大きな契機となり、最終的にタイミーでのキャリアをスタートさせるに至りました。 プライベートでは、2歳になる娘を持つ三人家族の一員として、忙しい日々を過ごしています。 最近では、趣味と言えばすっかり子育てに夢中になっています。子育ては日々の新しい発見と喜びに満ちており、私の人生にとって大切な部分です。 家庭と仕事のバランスを保ちながら、日々成長を続けていけたらと思います。 タイミーで働くことで、充実したキャリアを築きつつ、家族との時間も大切にすることも可能です。 部署紹介 タイミーは、急速に成長を遂げているベンチャー企業です。その成長の基盤の一つが、私たちデータ統括部です。 データアナリストは、現場のチームと協力しながら、実際の業務に即した分析を行っています。また、経営層との密接な連携を通じて、経営に関する直接的な提案を行うことも可能です。 私はプロダクトアナリティクスチームに所属し、プロダクトの改善と向上に日々貢献しています。同じ部署での同僚であるtakahideさんの記事も参考になるでしょう。> takahideさんの記事はこちら 今日は、タイミーのデータアナリストとしての一日を紹介し、私たちの業務の流れを具体的にお伝えします。それでは、さっそく始めていきましょう。 一日の流れ 朝のルーチン : 朝は7時頃に起きます。家族との朝食は一日の始まりの大切なひととき。 娘を保育園に送り出した後、9時前後に自宅の仕事スペースへと移動し、一日の業務をスタートします。 仕事を始める前に、短い時間を使ってメールのチェックや一日のスケジュールを見直します。 午前中の仕事 : 9:00~11:00 フォーカス課題の分析 直近のフォーカスしている課題として、時給と勤務状況の関係性に関する分析です。 こちらは、プロダクトマーケティング(PMM)部と連携しながら進めており、得られたデータから新たなビジネス洞察を得ることが目標です。 フォーカス課題は、担当する部署の目標から派生した課題や、日々の業務から得た気付きに基づく自由研究も含まれます。 進め方としては、議論を重ねて仮説を立てて、それを検証していくサイクルを回します。この過程に置いて、PMM部との協力は非常に重要です。彼らの市場に対する深い洞察と私たちのデータ分析能力が相乗効果を生み出すことで、最終的には、この分析がプロダクト機能の拡張という形で実現されることを目指しています。 11:00~11:30 データアナリスト全体のデイリーミーティング この時間帯は、データアナリストチーム全体でのデイリーミーティングを行います。 ここでは、チーム全員で共通の連絡事項を共有し、データアナリスト部向けの依頼タスクの対応方法について話し合います。通常、このミーティングは30分間設定されていますが、内容によっては早く終わることもありますし、新しいアイデアや施策につながる議論が盛り上がることもあります。 依頼タスクについて少し詳しく説明します。現在、私たちのチームはマーケティング、ビジネス、プロダクトといったユニットごとに分かれており、各ユニットは通常、特定の課題に集中しています。しかし、全社からのデータ抽出依頼が多数寄せられるため、これらに対応するにはチーム全体でリソースを効率的に調整する必要があります。 Lookerの導入と普及により、多くのデータ抽出は各部署が自力で行えるようになりましたが、複雑なデータ集計やLookerで対応できない項目がある場合は、依然として私たちのチームへ依頼が来ます。 これらのタスクは専門性を要求されることは少ないですが、緊急性が高く迅速な対応が求められます。メンバー一人ひとりがこれらのタスクに取り組む頻度は、週に1回くらいです。 11:30~12:00 他のメンバーのクエリレビュー 一般的に、私たちの日常的な課題や依頼タスクの成果物は、データを抽出した後、そのまま提出して完了となります。 しかし、社外向けの資料や財務に関わるデータなど、特に正確性が重要視される場合があります。こうした場合には、原則としてレビュワーを割り当てて、二重チェックの体制を取ります。 この二重チェックプロセスは、データの品質を保証し、エラーや誤解を防ぐために不可欠です。レビューは、データの正確性だけでなく、使用される分析方法や導かれた結論の妥当性についても検証します。 これにより、提供するデータと情報の信頼性を向上させ、私たちのデータアナリスト業務の品質を高めることができます。 昼休憩 : 昼休憩の時間は、日によって多少前後することがありますが、基本的には冷蔵庫にある食材を使って手早く料理を作り、食事をします。 時間が許せば、10〜15分の短い仮眠をとることもあります。 午後の仕事 : 13:00~13:30 依頼タスクのヒアリング 午前中にアサインされた依頼タスクの取り組みに先立ち、依頼者へのヒアリングを行います。依頼タスクの要件は通常、事前に依頼者によって文書化されていますが、より詳細な情報が必要な場合はさらなる確認が行われます。 このステップは必ず行うわけではなく、要件が明確に定義された場合は、成果物を作成した後に依頼者とイメージをすり合わせたり、結果を直接チャットで伝えたりすることもあります。 使い道の確認 抽出データがどの程度の規模で、どれくらいの期間使用されるかを確認し、それに基づいて適切な出力形式を提案します。また、抽出データが他の目的にも汎用的に使用できる場合、今後の依頼タスクでの流用の可能性を検討して作成していきます。 項目の定義のすり合わせ 項目によっては、部署ごとに基準が異なることがあります。そのため、集計条件や項目の定義を明確にしておきます。 抽出項目の提案 時に依頼者がデータに関するリテラシーが低い場合や、要件が十分に記載されていない場合があります。このような状況では、実際に求められている内容を詳しくヒアリングし、最適な出力方法をアドバイスします。 13:30~14:30 依頼タスクの対応、納品 先ほどヒアリングで得た結論に基づいて早速作業に取り組みます。タスクの難易度にはばらつきがあるため、完了までの時間はさまざまです。通常は30分から60分で完了するタスクもありますが、依頼者との段階的なやりとりが必要な場合は、全体として数時間を要することもあります。 14:30~16:30 フォーカス課題の分析 午前中に取り組んでいたフォーカス課題の分析作業を続けます。この作業には、集中を要するため、中断されることなく継続的に取り組むことが重要です。そのため、あらかじめスケジュールをブロックしておくことで、分析に専念する時間を確保できます。 16:30~17:00 定例ミーティング(部署連携の持続PJT) データ統括部以外の部署と協力して進めている持続的なプロジェクトの定例ミーティングを行います。プロジェクトの性質によって、その期間は通常数週間から数ヶ月に及び、状況に応じて定例ミーティング以外の方法での連携も行われることがあります。 この定例ミーティングでは、私が社内でリリースした営業用ダッシュボードの利用状況と改善点に重点を置いています。このダッシュボードは社外向けで、営業活動における重要なツールとして利用されています。現在、社内で最も頻繁に参照されるダッシュボードの一つであり、営業効率の向上と営業レベルの平準化に大きく寄与しています。 17:00~18:00 採用面接 急速に拡大しているタイミーでは、新たな才能とスキルを持つ仲間を増やすことが非常に重要です。 面接では、候補者の技術的能力やチームとの相性、将来のポテンシャルを評価します。これには、専門的なスキルだけでなく、組織文化への適合性やコラボレーション能力も含まれます。私たちは、優秀な人材を見極め、チームと会社全体の成長を支える人材を採用することを目指しています。 18時から中抜け(あるいはそのまま退勤) : 一日の仕事を終えた後の夕方は、家族との大切な時間です。 最初に保育園に娘を迎えに行き、その後は家で夕食の準備に取り掛かります。家族みんなで食事を共にし、その後は子供と一緒に楽しいバスタイムを過ごします。 毎晩ではないものの、娘が就寝する時間が近づくと、その準備は妻が担当し、私はその間に追加の仕事に取り組むことがあります。 20~21時以後 : 20:00~20:30 面接の議事録完成、評価の完了 行われた面接に関する議事録のまとめや、面接評価を行います。 また、この時間を使って追加分析やタスクの整理を行うこともあります。あるいは、そのまま切り上げてプライベートで映画や読書などに充てることもあります。 こちらは私のある一日の過ごし方です。タイミーでデータアナリストとして働く中で、仕事とプライベートのバランスを保ちつつ、様々な課題に取り組む毎日を送っています。 いかがでしょうか。少しでもタイミーでのデータアナリストとしての仕事のイメージをつけたら幸いです。 勤務体系 データ統括部では、フルリモートワークが可能であり、始業時間も柔軟に設定できます。これにより、私たちは自分のライフスタイルに合わせた働き方を選ぶことができます。 私の場合、育児のため、18時には仕事を切り上げることができます。これにより、家族との時間を大切にしながら、効率的に業務を進めることが可能になっています。 さらに、最近は娘が月に一度程度熱を出すことがあり、その都度スケジュールを調整したり、同僚からのサポートを受けたりしています。タイミーでは、このような状況にも柔軟に対応しやすい環境が整っています。 We’re Hiring! 私たちは、ともに働くメンバーを募集しています!! product-recruit.timee.co.jp
タイミーのyama_sitter、須貝、小林です。 国内最大級の アジャイル 、 スクラム 関連のイベント「Regional Scrum Gathering Tokyo 2024(RSGT2024)」 が1/10〜1/12の3日間にわたって開催されました。 2024.scrumgatheringtokyo.org タイミーには世界中で開催されるすべての技術系カンファレンスに無制限で参加できる「Kaigi Pass」という制度があります。 productpr.timee.co.jp こちらの制度を利用して今年は スクラム マスター3名、エンジニア3名が参加してきました。 前編 に続き、後編の今回はエンジニア3名から参加レポートをお送りします。 SM/EMからエンジニアに視点を変えて参加 エンジニアの yama_sitter です。 参加は今年で2回目になります。前回は前職からSM/EMの立場として参加しましたが、今回はタイミーの現場エンジニアという立場で参加する形となりました。 「エンジニアからSMになり、EMを経てエンジニアに戻った人」という視点で、特に印象に残ったセッションが3つありましたので紹介します。 Badプラクティスを選んで失敗しながら進めた新規プロダクト開発 自分はSM時代に「形」に捕らわれ過ぎて色々な失敗を重ねてきました。一方で今所属するチームではいわゆる スクラム の形式では仕事をしておらず、それでもちゃんと成果が出せている状態です(※1)。これらの経験から、この1年ほどは「 アジャイル は形じゃない」というのを自分なりに理解し、また考え続けていました。(この間、世に出回る「べき論」や「プ ラク ティス」みたいなものをとにかく疑ってかかっていました) そんな中見たのがこの「Badプ ラク ティスを選んで~」のセッションです。ここでは世間的にはNGとされるプ ラク ティスを敢えて用い、(もちろん苦しみながらも)ちゃんと成果を出した事例が語られていました。Badと言われるものだと分かった上で、そのリスクを理解し取り入れ、結果に結び付ける。このあり方は教科書的でこそないものの、ちゃんとした一つの解だなぁ、と。 つまるところ「価値に向き合い、自分たちが考えうる/持ちうる最大の力で成果を生み出す」ことが重要なのであって、形ではないなという話です。今の自分が感じていることを後押しし更に前に進めてくれたこのセッションは非常に有意義なものでした。 こちらはスライドもあるので是非ご一読を。 speakerdeck.com ※1 あくまで会社全体としては スクラム に力を入れており、自チームは特殊なケースです Lack of curiosity: The silent killer of agile 「好奇心の無さはアジリティを殺す」という話です。内容は勿論ですが、特にこのタイトルが強く印象に残っています。 入社して半年、以前考えていた抽象的な問いからは離れて今はひたすらに具象と向き合っています。入社直後に感じていた様々な疑問も少しずつ薄れてきました。アウトプットこそ出せているとは思います。が、少しずつ「疑問に思う力」や「ワクワクする力」がマヒしていっているのを感じています。 これだと、本当に向き合うべき課題に気付き向き合うことができないんですよね。セッションでも述べられていましたが、「人間はルーチンが好き」なので尚更です。 自分や目の前のコードとひたすら向き合うだけでは高い視点からは物事を考えられません。疑問に思わなければ脳が刺激を受けずに鈍化していきます。ワクワクしていなければ途中で力尽きます。結果として気付ける課題、向き合う課題がすごくミニマムになっていく。 現場にフォーカスするだけだと、巡り巡って良いエンジニアにはなれないなぁ、ちゃんと好奇心を持ち続ける努力をしないとなぁ、と感じさせるセッションでした。 Solving The Value Equation 「レガシーコード改善ガイド」の著者であるMichael Feathersさんのキーノートです。 めちゃくちゃためになる話ばかりでしたが、個人的に刺さったのは「プロセス、 アーキテクチャ 、チームの能力、組織構造といった各レイヤーの目標は、 “価値に至るまでのプロキシ” でしかない」という話です。 “プロキシ” というのが特に良くて、これを意識すると「今の取り組みとその結果は、必ず何らかの価値に転換されるために存在する」という考え方ができます。当然のことではあるんですが、目の前のことにフォーカスしたり「べき論」に囚われたりすると忘れがちだなぁ…と思ったりします。 余談ですが、前職のSM最初期の頃は「それっぽいメトリクス」を見つけては右往左往していました。あれはあれで必要なプロセスだったものの、できればこの “プロキシ” の考え方を持っておきたかったです。 視点を変えての参加となりましたが、選ぶセッションも見るスタンスも感じることも得られるものもかなり違うし、得るものの幅が増えていることに気付いて面白かったです。一度全力でSMをやってからエンジニアに戻ると面白いですね。 とまぁここまで色々書きましたが、正直セッションよりも「素晴らしいセッションを見たあとに同じ熱量を持ったタイミーメンバーと集まり、酒を飲みながら議論する」時間が一番良かったです。こういった時間のために行っているフシすらある。 総じて、RSGTは今年も良いイベントでした。企画/運営の皆さま、ありがとうございます。 メンバーと自分たちの組織について語り合うきっかけに エンジニアの 須貝 (CSM保持)です。 RSGTは今回が初参加でして熾烈なオンサイトチケットの争奪戦を勝ち抜いて現地に行ってまいりました。自分は現在はマネージャーでも スクラム マスターでも無いのですが、以前からチーム・組織で成果を出すにはどうすれば良いかといったテーマに興味があったので参加しました。 基本はセッションを聞くことを中心に、合間の休憩時間などで知り合いの方とお話をして過ごしました。中でも印象に残ったセッションのひとつはJoe Justiceさんの「 ジョーが語る、Teslaでの衝撃的な開発スピード 」です。電気自動車メーカーTeslaの開発サイクルのあまりの速さに本当に自動車の開発なのか!?と驚きの連続でした。と同時にハードでこのスピードでできているのだからソフトウェア開発をしている自分たちももっとやれるのでは、勝手にできないと思っているだけなのでは、という反省もありました。 オフトピックなところだと会場内でプロのカメラマンに写真を撮ってもらえるフォトブースがあったのが良かったです。Global Scrum Gathering Amsterdamで行われていたものが日本にも輸入されたそうです。 プロのカメラマンに撮影されるりっきーさんとShinoPさん 自分たちは普段フルリモートなので、弊社のメンバーと自分たちの組織などについて対面でじっくり話せたのも非常に良い体験でした。チャンスがあればまた参加したいと思います。 RSGTは気づきと学びの場 こんにちは!タイミーでQA スペシャ リストを担当している小林依光です。 RSGTはオンラインで参加しましたが、今回も「やっぱりそうだったんだ」と自分の知識や経験を後押ししてくれる発表内容に、感謝の気持ちでいっぱいになりました。 事例/実績、考え方の共有は気づきと学びの場だと、改めて思いました。 少しですが、私が気になったセッションについて、紹介したいと思います。 「 ベロシティ Deep Dive 」ではベロシティを生産性に活用することをやめましょう!ということを多様な角度から説明していました。どの角度からの説明も納得感のあるものばかりでしたが、一番印象的だったのが、“ アジャイル や スクラム が目指すのは価値の実現であり、この文脈での生産性は「付加価値生産」である”という説明でした。 アジャイル を採用し探索的/実験的にプロダクトを開発し価値を提供するという基本を忘れてはいけないと学べました。 「 プロダクトをあきらめるとき 」のセッションは一般的な スクラム の話ではありませんでしたが、実際のプロダクト開発で遭遇する実例でした。特に“プロダクトを終了させるときの費用”をプロダクト バックログ の順位の下の方に入れておくという考えには共感でき、あきらめる判断やサービス撤退に必要な洗い出しは、プロダクトを止めるときでなく開発を始める際に決めておく必要があると何度か痛感していたので、改めていままでの経験は役に立つことがあると思いました。 紹介したセッション以外からも多くを学べたRSGT、来年は現地で参加できるようにしたいと思いました。 まとめ いかがでしたでしょうか。 参加して満足して終了では意味がない!ということで後日参加者全員で振り返り(Fun Done Learn)も行いました。しっかりと ネクス トアクションも生まれたので、ここからチーム・組織に今回得た学びを還元していければと思います。 来年もまたGatheringしましょう!
タイミーのmaho、ShinoP、りっきーです。 国内最大級の アジャイル 、 スクラム 関連のイベント「Regional Scrum Gathering Tokyo 2024(RSGT2024)」 が1/10〜1/12の3日間にわたって開催されました。 2024.scrumgatheringtokyo.org タイミーには世界中で開催されるすべての技術系カンファレンスに無制限で参加できる「Kaigi Pass」という制度があります。 productpr.timee.co.jp こちらの制度を利用して今年は スクラム マスター3名、エンジニア3名が参加してきました。 その参加レポートとして印象に残ったセッション、ワークショップや学びなどを参加者それぞれの視点で共有できればと思います。今回は前後編の前編として スクラム マスター3名のレポートをお送りします! 初参加で OST のホストに挑戦 スクラム マスターをしているmahoです。RSGTは今回が初参加で緊張していましたが、一緒に現地参加するメンバーがいたので心強かったです。 私はまだまだ スクラム マスター初心者ということもあり、セッションを聴いて学びを深めることを一番の目的にしていました。どのセッションも興味深い内容でしたが、全体を通して感じた共通点は以下の三つです。 チームの基盤を支える重要な柱のひとつは関係性であること 変化は時間がかかることを理解して忍耐を持つこと システム全体を捉えるよう努めること 私もこれが体現できるように、学びを実践しながら精進していきたいと思います。 また、三日目の OST には話したいテーマを発表し、ホストとしての参加に挑戦してみました。不安でいっぱいの中、いざ始まってみると集まってくださった方々と予想以上に議論が盛り上がり、とても楽しい時間を過ごすことができました。セッションを聴くだけでなく、Gatheringとしてもよい体験ができたので、もし次回も参加することになれば、より積極的に話す機会を作ってみたいと思いました。 どう社内に持ち帰るかを話す時間は何事にも変え難い タイミーで スクラム マスターをやっているりっきーと申します。昨年に引き続き2回目の現地参加になります。 私は毎年年末にテーマを決めていまして、1年かけて達成したかどうかを振り返っています。 その中で、RSGTは年初一発目ということで年末に決めたテーマについて知見を得たり、ディスカッションをできるので非常に助かっています。 私の本年度のテーマは「 スクラム マスターとして成長できる・やってみたくなる環境を作る」です! テーマに最も関連していたので以下を紹介いたします。 「 スクラムマスターを職能にする挑戦 - 健全なチームを増やし組織をチームワークであふれさせる道のり 」 スクラム マスターをどのように増やしていったか、どのような仕組みを作っていったかは大変参考になり、勇気がもらえました! 1on1や コーチン グ、メンタリング活動は弊社としても取り組み始めていたのですが、給与レンジの検討や成長支援の予算などは検討できてない部分なので弊社ならではを組み合わせつつ、一つの事例として社内に紹介したいと思います。 また、メンターとしては初心者の方もRSGTで楽しめるように社外の人との会話に入ってもらったり、 OST に参加するように促したりを 裏目 標として持っていましたが、楽しめたようで何よりでした! 皆さんも書いてますが、同じものを見て聞いてそれについてどのように社内に持ち帰るかを話す時間は何事にも変え難いので、来年も参加したいなと思いました。(オフライン参加は難しいかもしれませんが) RSGTのオススメの歩き方 こんにちは!タイミーで スクラム マスターをしている ShinoP です! 今回のRSGTは現地参加としては2回目なのですが、前回はセッションを聴くことに夢中になっていて、本当の意味でのGatheringができませんでした。 その中でも OST のホストをやった事で、参加者同士の触れ合いを体験しGatheringの本当の意味を理解しました。 ですので、セッションに関しての感想というよりは、RSGTのオススメの歩き方を紹介したいと思います! 今回のRSGTでの立ち回りはセッションを聴くだけでなく… 「廊下で初めて会った人と話す」 「お昼に社外の人と話す」 「研修やコミュニ ティー で面識のある人と話す」 「登壇者と話す」 「飲み会に参加する」 「お昼の30秒宣伝コーナーで話す」 などを積極的に行った結果、同じような悩みを抱えている方と話すことによってヒントを得られたり、登壇者の方と話してアド バイス をもらったり、面識のある方々とワイワイできたり…このような歩き方も学びがあるので是非試してみてください! また、RSGTや スクラム フェスは人に話しかけやすい構造になっていると思いますので、隣に座っている人とかに話しかけたりすると繋がりが広がっていくと思っていますので、是非思い切って話しかける事がオススメです! 今回のレポートは以上となります。 続きの後編は「エンジニア編」として近日公開予定です。
こちらは Timee Advent Calendar 2023 シリーズ1の25日目の記事になります。 昨日は @tomoyuki_HAYAKAWA による Swift Concurrency AsyncStreamを使ってみる #Swift - Qiita でした。 タイミーでバックエンドエンジニアをしている id:euglena1215 です。 メリークリスマス🎄 みなさんの手元にはプレゼントは届いているでしょうか。 Ruby の世界では Ruby コミッターサンタさんがクリスマスプレゼントとして新しい Ruby バージョンをリリースしてくれます。 今年は Ruby 3.3 ですね。個人的には 3.3 の YJIT がどれだけ速くなるのか楽しみです。 また、新しいバージョンのリリースにはアップグレードがつきものです。アップグレードせずには新しいバージョンの恩恵を受けることはできません。 ということで、今回はタイミーが社内で運用している社内版 Ruby Rails アップグレー ドガ イドを社外に公開します。 社内版の情報を黒塗りしては社内版を公開する意味がありません。そのため、最大限 原文ママ でお送りします。前提として足りない部分は「記事用補足」と追記しています。 社内版 Rails アップグレー ドガ イド このドキュメントは Rails アップグレードのために普段からやること、実際のアップグレードの際にやることをまとめたものです。基本的には一般的な Rails アップグレー ドガ イドと同じですが、QAチェックの必要性など社内特有の事情も考慮されています。 下記のドキュメントは Rails のメジャーバージョン・マイナーバージョンを上げる際に意識すべきことです。パッチバージョンは普段のライブラリアップデート同様に上げてもらって構いません。 🟥 MUST: 安全なアップグレードのために必ず実施しなければいけません。 🟨 SHOULD: 必ず実施しなくてもいいですが、やっておくことを推奨します。 🟩 MAY: 行わなくてもアップグレードは実施できます。関心がある方だけで構いません。 以下の作業は基本的に並列かつ複数人で実施可能です。 社内版 Rails アップグレードガイド 普段やること Rails Edge のキャッチアップ(🟩 MAY) Rails Edge 起因で失敗しているテストの修正(🟨 SHOULD) Rails へのコントリビュート(🟩 MAY) アップグレード前にやること アップグレード先のCIを用意する(🟨 SHOULD) Railsバージョン起因でスキップしているテストをなくす(🟥 MUST) deprecation warning をなくす(🟨 SHOULD) rails app:update の実行(🟥 MUST) Rails アップグレードガイドのバージョンに対応した変更を読んで問題ないことを確認(🟥 MUST) リリース前の手動での動作確認(🟥 MUST) アップグレード作業中に行うこと アップグレードの事前周知(🟥 MUST) rollback 用のコミットハッシュを取得する(🟥 MUST) Revert PR を作成する(🟩 MAY) 各種監視を行う(🟥 MUST) アップグレード後にやること new_framework_defaults_x_y.rbの有効化(🟨 SHOULD) config.load_defaultsの更新(🟨 SHOULD) 参考 普段やること Rails Edge のキャッチアップ(🟩 MAY) #guild_rails_edge には毎日 rails / rails の main branch にどんな変更がマージされたのかが流れてきます。ここで次のアップデートでどんな変更が入るのかをチェックしましょう。日頃からチェックしておくとアップデート時に情報の波に飲まれにくくなります。 (記事用補足:ここで流しているのは y-yagi さんのブログです) y-yagi.hatenablog.com Rails Edge 起因で失敗しているテストの修正(🟨 SHOULD) 通常の Rails バージョンでは動作するが Rails Edge で動かないテストは pending: pending_if_rails_edge をつけて pending してあります。 grep して pending しているテストを見つけて問題を特定し修正しましょう。 (記事用補足:タイミーでは CI で Rails Edge を使ったテストを実行しています。詳しくは以下) tech.timee.co.jp Rails へのコントリビュート(🟩 MAY) 「 Rails Edge 起因で失敗しているテストの修正」の大半はアプリケーションコードに起因する問題であることが多いですが、たまに Rails 本体のバグに遭遇することもあります。その際は Rails にバグレポートや修正 PR を送ることを推奨しています。 リリース済みのバージョンの仕様を変えるのは難しいですが、betaやrc版ではissueやPRを送ることで仕様を変えられる可能性があります。意図しない破壊的変更を見かけた場合は積極的にやりとりしましょう。 参考: Get started with OSS contributions - Speaker Deck アップグレード前にやること アップグレード先のCIを用意する(🟨 SHOULD) アップグレードを検討している頃には既にアップグレード先のバージョンがリリースされているため、 Rails Edge はその次のバージョンになっていることが多いです。そのため、 Rails Edge CI ではアップグレード先のバージョンでのテストは実行できません。 アップグレード先の Rails バージョンでの CI を用意しましょう。そうすることで、アップグレード先バージョンでのテストが普段から実行できるようになるので問題を早期発見できます。 参考 (ここに Rails 7.1 の CI を用意した Pull Request URL が貼ってありました) Rails バージョン起因でスキップしているテストをなくす(🟥 MUST) Rails バージョン起因でスキップしているテストはアップグレード後に動かなくなるテストです。このテストを放置したままアップグレードを実施すると該当機能が動かなくなるので必ずスキップしているテストがないことを確認しましょう。 「 Rails Edge 起因で失敗しているテストの修正」を実施していればスキップしているテストはほとんどなくなっているはずなので、このステップの対応が楽になります。 参考 (ここに Rails バージョン起因でスキップしているテストを修正している Pull Request URL が貼ってありました) deprecation warning をなくす(🟨 SHOULD) ほとんどの問題は「 Rails バージョン起因でスキップしているテストをなくす」によって解消されますが、テスト環境では捉えきれない問題も存在します。それらの問題を洗い出すために、タイミーでは本番環境で発生した deprecation warning をログとして出力するようにしています。出力されたログは Datadog Logs で確認できます。 また、ログが出力されすぎて Datadog のコストを圧迫することを防ぐためにログ出力は確率的としています。deprecation warning が減ってきたら合わせて確率を100%に近づけ漏れなくキャッチできるようにすることを推奨します。 rails app:update の実行(🟥 MUST) Rails では app:update というコマンドが提供されています。 Gemfile に記載されている Rails のバージョンを更新後、このコマンドを実行することで、新しいバージョンでのファイル作成や既存ファイルの変更を対話形式で行うことができます。 $ bin/rails app:update exist config conflict config/application.rb Overwrite /myapp/config/application.rb? (enter "h" for help) [Ynaqdh] force config/application.rb create config/initializers/new_framework_defaults_7_0.rb ... 予期しなかった変更が発生した場合は、必ず差分を十分チェックしてください。 https://railsguides.jp/upgrading_ruby_on_rails.html#アップデートタスク デフォルトに合わせていた方が今後のアップグレードが楽になるため、既存の挙動をなるべく変化させないように更新分を取り込みましょう。 変更差分を知りたい場合は https://railsdiff.org/ から確認できます。 Rails アップグレー ドガ イドのバージョンに対応した変更を読んで問題ないことを確認(🟥 MUST) 公式の Rails アップグレー ドガ イドにはメジャーバージョン・マイナーバージョンのアップグレードに対して破壊的変更など何らかの対応が必要な変更がまとまっています。これらを確認して問題がないことを確認してください。懸念がある場合は #prd_ch_ruby_on_rails で相談するなど適切な対応を行なってください。 例:7.0→7.1 Rails アップグレードガイド - Railsガイド 参考 (ここに確認したログをまとめた Notion リンクがありました) リリース前の手動での動作確認(🟥 MUST) リリース前の手動での動作確認は必須ですが、社内向け管理画面の最低限の疎通確認のみで問題ありません。 背景: (ここに意思決定の証跡として MTG 議事録リンクが貼ってありました) また、社内向け管理画面においても十分なテスト カバレッジ があれば動作確認を省略することができます。社内向け管理画面のテスト カバレッジ を上げるプロジェクトについては(Notion URL が貼ってありました)を確認してください。 (記事用補足:プロジェクトの Notion URL よりもTimee Advent Calendar 2023シリーズ1の5日目記事の方がより詳細にプロジェクトの説明をしています。興味があればご覧ください。) tech.timee.co.jp アップグレード作業中に行うこと アップグレードの事前周知(🟥 MUST) Rails アップグレードのリリース直後に rollback が困難な変更が行われると Rails アップグレード起因で問題が発生した際に rollback が困難になり、問題の復旧が遅れます。そのため、アップグレードを事前に周知しアップグレード後30分間はデプロイ(=マージ)を行なわないよう呼びかけてください。 rollback 用のコミットハッシュを取得する(🟥 MUST) 問題があった際の復旧を早めるために rollback で戻す先のコミットハッシュを用意しておきましょう。 https://github.com/x/x/commits/master から確認できます。 Revert PR を作成する(🟩 MAY) 問題があった際の復旧を早めるために merge 後すぐに Revert PR を作成しておくことを推奨します。先に Revert PR を作っておけば feature branch での CI 待ちをショートカットすることができます。 問題が発生せずに無事リリースできた場合はきちんと PR を close しておきましょう。 各種監視を行う(🟥 MUST) リリース直後は問題を早期発見するために各種の監視を行なってください。15分様子を見て問題が見つからなければ急いでrollbackする必要はありません。 Sentry 普段見かけないエラーが発生していないかどうか Datadog ダッシュ ボード 大きなメトリクスの変化がないかどうか APM レイテンシやエラーレートに変化がないか (記事用補足:Sentry や Datadog など各種 URL が貼ってありましたがさすがに削除させていただきました) アップグレード後にやること new_framework_defaults_x_y.rbの有効化(🟨 SHOULD) Rails をアップグレードしただけでは多くの新しい機能は有効化されていません。 rails app:update で作成された new_framework_defaults_x_x.rb の コメントアウト を1つずつ確認してデフォルトに合わせられそうなものは有効化しデフォルトに合わせ、意図を持ってデフォルトとは異なる設定を行う場合は application.rb に設定を追記しましょう。 config.load_defaultsの更新(🟨 SHOULD) app:update タスクでは、アプリケーションを新しいデフォルト設定に1つずつアップグレードできるように、 config/initializers/new_framework_defaults_X.Y.rb ファイルが作成されます(ファイル名には Rails のバージョンが含まれます)。このファイル内のコメントを解除して、新しいデフォルト設定を有効にする必要があります。この作業は、数回のデプロイに分けて段階的に実行できます。アプリケーションを新しいデフォルト設定で動かせる準備が整ったら、このファイルを削除して config.load_defaults の値を反転できます。 https://railsguides.jp/upgrading_ruby_on_rails.html#フレームワークのデフォルトを設定する 参考 railsguides.jp qiita.com いかがでしたか? タイミーは上記の Rails アップグレー ドガ イドを用いて Rails アップグレードを行なっています。とは言ったものの、このアップグレー ドガ イドは Rails 7.1 アップグレードでやったことを体系的にまとめたもので本当に運用され始めるのは Rails 7.2 アップグレードのタイミングになります。 Rails アップグレードは属人的なタスクになりがちです。特定の人物がアップグレードの番人になるのではなく、誰でもアップグレードにチャレンジできるようにしたかったのがアップグレー ドガ イドを作成した背景になります。 ネットには質の高い Rails アップグレー ドガ イドがたくさん存在します。ですが、どのステップをどんな期待値で実施するか・動作確認はどこまでやるかは各社の状況に依ると思います。社内の暗黙値を減らすためにも社内版 Rails アップグレー ドガ イドを作ってみてはいかがでしょうか。
こんにちは!株式会社タイミーでプロダクトマネージャーをしているAndrewです。 私はオフショ アメンバー が関与するSquadに所属しています。このSquadはエンジニア組織の中でもユニークな環境であり、ここで直面した問題とそれを乗り越えるための取り組みをこの記事で紹介したいと考えています。 オフショ アメンバー とのコラボレーションの課題 約半年前、オフショ アメンバー のいるSquadと関わり始め、このSquadの各メンバーを知るきっかけとなりました。 最初は、日本メンバーとオフショ アメンバー のコミュニケーションがスムーズでないと感じました。ミーティングでは通訳担当の方以外、オフショ アメンバー 全員がほとんど発言しませんでした。 また、ミーティングで話されている内容が彼らが理解できる言語で記録されていないケースが多く、情報の透明性に欠けていました。開発した機能の目的が何かを理解しない場面を見かけたこともありました。 しかし、これは単なる課題ではなく、Squad全体のポテンシャルを引き出すためのチャンスでもあると考えました。 エンジニアは機能を作るだけでなく、プロダクトに関心を持ち、価値を届けることに注力すれば、より多くのアイディアやソリューションが生まれ、良いプロダクトが作れるのではないかと。そのためには、オフショ アメンバー が積極的にディスカッションに参加できるようにする必要がありました。 最初は言語の壁があると感じたため、心配もありましたが、様々な施策を試してみました。その一環として、ドキュメントの整理とオンライン言語交流会を実施してみました。 情報透明性を向上するためのドキュメント 「ドキュメントのメンテナンスが面倒くさい!」、「コードを読む方が早い!」と思う方は少なくないでしょう。 コードにコメントがないと、そのコードが何をしているか理解することが難しくなります。それと同様に、ドキュメントがないと、システムや機能の全体像を把握するのに時間がかかり、理想的な状態と言えません。 コードで説明できない背景や設計の意図、特定の決定の背後にある論理をコメントで説明することで、コードを読む人が理解しやすくなります。しかし、コードのコメントでわかりやすく説明できる内容はテキストベースの情報に限られているということもあり、コードは特定のメンバーしかアクセスできないため、ここでドキュメントが強力な情報共有手段になります。 ドキュメントに対する工夫 ドキュメントを書くときにわかりやすくするためにいろんなテクニックがあります。 テキストに色をつけたり、フォントサイズを変えたり、ページの余白を活かすことで視覚的なメリハリをつけることが重要です。 これにより、複雑な情報も読みやすくなり、重要な情報を強調することができ、逆に強調したくない情報を目立たなくすることもできます。デザインが好きな私にとっては、ドキュメントは良いデザインを表現することのできる優れたツールです。 わかりやすいドキュメントを書くことは簡単ではありません。いろんなドキュメントの種類の中で、エンジニア向けのものもあれば、 ステークホルダー (非エンジニア)向けのものもあるので、伝わるように読み手のバックグラウンドや知識に合わせて書くことが必要です。 難しい単語ではなく、あえてシンプルな単語を選び、物事を説明することで言語の壁をなくせるので、自分の言葉の知識を見せびらかす必要なんてありません。 このような意識をもって書けば、ドキュメントを書くことは単調な作業ではなく、実は楽しい作業なんです。 バランスがすべて 口頭でコミュニケーションが取りづらい状況では、ドキュメントは尚更重要です。 ドキュメントがあることで、メンバーはいつでも情報にアクセスでき、フィードバックや提案もしやすくなります。ただし、あまりにも詳細な内容、たとえばコード実装のレベルの情報まで書いてしまうと、細かなコードの変更が生じるたびにドキュメントを更新しないといけなくなってしまいます。 同様に、テキストだけの長い文章を書いてしまうと、ドキュメントの恩恵が受けられなくなり、わかりやすさが損なわれ、逆に効果が薄れてしまいます。適度な詳細と抽象度のバランスを取ることが大切であり、ドキュメントが管理の手助けとなるよう心がけが必要です。 活用されるドキュメント 実際にこの取り組みを導入して、Squadの振り返りミーティングで「 ドキュメンテーション をよく参照するようになって、仕事において役立った」「ドキュメントが整理されていてわかりやすい」というメンバーからの声がありました。 今後、ドキュメントを書くのは私ではなく、オフショ アメンバー 全員も同じようなケイパビリティを持たせたいので、以上に書いたポイントを彼らに教えました。 今ではオフショ アメンバー 全員がドキュメントを書くようになり、 ステークホルダー から仕様確認の問い合わせが来ても、すぐ回答できるようになりました。これにより、プロジェクト全体の透明性が向上し、知識の共有がスムーズになりました。 長期的な視点で見れば、ドキュメントはSquad全体の知識の蓄積として機能し、メンバーが増えても情報の共有の負担は軽減されます。 オンライン言語交流会 ドキュメント整理が進む中、私たちはSquadメンバーがより積極的に参加し、アイディアを共有できる環境を整えるためにもう一つの取り組みを始めました。それが、オンライン言語交流会です。 知っている人とコミュニケーションを取ることは楽ですが、知らない人となると相手の意図がどのようなものかもわからないし、ミスコミュニケーションの原因にもなります。できるだけオフショ アメンバー とのコミュニケーションを増やすことで、彼らもより気軽に話しかけてくれるだろうと期待しています。しかし、日本語もできず、英語にも自信がないメンバーとどのようにすれば交流できるのか悩んでいました。そこで、オンラインで言語交流会を試してみました。 オンラインで実施しやすいアイスブレイク いきなり何かを英語で話せと言われても難しいですよね。 そこでアイスブレイクゲームを導入し、わざわざ自分でトピックを考える必要がなく、よりカジュアルに話せる環境にしました。最初は簡単なものから始め、英語で自分のカバンに入っているものを紹介したり、謎解きをしたりしました。 カバンに入っているものを紹介する中で、お弁当の中身だったり、意外なエアコン用のリモコンの話も出てきて、会話が弾みました。謎解きをするときもトリッキーな謎が多く、あるメンバーがたくさん正解を回答できて、他のメンバーから カンニング しているだろうと冗談で言われたりしていた覚えがあります (笑)。 これにより、お互いの趣味や考え方を知ることができ、メンバー同士のコミュニケーションが深まりました。 伝わることの喜び オフショ アメンバー と会話を重ね、最初は英語に対して悲観的で、喋ろうとしないメンバーも自然と喋るようになりました。この記事を書く際に彼らにその理由を聞いてみました。 「英語の発音は下手ですが、理解してくれる人がいるので勇気が出る」「私の英語で喋っても笑われていないし、Andrewからの促進で一歩踏み出そうと思うようになって、ディスカッションに関与する重要性を理解できるようになった」という素敵なコメントをいただきました。 これらの言葉を通じて、協力し合いながら成長するプロセスに感謝しています。 このオンライン言語交流会の ファシリテーション は最初は私が担当していましたが、現在はオフショ アメンバー が積極的に ファシリテーション することもあります。今では毎回アイスブレイクゲームだけでなく、単純に英語で雑談することもできる環境になりました。 また、この会の名前の通り、英語に限らず、最近私が彼らから言語を学ぶ機会も得ました。 Squadの成長と今後 まだ完璧な状態には達していませんが、Squad全体がどんどん成長している実感があります。オフショ アメンバー が積極的にコミュニケーションに参加し、自ら意見を言うようになったことは、大きな進歩と言えます。 異なる文化やバックグラウンドの人と仕事することは、チームが結束するまでには時間がかかりますが、結束ができた際には異なる視点から物事を判断でき、それによるメリットも大きいです。 私の過去の経験では、さまざまなバックグラウンドを持つ人々が集まれば、クリエイティブなアイディアが生まれやすくなります。そのため、このような多様性を大切にしていきたいです。 最後に、今後もSquad全体で協力し、より良いプロダクトを生み出すために努力していきたいと思います。
こちらは Timee Advent Calendar 2023 シリーズ1の19日目の記事です。 はじめに こんにちは、タイミーで Android エンジニアをしているsyam( @arus4869 )です。 この記事では、タイミーで実際に利用しているBitriseとFirebase App Distributionを用いた Android アプリの配布方法を実例を交えながら紹介していこうと思います。 この記事を通じて、同じようなツールを利用している他の開発者の皆さんにとって、参考になる情報を提供できればと思います。 BitriseとFirebase App Distributionについて Bitriseは、モバイルアプリのCI/CDプロセスを自動化するプラットフォームです。ビルドからデプロイまでを簡単に管理でき、開発サイクルを効率化します。 Firebase App Distributionは、アプリのベータ版やテスト版をテスターに迅速に配布するためのツールです。新しいビルドをテスターに届け、フィードバック収集が可能です。 これらのツールを組み合わせることで、 アプリ開発 の流れをスムーズにしてくれます。 事前準備 BitriseとFirebase App Distributionを使用する前に、いくつかの事前準備が必要です。 まず、BitriseとFirebase、そして Google Cloud Platform( GCP )のアカウントを準備します。 それぞれのツールを利用するには適切なアクセス権と設定が必要です。事前に準備しましょう。 詳細なアカウント作成方法については、それぞれの公式を参照してください。 参照URL Bitrise Firebase Google Cloud Platform(GCP) 次は具体的な手順へ進めていきます。 手順1: Firebase App Distributionのグループとテスターの設定 Firebase App Distributionを使用してアプリを効率的に配布するためには、適切なグループとテスターの設定が必要です。 以下のステップに従って設定を行いましょう。 Firebaseプロジェクトにアクセス Firebaseコンソールにログインし、対象のプロジェクトを選択します。 テスターグループの作成 「App Distribution」セクションに移動し、「テスターとグループ」タブを選択します。 「新しいグループを作成」をクリックし、グループ名(例:product_team)を入力します。 テスターの追加 新しいグループを選択し、「テスターを追加」をクリックします。 テスターのメールアドレスを入力し、グループに追加します。 テスターは開発用と本番用のアプリに分けてグループ化すると管理がしやすくなります。 この手順により、特定のテスターグループに対して、アプリのテストビルドを簡単に配布できるようになります。 グループとテスターの設定が完了したら、次にFirebaseの認証用サービスアカウントの作成をしていきます。 手順2: Firebaseの認証用サービスアカウントの作成 Firebase App Distributionでアプリを配布するためには、Firebaseの認証用のサービスアカウントを設定する必要があります。この手順では、その設定方法を説明します。 Google Cloud Platform( GCP )でサービスアカウントを作成 GCP の ダッシュ ボードにアクセスし、「サービスアカウント」ページを開きます。 「サービスアカウントを作成」を選択し、アカウントの詳細を入力します。 必要なロールを割り当て サービスアカウントに以下のロールを割り当てます: Firebase 品質管理者 Firebase App Distribution Admin SDK サービス エージェント これらのロールにより、アカウントはFirebase App Distributionでのアプリ配布に必要な権限を持つことになります。 秘密鍵 の生成と保存 サービスアカウントに対して新しい 秘密鍵 を生成します。 生成された 秘密鍵 を安全な場所に保存し、後のBitriseの設定で使用します。 次は、このサービスアカウントを使用して、Bitriseでのプロジェクト設定を行います。 手順3: Bitriseの設定 次は、BitriseからFirebase App Distributionを通じてアプリを配布するためには、Bitrise上での適切な設定が必要です。以下のステップに従って、Bitriseでの設定を行いましょう。 Bitriseプロジェクトのセットアップ : Bitriseにログインし、新しいプロジェクトを作成または既存のプロジェクトを選択します。 プロジェクトのビルド設定を確認し、必要に応じて調整します。 Firebase App Distributionステップの追加 : プロジェクトのワークフローを編集し、「[BETA] Firebase App Distribution」ステップを追加します。 このステップにより、ビルドが成功すると自動的にFirebase App Distributionを通じてアプリが配布されます。 認証情報の設定 : GCP で生成したサービスアカウントの 秘密鍵 をBitriseの「Code Signing & Files」タブにある「GENERIC FILE STORAGE 」 セクションにアップロードします。 「[BETA] Firebase App Distribution」ステップの設定で、Service Credentials Fileの項目に「GENERIC FILE STORAGE」セクションにアップロードしたサービスアカウントの 秘密鍵 のパスを設定します。 これらのステップにより、BitriseはFirebase App Distributionと連携し、アプリのビルドと配布を自動化できるようになります。設定が完了すれば、BitriseからFirebase App Distributionを通じてアプリをテスターに配布する準備が整います。 参考程度に「[BETA] Firebase App Distribution」に設定している項目を記載します。 項目 説明 例 Service Credentials File Bitriseのアップロードした 秘密鍵 のパス $BITRISEIO_development_service_account_key_URL App Path APK及びAABファイルが格納されているパス $BITRISE_APK_PATH Firebase App ID Firebaseコンソールのプロジェクトの設定から見れるアプリ ID 1:1234567890: android :0a1b2c3d4e5f67890 Release Notes テスターが見るリリースノート メインブランチにマージされたビルドです。 Test Groups 手順1で設定したテスターグループ product_team まとめ この記事では、BitriseとFirebase App Distributionを活用して Android アプリを配布するための手順を紹介しました。以下は、ポイントのまとめです。 事前準備が鍵 :BitriseとFirebase、 GCP のアカウント設定から始め、必要なツールと情報を確認することが重要です。 Firebase App Distributionの設定 :適切なテスターグループとテスターの設定を行い、アプリのテスト版を簡単に配布できる環境を作ります。 Bitriseの自動化設定 :ビルドプロセスをBitriseで自動化し、Firebase App Distributionを通じてアプリを配布する設定を行います。 このプロセスを通じて、テストアプリの配布が可能となります。あとはテストアプリをどのように使ってもらえるか、開発者以外のメンバーにもフィードバックをもらえるようにドキュメント化することをお勧めします。本記事が、みなさまの開発に役立つことを願っています。
こんにちは、データ統括部BIグループ所属のtakahideです。 本記事では、BIグループで取り組んでいる全社的なデータ活用に関してご紹介します。 この記事を通して、少しでも「社内のデータ活用を進めたい」と思っている方のお役に立てたら幸いです。 ※ Timee Advent Calendar2023 の12月18日分の記事です。 課題感 データ活用に役立つスキル 講習会の開催 少人数の相談会 データ活用スキルの指標化 おわりに We’re Hiring! 課題感 まずは、データ活用を進めるに至った経緯を簡単に説明させてください。 タイミーは、データを用いた意思決定を大切にしているのですが、 近年の組織拡大にともない、データ活用を全社的に推進するニーズが高まっていました。 一方で、データを利用するメンバーのスキルとニーズとの間に乖離が存在していることが分かってきました。 そこで「データ活用を全社的に推進するPJT」をBIグループ中心に立ち上げることになりました。 データ活用に役立つスキル データ活用といっても人によって解釈が異なるため、 データアナリストが日々の業務で用いているスキルの言語化から始めました。 機械学習やプログラミングといった一部の職種で使われるスキルは除外して、 どの職種の方でも役に立つ汎用的なスキルを選択しています。 「課題の発見→課題の解像度の向上→検証に必要なデータの解釈→結果のまとめ」といった流れを意識しています。 講習会の開催 スキルの整理ができたので、次にスキルの意義や使い方を伝える講習会を行うことにしました。 データの価値を実感してもらうことを優先して「データ抽出」の講習会を実施して、 顧客の行動を数値で見る体験をしてもらいました。 具体的には、簡易にデータを扱えるツールとしてLookerの講習会を開催しました。 講習会をキッカケにLookerの利用者が増え、データを見る習慣が作られたと考えています。 最初はお試しで始めた講習会も、現在は毎月実施していて、新入社員の方がデータに触れる機会を作っています。 (詳細は こちらのブログ をご覧ください) 次に行ったのが「論理的思考」「データ構造の理解」「データの解釈と可視化」の講習会です。 これらはデータ抽出の前後に用いることが多く、「データ抽出」の後に実施することで理解が深まると考えました。 下記のように、First Step→Second Stepと段階を踏んで進めてきました。 少人数の相談会 ここで、講習会を通じて見えてきた課題とその対応をお伝えできたらと思います。 課題として分かったことは大きく二つで、 「講習会の難易度」と「質疑応答のしづらさ」になります。 「講習会の難易度」ですが、 講習会では必要最低限の内容をコンテンツに盛り込んでいるものの、 参加者の習熟度の違いを吸収しきれていませんでした。 また、「質疑応答のしづらさ」ですが、 講習会の参加人数が50~100人になるため、質問しづらい雰囲気がありました。 特に、どのレベルの質問をして良いかが分かりづらいという声が挙がりました。 これらを踏まえて、少人数の相談会を進めようとしています。 テーマを絞った数人〜十数人の会にすることで、活発な意見が出ることを期待しています。 全社向けの講習会を定期開催しつつ、補完的に相談会を実施することで、 講習会の内容の充実にも繋がると考えています。 データ活用スキルの指標化 最後に、データ活用の測定に関してお話しできたらと思います。 全社のデータ活用を推進する上で、データ活用スキルの習熟度の把握が重要になります。 タイミー全体でデータ活用がどの程度進んでいるかが分かることで、 データ活用のPDCAが回しやすくなり、スキル習得のモチベーションにも繋がると考えます。 おわりに この記事では、BIグループが実施している、データ活用の取り組みを紹介しました。 改めて「社内のデータ活用を進めたい」と思っている方のお役に少しでも貢献できていたら嬉しいです。 今回は全体の紹介で、個別の詳細はお伝えできていなかったので、 そちらも機会がありましたらお話しできたらと思います。 We’re Hiring! タイミーのデータ統括部では、ともに働くメンバーを募集しています!! product-recruit.timee.co.jp
好きな水風呂の温度は16℃でお馴染み edy69x です。 Timee Advent Calendar 2023 の16日目を担当します。 本記事では今年完遂したUIリニューアル(SPA化)を通してタイミーで実施した工夫や学びを普段バックエンドの開発を担当する私の視点からお伝えします。 先日のイベントでの登壇内容を補完した内容となっています。気になる方は下記資料もご覧ください。 speakerdeck.com イベントの方はプロジェクト終盤での断捨離やリファクタリングなどがテーマになっていたので本記事ではプロジェクト進行過程全般での知見をシェアしていきます。 プロジェクト概要 まずプロジェクトの概要です。大雑把に言うとフロントエンドの技術基盤を移行しながらUIリニューアルを実施しました。 それだけだと「何のことだ?」となるので前提からご説明します。 タイミーでは単発のアルバイト求人の掲載を行う事業者用のWeb管理画面を提供しています。 リニューアル前はRailsエンジニアがテンプレートエンジンのSlimを活用し、フロントエンド開発も担っていました。Railsで作られたサーバは動的に生成したHTMLをレンダリングする責務も持っていました。いわゆる Server Side Rendering(SSR) です。タイミー創業当初から変わらない技術スタックで構成されていて価値も生み出し続けていました。 しかし、サービス拡大にともない、古くから存在する Model や Controller への継ぎ足しの実装などが生まれ、Railsアプリケーションのバックエンドとフロントエンドの密結合なロジックが増えたり Fat Controller に頭を悩ませられるシーンが発生し始めました。 一方のフロントエンドでは保守性や情報設計(Information Architecture)を始めとして品質向上を狙ったり、jQueryに代わるモダンWebフロント技術の導入、またフロントエンド専任のエンジニアの採用拡大も狙っていました。 上記の理由などからUIリニューアル及びフロントエンドの技術基盤を刷新するプロジェクトがスタートしました。 フロントエンドの技術は下記の構成で、Railsのリポジトリとは別で切り出しました。 言語: TypeScript ライブラリ: React フレームワーク: Next.js APIドキュメント: OpenAPI (Swagger) Webページ構成やレンダリング手法もこのタイミングから Server Side Rendering(SSR) から Single Page Application(SPA) に変更しました。 いざ始まったUIリニューアル UIリニューアルを進める上で不確実性を大いに孕んでいたので管理画面全体を一気にビッグバンリリース的に旧バージョンから新バージョンに切り替える方針は見送りました。 方針としてはハレーションを抑えるためにアクセス数の少ない画面から徐々にリプレイスしていき、顧客が最も利用する事業のコア機能を終盤にリプレイスする計画を立てました。 同時にDatadogやGoogleAnalyticsなどの監視・分析ツールを用いて、アクセス数の解析、利用デバイス比率の特定をしたり、売上規模の上位を占める事業者を選定し、移行に際して障壁となるポイントが無いかを探っていきました。 従来デザイン使い続けたい問題 進行する中で発見されたのが「従来のデザインを使い続けたい」というユーザーニーズです。 背景には、既存UI/UXに対してのメンタルモデルが形成されているので変化を忌避してしまったり、画面構成やボタン単位で指定オペレーションを厳密に組んでいるケースなどがありました。 強行突破する方法もあると思いますが、打ち手として新デザインのリリース後も従来の旧UIに切り替えられる仕組みを導入しました。デバイス変更やセッション切れ等で、従来デザインを選択したユーザーが新デザインに切り戻されることを回避したり、データ分析観点で活用するために従来デザインを選択した状態はDBに永続化しました。 プロジェクト終了時には削除する前提だったので明確さやアクセスのし易さを優先しました。フロントエンドは使用状況をAPI経由で取得する方針を採用しています。 [従来のデザインに切り替える] ボタンを配置 この仕組みのお陰でリリース後に利用者に多少影響があっても完全にロールバックすることなく、利用者ごとの判断に委ねることが出来ました。新デザインを許容できる利用者には新デザインを提供し、どうしても従来のバージョンを利用したい方には一定期間の従来バージョン利用を許容する運用をしました。 事前告知による期待値調整も勿論大事だと思うのですが、石橋を叩きすぎずにリリース後の ”動くソフトウェア” を通しての実際のユーザーのフィードバックから次の意思決定に繋げられるアプローチを経験できたのは大きな財産になりました。 画面移行の約80~90%程度が終わる頃には新デザインがマジョリティになったので、上記機能はほぼ役目を終え勇退しました。 影響範囲を限定する話での余談ですが、カナリアリリースの仕組みがあると影響を抑えられた障害などもあったので今思い返すと導入しておけると良かったです(プロジェクト中には追加出来なかったので今後導入していきたい)。 ユースケースロジックを切り出すFormObjectを活用 プロジェクトも佳境に差し掛かった中で、とあるエンドポイントに対応するAPIを実装する工程が最も難を極めました。タイミーのコアドメインに関わる機能を司っている Controller のリプレイスです。元々が Fat Controller だったケースでして既存の仕様理解や根本的なリファクタリングが求められたのを覚えています。 リクエストを受けてからHTMLを返却する一連の処理の中に、データベースへの書き込みや外部APIへの通信、ビジネスロジックに関係する処理など様々な責務を Controller が抱えていました。テスタビリティも低く、RSpecで書いていた controller spec では仕様は網羅されていませんでした。 その際に Controller の責務を一部切り出す方法として FormObject を採用しました。ユースケースに対応したロジックを FormObject クラスに閉じ込め、Controllerはクラスのパブリックメソッドの呼び出しとリクエストの受付、及び適切なレスポンスの返却に特化する様な作りにしました。 FormObject には単に移行するだけではなく「テストピラミッド」も意識し、テストケースの割合が結合テスト < ユニットテスト になるように必要に応じて責務の見直しも行いました。 テストピラミッド 結果的に Fat Controller は消え去り、元々はAPIリクエストの受付からレスポンスまでの過程を通して結合テストでカバーしていたテストケースをユニットテストで再現できるようになりました。Controller は RSpec の request spec にて受け付けるリクエストとレスポンスを明示し、副作用のうち代表的なケースをテストすることで不要に FormObject 側のユニットテストと重複することも回避しました。 Controller の上部に君臨し続けていたTODOコメントを削除できたときは非常に感慨深かったことを今でも覚えています。 古来からタイミーを見守ってきた長老の様なTODOコメント プロジェクトの中断 これは少しオフトピック的な話ですがプロジェクト進行のメタ的な話として触れておきます。 一般的にプロジェクトのみならず仕事を進める中で優先度が高い別Issueが割り込まれることはありますよね。今回のUIリニューアルプロジェクトでも起きました。 プロジェクトの性質的には「技術改善」をテーマとし基本的に従来機能を踏襲しながらUIリニューアルを進行する前提でした。そのため、割り込み的な機能開発に対してスイッチングコストが発生したり、リニューアルとの優先順位付けが必要になったりと苦労した覚えがあります。移行期間全体が約3年あったうち合計1年ほどはチーム構成やミッションが根本から変化し、別テーマの開発を担当する時期もありました。 結果として生存期間が短い前提で作られた機構が想定より長く存在し続けることになりました。例えば先に述べたデザイン切り替えの仕組みや、Rails, Next.js それぞれのリポジトリが互いに依存する様な暫定的なロジックなどです。 当時の自分はイレギュラーに対してある種「当たり前」くらいで考えていたのですが、水面下ではコードベース上に認知負荷を高める要因が生まれていました。新規参画メンバーから質問が来ることもありましたが、当時は影響を理解したり、言語化することは出来ていませんでした。 今思い返すと内部品質低下に繋がることから、プロジェクト完遂までのリードタイムを短縮したり、テーマが変化する前に最低限の内部品質改善をするように働きかける余地はあったなと感じます。 プロジェクトが順調に進んだり完了することだけが学びではなく、むしろ想定外の中に自分の枠を超えた学びのきっかけがあると気付かされた瞬間でした。 プロジェクト完遂 過程では様々な事があり、ここでは語り切れないのですが3年の歳月を経てプロジェクトは完遂しました。RailsリポジトリからはHTMLレンダリングにまつわるコードやCSSライブラリなど5万行を超えるコードが削除されました。特に1つのPull Requestで1万行を超えるコード削除をした時は非常に爽快でした。 Webpackerやyarnなどにも別れを告げ、外部顧客向けの機能についてはRailsリポジトリはWebAPIの開発に特化する様な存在になっています。GraphQL化を進める様なチャレンジも生まれました。 WebFrontも1名でプロジェクトがスタートしましたが今では技術コミュニティが生まれたり、技術顧問の方が付いていたりと2020年当時と比べてだいぶ拡大しています。いい話ですね。 おわりに プロジェクトが終われど、フロントエンドにとってはスタートラインに立ったとも言えますし、バックエンド側も保守性が多少増したとは言え、会社の成長を支える面でいうとまだまだ改善余地があります。 会社に興味がある方がいたら、タイミーワーカーで運営が成り立っている THE 赤提灯 という居酒屋が新橋オフィス近くにあるので是非飲みに行きましょう。 一応採用ページも貼っておきます。 product-recruit.timee.co.jp 忘れていましたが、声を大にして改めて言っておきたい。 「タイミーはSPA化やり遂げたぞ!!!!」 完
こちらは Timee Advent Calendar 2023 シリーズ1の15日目の記事になります。 こんにちは、タイミーで Android エンジニアとして働いている @orerus こと村田です。 私は現在タイミーのAndroidChapter(弊社は特定領域のメンバーの集まりのことをChapterと呼称しています)の一員で、喜ばしいことに来年早々にメンバーが大きく増加する予定です・・・! 以前はAndroidChapterのメンバーが全員同じチームで開発を行っていましたが、タイミーのエンジニア組織拡大に伴い全員が異なる開発チーム(弊社ではSquadと呼称しています)に所属する形へと変化しました。その為、各Squadには Android エンジニアが少人数しか所属しておらず、 Android アプリに関するPRレビューについてはSquadを跨いで行うことになります。必然、故も知らないPRレビューが飛んでくる為、PRレビューの負荷が上がり 工数 的にも 心理的 にも辛いものとなってしまいました。 そこで今回は、そういった組織のスケールに伴い発生する課題解決の為の施策の一環として、弊社AndroidChatperで導入した独自のLADR(Lightweight Architecture Decision Records)について紹介したいと思います。 また、導入して得た学びや見えてきた改善点についても共有できればと思います。 施策の背景、課題 独自LADRについて LADRのサンプル LADR導入の経緯 導入後の成果と学び、および見えてきた改善点 AndroidChapterメンバーからのFB 自身の振り返り 学びと改善点のまとめ 当初抱えていた課題は解決できたのか 施策の背景、課題 先述の通り、タイミーでは現在 Android メンバーが全員異なるSquadに所属し、それぞれが異なるプロダクトゴールに向けた機能開発を行っています。 AndroidChapterで毎日10分程度のデイリー MTG は行っていますが、そこでは現在取り組んでいるもの・これから触るコード領域、困りごと等の共有に留まります。(各Squadのデイリー スクラム もある為、あえて軽い内容にしてあります) そのような状態で開発サイクルを回す中で、いくつかの大きな課題が見えてきました。 PRレビュー レビューに入る前に、PRが行っている開発内容を把握する為の多大な コンテキストスイッチ コストがかかる コンテキストを十分に理解できていない為、仕様や設計の妥当性の判断が困難で表面的なレビューになりがち PRという完成形で初めてレビュー依頼が飛んでくる為、仕様や設計で致命的な問題があった場合に後戻りが難しい(修正コストが高い) PRレビューコストが高い為、PRレビューを行う際にまとまった時間を確保する必要がありレビュー完了までのリードタイムが長くなる 改修/影響調査 昔のコードや自身が触っていないコードについて、開発当初の意思決定根拠や設計意図が分からず、影響調査に時間がかかったり変更妥当性の判断が難しい そこで、これらの課題を解決するために実験的に導入を始めたのが独自LADRでした。 独自LADRについて ここでは我がAndroidChapterで定義している独自LADRについて紹介します。なお、ここでいうLADRは弊社AndroidChapter用に独自改変したLADRですが、AndroidChapter内では単に「LADR」と呼称している為、この記事でも以後は単にLADRと記述します。 そんなAndroidChapterで導入している独自LADRですが、株式会社 ラク スの鈴木さんが公開されている LADR-template をベースにさせていただいています。 また、 鈴木さんの記事 にある通り、LADRの本来の用途は アーキテクチャ 選定において「導入しなかった」記録を残す為であると認識していますが、AndroidChapterではLADRの目的や対象をそこから拡大解釈して利用しています。 目的や対象を具体的にどのように拡大解釈しLADRを運用しているかについては、実際に私が作成した「LADRを導入する為のLADR」を以下に添付しますので、こちらをご覧いただければ雰囲気が掴めるかと思います。(「Context - 文脈」「Specification - 仕様、やること、やらないこと」の項目のみご覧いただければ十分です) ご覧の通り、LADRのドキュメント自体は軽量なものになっている事が分かるかと思います。ここがLightweight形式を採用した最大の理由でして、ハードルを下げることでまずはこのドキュメントが書かれることを一番の狙いとしています。 LADRのサンプル 先ほどお見せしたLADRは機能開発を伴うものではなかった為にいくつか項目を省略してますが、機能開発時のLADRでは必要に応じて詳細な仕様を記述したり、実装時の設計についても触れています。 以下、実際に作成されたLADRのサンプルです。(雰囲気が伝わるようにシンプルなものと重めなものを抜粋しています) サンプルA. 機能追加のためのLADR サンプルB. 不具合修正のためのLADR このようなLADRを作成した後、AndroidChapterにLADRのレビュー依頼をPRとして投げ、そこでLADRに書かれたコンテキストや仕様、設計について 開発着手前に レビューを受けるようにしています。 LADR導入の経緯 先述のLADRについての記事を拝見したときに「これだ!」と思い、すぐさま「LADR導入の為のLADR」、および「LADRのテンプレート」を作成し、 Android メンバーにPRという形で投げつけました。LADRについて解説するより、まず実物を見せ、そこから話をするのが早いと感じた為です。 PR上でLADRの狙いや、他ドキュメントとの棲み分けについてなどの多少のラリーはありましたが、好意的に受け入れられすんなりと実験導入が始まりました。 運用を初めて2ヶ月程度ですが、現在以下の18個のLADRが作成されています。 導入後の成果と学び、および見えてきた改善点 AndroidChapterメンバーからのFB まずは2ヶ月運用してきて、AndroidChapterのメンバーはどう感じているのかを探るためにアンケートを実施してみました。 アンケート結果について、AndroidChapterメンバーの中でLADR作成経験済み、作成機会がまだ無い状態の2人の回答を紹介します。 「ありのままを記事に書きたいので率直に書いてね」とお願いをしておいたので、きっちりと本音が書かれているかと思います・・・! ※なお、アンケートの設問はChatGPT先生にご協力願いました その結果がこちらです。 まずは分かりやすく数値で評価してもらいました。 一番右の私の回答分はバイアスがかかりまくっているのでスルーして、他メンバーの評価は以下のような感じです。 満足度はどちらも7と「やや良い」点数 プロセスの効率化や課題解決度合いの感じ方はLADR作成機会があったメンバーは全体的に高め、機会が無かったメンバーは低め Bの方が「LADR導入によって解決された課題の効果度」の項目の3点について、「まだ自身で作成したことがないために自分事感が薄い」とのFBをもらっています 次に、フリーテキストで回答してもらったものを 原文ママ で掲載します。 ※2人分の回答をマージしています まずは 導入による成果 についての質問についてです。 こちらにより以下のことが言えそうです A、Bの両者ともに「コンテキスト共有」については効果を明確に感じている LADRを作成する機会があったメンバーは仕様/思考の整理に効果を感じている LADRを作成する機会がなかったメンバーもPRレビューの効率化には効果を感じている ただし、自身でLADR作成を行っていないと課題解決の実感が薄い 次に 改善点 についての質問です。 こちらにより以下のことが言えそうです LADRの制度自体の課題点はまだ発生していない 一方、ドキュメントの参照のしやすさ、ドキュメント作成のオンボーディングといったLADRの活用方法についての改善点が挙がっている この点は当初から想像していた懸念点であった為、今後の明確な改善点だといえる 組織がスケールしてもコンテキスト共有に関する課題解決の効果が見込めそう 自身の振り返り また、私自身が感じているLADRのメリットデメリットも軽く挙げておきます。 メリット 何にせよ意思決定のログが残るようになった メンテを保証できない仕様書にするより、意思決定のログと割り切って扱っている PR作成時のコンテキスト共有が楽になったように感じた 「実装→ドキュメントを書く」が「ドキュメントを書く→実装」と順序が変わったのが大きいのかもしれない 設計段階の指摘や懸念点の伝達が事前にできるようになった 実装者以外のメンバーのコンテキストの理解度合いが深くなったように感じた デメリット LADRの作成の 工数 がかかる 以前もPR本文に一定のコンテキストを書いていたので、劇的に 工数 が増加した訳では無い LADRのPR、機能開発のPRと、レビューが必要となるPRの数が増える 学びと改善点のまとめ 以上から、学びと改善点について乱暴にまとめると以下のようなことが言えるかと思います。 課題解決に一定の効果は確実に出ており、デメリットを上回るメリットがあるといえる LADRドキュメントの参照性に課題がある LADRドキュメントを作成するまでのハードルがまだ感じられる オンボーディング時に1度作成してもらう等のケアが検討余地としてありそう 当初抱えていた課題は解決できたのか 最後に、当初挙げていた課題がどの程度解決できたかの所感をまとめます。 課題1 : レビューに入る前に、PRが行っている開発内容を把握するための コンテキストスイッチ コストがかかる 解決状況 : ✅ 完全に解決 課題2 : コンテキストを十分に理解できず、仕様や設計の妥当性判断が困難 解決状況 : ✅ 完全に解決 課題3 : PRという完成形で初めてレビュー依頼が飛んでくる為、仕様や設計で致命的な問題があった場合の修正コストが高い 解決状況 : 🤔 様子見 現状では問題なし。設計難易度の高い開発での対応を今後注視 課題4 : PRレビューコストが高く、レビュー完了までのリードタイムが長い 解決状況 : 🟢 一定の解決 PRレビューコスト減少、ラリーの回数も減少 課題5 : 昔のコードや自身が触っていないコードの開発意図が分かりづらい 解決状況 : 🟢 様子見、ただし解決の兆しあり まだ運用期間が短く見返す機会が少ないが、LADRのルールを見直す際に当初作成したLADRドキュメントが役立った 結論として、全体的には解決に向かっていると感じています。ただし、組織のスケールアップに対する対応として導入した施策であるため、今後も組織がスケールした際の変化に注視しつつ、より良い形へと進化をさせ続けていく所存です。
※ Timeeのカレンダー | Advent Calendar 2023 - Qiita の12月13日分の記事です。 はじめに こんにちは okodoooooonです dbtユーザーの皆さん。dbtモデルのbuild、どうやって分割して実行してますか? 何かしらの方針に従って分割をすることなく、毎回全件ビルドをするような運用方針だと使い勝手が悪かったりするんじゃないかなあと思います。 現在進行中のdbtのもろもろの環境をいい感じにするプロジェクトの中で、Jobの分割実行について考える機会があったので、現状考えている設計と思考を公開します!(弊社は一般的なレイヤー設計に従っている方だと思うのでJob構成の参考にしやすいと思います) この辺をテーマに語られていることってあんまりないなあと思ったので、ファーストペンギンとして衆目に晒すことで、いい感じのフィードバックをもらえたらなーと思ってます。 弊社のデータ基盤全体のデザインについて把握してからの方が読みやすいと思うので、そちらをご覧になりたい方は こちらの記事 からご覧ください。 これまでの弊社のデータ更新周りについて これまでの弊社のdbt Job設計の概念図を作るとしたらこんな感じになります。 走っているクエリがフォルダ単位/モデルファイル単位などバラバラな粒度で実行されている リネージュを意識したJobの走らせ方になっておらず更新頻度の噛み合わせが悪い 明確なルールがないので意図しないタイミングで同じモデルがビルドされたりする 明確なルールがないのでビルドから漏れているモデルがひっそり存在している dbtコマンドで示すとこんな具合のカオス感 dbt build --select models/path_to_model_dir1/model1-1.sql dbt build --select resource_name dbt build --select models/path_to_model_dir2/model2-1.sql dbt build --select models/path_to_model_dir3 .... 改善のための試行錯誤 v1 レイヤーごとにtagを付与して以下のようなビルドコマンドが走らせられるようにしました。 dbt build --select tag:staging_layer dbt build --select tag:dwh_layer dbt build --select tag:dm_layer 更新頻度tagの概念を設計して、以下のようなビルドコマンドを走らせられる構成を検討しました。 dbt build --select tag:hourly_00 # 毎時00分にビルドするものに付与するタグ dbt build --select tag:daily_09 # 毎日9時にビルドするものに付与するタグ これらの設計をしてみて、レイヤー単位でJobを走らせることを可能にできたのと、更新頻度をdbt上で管理可能な形にはできました。 しかし、ユーザーのデータ更新ニーズに基づいたJob設計になっていないことから、ユーザーニーズベースでのJob管理方針の検討を進めました。 データ活用ユーザーのデータ更新ニーズの整理 弊社のレイヤー設計とデータ活用ユーザーのアクセス範囲は以下のような形になります。 アナリストはステージング層以降の層に対するアクセス権を保持していますが、現状アナリスト業務はモデリング済みテーブルではなく、3NFテーブルに対するクエリを作成する作業が支配的です(モデリング済みテーブルの拡充とその布教をもっと頑張りたい)。 データ組織外の社内ユーザーはデータ組織が作成したアウトプットを通して分析基盤のデータを活用できるような状態になっています。 ※弊社内ではデータ組織以外のユーザーにBigQueryのクエリ環境を開放しておらず、LookerやLookerStudioなどのアウトプットを経由して社内データにアクセスする状態にしています。 それぞれの層ごとの現在顕在化しているデータ更新ニーズを整理すると以下のようになります。 アナリストと野良アウトプットによる「ステージング層のなるはや更新ニーズ」 アナリストのアドホッククエリ 分析要件は予測ができず、要件次第では最新のデータが必要となるため、なるべく早く更新されることが期待されます。 マートから作成されずステージングテーブルから作られるアウトプット 更新頻度ニーズのすり合わせなく作られて提供されるものも多く、要件次第では最新のデータが必要となるため、なるべく早く更新されることが期待されます。 データ活用ユーザーによる「アウトプット更新ニーズ」 データ活用ユーザーに提供するデータマート経由のアウトプットは更新頻度を擦り合わせられているものだけになっている(今はまだ数が少ないだけだが)ため、hourly,daily,weekly,monthlyなどの頻度ごとの更新設計が可能となっています。 例えば弊社のよく使われるLooker環境はhourlyの頻度で更新が要求されています。 単純なジョブ設計をしてみる 単純な ジョブ実行案① ステージングなるはや更新プラン ソースシステムごとのデータ輸送完了後にそのソースシステムを参照しているモデルを全てビルドするプラン コマンド例 salesforceのデータ輸送完了後のコマンド: dbt build --select tag:salesforce_source+ dbt build --select models/staging/salesforce+ アプリケーションDBのデータ輸送完了後のコマンド: dbt build --select tag:app_source+ dbt build --select models/staging/app_db+ 実装方法 airflowなど何かしらのオーケストレーションツールで転送完了をトリガーに下流一括ビルドのコマンドを実行する必要がある。 この場合の更新ジョブを概念図に表すと以下のようなものになると思います(上流から下流へのビルド時のデータリネージュを黄色の三角形で表現しています)。 メリデメをまとめると以下のようになるかと思います メリット 下流が全てビルドされるのでビルド漏れが発生しない。 常にモデルの鮮度が最新になる = アナリストのstaging最新化ニーズは満たせている デメリット 更新がそこまで不要なモデルに対してまでビルドが実行される。 BigQueryのクエリ料金が高額になる 単純な ジョブ実行案② ユーザーニーズに合わせるプラン ユーザーのデータ更新ニーズに合わせて更新頻度をアウトプットごとに設定。更新ニーズの頻度ごとに最新化されるようなプラン コマンド例 1時間おきにビルドされて欲しいアウトプットを更新するコマンド: dbt build --select +tag:hourly 1日おきにビルドされて欲しいアウトプットを更新するコマンド: dbt build --select +tag:daily この場合の更新ジョブを概念図に表すと以下のようなものになります(下流から上流へのビルド時のデータリネージュを赤色の三角形で表現しています)。 メリデメをまとめると以下のようになります。 メリット:アウトプットの更新頻度が最適化される。 デメリット stagingのモデル作成の重複が発生する。 出力ニーズが存在しないstagingテーブルなどがビルド対象から漏れてしまう ではジョブ分割をどのように設計するか ステージングなるはや更新に合わせてリネージュの上流から実行すると下流で無駄なビルドが発生してしまう。 ユーザーニーズベースでリネージュの下流から実行すると上流で無駄なビルドが発生してしまう。 この二つの問題の折衷案を考える必要があると考えました。 現状のジョブ実行案 更新ジョブの概念図は以下のようなものになります(上流から下流へのビルド時のデータリネージュを黄色の三角形、下流から上流へのビルド時のデータリネージュを赤色の三角形で表現しています)。 ソースデータ ~ ステージング層のビルド ソースデータが連携されたらステージング層までを下流に向かってビルド コマンド: dbt build --select tags:source_a+ --exclude tags:dwh_layer tags:dm_layer DWH層~アウトプットの間のビルド ステークホルダーと定めた更新頻度に合わせて上流に向かってビルド コマンド: dbt build —select +tags:daily_00_00 —exclude tags:staging_layer tags:datalake_layer こうすることで、ステージング層までは常に可能な限り最新化されつつ、アウトプットは要件ごとに更新頻度が最適化された状態となります。 ただ、DWH層やデータマート層に多少のビルドの重複は発生してしまいますが、そこは許容しています。 本当はこうしたい案 アナリストがモデリング済みのDWH層を使うことが常態化するような世界観になってくると、上図のように「レイク~DWHまでは最新鮮度」「それ以降はユーザーニーズベースで更新」って流れがいいのかなと思っています。 また source_status:fresher+ などのstate管理をうまく使って、更新があったものだけをビルドするような方式を模索していきたいです。 おわりに dbtの環境リプレイスとともにこのJob設計も実戦投入しようと考えているので、想定していなかったデメリットが発覚したり、改善点が見つかったら改善していこうと思います! 弊社データ基盤でもストリーミングデータが取り扱えるようになったので、そのデータの使用が本格化すると ストリーミング✖️バッチ のJob構成などを考える必要があり、まだまだ俺たちの戦いはこれからだ。と思います ていうかみなさんどうやって分割して実行してるの!!!教えてほしすぎる We’re Hiring タイミーのデータ統括部はやることがまだまだいっぱいで仲間を募集しています!興味のある募集があればこちらから是非是非ご応募ください。 product-recruit.timee.co.jp
こんにちは、タイミーのデータ統括部、DRE(Data Reliability Engineer)グループ & DS(Data Science)グループ所属の筑紫です。 DSグループではML基盤の構築・運用保守を担当しています。 本記事では、ML基盤を再構築した話を紹介したいと思います。 ※ Timee Advent Calendar2023 のシリーズ 2の12月13日分の記事です。 経緯と課題 DSグループでは、様々なプロジェクトのML基盤を構築しています。 当初は、1つのCloud Composerの上に、全てのpipelineを載せて運用していました。 以下に当初の構成のイメージ図を示します。 ただ、このML基盤についてはいくつか課題がありました。 本番環境しかない 本番稼働しているpipelineが複数ある中、環境が本番環境しかありませんでした。 Cloud Composerも本番の インスタンス 1つしかなく、例えばCloud Composerのimageのupdateが必要な際もupdateして既存本番に影響がないか検証できる環境がない、などの問題が発生しており、保守に耐えられない状況でした。 サービスレベルの異なるpipelineが同じワークフロー上に乗っている 当時ML基盤の予測結果を社外に提供する取り組みも開始している中で、社内利用のML pipelineと社外利用のML pipelineが同じワークフローツール(Cloud Composer)上に乗っている状況でした。 ML基盤でもその結果を社内で使用するものと社外で使用するものでは、サービスレベルが変わってきます。 異なるサービスレベルを持つ複数のpipelineが一つのワークフローに乗っている状況では、あるpipelineの挙動が他のpipelineにも影響を及ぼし、サービスレベルに影響を与える可能性があるため、運用上好ましくありませんでした。 インフラ反映までのプロセスが長い GoogleCloud環境はTerraformで管理していますが、その リポジトリ はDREグループ管理になっており、DSグループがリソースを作成する際に、以下の手順を踏む必要がありました。 DSグループで修正のPullRequest(以降PR)を作成 DREグループにレビューを依頼 DREグループのレビュー通過後にマージ & デプロイされるので、反映結果を確認 このような手順を踏むので、 検証のために、試しにリソースを作成したり変更したりする際に、都度PRを作成し、レビュー依頼しないといけない 他チームのレビューを挟むので、GoogleCloudのリソースを作成するまで、リードタイムがかかりがち という問題があり、DX(Developer eXperience)に影響を与えていました。 ソリューション まず本番環境しかない問題については、開発環境を作り、Cloud Composerを本番環境、開発環境それぞれに配置することにしました。 それに合わせてGoogleCloudのprojectも分けることにしました。 1つのproject上に本番環境と開発環境を構成するよりも、分けた方が事故が起こりにくく、Terraform上の管理もしやすかったためです。 また、サービスレベルの異なるpipelineが同じワークフローに載っている問題について、サービスレベルが大きく異なる ユースケース ごとにCloud Composerを分けることにしました。 コストとの トレードオフ になりますが、運用・保守のしやすさを考えると、社内で使う ユースケース と社外などConsumerなどに提供する ユースケース でCloud Composerを分けた方が良いという判断からこの構成にしました。 結果、下図のような構成になりました。 その上で、上記環境のTerraformのコードをDRE管理の リポジトリ と分けて、DSグループ管理の別 リポジトリ で管理する方針としました。 また、ブランチ戦略を整理して、featureブランチにpushする度に開発環境にデプロイされることにしました。 これにより、デプロイ都度レビューを挟まないといけないフローが、featureブランチにpushするだけでデプロイされるようになり、検証までのリードタイムを改善できたと思ってます。 結果 最終的に、数ヶ月かけてこの新環境の構築とpipelineの移行を行いました。 結果、上記の3つの課題については、解消することができたと思ってます。 特に、開発環境ができたことと、DSグループ管理のTerraform リポジトリ ができたこと、featureブランチのpushでデプロイできるようになったことから、インフラの検証のしやすさは格段に上がったと思っており、DSグループ内のDX向上に寄与できたのではと思っております。 We’re Hiring タイミーのデータ統括部では、データサイエンティスト、DRE、Data Analystなど、様々な職種のメンバーを募集してます! https://hrmos.co/pages/timee/jobs カジュアル面談 からでも対応できますので、少しでも気になった方は申し込み頂けると嬉しいです!