snaqme Engineers Blog

おやつ体験メーカー snaq.me エンジニアによる開発プロダクトブログ

第4回【社内LT会】を開催しました🎉

こんにちは。スナックミーでエンジニアをしているタク(@yamataku3831)です。

つい先日、4回目の【社内LT会】を開催しました!今回もスナックミーの業務委託メンバーである“ぱーとなー”も多く参加してくれて、ワイワイしながら情報発信を行うことができました。

今回もスナックミーらしくおやつを楽しみながら…

今回は、先月韓国に帰省したときに私がスーパーで買ったおやつを紹介しました!韓国の돼지바(テジバー)というアイスクリームと、食べたことがある方もきっと多い CRUNKY がコラボしてできたお菓子です。

韓国のチョコ菓子!

ちょっとスナックミーっぽくないので、紹介しようか迷いました(笑)。ただこういう商品からインスピレーションをもらって、スナックミーらしい商品として開発につなげることもできるかも?と思ったので、今回持ってきてみた次第です。

発表内容

MSX の昔と未来

発表者:大場

大場 - 発表資料の一部切り抜き

大場はマレーシアを拠点とし、スナックミーの開発に携わっている”ぱーとなー”です。彼が「MSX」という機械をきっかけにプログラミングと出会ったのは、小学生の頃。ブラウン管と MSX を繋いでプログラミングを行い、ゲームを作って遊んでいたんだとか。

一般の人たちが MSX で作ったゲームのソースコードを集めた雑誌もあったみたいで、そのソースコードを見ながら MSX に直打ちして、同じファンの人が作ったゲームを楽しんでいたようです。なんだかエモい気持ちになりますね…!

MSX は現在も開発が続いていて、IoTプロダクトや Watch なども作られているみたいです。スナックミーとしても「ファンに愛されるプロダクト」を目指していきたいなと改めて実感しました。

フロントエンドのベースライン

発表者:小林

小林 - 発表資料の一部切り抜き

小林はフロントエンド開発に携わっている”ぱーとなー”です。今回はブラウザやモバイル OS における市場シェアや、各ブラウザにおける標準仕様の比較、iOSAndroid のCPU パフォーマンスなどを調査してくれました。

その調査結果から、Safari の標準仕様に合わせて実装することや、低スペックな Android 端末にも対応できるようパフォーマンスを考えて実装することの大切さが理解できるように。

突き詰めるとユーザーのことを考えて画面を実装することに繋がりますが、ブラウザの仕様やモバイル端末のスペックとも戦いながら実装していると知れて、改めてメンバーに対して尊敬の念を抱くよいきっかけとなりました。

おわりに

今回で4回目の社内LT会でしたが、発表してくれたメンバーからも「貴重な体験になりました!また機会があればぜひ!」と嬉しい言葉をもらえるようになってきました。

チームメンバーが情報発信をしやすい土壌を整えたくて始めた社内 LT 会なので、メンバーからそういった言葉をかけてもらうととっても嬉しく感じます。これからもこの活動は続けていこうと思います!

そんなスナックミーでは、エンジニアを積極的に探しています!この記事を読んで興味を持ってくださった方や、おやつが大好きで「おやつと世界を面白くしていきたい」とお考えの方がいらっしゃれば、ぜひ応募していただけると嬉しいです。

engineers.snaq.me

募集ポジション

ソフトウェアエンジニア Backend (lead) / 株式会社スナックミー

ソフトウェアエンジニア FrontEnd (lead) / 株式会社スナックミー

ソフトウェアエンジニア Data Engineer / 株式会社スナックミー

Framer Motion でアニメーションを実装する

こんにちは。スナックミーでフロントエンドをやっている前田です。
今回は、 snaq.me のマイページで使用している Framer Motion についてご紹介したいと思います。

Framer Motion とは

Framer Motion は複雑なアニメーションを簡単に実装できる React のライブラリです。
シンプルな例では、下記の記述で左右に 100px ずつ跳ねながら移動する円を描画できます。

<motion.div
  style={{
    width: 30,
    height: 30,
    background: "red",
    borderRadius: 30
  }}
  initial={{ translateX: 0 }}
  animate={{ translateX: 100 }}
  transition={{
    type: "spring",
    bounce: 0.5,
    repeatType: "mirror",
    duration: 2,
    repeat: Infinity
  }}
/>

デフォルトでバネのようなエフェクトが使用され、 bounce のオプションに 0~1 の少数値を指定することにより、その動きを制御できます。

bounce: 1 を使用する事はほとんどありませんが、ユーザーにしっかり気づいて欲しいインタラクションには高め(0.6 ぐらい)、自然に振る舞って欲しいときには未指定(デフォルトが 0.2)を使用する事が多いです。

