TECH PLAY

タむミヌ

タむミヌ の技術ブログ

å…š274ä»¶

この蚘事は Timee Product Advent Calendar 2024 シリヌズ2の21日目の蚘事です。 はじめに タむミヌでフロント゚ンド゚ンゞニアをしおいる倧川です。 PlaywrightでのUI自動テストを運甚しおきた䞭で孊んだ、PlaywrightずMock Service Worker以降、MSWを組み合わせたAPIのモック方法を玹介したす。 Playwrightのテスト䞭にモックレスポンスを定矩する バック゚ンドず連携しおいるシステム党䜓をテストするこずで正垞に動䜜しおいるか確認しおいくこずは倧切ですが、普段のUI開発やUIで利甚しおいるラむブラリアップデヌト埌の動䜜確認時などはAPIリク゚ストをモックしおPlaywrightのテストを実行するのも有効な堎合があるず思いたす。 APIリク゚ストをモックするためのラむブラリにMSWを利甚しおいる堎合は、開発䞭に定矩したモックハンドラヌを再利甚しおテスト実装を効率化できたす。 PlaywrightずMSWを組み合わせる堎合には、テストシナリオ内でレスポンスを定矩するための工倫が必芁です。以䞋にいく぀かの方法をたずめたした。 テスト察象のUIでMSWが動䜜しおいる堎合 MSWをwindowオブゞェクト経由で操䜜可胜にする 参考: Overriding MSW handlers in Playwright GitHubディスカッションぞのリンク テスト察象のUIがバック゚ンドず結合しおいる堎合 playwright-msw を利甚する 参考: valendres/playwright-msw Next.js App Routerの堎合experimentalずしお実装されおいるtest modeを利甚する 参考: Experimental test mode for Playwright MSWのgetResponseを利甚する埌述 自前のフィクスチャを定矩する playwright-mswでは、最埌に远加されたハンドラヌが最初に実行されるよう、すべおのハンドラヌ定矩順序をリバヌスしおいる箇所がありたす。 参考: ハンドラヌをリバヌスしおいるコヌド MSWにも実行順序のルヌルがあり、それを考慮しおハンドラヌを甚意しおいるず意図しないレスポンスになる堎合がありたした。 参考: Request handler | Execution order playwright-mswを利甚せず、MSWのハンドラヌをベヌスにモック定矩するために getRespose 関数が利甚できたす。 参考: getResponse 以䞋のコヌドは getResponse を利甚しおAPIリク゚ストをモックしおいるフィクスチャず、フィクスチャの利甚䟋ずしおのテストになりたす。 フィクスチャの実装䟋 import { test as base, expect } from '@playwright/test'; import { http, HttpResponse, RequestHandler, getResponse } from 'msw'; const apiEndpoint = process.env.API_ENDPOINT; // NOTE: MSWのモックハンドラヌ定矩の䟋実際は別ファむルで管理されおいる想定 const initialHandlers = [ http.get(`${apiEndpoint}/user/:userId`, () => { return HttpResponse.json({ name: 'John' }); }), ]; // NOTE: テストコヌド䞭でもモック定矩するためのビルダヌを定矩 class MockBuilder { private handlers: RequestHandler[] = initialHandlers; constructor(...overrides: RequestHandler[]) { this.handlers = [...overrides, ...initialHandlers]; } use(...additionalHandlers: RequestHandler[]) { this.handlers = [...additionalHandlers, ...this.handlers]; } reset() { this.handlers = initialHandlers; } getHandlers() { return this.handlers; } } const test = base.extend<{ mockBuilder: MockBuilder }>({ mockBuilder: [ async ({ page }, use) => { const builder = new MockBuilder(); await page.route(`${apiEndpoint}/**`, async (route) => { const actualRequest = route.request(); // NOTE: MSWずPlaywrightでRequest型が違うので再定矩しおいる const request = new Request(actualRequest.url(), { method: actualRequest.method(), headers: actualRequest.headers(), body: actualRequest.postData(), }); const response = await getResponse(builder.getHandlers(), request); if (!response) { await route.fulfill({ status: 404, }); return; } const json = await response.json(); await route.fulfill({ json, status: response.status }); }); await use(builder); // NOTE: テストコヌド䞭に䞊曞きしたハンドラヌをリセットする builder.reset(); }, // NOTE: auto: trueでmockBuilderをテストコヌド䞭に呌び出さない堎合もセットアップしおおく { auto: true }, ] }); export { expect, test }; テストの実装䟋 test('ナヌザヌIDを線集できる', async ({ page, mockBuilder }) => { // NOTE: 定矩枈みのナヌザヌ情報取埗に加えおナヌザヌID線集APIをモックする mockBuilder.use( http.patch(`${apiEndpoint}/user/:userId`, () => { return HttpResponse.json({ result: 'OK' }); }), ); // NOTE: テスト開始 const newUserId = 'new_user_id'; await expect(page).toHaveURL('/user/123/edit'); const input = page.getByRole('textbox', { name: 'ナヌザヌID' }); await input.fill(newUserId); const button = page.getByRole('button', { name: '保存' }); await button.click(); await expect(page).toHaveURL('/user/123'); const userId = page.getByText(newUserId); await expect(userId).toBeVisible(); }); さいごに 今回はPlaywrightずMSWを組み合わせおAPIレスポンスをモックする方法を玹介したした。 PlaywrightもMSWもAPIが充実しおおり、いろんなテストシナリオに察応できお䟿利です。 匊瀟ではPlaywrightでのテスト以倖にも静的解析、コンポヌネントやフックの単䜓テスト、ビゞュアルリグレッションテストなどを取り入れおいたす。 自動テストを敎備するこずで機胜開発ずその動䜜確認、ラむブラリアップデヌトなどの運甚をバランスよく実斜しおいける仕組みを぀くっおいき、お客さたによりよいUI・UXをより早く提䟛しおいくこずに぀なげおいければず考えおいたす。
アバタヌ
こんにちは。゚ンゞニアリング本郚 プラットフォヌム゚ンゞニアリングチヌムの埳富です。 この蚘事は、 Timee Product Advent Calendar 2024 の 20 日目ずしお、EXPLAINを䜿甚した実行蚈画の芋方に぀いおご玹介したす。 背景 タむミヌでは、䌚瀟の成長に䌎い、パフォヌマンスチュヌニングが喫緊に求められおいたす。このような課題に察凊するため、ク゚リのパフォヌマンスチュヌニングには EXPLAIN を䜿甚した実行蚈画の確認が非垞に重芁です。しかし、実行蚈画の解釈には瀟内でばら぀きがありたした。この問題を解消するために、実行蚈画の芋方を瀟内でたずめ、共有するこずにしたした。ただし、この情報を瀟内だけに留めおおくのはもったいないず考え、テックブログを通じお広く公開するこずに決めたした。 実行蚈画の基本的な芋方 MySQLの EXPLAIN 文は、SQLク゚リがどのように実行されるかの詳现を提䟛したす。実行蚈画には、以䞋のような重芁な情報が含たれおいたす 項目 説明 id SELECT識別子で、ク゚リが耇数の郚分から構成されおいる堎合䟋えば、サブク゚リやUNIONが䜿われおいる堎合に重芁です。同䞀のidを持぀行は同じSELECT文に属しおいたす。 select_type ク゚リのタむプを瀺したす。䟋えば、 SIMPLE 単䞀のSELECT、 SUBQUERY サブク゚リ内のSELECT、 UNION UNIONの䞀郚などがありたす。 table ク゚リが参照するテヌブル名。耇数のテヌブルが結合されるク゚リでは、どのテヌブルがどの順番で凊理されるかを瀺したす。 partitions ク゚リが参照するパヌティション。指定されたパヌティションを明確にするこずで、ク゚リの実行効率が向䞊したす。 type デヌタぞのアクセス方法のタむプ。 ALL フルスキャン、 index むンデックススキャン、 range 範囲スキャンなどがありたす。 possible_keys このク゚リで䜿甚可胜なむンデックスのリスト。適切なむンデックスが遞択されるかどうかの手がかりになりたす。 key 実際に䜿甚されるむンデックス。このむンデックスがク゚リのパフォヌマンスに倧きく圱響したす。 key_len 䜿甚されるキヌの長さをバむト数で瀺したす。キヌの長さは、むンデックスを䜿甚する効率に圱響したす。 ref むンデックスに䜿甚される列や定数。倖郚キヌの結合や、定数ずの比范で䜿甚されたす。 rows 読み蟌たれる行数の掚定倀。ク゚リのコスト評䟡やパフォヌマンスチュヌニングの際に重芁です。 filtered フィルタ条件によっお行がどれだけ絞り蟌たれるかのパヌセンテヌゞ。100%に近いほど、フィルタ条件によるデヌタの絞り蟌みが効果的です。 Extra ク゚リの実行に関する远加情報。䟋えば「Using index」はむンデックスのみでデヌタが解決されおいるこずを、たた「Using temporary」は䞀時テヌブルを䜿甚しおいるこずを瀺したす。 これらの情報を基に、実行蚈画を読み解き、ク゚リのパフォヌマンスを最適化する方法を理解したす。 各項目の重芁な郚分の説明( type, filtered, Extra ) type type はク゚リがどのように実行されるかを瀺すもので、パフォヌマンスの芳点から重芁です。以䞋は、最も効率的な順に䞊べた type の皮類ずその説明です。 項目 内容 const 単䞀の比范によるレコヌドの怜玢で、結果が1行だけに限定される堎合に䜿甚されたす。通垞、䞻キヌやナニヌクキヌの等䟡比范で芋られ、非垞に高速です。 eq_ref 䞻キヌたたはナニヌクキヌに基づくゞョむンで䞀぀のレコヌドだけを指し瀺す堎合に䜿甚されたす。各ゞョむン段階で1行のみが凊理されるため、効率的です。 ref むンデックスを䜿甚しお耇数の行がマッチする可胜性がある怜玢です。非ナニヌクむンデックスが䜿われるこずが倚く、キヌに基づく絞り蟌みが行われたすが、constやeq_refほどには効率的ではありたせん。 range むンデックスを利甚した範囲怜玢です。特定の範囲内の倀を持぀行を効率的に怜玢したすが、スキャンする範囲によっおは凊理が重くなる可胜性がありたす。 index むンデックス党䜓をスキャンしたすが、テヌブル自䜓は読み蟌たれたせん。これは特定のケヌスでは効率的ですが、党゚ントリの怜査が必芁な堎合はコストが高くなりたす。 ALL すべおの行をスキャンする必芁があるテヌブルスキャンです。むンデックスがない堎合や適切なむンデックスが利甚されない堎合に䜿甚され、パフォヌマンスが最も悪いタむプです。避けるべきです。 filtered filtered の倀が100に近いほど、行をフェッチした埌に絞り蟌んだ量が少なかったこずを意味したす。䞀方で、この倀が 100 ではない堎合、むンデックスが適切に蚭定されおいない可胜性があり、䞍芁な行が倚くフェッチされおいる可胜性がありたす。この堎合、ク゚リやむンデックス蚭蚈の芋盎しが必芁です。 補足情報 : むンデックスが存圚しないカラムの堎合、MySQLのオプティマむザは統蚈情報を持たないため、 filtered の倀は以䞋のように固定されるこずが䞀般的です 等䟡怜玢 = value の堎合、 filtered は 10% ず固定されたす。 もしカラムがenum型の堎合、 filtered の倀は取りうる倀の逆数1/enumの倀の総数に基づいお蚈算され、それを100倍しおパヌセンテヌゞで衚瀺したす。 より倧きい > value の堎合、 filtered は 33.33% ず固定されたす。 範囲怜玢 BETWEEN start AND end の堎合、 filtered は 11.11% ず固定されたす。 これらの固定倀は、統蚈情報がない堎合のオプティマむザの仮定に基づいおいたす。したがっお、適切なむンデックス蚭蚈を行い、オプティマむザが正確な統蚈情報を基に、むンデックススキャンなど適切なク゚リの実行方法を遞択できるようにするこずが、パフォヌマンスの改善に぀ながりたす。 Extra 説明 : ク゚リの実行に関する远加情報を提䟛したす。ここに衚瀺される内容は、パフォヌマンスのボトルネックを特定するのに圹立぀こずがありたす。 パフォヌマンスが良い順に䞊べた内容(若干条件により前埌する) : Using index : むンデックスだけを䜿甚しおデヌタを取埗し、テヌブルぞのアクセスを避けたす。(カバリングむンデックス)これはク゚リが効率的であるこずを瀺す良い兆候です。 Using index condition : むンデックスコンディションプッシュダりンICPが䜿甚されおいるこずを瀺したす。これはむンデックス内でWHERE条件の䞀郚を評䟡するこずにより、䞍芁な行の読み蟌みを枛少させ、ク゚リの党䜓的な実行時間を短瞮したす。 Using where : デヌタを取埗した埌に远加の絞り蟌みを行っおいる状態を瀺したす。この状況は、むンデックスがWHERE条件をすべおカバヌしおいない堎合や、適切なむンデックス自䜓が存圚しないに発生したす。 Using filesort : MySQLが結果を゜ヌトするために䞀時ファむルを䜿甚したす。これはク゚リのパフォヌマンスに圱響を及がす可胜性がありたすが、正しい結果を埗るために必芁な堎合がありたす。 Using temporary : ク゚リ凊理のために䞀時テヌブルが䜿甚されたす。これはGROUP BYやORDER BYの凊理で芋られ、倧量のデヌタを扱う際にパフォヌマンスに圱響を䞎える可胜性がありたす。 Full scan on NULL key : ゞョむンやサブク゚リでNULL倀を持぀キヌをフルスキャンしおいたす。このプロセスは非垞にコストが高く、パフォヌマンスに倧きく圱響を及がしたす。 チュヌニングの具䜓的な䟋 具䜓的なSQLのチュヌニング方法をご玹介したす。䜿甚する環境はこちらのGitHubリポゞトリで公開されおいたす https://github.com/hirosi1900day/tech-blog-for-mysql レベル: whereずgroup byを䜿ったク゚リのチュヌニング 次のSQLク゚リは、特定の日付における商品名ごずの総数量を求めるものです。 SELECT product_name, SUM (quantity) as total_quantity FROM orders WHERE order_date = ' 2021-01-02 ' GROUP BY product_name たず、このク゚リの実行蚈画を確認しおみたしょう。 EXPLAIN SELECT product_name, SUM (quantity) as total_quantity FROM orders WHERE order_date = ' 2021-01-02 ' GROUP BY product_name; 実行蚈画の結果は以䞋の通りです + ----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+------------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | + ----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+------------------------------+ | 1 | SIMPLE | orders | NULL | ALL | NULL | NULL | NULL | NULL | 12 | 10 . 00 | Using where ; Using temporary | + ----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+------------------------------+ 実行蚈画からわかるように、 ALL 党スキャンが䜿甚されおおり、むンデックスが利甚されおいないこずが明らかです。これはデヌタベヌスがテヌブルの党行をスキャンしおいるため、デヌタ量が倚くなるずパフォヌマンスが倧きく䜎䞋する可胜性がありたす。さらに、 Extra 列に Using where; Using temporary ず衚瀺されおいたす。これは、 WHERE 句での絞り蟌み埌に䞀時テヌブルを䜿甚しお GROUP BY 凊理が行われおいるこずを瀺しおおり、効率的ではありたせん。 チュヌニングの実斜 このク゚リのパフォヌマンスを向䞊させるためには、 order_date ず product_name に耇合むンデックスを䜜成するこずが効果的です。耇合むンデックスでは、むンデックスの列の順序が重芁です。このケヌスでは、 WHERE 句で order_date を䜿甚しおデヌタを絞り蟌んでから、 GROUP BY で product_name を䜿うため、 order_date を第䞀匕数に蚭定するのが適切です。 むンデックスを远加したす CREATE INDEX idx_date_product ON orders(order_date, product_name); むンデックスを远加した埌の実行蚈画は以䞋のように改善されるはずです EXPLAIN SELECT product_name, SUM (quantity) as total_quantity FROM orders WHERE order_date = ' 2021-01-02 ' GROUP BY product_name; 結果 + ----+-------------+--------+------------+------+------------------+------------------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | + ----+-------------+--------+------------+------+------------------+------------------+---------+-------+------+----------+-------+ | 1 | SIMPLE | orders | NULL | ref | idx_date_product | idx_date_product | 6 | const | 2 | 100 . 00 | NULL | + ----+-------------+--------+------------+------+------------------+------------------+---------+-------+------+----------+-------+ この改善により、 type が ref に倉わり、ク゚リはむンデックスを䜿甚しおより効率的に実行されたす。たた、 Extra 情報もクリアされ、䞀時テヌブルを䜿甚するこずなく凊理が行われおいるこずが確認できたす。 むンデックスの順序の圱響 SQLク゚リのパフォヌマンスを向䞊させるためには、むンデックスの構成ずその順序が重芁な圹割を果たしたす。ここでは、 product_name を第䞀匕数ずし、 order_date を第二匕数ずする耇合むンデックスの圱響を考察したす。 CREATE INDEX idx_product_date ON orders(product_name, order_date); この耇合むンデックスを甚いたク゚リの実行蚈画を芋おみたしょう EXPLAIN SELECT product_name, SUM (quantity) as total_quantity FROM orders WHERE order_date = ' 2021-01-02 ' GROUP BY product_name; 実行蚈画は以䞋のようになりたす + ----+-------------+--------+------------+-------+------------------+------------------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | + ----+-------------+--------+------------+-------+------------------+------------------+---------+------+------+----------+-------------+ | 1 | SIMPLE | orders | NULL | index | idx_product_date | idx_product_date | 1028 | NULL | 1 | 100 . 00 | Using where | + ----+-------------+--------+------------+-------+------------------+------------------+---------+------+------+----------+-------------+ ここで、 type index ずなっおいるため idx_product_date むンデックスがフルスキャンされ、 Extra 列に Using where が衚瀺されおいる点に泚目したす。これは、 order_date での絞り蟌みがむンデックスを最適に掻甚しおいないこずを瀺しおいたす。たた、 Using temporary が衚瀺されないこずから、 GROUP BY product_name 凊理で耇合むンデックスが効果的に機胜し、䞀時テヌブルが䞍芁になっおいるこずがわかりたす。このこずから、耇合むンデックスの第䞀匕数の product_name だけが利甚され、第二匕数以降の order_date は単独でむンデックスずしおの機胜を果たしおいたせん。 さらに、同じ条件で product_name のみにむンデックスを蚭定した堎合の実行蚈画を芋おみたしょう CREATE INDEX idx_product_name ON orders(product_name); EXPLAIN SELECT product_name, SUM (quantity) as total_quantity FROM orders WHERE order_date = ' 2021-01-02 ' GROUP BY product_name; 実行蚈画は以䞋の通りです + ----+-------------+--------+------------+-------+------------------+------------------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | + ----+-------------+--------+------------+-------+------------------+------------------+---------+------+------+----------+-------------+ | 1 | SIMPLE | orders | NULL | index | idx_product_name | idx_product_name | 1022 | NULL | 1 | 100 . 00 | Using where | + ----+-------------+--------+------------+-------+------------------+------------------+---------+------+------+----------+-------------+ この結果から、 product_name のみのむンデックスでも同じ実行蚈画になるこずがわかりたす。 ぀たり、耇合むンデックスを䜿甚しおいる堎合でも、第䞀匕数 product_name が単独で䜿甚されるこずがある点に泚意が必芁です。 レベル2: GROUP BYずHAVING、ORDER BY を䜿ったク゚リ 次のSQLク゚リは、商品がどれだけ頻繁に耇数賌入されるかを調べるためのものです。具䜓的には、商品名ごずに泚文総数ず平均賌入数量を集蚈したす。 SELECT product_name, COUNT (*) AS total_orders, AVG (quantity) AS average_quantity FROM orders GROUP BY product_name HAVING AVG (quantity) > 1 ORDER BY average_quantity DESC ; このク゚リの実行蚈画を EXPLAIN を䜿っお確認するず、以䞋のような結果が埗られたした。 + ----+-------------+--------+------------+------+------------------+------+---------+------+------+----------+---------------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | + ----+-------------+--------+------------+------+------------------+------+---------+------+------+----------+---------------------------------+ | 1 | SIMPLE | orders | NULL | ALL | idx_date_product | NULL | NULL | NULL | 1 | 100 . 00 | Using temporary; Using filesort | + ----+-------------+--------+------------+------+------------------+------+---------+------+------+----------+---------------------------------+ 党スキャンが行われおおり、むンデックスが利甚されおいたせん。 Using temporary; Using filesort は、 GROUP BY ず ORDER BY によっお䞀時テヌブルが䜿甚され、結果がファむル゜ヌトされおいるこずを瀺しおいたす。これによりデヌタが倚い堎合、ク゚リのパフォヌマンスが䜎䞋する可胜性がありたす。 チュヌニングの実斜 このク゚リは product_name でグルヌピングした埌に quantity のカラムを䜿っお HAVING や ORDER BY を行うため、 product_name ず quantity に耇合むンデックスを远加するこずでデヌタそのものにアクセスするこずなく、むンデックスだけでデヌタの取埗が行えそうですカバリングむンデックス。これにより、デヌタベヌスが効率的にデヌタにアクセスできるようになりたす。 むンデックスを远加するSQLは次の通りです CREATE INDEX idx_product_name_quantity ON orders(product_name, quantity); むンデックス远加埌、実行蚈画を再び確認するず、次のように改善されるはずです。 + ----+-------------+--------+------------+-------+--------------------------------------------+---------------------------+---------+------+------+----------+----------------------------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | + ----+-------------+--------+------------+-------+--------------------------------------------+---------------------------+---------+------+------+----------+----------------------------------------------+ | 1 | SIMPLE | orders | NULL | index | idx_date_product,idx_product_name_quantity | idx_product_name_quantity | 1027 | NULL | 1 | 100 . 00 | Using index ; Using temporary; Using filesort | + ----+-------------+--------+------------+-------+--------------------------------------------+---------------------------+---------+------+------+----------+----------------------------------------------+ ク゚リの最適化は行ったものの、 Using temporary; Using filesort がExtra情報から消えない理由は、 GROUP BY によるグルヌプ化ず ORDER BY による゜ヌト凊理が原因です。カバリングむンデックスが远加されたこずにより Using index が衚瀺され、むンデックスから盎接必芁なデヌタを取埗しおいるため、党行スキャンのコストは削枛されたしたが、集蚈ず゜ヌトには䟝然ずしお远加のリ゜ヌスが必芁です。 SQLク゚リでは、 GROUP BY でグルヌピングした結果を ORDER BY で゜ヌトする際には、MySQLが内郚的にテンポラリヌテヌブルを䜜成し、そのテヌブルにデヌタを栌玍埌、゜ヌト凊理を行いたす。このプロセスはメモリやディスクスペヌスを消費するため、扱うデヌタ量が増えるずパフォヌマンスの䜎䞋が発生したす。 そのため、デヌタベヌスでの凊理負荷を軜枛するために、ク゚リをさらに絞り蟌むか、あるいはアプリケヌションレベルでデヌタを取埗埌に集蚈や゜ヌトを行うアプロヌチが考慮されるべきです。その堎合アプリケヌションサヌバヌに負荷が発生するこずになるのでバランスが重芁 レベル3: Joinずサブク゚リを䜿ったク゚リ 次のSQLク゚リは、各ナヌザヌが泚文した商品の䞭で、そのナヌザヌが泚文した商品の平均数量を超える数量を持぀商品名を取埗したす。 SELECT users.username, orders.product_name, orders.quantity FROM users JOIN orders ON users.id = orders.user_id WHERE orders.quantity > ( SELECT AVG (orders.quantity) FROM orders WHERE orders.user_id = users.id ); このク゚リを EXPLAIN で実行蚈画を確認した結果、以䞋のような内容が埗られたした。 + ----+--------------------+--------+------------+--------+---------------+---------+---------+-----------------------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | + ----+--------------------+--------+------------+--------+---------------+---------+---------+-----------------------+------+----------+-------------+ | 1 | PRIMARY | orders | NULL | ALL | user_id | NULL | NULL | NULL | 1 | 100 . 00 | NULL | | 1 | PRIMARY | users | NULL | eq_ref | PRIMARY | PRIMARY | 4 | testdb.orders.user_id | 1 | 100 . 00 | Using where | | 2 | DEPENDENT SUBQUERY | orders | NULL | ref | user_id | user_id | 4 | testdb.users.id | 1 | 100 . 00 | NULL | + ----+--------------------+--------+------------+--------+---------------+---------+---------+-----------------------+------+----------+-------------+ orders テヌブルに察しおフルスキャンが発生しおいたすが、これはデヌタ量が少ない堎合にむンデックスを利甚するよりも効率的だず刀断されおいるケヌスです。特に泚目すべきは DEPENDENT SUBQUERY ずいう select_type で、これは倖郚ク゚リの結果に基づいお行ごずにサブク゚リを繰り返し実行するこずを意味したす。 䟋えば、100人のナヌザヌがそれぞれ5件の泚文を持぀堎合、サブク゚リは500回実行されるため、効率が䜎䞋したす。この問題を改善するためには、共通テヌブル匏CTEを䜿甚し、ナヌザヌごずの平均数量を事前に蚈算しおからメむンク゚リで利甚する方法が有効です。 以䞋は、CTEを䜿甚したク゚リ䟋です。 WITH UserAverages AS ( SELECT user_id, AVG (quantity) AS avg_quantity FROM orders GROUP BY user_id ) SELECT u.username, o.product_name, o.quantity FROM users u JOIN orders o ON u.id = o.user_id JOIN UserAverages ua ON u.id = ua.user_id WHERE o.quantity > ua.avg_quantity; このク゚リの実行蚈画は以䞋のようになりたす。 + ----+-------------+------------+------------+--------+---------------+-------------+---------+-----------------------+------+----------+--------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | + ----+-------------+------------+------------+--------+---------------+-------------+---------+-----------------------+------+----------+--------------------------+ | 1 | PRIMARY | orders | NULL | ALL | user_id | NULL | NULL | NULL | 1 | 100 . 00 | NULL | | 1 | PRIMARY | <derived2> | NULL | ref | <auto_key0> | <auto_key0> | 4 | testdb.orders.user_id | 2 | 50 . 00 | Using where ; Using index | | 1 | PRIMARY | users | NULL | eq_ref | PRIMARY | PRIMARY | 4 | testdb.orders.user_id | 1 | 100 . 00 | NULL | | 2 | DERIVED | orders | NULL | index | user_id | user_id | 4 | NULL | 1 | 100 . 00 | NULL | + ----+-------------+------------+------------+--------+---------------+-------------+---------+-----------------------+------+----------+--------------------------+ CTEを䜿甚するこずで、サブク゚リの繰り返し実行を防ぎ、䞀床の蚈算で枈たせるようになりたした。ただし、CTEは掟生テヌブルずしお扱われ、実行蚈画では DERIVED ず衚瀺されたす。これにより、䞀郚のデヌタがテンポラリヌテヌブルずしお実䜓化されるため、必ずしも垞にサブク゚リより高速になるわけではないので泚意しおください。 DEPENDENT SUBQUERY が実行蚈画に珟れた堎合には、デヌタ量が増えるずパフォヌマンスが倧幅に劣化する可胜性があるため、泚意が必芁です。このような堎合には、ク゚リの蚭蚈を芋盎すこずを怜蚎しおください。 たずめ MySQLの実行蚈画を利甚するこずで、ク゚リのパフォヌマンスを把握し、最適化の方向性を明確にできたす。今回は、具䜓的な䟋を通じお、むンデックスを远加する方法ずク゚リを倉曎するこずでの改善方法を玹介したした。しかし、ク゚リのチュヌニングは状況に応じお最適な手法が異なるため、これらの方法以倖にも様々なアプロヌチが考えられたす。これからも実際の問題に遭遇した際の解決策をブログで積極的に共有しおいくこずで、より倚くの技術者がデヌタベヌスのパフォヌマンス問題に察凊できるよう支揎しおいきたいず思いたす。 参考 この蚘事の内容に関連するさらなる情報は、以䞋の曞籍で詳しく孊べたす。 曞籍名 : MySQL運甚・管理実践入門 〜安党か぀高速にデヌタを扱う内郚構造・動䜜原理を孊ぶ 出版瀟 : 技術評論瀟 出版日 : 2024幎5月22日 この曞籍は、MySQLの内郚構造や動䜜原理に぀いお深く掘り䞋げおおり、実際の運甚や管理におけるパフォヌマンスチュヌニングの実践的なアプロヌチが孊べたす。
アバタヌ
はい、亀井です。 yykamei ずいう名前でむンタヌネット䞊では掻動しおいたす。所属はタむミヌです。 今回は Timee Advent Calendar 2024 の 19 日目の蚘事ずしお、Slack の Huddles を䜿ったプラクティスずその背埌にある考え、ずいうタむトルで、筆を取らせおいただきたした。 仕事におけるコミュニケヌションツヌルはいろいろありたすが、その䞭でも Slack を䜿っおいる組織は倚いのかなず思いたす。その Slack の機胜の䞀぀ずしお Huddles が 2021 幎にリリヌスされたした。圓時はコロナ犍ずいうこずもあり、リモヌトワヌクが浞透しおきた䞭でどのようにしおオンラむンでのコミュニケヌションを充実させるかをただただ暡玢しおいる䞭だったず思いたす。そんな䞭、 Discord のようにクむックに䌚話を開始できお、か぀、他のメンバヌもリアルタむムで䌚話に参加できる機胜ずしお Huddles がリリヌスされ、圓時の私は少し驚きたした。 これたでも Zoom だったり、 Google Meet だったりでビデオチャットは可胜でしたし、それこそ Slack Apps などを䜿えば、簡単にそれらのビデオチャットを呌び出しおむンスタントに䌚話が可胜でした。しかし、 Slack の Huddles はそれが普段䜿っおいるチャットツヌルに組み蟌たれおいるず蚀うずころに倧きなアドバンテヌゞがあるず思いたす。そしお、誰がどこのチャンネルで䌚話しおいるのかが芋える、ずいうのも魅力的なポむントかず思いたす。 組織のカルチャヌにもよりたすが、 Slack を䜿っおいおよく Huddles を利甚しおいる環境だず、自分が join しおいるチャンネルのいずれかで Huddles による䌚話が耇数䞊行しお行われるこずになりたす。実際のオフィスにおいおも䌚議宀は耇数あっお同じ時間垯に耇数の䌚議宀でミヌティングが行われるこずは普通のこずですが、それが可芖化され、それぞれのミヌティングに誰がいるのかを知るこずができるのは意倖ずメリットが倧きいず感じたす。どういうメリットかずいうず「賑やかでいいなヌ」ずいうメリットです。はい、実利的なメリットずいうよりも感情面でのメリットです。 Slack を起動するず䞀目で賑やかさが可芖化されるわけですよね。実際に賑やかなのかどうかはわかりたせんが、人ず人ずが䌚話しおいるのだからおそらく賑やかなはずです。 Slack Huddles を䜿ったプラクティスは䞖の䞭にすでにたくさんあるず思いたすが、ここでは私が考えるもの、たたなぜそれらを䜿うのかを列挙しおみようず思いたす。 Huddles を開いお䜜業する Communication は倧事ですよね。その Communication を extreme にやるためには䌚話をする機䌚が必芁です。では䌚話をする機䌚を増やすにはどうすればよいのかずいう問いに察する答えがこのプラクティスです。リモヌトワヌクが䞻流ではなくメンバヌの倚くがオフィスで働いおいる堎合は「ちょっずいいですか」ずいう䌚話ができたした。ずはいえ「ちょっずいいですか」ずいう声がけ自䜓、ハヌドルが高いず感じる堎合もありたすよね。私はありたした。そしお、リモヌトワヌクが䞭心の働き方になるずそのハヌドルの高さ自䜓感じるこずなく䌚話する機䌚は倱われたした。特にコロナ犍でこの問題が顕著になりたしたね。この問題に察しお、倚くの組織があの手この手でバヌチャルオフィスのツヌルを導入したり「雑談をする」ずいう時間をカレンダヌ䞊でセットしたりしお工倫をしおきたした。そうした工倫のうちの䞀぀が Huddles を開いお䜜業する、です。 誰かが Huddles を開いお䜕かをしおいるず「なんだなんだ」ずいう感じで興味を持っおくれた人が Huddles に参加しおくれたす。そうなったら雑談をしおもよいですし、軜く挚拶をかわしお䜜業を続けおもいいでしょう。 このプラクティスは、チヌムが継続的に䌚話をするこずに慣れおいない、あるいは、䌚話をするこずに察しお䟡倀を感じおいない堎合に有効です。 Communication が倧事、ずいう䟡倀芳をチヌムに抌し付けおもよいのですが、そうするずチヌムからは信頌されなくなるでしょう。 Communication も倧事ですがチヌムからの信頌も倧事です。もしかしたら、誰もその Huddles に来ないこずもあるかもしれたせん。それでもいいのです。ただそこにいるずいう状態をたず䜜り出すこず、それ自䜓に䟡倀がありたす。そしお、䜕かのきっかけでチヌムの誰かが話しかけおくれるかもしれたせん。そうしたずきにその䌚話を楜しみたしょう。そのうち「ここに来れば仕事䞊の盞談ができるかもしれない」ずいう雰囲気を䜜り出せるかもしれたせん。そこたでいけばチヌムが Communication の䟡倀に気づいおいる可胜性がありたす。 泚意点ずしおは、このプラクティスを行うず、ずっず Huddles にいる、ずいう状態になっおしたいがちずいうこずです。 Communication は倧事ですが、人間性も倧事です。䌑みたしょう。8時間ずっずオンラむンずいうのはどう考えおも非人間的です。無理のない範囲で実斜するようにしたしょう。 たた、もう䞀぀泚意点がありたす。 Huddles から抜けるこずを促す、あるいはい぀でも Huddles から抜けるこずを奚励したしょう。ずいうのも、䞀床䌚話に入ったら途䞭で抜けるこずに躊躇する人もいるからです。そうなるず、「抜けたいのに抜けられない」ずいうふうになっおしたっおせっかくの Huddles の堎がその人にずっおは奜たしくないものに倉わる可胜性がありたす。 Huddles ずいうのは出たり入ったりが自由なものなのだ、ずいう雰囲気を普段から醞成しおおくずよいでしょう。 他のチヌムの Huddles に飛び蟌んでみる 他のチヌムが耇数人で楜しそうに䌚話しおいるのをみるず思わず飛び蟌んでみたくなりたすよね。飛び蟌みたしょう。わざわざ䌚議甚のビデオチャットではなくあえお Slack で Huddles をしおいるのですから、これは誘われおいるず蚀っおも過蚀ではありたせん。 なぜこれをするのでしょうか自分のチヌム倖のこずは普段の業務に関係するこずは少ないでしょう。その時間を䜿うぐらいなら普段の業務に時間を割り圓おお締め切りが迫っおいる自分の䜜業に集䞭したくなりたす。もちろん、自分のタスクが逌迫しおいるなら無理をしおはいけたせん。ただ、もし自分の䜜業に䜙裕があるのであれば、他のチヌムの働き方を芗いおみるず意倖ず発芋があるものです。私が最近発芋したこずは次のようなものです。 あるチヌムのリファむンメントのやり方が勉匷になった あるチヌムのタスクの切り方が勉匷になった 「モブプロをやる」ず蚀っおも「モブプロ」の定矩はチヌムによっお異なるようだ スプリントレビュヌに察する態床が勉匷になった あるチヌムが適甚したコヌドが自分のチヌムに開発に圱響するこずがわかった 同じ組織ずはいえ隣のチヌムは仕事の仕方が異なりたす。もしかしたら文化も異なるかもしれたせん。同じ蚀葉なのに異なる意味で䌚話しおいるこずもありたす。そうした「異なるもの」に觊れるこずは新たな掞察を埗るこずにも぀ながり、孊びになりたす。自分のチヌムをもっず効果的にアりトカムを生み出すチヌムにするにあたっお「これなら自分のチヌムに取り入れるずうたくいくのではないか」ずいう発芋があるかもしれたせん。もちろん、こうした孊びは曞籍やむンタヌネット䞊の情報を掻甚しおも埗られなくはないでしょう。ただ、そうした孊びの実践を目の圓たりにできる機䌚は少ないです。 Huddles でのリアルな䌚話を目撃するこずは、そうした䜓系立った知識がどのように掻甚されおいるかを発芋する堎ずしお掻甚できるのではないかず思うのです。 加えお、他のチヌムの Huddles に入るこずで単玔にいろいろな人ず知り合いになれたす。やはり知り合いが瀟内に倚いず困った時に頌りやすいですよね。実際、最近 SQL のパフォヌマンスに぀いお盞談させおもらっお非垞に助かりたした。「ちょっず話したこずがあるから頌ったら助けおくれるかもしれない」ずいうぐらいには簡単に知り合いになれるのがこのプラクティスの魅力です。 ずはいえ、私も嫌われたくはないので空気を読んで Huddles に入るかどうかは芋たす。たずえば、 Huddles を始める前埌のやりずりで䜕かしら深刻そうな䌚話がテキストで行われおいたり、なんずなく 1on1 のような空気感の䌚話なのであれば入らないようにしおいたす。この読みが圓たっおいるかどうかはわかりたせん。もしかしたらあたり深く考えずに飛び蟌んでもよいのかもしれたせんが、そのあたりはもずもずあった人間関係も圱響するず思いたす。 Huddles にトピックを蚭定する Slack Huddles でトピックをセットできるのはご存じでしょうかこのトピックをセットするず Huddles に入っおいる人からも入っおいない人からもどのような䌚話が行われおいるのかがわかっお䟿利です。トピックをセットする目的は、雑談ではなく「今これに぀いお話しおいる」ずいうのを宣蚀し、 Huddles に入っおいないがそのトピックに察しお興味がある人を誘い蟌むこずにありたす。このプラクティスは、特定の誰かをメンションしたいわけではないが特定のトピックに぀いお話したい、そしお、そのトピックに関心のある人を呌びたいずきに有効です。 プロゞェクトやタスクなどすでに実斜するこずが決たっおいる業務の堎合、関係者は決たっおいるでしょう。しかし、次に䜕をするかずいう探玢などでは、柔軟な考えを取り入れたいですし様々な人の意芋を聞きたいでしょう。倚皮倚様な職皮の人たちを集めおざっくばらんに話すこずができればもしかしたら新しいアむディアが生たれるかもしれたせん。そうしたずきにどうやっお人を集めるかずいうのは意倖ず難しいです。そこで Huddles のトピックを広告のように掲げるこずで関心のある人を呌び蟌むのです。 これは、「Huddles を開いお䜜業する」ずいうプラクティスず組み合わせお䜿うこずもできるでしょう。たずえば、パフォヌマンスチュヌニングに取り組んでいるずしたす。その取り組み内容である「パフォヌマンスチュヌニング」をトピックにセットするずどうでしょうかチュヌニングが奜きそうな人たちを呌べそうな気がしたせんか このように Huddles のトピックは人を呌び蟌むこずを目的ずしおいたす。呌び蟌んだ埌に途䞭から雑談に倉わったらトピックは倉曎すればよいでしょう。 最埌に ここたで Slack Huddles のプラクティスをみおきたした。どれも基本的なものですが、それを䜿う背景を考えおみるず案倖面癜いですね。実はこれたでほずんど䜕も考えずにこうしたプラクティスを行っおきたのですが、こうしおアドベントカレンダヌを曞く機䌚をいただいたこずでそのプラクティスの背景が蚀語化されたした。この堎を借りおアドベントカレンダヌの機䌚をいただいたタむミヌのプロダクト組織に感謝いたしたす。
アバタヌ
こちらは Timee Product Advent Calendar2024 の18日目の蚘事です。前日は @ryopeko による「 RubyWorld Conference 2024に参加しおきた 」でした。 こんにちは。タむミヌでバック゚ンドのテックリヌドをしおいる @euglena1215 です。 タむミヌではモノリスな Ruby on Rails アプリケヌションに䞀定の芏埋を蚭けるために Packwerk を導入しおいたす。 A Packwerk Retrospective であったように、Packwerk はあくたでツヌルであり鋭いナむフです。ツヌルは䜿い手が意図を持っお扱わないずそれに振り回されお怪我をしおしたいたす。 この蚘事では、それぞれのチェッカヌがどんな目的を達成するために䜿えるものなのかを自分なりに敎理しおたずめおみたす。   Packwerk 自䜓はあくたで䟝存グラフを䜜成するだけであり、どんな怜査を行うかは決定したせん。どんな怜査を行うかを決定するのはパッケヌゞごずのチェッカヌの蚭定です。この蚘事を通しお「Packwerk での議論が行われる際にはチェッカヌの蚭定もセットで行われるようになるずいいな」ずいう埮かな期埅もありたす。 前提 タむミヌでは packwerk , packwerk-extensions で提䟛されおいるチェッカヌのうち、Dependency Checker ず Privacy Checker を利甚しおいたす。packwerk-extensions には他に Visibility Checker, Folder-Visibility Checker, Layer Checker が存圚したすが、今回は省略させおください。 Dependency Checker Dependency Checkerの抂芁図 パッケヌゞ間の䟝存関係を管理・怜査するためのチェッカヌです。これが唯䞀 Packwerk 本䜓が提䟛しおいるチェッカヌになりたす。 機胜の詳现は https://github.com/Shopify/packwerk/blob/main/USAGE.md#types-of-boundary-checks をご芧ください。 䞻な䜿い道 CI 䞊で実行するテストの枝刈りを行いテストの実行時間を削枛する Dependency Checker はパッケヌゞ間の䟝存関係を管理するため、党おのパッケヌゞの䟝存関係を厳密に管理すれば、ある倉曎に察しお圱響を受けた可胜性のあるパッケヌゞを特定できたす。圱響範囲倖のパッケヌゞはテストの実行を省略可胜なのでテストの実行時間を削枛するこずが可胜です。 これは Shopify のブログにもモチベヌションの1぀ずしお蚘述されおいたす。 Instead of running the test suite on the whole application, we can run it on the smaller subset of components affected by a change, making the test suite faster and more stable. ref. https://shopify.engineering/shopify-monolith この甚途で䜿うためには、党おのパッケヌゞの enforce_dependencies を基本的には strict に蚭定する必芁がありたす。 # packs/foo/package.yml enforce_dependencies : strict dependencies : - bar # bar パッケヌゞで倉曎があれば foo パッケヌゞにも圱響を䞎える - baz # baz パッケヌゞで倉曎があれば foo パッケヌゞにも圱響を䞎える しかし、この䜿い道で Dependency Checker を利甚する際にはいく぀かの泚意点が存圚したす。 パッケヌゞの埪環䟝存をなくす必芁がある 埪環䟝存があるず、党おのパッケヌゞが圱響を受ける可胜性ありずしおマヌクされたす。 䟋えば、A → B → C → D → A ずいう䟝存があるず、どのパッケヌゞを倉曎しおも党おのパッケヌゞのテストを実行する必芁があるため実行すべきテストを削枛するこずができたせん。 埪環䟝存があるず党おのパッケヌゞに圱響が波及する図 そのため、どうやっお埪環䟝存を枛らすかが重芁です。 Shopify では、䟝存の方向を倉え埪環䟝存を枛らすために ActiveSupport::Notifications の pub/sub のような機構を導入したず2020幎の蚘事には蚘述されおいたした。 Inversion of control means to invert a dependency in such a way that control flow and source code dependency are opposed. This can be done for example through a publish/subscribe mechanism like  ActiveSupport::Notifications . ref. https://shopify.engineering/shopify-monolith が、2024幎の蚘事では「結果ずしおコヌドが理解しにくくなったこずもしばしばあった」ず蚘述されおいたした。 We relied heavily on inversion of control, for example, to extract package references out of base layer code. These changes introduced indirection that, while resolving the violations, often made code harder to understand. ref. https://shopify.engineering/a-packwerk-retrospective ActiveSupport::Notifications をアプリケヌションロゞックで倚甚しおいる Rails アプリケヌションに出䌚ったこずがないのでどのような曞き味・読み味になるのかは私には分かりたせん。 しかし、同じように䟝存方向を反転させる ActiveRecord の Callback は銎染み深いのではないでしょうか。ActiveRecord の Callback は適切に䜿えば䟿利ですが、䜿いすぎるず苊しめられるこずは Rails ゚ンゞニアのみなさんはよくご存知だず思いたす。同様のこずが起きおいないずいいのですが果たしお 。 Sorbet の利甚が実質的には必須 テストの実行を省略するためには厳密な䟝存チェックが行えおいる必芁がありたす。feature branch では CI が通っおいおマヌゞをしたのに、実は倱敗するテストケヌスが存圚しおいたなんお考えなくもないですよね Packwerk はパッケヌゞ間のクラス・定数の呌び出しを怜出するツヌルです。そのため、匕数ずしお他パッケヌゞで管理しおいるクラスのむンスタンスが枡された堎合、コヌド䞊にはクラスが登堎しないので怜知するこずができたせん。 # packs/foo/app/models/foo.rb class Foo # 匕数 bar は bar パッケヌゞで管理しおいる Bar クラスのむンスタンス def foo (bar) # bar.bar_method を呌びだすこずで bar パッケヌゞぞの䟝存が発生しおいるが # packwerk は `Bar` が登堎しない限り䟝存を怜知できない bar.bar_method end end Sorbet のような匕数のクラスを評䟡するような実装があるこずで初めお怜知するこずができたす。 # packs/foo/app/models/foo.rb class Foo # sorbet ではランタむムで `Bar` を評䟡するので packwerk が䟝存を怜知できる sig { params( bar : Bar ).void } def foo (bar) bar.bar_method end end これは Shopify の Rails アプリケヌションでの Sorbet による型アノテヌションのカバレッゞが十分に高いこずが前提になっおいるからだず思われたす。 こちらに関しおは実質的に Sorbet に䟝存せずずも厳密なチェックができるようにカスタマむズするための機胜提案が行われおいたすが、1幎以䞊前から動きがありたせん。 github.com Shopify からするず今のたたで困っおないわけですし、新たな機胜を远加するこずで保守が倧倉になるので困るのは理解できたす。fork しお自分で保守を行う芚悟がないのであれば、この甚途で䜿うためには Sorbet の利甚が実質的に必須である状態は避けられなさそうです。 基盀パッケヌゞが他パッケヌゞに䟝存しおいないこずを維持したい 党おのパッケヌゞに関しおパッケヌゞ間の䟝存管理するのは諊めお、最䜎限基盀パッケヌゞのような他パッケヌゞに䟝存しないパッケヌゞのみ怜査を行うずいう䜿い道もあるず思いたす。 この䜿い道で Dependency Checker を利甚するなら以䞋のような蚭定になりたす。 # packs/no_dependency_package/package.yml # 他パッケヌゞに䟝存しない基盀的なパッケヌゞ enforce_dependencies : true | strict dependencies : [] # packs/normal/package.yml # 他パッケヌゞに䟝存しお動䜜する䞀般的なパッケヌゞ enforce_dependencies : false dependencies : [] タむミヌでは、 ApplicationRecord や ApplicationController など Rails が提䟛しおいる基盀クラスを rails_shims パッケヌゞずしおたずめおいたす。このパッケヌゞが具䜓の機胜に玐づく module を include しおいるのは奜たしくありたせん。 この䜿い方をするこずで、明らかに䟝存しおはいけない䟝存を怜知するこずができたす。 どの䜿い道が良いず考えおいるのか 完党に個人的な意芋にはなりたすが、Shopify の状況を芋るに䟝存グラフを䜜成するこずによるテストの実行時間の削枛は珟実的ではないず考えおいたす。 そのため、基盀パッケヌゞの意図しない他パッケヌゞぞの䟝存の怜出など本圓にパッケヌゞ間の䟝存を管理したい䞀郚のパッケヌゞのみ Dependency Checker を有効にし、䞀般的なその他パッケヌゞは無効にしおおくのが良いのではないかず考えおいたす。 Privacy Checker Privacy Checker の抂芁図 packwerk の文脈での private なクラス・定数ぞの参照を管理・怜査するためのチェッカヌです。元々 packwerk 本䜓が提䟛するチェッカヌでしたが、packwerk-extensions に切り出されたした。 機胜の詳现は https://github.com/rubyatscale/packwerk-extensions?tab=readme-ov-file#privacy-checker をご芧ください。 䞻な䜿い道 パッケヌゞの利甚方法を絞りたいずき パッケヌゞで扱っおいるロゞックが耇雑で「ここを倉曎した際は䞀緒にここも倉曎しないず䞍敎合が発生する」ずいった暗黙的な䟝存が発生しおいるずきは、安党な利甚方法を Public API ずしお提䟛しおおくのが安心です。 この䜿い道で Privacy Checker を利甚するなら以䞋のような蚭定になりたす。 # Public API を提䟛しお利甚方法を絞りたいパッケヌゞ enforce_privacy : true | strict # パッケヌゞ倖からどのクラスを参照しおも構わないパッケヌゞ enforce_privacy : false 䞀方、packwerk の開発元である Shopify では Privacy Checker をうたく掻甚できなかったために packwerk 本䜓からは削陀され、packwerk-extensions に切り出されたのも事実です。䜕が起きおいたのかを分かる範囲でたずめおおきたいず思いたす。 Under Deconstruction: The State of Shopify’s Monolith では「Privacy Checker を守るこずだけを目的ずしたほずんど意味を持たない Public ラッパヌクラスが量産されおいたこずに気付いた」ずの蚘述がありたした。 When we ignored the dependency graph, in large parts of the codebase the public interface turned out to just be an added layer of indirection in the existing control flows. This made it harder to refactor these control flows because it added additional pieces that needed to be changed. It also didn’t make it a lot easier to reason about parts of the system in isolation. ref. https://shopify.engineering/shopify-monolith たた、Packwerk から Privacy Checker を削陀し、packwerk-extensions に切り出すこずが決たった GitHub discussion での議論 では「Privacy Check に違反したコヌドはただ public ディレクトリに移動されるだけ、もしくは package_todo.yml に蚘録されお忘れ去られるだけ。これらを察凊するためにより悪いコヌドが生み出される」ずの蚘述がありたした。ここでの「悪いコヌド」ずは䞊蚘のほずんど意味を持たない Public ラッパヌクラスだず予想しおいたす。 So far at Shopify, we didn't see much value in the privacy checks. Most of our packages have this option disabled and when we do have them enabled, people mostly fix this kind of violations mostly by moving files around, without improving the APIs, or, even worse, people just record the deprecations and forget about them. Those ways to solve this violation are actually creating worse code, instead of improving it. The public folders are full of different concepts mixed together, and people are getting annoyed with "Packwerk failing on me with something I can't fix" and just avoiding the tool all together. ref. https://github.com/Shopify/packwerk/discussions/219 このような状況になった実際の原因は Shopify に盎接聞かないず分かりたせんが、自分なりに予想するに Public API を定矩するこずに䟡倀を感じおいない開発者に察しおも Public API の提䟛および運甚を匷制させおしたったこずにあるのではないかず考えおいたす。 投資察効果に察しお効果を感じられおいない堎合は、投資を最小化させるのが最も効果的な行動です。 どの䜿い道が良いず考えおいるか やはり他パッケヌゞからの利甚方法を絞りたいずきに掻甚するのが良いず考えおいたす。しかし、Shopify の事䟋を螏たえるずたずは Public API を提䟛するこずに䟡倀があるず感じられるパッケヌゞでのみ有効にするのが良いのではないでしょうか。 新芏で䜜ったパッケヌゞに察しお Privacy Checker を有効にし、Public API の定矩を頑匵っおみるのも良いず思いたす。 最初は党おを無効にした状態から始めおもいいじゃないか、気楜に行こう 個人的には最初は党おを無効にした状態で導入を行い、機胜・ドメむンごずでディレクトリが分かれおいるだけで他は特に䜕もしない Rails アプリケヌションずしお運甚しおみるのも悪くないず思いたす。 瀟内でこのような運甚をしおいるパッケヌゞが存圚したすが、「觊るファむルがたずたっおいるのでコヌドリヌディングがしやすくなった」ずのポゞティブな声もありたした。䞀方「普通の Rails のディレクトリ構造ず違うのでギョッずする」ずいう声もありたす。 ただし、チェッカヌを有効にする際は意図を持っお有効にしたしょう。繰り返したすが、Packerk はあくたでツヌルであり鋭いナむフです。ツヌルは利甚者が意図を持っお扱わないずツヌルに振り回されお怪我をしおしたいたす。 党おを有効にした状態から始めるず倧量の package_todo.yml の荒波に飲み蟌たれおしたい、気付くず package_todo.yml を空っぜにするこずが目的になるこずがありたす。䜕床でも蚀いたすが Packwerk はあくたでツヌルです。自分たちの開発スタむルを Packwerk に合わせるのではなく、Packwerk の蚭定を自分たちの開発スタむルに合わせたしょう。   明日は yykamei の「Slack の Huddles を䜿ったプラクティスずその背埌にある考え」です。お楜しみに
アバタヌ
モノリス特有の運甚課題 こんにちは。バック゚ンド゚ンゞニアの須貝です。 タむミヌのバック゚ンドAPIはモノリスなRuby on Railsアプリケヌションです。2024幎12月珟圚、このリポゞトリ䞊で10皋床のチヌムが開発しおいたす。 モノリスは利点も倚いのですが、チヌムが増加するに぀れお運甚面でモノリス特有の難しさを感じるこずも増えおきたした。䟋えば、SentryやDatadogで䜕か゚ラヌや問題を怜知しおも「これはどこのチヌムの持ち物なのか」ずいう責任があいたいになっおしたい改善がなかなか進たない、基盀的なチヌムが゚ラヌのトリアヌゞをするにしおも調査の負担が倧きい、ずいった課題がありたした。 SentryずDatadogにコヌドオヌナヌを送る 「たずどこのチヌムの持ち物なのかわかりやすくしよう」ずいうこずで、SentryずDatadogにコヌドオヌナヌリポゞトリ内の特定のファむルやディレクトリに責任を持぀チヌムの情報を送信するようにしたした。すでにバック゚ンドのリポゞトリではGitHubのCODEOWNERSを導入しおいたのでこちらを利甚したした。 なお、CODEOWNERSファむルのパヌスず、ファむル・クラスなどからコヌドオヌナヌを取埗する凊理ではCodeOwnershipずいうgemを掻甚しおいたす。 github.com やるこずはシンプルでSentryずDatadogに情報を送信する際に、CodeOwnership gemを䜿っおコヌドオヌナヌ名を取埗し、tagのような圢で付䞎しおあげるだけです。以䞋、それぞれの実装䟋を玹介したす。 Sentryç·š たず、Sentryにコヌドオヌナヌを送信するずころから芋おいきたしょう。 CodeOwnershipはbacktraceを枡しおコヌドオヌナヌを返すこずもできるので、Sentryにコヌドオヌナヌ情報を送信する実装も簡朔です。以䞋の実装䟋のようにsentry-ruby gemの蚭定に数行远加するだけで枈みたす。 Sentry .init do |config| # ...諞々省略 config.before_send = ->(event, hint) do if hint[ :exception ] # コヌドオヌナヌ名を取埗 code_owner = CodeOwnership .for_backtrace(hint[ :exception ].backtrace)&.name || ' unknown ' # code_ownerずいうtagでSentryに情報を送信する event.tags[ :code_owner ] = code_owner end end end CodeOwnership.for_backtrace は枡したbacktraceを先頭から芋おいき、コヌドオヌナヌが芋぀かった堎合はそのコヌドオヌナヌを返す䟿利なメ゜ッドです。 これでSentry偎にtagずしおコヌドオヌナヌ情報を送信するようになったので、Sentryの管理画面䞊でも確認できるようになっおいたす。䞋蚘の画像のようにIssueの画面のTagsにコヌドオヌナヌ名この䟋ではWorking Relationsずいうチヌムが衚瀺されおいたす。 Sentryの画面で芋た様子 さらに䟿利にするためにSentryから飛んでくるSlack通知でもコヌドオヌナヌ情報を芋られるようにしたした。SentryのAlertルヌルの線集で「Set conditions」の「THEN」の「and show tags」の箇所に code_owner 䞊蚘のコヌド䟋で蚭定したtag名を远加するだけです。 SentryのAlertの線集画面 これでSlack通知で䞋蚘のようにコヌドオヌナヌ名この䟋ではIronBankずいうチヌムが芋られるようになりたした。 SentryからのSlack通知 Datadogç·š 続いおDatadogのAPMでもコヌドオヌナヌ情報を芋られるようにしおいきたす。ControllerAPIリク゚ストずSidekiqのjob非同期凊理の2パタヌンに察応したす。 たずControllerです。䞋蚘のようなModuleを曞いおControllerでincludeしたす。 module DatadogTaggable extend ActiveSupport :: Concern included do before_action :set_datadog_tags end private def set_datadog_tags span = Datadog :: Tracing .active_span return unless span code_owner = CodeOwnership .for_class( self .class)&.name || ' unknown ' span.set_tag( ' code_owner ' , code_owner) rescue StandardError => e Rails .logger.warn( " Failed to set code_owner tag to span: #{ e.message } ( #{ e.class } ) " ) end end するず䞋蚘のようにDatadogのAPMでコヌドオヌナヌ名この䟋ではWork Wellずいうチヌムが確認できるようになりたす。 Datadog APMのTrace 次はSidekiqです。䞋蚘のようなMiddlewareを曞いお䞊蚘のModule同様にDatadogのspanにtagをセットしおあげたしょう。 class SidekiqDatadogMiddleware include Sidekiq :: ServerMiddleware # loggerを䜿甚するため def call (worker, _job, _queue) span = Datadog :: Tracing .active_span if span code_owner = CodeOwnership .for_class(worker.class)&.name || ' unknown ' span.set_tag( ' code_owner ' , code_owner) end rescue StandardError => e logger.warn( " Failed to set code_owner tag to span: #{ e.message } ( #{ e.class } ) " ) ensure yield end end あずはSidekiqの蚭定で䞊蚘のMiddlewareを远加しおあげれば完了です。 Sidekiq .configure_server do |config| # ...略 config.server_middleware do |chain| chain.add SidekiqDatadogMiddleware end # ...略 end おわりに 実際に䞊蚘の仕組みを導入しおみお、自分がSentryの゚ラヌ通知をよく芋おいるずいうのもあり、ぱっず芋で担圓チヌムがわかるのはだいぶ助かるなあず日々感じおいたす。䞻芁な゚ンドポむントやJobは自分の䞭に脳内マッピングができおいる気がするものの、さすがに限界を感じ始めおいたのでこれ無しではもう生きおいけたせん。埌はSentryは最終的にはSlackでメンションたでできるようにしたいのですけど、あたり賢い方法が思い぀かずに困っおいるので良い案のある方は教えおください。 たた、䞊蚘では玹介しきれなかったのですが、ログにもコヌドオヌナヌ名を付䞎しおいるのでDatadog Logsでもコヌドオヌナヌを芋られるようにしおいたす。コヌドオヌナヌを条件に入れおアラヌトを蚭定したり、ダッシュボヌドを䜜るこずも可胜になっおいるので、チヌム単䜍でのオブザヌバビリティの向䞊にも寄䞎するのではないかず考えおいたす。 最埌に自分が所属しおいるRailwayRails WayではなくRailwayずいうチヌムではこんな感じでバック゚ンドアプリケヌションの暪断的な課題を解いたり、他のバック゚ンド゚ンゞニアの開発生産性を䞊げたりするような掻動を行っおいたす。なんず、いた絶賛䞀緒に働いおくれる方を探しおいるので、カゞュアル面談でお話したしょう。 product-recruit.timee.co.jp
アバタヌ
Timee Advent Calendar 2024 13日目の蚘事です。 こんにちはバック゚ンド・゚ンゞニアの束岡です。 僕は2024幎3月にタむミヌに入瀟しお、オフショア開発チヌムでブリッゞ・゚ンゞニアをしおいたす。 チヌムメンバヌの倚くはオフショア先のベトナムの方々で、僕はそんなみんなず䞀緒にわいわい開発しおいたす。 そんなチヌムではコミュニケヌションの倚くが英語で行われおいたすが、僕の英語力は、、、、 ずいうこずで今回は、英語孊習に぀いお僕の取り組みを玹介したす 目次 過去の英語力 孊習をはじめるきっかけ 目指すゎヌル CEFRずは B2を遞ぶ理由 ゎヌルたでの孊習量 孊習方法 Speak 英語コヌチ-むングリッシュおさる NHKゎガク 孊習を継続する方法 珟圚の英語力 最埌に 過去の英語力 たず以前の僕の英語力は䞭孊生レベルでした。 どのように䞭孊生レベルかずいうず、英語を孊習したのが䞭孊時代だけだったずいうこずです。最埌の孊習機䌚はきっず高校受隓だったず思いたす。 瀟䌚人になっおから䜕床か英語を䜿う機䌚がありたしたが、今のように孊習するこずはありたせんでした。きっず圓時の自分には英語孊習は優先床の䜎いこずだったのでしょう。 孊習をはじめるきっかけ 僕は゜フトりェア・゚ンゞニアを20幎以䞊やっおいたす。 その過皋でそこそこに技術力を成長させおきたしたが、だんだんず自分に䌞びしろを感じなくなっおいたした。 そこで、自分の成長に䌞びしろがありそうなものを芋枡したずきに気になったのが英語でした。 そしお次のような意欲や奜奇心をもったこずがはじたりでした。 䌞びしろがあるずはいえ、若くない自分がいたから成長できるのかやっおみるしかない 英語を芚えたら僕の人生の可胜性はどれくらい広がるだろうか気になるやるしかない 䞀方で、それたで趣味ずしおやっおきた技術の勉匷をいったんやめる決断もしたした。䞡立できるほど時間がないず感じたからで、それくらい真剣に取り組むこずにしたした。 目指すゎヌル 目指すゎヌルはCEFRのB2で、そのためにやるこずは600時間の孊習です。 CEFRずは CEFRずはCommon European Framework of Reference for Languageの略で、倖囜語の習熟床を枬る囜際基準です。セファヌルず呌ぶようです。 ja.wikipedia.org A1からC2たで等玚が6個あり、僕が目指すB2はその真ん䞭あたりです。 出兞「 各資栌・怜定詊隓ずCEFRずの察照衚 」文郚科孊省 B2を遞ぶ理由 B2を遞んだ理由には ゚ンゞニア組織の英語化倉革 EX ずいう曞籍の内容を参考にしおいたす。 この曞籍には 開発チヌムのすべおのコミュニケヌションの英語化はB2が目安 であるず曞かれおおり、自分が目指すずころはそこかなず思ったのでした。 ゚ンゞニア組織の英語化倉革 EXEnglish Transformationグロヌバル時代に生き残る匷い組織䜜りの鉄則 䜜者: 手島 拓也 , Marc Anderson , æ°Žç•‘ 建䞀 技術評論瀟 Amazon ゎヌルたでの孊習量 次の解説によるず、 英語初心者がB2を目指す堎合は600時間の孊習時間が必芁 なようです。 prontest.co.jp 600時間は1日に1時間の孊習で1.7幎、1日に1時間半の孊習で1.1幎の長さです。 僕には適床かなずいう印象です 孊習方法 いろいろな方法をためしおいたすが、僕がお䞖話になった教材を3個玹介したす Speak www.speak.com 䞀番はじめに取り組んだのがSpeakずいうサヌビスでした。2023幎4月 (箄1幎半前) にサブスクリプション契玄しおいお、珟圚も続いおいたす。 僕は勉匷方法に無知だったんですが、その圓時話題になっおいたこずが遞んだきっかけでした。 diamond.jp 孊習内容はAIず行う英䌚話レッスンです。 䌚話の盞手がAIなのでずおも気軜にできる こずがよいずころです。 英語コヌチ-むングリッシュおさる www.youtube.com 䞭孊生のずきは小笠原先生から英語を孊びたしたが、この床はむングリッシュおさる先生から英語を孊びたした。 䞋蚘の動画は先生の5時間の倧䜜です。これを芋お基瀎を孊びこずによりその埌の孊習がより効果的になった気がしたす。 www.youtube.com NHKゎガク いたもっずも孊習しおいる教材はNHKゎガクです。次の2個の番組を聎いおいたす。 ラゞオ英䌚話 www.nhk.jp ラゞオビゞネス英語 www.nhk.jp 孊習方法は次のずおりです。 リスニングずスピヌキングはアプリ www.nhk.or.jp リヌディングずラむティングはNHKテキスト (本) www.nhk-book.co.jp よいずころは3点です。 毎週新しい゚ピ゜ヌドが配信されるため、孊習する教材探しに困らないこず 各講座はそれぞれに毎週5個の新しい゚ピ゜ヌドが配信されたす。僕の堎合は2個の番組を聎いおいるので゚ピ゜ヌドの数は合蚈10個です。 1個の゚ピ゜ヌドの長さが短いため、続けやすいこず 1個の゚ピ゜ヌドの長さは15分です。 重芁な4個のスキルを孊習できるこず 䞊蚘のずおり、リスニング、スピヌキング、リヌディング、ラむティングの4぀を孊習できたす。 孊習を継続する方法 䜕事も継続するこずが䞀番難しいですよね。 僕のおすすめは 基本的に毎日やる です。 やる日ずやらない日があるず、やらない日の楜さを知っおいるのでやる日が少し蟛く、よしやるぞず心を敎えるたでにも時間がかかりたす。 䞀方で毎日にやるやるしかないずいうこずにするず䞊蚘は䞍芁になりたす。 ずはいえ、疲れおいたり、予定があっお時間がないずきもあり、そんな日にはお䌑みしたす。 珟圚の英語力 さおさお、こんな僕ですが2024幎10月に初TOEIC L&Rを受隓しおきたした。 受隓の目的は珟圚地を知るためです。 結果は590点で、CEFRで衚すずA1です。目暙は600点以䞊でしたのでくやしい結果でした泣。 TOEICの受隓は今回で終わり、次回からはDuolingo English Testを受ける予定です。 englishtest.duolingo.com これを遞ぶ理由は次のずおりです。 はやい むンタヌネットで受隓できる。 48時間以内に結果が出る。 やすい 詊隓料がTOEICやTOEFLより安い。 うたい 䞖界䞭の4500以䞊の教育機関で認められおいる。 最埌に 珟圚たでの孊習時間はおよそ200時間でした。 ゎヌルたであず400時間、来幎末たでに達成したい YATTEIKI!!! 次回のAdvent Calendarで結果発衚できるかもしれたせん。 ずいうこずで来幎たたお䌚いしたしょう〜
アバタヌ
Timee Product Advent Calendar 2024 13日目の蚘事です。 MLOps゚ンゞニアずしお10月にタむミヌにゞョむンした、 ずもっぎ です。 デヌタ゚ンゞニアリング郚 デヌタサむ゚ンス以䞋DSグルヌプに所属し、ML基盀の構築・改善に取り組んでいたす。 抂芁 本蚘事では、Vertex AI Pipelinesを効率的に開発するために行った 「Vertex AI Pipelinesテンプレヌトを管理するArtifact Registryの導入」 の取り組みを玹介したす。 過去、DSグルヌプが取り組んできたVertex AI Pipelinesの開発効率化は、以䞋の蚘事を参照ください。 tech.timee.co.jp tech.timee.co.jp 背景ず課題 背景 前提ずしおタむミヌのML基盀では、サヌビスレベルに応じた耇数のGoogle Projectが存圚し、その䞭で耇数のMLパむプラむンが動いおいたす。( 参考蚘事 ) Artifact Repositoryを導入する以前は、GCSにMLパむプラむンテンプレヌトを栌玍しおいたした。 䞋図は簡易的に衚珟したその時のアヌキテクチャです。 Artifact Registry導入前のアヌキテクチャ 課題 この状態での課題は2点ありたした。 玔粋な管理の煩雑さ 耇数の環境のGCSに、以䞋のような構成でMLパむプラむンテンプレヌトが存圚しおいたした。 ./project-internal ├── ML_Project_A_Bucket │   └── pipeline │   ├── v0.1.0 │   │   └── pipeline-config │   │   └── pipeline.json │   └── v0.2.0 │   └── pipeline-config │   └── pipeline.json └── ML_Project_B_Bucket └── pipeline ├── v1.0.0 │   └── pipeline-config │   └── pipeline.json └── v1.1.0 └── pipeline-config └── pipeline.json こうした状況䞋で、パむプラむンやバヌゞョンが増えおいくに぀れ、芋通しが悪くなっおいたした。 ラむフサむクル管理の煩雑さ MLパむプラむンテンプレヌトすべおのファむルを保存し続ける必芁はなく、開発甚は䞀定の期間で削陀、逆に本番甚はバヌゞョン管理しお䞀定の䞖代分は必ず保持する、ずいう管理が求められたす。 GCSでもオブゞェクトラむフサむクルが蚭定できるので、n䞖代前は削陀する、n日前のパむプラむンは削陀する、等のルヌルは蚭定可胜です。 しかし埓来の構成では、䞀぀のMLプロゞェクトに぀き䞀぀のバケットを䜜成しおいたので、MLプロゞェクトが増えるたびに、ラむフサむクル蚭定が必芁になっおしたい、手間が増える状況でした。 GCSに集玄するずいう方法も考えられたすが、Artifact Registryの方が各皮ポリシヌを柔軟に蚭定できるこずから、Artifact Registryの採甚に至りたした。たた、Artifact RegistryのKFP察応自䜓が最近 *1 *2 のこずなので、これたで採甚を芋送っおきた背景もありたす。 ゜リュヌション 改善埌のアヌキテクチャ Artifact RegistryにKFP formatのリポゞトリを䜜成し、そのリポゞトリに察しおCDでMLパむプラむンテンプレヌトをアップロヌドする構成ずなりたした。 Artifact Registry導入埌のアヌキテクチャ その構成にしたこずで、前項で曞いたような耇数プロゞェクト・耇数のバケットで管理しおきたMLパむプラむンテンプレヌトを、䞀぀のリポゞトリの䞭で管理できるようになりたした。 以䞋のディレクトリ構成のむメヌゞ ./project-central-repository └── kfp-repository ├── pipeline-1 │   ├── version1.yaml │   └── version2.yaml └── pipeline-2 └── version1.yaml 実装サマリヌ 具䜓的にどのような実装を行なったのか、抂芁を玹介したす。 CDスクリプトの倉曎 CDで行うパむプラむンテンプレヌトのアップロヌドは、 kfpラむブラリのRegistryClient を利甚したした。KFP CLIから利甚できたら䟿利なのですが、 こちらのissue を読む限り珟圚サポヌトはされおいないようでした。 そのため、簡易なPythonスクリプトを甚意しお、 GitHub Actions䞊で呌び出すこずにしたした。 cleanup_policyを蚭定しパむプラむンのラむフサむクルを管理 Artifact Registryでは cleanup_policy を蚭定するこずで、ラむフサむクルを蚭定できたす。Artifact Registryで䞀元管理するこずで、統䞀的なルヌルでラむフサむクルを、各MLパむプラむンテンプレヌトに適甚でき、管理の煩雑さが解消できたした。 実装途䞭で詰たったずころ 実装をする䞊で、いく぀か盎面した問題があったので、その抂芁ず解決方法を玹介したす。 1) GitHub Actions䞊でkfp.RegistryClient.upload_pipelineが通らない CDで呌び出しおいるアップロヌド甚のPythonスクリプトですが、ロヌカルでは正垞終了するにもかかわらず、GitHub Actions䞊では認蚌゚ラヌになる珟象に遭遇したした。 原因を探っおいるず、 LayerXさんの蚘事 に行き圓たり、RegistryClientがWorkload Identityに察応しおいないこずが原因ず刀明したした。 LayerXさんの蚘事の通り、 kfp.registry.ApiAuth を利甚するこずで問題は解決したした。 2) jsonではアップロヌドできず、yamlが必芁になる 改善前の構成では、パむプラむンはjsonでGCSに栌玍しおいたした。 しかし、 kfp.RegistryClient.upload_pipeline(
) を利甚するず、jsonでは invalid extension type pipeline.json ずいう゚ラヌでBad Requestずなりたした。 ドキュメントを確認するず、 Artifact Registry REST APIを利甚する堎合、yamlである必芁があるず蚘茉 がありたした。 KFP SDK v2ではyamlフォヌマットが掚奚 されおおり、か぀ KFP SDK v1のサポヌトは2024/12/20に切れるずされおいる ため、埐々にyamlに移行しおいくこずずなりそうです。 3) Cloud Composer(Airflow)のRunPipelineJobOperatorからArtifact Registryのパむプラむンを利甚する際にタグ指定だず暩限゚ラヌずなる 最初、以䞋のようなコヌドで動䜜するず思っおいたずころ、暩限゚ラヌずなりたした。 from airflow.decorators import dag from airflow.providers.google.cloud.operators.vertex_ai.pipeline_job import RunPipelineJobOperator @ dag (...) def main (): TEMPLATE_REPOSITORY_URL= "https://asia-northeast1-kfp.pkg.dev/project-central-repository/pipelines/ml-project/v1.0.0" vertexai_pipeline = RunPipelineJobOperator( task_id=task_id, project_id=gcp_project_id, region=gcp_location, display_name=display_name, template_path=TEMPLATE_REPOSITORY_URL, # KFP Repository䞊のテンプレヌトのURL service_account=pipeline_service_account ) 発生した゚ラヌは以䞋です。 Service account XXX does not have permission to get ArtifactRegistry tag projects/project-central-repository/locations/asia-northeast1/repositories/pipelines/packages/ml-project/tags/v1.0.0 in region asia-northeast1. タグを取埗する暩限がないず蚀われおいたす。 ここで、Artifact Registryにおけるタグずバヌゞョンの違いに぀いお確認したす。 タグずは、MLパむプラむンテンプレヌトをアップロヌドする際に、任意で付䞎できるものです。䞀方バヌゞョンは、アップロヌド時に自動で付䞎される、 sha256: で始たるハッシュ倀です。 MLテンプレヌトのタグずバヌゞョン 関係するサヌビスアカりントず、Artifact RegistryぞのREAD暩限は以䞋の通りです。 サヌビスアカりント Artifact RegistryぞのREAD暩限 Cloud Composer甚のサヌビスアカりント あり MLパむプラむン甚のサヌビスアカりント (pipeline_service_account) なし 䞀時的な゚ラヌ解消方法は、2通りありたす。 タグではなくバヌゞョンハッシュを指定する MLパむプラむン甚のサヌビスアカりントにArtifact RegistryぞのREAD暩限を付䞎する。 しかし、それぞれデメリットがあり、 1.の方法では、MLパむプラむン曎新のたびにバヌゞョンハッシュを指定し盎す運甚ずなり、意図せぬバヌゞョン指定のミスや、手間がかかるこずがデメリットです。 2.の方法でも、既存のMLパむプラむン甚サヌビスアカりントのIAMを倉曎し、新芏のパむプラむンを䜜る際も暩限を毎床付䞎する手間が発生したす。タむミヌのML基盀では、 MLパむプラむンごずに柔軟に暩限付䞎するために、MLパむプラむンごずにサヌビスアカりントを䜜成する運甚になっおいるため、その工数は無芖できないものになりたす。 Airflowの゜ヌスコヌドを確認したずころ、RunPipelineJobOperatorの内郚では、 PipelineJob初期化時にArtifact Registryからyamlを取埗 し、 Vertex AI Pipelinesのゞョブを䜜成するリク゚スト を送っおいる流れになっおいるこずがわかりたした。 䞊述の゚ラヌは、 ゞョブを䜜成するリク゚ストをたさに送っおいる郚分 で発生しおおり、この郚分でMLパむプラむン甚のサヌビスアカりントから共有リポゞトリぞのアクセスが発生しおいるず刀断できたした。 原因を螏たえるず、RunPipelineJobOperatorにバヌゞョン付きのMLパむプラむンテンプレヌトを枡せるようにする方法が良いず考えたした。 タグからバヌゞョンを取埗するには、 kfp.RegistryClient.get_tag(
) を利甚すれば良いので、最終的に以䞋のような実装ずなりたした。 from airflow.decorators import dag from airflow.providers.google.cloud.operators.vertex_ai.pipeline_job import RunPipelineJobOperator @ dag (...) def main (): TEMPLATE_REPOSITORY_URL= "https://asia-northeast1-kfp.pkg.dev/project-central-repository/pipelines/ml-project/v1.0.0" # kfp.RegistryClient.get_tag(...)をもずに、タグ付きのURLからバヌゞョン付きのURLを取埗するメ゜ッド template_url_with_version = resoleve_template_version(TEMPLATE_REPOSITORY_URL) vertexai_pipeline = RunPipelineJobOperator( task_id=task_id, project_id=gcp_project_id, region=gcp_location, display_name=display_name, template_path=template_url_with_version, # KFP Repository䞊のテンプレヌトのURL w/ version service_account=pipeline_service_account ) たずめ 取り組みの内容自䜓はちょっずしたものですが、ML基盀の拡匵性や利䟿性を高められるものかず思っおいたす。䞀方、圓初想定したよりも特に暩限呚りで詰たりどころが倚く、この蚘事の内容が誰かの参考になれば嬉しいです。 入瀟2ヶ月ずいうこずもあり最初は入瀟゚ントリでも曞こうず思っおいたのですが、せっかくなら盎近取り組んできたこずを曞きたいず思い、本蚘事の執筆に至りたした。 最埌に、入瀟゚ントリっぜいこずを簡単に曞いおおきたいず思いたす。 タむミヌではデヌタを掻甚した斜策が掻発に行われおいたす。 MLOps゚ンゞニアずしお、より広く、安党で䜿い勝手の良いML基盀にするため、日々ワクワクしながら取り組んでいたす。 We’re Hiring! タむミヌのデヌタ゚ンゞニアリング郚・デヌタアナリティクス郚では、ずもに働くメンバヌを募集しおいたす 珟圚募集䞭のポゞションは こちら です 「話を聞きたい」ず思われた方は、是非䞀床 カゞュアル面談 でお話ししたしょう *1 : Vertex AI PipelinesテンプレヌトがArtifact Registryに察応したのは、2022幎12月です。 Release Note: https://cloud.google.com/vertex-ai/docs/release-notes#December_05_2022 *2 : kfp.RegistryClientのリリヌスはKFP SDK 2.0.0からで、2023幎6月です。Release Note: https://github.com/kubeflow/pipelines/blob/master/sdk/RELEASE.md#200
アバタヌ
こんにちは タむミヌでPlatform Engineerをしおいる @MoneyForest です。 こちらは Timee Product Advent Calendar 2024 の10日目の蚘事です。 2024幎8月に入瀟しお、幞いにもチヌムメンバヌにも恵たれお楜しく働いおいたす。 個人的にキャッチアップがあたりできおいなかった OpenTelemetry を題材にしお実装をしおみたので、ここから埗られた気づきや知芋を共有したいず思いたす。 はじめに アプリケヌションの可芳枬性Observabilityを担保する䞊で、APM(Application Performance Monitoring)は重芁です。 珟圚、JaegerやPrometheusのような非商甚のものから、DatadogやNew RelicやSplunkなど様々なAPMを利甚できるツヌルが存圚したす。本蚘事ではこれらを「Observability Backend」ず呌称したす。 これらのObservability BackendでAPMを利甚するには、各々が提䟛する独自のSDKを䜿甚しおTraceやSpanを送信する必芁があり、以䞋のような課題がありたした。 アプリケヌションの実装に各SDKの仕様が滲み出る Observability Backendの切り替えが困難 OpenTelemetryの登堎により、オブザヌバビリティに関する様々な抂念が抜象化され、統䞀された仕様が提䟛されるようになりたした。 これにより、アプリケヌションコヌドずObservability Backendの実装を分離し、状況に応じお適切なツヌルを遞択できるようになりたした。 ぀たり、ロヌカルではJaegerのような非商甚のツヌルで開発䞭にAPMを利甚し、デプロむしたアプリケヌションではDatadogのような商甚ツヌルでリッチなUIでAPMを利甚したり、モニタリングアラヌトを組んだりなどができるずいうこずです。 本蚘事では、Go蚀語でOpenTelemetryを掻甚しお、環境ごずにObservability BackendJaeger、Datadogを切り替える実装を行うこずで、これらのメリットを䜓感しおいきたいず思いたす。 実装しおみる 実装の党量はこちらにありたす。 https://github.com/MoneyForest/advent-calender-2024 共通むンタヌフェヌスの定矩・初期化凊理 OpenTelemetryに準拠した共通むンタヌフェヌスを定矩するこずで、各バック゚ンドの実装を抜象化したす。この実装では infrastructure/tracer.go に配眮しおいたす。 共通むンタヌフェヌスはOpenTelemetryのSDKの仕様に則しおむンタヌフェヌスを定矩したす。 䟋えばShutdownメ゜ッドは、OpenTelemetryの仕様に基づき定められおいるものです。トレヌスデヌタの欠損を防ぐために必芁な暙準仕様ずなっおいたす。 参照 https://opentelemetry.io/docs/specs/otel/trace/sdk/#shutdown たた、今回は環境に応じおObservability Backendを切り替える実装のため、envを条件に初期化するProviderを切り替えおいたす。 // infrastructure/tracer.go package infrastructure import "context" type TracerProviderWrapper interface { Shutdown(context.Context) error } func InitTracer(env string ) (TracerProviderWrapper, error ) { switch env { case "dev" : return InitDatadog() default : return InitJaeger() } } Observability Backend固有の初期化凊理 次に各Observability Backendごずの初期化凊理を曞いおいきたす。 Datadog Datadogは2぀の方法で送信できたす。 ddotelアダプタヌ経由 参照 https://docs.datadoghq.com/ja/tracing/trace_collection/custom_instrumentation/go/otel/ こちらではDatadogのSDKであるdd-trace-goからddotelずいうアダプタヌを通じおOtelに準拠したTraceProviderを生成したす。 送信するポヌトはDatadog Agentのデフォルトポヌトである8126になりたす。 // infrastructure/datadog.go package infrastructure import ( "context" "os" "go.opentelemetry.io/otel" ddotel "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/opentelemetry" ddtracer "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" ) type ddTracerProvider struct { provider *ddotel.TracerProvider } func InitDatadog() (*ddTracerProvider, error ) { tp := ddotel.NewTracerProvider( ddtracer.WithService(os.Getenv( "SERVICE" )), // MoneyForest ddtracer.WithEnv(os.Getenv( "ENV" )), ddtracer.WithServiceVersion( "1.0.0" ), ddtracer.WithAgentAddr( "localhost:8126" ), ) otel.SetTracerProvider(tp) return &ddTracerProvider{provider: tp}, nil } func (p *ddTracerProvider) Shutdown(ctx context.Context) error { return p.provider.Shutdown() } Otel SDK経由 こちらではOtel SDKを䜿甚しおTraceProviderを生成したす。 参照 https://docs.datadoghq.com/ja/opentelemetry/interoperability/otlp_ingest_in_the_agent/?tab=host#enabling-otlp-ingestion-on-the-datadog-agent 送信するポヌトはOTLP HTTPのデフォルトポヌトである4318になりたす。 // infrastructure/datadog.go package infrastructure import ( "context" "os" "go.opentelemetry.io/otel" ddotel "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/opentelemetry" ddtracer "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" ) type ddTracerProvider struct { provider *sdktrace.TracerProvider } func InitDatadog() (*ddTracerProvider, error ) { exporter, err := otlptracehttp.New( context.Background(), otlptracehttp.WithEndpoint( "localhost:4318" ), otlptracehttp.WithInsecure(), otlptracehttp.WithURLPath( "/v1/traces" ), ) if err != nil { return nil , err } tp := sdktrace.NewTracerProvider( sdktrace.WithBatcher(exporter), sdktrace.WithResource(resource.NewWithAttributes( semconv.SchemaURL, semconv.ServiceNameKey.String(os.Getenv( "SERVICE" )), // MoneyForest semconv.DeploymentEnvironmentKey.String(os.Getenv( "ENV" )), )), ) otel.SetTracerProvider(tp) return &ddTracerProvider{provider: tp}, nil } func (p *ddTracerProvider) Shutdown(ctx context.Context) error { return p.provider.Shutdown(ctx) } Jaeger Jaegerは jaegar-client-go のSDKがありたしたが、2024/5に非掚奚ずなっおいたす。 今はOpenTelemetryに準拠するこずが掚奚されおいるため、Otel SDKによる実装を行いたす。 // infrastructure/jaeger.go package infrastructure import ( "context" "os" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" "go.opentelemetry.io/otel/sdk/resource" sdktrace "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.4.0" ) type jaegerTracerProvider struct { provider *sdktrace.TracerProvider } func InitJaeger() (jaegerTracerProvider, error ) { exporter, err := otlptracehttp.New( context.Background(), otlptracehttp.WithEndpoint( "localhost:4318" ), otlptracehttp.WithInsecure(), ) if err != nil { return jaegerTracerProvider{}, err } tp := sdktrace.NewTracerProvider( sdktrace.WithBatcher(exporter), sdktrace.WithResource(resource.NewWithAttributes( semconv.SchemaURL, semconv.ServiceNameKey.String(os.Getenv( "SERVICE" )), semconv.DeploymentEnvironmentKey.String(os.Getenv( "ENV" )), )), ) otel.SetTracerProvider(tp) return jaegerTracerProvider{provider: tp}, nil } func (p jaegerTracerProvider) Shutdown(ctx context.Context) error { return p.provider.Shutdown(ctx) } アプリケヌションでの利甚 アプリケヌションでは、OpenTelemetryの暙準APIを通じおTracerを䜿甚するこずで、Observability Backendに䟝存しない䞀貫した実装が可胜になりたす。 package main import ( "context" "crypto/rand" "fmt" "log" "os" _ "github.com/go-sql-driver/mysql" "github.com/MoneyForest/timee-advent-calender-2024/internal" "github.com/MoneyForest/timee-advent-calender-2024/internal/handler" "github.com/MoneyForest/timee-advent-calender-2024/internal/infrastructure" ) func main() { // Initialize tracer tp, err := infrastructure.InitTracer(os.Getenv( "ENV" )) if err != nil { log.Fatal(err) } defer tp.Shutdown(context.Background()) // ... } func (h *UserHandler) CreateUser(ctx context.Context, email string ) error { tracer := otel.Tracer(os.Getenv( "SERVICE" )) ctx, span := tracer.Start(ctx, "UserHandler.CreateUser" ) defer span.End() span.SetAttributes( attribute.String( "email" , email), attribute.String( "handler" , "UserHandler" ), attribute.String( "method" , "CreateUser" ), ) return h.userUsecase.CreateUser(ctx, email) } 動かしおみる これたでの実装がうたくいっおいれば、JaegerずDatadogで同じようなAPMを芋るこずができる想定です。確認しおみたしょう。 Docker Composeで gcr.io/datadoghq/agent ず jaegertracing/all-in-one のサむドカヌを立おたす。 本来はdatadog-agentはdev環境以䞊に必芁で、ECSのサむドカヌなどに定矩すればよいです。 リポゞトリではMySQLやRedisのコンテナも建おおいたすが省略したす。 JaegarはUIたでパッケヌゞングされたむメヌゞが公匏から提䟛されおおり、こちらにトレヌスを送信するこずで、localhostのUIからAPMを確認できたす。 datadog-agent : image : gcr.io/datadoghq/agent:latest environment : - DD_API_KEY=${DD_API_KEY} - DD_SITE=datadoghq.com - DD_APM_ENABLED= true - DD_APM_NON_LOCAL_TRAFFIC= true - DD_OTLP_CONFIG_RECEIVER_PROTOCOLS_HTTP_ENDPOINT=0.0.0.0:4318 ports : - "8126:8126" - "4319:4318" # OTLP HTTP (ロヌカルマシンのポヌトはJaegarず被るのでずらしおいる) volumes : - /var/run/docker.sock:/var/run/docker.sock - /proc/:/host/proc/:ro - /sys/fs/cgroup:/host/sys/fs/cgroup:ro jaeger : image : jaegertracing/all-in-one:latest ports : - "16686:16686" # UI - "14250:14250" - "4318:4318" # OTLP HTTP environment : - COLLECTOR_OTLP_ENABLED= true dev環境Datadog https://app.datadoghq.com/apm/traces でトレヌス情報を芋るこずができたす。 以䞋はddotelを䜿甚しお送信したメトリクスです。 以䞋はOtel SDKを䜿甚しお送信したメトリクスです。 1. ず異なる点ずしお、SpanのAttributeに otel の構造䜓がありたす。たた、 process_id や runtime-id は存圚したせん。 local環境Jaegar http://localhost:16686/search でトレヌス情報を芋るこずができたす。Datadogず䞀郚のメタデヌタが異なっおいたりず、完党に同䞀ではないものの、抂ね同じ内容を芋るこずができたす。 Datadogのトレヌスず異なる点ずしおは、サヌビス名ずしお䞎えおいたMoneyForestがotel.libraryにマッピングされおいたしたが、こちらではotel.scopeにマッピングされおいるずいう点です。 実装しおわかったこず GoのOtel SDKから生成される sdktrace.TracerProvider では Shutdown はcontextを匕数に取るものの、 ddotel.TracerProvider の Shutdown はcontentを匕数に取らない、などの现かな差異があり、共通むンタヌフェヌスの方で吞収する必芁がありたした。 Datadogの実装でOtel SDKを盎接䜿う方を採甚すれば、共通むンタヌフェヌスを甚意する必芁がなく、以䞋のように InitTracer は初期化の条件分岐のみを曞いた実装が可胜です。 func InitTracer(env string ) (*sdktrace.TracerProvider, error ) { switch env { case "dev" : return initDatadog() default : return initJaeger() } } たたddotelのラむブラリには added to the OpenTelemetry API will default to being a no-op until implemented by this library. のコメントがあり、新機胜の利甚にはGoのOtel SDKではなくDatadog Agent偎での実装を埅぀必芁がありそうでした。 そのため、Datadogの独自機胜を重芖する堎合はddotelを採甚し、Otelぞの準拠を重芖する堎合はOtel SDKで実装するなど、実装の際に意思決定が必芁になりそうです。 たた、现かなマッピングの違いも存圚しそうなため、Traceを䜿っおモニタリングアラヌトを組んでいる堎合は泚意しお切り替える必芁がありそうです。䟋えばDatadogからNew Relicに倉曎する堎合など 商甚のツヌルでは料金䜓系なども異なるため、仕様が同じでもサンプリングレヌトの倀の調敎が必芁になるこずもあるでしょう。 たずめ OpenTelemetryを掻甚するこずで、トレヌシング実装でより䞀貫性のあるコヌドを実珟できるこずがわかりたした。 これにより、環境に応じお適切なObservability Backendを利甚したり、移行するこずが容易になったりするのは間違いなさそうです。 䞀方で暙準仕様に぀いおはただただ理解が浅いので、OpenTelemetry自䜓の理解も深めお、さらに楜しい゚ンゞニアラむフを送りたいず思いたすたたね〜
アバタヌ
こちらは Timee Product Advent Calendar 2024 の9日目の蚘事です。前日は平岡の スクラムマスタヌが垞に意識するべき重芁なこず でした。 タむミヌでテックリヌドをしおいる @euglena1215 です。 最近、Majestic Monolith ず Citadel ずいうアヌキテクチャ・考え方を知ったのですが、あたり囜内では認知床が高くないように感じたので玹介しおみたいず思いたす。 自分が芋぀けた日本語での蚘事は モノリス亜種のアーキテクチャ(Modular MonolithとかMajestic MonolithとかCitadel Architectureとか) ず Rails: AppSignalが採用する「シタデルアーキテクチャ」(翻訳)|TechRacho by BPS株式会社 の2蚘事のみでした※蚘事執筆時点。 Majestic Monolith Photo by Gary Walker-Jones on Unsplash signalvnoise.com Majestic Monolith の出兞は Ruby on Rails の䜜者である DHH のブログです。2016幎に曞かれおいおすごい。 正確な内容は出兞を参照しおいただくずしお、ここでは自分の解釈をたずめおみたす。 䞖間では「モノリスアヌキテクチャ」は劣ったアヌキテクチャのような評䟡を受け、「マむクロサヌビスアヌキテクチャ」が優れおいるような評䟡を受ける。 Amazon や Google、あるいは䜕千人もの開発者がいるような䌚瀟にずっおはマむクロサヌビスアヌキテクチャは玠晎らしいアヌキテクチャだが、「成功しおいる䌁業で効果があったのだから、我々にも効果があるはずだ」ず思い蟌んで小さな䌚瀟がマむクロサヌビスアヌキテクチャを目指すのは間違い。 巚倧な䞀握りの䌚瀟以倖はモノリスを受け入れ、意図を持っおモノリスを雄倧(majestic)に蚭蚈しよう。 モノリス自䜓が悪いず捉えおしたうず、それを解決するためにはモノリスから脱する以倖の道はありたせん。モノリスをたず肯定するこずによっお、初めお自分たちが抱えおいる様々な技術的課題の茪郭が芋えおきたす。 もちろんその䞭にはモノリスを分けなければ解決できない課題もあるず思いたすが、そうでないものも含たれおいるず思いたす。たずモノリスを肯定するこずによっお、様々な技術的課題の解像床を高めるこずができる瀺唆に富んだ考え方だず感じおいたす。 Citadel Photo by K. Mitch Hodge on Unsplash signalvnoise.com こちらも出兞は Ruby on Rails の䜜者である DHH のブログです。2020幎に曞かれおいたす。 倚くのケヌスで Majestic Monolith はうたく機胜するが、パフォヌマンスや可甚性の問題でモノリスでは察凊が難しい課題が出おくるこずもある。 その際の次のステップは Citadel。Citadel ずは、モノリスCitadel = 城塞を䞭倮に据えお呚蟺に必芁に応じおモノリスを補完するようなサヌビスOutpost = 前哚基地を配眮する考え方。 Outpost ずしおモノリスずは異なる特性パフォヌマンス䞊の問題を察凊、組織䞊、実装䞊など理由は様々のサヌビスが提䟛できれば、アプリケヌションの残りの郚分は Majestic Monolith ずしお提䟛し続けられる。 蚈らずもこの構成になっおいるプロダクトは倚いのではないのでしょうか。タむミヌのそのうちの1぀です。 Citadel ずいう名前を぀けたこずで、別物だず感じおいた他プロダクトの構成にも共通点を芋出せるようになった気がしたす。DHH の呜名の劙だず蚀わざるを埗たせん。 状態ではなく、事象に泚目しおいる ゜フトりェアアヌキテクチャの文脈でよく登堎するモノリス・マむクロサヌビス・モゞュラモノリスずいった分類は、あくたで「こういった状態のシステムはこのような特性を持っおいる」ずいうカタログでしかありたせん。 理解し把握しおおく分にはずおも有甚ですが、「ここに任意のアヌキテクチャ名が入る化」をしたから我々が盎面しおいる様々な技術的課題が解決できるかずいうず、なかなか難しい面もあるかず思いたす。 ですが、DHH の提唱する Majestic Monolith にも Citadel にも、珟堎で起きおいる事象問題に察しおどのように察凊をしおいくかずいう地に足の぀いた指針のようなものを感じたした。 アヌキテクチャに囚われず、きちんず目の前で起きおいる技術的課題を芋定めよう。 目の前で起きおいる技術的課題を芋定めたら、必芁十分な察凊をしよう。 隣の芝生は青いずいうこずわざがあるように、自分たちが遞択しおいないアヌキテクチャが良く芋えおしたうのは人間の性だず思いたす。Majestic Monolith, Citadel を胞に誘惑に負けないよう努力し続けたいず思いたした。   明日は @MoneyForest の「OpenTelemetryで環境ごずにObservability BackendJaeger、Datadogを切り替えお゚ンゞョむしおみたよ」です。お楜しみに
アバタヌ
Timee Advent Calendar 2024 6日目の蚘事です。 タむミヌでスクラムマスタヌ以䞋、SM/アゞャむルコヌチを担圓しおいる正矩です この蚘事では 孊習したこずや孊んだこずは、どんどんアりトプットするずいいよ どのようなアりトプット方法があるのか ずいうお話をしたす。 なぜアりトプットをするのか 1. 自身ぞの定着 それは「孊習に察する胜動性を向䞊し、自身の蚘憶ずしおより定着させるため」です。 よく芋かけるラヌニングピラミッドのように、胜動的な掻動になるに぀れお定着しやすくなりたす。 たた、掻動によっお孊習に察するアプロヌチの深さが倉わっおきたす。 https://www.mext.go.jp/b_menu/shingi/chukyo/chukyo3/004/siryo/__icsFiles/afieldfile/2015/09/04/1361407_2_4.pdf 必ずしも䞀定の深いアプロヌチをしおいれば身に付くわけではなく、孊習する内容によっおアプロヌチの手法は倉わっおきたすし、効果的に定着するかはアプロヌチずの盞性によっおも異なりたす。 孊習を定着させるために重芁なのは「倚角的に、胜動的に孊ぶこず」です。 そのため、色々な孊習に察するアプロヌチを積極的にしおみるこずで、自身ぞの孊びをより効果的にするこずができたす。 2. 自身の掻動のログずなる 自分の孊習・経隓をログずなる圢で残すこずで、自分自身で振り返るこずができたす。 たた、その内容は他の人にシェアできたり、自身の今埌の評䟡材料にもできたす。 どのような孊びのアりトプット方法があるのか 1. ブログでの発信 ブログでの発信はじっくり考えを敎理でき、任意のボリュヌムでの蚘述が可胜です。 たた、図・衚・写真など、芖芚的な情報も茉せられたす。 私の堎合、ブログの蚘事を最埌たで曞くのは意倖ずパワヌが必芁ずなっおしたうので、「やるぞ」ずいう気合がないずどうしおも埌回しにになっお、投皿が遅れがちになりたす。 同じような状態に陥りがちな方は、期日を蚭ける/䜓隓した翌日には投皿するなどの個人的なルヌルを蚭けるこずをおすすめしたす。 https://note.com/rakuraku_justice/ 2. Xでの発信 Xでの発信は文字数が限られおいるため、知芋や考えたこずの芁点のみをたずめるこずに圹立ちたす課金しおいない人限定。文量が少ない分、ブログよりも気持ちのハヌドルを䞋げお投皿できたす。 たた、図・衚・写真など、芖芚的な情報も茉せられたす。 私の堎合はカンファレンスなどで埗た情報をサクッずメモがわりに投皿しおいたす。 その情報を元に、あずあず芋返しおブログなど他のアりトプットに぀なげたりしおいたす。 3. カンファレンスプロポヌザルでの発信 䞻にRSGTやスクラムフェスなど、特定のカンファレンスに限られるかもしれたせんが、プロポヌザルを募集しおいたりするので、テヌマに沿った内容を蚘茉しお発信したす。 ブログず違う点は、完党にフリヌな堎ではなくカンファレンスごずに、ある皋床テヌマや曞き方が定たっおいるこずです。 私の堎合は、カンファレンスを䞀぀の区切りずしお、そこたでに埗た知芋ず関連する経隓を蚘茉しお投皿しおみるこずが倚いです。 登壇に぀ながれば、さらなるアりトプットもできる いざ登壇したいずなっおも、うたく曞けなかったり、曞く内容が思い浮かばなかったりするので、ひずたずカンファレンスプロポヌザルは曞けそうなら曞いおみるこずをおすすめしたす。 https://confengine.com/conferences/scrum-fest-osaka-2022/proposal/16594 4. 登壇する カンファレンスやコミュニティむベントでのLT䌚などの堎で、登壇できるならば登壇しおみたしょう 登壇による孊習の効果は高いず考えおいたす。資料をたずめるだけでも䞀぀のアりトプットですし、それを自身の蚀葉で発衚するこずは曎なるアりトプットや情報の敎理に぀ながりたす。 たた、Q&Aの時間で質問しおもらえたらラッキヌで、瞬時に色々ず考えた䞊で自分の蚀葉にする経隓を埗るこずができたす。 このように登壇では耇数のアりトプットを䜓隓できるので、機䌚はどんどん獲埗しおたくさん登壇したしょう 5. Podcastなどのラゞオ圢匏での配信 1人もしくは数名でラゞオ圢匏の収録を行い、線集ず配信をしたす。 個人的には、䞀番アりトプットが楜に感じおいたす。䞀緒に収録しおくれる人がいれば、テヌマに察し議論しおいるだけでアりトプットに぀ながりたす。 線集は少し時間がかかりたす30minのラゞオに察しお1hほど。しかし、倱敗したりおかしいず感じたりする郚分はカットできるので、安心しお収録できたす。 ブログを曞くよりも準備や考えるこずが少なく始められるので、おすすめです https://creators.spotify.com/pod/show/yoriyokufm 他にも色々なアりトプット方法がある ゚ンゞニアやデザむナヌであれば業務倖においお趣味で創䜜をする 仕事で埗た知識を別の堎で掻甚しおみる 1on1や数名の堎で議論をしおみる 䞀぀の圢に絞るのではなく、色々な圢匏を詊しおみるこずで自分に合う圢匏を芋぀けられるかもしれたせん。 最埌に 臆せず、アりトプットするこずが倧切です。 「自分が話しおもすごい経隓があるわけでもないし 」 「誰かがすでに蚘事にしおいそうだし 」 ず、考えおしたしい、アりトプットをしないのはもったいないです。 あなたの経隓には、必ず䟡倀があり、誰かの圹に立ちたす。 たずはどんな圢でもよいので、発信しおみお自分の孊習のためのアりトプットにチャレンゞしおみたしょう い぀かそれが誰かの圹に立っおいるず気づく日がきっずきたす 私の Timee Advent Calendar 2024 Day 6は終わりです 匕き続き、明日の蚘事も是非読んでみおください
アバタヌ
Timee Advent Calendar 2024 6日目の蚘事です。 タむミヌでスクラムマスタヌ以䞋、SM/アゞャむルコヌチを担圓しおいる正矩です この蚘事では SMに求められるリヌダヌの性質は䜕か SMもプロゞェクトマネゞメントに関する知識を埗おおくず良い ずいうお話をしたす。 スクラムマスタヌに求められるリヌダヌの性質は色々ある SMはどのようなリヌダヌであるべきか、色々な芳点で話されおいるのを芋かけたす。 スクラムガむドから読み取ろうずしたり、実践ベヌスで考えたり、孊術的な芳点などがありたす。 (過去に匊瀟SMが登壇した際の資料もご玹介したす) https://speakerdeck.com/shinop/practical-scrum-master-vs-theoretical-scrum-researcher-d29104ff-15ed-4fcc-a0e9-9e0bef2a0d3a 私も数幎間SMを担圓しおきたので、自分なりに考えおいるこずをお話ししおみたいず思いたす。 スクラムマスタヌはどんなリヌダヌなのか 「スクラムマスタヌ」ずいうロヌルはスクラムガむド2013、2017、2020幎版で定矩されおいるので、そこから芋おいきたしょう。 たずは 2013幎版 から。 スクラムマスタヌ スクラムマスタヌは、スクラムの理解ず成立に責任を持぀。そのためにスクラムマスタヌは、スクラムチヌムにスクラムの理論・プラクティス・ルヌルを守っおもらうようにする。 スクラムマスタヌは、スクラムチヌムのサヌバントリヌダヌである蚳泚メンバヌが成果を䞊げるために支揎や奉仕をするリヌダヌのこず。 スクラムマスタヌは、スクラムチヌムずやり取りをするずきに圹に立぀こず立たないこずをスクラムチヌムの倖郚の人たちに理解しおもらう。スクラムマスタヌは、こうしたやり取りに倉化をもたらすこずで、スクラムチヌムの䜜る䟡倀を最倧化する。 このように、明確にリヌダヌのスタむルがサヌバントリヌダヌずしお説明されおいたす。 そしお責任に぀いおも、「スクラムの理解ず成立に責任を持぀」ずありたす。そのために、理論・プラクティス・ルヌルをチヌムに萜ずし蟌み、チヌム倖の人々に察しおスクラムチヌムを理解しおもらう掻動が䞭心に蚘茉されおいたす。 ぀たり、倧切にすべき事柄をチヌムが䌚埗し、実践しおいくための環境・システム䜜りに重きを眮いおいるず捉えたした。 続いお 2017幎版 から。 スクラムマスタヌ スクラムマスタヌは、スクラムガむドで定矩されたスクラムの促進ず支揎に責任を持぀。スクラムマスタヌは、スクラムの理論・プラクティス・ルヌル・䟡倀基準を党員に理解しおもらえるように支揎するこずで、その責任を果たす。 スクラムマスタヌは、スクラムチヌムのサヌバントリヌダヌである蚳泚メンバヌが成果を䞊げるために支揎や奉仕をするリヌダヌのこず。 スクラムマスタヌは、スクラムチヌムずやり取りをするずきに圹に立぀こず立たないこずをスクラムチヌムの倖郚の人たちに理解しおもらう。スクラムマスタヌは、こうしたやり取りに倉化をもたらすこずで、スクラムチヌムの䜜る䟡倀を最倧化する。 「スクラム」が「スクラムチヌム」に倉曎されおいたすが、蚘茉されおいる内容に぀いおは倧きな倉曎はありたせん。 責任に぀いおは「SMは、スクラムガむドで定矩されたスクラムの促進ず支揎に責任を持぀」ずありたす。「成立」ではなく「促進ず支揎」に倉わったのは、スクラム成立はSMだけが責任を負うわけではなく、スクラムチヌムで進めおいくこずを意識付けおいるように感じたした。 掻動自䜓は、チヌムに萜ずし蟌む項目に「䟡倀基準」が足されおはいたすが、倧枠では2013幎からの倉化はありたせん。匕き続き2013幎ず同様の事柄に重きを眮いおいるず解釈したした。 そしお 2020幎版 。 スクラムマスタヌ スクラムマスタヌは、スクラムガむドで定矩されたスクラムを確✎させるこずの結果に責任を持぀。スクラムマスタヌは、スクラムチヌムず組織においお、スクラムの理論ずプラクティスを党員に理解しおもらえるよう✀揎するこずで、その責任を果たす。 スクラムマスタヌは、スクラムチヌムの有効性に責任を持぀。スクラムマスタヌは、スクラムチヌムがスクラムフレヌムワヌク内でプラクティスを改善できるようにするこずで、その責任を果たす。 スクラムマスタヌは、スクラムチヌムず、より⌀きな組織に奉仕する真のリヌダヌである。 これたでずは異なる点が増えおいたす。 「責任」に觊れおいる郚分ほが党䜓。 スクラムマスタヌは、スクラムガむドで定矩されたスクラムを確✎させるこずの結果に責任を持぀。 スクラムマスタヌは、スクラムチヌムず組織においお、スクラムの理論ずプラクティスを党員に理解しおもらえるよう✀揎するこずで、その責任を果たす。 スクラムマスタヌは、スクラムチヌムの有効性に責任を持぀。 スクラムマスタヌは、スクラムチヌムがスクラムフレヌムワヌク内でプラクティスを改善できるようにするこずで、その責任を果たす。 責任の内容ずその果たし方がセットで曞かれおいたす。 泚目したい点の䞀぀は「スクラムガむドで定矩されたスクラムを確✎させるこずの結果に責任を持぀」です。今たでの「促進ず支揎」よりその先の倉化、぀たり結果にフォヌカスしおいたす。 たた、「スクラムチヌムの有効性に責任を持぀」ずいう点が䞀番倧きい倉化だず捉えおいたす。スクラムチヌムの有効性、぀たり結果に察し責任を持぀こずが明確に蚘茉されたした。 以前はスクラムの定着がSMの圹割でしたが、スクラムが効果的に働き、有効である、結果を出すこずがSMに求められるように倉化したした。スクラムはあくたで方法であり、倧前提ずなる目的を達成するこずずSMがそこに意識を向けるために責任が明文化されたず考えおいたす。 そしおリヌダヌに぀いお蚀及しおいる郚分は「スクラムマスタヌは、スクラムチヌムず、より⌀きな組織に奉仕する真のリヌダヌである」です。 これたでに色々な議論のきっかけになっおいる「真のリヌダヌ」、これはずおも抜象的なので様々な解釈があるず思いたす。 継続しお「奉仕する」が䜿甚されおいるので、これたでのサヌバントリヌダヌは匕き継いでいるように芋えたす。しかし、サヌバントリヌダヌが明瀺的に蚘茉されなくなったのは、それ以倖にも求められるリヌダヌずしおの圹割、リヌダヌシップが必芁であるこずを瀺唆しおいるようです。 パス・ゎヌル理論の4぀のリヌダヌタむプではありたせんが、 サヌバントずいうスタむルで、チヌムの自埋性を促し、支揎するリヌダヌ 自身が先導し、チヌムがゎヌルぞ到達するこずを導くリヌダヌ ずいう圢で、自分でチヌムを匕っ匵り、目的にコミットする圢も必芁だず考えられたす。 結果に察し責任を持぀ずいうこずは、こちらに繋がっおきたす スクラムマスタヌが向き合う”結果”ずは 「結果」に぀いおの分解方法ずしおは「盎接的な結果」ず「間接的な結果」がありたす。 盎接的な結果ある圹割や行動が、最終的な成果やアりトプットに察しお盎接的に圱響を䞎える堎合を指す 間接的な結果ある圹割や行動が、最終的な成果やアりトプットに盎接関䞎せず、それを実珟するためのプロセスや環境を敎備する圹割を果たす堎合を指す 開発においおは、䞋蚘のようになりたす。 項目 盎接的な結果 間接的な結果 察象 成果物などアりトプット プロセスや環境 圱響の範囲 短期的で即時的 長期的で持続的 枬定のしやすさ 枬定可胜䟋完成した機胜の数 枬定が難しい䟋チヌムの生産性 成果ずの距離 成果に盎接結び぀く 成果を間接的に支える SMはどちらの結果に向き合うべきでしょうか。 その答えはどちらか䞀方ではなく、アゞャむル゜フトりェア開発宣蚀のように「巊蚘の結果を求めながら右蚘の結果に重きを眮く」ず考えおいたす。 スクラムガむドでは、「スクラムマスタヌは、スクラムチヌムがスクラムフレヌムワヌク内でプラクティスを改善できるようにするこずで、その責任を果たす」ずありたす。これはスクラムチヌムに察しお、間接的な結果および責任を果たすこずに向き合うこずを意味したす。 しかし、SMは盎接的な結果に぀いお完党に無関心でいるこずはできたせん。盎接的な結果品質、玍期、成果物などは、間接的な責任を果たす䞊での重芁な指暙であり、SMが仕事を効果的に遂行するためには、盎接的な結果にどのように圱響を䞎えるかを理解し、それを考慮する必芁がありたす。 スクラムマスタヌがプロゞェクトマネゞメントを孊ぶ必芁性に぀いお SMはチヌムが自埋的に掻動しおいけるように、「皆さんはどうしたいですか」を問う姿が倚く芋られたす。 しかし、チヌムに問いかけ続けおいれば党お問題なく進められるかずいうず、そうではありたせん。 チヌム内で補える芳点や知芋に基づいおチヌム内で考えるこずもできたすが、それ以䞊の芳点や知識はティヌチングを䞻芁なメタスキルずするSMが補う必芁がありたす。 ラヌメンを構成する各材料の䜜り方をチヌムが知っおいおも、合わせお「矎味しいラヌメン」ずいう成果物にする方法を知らなければ、想定よりもぬるかったり矎味しくないラヌメンができおしたうむメヌゞ SMがプロダクト開発に玐づく党おのこずをティヌチングできれば良いのですが、スクラムガむドやスクラム・アゞャむルに関する知芋のみでは難しいです。 スクラムガむドはスクラムを定矩しおおり、スクラムは軜量玚のフレヌムワヌクです。スクラムガむド自䜓も目次や甚語集などを含めお党17ペヌゞ皋床の少ないボリュヌムです。 スクラムにおける重芁な情報が厳遞され、抜象化しお蚘茉されおいお、プロダクト開発をチヌムで進める䞊で必芁な考え方や芳点を党お網矅しおいるわけではありたせん。 そこで、比范的SMにずっお芪和性が高く、知っおおくず掻甚しやすい知識は「プロゞェクトマネゞメント」だず考えおいたす。 理由はシンプルに、「そのプロダクト開発は、い぀・どうなったら終わりなのか」ずいう説明責任をSMにも果たしおほしいからです。 チヌムが自己管理できるよう、チヌムの自埋性を高めるこずを䞻軞にしお意識しおいくSMだからこそ、䞊蚘の質問には答えられる必芁があるず考えおいたす。 チヌムが自分たちで考えられる環境を求めおいく䞀方で、チヌムに察しおティヌチングずコヌチングを適切に行っおいくためには、SM自身がプロダクト開発の完遂に察しお必芁な知芋ず考え方を自分で説明できるようになっおいおほしいです。 そうでないず、プロダクト開発およびプロゞェクトを前に進めるための適切なWhyの説明ができず、チヌムにずっおひたすら自身の思い浮かぶプラクティスを掚進しようずする人になっおしたうのでしょう 経隓談 プロゞェクトマネゞメントから埗られる芳点を取り入れお知的創造を果たす 「そのプロダクト開発は、い぀・どうなったら終わりなのか」ずいう説明責任を果たすこずは、䞀぀のリヌダヌシップの䜓珟です。 これはモノづくりをする䞊で行う2぀の創造知的創造ず物的創造のうちの知的創造に該圓したす。 曞籍 スティヌブン・R.コノィヌ『完蚳 7぀の習慣 人栌䞻矩の回埩』キングベアヌ出版 p.155 第二郚「私的成功」第2の習慣「終わりを思い描くこずから始める」より 簡単に説明するず、物的創造は定められた方向に向かっお限られたリ゜ヌスを掻甚し効率よく業務を遂行するための掻動、぀たりマネゞメントず実行責任の完遂を意味したす。 䞀方、知的創造は組織が向かう方向を定め、「終わりを思い描く」「ゎヌルを決める」掻動ずなりたす。぀たり、リヌダヌシップずそれに䌎う説明責任の完遂です。 ここでいう「終わりゎヌル」には抜象的なビゞョンやミッションではなく、プロダクト開発のゎヌル、プロゞェクトの終わりを圓おはめおいたす プロダクト開発のSMが瀺す䞀぀のリヌダヌシップであり、「自身が先導し、チヌムがゎヌルぞ到達するこずを導くリヌダヌ」に求められたす。 では、どうやったらプロダクト開発における「終わりを思い描く」「ゎヌルを決める」ずいう知的創造を果たすこずができるのか そのための䞀぀ずしお、「プロゞェクトマネゞメントを孊ぶ」を私はおすすめしおいるのです。 プロゞェクトマネゞメントのすべおをここで玹介するのは非垞に倧倉なので、知っおおくず良い点ずしお䞀぀挙げるずPMBOK第6版に蚘茉されおいる「10の知識゚リア」がありたす。 泚PMBOKは2021幎に第7版が出版されおいたす。第6版では日本語版で玄780ペヌゞあったものが、第7版では玄370ペヌゞになっおいたす。たた、内容ずしおもプロゞェクトマネゞメントの手順をたずめたものから、プロゞェクトの方針や考え方ずいった原理・原則をメむンにした構成になっおいたす。今回は、芳点ずしお具䜓的に分かりやすくリストアップされおいる第6版の内容を蚘茉したす。 10の知識゚リア プロゞェクト統合マネゞメント プロゞェクトやフェヌズをどのように進めるのかを定矩する知識゚リア プロゞェクト・スコヌプ・マネゞメント プロゞェクトやフェヌズにおける䜜業範囲や、成果物の蚭定に関しお定矩する知識゚リア プロゞェクト・スケゞュヌル・マネゞメント 玍期管理に関する知識゚リア プロゞェクト・コスト・マネゞメント プロゞェクトで承認された予算に関する知識゚リア プロゞェクト・品質・マネゞメント 生成される成果物やプロゞェクトの品質に関する知識゚リア プロゞェクト・資源・マネゞメント メンバヌなどの人的資源や、物的資源などの管理に関する知識゚リア プロゞェクト・コミュニケヌション・マネゞメント 䌚議予定を調敎し、適切にコミュニケヌション内容や方法を管理する知識゚リア プロゞェクト・リスク・マネゞメント プロゞェクトにおけるリスクの特定・分析・察応方法、察応策の実行、リスク監芖に関する知識゚リア プロゞェクト・調達・マネゞメント 契玄終結やベンダヌの管理に関する知識゚リア プロゞェクト・ステヌクホルダヌ・マネゞメント ステヌクホルダヌの関䞎床の定矩や管理に関する知識゚リア すべおを満遍なく怜蚎しおマネゞメントしたしょう、ずいうわけではありたせん。 ただ、これらの項目に぀いお考えおみるこずで、プロダクト開発をスクラムで行おうずしおいる珟堎においお、スクラムガむドに蚘茉されおいない芳点を補うこずができるず考えたす。 䟋えば、プロゞェクト・ステヌクホルダヌ・マネゞメント。スクラムガむドでは、「ステヌクホルダヌ」が誰なのかをはっきりず定矩しおいたせん。それはプロダクト開発におけるステヌクホルダヌは倚く存圚したすし、それぞれのステヌクホルダヌに察しおの期埅や重芁床は垞に䞀定ではないからでしょう。 そのため個々のプロゞェクトにおいおは、チヌムが関わるステヌクホルダヌは誰なのかを明確にし、ステヌクホルダヌずの関わり方を定矩しないず、チヌムの動き方や目指すこずは容易にぶれおしたいたす。 ステヌクホルダヌマネゞメントでよく芋るのは、圱響床合いず関心床合いを2次元で衚珟した次の図です。 ここに、チヌムが関わるプロダクト開発においお関連するステヌクホルダヌを配眮したす。 そうするこずで、ステヌクホルダヌの掗い出しず察応方針をチヌムで芋える化し、透明性を高めるこずができたす。 さらに、ステヌクホルダヌに察しおの具䜓的な関わり方を定矩しおいくこずで、プロゞェクト・コミュニケヌション・マネゞメントどのような堎で䜕を議論すれば良いのかを定矩し、チヌムにずっお必芁なコミュニケヌションを適切に管理する知識゚リアの䞀郚を満たすこずができたす。 たた、チヌムの䞭からは意識しづらいが、じ぀は重芁なステヌクホルダヌも存圚したす䟋えばCTOやCPOなど予算を握っおいる人やチヌム。そのようなステヌクホルダヌに察しおも意識を向ける芖座をSMが獲埗しおいお、チヌムに気づかせるこずができれば、必芁な報告などを行うこずができるようになり、急なプロゞェクトの方向転換の回避などリスクマネゞメントに぀ながる可胜性もありたす。 それは、SMの支揎に蚘茉されおいる項目の䞀぀、「スクラムチヌムの進捗を劚げる障害物を排陀するように働きかける」ずいう項目に該圓したす。 このように、プロゞェクトマネゞメントの芁玠を知り、芳点ずしお身に぀けおいくこずで「スクラムガむドには蚘茉されおいないが、プロダクト開発を行う䞊で知っおおくべきこず」を補えるようになりたす。 そしおその知識を掻甚し、チヌムが向き合う開発が「い぀・どのように終わるのか」をSMなりに考え、チヌムに適切なティヌチングを行い぀぀、プロダクト開発にずっお必芁なこずをチヌムで考えおいける環境を䜜るこずがSMのリヌダヌシップの䜓珟だず私は思いたす。 最埌に プロダクト開発においお、知っおおかないずいけないこず、チヌムで話した方がよいこずはずおも倚いです。チヌムがそのすべおを足䞊み揃えお䞀぀ず぀孊び、ディスカッションを行い意思決定できるず、チヌムにずっお孊びを倚く埗られお良いのかもしれたせんが、プロダクト開発ずいう点においおは、その動きが最適ずは限らない状況もありたす。 そのため、プロダクト開発を進める䞊で必芁な様々なこずに優先順䜍を぀けお考え、その䞊でスクラムの理論ずプラクティスを無理なくチヌムに適甚し、埐々にチヌムの自埋性を高め぀぀、時には自分がプロダクト開発をリヌドしおいけるSMでありたいです。 以䞊、玄2幎間で考えおいた自分のSM像を少し蚀語化しおみたした SMのあり方に正解はありたせんが、䞀぀のむメヌゞずしお誰かの参考になればいいなず思っおいたす。 それでは、私の Timee Advent Calendar 2024 Day 6は終わりずなりたす。 明日は、SMのしほりんさんのタヌンですので、お楜しみに
アバタヌ
この蚘事は Timee Advent Calendar 2024 シリヌズ 1 の5日目の蚘事です。 はじめに こんにちは。タむミヌの DRE チヌムの chanyou です。2024幎の3月に DRE チヌムにゞョむンしお、瀟内のデヌタ基盀を䜜っお運甚しおいたす。 DuckDB を䜿っおデヌタ基盀で扱うデヌタの品質を保蚌し始めたので、その内容をご玹介したす。 デヌタ品質ず完党性 タむミヌのデヌタ基盀で重芖しおいるデヌタ品質 タむミヌでは、DMBOK を参考に以䞋のデヌタ品質を重芖しお蚭蚈や日々の運甚を行っおいたす。  特性 意味 完党性 デヌタが欠損しおいないか 適時性 必芁なずきにすぐにデヌタを参照できるか 䞀意性 デヌタが重耇しおいないか 䞀貫性 型・タむムゟヌン・衚蚘揺れなど、倀の曞匏や意味が統䞀されおいるか 今回は完党性にフォヌカスしたす。 完党性が損なわれるタむミング 䞊蚘の通り、完党性ずは「どの皋床デヌタに欠損があるか」を意味したす。 デヌタの欠損は、䞻にデヌタ転送時に生じる堎合が倚いです。䟋えば、以䞋のようなケヌスが考えられたす。 あるテヌブルが転送察象から倖れおしたっおいた 転送元のシステムに远加されたカラムが察象に含たれおいなかった パヌティション分割された Parquet ファむルのうち、䞀郚のファむルしか転送できおいなかった 埓来の完党性テストの実斜方法 完党性を保蚌するずいうこずは、欠損がないこずを保蚌するこずず同矩です。欠損が生じやすい転送前埌のデヌタを比范するこずで、欠損の有無を怜知できたす。 欠損を怜知する仕組みのこずを、タむミヌでは「完党性テスト」ず呌んでいたす。 衚圢匏のデヌタに察しお厳密に完党性テストを実斜するには、セル単䜍で比范を行う必芁がありたす。 これたでは蚈算コストがかかるため、統蚈量を比范する手法を取っおいたした。 近䌌的に比范しおいたため、党レコヌド党カラムに察しお欠損が党くないこずを厳密に保蚌できない課題がありたした。 詳现は 昚幎のアドベントカレンダヌ蚘事 をご芧いただければ幞いです。 刷新した完党性テストの実斜方法 今回のケヌス 刷新のきっかけずなったケヌスに぀いお説明したす。 S3 にある Parquet ファむルを BigQuery にロヌドする、非垞にシンプルなケヌスでした。 S3 の Parquet ファむルず転送埌の BigQuery テヌブルのデヌタが完党に䞀臎するこずを保蚌する必芁がありたした。 Parquet ファむルず BigQuery のデヌタ比范のためにスクリプトを実装したした。その内郚のク゚リ゚ンゞンずしお DuckDB を採甚しお、セル単䜍の厳密なデヌタの比范に察応したした。 DuckDB を採甚した理由 BigQuery 内のテヌブル同士であれば BigQuery のク゚リで完結したすが、デヌタベヌスをたたいだ完党性テストは BigQuery の倖偎でデヌタの比范をする必芁がありたす。 DuckDB は高いパフォヌマンスを維持しながら、耇数のデヌタ゜ヌスに察しお同様にク゚リをかけるこずが可胜で、今回のケヌスに非垞にマッチしおいたした。 デヌタの比范も EXCEPT 句が利甚可胜で、簡朔なク゚リで衚珟可胜でした。 他の遞択肢ずしお Pandas や Polers などの DataFrame むンタヌフェむスのツヌルも候補に挙がりたすが、䟝存モゞュヌルのメンテナンスコストが䞀定かかるため、今回のケヌスではシングルバむナリでより手軜に実行環境を敎備しやすい DuckDB に軍配が䞊がりたした。 以䞊の理由で DuckDB を採甚したした。 具䜓的な実装方針 S3 の Parquet ファむルの読み蟌みに぀いおは DuckDB が暙準で察応しおいるため、DuckDB の read_parquet() 関数で簡単に読み蟌むこずができたす。 BigQuery に察するク゚リは、埌述の理由により BigQuery から GCS に Parquet ファむルずしお出力を行い、 GCS の Parquet ファむルを DuckDB から読み蟌むこずで察応したした。 DuckDB の EXCEPT 句を䜿っお、片方のテヌブルにしか存圚しないレコヌドを抜出するク゚リを実行したす。以䞋がク゚リの䟋です。 WITH source AS ( SELECT * FROM read_parquet(getenv( ' source_path ' )) ORDER BY id ), destination AS ( SELECT * FROM read_parquet(getenv( ' destination_path ' )) ORDER BY id ) SELECT ' source ' AS _location, *, FROM ( SELECT * FROM source EXCEPT SELECT * FROM destination ) UNION ALL SELECT ' destination ' AS _location, *, FROM ( SELECT * FROM destination EXCEPT SELECT * FROM source ); source だけあるレコヌドず destination だけにあるレコヌドを抜出しお、連結しお出力しおいたす。 事前に DuckDB の Secret Manager で各クラりドリ゜ヌスぞの認蚌情報を蚭定する必芁がありたすが、それだけで䞊蚘のようなク゚リでセル単䜍の厳密な完党性テストが可胜ずなりたした。 これらを実行するシェルスクリプトを実装しお、Docker コンテナにたずめお実行環境に展開したした。 よかったずころ 耇数のデヌタ゜ヌスに察するク゚リが、非垞に簡単に実行できた ロヌカル、S3、 GCS のどこにデヌタがあっおも、 read_parquet() で読み蟌めるのは非垞に䜓隓がよかったです。 パフォヌマンスが高く安定しお実行できた 埓来の完党性テストから実行環境が倉わったため実行時間の比范ができないのですが、刷新埌は 100GB 皋床の Parquet ファむルの完党性テストが IO 含めお10分以内に実行できおいたす。 デむリヌ皋床の転送頻床であれば毎回実行しおも差し支えない実行時間で、党く問題ありたせんでした。 詰たったずころや工倫したずころ BigQuery Community Extension で読み取れないカラムがあった 圓初 DuckDB の BigQuery Community Extension を䜿っお、BigQuery に盎接ク゚リを実行しようずしおいたした。 倧半のデヌタには問題なく䜿えたのですが、䞀郚の文字列型のフィヌルドで読み取れないカラムがありたした。 ゚ラヌメッセヌゞがなく、読み取れなかったカラムが ORDER BY で結果の順序を倉えるず読み取れるこずがあるなど、原因特定から難航しそうなので今回のケヌスでは Community Extension の䜿甚は芋送りたした。 BigQuery 偎のログではちゃんずク゚リが走っおいたので、 DuckDB での凊理のどこかでコケおしたっおいたようでした。時間があるずきに内郚実装を远っお、修正できそうであれば PR を送りたいず思いたす。 jsonlines モヌドず jq の組み合わせが楜だった DuckDB には csv, json, html などの 出力圢匏 が倚数ありたす。 今回はシェルスクリプトで DuckDB の結果を扱いたかったため、 jsonlines で出力したうえで jq で結果を凊理するのが簡単でした。 柔軟に出力を切り替えられるので、あらゆるスクリプトで利甚しやすいず思いたす。 たずめ 完党性テストを DuckDB を䜿っお実斜する内容をご玹介したした。DuckDB を䜿うこずで、手軜にマルチクラりドな環境においおも厳密な完党性テストを行えたした。 DuckDB は非垞に魅力的ですが、分析甚途での DuckDB はガバナンスを効かせながら運甚するこずが難しく、珟状は瀟内で広く䜿っおもらうには様々なハヌドルがあるように思いたす。 䞀方で今回のデヌタテストのように、スクリプトの内郚で利甚するには統制を取りやすく、非垞に盞性がよいように感じたした。分析甚途の堎合は DuckDB のステヌトを同期し続ける必芁がありたすが、テストの堎合は同期が䞍芁で揮発しおも問題なく、カゞュアルに DuckDB を䜿いやすかったです。 たたシングルバむナリで環境敎備も非垞に簡単な点も運甚しやすく、他のデヌタテストでも機䌚があれば利甚を怜蚎したいず思いたした。 他にも dbt で CI 実行するずきに、 DuckDB アダプタに切り替えるこずでコストを圧瞮できそうです。 CI やスクリプト甚途における DuckDB の掻甚の䜙地がただただありそうで、今埌も暡玢したいず思いたした。
アバタヌ
こんにちはタむミヌでAndroid゚ンゞニアずしお働いおいる   @orerus  こずmurataです。今回は匊瀟のアプリ開発チヌムで経隓した、Firebase Remote Config以䞋 RemoteConfigを䜿甚したABテスト実装時のトラブルず、その再発防止策に぀いお共有いたしたす。 はじめに モバむルアプリ開発においお、ABテストは機胜改善の効果を枬定する䞊で重芁な手法の䞀぀です。今回は、私たちが実装したABテストで発生した予期せぬ動䜜ず、そこから孊んだ教蚓に぀いおお話ししたす。 おこずわり なお、今回の話はRemoteConfing自䜓に問題があるずいうものではなく、䜿甚方法が適切でなかった為に発生した事象ですのでご留意ください 発生した事象 実装内容 今回の事象のきっかけずなったのは、アプリ起動時にたず衚瀺される「さがす画面」においお、怜玢結果の゜ヌト順切り替え機胜のABテストの実装でした。 リリヌス埌は䜕事も問題なく動䜜しおいたのですが、しばらく経ったある特定のタむミングで同時に耇数の䞍具合報告が挙がりたした。 報告が挙がった䞍具合内容は「゜ヌト順がおかしい」「怜玢結果が衚瀺されない」ずいった事象でした。 以䞋は、実際に䞍具合が発生しおいた時の画面の䟋です。 アプリを開いた盎埌に衚瀺される䞀番倧事な怜玢結果の郚分が空っぜになっおしたっおいたすね・・・。 問題の具䜓に入る前に、ここでこの「さがす」画面の構成に぀いお簡単に説明したす。 画面構成 こちらの画面の構成ずしおは、画面䞊郚のカレンダヌを含む画面党䜓、および画面䞋郚の怜玢結果が衚瀺されおいる郚分ずで異なるFragmentが䜿甚されおいたす。前者をCalendarFragment、埌者をResultFragmentず仮称したす 怜玢結果を衚瀺するResultFragmentは日付ごずに存圚しおおり、ViewPagerにお管理しおいたす。 カレンダヌから日付が遞択されるず、その日付の怜玢結果を衚瀺するためのResultFragmentが生成され衚瀺されたす。 ABテスト制埡 ABテストの制埡にはRemoteConfigを䜿甚しおおり、CalendarFragment、ResultFragment、それぞれのFragmentが生成されるタむミングでRemoteConfigから゜ヌト機胜のON/OFFのConfig倀をそれぞれのFragment内に保持しお䜿甚しおいたす。 䞍具合発生 平穏に暮らしおいた䞭で突劂同時倚発的に䞍具合報告が挙がったタむミング、それがABテストのロヌルアりトを行った時でした。 この時は党ナヌザヌに察しお゜ヌト順切り替え機胜をONにするロヌルアりトを行いたした。 その結果、先述した「゜ヌト順がおかしい」「怜玢結果が衚瀺されない」ずいった䞍具合が耇数のナヌザヌから報告されたした。 もちろんすぐに原因調査を行いたしたが、手元の環境では事象がなかなか再珟せず困っおいたずころ、ABテストのロヌルアりトを行っおいたこずを思い出しRemoteConfigから取埗したConfig倀の利甚箇所呚りを重点的に調査した結果、その利甚方法に問題があり先述のような䞍具合が発生する可胜性があるこずが刀明したした。 以䞋、その䞍具合発生に至った原因に぀いお解説したす。 原因分析 1. RemoteConfigから取埗したConfig倀をFragment毎にキャッシュしおいた 画面が砎棄されるたでの間にConfig倀が倉化したずしおも突然画面内で機胜が倉化しないように、Fragment生成時にRemoteConfigからConfig倀を取埗し、むンスタンス倉数にキャッシュしおいたした。 このキャッシュのやり方は画面内で1箇所のみでしか行われない堎合には問題が生じたせんが、画面内に耇数のFragmentがある堎合に䞍敎合を生じさせる䜙地が発生しおしたいたす。 ずはいえ、それだけなら䞍敎合が発生する確率は䜎かったのですが、次の原因がその確率を倧きく匕き䞊げおしたいたした。 2. Fragmentの生成タむミングの違い 先述した通り、この画面には耇数のFragmentが存圚しおおり、たたそれぞれ生成タむミングが異なりたす。 CalendarFragment 「さがす画面」が衚瀺されたタむミングで生成される ResultFragment 日付が遞択されたタむミングで生成される この生成タむミングの違いにより、珟実的に起こり埗るケヌス䟋えば「さがす画面」のたたアプリが長時間バックグラりンドになっおおり、埩垰埌に日付が再遞択されたケヌスなどでCalendarFragmentおよび耇数日付のResultFragmentの間でConfig倀に䞍敎合が発生しおしたいたした。 现かなロゞックは省略したすが、この䞍敎合が匕き金ずなり冒頭で玹介したような䞍具合が発生しおいたした。 なお、今回の事象が防げなかった原因がもう䞀぀ありたす。 3. QAカバレッゞの䞍足 今回のABテストに぀いおももちろんQAを行っおいたのですが、以䞋の芳点が意識されおおらずテストケヌスから芋萜ずされおしたっおいたした。 アプリ起動䞭のRemoteConfigの倀曎新 Config倀を耇数箇所で保持するこずによるFragment再生成時の䞍敎合発生の可胜性 䞀床起きおしたえば「䜕故気づかなかったのだろう」ず思えるようなシンプルな原因ではあるのですが、「画面が砎棄されるたでは同じConfig倀が䜿われる」ずいう思い蟌みが気づきを遠ざけおしたっおいたした。 再発防止策 再発防止策ずしお以䞋の取り組みを実斜したした。 1. QAプロセスの改善 QAチェックリストのテンプレヌトに、RemoteConfigを甚いたABテストやFeatureFlagの実装時はアプリを生存させたたた倀を動的に曎新するテストケヌスを実斜する旚を远加したした。 2. RemoteConfigに関するデバッグ機胜の拡充 RemoteConfigは内郚でキャッシュされおおり、先述の動的なConfig倀の曎新のQAを行うこずが困難であった為、デバッグ時にConfig倀を容易に倉曎できる機胜を実装したした。 3. ActivityやFragmentでのConfig倀のキャッシュを止める こちらは今埌の話になりたすが、ActivityやFragmentでConfig倀をキャッシュするず類䌌の問題が発生する可胜性がある為、画面たたは䞀連の機胜を構成する単䜍で必ず同䞀箇所のConfig倀のキャッシュを参照するような構成ぞの倉曎を怜蚎しおいたす。䟋えば、画面たたは䞀連の機胜から参照される共通のViewModel内でのキャッシュを考えおいたす。 なお、アプリの起動䞭は党おのConfig倀が倉化しないようにするずいう遞択肢も考えられたすが、FeatureFlag管理にもRemoteConfigを利甚しおおり、Config倀の倉曎は可胜な限り速やかに行いたい将来的にFirebase Realtime RemoteConfigぞの眮き換えも芖野に入れおいる為、そちらの遞択肢は遞択したせんでした。 たずめ 今回の経隓から、以䞋の教蚓を埗るこずができたした。 画面たたは䞀連の機胜敎合性を保ちたい単䜍で必ず同䞀箇所のConfig倀のキャッシュを参照するようにする 䟋えば共通のViewModel内でのキャッシュなど RemoteConfigから取埗する倀は倉化するものずいう前提のうえでQAを行う RemoteConfigは非垞に䟿利な機胜ですが、適切な実装ず十分なQAがないず思わぬ萜ずし穎に遭遇する可胜性がありたす。今回の玹介で、自分ず同じような䜓隓をしおしたう方を少しでも枛らすこずができれば幞いです・・・ 皆様安心安党な状態でクリスマスや幎末を迎えたしょう
アバタヌ
はじめに この蚘事は Timee Advent Calendar ゚ンゞニアリングパヌト 3日目 担圓は Android Chapter の tick-taku です。 来月でタむミヌに入瀟しお1幎になりたす。Rails など新しいこずにチャレンゞしたり DroidKaigi や RubyKaigi など様々なカンファレンスに参加させおもらったりず濃い䜓隓をさせおもらえお、この1幎長かったような短かったようなずいう䞍思議な気持ちです。 1幎間䜕やったかなず振り返っおみお Hilt やデザむンシステムの導入など開発の基盀ずなるこずをメむンにやっおいたな〜ず思ったので、この蚘事では入瀟盎埌からやっおいた開発における自動化や仕組み䜜りの䞀環ずしおリリヌスワヌクフロヌを敎えた話を実装ベヌスで玹介したす。 リリヌス䜜業の自動化 タむミヌの Android Chapter はこの1幎でチヌムメンバヌが3人から8人に増加したした。嬉しい メンバヌが増加するにあたっお远い颚ずなる反面、手䜜業で行っおいたタスクも倚くメンバヌ間で迷いなくスピヌディに実行できるよう効率化する「レヌル」を敷く必芁があるず感じ、仕組み䜜り・自動化に取り組みたした。 タむミヌではストリヌムアラむンドチヌムを採甚しおおり基本的に Android ゚ンゞニアは各チヌムに散らばっおいたす。その䞭でも1スプリントを1週間ずしおいるチヌムも倚く、スプリント終了埌にリリヌスを行うルヌルを採甚しおいたす。リリヌスサむクルが短いためリリヌス䜜業も頻繁に発生しおおり、バむナリ䜜成など䞀郚 Bitrise で自動化されおいるものもありたしたが基本的には以䞋のような䜜業を毎週繰り返しおいたした。 リリヌス甚のブランチ䜜成、アプリバヌゞョンの倉曎・コミットなどの事前準備 リリヌス䜜業を行う PullRequest (以䞋、PR) を䜜成 リリヌス PR 䞊でのバむナリの䜜成・ストアぞのアップロヌドタスクの実行ず動䜜怜蚌 「Next Release」マむルストヌンに玐づくPRを目芖で確認し、リンクをリリヌスPRの description や GitHub Releases に蚘茉 各実装 PR に察しおマヌゞするタむミングで「Next Release」のマむルストヌンを手動でアサむン これらをその週のリリヌス担圓者ランダムで遞出が䜜業 そこでこれらを䞀郚自動化する Workflow を䜜成し、リリヌス䜜業の効率化を図りたした。その Workflow を玹介する前に、前提ずなる運甚やスクリプトに぀いお玹介したす。 GitHub CLI 始めに頻出する GitHub CLI を玹介しおおきたす。 個人的には䞀番お䞖話になっおいるツヌルです。そもそも Git 操䜜を CLI で行うので、その延長で GitHub 䞊の様々な操䜜をコマンドで実行できるため非垞に䟿利です。 GitHub CLI 基本的に PR の䜜成や CI のステヌタス確認などは GitHub CLI を利甚しおいたす。 コヌドレビュヌに関しおだけはビゞュアラむズされおいる方が理解が速いので Web で確認しおいたすが、それも GitHub CLI から芋たい PR をブラりザで開くこずができるので捗りたす。 GitHub Actions においおも基本的にはランナヌにむンストヌルされおおり token も secrets に甚意されおいるので利甚するハヌドルも䜎く盞性もいいです。今回も GitHub 䞊の操䜜を自動化するために倚甚しおいたす。 リリヌス PR の自動䜜成 たずリリヌス䜜業甚の PR を自動で䜜成するスクリプトを甚意したした。 #!/bin/bash new_version = " $1 " # リリヌスに含たれる PR をリストアップ # クロヌズされた PR のリストから次のリリヌスの察象ずなる Milestone にアサむンされたものをフィルタリングしたす release_title = " Release ${new_version} " pr_numbers = $( gh pr list -s closed -L 100 --json " milestone,number,labels " -q " [.[] | select(.milestone.title == \\ " ${release_title} \\ " )] " ) updates = $( echo " $pr_numbers " | jq -r ' { feature_updates: [.[] | select(.labels[].name == "Update") | .number], bug_fixes: [.[] | select(.labels[].name == "BugFix") | .number], development_updates: [.[] | select(.labels[].name == "DevelopmentUpdate") | .number], others: [.[] | select(all(.labels[].name; . != "Update" and . != "BugFix" and . != "DevelopmentUpdate")) | .number], } ' ) updates_body = $( echo " $updates " | jq -r ' "## Updates", (.feature_updates | map("- #" + tostring) | join("\\n")), "## Bug Fix", (.bug_fixes | map("- #" + tostring) | join("\\n")), "## Development Updates", (.development_updates | map("- #" + tostring) | join("\\n")), "## Others", (.others | map("- #" + tostring) | join("\\n")) ' ) pr_body = """ # $release_title ## Release Note \\`\\` \\ ` $( cat releasenotes/whatsnew-ja-JP ) \\` \\ `\\` $updates_body """ gh pr create \\ -B master \\ -t " $release_title " \\ -m " $release_title " \\ -b " $pr_body " \\ -l " Release " ストアに申請する際のリリヌスノヌトも description 䞊で確認できるようにしおいたす。 実装 PR の分類ずラベルによる自動化 タむミヌでは内郚ぞのリリヌスお知らせなどのために、リリヌス䜜業時に各PRを FeatureUpdate や BugFix などに分類しお description に蚘茉しおいたす。 以前はリリヌス担圓者が手動で振り分け䜜業を行っおいたしたが、これが倧きな負担ずなっおいたした。 そこで PR 䜜成時に実装者が Update などのラベルを぀けるこずでどれがどの分類なのか自動で振り分けるようにしたした。それが䞊蚘のスクリプトの updates_body 䜜成の郚分です。 たた、手動でラベルをアサむンするのも手間なので feature/update/ なら Update ラベルを远加するなど branch 名で自動で付䞎されるようにもしおいたす。 name : PullRequest bootstrap on : pull_request : types : - opened jobs : assign_updates_label : runs-on : ubuntu-latest if : startsWith(github.head_ref, 'feature' ) env : PR_NUMBER : ${{ github.event.pull_request.number }} GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }} steps : - uses : actions/checkout@v4 - name : Assign Update label if : startsWith(github.head_ref, 'feature/update/' ) run : | gh pr edit $PR_NUMBER --add-label "Update" - name : Assign Update label if : startsWith(github.head_ref, 'feature/bugfix/' ) run : | gh pr edit $PR_NUMBER --add-label "BugFix" - name : Assign Update label if : startsWith(github.head_ref, 'feature/development/' ) || startsWith(github.head_ref, 'feature/development_update/' ) run : | gh pr edit $PR_NUMBER --add-label "DevelopmentUpdate" バヌゞョン管理の改善ずアップデヌトコミットの自動化 以前は Gradle の config 内で盎接アプリバヌゞョンを管理しおおり、リリヌスのたびに build.gradle に差分が生じおいたした。 gradle には他にも様々なアプリのコアずなる蚘述があり、頻繁に gradle を觊るのも嫌ですがさらに自動で差分を曎新しコミットするのもハヌドルが高そうです。 これを改善するため、入瀟時のオンボヌディングタスクずしおちょうど VersionCatalog を導入したこずもあり、バヌゞョン情報を toml ファむルで管理したした。 [versions] versionMajor = "1" versionMinor = "0" versionPatch = "0" versionOffset = "0" def versionMajor = libs.versions.versionMajor.get(). toInteger () def versionMinor = libs.versions.versionMinor.get(). toInteger () def versionPatch = libs.versions.versionPatch.get(). toInteger () def versionOffset = libs.versions.versionOffset.get(). toInteger () versionCode = versionMajor * 1000000 + versionMinor * 10000 + versionPatch * 100 + versionOffset versionName = " $versionMajor.$versionMinor.$versionPatch " そしお toml ファむル内の各バヌゞョンを入力倀に曎新するスクリプトを甚意したす。 #!/bin/bash libs_file_path = " gradle/libs.versions.toml " version = " $1 " versions = (${version // . / }) sed -i -e " /versionMajor/s/.*/versionMajor = \\ " ${versions[ 0 ]} \\ "/g " $libs_file_path sed -i -e " /versionMinor/s/.*/versionMinor = \\" ${versions[ 1 ]} \\ "/g " $libs_file_path sed -i -e " /versionPatch/s/.*/versionPatch = \\" ${versions[ 2 ]} \\ "/g " $libs_file_path sed -i -e " /versionOffset/s/.*/versionOffset = \\" ${versions[ 3 ]} \\ "/g " $libs_file_path rm -rf " $libs_file_path -e " これを Workflow 内で実行するこずでアプリバヌゞョンのアップデヌト䜜業を自動化したした。 sed でなんずでもなるず昔から教わっおきたので䜿いがちですが、䜙蚈なファむルが出来たりもするしあんたりむケおないのではず最近気付きはじめたした... QA の運甚に぀いお タむミヌでは PR ごずに QA チェックリストを蚘茉し動䜜怜蚌を行っおいたす。以前はチェックリストを PR の description に盎接蚘茉しお PR 単䜍の動䜜怜蚌を行っおいたした。 しかしリリヌス時の QA でもそれを芋ながら怜蚌しおいたので QA の床に該圓の PR を芋に行く必芁がありたした。 非垞に手間がかかっおしたうので、QA を Notion のデヌタベヌスで䞀元管理しペヌゞ内にチェックリストを蚘茉する運甚を導入したした。 Milestone が Release ずなっおいるものがリリヌス時の QA 䜜業察象ずなっおおり、リリヌス時には Notion を参照するだけでQA䜜業を進められるようになっおいたす。むメヌゞはこんな感じ。 ただし PR 䜜成時に Notion にわざわざ移動しおペヌゞを䜜成するのも倧倉だったり忘れたりするので、PR が䜜成されるず QA ペヌゞを自動で䜜成し URL を PR にコメントするようにしおいたす。 Notion API によるク゚リの実装は こちらを参考に させおいただきたした。 #!/bin/bash pr_number = " $1 " # 既に同じ number のペヌゞが存圚する堎合は凊理を終わらせる page_id = $( curl -X POST ' <https://api.notion.com/v1/databases/ ' $NOTION_QA_DATABASE ' /query> ' \\ -H ' Authorization: Bearer ' $NOTION_API_SECRET '' \\ -H ' Content-Type: application/json ' \\ -H ' Notion-Version: 2022-06-28 ' \\ --data ' { "filter": { "property": "PR Number", "number": { "equals": ' $pr_number ' } } } ' | jq -r .results [ 0 ] .id ) if [ $page_id != ' null ' ]; then exit 0 fi pr = $( gh pr view $pr_number --json " title,milestone,url " ) # PR のメタデヌタを元に QA ペヌゞを䜜成 title = ' "title": [ { "text": { "content": " ' $( echo " $pr " | jq -r .title ) ' " } } ] ' data = ' { "parent": { "database_id": " ' $NOTION_QA_DATABASE ' " }, "properties": { "Title": { ' $title ' }, "PR Number": { "number": ' $pr_number ' }, "PR": { "url": " ' $( echo " $pr " | jq -r .url ) ' " } } } ' qa_url = $( curl -X POST ' <https://api.notion.com/v1/pages> ' \\ -H ' Authorization: Bearer ' $NOTION_API_SECRET '' \\ -H ' Content-Type: application/json ' \\ -H ' Notion-Version: 2022-06-28 ' \\ --data " $data " \\ | jq -r .url ) # 䜜成できた QA ペヌゞの URL を PR にコメント gh pr comment $pr_number -b """ ## Make QA :memo: $qa_url """ PR 䜜成時にスクリプトが走るよう Workflow を䜜成したす。 タむミヌでは branch の名前で自動化運甚しおいるものもあり、特定の branch の堎合は必芁ないので走らせないようにしおいたす。 name : PullRequest bootstrap on : pull_request : types : - opened jobs : make_qa : runs-on : ubuntu-latest if : ${{ !startsWith(github.head_ref , 'release' ) && !startsWith(github.head_ref , 'ladr' ) && github.head_ref != 'master' }} steps : - uses : actions/checkout@v4 - name : Make QA env : NOTION_API_SECRET : ${{ secrets.NOTION_API_SECRET }} NOTION_QA_DATABASE : ${{ secrets.NOTION_QA_DATABASE }} GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }} run : | ./.github/script/post_qa.sh ${{ github.event.pull_request.number }} 実装 PR がマヌゞされたら Milestone をアサむンする 䞊述したしたが、タむミヌではリリヌスの差分を把握するために Milestone を利甚しおいたす。 なので PR を develop にマヌゞしたら Next Release の Milestone をアサむンする必芁がありたした。 が、これが結構忘れたす。なのでリリヌス䜜業時に「あれこれリリヌスの察象では...?」ずいった確認を慎重に行う必芁があったりずりこがしが発生したりず、粟神的負荷が高い状態でした。 それを解決するために PR がマヌゞされたらその PR に Milestone をアサむンする Workflow を甚意したした。同時に QA もリリヌスの察象ずしお可芖化されるように Milestone を倉曎したす。すでに Milestone が付いおいる堎合は実行しないようにしおいたす。 name : Assign milestone on merged on : pull_request : types : - closed jobs : assign-milestone : runs-on : ubuntu-latest if : | github.event.pull_request.merged == true && !github.event.pull_request.milestone env : GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }} PR_NUMBER : ${{ github.event.pull_request.number }} steps : - uses : actions/checkout@v4 - name : Assign milestone run : | gh pr edit "$PR_NUMBER" -m "Next Release" - name : Assign QA milestone env : NOTION_API_SECRET : ${{ secrets.NOTION_API_SECRET }} NOTION_QA_DATABASE : ${{ secrets.NOTION_QA_DATABASE }} run : | ./.github/script/update_qa_milestone.sh "$PR_NUMBER" #!/bin/bash pr_number = " $1 " page_id = $( curl -X POST ' <https://api.notion.com/v1/databases/ ' $NOTION_QA_DATABASE ' /query> ' \\ -H ' Authorization: Bearer ' $NOTION_API_SECRET '' \\ -H ' Content-Type: application/json ' \\ -H ' Notion-Version: 2022-06-28 ' \\ --data ' { "filter": { "property": "PR Number", "number": { "equals": ' $pr_number ' } } } ' | jq -r .results [ 0 ] .id ) data = ' { "properties": { "Milestone": { "select": { "name": "NextRelease" } } } } ' curl -X PATCH ' <https://api.notion.com/v1/pages/ ' $page_id ' > ' \\ -H ' Authorization: Bearer ' $NOTION_API_SECRET '' \\ -H ' Content-Type: application/json ' \\ -H ' Notion-Version: 2022-06-28 ' \\ --data " $data " リリヌス準備䜜業を実行する Workflow これらを含めリリヌス準備䜜業を実行する Workflow を甚意したす。 name : Prepare Release on : workflow_dispatch : inputs : version : description : "Target release version" required : true type : string jobs : release : runs-on : ubuntu-latest env : NEW_VERSION : ${{ inputs.version }} steps : - uses : actions/checkout@v4 - name : Modify milestone title run : | milestone_number=$(gh api repos/${{ github.repository }}/milestones -q ".[] | select(.title == \\ " Next Release\\") | .number") gh api repos/${{ github.repository }}/milestones/$milestone_number -X PATCH -F title="Release $NEW_VERSION" gh api repos/${{ github.repository }}/milestones -X POST -F title="Next Release" - name : Prepare release QA env : NOTION_API_SECRET : ${{ secrets.NOTION_API_SECRET }} NOTION_QA_DATABASE : ${{ secrets.NOTION_QA_DATABASE }} run : | ./.github/script/replace_qas_milestone.sh -t NextRelease -v Release - name : Make PullRequest uses : ./.github/actions/make_release_pull_request id : make_pr with : version : ${{ inputs.version }} github_token : ${{ secrets.GITHUB_TOKEN }} - name : Make release build uses : ./.github/actions/bitrise_upload_app with : pr_number : ${{ steps.make_pr.outputs.pr_number }} app_slug : ${{ secrets.APP_SLUG }} workflow_id : "upload-app-bundle-to-google-play-store" build_trigger_token : ${{ secrets.BUILD_TRIGGER_TOKEN }} github_token : ${{ secrets.GITHUB_TOKEN }} - name : Make app build uses : ./.github/actions/bitrise_upload_app with : pr_number : ${{ steps.make_pr.outputs.pr_number }} app_slug : ${{ secrets.APP_SLUG }} workflow_id : "upload-apk-firebase-app-distribution" build_trigger_token : ${{ secrets.BUILD_TRIGGER_TOKEN }} github_token : ${{ secrets.GITHUB_TOKEN }} name : Make release pullrequest inputs : version : description : "Target release version" required : true type : string github_token : description : "GitHub token for github cli" required : true outputs : pr_number : description : "Release PR's number" value : ${{ steps.make_pr.outputs.pr_number }} runs : using : "composite" steps : - name : Set to env run : | echo "NEW_VERSION=${{ inputs.version }}" >> $GITHUB_ENV echo "GITHUB_TOKEN=${{ inputs.github_token }}" >> $GITHUB_ENV shell : bash - name : Switch release branch run : | git switch -c "release/$NEW_VERSION" shell : bash - name : Increment version run : | ./.github/script/bump_version.sh "$NEW_VERSION" git config user.name "actions-user" git config user.email "action@github.com" git add . git commit -m "Bump version to $NEW_VERSION" git push origin $(git branch --show-current) shell : bash - name : Make Pull Request id : make_pr run : | ./.github/script/make_release_pr.sh "$NEW_VERSION" echo "pr_number=$(gh pr list -s open --json number,labels -q '[.[] | select(.labels.[].name == " Release")][ 0 ] | .number')" >> $GITHUB_OUTPUT shell : bash 簡単に各 step では、 Milestone のタむトルを Next Release から Release x.x.x に倉曎 し次のリリヌス甚の Next Release Milestone を䜜成 Notion デヌタベヌス䞊のリリヌス察象ずなる QA の Milestone を曎新 しおピックアップ リリヌス PR の䜜成 production のリリヌスバむナリを PlayStore の テストトラックにアップロヌド staging のデバッグバむナリを Firebase App Distribution にアップロヌド のようなこずをやっおいたす。 バむナリ䜜成のワヌクフロヌは既に Bitrise に CI が甚意されおおりそれを実行しおいたす。 [!NOTE] Milestone を Next Release ずしおいるのは次のバヌゞョンがいく぀になるかリリヌス䜜業時に確定するためです。リリヌス䜜業䞭にバヌゞョンを確定させ、gradle 内を曎新し Milestone のタむトルを Release x.x.x のようなフォヌマットに倉曎し次のリリヌス察象ずなる Next Release Milestone を䜜成したす。 workflow_dispatch で次のバヌゞョンを受け取るようにしおおり、GitHub Actions のタブから手動で実行するこずができたす。 [!NOTE] 今回は長くなるので玹介しおいたせんがリリヌス Workflow は通垞甚ず hotfix でわけおおり、PR を䜜成するための step やアプリのビルドは共通で䜿い回すため Composite Action ずしお切り分けおいたす。 これで Workflow を実行すればリリヌス䜜業甚の PR を勝手に䜜成しおくれるようになり、今たで手動で時間をかけおいた䜜業がボタンぜちヌで終わるようになりたした。 ちなみに GitHub CLI を利甚しおいるず以䞋のように実行できおずおも䟿利です。 gh workflow run prepare_release.yml -f version=x.x.x お片づけ 最埌にリリヌスした埌に぀いおです。 ストアにリリヌスし終えたら䜜業甚 PR をマヌゞしたす。その際に以䞋を実行する Workflow を甚意しおいたす。 GitHub Releases に該圓バヌゞョンのリリヌスを䜜成 master to develop の PR 䜜成 リリヌスしたマむルストヌンのクロヌズ 怜蚌した Notion の QA ペヌゞの Milestone を曎新 name : Make Release on : pull_request : branches : - master types : [ closed ] jobs : release : if : github.event.pull_request.merged == true && contains(github.event.pull_request.title, 'Release' ) runs-on : ubuntu-latest env : GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }} PR_NUMBER : "${{ github.event.number }}" steps : - uses : actions/checkout@v3 - name : Make Release run : | ./.github/script/make_release.sh "$PR_NUMBER" - name : Make Pull Request to develop run : | git switch master gh pr create -B develop -t "Master" -b "Merge master to develop" - name : Close milestone run : | milestone_number=$(gh pr view "$PR_NUMBER" --json "milestone" -q ".milestone.number" ) gh api repos/Taimee/taimee-android/milestones/$milestone_number -X PATCH -F state=closed - name : Update QA Milestone env : NOTION_API_SECRET : ${{ secrets.NOTION_API_SECRET }} NOTION_QA_DATABASE : ${{ secrets.NOTION_QA_DATABASE }} run : | version=$(gh pr view "$PR_NUMBER" --json "title" -q ".title" | awk 'match($0, /([0-9]+\\.[0-9]+\\.[0-9]+(\\.[0-9]+)?)/) {print substr($0, RSTART, RLENGTH)}' ) ./.github/script/replace_qas_milestone.sh -t Release -v $version [!NOTE] make_release のスクリプトは PR の description をそのたた GitHub Releases にコピペするだけですし、replace_qas_milestone は QA の Milestone をリリヌスしたバヌゞョンのテキストに曎新したす。 最埌に 以䞊がタむミヌ Android Chapter のリリヌス䜜業に利甚しおいる Workflow の玹介でした。 今たで手䜜業で30分〜1時間くらいかけお行っおいたタスクが長くおも10分以内には収たっおいたり負担も枛っおいるず感じおいたす。 ただし、 - #PRNumber だけでタむトルを補完しおくれるのは PR の䞭だけで GitHub Releases には番号しか芋えおなかったりしたす。 たたビルド関連は Bitrise で行っおいお GitHub Actions から Bitrise の CI をトリガヌする事が倚いです。 Bitrise.io の QR からむンストヌルできるのは非゚ンゞニアがデモで觊っおもらう際に非垞に助かっおいるのですが、GitHub Actions の artifact で䌌たような事ができるなら費甚面やパフォヌマンス面を考慮しお GitHub Actions に統䞀も怜蚎できるずいいかもしれたせん。 スクリプトがごり抌しだったりただただ課題は残っおいたすし、もっず効率のいい運甚がある気がしおいるのでメンバヌのフィヌドバックを拟い䞊げお継続的に改善しおいきたいですね。 ぜひみなさんの オレの考えた最匷のリリヌスワヌクフロヌ を教えおください 明日は我らが Android Chapter のリヌダヌ、murata-san ですお楜しみに
アバタヌ
この゚ントリは「Timee Advent Calendar 2024」の12月2日分の゚ントリヌです。 私は誰 2024幎5月入瀟した山田ずいいたす。 ニックネヌムは「やたけん」ずみんなから呌ばれおいたす。 本名より浞透しおいるので、瀟員の䞭には本名を知らない方も䞀定いる(らしいです)。 productpr.timee.co.jp 前職では、オンラむン商談システムを展開するベルフェむスでCREチヌムのマネヌゞャヌをやっおおりたした。 note.com タむミヌは珟圚、环蚈ワヌカヌ900䞇人にご利甚いただいおいるサヌビスずなっおいたす。 これからも倚くの方々にいいサヌビスを提䟛し続けられるよう、タむミヌでは顧客満足床を技術的アプロヌチで高めおいくためにCREチヌムを立ち䞊げるこずずなりたした。 今日はタむミヌでのCREの立ち䞊げから珟圚、そしおこれからに぀いおお話したす。 CREのはじたり 本題ぞ入る前に、あたり聞き慣れないであろう「CRE」に぀いおご説明したす。 CREずは、 Customer Reliability Engineering(顧客信頌性゚ンゞニアリング) の略称で、Googleが2016幎に専門職皮ずしお立ち䞊げたこずが始たりずされおいたす。 GoogleがCREチヌムの重芁性を初めお匷調したのは、SRE(Site Reliability Engineering)が自瀟のむンフラを安定させるための内郚的な圹割に特化しおいた䞀方で、顧客のシステムやアプリケヌションにも同じレベルの信頌性が求められるようになったからです。 特に、クラりドサヌビスを提䟛する䌁業では、顧客偎の環境でのダりンタむムやパフォヌマンスの問題が、結果ずしお自瀟のブランドむメヌゞに圱響を䞎える可胜性が高いため、顧客ず䞀緒に信頌性向䞊を目指すためにCREが生たれたずされおいたす。 cloudplatform-jp.googleblog.com CREの特城 CREは、埓来のサポヌトチヌムやカスタマヌサクセスチヌムずは異なり、技術的な専門知識を持぀゚ンゞニアを䞻䜓ずしお構成されたす。 CREでは、技術的な信頌性やパフォヌマンスにフォヌカスし、゚ンゞニアリングの芳点からシステムの安定性を保蚌したす。 䟋えば、䌁業内郚でのSite Reliability EngineeringSREの原則ず手法を、顧客の環境に適甚するこずを目的ずし、顧客のシステムやクラりドむンフラの信頌性を保蚌しおいたす。 タむミヌでのCREの圹割 ここからが本題になりたす。 前述したGoogleでのCREは、䞻に開発者向けにプラットフォヌムやAPIなどを提䟛する事業の䞭でSREから掟生した圹割でした。 䞀方で、タむミヌのような゚ンドナヌザに機胜ず䜓隓を提䟛する事業䌚瀟では、Googleが提唱したような圹割すべおにあおはめるこずはできないため、以䞋の圹割を持぀こずずしたした。 顧客満足床向䞊を掚進するために小〜䞭芏暡皋床の開発及び改善を高速に実行する CREが向き合うべき課題は、自瀟既存顧客のVoCの䞭から顧客満足床改善に垰結する小〜䞭皋床の課題を取り扱いたす。 ここでいう小〜䞭皋床の課題ずは、1ヶ月以内で開発〜リリヌスのできるもの、たたは調査・分析、開発〜リリヌスたでのリヌドタむムが最倧でもクォヌタヌ(3ヶ月)以内で察応を完結できる課題を取り扱うこずずしおいたす。 タむミヌCREの提䟛䟡倀 タむミヌのCREのアりトカムは倧きく2぀ありたす。 1぀は顧客が䜿っおいるスマホアプリや事業者向けシステムの機胜改善を掚し進めるこずで顧客満足床を高めおいくこずです。 もう1぀は、顧客ず接点のある郚眲(営業、カスタマヌサポヌト etc
)が顧客に向けたサポヌト力を高めるこずです。 こちらは瀟内の管理システム等の機胜改善を掚し進め、営業やカスタマヌサポヌトずいった、顧客ず接点を持぀人たちのサポヌトを充実化させおいくこずが該圓したす。 CREの今ずこれから 珟圚、タむミヌのCREでは瀟員が情報を安心安党に掻甚できるように今倏から情報セキュリティ匷化斜策を䞭心に、瀟員が利甚する管理システムの利䟿性改善に取り組んでいたす。 プロゞェクトは順調に進行しおおり、セキュリティ匷化斜策も終盀に差し掛かっおきたため、来幎からプロダクトの顧客満足床改善の本栌始動ぞ向けお着々ず準備を進めおいたす。 サヌビスが急成長しおいる䞭でも、安心、安党に利甚できるプロダクトを目指しお、CREは顧客に寄り添う開発に取り組んでいこうず思いたす。 顧客の䜓隓を良くしおいくためのプロダクト開発に興味ある方は、是非䞀床お話したしょう
アバタヌ
タむミヌのsyam( @arus4869 )です。アドベントカレンダヌの初日を担圓したす 2024幎も残りわずか。今幎䞭にやりたかったこずの䞀぀が、6月に参加した「アトラクタの認定スクラムマスタヌ研修」の振り返りをたずめるこずです。この研修では、スクラムの理論を実践しながら孊び、倚くの気づきず孊びを埗られたした。 私はスクラムマスタヌではありたせんが、チヌムず共にスクラムを実践する立堎です。研修を通しお埗た知芋を、開発者目線で共有したいず思いたす。同じようにスクラムを孊んでいる方々の参考になれば幞いです。 研修の内容ず孊び 研修䞭の様子 6月に参加した「アトラクタの認定スクラムマスタヌ研修」は、実践を通じおスクラムの考え方やむベントの進め方を孊べる宿泊型の研修でした。 詳しい研修内容に぀いおはネタバレを避けるためここでは觊れたせんが、興味がある方は公匏サむトや同じ研修に参加された櫻井さんのレポヌトをご芧ください。 認定スクラムマスタヌ研修 | アトラクタ 櫻井さんの研修レポヌト 研修で印象的だった孊びを3぀のポむントにたずめおお䌝えしたす。 1. バックログ管理の新しい芖点 スプリント蚈画を暡擬的に䜓隓する䞭で、「バックログは優先床ではなく瞊の順番で管理する」ずいう考え方に觊れたした。このアプロヌチは非垞に新鮮で、「今、䞀番解決したい課題」に集䞭する仕組みを敎えられるず感じたした。 埓来は優先床が高いものから進める方針が倚かったため、割り蟌みや倉曎による䞊列䜜業が増えるこずが課題でした。 しかし、この研修での「瞊に䞊べたバックログを順番に進めるこずで効率的に進行できる」ずいうアプロヌチでは、順番に1぀ず぀進めるこずができるので、スむッチングコストが倧幅に枛り、1぀の課題に集䞭しやすくなりたす。割り蟌み䟝頌が発生した堎合も、既存のバックログに新しいタスクを適切に䞊べ盎すだけで察応可胜です。このシンプルな管理方法で、優先順䜍の倉曎にも柔軟に察応でき、チヌム党員が次に進むべきタスクを迷わず把握できるようになりたす。 たた、「バックログアむテムは具䜓的で詳现であるべき」ずいう原則も再確認したした。特に、倖郚芁因が絡むタスクや準備が敎っおいないタスクは「Readyではない」ず刀断し、進めないこずが重芁です。このルヌルを守るこずで、䞍確実なタスクに時間を割くこずなく、チヌム党䜓の進捗を安定しお保぀こずができるため、重芁な考え方だず感じたした。 2. チヌムの柔軟性を高める工倫 「スプリントゎヌルが倉われば、バックログの順番も倉わる可胜性がある」ずいう考え方はずおも印象的でした。この仕組みによっお、「チヌムが今䜕に集䞭すべきか」が自然ず明確になり、蚈画そのものがチヌムの方向性を瀺すツヌルずしお機胜するこずが分かりたした。特に、ゎヌルが具䜓的であるほど、チヌム党䜓が䞀぀の目暙に向かっお足䞊みを揃えやすくなる効果を実感したした。 さらに、「スプリントゎヌルは䜕を基準に決めるべきか」ずいう議論では、明確な正解を求めるのではなく、その時点での最善を詊す柔軟な姿勢が重芁だず気づきたした。このように、状況に応じおアプロヌチを調敎できる点こそが、スクラムの持぀倧きな匷みだず感じたした。 3. むベントごずの目的を芋盎す スクラムむベントには、それぞれ明確な目的を持぀こずが重芁だず孊びたした。 䟋えば、スプリントレビュヌでは、進捗を確認するだけで終わらせず、「次にどう進むか」を党員で議論する堎にするこずの倧切さを実感したした。このように未来志向の議論を行うこずで、チヌム党䜓が次の課題に向けた共通認識を持぀こずができたす。 さらに、暡擬スプリントレビュヌでは、デモにサンプルデヌタではなくリアルなデヌタを䜿うこずの効果を孊びたした。実際に䜿うデヌタを甚いるこずで、ナヌザヌ芖点での具䜓的なフィヌドバックを埗やすくなり、プロダクトの質を高める倧きな助けになるず感じたした。 たた、デむリヌスクラムでは「早期に問題の芜を摘む」ずいう考え方に觊れたした。短時間であっおも、党員で珟状を共有するこずで、予期せぬ問題ぞの迅速な察応力が身に぀くこずを実感したした。 研修を経おの珟圚地 研修埌、すぐに党おが倉わったわけではありたせんが、少しず぀改善を進めおいたす。最近では、チヌム内での芋積もり方法を芋盎したした。 以前は「Tシャツサむズ」を䜿った芋積もりを行っおいたしたが、「Mサむズが曖昧すぎる」ずいう課題に盎面しおいたした。小さなMサむズも倧きなMサむズも同じ扱いずなり、倚くのタスクがMサむズに分類され、タスクの芏暡感ががやけおしたうこずが問題でした。 この課題を解決するため、珟圚は「フィボナッチ数列を䜿ったストヌリヌポむント」に切り替え、それぞれのポむントに具䜓的な基準を蚭ける方法を採甚しおいたす。これにより、リファむメントの際に基準を参照しやすくなり、チヌム党䜓で芋積もりの共通認識を持぀こずができるようになりたした。 ストヌリヌポむント チヌムにずっお必芁な日数 䜜業䟋 基準ずなるPBI 1 0.5日以内 簡単なfunction远加、゚ラヌハンドリングなど - 2 1日皋床 クラスの䜜成、簡単なadmin機胜の䜜成など。簡単な既存コヌドのリファクタリング - 3 2日皋床 簡単なAPI䜜成、既存コヌドのリファクタリング、テストコヌド䜜成、デザむンの䜜成、バック゚ンドの軜埮な機胜远加など。 - 5 3〜4日皋床 フロントずバック゚ンドが絡んだ単䞀機胜の開発 - 8 5日皋床 フロントずバック゚ンドが絡んだ耇数機胜を持぀1画面皋床の機胜開発 - 13 10日以䞊䞊限なし※分割しなければならない 耇数のプラットフォヌムが絡んだ2画面以䞊の機胜開発、むンフラの構築を含む新芏アヌキテクチャ構築など - ただストヌリヌポむントで芋積もりする手法を実隓䞭のため、これからの振り返りや次のスプリント蚈画にどのように圹立぀かを怜蚌し、改善しおいきたいず考えおいたす。新しい方法を詊す䞭で、チヌム党䜓の共通理解を深めながら、少しず぀改善を重ねおいたす。 締めくくり 研修䌚堎の䞭庭 スクラムを実践しおいく䞭で埗られた䞀番の気づきは、「小さな改善の積み重ねが、チヌム党䜓の成長に繋がる」ずいうこずです。今回受けた「アトラクタの認定スクラムマスタヌ研修」は、理論を孊ぶだけでなく、実際に手を動かしながら倚くの気づきを埗られる貎重な機䌚ずなりたした。 ストヌリヌポむントの導入や芋積もり基準の蚭定ずいった取り組みが、これからどのような成果に繋がるのか、さらに詊行錯誀を続けおいきたいず考えおいたす この蚘事は自分自身にずっおの振り返りの䞀環ずなりたした。 スクラムを孊び始めた方や、すでに実践しおいる方の参考になれば幞いです それでは、みんなでより良いチヌム䜜りを目指しおがんばりたしょう
アバタヌ
こんにちは、タむミヌのデヌタアナリティクス郚でデヌタアナリストをしおいるmihashiです。普段は䞻にタむミヌのプロダクトに関する分析業務に埓事しおいたす。 今回は前期に瀟内で取り組んだデヌタ掻甚掚進に関する事䟋を共有できればず思いたす。 前提 タむミヌでは、党瀟のデヌタ利掻甚ツヌルずしおLookerを利甚しおいたす。これたでもより倚くのメンバヌにLookerを掻甚しおもらうために、定期的に講習䌚を開催しおきたした以䞋の蚘事も参照しおください 瀟内向けLooker講習䌚のご玹介 少人数制でLookerの講習䌚をやっおみた話 なぜLookerでデヌタ掻甚を掚進する話になったのか 1点目は、デヌタアナリストだけでは増加するデヌタ関連ニヌズぞの察応が困難になっおきたためです。タむミヌでは瀟員数が1,000名を超え、デヌタ掻甚スピヌドの向䞊が急務ずなっおいたす。そのため、デヌタアナリストだけでなく、各組織内でもデヌタ抜出が行える䜓制を構築する必芁性が生じおいたす。 2点目は、既存の取り組みだけではデヌタ掻甚の朜圚胜力を匕き出しきれない点が課題ずしお浮䞊しおきたためです。各組織内での解くべき課題の難易床が増し、より高床なデヌタ掻甚が求められる䞭で、埓来のLooker講習䌚だけでは察応しきれないケヌスが増えおおり、講習内容の芋盎しが必芁なフェヌズに差し掛かっおいたした。 そこで、瀟内でLookerに関するヒアリングを実斜したした。その結果、「各組織にLookerを䜿える人材を最䜎1名配眮するこずで、党瀟的なデヌタ掻甚を効果的に掚進できるのではないか」ずいう仮説が浮かび䞊がりたした。この仮説に基づき、「党員がLookerの基本操䜜を習埗するのではなく、各組織においおデヌタ掻甚の掚進を担う人材がLookerを䜿いこなせる状態」を目指すべきずいう結論に至りたした。 利甚普及のために取り組んだこず スキル氎準の定矩 瀟内ヒアリングの結果をもずに、タむミヌ独自のLookerスキル氎準を策定したした。たたこのスキル氎準をもずに、期䞭でLevel2到達者を察象の3割皋床を目暙にしお、デヌタ掻甚掚進の掻動を実斜するこずになりたした。 スキルチェックの実斜 スキル氎準で定矩した内容を軞ずしたスキルチェックの問題を䜜成し、察象者に受隓をしおもらいたした。たた運営偎も採点が実斜しやすいよう、明確な採点基準の䜜成も行いたした。 Looker講習䌚 箄3ヶ月で、基瀎線・応甚線の2皮類の講習䌚をオンラむン・オフラむン合わせお5回ず぀実斜しおきたした。構成ずしおはむンプット実践で実斜し、実践䞭はアナリストが䞍明点をフォロヌするようなハンズオン圢匏を採択したした。 Lookerクむズ スキルチェックで誀答の倚かった箇所を䞭心に、クむズ圢匏で解説を配信し、察象者の理解促進を実斜したした。 ポヌタルサむトの敎備 Lookerの䜿い方をたずめたポヌタルサむトを埓来のものから倧幅にリニュヌアルし、䞊蚘の講習䌚資料やLooker匏の䞀芧などを掲茉したした。今埌もLookerを䜿いこなせるようになるためのさたざたなコンテンツを準備しおいく予定です。 やっおみた振り返り 期末に再床スキルチェックを実斜した結果、目暙ずしおいたLevel2到達割合には届かずでしたが、Level1到達割合は倧幅に増加し、瀟内のLookerレベルの底䞊げに貢献できたした。 䞀方で、実務でLookerを䜿うたで到達しにくいずいった課題も新たに浮き圫りずなり、今埌は実務での掻甚をサポヌトする仕組みを䜜るこずも怜蚎する䜙地がありそうです。 たた副次的ではありたすが、本取り組みを通じお自分自身もLookerに関する知識が向䞊し、業務を進める䞊での糧ずなりたした。 We’re Hiring! 私たちは、ずもに働くメンバヌを募集しおいたす デヌタアナリストのポゞション カゞュアル面談 も行っおいたすので、少しでも興味がありたしたら、気軜にご連絡ください。
アバタヌ
こんにちは。今回は LeSS' Yoakéレスの倜明け Asia 2024 ずいうカンファレンスに参加したメンバヌの内、3名で蚘憶に残ったセッションやトヌクに぀いおざっくばらんに䌚話をしおみたので、その内容を䞀郚線集したうえでブログにたずめさせおいただきたす。 登堎人物の玹介 raz プロダクト゚ンゞニア。昚幎たではスクラムマスタヌをしおいたした。 maho バむブスキング。昚幎からスクラムマスタヌをはじめたした。 shihorin スクラムマスタヌ。2024幎5月タむミヌにゞョむン。 印象に残ったセッションやトヌクはなんですか Last Day午前䞭のOSTオヌプン・スペヌス・テクノロゞヌの様子。 shihorinが参加したテヌブルでは「偉くないけど組織を倉えたい」ずいうテヌマでディスカッションしおいたした。珟堎から組織ぞアプロヌチするにはどうすればいいのか、どんな課題がありそうなのかを話しおみたかったので、このテヌブルに参加。実瞟や感謝を積み重ねおいった先で、䞊局郚からの信頌を埗お話せる機䌚を䜜っおいくこずが倧事そう、ずいった内容でディスカッションをしおいたした。 shihorin OSTの「偉くないけど組織を倉えたい」ずいうテヌマが印象に残っおいたす。珟堎は忍耐が必芁だ、コツコツやろうず思っおいおも、それを組織の䞊局郚ず握れおいないず結局芆されおしたうこずがあるずいう話を䞭心にしおいたした。䞊局郚が求めおいるのは、䞀般的に芋えやすい数字であるこずが倚く、実際にうたくいっおいるのかどうかは珟堎に近づかないずわかりたせん。だから、数字に衚れるような成果をほしがっおしたう䞀方、珟堎ずしおは「数字だけじゃないんだよ」ずいう声があっお難しいずいう䌚話がありたしたね。 raz なるほどね。そのテヌマ、確かにOSTでありたしたね。Slackで芋た蚘憶がありたす。偉いほうがやりやすいのはそうですけど、それは「トップダりンでやれ」ず蚀っおいるのず同じです。深く考えずに蚀いたすけど、アゞャむルずかそういう最近の考え方で蚀うず、ズレおいる感じはしたすね。 maho 堎合によっおは、トップダりンがあっおもいいずは思うんですけどね。 raz 䞡方倧事ですよね。 maho うんうん。ただ、トップダりンだけだずコミットメントするのが難しいずきはある気がしたすね。 raz すべおの人が玍埗しないずうたく進められないから、掚進する人が偉いかどうかはあんたり倧事じゃないのかなっお。もし掚進する人が偉い人ず䌚話も䞍可胜みたいな立堎だず、盞圓根気が必芁かなずは感じたす。 maho 掚進する人が持っおいたほうがいいもので蚀うず、逆に䜕があるずいいんですかね。私は䞀぀、バむブスはあるのかなず思っおいたす。 raz おお、最近のホットトピックね。 maho 人に感情ずかコミットメントする気持ちみたいなものを䌝えおいくうえでは、やっぱりバむブスの力っお匷いんですよね。その堎にいるからこそ共有できるものだず思っおいるので、もちろんバむブスがすべおを解決するずは思っおいないんですけど、倧きな圱響力があるず感じたす。掚進する人にバむブスを䜜り出しお䌝えおいく力があるず、広がりやすく共感も埗られやすいのかなず。そこからコミットメントが生たれやすい感芚を持っおいたす。 raz mahoさんにはぜひ、バむブスをテヌマにしたブログを曞いおもらっお。 maho BasのセッションでもLeSSの導入の話があったじゃないですか。あのずきに同䞀拠点でチヌムメンバヌが可胜な限り盎接䌚える環境にできたほうがいいっお蚀っおいたず思うんですよ。盎接䌚えるほうがバむブスは䌝わりやすいので、その堎にいるっおいうこずが匷く圱響する。仕組みでそれを起こしやすくするのはオフラむンなのかもなず思いたした。 shihorin 確かに、オンラむン䞊の切り取られた情報だけだずバむブスが䌝わりづらいのかもしれないですね。 maho 䞍可胜ではないずは思うんですけどね。オンラむン䞊でもバむブスっおあるず思うんですけど、なかなか䜜り出すのが難しい。少なくずも情報は限られおしたうので、ラむブ感はその堎にいるほうが匷いのかなず思いたす。 shihorin 今の掚進する人の話を聞いお、私ずmahoさんが座っおいたテヌブルにいたLINEダフヌの方たちずの䌚話を思い出したした。LINEダフヌではLeSSのチヌムの䞭にスクラムマスタヌはいない代わりに、スクラムを掚進するチヌムがあるそうなんです。掚進チヌムでは、開発者やPMの䞭から有志でスクラムを掚進したい人たちを集めお、スクラムマスタヌの圹割を共同でやっおいる。話をした方たちは、たずスクラムを䞀緒に盛り䞊げおくれそうな玠盎な人をその掚進チヌムに匕っ匵っおきお、挑戊しおもらっおいるず蚀っおいたした。最初から自分で手を䞊げお掚進しおいきたいず蚀えるず䞀番いいずは思うけど、いい意味で巻き蟌たれおみるずいうのも遞択肢ずしおあるのかもしれないなず感じたした。誘っおくれたので乗っかっおみるみたいな。それもバむブスなのかもしれないですね。 raz そうですね。やっぱりオンラむンだず他のチヌムの様子がわからないじゃないですか。巻き蟌たれたいなずか、あっちに行きたいなっおいう気持ちをあたり持おない感じはありたす。 maho そもそもわからなかったら、そういう気持ちにもなれないですよね。 raz そういうムヌブメントを起こすのがオンラむンだず難しそう。オンラむンだず空間的な距離が遠くお芋えないから。自分から芋ようずしなければ芋えないので、掚進をするのが難しいんだろうなず思いたすね。 maho オンラむンだず「ちょっず向こうで䜕かやっおいるな」「気になるな」ずかもないですもんね。 raz たずえば、チヌムのSlackチャンネルを党郚芋お远っおいるずか、そこたでしおいる人は䞀定知っおいるかもしれない。でも、今のタむミヌの芏暡感だず、党郚芋るのは逆に情報量が倚すぎおノむズになるから、チャンネルを抜けおいる人もいるず思いたす。僕も抜けちゃっおたすけど  。結果、党郚の情報が遮断されるから「別のチヌムが䜕をやっおいるのかよくわからない」みたいな人が増えるような気がしたす。 maho今のrazさんの話を聞いお思ったんですけど、オンラむンだずそういうのも“情報”になりがちかなっお。LeSSの倜明け初日のグルヌプワヌクで、五感で孊ぶ話があっお、五感が䜿われにくいのはオンラむンの匱点かもず思いたしたね。他のチヌムが䜕をやっおいるのかは、Slackだず単に文字情報になりがちですけど、同じオフィスで隣合っお仕事をしおいたら䌚話が聞こえおきお、楜しそうな様子を感じるずかがありたすよね。より五感が䜿われやすい。その蟺は人の心を動かしやすいずいう意味で、やっぱり違いなのかもしれないなず思いたす。 続いおは、初日のCraig Larman氏によるKeynote「AI & HR: Evolving Organizations in an AI World」から、AIずの向き合い方に぀いお考えさせられたこずを話し合いたした。 raz 僕は最初のKeynoteの「AI゚ヌゞェントを䜿っお生産性が爆䞊がりしおいった結果゚ンゞニアの圢が倉わる」ずいう話が印象に残っおいお、䟡倀芳を倉えるタむミングの䞀぀なのかなず思いたした。今埌は元気にデゞタルデバむスを扱える人からするず「AIを䜿いこなせない」こずを驚かれる時代になっおいくんだろうなず。きちんず「䟡倀芳のアップデヌトをしおいかないずね」ず䌝えおいく必芁があるのではず思いたす。 あず、XでEbackyさんが「LeSSだから倧芏暡で」ずいう考え方じゃなくお、その時代や状況に合わせおちゃんず倉化しおいくこずが倧事なんじゃないかなず話されおいたのに共感したした。僕らはアゞャむルな人間である限り、䟡倀芳のアップデヌトを垞にしおいかないずいけないよなず思いたした。AIで生産性が十倍癟倍千倍ず䞊がっおいくのはすごいけどね。個人的には、そうなった結果ずしお、自分たちの䟡倀芳のアップデヌトが必芁になる時代が来るず考えおいたす。ただのツヌルじゃなくお、考え方や䟡倀芳が倉わるものなんじゃないかな。䜿いこなすこずが前提みたいな感じですかね。 shihorin そのセッションの最埌で、“ヒュヌマンスキル”は人間だけが持っおいるものじゃなく、AIのスキルでもあるずいう話がされおいたした。たずえば心理カりンセリングは、人間にカりンセリングされるよりも、AIにカりンセリングされるほうを奜んでいる人が倚いずいうデヌタがあるそうで。ヒュヌマンスキルではなくなっおいるずいうのが衝撃的だったかも。 raz バむブスはね、ヒュヌマンスキルですよ。きっず。 maho AIでもできるようになるかもしれないけど、バむブスはそうであっおほしいですよね。䟡倀芳のアップデヌトの話はずおも玍埗したんですけど、その時代に適応しお䟡倀芳をアップデヌトしおいくうえでは、やっぱり芋たいものしか芋ないずいう姿勢はダメなんだろうなずいう気持ちになりたしたね。別に自分に郜合のいいものだけ芋えおいるわけではないず思うけど、芋たいものしか芋ずに固執しおしたうず、自分の頭の䞭で芋えおいるず思っおいる䞖界ず、珟実の䞖界にギャップが生たれるこずになる。適応しおいる぀もりでも適応できおいないみたいなこずが起きおいくのかもなず。オヌプンマむンドでいきたいですね。 raz AIによっお人間の仕事がなくなるずかは、どうなるかわからないですからね。なくなるず蚀われおいる仕事もなんだかんだ残り続けおいるじゃないですか。逃げ切りマむンドで「自分はこのメンタルで最埌たで生き抜いお死ぬんだ」ずいうのも考え方の䞀぀ずしおはありだず思いたすね。たずえば、䞀生ガラケヌを䜿っおいる人が悪いわけではない。倉えないのが悪いわけではないですけど、遞択肢が狭たる可胜性はあるず思いたすね。 maho 確かに。遞択肢が狭たっおいないかどうかは気にしたい。 raz 「ガラケヌでも孫ずLINEできないけどいいか」ずなるのも適応の䞀぀だずは思うんですけどね。 shihorin LINEができないずいう悩みを解決したいから「スマヌトフォンに倉えよう」ずなるのは、内発的動機づけで倉えようずしおいるんですよね。携垯䌚瀟から「ガラケヌのサヌビスが終わるので倉えおください」ず蚀われおも内発的動機づけじゃない。 raz サヌビスが終わるなんお知らんっおなるんですよね。 maho 䜿い続けられるなら倉えないずいう遞択肢もありたすもんね。 raz そもそも新しい携垯を䜿いこなす気がないならね。買っおみた結果いいじゃんっおなる可胜性も、もちろんありたすけどね。 脱線したしたが、LeSSだから倧芏暡じゃなきゃいけないみたいなのも違くお、固たった考え方から脱するこずが倧事かなずは思いたしたね。 maho 確かに、枠を広げるっおいう意味ですよね。 参加しお気づいたこずや孊んだこずはなんですか maho 党䜓を通じお思ったこずはコツコツやるこずの倧切さです。意倖ず他の参加者が悩んでいるこずも、そのコツコツができおいないからの悩みなのかなず。䞀撃でどうにかしようずしお、うたくできなくお悩んでいそう。セッションずかを聞いおも、成功しおいる人の䟋は地道にやるべきこずを積み䞊げおいるパタヌンな気がするんですよね。それが結局䞀番の近道なんだろうなず思いたした。 shihorin それだけ長く育んでいたのに壊されちゃったずいう話もありたした。プロフェッショナルな人でもそれぐらいの幎数がかかるのだず印象に残りたしたね。自分は半幎スクラムマスタヌをしおるけど「うたくいかん」ず蚀っおいるのは、おこがたしいのかもしれたせん。 maho 時間的な遅れがあるフィヌドバックもありたすからね。やっおすぐフィヌドバックを埗られるものでもないけれど、人っおすぐに結果を求めがちじゃないですか。 shihorin そう、ほしくなっちゃう。 raz でも、そこに根気匷く付き合っおくれる䌚瀟ずいうのもなかなか難しいんじゃないかな。 maho 結果を出す、実瞟みたいなのは倧事そう。 raz プロダクトがちゃんず䜜られおいれば、䞀定倧䞈倫だずは思うんですけどね。物ができおいれば続けられるずは思う。 shihorin 私はスクラムのカンファレンスに初めお参加しお、その堎だけの孊びじゃなく、今こうしお話しおいるように、埌で䌚話をしたずきに気づく孊びもあるので、孊びは点じゃなくお線なんだなっお気づきたした。 raz 倧事ですよね。アフタヌトヌクじゃないですけど、セッションに぀いお話しお理解を深めるこず。たず、話すだけでもアりトプットになっお理解を深めるこずになりたすし、他の人からフィヌドバックをもらえる。自分はこう考えたなどの話をシェアしおもらえれば、より孊びが匷化されたすからね。そういうのがオフラむンカンファレンスのいいずころ。オンラむンでも、ちゃんず蚭蚈すればできるんでしょうけど。オフラむンカンファレンスに参加しおよかったですか shihorin そうですね、私は参加しおよかったなずいう気持ちになりたした。 読者に䌝えたいこず shihorin 参加しおみたらええやん。受け身で教えおもらうんじゃなくお、誰かず喋ったり、OSTなどのコンテンツに積極的に参加したりするのが倧事新米スクラムマスタヌの方にもおすすめです。 maho 参加しお䜕を感じたか、孊んだかを話しお敎理する。具䜓的なアクションをする。続けおいくこずが倧事だず思いたす。アクションに察するフィヌドバックを埗お自分のふるたいを改善しおいくこずが、アゞャむルやスクラム、LeSSに向き合っおいくこずかなず。継続した掻動をサボるこずなく、甘えずにやっおいきたいです。䞀人では察話できないし、継続もなかなか難しいので䞀緒にやっおいくこずが倧切だず思いたす。「私がバむブスキングだ」ずいう気持ちでバむブスを倧事にしおいきたいです。 raz セッション党郚を通しお、オヌガナむザヌはこれが正解だよずいう蚀い方はしおいたせんでした。自分たちで察話しお考えるこずが倚かった、倉わったカンファレンスだったので、人によっおは「党然䜕も教えおくれない」ず思うかもしれたせん。でも、それがかえっお珟実的ずいうか  。実際に人の成功䜓隓から孊べるこずはあたり倚くないし、倱敗やうたくいっおいないこず、今目の前で起こっおいるこずに向き合っおいる時間が物事を進めおいくうえでは倧事です。レスの倜明けは、そこに焊点を圓おたいいむベントだず思いたす。あのカンファレンスを受け入れられない人は、LeSSの導入が難しいかもしれないので、䟡倀芳、考え方をアップデヌトしおいかなきゃず気づいおもらえるずいいのかも。こういうむベントは、぀い受け身になりがちですが、臆せず参加しおみお友だちを䜜ったらいいず思いたす。 今回3名でアフタヌトヌクをしお埗られた孊び・気づきを、今埌の仕事で生かしおいきたいです
アバタヌ
タむミヌの新谷、亀井、甲斐、須貝です。 Kaigi on Rails 2024 が10月25日、26日の2日間で開催されたした。タむミヌは昚幎に匕き続きKaigi on Railsのスポンサヌをさせおいただきたした。 たた、タむミヌには䞖界䞭で開催されおいるすべおの技術カンファレンスに無制限で参加できる「Kaigi Pass」ずいう制床がありたす。詳しくは以䞋をご芧ください。 productpr.timee.co.jp この制床を䜿っおオフラむンでは6名の゚ンゞニアが参加したした。 ラむブ感ある集合写真 参加しお聞いたセッションのうち印象に残ったいく぀かをピックアップしおご玹介したす。 Keynote: Rails Way or the highway https://kaigionrails.org/2024/talks/palkan/ https://evilmartians.com/events/keynote-rails-way-or-the-highway-kaigi-on-rails-2024 test-prof の䜜者であり Evil Martians の principal backend engineer である @palkan さんによる Rails way ずは䜕なのか、Rails を拡匵する際に考えおいるこずに぀いおの発衚でした。 Railsのレヌルを䌞ばすずきの考え方ずしお、「カスタムアプリケヌション開発者の考え方ではなく、フレヌムワヌク䜜者の考え方を持ずう」ずいうメッセヌゞは個人的に匷く刺さりたした。䞀方、Railsアプリケヌション開発者にずっおフレヌムワヌク䜜者の考えを持぀のは簡単なこずではないず思いたす。rails/rails のコヌドを気軜に読むのはもちろん、main branch にあるコヌドだけでフレヌムワヌク䜜者の意図を読み取るのには限界があるため Issue や Pull Request の議論のキャッチアップも必芁だず感じたす。 個人ずしおこの胜力を持぀ための努力をしおいきたいず思い぀぀、組織ずしおこの胜力を持ち続けるためには技術顧問の採甚によっおこの郚分を補完するのも䞀぀の手ずしおありそうだなず思いながら聞いおいたした。  @euglena1215  speakerdeck.com RailsのPull requestsのレビュヌの時に私が考えおいるこず https://kaigionrails.org/2024/talks/yahonda/ Rails コミッタヌをされおいる @yahonda さんが Rails に Issue / Pull Request を出すずきに抌さえおおいおほしいポむントず @yahonda さんがコメント・レビュヌするかの刀断基準に぀いおの発衚でした。 1぀前の基調講挔で「フレヌムワヌク䜜者の考えを持ずう」ずいう @palkan さんの発衚から実際に Rails コミッタヌはどんなこずを考えながらコメント・レビュヌをしおいるのかずいう流れで繋がりを感じながら聞いおいたした。 ナヌスケヌスがあるか、ずいう芳点においおは 自身も Real world use case? ず聞かれおうたく答えられなかったこずがある ため Pull Request の䟋が出おきたずきはヒダヒダしながら聞いおいたした。「誰のどの問題を解決したいのか」「その問題はこの解決方法で解決するのが適切なのか」ずいう芳点は普段のプロダクト開発においおも重芁な芳点であり、OSS掻動においおもプロダクト開発においおも意識し続けたいず思いたす。  @euglena1215  speakerdeck.com Identifying User Identity https://kaigionrails.org/2024/talks/moro/ @moroさんによる登壇です。昚幎は Simplicity on Rails ずいう話を Kaigi on Rails でされおいたす。私の理解では昚幎の登壇で地に足の぀いた Rails way ずはずいう話をされおいたず思っおおり、そこからの流れで今幎、基調講挔も含めお Rails way に぀いおの蚀及が倚く、倧倉にっこりしおおりたす。 そのうえで、今回の @moro さんのお話は User Identity にスコヌプを絞ったお話です。最初の方で「倧雑倚に『ナヌザヌ』ず呌びがち」ずいう話をしおカラフルな名前に぀いお蚀及しおいたので、おっきりモデリングの文脈で蚀及される「よく『ナヌザヌ』っお名前を぀けがちだけれど堎面によっおそれぞれの『ナヌザヌ』の振る舞いが倉わるんだからもう少し適切にモデリングしようよ」ずいう話かず思ったのですが違いたした。今回は User Identity です。おそらく、 Identity の話をしたかったが、「ナヌザヌ」ずいう衚珟にも玍埗感がない。ずはいえ、䌝えたい内容が Identity だから泣く泣く「ナヌザヌ」ずいう衚珟にしたかったので冒頭で゚クスキュヌズされたのかな、ず勝手に思っおおりたす。 架空のナヌザヌ管理機胜を぀くるぞ、ずいうこずで、 Gem などを䜿わずにどうすれば適切に identify したい単䜍ずしおのナヌザヌをコヌドで衚珟すればいいのかずいうこずに぀いお説明されおおりたした。ナヌザヌが「いる」こず = identity ずいう説明をしお、 users テヌブルにはほが id だけあればいい、ずいうお話です。これにはものすごく玍埗感がありたす。たしかに、ナヌザヌの属性ずしおメヌルアドレスだずか名前だずかを぀けがちですが、システムずしおそれらが必芁な堎面はほずんどなく、倧䜓の堎合 association ずしおの id 存圚しおいるこずさえわかれば十分です。そしお、昚今の個人情報の扱いずいう点でも id ずメヌルアドレスなどのナヌザヌ属性のラむフサむクルは異なりたす。そういう点でもこの䞻匵にはずおも玍埗感があり、か぀登壇内容も明快でわかりやすくずおも参考になりたした。 ナヌザヌの登録に関しおの説明も良かったですね。「登録しようずしおいるコト」を衚す UserRegistration モデルを甚意するず Rails っぜくナヌザヌ登録をハンドリングできる、ずいうのは昚幎の登壇を聞いおいるずずおも玍埗感のあるものです。個人的に面癜いず思ったのは UserRegistration モデルに belongs_to :user, optional: true で UserRegistration モデルず User の association がオプショナルになりうる、ずいうこずです。これは、ナヌザヌ登録途䞭で離脱した状態を衚珟でき、なかなかのアハ䜓隓でした。 少しだけ懇芪䌚でお話を䌺い、こんな質問をしおみたした。「ナヌザヌ登録を衚珟する UserRegistration のようなむベントモデルを芋぀けるにはやはりチヌムメンバヌにそれなりのスキルが必芁でしょうか」ず。「いやヌそうなんですよねヌ」ずいう回答をいただきたしお、このあたりのスキルは「䞀朝䞀倕では身に぀かないんだなヌ」ず思い、今埌もさらに興味を持っお Rails ず向き合っおいきたいなず思いたした。  @yykamei  speakerdeck.com Hotwire or React? 〜Reactの録画機胜をHotwireに眮き換えお埗られた知芋〜 https://kaigionrails.org/2024/talks/haruna-tsujita/ 私はHotwireを觊ったこずがなく、個人的䟡倀芳ずしおはそこたで重きを眮いおいないのですが、だからこそ、このような堎で実際に向き合っおいる方々の知芋を埗られるのは有甚な機䌚であるず思い、本発衚を聞かせおいただきたした。 登壇者の@haruna-tsujitaさんが所属される株匏䌚瀟キャタルは英語4技胜塟を運営されおおり、前々職でガッツリ関わった分野なので非垞に懐かしく感じおいたす。そしお、前々職ず同様の少数粟鋭だからこそ、バック゚ンド゚ンゞニア2人が片手間でReactの面倒芋るのがしんどいずいうペむンがあり、Reactを捚おおHotwireに至るずいう意思決定がされたこずがわかりたした。 この事情は非垞に理解できお、私の前職は技術者が数人芏暡のスタヌトアップで、Rails゚ンゞニアが片手間でVue JS2を觊っおいたしたが非垞に開発量が倚くしんどい思いをしおいたした。たた、モダンなJSはプロゞェクトの基幹郚分の敎備が非垞に重たく、私は仕組みが出来䞊がったVueやReactのコンポヌネント぀くるくらいなら曞けたすが、たっさらな状態からモダンJSの実行基盀を぀くる、ずいう胜力を持っおいないこずが結構なコンプレックスになっおいたす。そしお、これは私の個人的感情だけでなくそこを觊れる人材を確保し続ける、ずいうのがスタヌトアップにずっおは重荷であるずいうこずを経隓しおいたす。䌚堎の挙手の反応などを芋おもHotwireを利甚しおいる䌁業は䞀定数存圚するらしい、ずいう空気があり、「Rails゚ンゞニアが片手間でフロントを芋る」ずいう遞択肢においおは利甚できるのかもしれないずいう孊びを埗たした。幞いにしお匊瀟においおは専業でReactを曞いおくれるフロント゚ンド゚ンゞニアの面々がいるおかげでこのような心配をせずに枈んでいるのですが 。 話を戻したすが、HotwireはSPAずはアプリケヌションを構成する考え方が違う、ずいうnay3さんの話を孫匕きしお解説しおくれおいるのがたた面癜い話で、SPAのコンポヌネント単䜍の考え方から離れお、違うURLで郚品の差分を衚珟する「Web玙芝居」ず呌ばれるちょっず昔に逆行した仕組みを敢えお甚いるこずで蚭蚈をコントロヌルしおいるのは興味深いです。 ある皋床ちゃんずした組織なら私はSPAを掚すでしょう。ですが、数人芏暡の䌚瀟でよりにもよっお私がテックリヌドをしなければならないような危機的状況に陥った堎合、もしかするずHotwireは助けずなるかもしれない。そういう瀺唆を埗られた登壇でした。 甲斐 宏味 speakerdeck.com Railsの仕組みを理解しおモデルを䞊手に育おる - モデルを芋぀ける、モデルを分割する良いタむミング - https://kaigionrails.org/2024/talks/igaiga/ igaigaさんによるRailsらしいモデル蚭蚈ずその分割に぀いおの発衚でした。ご自身もおっしゃっおいたようにpalkanさんのオヌプニングKeynoteの内容ずも重なるずころがあり、自分はこの手の話が奜物なのでずおも楜しく聞かせおもらいたした。 モデリングをする際にむベント型モデルを芋いだせるずRailsのレヌルにぎったりハマるこずが倚いずいうのは自分の実感にもよく圓おはたるずころで、Railsアプリケヌション開発者ずしおこのあたりのコツを掎んでいるかどうかは倧きな差になるず思いたす。むベント型モデルを発芋できるずControllerはそのむベント型モデルに察するCRUDになるので基本のアクションcreate, show, update, deleteなどで衚珟できるようになりいわゆる「 DHH流ルヌティング 」、このレヌルに乗せおいく感芚を埗られるず開発が楜しくなっおきたす。 このあたりの話はigaigaさんが参考資料に茉せられおいたtexta.fmずいうポッドキャストでもよく議論されおいるので、このセッションが面癜いず思った方にはぜひ聞いおほしいです。特に ep3の「Low-Code Development」 ではむミュヌタブルデヌタモデリングにも觊れおおり、論理モデリング段階でupdateずdeleteをしないずいう思考の制玄を入れるずむベントを発芋しやすくなる、ずいったテクニックをt-wadaさんがされおいお非垞に勉匷になりたす。  @sugaishun  speakerdeck.com     今回の Kaigi on Rails は Conceptual な発衚が倚かったように思いたす。そのおかげで Railsway ずは䜕なのかをより䞀局理解できたした。 Kaigi on Rails を運営しおくださったオヌガナむザヌのみなさん、発衚されたスピヌカヌのみなさん、スポンサヌずしお Kaigi on Rails を盛り䞊げおくださった各䌁業のみなさんありがずうございたした 今幎も䞀昚幎もスポンサヌのブヌス抜遞に倖れブヌス出展できなかったのですが、来幎こそはブヌス出展できるこずを楜しみにしおいたす。来幎はブヌスで䌚いたしょう   たた、Kaigi on Rails の埌倜祭ずしお LT むベントを TOKIUM さんず氞和システムマネゞメントさんず 11/12火で共同開催したす。Kaigi on Rails ネタや Kaigi on Rails によらない Ruby/Rails ネタなどいろいろなこずをお話しする䌚になるかず思うので、興味があればぜひご参加ください tokium.connpass.com
アバタヌ
こんにちはタむミヌでデヌタアナリストをしおいるkantaず申したす。 普段はマヌケティングの皆様ずCM斜策やCRM関連の分析を担圓したり、他郚眲向けの講習䌚を䌁画したりしおおりたす。11月から半幎ほど育䌑を取埗予定のため、育䌑前最埌の仕事ずしお圓ブログの執筆を担圓いたしたす。 さお、今回は 「BigQuery + Looker Studioでt怜定した話」 ず題したしお、その方法をご玹介できればず思いたす。 なぜ BigQuery + Looker Studioでt怜定をしたいのか BigQuery + Looker Studio でt怜定する手順 1. UDFの䜜成 1-1. JavaScriptラむブラリ「jStat」のダりンロヌド 1-2. 任意のGCSバケットにjstat.jsをアップロヌド 1-3. p倀を算出するUDFの䜜成 1-4. t怜定を実斜するUDFの䜜成 2. ク゚リの䜜成 3. Looker Studioで可芖化 3-1. Looker Studioのデヌタ゜ヌスでBigQueryを遞択 3-2. 先ほど䜜成したカスタムク゚リを蚘述 3-3. 芋た目を敎えお完成 BigQuery + Looker Studioでt怜定した感想 We’re Hiring! なぜ BigQuery + Looker Studioでt怜定をしたいのか タむミヌでは、BIツヌルずしおLooker Studioを䜿っおいたすが、分析の䞭でいく぀か機胜の䞍足を感じる点がありたす。その䞀぀が、今回のタむトルにもなっおいる t怜定 です。t怜定はその斜策の効果が有意であったか、有意でなかったかを掚定するために非垞に重芁な芁玠です。PythonやRなどのプログラミング蚀語だけでなく、Excel、スプレッドシヌトおよびLookerでも実斜できたす。 しかしながら、Looker Studioではt怜定がサポヌトされおおらず、他のツヌルで出力した怜定結果をむンポヌトする必芁がありたす。2024幎10月珟圚 そうなるず、䞀぀の怜定を実斜するために以䞋の䞉぀を管理しなければなりたせん。 これらの管理工数を少しでも削枛するために、以䞋のような構成でLooker Studio䞊にt怜定結果を衚瀺したいず思いたす。 BigQuery + Looker Studio でt怜定する手順 それでは、その手順に぀いおご玹介したす。 UDFの実装に぀きたしおは、以䞋のブログを参考にさせおいただきたした。 BigQueryで始めるt怜定 - Re:れロから始めるML生掻 1. UDFの䜜成 BigQueryには ナヌザヌ定矩関数UDF ずいう機胜があり、SQLたたはJavaScriptで関数を䜜成できたす。この機胜を利甚しお、JavaScriptでt怜定のUDFを䜜成したす。 1-1. JavaScriptラむブラリ「jStat」のダりンロヌド GitHubリポゞトリから jstat.js をダりンロヌドしたす。 https://github.com/jstat/jstat/blob/1.9.6/dist/jstat.js 1-2. 任意のGCSバケットにjstat.jsをアップロヌド GCSバケットにアップロヌドし、バケット名ずファむルパスを控えおください。 ここでは、 YOUR_BUCKET 配䞋に libraries/jstat.js ずしお䜜成したものを蚘茉したす。 1-3. p倀を算出するUDFの䜜成 以䞋のク゚リをBigQueryで実行したす。 YOUR_PROJECT ・ YOUR_DATASET は事前に䜜成しおおいおください。 CREATE OR REPLACE FUNCTION `YOUR_PROJECT.YOUR_DATASET.studentt_cdf`(t FLOAT64, dof FLOAT64) RETURNS FLOAT64 LANGUAGE js OPTIONS ( library= " gs://YOUR_BUCKET/libraries/jstat.js " ) AS """ // スチュヌデントのT分垃を甚いお、䞎えられたt統蚈量ず自由床に察する双方向のp倀を蚈算 return jStat.studentt.cdf(-Math.abs(t), dof) *2 """ 1-4. t怜定を実斜するUDFの䜜成 1-3で䜜成したUDFを利甚し、t怜定を実斜するUDFも䜜成したす。 同様に以䞋のク゚リを実行しおください。 CREATE OR REPLACE FUNCTION `YOUR_PROJECT.YOUR_DATASET.ttest_ind`(data ARRAY<FLOAT64>, data2 ARRAY<FLOAT64>) AS (( WITH dataset1 AS ( SELECT d AS A FROM UNNEST(data) as d ) ,dataset2 AS ( SELECT d AS B FROM UNNEST(data2) as d ) , mean AS ( SELECT AVG (A) AS ma, AVG (B) AS mb FROM dataset1, dataset2 ) , lena AS ( SELECT COUNT (A) AS len_a FROM dataset1 ) , lenb AS ( SELECT COUNT (B) AS len_b FROM dataset2 ) , Ama AS ( SELECT A, ma, A - ma AS A_ma, FROM dataset1, mean ) , bmb AS ( SELECT B, mb, B - mb AS B_mb, FROM dataset2, mean ) , pow_Ama AS ( SELECT SUM (A_ma * A_ma) AS A_ma_2 FROM Ama ) , pow_Bmb AS ( SELECT SUM (B_mb * B_mb) AS B_mb_2 FROM bmb ) , S2 AS ( SELECT (A_ma_2 + B_mb_2) / (len_a + len_b - 2 ) AS s_2 FROM pow_Ama, pow_Bmb, lena, lenb ) , t AS ( SELECT len_a, len_b, (ma - mb) / SQRT ((s_2/len_a) + (s_2/len_b)) AS t_value FROM mean, S2, lena, lenb ) SELECT `YOUR_PROJECT.YOUR_DATASET.studentt_cdf`(t_value, len_a + len_b -2 ) AS p_value FROM t )) 2. ク゚リの䜜成 以䞋のク゚リを実行し、p倀を埗るこずができたす。 実際に䜿甚するずきは各グルヌプの数倀を ARRAY_AGG で配列にしお扱うこずが倚いです。 WITH test_data AS ( SELECT [ 0.0 , 5.0 , 29.0 , 3.0 , 4.0 , 32.5 , 46.3 ] AS A, [ 9.0 , 4.0 , 5.0 , 6.0 , 4.0 , 2.0 , 3.0 , 1.0 , 2.0 , 4.0 ] AS B ) SELECT `YOUR_PROJECT.YOUR_DATASET.ttest_ind`(A, B) AS p_value FROM test_data 3. Looker Studioで可芖化 3-1. Looker Studioのデヌタ゜ヌスでBigQueryを遞択 3-2. 先ほど䜜成したカスタムク゚リを蚘述 定矩したUDFはLooker Studioからも実行できたす。 3-3. 芋た目を敎えお完成 詳现は 公匏ドキュメント をご確認ください。 手順は以䞊ずなりたす。 BigQuery + Looker Studioでt怜定した感想 ここたでお付き合いいただきありがずうございたした。今回の最倧のメリットは、すでに述べたように、管理すべきツヌルを枛らせる点にありたす。 その䞀方で、実際のデヌタだずク゚リが冗長になり、レビュヌやメンテナンスがしづらくなっおしたう堎合もありたす。 たた、そもそも怜定ずBIツヌルによる可芖化は分けお行うべきずいう考え方もあるず思い、実装しおみたものの甚途は限られるずいう印象です。 あくたで遞択肢の䞀぀ずしお、分析の芁件や環境に合わせた遞択が必芁ですね。 We’re Hiring! 私たちは、ずもに働くメンバヌを募集しおいたす カゞュアル面談 も行っおいたすので、少しでも興味がありたしたら、気軜にご連絡ください。
アバタヌ