every Tech Blog

株式会社エブリーのTech Blogです。

日本CTO協会の合同新卒研修に参加しました

はじめに

こんにちは、株式会社 エブリー の24新卒の蜜澤、きょー、新谷です。
今回は、2024年5月から7月にかけて開催された日本CTO協会主催の合同新卒研修に参加した際の内容と学びについてご紹介します。

合同新卒研修とは

本研修は、日本CTO協会が主催する新卒エンジニア向けの合同研修です。新卒エンジニアが業界全体・企業横断で育てられる試みとして、今年から開催されました。

日本CTO協会が新卒エンジニアを業界全体・企業横断で育てる試み「新卒エンジニア向けの合同研修」を5月29日から実施

上記記事にも書いてありますが、開催に至る背景として

  • 現状企業が経営・事業を大きくする、新たなチャレンジをする上でもエンジニアが常に足りない状況にある
  • スタートアップや中小企業が新卒エンジニアを採用するには、採用コストだけではなく育成のコストも大きくかかる

といった課題があることから、本研修が開催されています。

また講義は毎回オフラインで行われ、その後開催される懇親会では、他社の新卒エンジニア同士で交流を深めることができました。(懇親会では毎回お酒と軽食が用意されているので、和気あいあいとした雰囲気で交流ができました!)

研修内容

研修回 講義内容 講師
第1回 キャリア戦略・フォロワーシップとマネジメント 日本CTO協会 / 株式会社LayerX
第2回 Git基礎ハンズオン 株式会社Progate
第3回 BtoB SaaS開発基礎 株式会社アンチパターン
第4回 インテリアコーディネートで学ぶアジャイル開発 株式会社メンバーズ
第5回 BigQueryで始めるデータ分析入門 & 生成AIを活用した分析効率化 グーグル・クラウド・ジャパン合同会社
第6回 AWS研修 アマゾンウェブサービスジャパン合同会社
第7回 サーバ解体研修 GMOペパボ株式会社
第8回 生成AIに関する講義 日本マイクロソフト株式会社
第9回 日本CTO協会ISUCON新卒研修 + 解説 株式会社PR TIMES

24卒の新卒エンジニア3人でこの研修に参加させていただいので、1人1つずつ講義の内容をピックアップし、それぞれの講義内容と学びについて紹介します。

キャリア戦略・フォロワーシップとマネジメント

開発本部のデータ&AIチームの蜜澤です。

私からは「第1回:キャリア戦略・フォロワーシップとマネジメント」の紹介です。
講義を担当してくださったのは、日本CTO協会 理事 / 株式会社LayerXの松本CTO(@y_matsuwitter)です。

この講義は

  • 前編:投資的に考えるキャリアのあり方
  • 後編:フォロワーシップとマネジメント

の2つのパートに分かれていたので、それぞれのパートについての学びを紹介します。

前編:投資的に考えるキャリアのあり方

信頼や信用、知識や経験、時間といった自分が持っている「人生の資産」を、自分の仮説や学びたい方向性に向けて効率よく投資し、資産を拡大させていくという「投資家的に考えるキャリアのあり方」について学びました。

今自身に必要な資産を考え、自分の手元の投資可能な資産(お金、時間、信用など)をどのように配分し、どのようなリターンを期待するのか、抱えるリスクはなにかというポートフォリオを作成し、資産を拡大していくことが重要とのことでした。

何を投資するのか?

新卒の私には、たいした資産(特に知識や信用)はありません。
いったい何を投資すれば、、、

「時間」です!
家庭がなく(現在独身・一人暮らし)、健康上の問題も特にない20代の今が人生で最も可処分時間が多いです。
この20代の時間を最大限未来に投資していくことの重要性を松本さんは強調されていました。

「ドキッ!」
とした人も多いのではないでしょうか。
私もその一人です。

可処分時間を未来に投資していくことの重要性を理解しても、私のような遅延評価(必要になったらやる)型の人間は、今必要でないことはサボってしまうことがあると思います、、、

そんな時に努力を習慣化し、投資を続ける助けとなるのが「コミュニティ」のようです!

コミュニティの力

「コミュニティの平均値が自分」や「周りの5人の平均が自分」などの言葉はよく耳にします。
松本さんが所属していたコミュニティから次々とCTOが誕生したという話を伺い、より自分が所属するコミュニティの重要性を感じました。

そして、コミュニティにおいて特に重要だと思ったのが「健全な嫉妬」です。
仲間の昇進や技術的な成長を目の当たりにすると、私たちは「あいつには負けられない」という健全な嫉妬を感じます。
「健全な嫉妬心を努力の習慣化に繋げることで成長する」というのがコミュニティの力だと思いました。

幸いにも私の周りには同期や、CTO研修で出会った同世代のエンジニアといった切磋琢磨できる仲間がいます!
この中で一番になるという気持ちで、努力(投資)を続けていかなければと考えさせられる前編でした。

後編:フォロワーシップとマネジメント

マネージャーの仕事は、単に管理するだけではなく、チームの成果を最大限高めることだと学びました。

チームで大きな成果を出すために

チームの成果は、一人一人のモチベーションと能力の掛け算の総和であり、全員がモチベーション高く、かつ専門性を発揮できると大きな成果が出ると松本さんは考えているようです。