なぜ Framer Motion を使うのか

Web でアニメーションを表現するには、多くの手法が存在します。

  1. gif や スプライト画像でアニメーション
  2. Lottie を使用して JSON ファイルで管理
  3. CSS アニメーション
  4. JavaScript で DOM やスタイルなどを操作

それぞれ一長一短あり、 1 や 2 はデザイナーとの協業が必要となることなどから、 UI デザインに携わらないフロントエンド実装者が主導する場合は 3, 4 の手法を取ることが多いのではないでしょうか。
しかし、どちらも少し手間がかかり、 実装時にアニメーションを定義することを習慣づけるのは難しいと考えています。

どのような手間が必要となるか、例として簡単なフェードアニメーションを実装する場合を見てみましょう。
styled-components では以下のように書けます。

const Block = styled.div<{ isShow: boolean }>`
  opacity: ${({ isShow }) => isShow ? 1 : 0};
  transition: opacity 0.2s ease;
`;

これを Props を受け取らず、レンダリング後にフェードインするように変更するには keyframes を使用します。

const fadeIn = keyframes`
  to { opacity: 1 }
`;

const Block = styled.div`
  opacity: 0;
  animation: ${fadeIn} 0.2s ease-in-out forwards;
`;

opacity の定義が分断されたことにより、少し複雑さが増してしまいました。
さて、このコンポーネントを何らかの UI 操作などでフェードアウトさせたい場合はどうなるでしょう。

const fadeIn = keyframes`
  to { opacity: 1 }
`;

const fadeOut = keyframes`
  from { opacity: 1 }
  to { opacity: 0 }
`;

const Block = styled.div<{ isShow: boolean }>`
  opacity: 0;
  animation: ${({ isShow }) => (isShow ? fadeIn : fadeOut)} 0.2s ease-in-out forwards;
`;

やり方はいろいろあるかと思いますが、今回は animation-name を Props で切り替える仕様にしてみました。
keyframes の定義が増え、fadeOut は from の記述が必須(fadeIn は不要)となるなどさらに複雑性が増したように感じます。
このような手間が必要となれば、つい isShow && <Block /> と書いてしまいたくなるのも頷けるのではないでしょうか。

今度は同様の仕様を Framer Motion で記述してみましょう。

<motion.div
  initial={{ opacity: 0 }}
  animate={{ opacity: isShow ? 1 : 0 }}
/>

だいぶすっきりしましたね。 フェードだけだと描画エリアを確保してしまうので、要素ごと消す場合には以下のように書きます。

<AnimatePresence>
  {isShow && (
    <motion.div
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0 }}
    />
  )}
</AnimatePresence>

このように、インタラクションの定義を自然に取り込める記述性の高さと、type: "spring" による目を引くエフェクトの実装しやすさから、 snaq.me では Framer Motion を採用しています。
ここまで小さなサンプルコードで紹介してきましたが、やや実践的なサンプルとして snaq.me で良く使うエフェクトもご紹介します。

Framer Motion を使う場合に考慮すべき点

Framer Motion の良いところばかりを紹介してきましたが、いくつか注意すべき点も存在します。

バンドルサイズが大きい

アニメーションのための機能が数多く提供されている Framer Motion ですが、バンドルサイズが膨らみがちな点が大きなデメリットであると考えています。
Bundlephobia によると、 minified された状態でおよそ 126KB ものファイルサイズになるようです。

bundlephobia.com

この問題については Framer Motion のドキュメントに記載されているので、目的に合わせて設定することでバンドルサイズを減らす事ができます。

www.framer.com

他のライブラリと記法が競合する

Framer Motion では styled(motion.div) などと書くことにより、初期状態のスタイルを styled-components で書くことが可能です。 しかし、 animateexit で指定するプロパティを initial 以外で指定していると正しく動作しないため、 競合しないように管理する必要があります。

// 上手く動かない
<Block animate={{ translateX: 0 }}  />

const Block = styled(motion.div)`
  transform: translateX(100);
`;

これにより、スタイルで JSX の宣言が肥大化して読みづらくなったり、事前に styled-components で定義されているスタイルにアニメーションを付けようとして上手くいかなかったりなどの問題が発生しています。 弊社では Framer Motion を使うときは style を使用するようにして回避していますが、オブジェクト形式で CSS を書くのに抵抗がある方や、デフォルトのスタイルを styled-components に寄せたい場合には問題となる可能性があります。

JSX からスタイルの定義をを分離する手法としては styled-components の attrs を使用する事でも可能ですが、 attrs の generic に MotionProps を渡す手間が発生します。

const Block = styled(motion.div).attrs<unknown, MotionProps>(() => ({
  initial: { opacity: 0 },
  animate: { opacity: 1 },
}))``;

