MIXIのインターンに参加してきた話

MIXIのインターンである「Dive into MIXI 2023‐2024 冬・春季」に2ヶ月間参加してきました！

![PXL_20240414_075320538 (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3143089/f5fc3acc-2d61-0c90-ced5-2cf7d7626d5d.jpeg)


インターンで行ったことを振り返りつつ、感想などを記事にします！

# 配属チームとプロダクト

minimo事業部開発グループのバックエンド開発チームでインターンしてました。

ミニモって何？ って方もいるかもしれないので簡単に紹介すると、「サロン予約サービス」であり、サロンスタッフを**直接**予約できるといったサービスです。

https://minimodel.jp/

他のサロン予約サービスでは、サロン自体にスポットが当たりますが、ミニモでは口コミがサロンスタッフに対して行われるなど、個人 to 個人を大切にしているサービスだったりします。
店舗ではなく、スタッフの評価を直接見て予約できるという安心感があります。

またminimo限定価格といって安くなる場合もあるとかないとか...

私はインターンを機に使い始めましたが、内部のこだわり具合を見てしまうと推さずにはいられませんでした！

# タスク概要

インターンでは主に2種類のタスクに取り組みました。

１種類目はPerlからGoへのリプレス↓

- job workerにダンプ処理の追加
- 通報系API2つの実装

2種類目はCI/CD構築↓

- リリース時にMagicPodを動かすCI構築

# job workerにダンプ処理の追加

最初にオンボーディングタスクとして、定期実行される job worker の中の、「掲載タグ一覧をダンプする処理」のPerlからGoへの移行を行いました。

変更前のPerlのダンプ処理の流れが以下の図になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3143089/9c92bd2c-641d-b112-6fd1-a1a73664f614.png)

PerlからGoへの移行として、赤線で囲まれている job worker にダンプ処理を追加しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3143089/67fee31c-adf0-629d-b824-234051afad48.png)

ただし、このままでは 「2.処理を積む」 の部分で、管理ツールからPerl用SQSへ積まれているままであり、キューが取得できない状況になっています。
そのためjob workerの実装後、以下のように管理ツールからGo用のSQSに積むように切り替えを行いました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3143089/f808dd43-f69e-05e7-5041-e4da40bd32dc.png)

最初は「ダンプ」という言葉すら知らなかったため、これがオンボーディングタスク!? と思っていましたが、HさんやKさんの書かれていたわかりやすい過去issueのおかげで進めることができました。
自分のやったことをissueとして残す大切さを学ぶことができました。

# 通報系API2つの実装

次のタスクとして、予約通報と掲載者通報のリプレイスを行いました。

**予約通報**とは、サロンが予約に対して不正なキャンセルを行った場合、ユーザーがそのキャンセルを迷惑行為として通報するものです。

**掲載者通報**とは、掲載者(サロン)に迷惑行為などを受けた場合、ユーザーが掲載者を違反行為として通報するものです。

以下はバリデーションや排他制御を抜いた2つのAPIの実装方針です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3143089/5cee42b6-816b-d8d5-bddf-82613c0c95ef.png)

これを見て分かる通り、UseCaseの処理が似ていました。

:::note info

UseCaseとは以下の図の赤線で囲われた部分であり、domainを組み立ててアプリケーションの流れを作成する層のことです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3143089/449ea7dc-a00f-493d-4c15-fa82eeb5844f.png)

:::