そのモチベーションのために、一人一人が納得感と自信を持てるように、意思決定をし、内容を言語化して伝え、メンバーを導くのがマネージャーの重要な役割のようです。

役割は分かりましたが、実際にやるのとても難しそうだなと感じました。
メンバーのモチベーションの源泉を考え、納得感を持ってもらうためにメンバーのことをよく理解するとういう難しい役割を日々担っていただいているマネージャーには頭が上がりません。

マネージャーを支えるために私たちにできることも教えていただきました!

こまめな自己開示

マネージャーとうまく連携するには、自己開示が重要だそうです。

自己開示のコツは、何が楽しいか、何を目指したいか、何がわからないか、何が目標でどのような状況かをこまめに伝えることだとわかりました。

わからないことは頻繁に聞きますが、「何が楽しいか」や「目標と今の状況」などはこまめに伝えられていないなと反省しました。
「私自身が自己開示したつもりになっていても、マネージャーには伝わっていなかった」ということはよくありそうだなと思い、自分のことをどれだけ理解してもらえているのか確認しつつ、こまめにコミュニケーションをとっていくことが大切だなと思いました。

マネージャーを理解する

自己開示だけではなく、マネージャーを理解することも大切だと教えていただきました。
「あなたのマネージャーの目標はなんですか?」と聞かれましたが、この時の私はわかりませんでした。

マネージャーを理解することで自分が何をすべきかわかると思ったので、1on1やチームでのランチ会の時に「マネージャーの目標」や「休みの日に何をしているのか」などを聞いてみました!

ということで、少しだけ私のマネージャーについて紹介します!!

私のマネージャー

  • 短期目標:マネジメントしながら手を動かすプレイングマネージャー的に技術を高めていきたい
  • 長期目標:全体的に組織を見て、率いていきたい
  • チーム目標:各自の専門性を深めつつ、専門性+αのことをできる組織にする
  • 休日の過ごし方:お子さんと遊ぶことが多いが、最近は暑いので大変

まだまだ理解不足ですが、実際に聞いてみたことで、私はこれから専門性(データ系)に加えて、+α(バックエンドやインフラ等)の知識も身につけていく必要があるということを認識できました。

私のチームにはマネージャー以外にも上司が4人おり、マネージャー以外の方々のことも理解する必要があると思うので、コミュ二ケーションを頻繁に取っていこうと思います!

フォロワーシップはマネジメントのスタートライン

マネージャーを支えるとは、マネージャーを理解しようとすることで、その視点を手に入れるということは、自身がマネジメントへ進む準備運動であると学びました。
将来的にはマネジメントにも関わりたいと思っているので、フォロワーシップを磨き、準備運動を完了させようと思います!

今後に向けて

この研修を5月末に受けたので、この研修から約3ヶ月が経ちました。

しかし、この研修で学んだ、可処分時間を有効活用し、最大限に未来に投資するというのができているかと聞かれると、まだまだできていないと思います。

この記事の執筆にあたり研修の内容を振り返る良い機会になったので、健全な嫉妬心を燃やし頑張ります!

サーバー解体

こんにちは、開発本部 DELISH KITCHEN 開発部のきょーです! 僕の方からは GMO ペパボ株式会社様に講義をしていただいた「サーバ解体研修」について紹介していこうと思います。

講義の名前からわかるかもしれませんが、実際にサーバを解体していく内容です!とてもワクワクしますね!僕自身家にサーバもなければ自作 PC を組み立てたこともなかったので、この機会に物理サーバを解体しまくって理解を深めるぞ!と息巻いて講義に臨みました。

解体するぞ!!

参加者は何班かに別れた後、GMO ペパボの社員の方にサポートしていただきながら既に組み立てられているサーバを解体していきます。

最初は ↓ のような状態です。

天板を外すと ↓ のような感じに。ここにびっしり詰まっているそれぞれの部品を解体していいんだ、、、と思うと早く手を動かしたくなりました。 この時点でファンが 4 つ、CPU、メモリ、電源ユニットが 2 つあることがわかるかと思います。電源ユニットが 2 つある理由としては電源の供給元を分散させることによって 1 つの供給元が落ちたとしても稼働し続けられるように、とのことでした!いろんなことが考えられて設計されていることを学びました。(教えてくれたメンバーの方ありがとう!)

ここからは班のメンバーで手分けしていきながら解体作業に移っていきます。最初はおっかなびっくり解体していたメンバーも ↓ のようにサーバが解体され尽くされる頃には「これって取れるかな?」と手を動かしていてとても面白かったのを覚えています笑

解体していく!!

解体しました。正直ここまで解体できるとは思っていなかった、、、達成感えぐい、、、(メモリの部分を外した時の写真取り忘れた)

また解体しやすいように部品が配置されている設計にとても驚きました。外したいものだけを外せるし、戻したいときもすぐ戻せる、そのような部品の配置、ケーブルの配線になっていて感動しました。(ソフトウェアも交換したい部分だけを交換できるように設計することは大切ですよね。) 一つ一つの部品が組み合わさり PC が完成されていることを学べたとても貴重な機会だったと思います。

元に戻すまでが研修ということで、これから組み立て直していきます。 難しいかと思いましたが、解体しやすかった分元に戻すのも手順さえ覚えておけば簡単でした!