SVG を埋め込みすぎるとバンドルサイズが大きくなる

強力で便利な Framer Motion ですが、 SVG でアニメーションで多用しすぎるとバンドルサイズを大きくする要因となります。 Framer Motion では SVG の path, g, rect, circle などのタグを motion.path, motion.g, motion.g, motion.g などに変えることで個別にアニメーションを指定可能ですが、 d 属性なども同時にバンドルされてしまうため、配信される JS ファイルのサイズに影響を及ぼします。
ファイルサイズの大きい SVG には

  • Dynamic import を使用する
  • ラフ加工されてアンカーポイントの多い SVGPNG にする
  • フロントエンドでのアニメーションは諦める(GIF や Lottie などを使う)

など、状況に合わせた対策が必要です。

まとめ

snaq.me で導入してから2年ほどが経過しましたが、今では snaq.me のマイページの多くの場所で使用しています。
その中でも特に多用しているのが snaq.me の eGift で、オンラインメッセージカードのインタラクションは Framer Motion を使用して実装しています。
近日中に、りっす(弊社の公式タレント)のかわいいクリスマス eGift カードが公開となるので是非覗いてくださいね。
(画像は実装途中の物です)

余談ですが、りっす氏は顔の作りがシンプルでデータ量が少なく、アニメーションを付けやすいのも推しポイントです。

スナックミーのエンジニアチームで直近動きたいこと (2023年10月)

こんにちは スナックミー CTO の三好 (@miyoshihayato) です
四半期ごとにチームに共有している近期の取り組みたい内容を一部変更し、こちらのエンジニアブログに載せたいと思います。

仲間集め

「仲間集め」今年は例年以上に力を入れています(特に後半から)ので、毎回仲間集めをテーマに入れ続けてます。

こちらに紹介してませんでしたが、おやつがユーザーの手元に届くまでのプロセスを詳細に解説した動画を公開しています。興味のある方は以下のリンクからご覧いただけます。

www.youtube.com

さらに、この取り組みの中でエンジニアがなぜ必要なのか、その背景と理由を動画で深堀りしています。関心がある方はこちらもチェックしてみてください。

www.youtube.com

私たちの取り組みに興味を持った方、ぜひカジュアルにお話ししてみませんか?お気軽にご連絡ください。

相談前に自分の考えを持つ取り組み

毎四半期ごとに取り組む社内テーマの一つを、新たな言い回しで紹介いたします。前回は「倍速」 に取り組み、チームの行動の迅速化を実感できるようになりました。具体的には、他チームからの要望や質問に対して、誰かが応答するのを待つのではなく、自分で積極的に対応する姿勢が増加しました。

この四半期のテーマは「自らの考えを持つ」です。スナックミーにはオペレーション、商品開発、パティシエ、CSなど多岐にわたる職種のメンバーが在籍しています。このため、様々な施策や案を実施する際、明確な方針が決まっていない段階でも前向きに取り組んでくれるメンバーが多いです(私たちの中で、このようなメンバーを「チームスナックミー」と称しています)。

しかし、様々な選択肢の中から誰かが決定した策に乗っかるのではなく、相談する前に自分の意見や考えを持つことが大切だと感じています。例えば、以下の2つの会話の違いを考えてみてください。

A案とB案どちらがいいですか?
A案とB案を考えましたが、私はA案がこの理由で良いと感じています。どう思いますか?

これらは似ていますが、後者には明確な意見や考えが反映されています。このため、実施結果を振り返った際、成功や失敗の理由を自らの経験として学び取ることができます。対照的に、前者のアプローチでは、失敗した際に「自分の意見ではなかった」という逃げの姿勢が生まれる可能性があり、成功した際もそれを自分の成果として受け取るのが難しくなると思います。

実際、私含めて全くできていないというわけではなく、意識して取り組んでいこうということになります。

来年(中長期)の課題の整理土台作り

スナックミーは定期便以外にもストア(EC)やtoB向けや卸、自社店舗(直営店)など多方面に渡り事業を大きくしていこうと考えています。 詳しくは以下をご覧ください。

www.wantedly.com

創業当初から、我々は定期便事業の最適化に努力してきました。その結果、他の事業領域と比べると、定期便の方が進展している状況ですが、それでもまだ完璧とは言えません。また、来年3月でスナックミーは創業から8年目を迎えます。この長い期間にわたり、良い意味での技術負債も積み重なってきました。数年前からは、これらの技術負債への対応を開始し、今後もその取り組みは継続していく予定です。

