All Articles

ACEインターンを終えて...

初めましてつばめと申します! 今回サイバーエージェントさんのACEというインターンに参加し個人とチームで賞をいただけたので、これを機会にブログを始めてみようと思います。

インターンACEとは

インターン募集ページ

開発型のインターン(ハッカソンじゃないここ重要)で、事前開発や当日3日間の開発をもとに実際にエンジニアとして働いている社員さんにFBをもらいながら成果物を突き詰めていくという内容でした。 具体的には、自分のチームの場合だとフロント2名+サーバサイド2名の計4名で取り組みました。使用技術は以下に示します。また、使用技術は他のチームの場合Golangだったり、Reactだったりとチームによって異なりました。また、これらの技術は選べるわけではなく、選考時に使用希望言語を選択する欄があり、そこで入力したものからチーム分けが行われるという形でした。そのため、この技術の欄はなるべく自信があるものを選択しておくほうが良いと思います…(自分達のチームでは2人ともあまりNodeに触れたことがなく大変なことになりました…)

  • フロント(記憶違いだったらすみません…) - Swift(iOS) - Swift UI
  • バックエンド - Node.js(後にTypeScript化) - AWS(Fargate+Aurora)

今回のインターンで学びたいと思っていたこと

最近Sceneryというサービスを開発しており、その過程で自分の作ったコードが読みにくかったり追いづらいなど、あまりにも保守性や拡張性が極端に低く、このままでは継続して開発してたらスパゲッティーしかできないと思い、「ドメイン駆動設計入門」という本を参考にドメイン駆動設計を学ぶことにしました。 そのため、今インターンでは実際に自分が思うコードを作り、メンターさんからFBをもらうことでより設計手法についての理解を深めたいという目標を掲げ参加しました。

本番前に感じたこと

募集ページにも書いてあるとおり、本番は3日間(8/20〜8/22)ですがその前に事前開発の期間があります。 自分は面接の最後に「事前開発の時間をとってもらいたいが大丈夫か?」という質問に対し「1週間開けてあります!」と答えましたが、全然足りませんでした… 7/30日にはチーム発表されているので少しずつ開発を行なっていたのですが、ディレクトリ構成やDockerfileの修正など行なっていたら、ベースを作るだけで後1週間ちょっとしかない…!?となります

また、他のチームではSwaggerを使いすでにフロントとサーバサイドでAPIの内容よあモックの共有をされていたのですが、自分達はエンドポイントとこのデータを返すという部分しかなくフロントの作業に迷惑をかけてしまうということがありましたので、最初のチーム会で決めておけばよかったなと後々後悔しました…

実際に作ったもの

私たちのチームではドメイン駆動設計を元にAPI開発を行いました。ディレクトリ構成図は以下に示したとおりです。

          2021 08 28 15 31 12

今回のインターンでは事前にMySQLやNode.jsの動くDockerfileと、Hello Worldが変えるAPIとMySQLに接続確認ができているプログラムファイルが提供されていてそれを元に開発を行うという流れでした。ちなみにもとのファイルはJavascriptで書かれており、Typescript化は自分達で行う必要があります。

また、今回の開発ではそれぞれ以下のことを目的にテストコードを書きつつ開発を進めていました。

  • Repository層(infra):正しくデータベースの検索が行われているかや、ORMのエンティティの定義が間違っていないか
  • Usecase層:RepositoryやInterfaceからのデータをもとに正しく処理が行われているか、または必要な箇所で想定する例外が返ってくるか
  • Handler(Interface層):今回統合的なテストコードを書く時間がなかったため、リクエストに対し想定するレスポンスが返ってくるか

細かい部分だと、Dockerfile内にTypescriptをコンパイルする処置を作ったりなど工夫した点は様々あるのですが、今回のインターンの目的が割と品質寄りだったこともあり、自分の中ではテストコードは書いてAPIを作成したつもりです…

開発中について