無事に元に戻せました!!おめでたい!!

サーバー解体を終えて

解体から元に戻すところまで無事にできました。さてそれでは物理サーバはクラウド技術が発展してきた現代でどのように使われているのでしょうか? 全てクラウドを使ってサービスを運用することは可能です。しかし適切に物理サーバを用いることで運用コストを下げたり、パフォーマンスをあげたり、セキュリティ面を強固にすることができるとのことでした。例えば、クラウドのストレージは格納するデータ量によってコストがかかりますが、物理サーバにそれらを配置することでコストが抑えられるかもしれません。また、機密データ等は物理サーバに配置することでセキュリティの強化を見込めます。

適切にクラウドなのか物理サーバを使うのかを判断できるようになることで考えられる選択肢に幅を持たせられ、エンジニアとして成長できると講師の方が言っていました。クラウドしか触ったことがない自分にとっては実際に分解することで物理サーバの知識や興味を深められ、エンジニアとして成長できる一歩を踏めたと感じています!

P.S

自分たちのサービスである DELISH KITCHEN であれば高解像度の動画や画像を取り扱っているので、それらを物理サーバに配置することで運用コストが下がるのではないか、、?と妄想したりしました。もし物理サーバを導入するとした場合、サーバの購入費や、どこにサーバを配置するのか、既存から乗り換えるのにどれくらいコストがかかるのか、など考えなければいけないことがたくさんありそうです。

また、懇親会の時に HDD も解体してきました!!元には戻せませんでした!!!!

ISUCON 研修

DELISH KITCHEN 開発部でソフトウェアエンジニアをしている新谷です。私からは第9回のISUCON研修について紹介します。

ISUCON研修では、本番のISUCONのようにチームで与えられた問題に取り組む形式で行われました。

そもそもISUCONとは、「いい感じに スピードアップ コンテスト」の略称で、お題となるWebサービスを決められたレギュレーションの中でどれだけ高速化できるかを競う大会のことです。

事前準備

私はISUCONには参加したことはないのですが、事前にISUCON研修に参加する人たちで有志の勉強会が開かれたのでそれに参加していました。そこでは、ISCUONでよく使われるツールやテクニックについて知ることができ、研修当日に備えることができました。

ツールとしては以下のようなものがあり、研修当日に活用しました。

  • pt-query-digest
    • slowqueryの解析に使うツール
    • mysqlのログを解析してsqlが遅い順に表示される
  • alp
    • NGINXのアクセスログの解析に使うツール
    • 遅いエンドポイント順に表示される

研修当日

研修当日は、計測ツールの導入、ボトルネックの特定、修正を高速に行いました。計測から修正までの一例としてDBへのインデックス追加を行った際の流れを紹介します。

まずpt-query-digestでslowqueryを解析します。以下は解析結果の一部です。上位に書いているクエリほど遅いクエリです。

# Profile
# Rank Query ID                      Response time  Calls R/Call V/M   Ite
# ==== ============================= ============== ===== ====== ===== ===
#    1 0x624863D30DAC59FA16849282... 497.2385 69.5%  1885 0.2638  0.02 SELECT comments
#    2 0x422390B42D4DD86C7539A5F4... 165.4411 23.1%  2016 0.0821  0.01 SELECT comments
#    3 0x100EC8B5C400F34381F9D7F7...  37.9935  5.3%   131 0.2900  0.00 SELECT comments

上記から、SELECT commentsが遅いことがわかりました。そのため、commentsテーブルにインデックスを追加しました。その後再度pt-query-digestでslowqueryを解析します。

# Profile
# Rank Query ID                     Response time Calls  R/Call V/M   Item
# ==== ============================ ============= ====== ====== ===== ====
#    1 0x4858CF4D8CAA743E839C127... 48.3164 44.0%    933 0.0518  0.00 SELECT posts
#    2 0x7A12D0C8F433684C3027353... 10.2537  9.3%    160 0.0641  0.00 SELECT posts
#    3 0xDA556F9115773A1A99AA016... 10.1553  9.3% 126417 0.0001  0.00 ADMIN PREPARE
#    4 0x396201721CD58410E070DA9...  8.3778  7.6%  58802 0.0001  0.00 SELECT users
#    5 0xCDEB1AFF2AE2BE51B2ED5CF...  8.3270  7.6%    191 0.0436  0.00 SELECT comments
#    6 0x19759A5557089FD5B718D44...  7.2387  6.6%  15215 0.0005  0.00 SELECT posts
#    7 0x624863D30DAC59FA1684928...  4.1172  3.8%  23976 0.0002  0.00 SELECT comments
#    8 0x422390B42D4DD86C7539A5F...  3.9942  3.6%  25103 0.0002  0.00 SELECT comments

インデックスを追加したことで、SELECT commentsのクエリが大幅に高速化されました。このように、計測してボトルネックを特定し、ピンポイントで修正を行っていきました。上記の流れで、他にもNginxへのキャッシュやクエリのチューニング、N+1問題の解消などを行い、大方目立ったボトルネックを全て解消することができました。

個人的にN+1を時間内に全て解消することができたのは、自分にとって大きな成長だと感じています。今回のISUCONはGo言語を選択したのですが、普段業務でGo言語を書いていることもあり、比較的スムーズにN+1問題を解消することができました。