現在、仲間を増やす取り組みを強化する中で、事業の拡大やチームの成長に伴い、新たな技術的、組織的課題が生じると予想されます。そのため、これからの期においては、「課題の整理と土台作り」をキーセーマとして位置づけ、積極的に取り組んでいきたいと考えています。私たちエンジニアチームとしては、事業が安定して成長を続け、新しい仲間が迎え入れられる環境を整備することに焦点を当てて活動していきます。

まとめ

以上が、エンジニアチームが直近で取り組みたい3つのテーマです。 常にエンジニアの仲間を探しています。エンジニアはあらゆる面でチーム力の底上げに貢献したいと考えています(PM、バックエンド、フロントエンド、データエンジニアなど)。

興味がある方は、ぜひカジュアル面談でお話ししましょう。

おやつと、世界を面白く。」 一緒に面白くしたい仲間をお待ちしてます!!

meety.net

engineers.snaq.me

募集ポジション

ソフトウェアエンジニア Backend (lead) / 株式会社スナックミー

プロダクトマネージャー / 株式会社スナックミー

ソフトウェアエンジニア FrontEnd (lead) / 株式会社スナックミー

ソフトウェアエンジニア Data Engineer / 株式会社スナックミー

第3回【社内LT会】を開催しました🎉

こんにちは。スナックミーでエンジニアをしているタク(@yamataku3831)です。

つい先日、3回目の【社内LT会】を開催しました!今回も業務委託メンバーが多く参加してくれて、ワイワイしながら情報発信を行うことができました。

今回もスナックミーらしくおやつを楽しみながら…

今回もまたマレーシアを生活の拠点とされている業務委託の方が、現地で売られていたおやつを紹介してくださいました!

トルコの伝統的なおやつ「ロクム」

「ターキッシュ・ディライト(ロクム)」という名前で、砂糖にデンプンとさまざまな種類のナッツを加えて作る、トルコの伝統的な甘いおやつとのこと。食感は柔らかく弾力があり、日本の「ゆべし(柚餅子)」に似ているようです。食べてみたい!

発表内容

おやつ体験の「飽き」をアサインで克服したい

発表者:兼崎

中身をお見せできないのが残念!

兼崎は2年以上前に、当時インターンとしてジョインしてくれたメンバーで、非エンジニアのメンバーとコミュニケーションを取りながら、弊社のシステムを幅広く開発してくれています。

最近はおやつの定期便の満足度を向上するため、パーソナライズのロジック部分を試行錯誤してくれています。特に「飽き」という部分にフォーカスを当てており、データアナリストのインターン生と協力して、どのようにデータ分析しているかなどを共有してくれました。

とても忙しいのにも関わらず、限られたリソースの中でしっかりスライドを作ってアウトプットする姿が、スタートアップのエンジニアらしくて感動しました。

アウトプットのモチベーションはみんな違ってみんな良い!

発表者: @yamataku3831

技術広報関連の勉強会などに参加すると、どうしても採用&組織のために技術発信してくれないかと働きかける方法…みたいなことが取り上げられている印象を受けます。自分もエンジニアリングマネージャーとして、チームメンバーにはどんどん技術発信をしてもらいたくて、さまざまな施策を行っています。

ただ、いちエンジニアとして過去を振り返った時に、私が技術発信を始めるようになったのは「自分のスキルを向上させるため」だったことを思い出しました。そして技術発信のおかげで言語化能力が鍛えられ、コミュニケーションが円滑になり、徐々に仕事がしやすくなったんです。

そう考えた時に「もっと自分のために技術発信してもいいよな。その結果チームに貢献できればWin-Winだと思えるくらいのスタンスでもいいよな」と思うように。そういったことを伝えたくて、今回の発表に至りました。

おわりに

社内LT会もいよいよ3回目。チームメンバーのアウトプットに対する向き合い方が、徐々に変わりつつあるように思えます。フロントエンドエンジニアのメンバーは約3ヶ月ごとにテックブログを書いてくれますし、どうすれば定期的に記事を書けるか模索している内容を Slack に投稿してくれていたりもします。

チームメンバーが情報発信をしやすい土壌を整えたくて始めた社内LT会なので、メンバーのそういった行動をとっても嬉しく感じます。これからもこの活動は続けていこうと思います!

スナックミーでは、エンジニアを積極的に探しています!この記事を読んで興味を持ってくださった方や、おやつが大好きで「おやつと世界を面白くしていきたい」とお考えの方がいらっしゃれば、ぜひ応募していただけると嬉しいです。

engineers.snaq.me

募集ポジション

ソフトウェアエンジニア Backend (lead) / 株式会社スナックミー

ソフトウェアエンジニア FrontEnd (lead) / 株式会社スナックミー

ソフトウェアエンジニア Data Engineer / 株式会社スナックミー

7年目の React プロジェクトを TypeScript に移行した話