元々Perlでは同じファイルであり、似たような処理であれば、UseCaseを統合し、DRY(Don't repeat yourself)にできるのではないかと考え、予約通報APIと掲載者通報APIでUseCaseを使い回せるように実装を行いました。

しかしいざ実装してみると、違和感のあるコードが出来上がりました。
2つのAPIではリクエストから取得できる値が異なるため、それぞれの通報用の構造体を受け取ったら処理が切り替わるというフラグのような実装になっていました。

ここで、迷ったときは書籍に頼ってみるのも手だと考え、**Clean Architecture**を引っ張ってきました。

https://tatsu-zine.com/books/clean-architecture

この本の16章にある「重複」という節では

> ユースケースを垂直に分離していると、こうした問題に遭遇する。そして、ユースケースを統合したくなる。なぜなら、画面構成が似ていたり、アルゴリズムが似ていたり、データベースのクエリやスキーマが似ていたりするからだ。気をつけてほしい。反射的に重複を排除する罪を犯してはいけない。その重複が本物かどうかを見極めるべきだ。

と書かれていました。
事例もほぼドンピシャであったため、最終的にはUseCaseを統一せず分けて実装を行いました。

## リプレイスタスクに取り組んでみて

「なぜこのような実装になっているのか」を過去のPRなどから解明していくという作業を初めて行いました。
ミニモは10年前からあるプロダクトであり、歴史的経緯を知るたびに考古学のようでとても面白かったです。

またPerlを学ぶことでGoやその他の言語に感謝の心が芽生えました。

Perlはモジュールの依存関係を自動で解決してません。
Goでは依存関係を自動で解決してくれますが、最近ではそれを当たり前と享受していたため、これからはもっとGoに感謝しようと思いました。

また過去のPerlでは以下のようにサブルーチンに引数の宣言がありません...

```perl
sub func {
    my $self = shift;
    my $param = shift;
}
```

:::note warn
現在のPerlでは引数宣言ができるようになっています
:::

他にもPerlでは1行で書いた場合、右から左に読まなくてはいけないため慣れるまでが大変でした。

```perl
print "foo" if $param
print "bar" unless $param
```

色々Perlの愚痴を書いてみたものの、コード自体はとても読みやすかったです！
10年経っても読みやすいようなコーディングを心がけようと思いました！

# リリース時にMagicPodを動かすCI構築

インターンの後半では、GitHub Actionsを使った「リリース時にMagicPodを動かすCI構築」を行いました。
CI構築と書きつつ、デプロイも行っているため実際はCI/CD構築のタスクと言ってもいいかもしれません。

**MagicPod** とは簡単に言うとE2E自動テストのことであり、QAさんが手作業で仕様確認している業務を自動で行ってくれるサービスです。

リリースする前の最終チェックとしてQAさんの作ったテストで確認したい！といったモチベーションがあり、今回のタスクをいただきました。

CIの簡単な流れとしては以下のように実装を行いました。

1. CIをコメントでトリガー
2. テスト環境に対して差分をデプロイ
3. デプロイが完了するまで待つ
4. MagicPodのテストを実行する

3の「デプロイが完了するまで待つ」方法が一番難しいところでした。
メンターさんと相談し以下の方法でWaitすることにしました。

- ECSで適用されているイメージタグ(コミットハッシュ)を返すエンドポイントをサーバに生やし、レスポンスが最新のコミットハッシュと一致するまで待つ

この方法はCDKでECSの環境変数にコミットハッシュを追加することで実現できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3143089/93db79b3-da35-f6e8-5141-4d4072a7660c.png)

:::note warn
【4.差分を検知】の部分について、正確には以下の流れとなっています。
[CDKリポジトリ]-(CD実行)->[CodeBuild]-(デプロイ実行)->[CloudFormation]
:::


## CI/CDのタスクに取り組んでみて

最初にこのCI/CDのタスク説明を受けたとき、わからない単語が多くて笑ってしまった記憶があります。
ですが、CI/CDに詳しいメンターさんがわからないところや見逃している点をわかりやすく教えていただけたおかげで、なんとか終わらせることができました！

タスクの感想として、CI/CD構築は環境を破壊してしまうのではないかという恐怖との戦いでした。

デプロイ先を間違えると本番環境に影響してしまうため、メンターさんにたくさんレビューしてもらい心を落ち着かせつつ、インターン生でこのような経験ができるのはとてもありがたいなとも思っていました。

また Github Actions に関して言うと `issue_comment` をトリガーにした場合、ワークフローファイルがデフォルトブランチにある場合にのみ、ワークフローの実行がトリガーされるため、mainブランチにマージしないと本当の意味で動作確認ができないという怖さがありました。

他にもデプロイが絡んでくると、実装手順や動作確認方法についても大変でした...

とはいえ、CI/CDはとても便利だと感じました。ミニモではCI/CDが整えられており、

- マージするだけでリリースができる
- 誤まったパッケージ名の修正
- 自動でコンフリクト解消してPR作成
- 自動でフォーマットしてPR作成
- 他にも色々...

などがあり、開発体験がとても良かったです。

# タスクの感想

学生では経験しづらいリプレイスやCI/CD構築の経験ができ、とても成長できたと思います。

新規開発の経験がある人は多いですが、リプレイス経験がある人は少ないと思うのでとても貴重な経験をさせていただきました。

またCI/CDに関しても、学生の段階ではプロダクトにCI/CDを構築する機会が基本的に無いため、リプレイスと同じく貴重な経験をさせていただきました。

総じて、新しいことにたくさん取り組めてとても楽しかったです！

# ミニモの感想

ミニモでは、BizやCSなどエンジニア以外の人との距離の近さが印象的でした。
基本的に朝会はチームで行うものだと思っていましたが、ミニモでは全体で朝会を行っており、ミニモ事業部全体がチームのようでした。

そして、その朝会の5分LTが実は毎日の楽しみでした。
趣味の話や旅行の話、タメになる話など色々ありましたが、他の人ってこんなことしてるんだ！の連続で面白かったです。

# おまけ

MIXIのオフィスは渋谷スクランブルスクエアにあります。
なんという高さ！！

![PXL_20240329_105859411.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3143089/5bf4c7d7-5bf7-8861-5f76-34bf341ea952.jpeg)

眺めがとても良かったです。

![PXL_20240329_064314312.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3143089/111a87e3-4ae6-8269-224a-060121189e0f.jpeg)

スクランブル交差点がとても小さく見えました！

![PXL_20240329_064419518.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3143089/e8bb2465-8478-668e-296b-48e53c315131.jpeg)

改めてすごい場所で働いてたんだな〜と実感...

# 最後に

メンターのMさんをはじめ、バックエンド開発チームの方々、人事のKさん、インターン期間中に関わってくださった全ての方々にとても感謝しております！

2ヶ月間ありがとうございました！！