結果

最終的に、私たちのチーム「唐揚げ丼」は31チーム中2位という結果を残すことができました。

前半にツール導入に手間取ったりして反省点などありますが、ISUCON本番のような空気感を味わうことができ、とても有意義な研修だったと感じています。

ちなみに、1位の黒酢サンドさんのスコアは2,3位のチームのスコアの2倍以上差があり圧倒的でした。後日記事が公開されていましたが、学ぶべき点が多くありました。

【CTO協会研修記録】 未経験エンジニアがISUCONで圧倒優勝するまでの話

特にhtmlファイルのExecuteが遅かったため、htmlを全てバイト列で持ってレスポンスに書き込むといった点にはかなり驚きました。

研修全体を通して

この研修を通して私たちが得たものは大きく分けて 2 つあると思っています。

1 つ目はエンジニアとして成長するためのきっかけです。 社内で利用しているような技術から触ったことがない技術まで本当に幅広く体験することができました。また、成長するためのキャリアについての考え方も学ぶことができました。ただ学んで終わりにするのではなく、学んだ技術を自分のものにし、どう会社に還元していくかを考え行動することが次のアクションとしてあると思います。そして研修を通していただいた分を何らかの形でこの業界に還元していきたいです!

2 つ目は研修を一緒に駆け抜けてくれた仲間です。 同じ年代の方達と会社の枠を超えて巡り会えたのは一番の財産だと思っています。ここで知り合った仲間とのコミュニティを大事にし、健全な嫉妬を与えたり、受けたりしてこれからも切磋琢磨していきたいです!最初はよそよそしかったですが、研修を通して仲を深め、今では輪読会を行うようにまでなりました!

この研修を開いてくださった日本 CTO 協会の方々と、講義をしてくださった企業様、スポンサーをしていただいた企業様には本当に感謝しています。ありがとうございました!!

VueUse: 5分で分かる Vue.js 開発の効率化術

はじめに

こんにちは、Retail Hub 事業部でエンジニアを務めている 羽馬 です。

この記事は、Vue.js 日本ユーザーグループ主催の Vue.js v-tokyo Meetup #21 で登壇した際の発表資料を元に、VueUse というライブラリを使って Vue.js 開発を効率化する方法をご紹介します。

登壇資料はこちら:

speakerdeck.com

VueUse とは

VueUseは、Vue Composition APIのための包括的なユーティリティコレクションです。以下の特徴があります:

  • 200以上の便利な関数を提供
  • Vue.jsアプリケーション開発の生産性を大幅に向上
  • ローカルストレージ、デバイス情報、スクロール位置、フォームバリデーションなど、幅広い機能をカバー
  • 宣言的で再利用可能なコンポーザブル
  • ライフサイクルフックの自動処理
  • 必要な機能のみをインポート可能(tree-shaking対応)
  • 高度にカスタマイズ可能なオプション

vueuse.org

VueUseを使用することで、複雑な機能を簡潔に実装でき、開発効率を劇的に向上させることができます。

VueUseが提供する主な機能

VueUseは非常に多くの機能を提供していますが、ここでは特に有用な機能をいくつか紹介します:

  1. 状態管理

    • useStorage: ローカルストレージやセッションストレージとリアクティブな状態を同期
    • useState: シンプルな状態管理
  2. センサーと端末情報

    • useMouse: マウスの位置を追跡
    • useGeolocation: デバイスの位置情報を取得
    • useDeviceOrientation: デバイスの向きを検出
  3. ブラウザ操作

    • useClipboard: クリップボードの操作
    • useDark: ダークモードの切り替え
    • useFullscreen: フルスクリーンモードの制御
  4. アニメーションとタイミング

    • useInterval: 定期的な処理の実行
    • useTimeout: 遅延処理の実行
    • useTransition: スムーズな状態遷移
  5. ネットワークとAPI

    • useFetch: HTTPリクエストの簡易化
    • useWebSocket: WebSocketの操作
  6. UI操作

    • useVModel: v-modelの簡易実装
    • useInfiniteScroll: 無限スクロールの実装

これらの機能を使用することで、一般的なWeb開発タスクを簡単に、そして効率的に実装することができます。

VueUseの具体的な使用例

VueUseの機能の中から、特に有用なものをいくつか抜粋して具体的に説明します:

  1. ローカルストレージの利用 (useStorage)

ローカルストレージの利用 (useStorage)

   import { useStorage } from '@vueuse/core'

   const state = useStorage('my-storage-key', { count: 0 })

   // stateを変更すると自動的にローカルストレージに保存される
   state.value.count++

VueUseを使用しない場合:

   import { ref, watch } from 'vue'

   const state = ref(JSON.parse(localStorage.getItem('my-storage-key')) || { count: 0 })

   watch(state, (newState) => {
     localStorage.setItem('my-storage-key', JSON.stringify(newState))
   }, { deep: true })

   // stateを変更する度に手動でwatchを設定する必要がある
   state.value.count++

ダークモードの実装 (useDark)

VueUseを使用する場合:

   import { useDark, useToggle } from '@vueuse/core'

   const isDark = useDark()
   const toggleDark = useToggle(isDark)

   // ダークモードの切り替えが簡単
   toggleDark()