こんにちは。スナックミーでフロントエンドエンジニアをやっている前田です。
以前 新規サービスの技術選定についての記事 を書きましたが、今回は定期便のマイページについてのお話をしようと思います。

snaq.me の定期便とは

定期便のお届け内容イメージ

弊社のメインサービスである snaq.me は、8個のおやつを定期的にお届けするサブスクリプションサービスです。100種類以上あるおやつのレパートリーの中から、お客様の好みに合うおやつが自動的に選ばれるのですが、その選定はマイページで登録していただいた情報をもとに行われます。
マイページはお客様の情報を得るための重要なツールであるため、その歴史も古く、リポジトリが作成されたのは2017年1月でした。

(どうやっておやつが選択されているかを詳しく知りたい方は、 ユーザーに最適なおやつを届ける「アサイン」の歴史 などの記事をどうぞ!)

初期の技術選定と時代背景

2017年というと、つい最近のような、ずいぶん昔のような不思議な感覚を覚えますね。皆さんは当時どのような技術スタックを使用されていましたか?当時の私は、素の JavaScriptNext.js (まだ zeit で、v4.0.0!!!) を使ったり、flow-typedVue.js を使ったりしていた形跡が古い PC から見つかりました。
TypeScript は2016年の9月に v2.0 がリリースされ、 strictNullsCheck がサポートされた時期です。世間的にも、フロントエンドを Ruby on Rails (2016年に v5.0 がリリースされて API モードをサポート) などのサーバーサイドフレームワークから分離する設計が広く受け入れられるようになった時期だと記憶しています。

私が入社したのが 2021年なので、選定理由などはあまり把握していませんが、snaq.me のマイページはリポジトリ作成時から React, Redux を使用しています。それらは今でも活発にメンテナンスされているので、とても息の長い技術選定をされたと考えています。

昨今のフロントエンドの風潮と、マイページの課題

そうして走り出したマイページのプロジェクトですが、今でも日々多くの試行錯誤を行っています。我々のようなスタートアップにとって「少ない人的リソースの中でもとにかく早くお客様に価値を届け、フィードバックを得る」 ということは何より重要であり、エンジニアに限らずすべての社員が持っているマインドです。
しかしそのような試行錯誤の連続の中では、一度立ち止まって技術選定や設計の正しさを問うことは非常に難しいものです。徐々に問題が蓄積されていきました。

私が入社した時点ではリポジトリ作成から4年以上が経過しており、主に以下のような課題があったと記憶しています。

  1. 素の JavaScript で書かれており、静的型解析を利用できない
  2. 自動テストが少なく、変更の安全性が低い
  3. JSDoc などのドキュメントが少なく、コンポーネントや関数の使い方を調べるために多くのコードを読む必要がある
  4. ライブラリが古くアップデートしたいが、静的型解析や自動テストの恩恵をあまり受けられないことが原因で一歩を踏み出せない

昨今のフロントエンドでは TypeScript による型安全な開発が好まれるケースが多く、弊社でも 1 を解決することで 3, 4 の大部分も解決することができると考え、 TypeScript の検討を開始しました。
なお、2 の自動テストについては本記事では言及しませんが、静的型解析の有無にかかわらず書いていかなければなりません。(自戒も込めて…)

意思決定

さて、 TypeScript 導入を決意しましたが、事業としての優先度を決めるために社内での合意を得る必要があります。
スタートアップで大きな技術スタックの変更を行う場合、最初の壁となりがちなのが社内での合意形成ですが、当時から API のフルリプレイスを進めていた背景もあり、スムーズに合意を得ることができました。

特別なことは何もしていません。ですが、毎週のスプリント振り返りで型がないことの問題点を説明し、Slack の times チャンネルで TypeScript の素晴らしさを説き、本番環境を障害で止める(変更したファイルに依存したページが他にあることに気づかず...)など、毎日少しずつジャブを打ったのは重要だったように思います。

(余談ですが、現在ではスナックミーのバリューに「やってみよ!」という項目があり、このようなチャレンジが広く受け入れられる土壌が整っています)

移行期間と考察

結論から書くと、弊社では 2021年8月に移行を開始し、すべての .js(x) を .ts(x) に変換完了したのが 2023/6/15 でした。
推移は以下のグラフをご覧ください。

移行戦略

単に拡張子を変えるだけであれば、 tsconfig.json で型の厳格性を弱めてしまえばすぐにでも可能でしたが、安心して TS ファイルを扱いたかったため strict: true で移行を開始することにしました。
また、 strict: true で TypeScript へ移行する場合には移行作業に時間がかかりますが、機能実装を一定期間止める(もしくは優先度を下げる)ことを許容できなかったので、対象を定めてファイル単位で少しずつ移行しています。