開発中に様々なアドバイスをいただきましたが、その中でも印象に残った2つについて書かせていただきたいと思います。

(私の受け取り方が違ったらすみません…)

Interface層で入力されたデータの確認をしっかりとするべき

以前DDDの勉強中、入力された値のチェックはどのように行うべきかを調べた際、ドメインロジックを使いバリデーションを行うと書かれていたものがあったため、それに倣いInterface層で受け取ったパラメータをそのままUsecase層に流していました。 そこでメンターさんから、途中でデータのバリデーションをつけるべきだというアドバイスをいただき上記のことを質問させていただいたところ、確かにしっかりとしたオブジェクト指向の言語の場合はUsecaseの入力時に型をつけることである程度不正な値は弾けるが、今回のTypescriptなどの場合Interface層できちんと値の選別をしないと不正データがUsecase層まで侵入し大変なことになると回答をいただき、なるほどなと思いました。また、その後に設計は決まった形があるわけではなく言語特性によって加えたり減らしたりする必要があるというお話をいただき、今まで自分は複数の言語で同じものを作るということがなかったため、とても印象的でした。

ちなみに、はそれぞれの言語でテンプレートを作ってGithubとかに持っておくと便利だよというアドバイスもいただきました。勉強して適宜修正すれば学んだことの履歴を残すこともできるので、今度時間がある時に今行っているNodeとGolangのテンプレート作ろうと思いました!

Usecase層とのやりとりで直接ドメインモデルを渡さないほうが良い

上記のアドバイスをもらった際、Interface層とUsecase層のデータの受け渡しに関してもアドバイスをいただきました。 今回作成したAPIの場合、そもそもデータの加工が少なかったため特に大きな問題が発生しているわけではないが、今後複雑化していく中で返すデータもモデルと1対1で結びつくわけではなくなる可能性が高いので、きちんとインタフェースを作りデータの受け渡しをしたほうが良いとのことでした。このことに関しては、DDDを元に自分がまだそこまで大きな開発を行なったことがないのですぐになるほど!とはならなかったのですが、確かに、規模が大きくなった時のことを考えると、それぞれで型を決めておかないと拡張性が下がるなと思い結局なるほどなりました。

他にも参照透過性やlet→constなど、ものすごく細かくまたためになるコードレビューをいただけたので、今後記録に残したものをいろんな場面で使っていこうと思います! (そのレビューをもらうためには早く開発を終わらせる必要があるので事前開発が大事に…)

また、とにかくメンターさんのフォローがすごかったです。 インフラ担当のメンターさんは開発時間外にも関わらずAWSの操作可能時間ギリギリまで手伝ってくれたり、サーバサイド担当のメンターさんは日付が超えそうになるまでプログラミングの面倒を見ていただきました。本当にありがとうございます!!!の一言に尽きます。 他にも、当日Discord上に駆け込み寺が設置されたりと本当につきっきりで3日間メンタリングをしてもらいとても勉強になる日々でした! 開発とは関係ありませんが、私たちがチームで作業していたりする間Discordのチャンネルに集まって話していたり、もともと社員さん同士の繋がりが強いイメージがありましたが、想像以上に仲が良さそうな印象を受けました。

感想

今回のインターンでは3日間という短い時間にも関わらずとても多くのことを学べたなと感じました。特に、自分が今興味のある設計についてアドバイスを頂けたことは非常に大きかったです。 また、その他にもチーム開発ができたことはとても良い経験でした。今までにもインターンでチーム開発を行うことはありましたが、その場でフロントとサーバを分けて行うという形だったため、今回のようにしっかりとアプリとサーバで分けて開発を行うことはありませんでした。そのため、別れているからこそ共有しなければならないことがあり、その点で色々と迷惑をかけてしまったことが今後の反省点です…。 また、私たちのチームはありがたいことに賞をいただけたことで1ヶ月追加開発する期間をいただけたので、可能な限り完成形に近づけるため残りの期間頑張っていきたいと思います。