VueUseを使用しない場合:

   import { ref, watch } from 'vue'

   const isDark = ref(false)

   const toggleDark = () => {
     isDark.value = !isDark.value
     if (isDark.value) {
       document.documentElement.classList.add('dark')
     } else {
       document.documentElement.classList.remove('dark')
     }
   }

   watch(isDark, (newValue) => {
     localStorage.setItem('dark-mode', newValue)
   })

   // 初期化時にローカルストレージから設定を読み込む
   isDark.value = JSON.parse(localStorage.getItem('dark-mode') || 'false')

無限スクロールの実装 (useInfiniteScroll)

VueUseを使用する場合:

   import { useInfiniteScroll } from '@vueuse/core'

   const el = ref(null)
   const { arrivedState, reload } = useInfiniteScroll(el, () => {
     // 新しいデータをロードする処理
   })

VueUseを使用しない場合:

   import { ref, onMounted, onUnmounted } from 'vue'

   const el = ref(null)
   const isLoading = ref(false)

   const checkScroll = () => {
     if (!el.value) return
     const { scrollTop, scrollHeight, clientHeight } = el.value
     if (scrollTop + clientHeight >= scrollHeight - 50 && !isLoading.value) {
       isLoading.value = true
       // 新しいデータをロードする処理
       // 処理が完了したらisLoading.value = falseにする
     }
   }

   onMounted(() => {
     el.value?.addEventListener('scroll', checkScroll)
   })

   onUnmounted(() => {
     el.value?.removeEventListener('scroll', checkScroll)
   })

これらの例から分かるように、VueUseを使用することで、複雑な機能をより簡潔に、そして宣言的に実装できます。特に、ローカルストレージの同期やダークモードの実装など、頻繁に必要となる機能を簡単に実装できる点が大きな利点です。

一方で、VueUseを使用しない場合、より多くのボイラープレートコードが必要となり、ライフサイクルフックの管理やイベントリスナーの設定など、細かい実装の詳細に注意を払う必要があります。

ただし、プロジェクトの規模や要件によっては、外部ライブラリに依存せず、Vueの基本機能のみで実装することが適切な場合もあります。特に、使用する機能が限定的で、バンドルサイズを最小限に抑えたい場合などは、VueUseを使用しない選択肢も考慮に値します。

まとめ

VueUseは、Vue.jsアプリケーション開発において非常に強力なツールです。以下に、VueUseを使用することの主な利点をまとめます:

  1. 開発効率の向上

    • 複雑な機能を少ないコードで実装可能
    • 頻繁に使用される機能が既に最適化されて提供されている
  2. コードの可読性と保守性の向上

    • 宣言的なAPIにより、コードの意図が明確になる
    • コンポーザブルの再利用が容易
  3. 学習曲線の緩和

    • Vue.jsのベストプラクティスが組み込まれている
    • 豊富なドキュメントとコミュニティサポート
  4. パフォーマンスの最適化

    • ライフサイクルフックの自動管理
    • tree-shakingに対応し、必要な機能のみをバンドル可能
  5. Vue.jsエコシステム互換性

    • Vue.js 2、Vue 3、Nuxt.jsなど、様々な環境で使用可能

VueUseを活用することで、開発者はビジネスロジックの実装に集中でき、結果としてより高品質なアプリケーションを効率的に開発することが可能になります。ただし、プロジェクトの要件や規模に応じて、VueUseの使用を検討することが重要です。

今後のVue.js開発において、VueUseは重要なツールの一つとなることが期待されます。継続的な学習と実践を通じて、VueUseの可能性を最大限に活用していくことをお勧めします。

プロダクト開発にデータ職責として浸かってみて思ったこと

はじめに

DELISH KITCHENでデータサイエンティストをやっている山西です。

今回は「データサイエンティストとしてプロダクト開発プロジェクトに積極関与した経験談」をお送りします。

背景

DELISH KITCHENをはじめとするプロダクトの開発/改善は、仮説検証サイクルによって日々推進されております。

仮説検証サイクルにより、各機能/改善のリリース後の効果の良し悪しが分析によって振り返られ、次の方策へと繋げられていきます。

本記事では、データサイエンティストの立場で、この仮説検証サイクルを支援するプロダクト改善フローを紹介します。

実践して学んだことや意識したこと等々もポエム調で織り交ぜていきます。

業務フロー

プロダクトの仮説検証サイクルにおけるデータ職責としての業務フローは、

  1. 分析の準備
  2. データの準備
  3. 分析および振り返り

に大別できます。

以下、それぞれの業務感について簡単に紹介します。

1. 分析の準備

KPIとログの設計

プロダクトへの新機能追加/または改善を行う際、リリース後にその結果の良し悪しをKPI、特定の指標で観察することになります。

よって、

何を観測したいか
→そのためにはどんな準備(分析設計/ユーザーの行動ログ)が必要か

をPdM(プロダクトマネージャー)と連携しながら整理していきます。

その具体作業や心持ちは以下の記事に詳しくまとめています。 tech.every.tv

当たり障りの無い主張ではありますが、「目的、仮説をしっかり言語化し共通認識を持ったうえで具体(ログ、分析手法)を詰める」ことの大切さを、実践してみて改めて学ぶことが多々ありました。