移行のフェーズ

機能実装を続けていたため、ファイル数は全体を通して緩やかに増加していますが、 .js(x)ファイルの減少にはいくつかの段階がありました。

機能実装のついでに期

初期は TypeScript のお試し期間でもあったので、「新規追加するファイルは TypeScript で作成して、そのファイルから参照されるファイルを時間の許す限り移行しようね」という緩めのポリシーで進めていました。グラフ中では 2021年8月から 2022年4月 のあたりです。
想定していたよりサクサクと移行が進み、半年ちょっとで TS 率50% を超過。「これは2022年中の移行完了も可能では...?」と考えていましたが、ここから長い停滞が始まります。

JS ファイル全然減らない期

2022年4月から年末まで、 JS ファイルが一切減らない時期が続きました。大きな新規機能実装が続いたことと、よく編集する JS ファイルの移行が軒並み完了したことが主な原因です。
新規開発で TS ファイルがモリモリ増えたので相対的には TS 移行率が向上しましたが、2022年の後半は実質的にまったく進捗がありませんでした。

Issue 上げてみる期

設定画面などのあまり変更されない画面がボトルネックになっていたため、 UI 改善などの名目で issue を作成し、スプリントに組み込むように。これはおよそ2022年12月から2023年3月の時期ですが、グラフからもわかるようにあまり良い方針ではありませんでした。
当時全体のデザインリニューアルが進んでおり、設定画面だけ古いレイアウトのままだったこともこの手法を選んだ要因でしたが…

  • ユーザー体験としては全体の見た目を統一することが目的であるため、事業的に優先度が低い
  • UI 改善にはデザイナーを巻き込む必要があるため、エンジニアのみの工数で完結しない
  • 「新しい UI の適用」と「型のついていないファイルを読み込んで仕様を理解し、場合によって作り直す」を同時に行う必要があったため対応の工数が高い(よってさらに優先度が下がる)

などの理由から、一旦諦めて別の手法を取ることとしました。

いらないファイル一掃期

この時点でおよそ 250 ファイルぐらい JS ファイルが残っていましたが、まずは使われていないファイルを削除して以降対象を見極めることとしました。

  1. JS ファイルのファイル名から import 文で使用されそうなワードの一覧を生成
  2. ワード毎に git grep して1件もヒットしなかった JS ファイルを絞り込み
  3. 絞り込んだファイルを 1件ずつ目視で確認し、問題無ければ削除
  4. 削除した後もう一度 1 から実行(非 import が消えたことによって参照が消えた可能性がある)

という単純作業で、1日あたり 100ファイルほどの JS ファイルを検出し、削除することができました。

諦めてエラー踏み潰す期

ここまでで残った JS ファイルですが、

  1. あまり変更されない
  2. 難易度が高い

の二種に分類されていたため、まずは1を一掃することに。 ただし、あまり時間をかけられないため 「30分以上かかりそうなら 2 に分類して後回し」「@ts-expect-error と any を使ってもいい」という条件を付けて 1 ファイルずつ移行し、1日で 80ファイルほど移行することができました。

クロージング

この時点で残り70ファイルです!90% 以上が TypeScript なので、以前消せなかったファイルも安心して消すことができるようになり、ファイル削除だけでさらに 30ファイルほど消すことができました。

残りは前項で高難易度と判断したファイルだけだったので、スプリントに組み込んで工数を確保し、地道に型を付けて完了させることができました。機能実装の優先度を一時的に下げることになったので少し心苦しかったですが、作業対象が小さくなったため見積しやすく、他課題との優先度調整も行いやすかったです。

移行作業の反省点

ほぼ2年近くかかってしまいましたが、機能実装の優先度を大きく下げることなくやりきれたのはとてもよかったかなと思います。また、 any をほぼ使わずに移行できたので、以前より安心して機能開発できるようになりました。

しかし、実質的に移行にかけた時間は初期に想定したよりも少なく、うまく優先度を調整をすれば半年から1年程度で移行することも可能だったのでは…とも考えています。
移行を短期間で終わらせることができると、機能実装やリファクタリングをスムーズに行えるようになるため、チームやプロジェクトの規模によってはこちらの方がメリットが大きいかもしれません。

いずれにしても、「移行のために数週間から数ヶ月機能開発を止める」もしくはフルリプレイスするという選択ではなく、少し長めの期間をとって機能実装と並行するという手法は弊社にとっていい選択でした。
移行期間中、設計についてじっくりと思考を巡らせることができたため、私自身の考えを整理することができましたし、リファクタリングや設計に関する良質な記事が多く公開されので、それらのエッセンスを取り込むことができました。

今後どうするか

「 TypeScript に移行した話」とタイトルを付けましたが、TypeScript を使ったことがある方ならお気づきの通り、まだまだ「TypeScript への移行が完了した!」と言える状態とは程遠いのが現状です。
喫緊では、下記を対応しなければならないと考えています。

  • @ts-expect-error, @ts-ignore, unknown, any がプロジェクト内部に多数記載されている
  • noUncheckedIndexedAccess が false になっているので、配列やインデックス型へのアクセスが安全ではない
  • API の型定義 (主に null, undefined ) に若干不整合がある

また、ソフトウェアの安全性を静的型解析だけで担保することは難しいため、自動テストの追加やアーキテクチャ変更、ライブラリの変更などやるべきことはまだまだ山積しています。

弊社では「永遠のβ版」として常にサービスをアップデートしているため、このような問題も永遠になくなりません。しかし、多くのお客様に使われているサービスの機能開発をしながら、技術的な課題の解決に取り組める環境はとても得がたいものだと考えています。

「多くのユーザーに使われているサービスの開発をしたい!」
「技術的な課題に立ち向かいたい!」
という欲張りな方は、一緒に snaq.me のマイページ開発にチャレンジしてみませんか?

engineers.snaq.me

募集ポジション

ソフトウェアエンジニア Backend (lead) / 株式会社スナックミー

ソフトウェアエンジニア FrontEnd (lead) / 株式会社スナックミー

ソフトウェアエンジニア Data Engineer / 株式会社スナックミー

第2回【社内LT会】を開催しました🎉

こんにちは。スナックミーでエンジニアをしているタク(@yamataku3831)です。

つい先日、前回に引き続き【社内LT会】を開催しました!今回は業務委託メンバーも多く参加してくれて、前回以上にワイワイしながら情報発信を行うことができました。

スナックミーらしくおやつを楽しみながら…

前回の社内LT会も盛り上がりはしたのですが、ごく一般的なLT会になってしまい、もう少しスナックミーらしさを出すことはできないかな…と思っていました。

スナックミーはおやつを取り扱っているスタートアップであるということと、そもそもアウトプットのハードルを下げるために始めた社内LT会であるということを考慮して、おやつをもぐもぐしながらリラックスした雰囲気でやってみることに!

食べながら参加というのがよかったのかはわかりませんが、前回よりも相互のコミュニケーション量が多く、終始和やかな雰囲気で会を進めることができました!この会をきっかけに、アウトプットのハードルがどんどん下がっていけば本望だなと思います。

ちなみに業務委託で手伝ってくださっている方のひとりに、マレーシアを生活の拠点とされている方がいらっしゃるのですが、マレーシアの伝統的なおやつを紹介してくださいました!

鮮やかで綺麗なニョニャクエ

「ニョニャクエ」という名前の甘いおやつで、米やタピオカ、ココナッツなどが使われているようです。カラフルな色が特徴的なのですが、花や植物などの天然色素を使って色づけしているので、体にもやさしいとのことでした。食べてみたい!

発表内容

僕の考えた管理画面とLambda の開発環境

発表者:岩田(スナックミーをしっかり支えてくれているパートナー)

岩田は約2年前から業務委託として一緒に働いているパートナーで、今日に至るまでずっとシステム開発を助けてくれています。

正社員とパートナーには、セキュリティ観点により、主に権限やデータ周りでお渡しできるものが異なります。それが理由で、パートナーにとってどうしても動作確認や開発を行いづらい部分が存在してしまいます。

そんな中、開発しやすい環境を自発的に構築していた彼が、他のパートナーも開発しやすいようにとわざわざ言語化して全体に共有してくれました。本当に感謝しています!

キーボード沼のすゝめ 〜自作キーボードの一歩手前まで〜

発表者:前田(スナックミーの頼れるフロントエンドエンジニア)

前田は自作キーボードを使って開発しているメンバーで、キーボードへの熱い想いを抱いています。先日自作したキーボードを見せてもらったのですが、とっても格好良くて、私も自作してみようかなと心が揺さぶられました(笑)

前田が作成した自作キーボード

エンジニアは1日8時間以上キーボードに触れ続けることも珍しくない職種です。体を労わることを目的としていたり、オシャレなキーボードでモチベーションを高めたり…キーボードにこだわる理由はいろいろありそうでした!

ちなみに私は前職で首から肩にかけての筋を痛めたことがあり、それがきっかけで肩が開く分離型のキーボードを使用するようになったので、キーボードへこだわる理由にかなり共感できました。

おわりに

チームメンバーが情報発信をしやすい土壌を整えていくためにも、アウトプットの練習を行う場として、これからも社内LT会を続けていきます!