ここが疎かになると、

  • KGIからズレたKPIを設定してしまう
    → 視点のすり合わせが出来ていない。アウトカムが意識出来ていない。
  • 仕込んだログが宙に浮いたり一人歩きしたりする
    → ログが使われない、意図されない使われ方をしてしまう。
  • 本来の目的とずれた分析をしてしまう
    → 統計、機械学習的にはリッチでも、ビジネスサイドから見たらSo What?な示唆になりがち
  • 過剰な準備をしてしまう
    → ダッシュボード作ったけど見られない、使われない問題

など、苦い着地をしがちです。

企画時点から一蓮托生的にPdMと視点をあわせることが、より良い仮説検証サイクルを目指すため近道になると感じております。

A/Bテストによる効果検証の準備

プロダクトの開発/改善を振り返るための効果検証のアプローチとしては、A/Bテストを採用することが多いです。

過去にその推進の具体感や全体像についてそれぞれ紹介した記事があるので、よろしければご覧ください。 tech.every.tv tech.every.tv

2. データの準備

分析としての準備が出来たら、次はデータの準備に取り掛かります。

1.で策定した分析計画の具現に向け、ユーザーの行動ログ等のビッグデータを目的に応じた形で利用可能な状態を作り出します。

そのために、

  • Spark, SQLを駆使しつつETLを実装
  • 必要に応じて中間テーブルを実装
  • BIツール(ダッシュボード)による可視化、定期実行体制の構築
  • A/Bテストの設定

等々、いわゆるアナリティクスエンジニアリングの部分もデータ職責として一通り行います。

弊社は、データサイエンティストでも結構ETL等、データ処理をはじめとしたエンジニアリングのコードを書いている組織だと勝手に思っています。
データエンジニアと完全分業できるほど人員が多く無い」という裏事情も正直あったりはします。

これは個人のスペシャリスト志向、ジェネラリスト志向等々のキャリア感にも左右され賛否両論はあると思います。

が、個人的には「"データの成り立ち"や"ビッグデータとしての集計の勘所"を経験で裏打ちできる」ことで生まれるプラスの側面も大きいと考えております。

例えば以下のエピソードが挙げられます。

エンジニアリング目線も加味しつつログ設計を最適化出来る

前段の話に戻りますが、「1. 分析の準備」でログを設計する際には、

  • 事業視点(観察したいKPIに対してどういうログが欲しいか)

を考慮していました。

ここにさらに

  • エンジニアリング視点(どういうログだと、効率的にETL, 集計管理できるか)

を加味できるようになれば、双方の視点を踏まえたログ設計が可能になります。

データのニーズの変化に臨機応変に対応できる

ビジネスサイドの要求は往往にして変化しがちです。

仮説に沿った分析、ログ設計計画を立てたとしても、「違う角度からデータを見たい」という要望は多々発生します。

こういう際、データエンジニアに頼らずとも「自前でデータの奥底にまである程度触ることができ、ETL手法や中間テーブルの持ち方等を再検討して新たなデータのニーズに対応できる」ことは、手の動かしやすさ、俊敏性に直結すると感じております。

3. データの分析

機能がリリースされ、データが観察可能な状態になったら、その経過をKPIの観察BIツールの観察等で見守ります。

そして、最終意思決定者であるPdMと共に結果や考察をまとめていきます。

仮説検証としては「1. 分析の準備」の内容の履行が主になりますが、必要に応じて追加の事後分析や探索的分析も行います。

例えば、「KPIの単純集計」や「シンプルな可視化」よりもさらに奥行きのある示唆(ユーザーニーズや、根底に潜むユーザークラスタなど)を得たい場合は、データと分析の特性に合った多変量解析やら機械学習手法を選定し実施します。

また、A/Bテストでは、解釈に癖のある「有意差」をどう評価するかなどなど、統計的な知見の解釈のサポートを行ったりもします。

そして、このようにして統計、機械学習の文脈で得られたデータ解釈を、PdM向けに還元することになります。

  • データの本質に着眼し、良い分析手法を選定し示唆を出すためのデータサイエンスのハードスキル面
  • その解釈結果をビジネスの言葉に翻訳し、PdMに還元するための言語化等々のソフトスキル面

など、意思決定を支援する計らいはさまざまな難しさはあるものの、新たな知見が生まれたり、成果に寄与したときは達成感があります。

終わりに

簡単ですが、プロダクト開発におけるデータサイエンティスト(アナリティクスエンジニアに近いかもしれません)の立ち回り例を紹介しました。

データ人材としてプロダクトの価値の増大に貢献できるよう、引き続き精進していきたいところであります。

似たような背景、課題感を抱えたどなたかに対して、この記事で何かしら響くものがあれば幸いです。

メンテナンスで出来るだけ再現性を持たせて考えることを減らそう

はじめに

こんにちは、トモニテ開発部ソフトウェアエンジニア兼、CTO 室 Dev Enable グループの rymiyamoto です。

今回はバックエンド系を触っている人なら誰しもが一度は関わるであろうメンテナンス(以下メンテと省略します)の話をしていきたいと思います、

実際のメンテのための計画方法は以下の記事で紹介されていますので、気になる方はご覧ください。

tech.every.tv

そもそもなぜメンテナンスが必要になってくるのか

まずメンテが起きないように基本オンタイムでアプリケーションが更新されるように仕組みを作ることは大切です。
たとえば、CI/CD からブルーグリーンデプロイメントなどの手法を使って、アプリケーションの更新を自動化することで、サービス利用者にとっては透過的にアプリケーションが更新されることができます。

しかしアプリケーションが動いているインフラ周りの変更や、アプリケーションの大規模な仕様変更などが発生すると、どうしてもダウンタイムを伴うメンテナンスが必要になります。

メンテの手順にどうやって再現性を持たせるか

サービスを止めるにあたって、メンテの手順を明確にしておくことが大切です。
しかしその手順は人間が行うものであるため、ヒューマンエラーが発生する可能性があります。

そのため、メンテ時には、アプリケーションの状態を元に戻すための手順を明確にしておくことが大切です。

例えば AWS の RDS でメンテンスを行う場合でも以下のような手順を踏みます。
(今回は例でインプレースアップグレードで話をします)

  1. バッチが走らないようにする
  2. アラートを一時的に無効にする
  3. サービスの停止を行う(ロードバランサーの切り替えて固定レスポンスを返す等)
  4. DB のバックアップを取る
  5. DB のアップデートを適用する
  6. アップデート後に動作確認を行う
  7. サービスを再開する(ロードバランサーの切り替えを元に戻す)
  8. アラートを有効にする
  9. バッチを再開する
  10. 必要であればバッチの再実行を行う

※実際に mysql8 化をした記事があるので気になる方はご覧ください。

tech.every.tv

これらの手順だけでもかなりの数があり、毎回コンソール上から手動で実行するのはミスが発生しやすいです。
意図せぬ設定をしてどこで間違ったのかがわからないということが起こりがちです。

そのため、メンテ時には、アプリケーションの状態を元に戻すための手順を自動化出来るようにしておくことが大切です。

コード化して再現性を持たせる

例えば、Terraform を使って、インフラの状態をコードで管理することで、メンテ時にはコードを実行するだけでアプリケーションの状態を元に戻すことができます。
以下はロードバランサーのルールを変更するコードの例です。

こちらでは、ロードバランサーのリスナールールを変更して、メンテ中には固定レスポンスを返すようにしています。
メンテ解除時は変更差分を取り消して apply するだけで元に戻すことができます。

// メンテ用のルール
resource "aws_alb_listener_rule" "server_maintenance_rule" {
  listener_arn = aws_alb_listener.lb_https.arn
  priority     = 4 // priorityが競合しないように番号を調整しておく

  action {
    type             = "fixed-response"

    fixed_response {
      content_type = "application/json"
        status_code  = "503"
        message_body = jsonencode(
        {
          message = "メンテナンス中です"
        }
      )
    }
  }
  condition {
      host_header {
        values = ["server.example.com"]
      }
  }
}

// 通常のルール1
resource "aws_alb_listener_rule" "server_rule" {
  listener_arn = aws_alb_listener.lb_https.arn
  priority     = 5 // 通常: 1

  action {
    type             = "forward"
    target_group_arn = var.server_tg_arn
  }

  condition {
    host_header {
      values = ["server.example.com"]
    }
  }
}

// 通常のルール2
resource "aws_alb_listener_rule" "dashboard_rule" {
  listener_arn = aws_alb_listener.lb_https.arn
  priority     = 6 // 通常: 2

  action {
    type             = "forward"
    target_group_arn = var.dashboard_tg_arn
  }

  condition {
    host_header {
      values = ["dashboard.example.com"]
    }
  }
}

// 通常のルール3
resource "aws_alb_listener_rule" "web_rule" {
  listener_arn = aws_alb_listener.lb_https.arn
  priority     = 7 // 通常: 3

  action {
    type             = "forward"
    target_group_arn = var.web_tg_arn
  }

  condition {
    host_header {
      values = ["example.com"]
    }
  }
}

コマンドライン上で再現性を持たせる

また物によってはコード管理していないものもあると思います。
そこでは AWS CLI で事前にコマンドを作成しておくことで、メンテ時にはコマンドを実行するだけで適用することができます。

これは AWS CLI で RDS のインスタンスのエンジンバージョンを変更するコマンドの例です。
本来であればコンソール上でボタンを押して切り替えたり手で打つところがなくなるので、ヒューマンエラーを減らすことができます。

aws rds modify-db-instance \
    --db-instance-identifier example-rds \
    --apply-immediately \
    --engine-version 8.0.35 \
    --option-group-name default:mysql-8-0 \
    --db-parameter-group-name mysql80-example-rds \
    --allow-major-version-upgrade \
    --enable-performance-insights

事前に模擬メンテを行う

実際に手順書を作成していざ本番だと、コマンド上のミスや考慮漏れなどが発生することがあります。
そのため可能であれば、開発環境や QA 環境等で事前に模擬でメンテを行うことで、本番でのミスを減らすことができます。

ただし本番とは異なる環境で行うため、実際のメンテ時には環境の違いを考慮して手順を確認することが大切です。
(実際にハマったものですが、DB アップデート時にインスタンスサイズの違いで開発環境では 15 分程度だったのものが本番では 30 分程度かかりました)

そのため出来ることなら本番と近い環境で行うことが望ましいです。