今回はおやつをもぐもぐしながら開催したからか、相互のコミュニケーションも増えて、とても和やかな雰囲気で行うことができました。とはいえ、毎回何かしらアップデートできるといいなと思っているので、次回も今とは違う何かを始めたいですね。

スナックミーでは、エンジニアを積極的に探しています!この記事を読んで興味を持ってくださった方や、おやつが大好きで「おやつと世界を面白くしていきたい」とお考えの方がいらっしゃれば、ぜひ応募していただけると嬉しいです。

engineers.snaq.me

募集ポジション

ソフトウェアエンジニア Backend (lead) /体験チーム / 株式会社スナックミー

ソフトウェアエンジニア Backend (lead) /オペレーションチーム / 株式会社スナックミー

プロダクトマネージャー / 株式会社スナックミー

第1回【社内 LT 会】を開催しました🎉

こんにちは。スナックミーでエンジニアをしているタク(@yamataku3831)です。

つい先日、スナックミー社では初の【社内 LT 会】を開催しました!LT とは、Lightning Talks(ライトニングトーク)という短時間で行うプレゼンテーションのこと。正社員メンバーだけでなく、業務委託の方々も参加してくれて、一緒にワイワイしながら情報発信を行うことができました。

メンバーがアウトプットしやすい土壌を作りたい!

先日 AWS Summit に参加した際は、スナックミーを知っている色んな方がブースへ立ち寄ってくださいました。スナックミーが多くの方に知られているという嬉しさがあった一方で、おやつ会社であるスナックミーがなぜ AWS Summit に出展しているのか?と聞かれることも多かったんです。

スナックミーからエンドユーザーのもとへ届くものはあくまで「おやつ」だけなので、ユーザーごとにパーソナライズされたおやつが無事届くまでの過程に使用されているテクノロジーの存在が、どうしても伝わりづらいという性質を持っています。

そういった背景もあって、スナックミーとしてエンジニアチームの存在をしっかりと発信することで、世のエンジニアにもっと興味を持ってもらいたいと思うように。とはいえ、メンバーに突然「技術発信しましょう」と言ったところで、もちろんそのハードルはかなり高く感じることでしょう。

自分も前職で上司やチームメンバーに協力してもらい、勇気づけられ、多くのハードルを乗り越えたことで、ようやくアウトプットすることができました。ですから、次は私がチームメンバーに協力して、勇気づけて、ハードルを乗り越えられるようにフォローする番。その想いで社内 LT 会を開催するに至りました。

発表内容

PC が変わっても使い慣れた Neovim で すぐに開発を始める仕組み

発表者: @yamataku3831

私は Neovim を使用して開発をしています。その運用方法を先日 Zenn で投稿したのですが、意外と多く読まれたこともあり、有益な情報になるかもと思って発表しました。

zenn.dev

ほとんどのメンバーは VSCode を使用していて、Dev Container を通じて Docker を使っていることを知りました。私の運用方法でも Docker を利用しているので、お互い共通の「重くなってしまう」という課題感があるとわかって学びになりました。

スナックミーのおやつアサインの歴史とこれから

発表者: @miyoshihayato

社外秘の情報が含まれるため、スライドを共有することができないのですが、おやつの定期便において根幹を担うシステムである「アサイン」の歴史とこれからの展望について CTO に発表していただきました。

おやつの定期便は、現在はユーザーの好みに合わせた8種類のおやつを機械学習を利用してアサイン(割り当て)しています。この方法に至るまでにどういった経緯があったのか、そして今後ユーザーの満足度を更に上げていくためにどういった展望を考えているかなどについて、チームで認識を揃える良い時間となりました。

ざっくりとした概要にはなりますが、アサインの歴史を知りたい方はぜひこちらの記事をご覧ください。

labs.snaq.me

おわりに

チームメンバーが情報発信をしやすい土壌を整えていくためにも、アウトプットの練習を行う場として、これからも社内 LT 会を続けていこうと思います!

また今回は私自身初めての企画ということもあり、バタバタしてしまって、ごく普通の LT 会になってしまいました。せっかくなので今後はスナックミーらしく、おやつをもぐもぐしながら LT 会を行ったりと、徐々にアップデートしていきたいです。

スナックミーでは、エンジニアを積極的に探しています!この記事を読んで興味を持ってくださった方や、おやつが大好きで「おやつと世界を面白くしていきたい」とお考えの方がいらっしゃれば、ぜひ応募していただけると嬉しいです。

engineers.snaq.me

募集ポジション

ソフトウェアエンジニア Backend (lead) / 株式会社スナックミー

ソフトウェアエンジニア FrontEnd (lead) / 株式会社スナックミー

ソフトウェアエンジニア Data Engineer / 株式会社スナックミー