アプリケーションコードの変更なしでメンテに追従できるようにする

こちらは再現性の観点からは外れますが、アプリケーションコードの変更なしでメンテに追従すると、サービスへのデプロイをすることなく切り替えが瞬時に行えるようになります。

例えば API 通信をしているアプリケーション(クライアントアプリや web、dashboard など)で事前にメンテ用に特定レスポンス(503)の挙動を考慮しておくことで、メンテ時にはアプリケーションコードの変更なしでメンテに追従することができます。

const response = await fetch("https://api.example.com");
if (response.status === 503) {
  // メンテナンス中の場合の処理
  // リダイレクトなり、画面に描画したり
  return;
}

// 移行通常の処理

まとめ

ここまでメンテに関わってくることはそれなりにありましたが、メンテナンスはサービスを維持するために必要な作業です。
再現性を持たせたり手順を自動化することで、ヒューマンエラーを減らすことができ精神的にもとても楽になります。

完璧にすることは難しいですが、今後ともトラブルなくメンテをやりきれるよう普段から意識してサービス開発に取り組んでいきたいと思います。

Vue.js v-tokyo Meetup #21 で登壇してきました

はじめに

こんにちは、Retail Hub 事業部でエンジニアを務めている 羽馬 です。

先日、Vue.js 日本ユーザーグループ主催の Vue.js v-tokyo Meetup #21 に登壇する貴重な機会をいただきました。本記事では、その経験を通じて得られた知見や、Vue.js 開発における効率化のヒントをご紹介します。

vuejs-meetup.connpass.com

登壇テーマ:VueUseで実現するVue.js開発の効率化

今回の登壇では、Vue.js 開発者にとって強力な味方となる「VueUse」というライブラリについて紹介しました。発表資料は以下からご覧いただけます

speakerdeck.com

VueUseとは

VueUse は、Vue Composition API のための包括的なユーティリティコレクションです。200以上の便利な関数を提供し、Vue.js アプリケーション開発の生産性を大幅に向上させます。

vueuse.org

なぜVueUseに注目したのか

VueUseに注目した主な理由は以下の3点です

  1. 開発効率の劇的な向上

    • 複雑な処理を数行のコードで実装可能
    • 例:useLocalStorage でローカルストレージ操作が簡素化
  2. コードの再利用性と保守性の向上

    • Composition API を活用したロジックのカプセル化
    • コンポーネント間での再利用が容易
  3. Vue.js 開発スキルの向上

    • コミュニティで広く採用されているベストプラクティスの学習
    • ソースコードから Vue 3 と Composition API の効果的な使用法を学習

発表のハイライト

1. VueUse の特徴

  • 200以上の多様なユーティリティ
  • ローカルストレージ、デバイス情報、スクロール位置、フォームバリデーションなど幅広くカバー

2. 代表的な機能と使用例

// マウス座標の取得
const { x, y } = useMouse()

// クリップボード操作
const { copy, copied } = useClipboard()

// 非同期通信
const { data, error, loading } = useAxios('https://api.com/data')

3. VueUse がもたらす価値

  • 宣言的で再利用可能なコンポーザブル
  • ライフサイクルフックの自動処理
  • 必要な機能のみをインポート可能(tree-shaking対応)
  • 高度にカスタマイズ可能なオプション

実践的な活用例

VueUseの実践的な活用例をいくつか紹介します

レスポンシブデザインの実装

   import { useMediaQuery } from '@vueuse/core'

   const isLargeScreen = useMediaQuery('(min-width: 1024px)')

無限スクロールの実装

   import { useInfiniteScroll } from '@vueuse/core'

   const el = ref(null)
   const { arrivedState, reload } = useInfiniteScroll(el, () => {
     // 新しいデータをロードする処理
   })

ダークモードの実装

   import { useDark, useToggle } from '@vueuse/core'

   const isDark = useDark()
   const toggleDark = useToggle(isDark)

これらの例からわかるように、VueUseを使用することで、複雑な機能を簡潔に実装できます。

得られた学びと今後の展望

Vue.js v-tokyo Meetup #21 への参加を通じて、以下の点を再認識しました

  1. コミュニティの力:Vue.js コミュニティの活気と、知識共有の重要性
  2. 継続的な学習の必要性:常に新しいツールや手法を学び、実践することの大切さ
  3. 知見の共有:得た知識を社内外で共有し、フィードバックを得ることの価値

今後は、以下の取り組みを行っていきたいと考えています

  • VueUseの社内導入と活用事例の蓄積
  • コミュニティイベントへの積極的な参加と貢献
  • 社内勉強会やテックブログを通じた知見の共有

おわりに

Vue.js v-tokyo Meetup #21 への登壇は、技術的な学びだけでなく、コミュニティとのつながりを深める貴重な機会となりました。イベントを運営してくださったスタッフの皆様、参加者の皆様に心より感謝申し上げます。

イベントの詳細なレポートについては、Vue.js 日本ユーザーグループの公式ブログ もご参照ください。

note.com

最後に、今回の経験を活かし、今後も Vue.js コミュニティへの貢献と、社内での知見共有を続けていきたいと思います。

今後も、このようなイベントや情報共有の場に積極的に参加し、Vue.js コミュニティの発展に少しでも貢献できるよう、努めてまいります。