はじめに
はじめまして!10月から Booost!!! Excite Internship 2025 に参加していました、髙木と申します。
ここでは1ヶ月間のExcite就業型インターン「Booost!!」から学べたことをブログにしました!
自己紹介
情報系の大学に通っています、髙木と申します。 普段は長期インターンでDifyプラグイン開発を行っていたり、インターンに参加したり個人開発を行ったりしています。 私が "Booost!!! Excite Internship 2025" に参加しようと思った理由は、「Goを使った開発を行いたい」と「アーキテクチャの理解を深めたかった」という理由から参加しました。
今回のインターンは特に「クリーンアーキテクチャの理解を深める」を意識して臨みました。 なんとなく個人開発などでクリーンアーキテクチャは実装したことがありましたが、わかったフリで実装している部分も多かったので、理解を深めることを意識しました。
なぜアーキテクチャの理解を深めたいのか
近年、AIの早すぎる進化にプロダクト開発の在り方が変わってきていると思います。 AIのコード生成の精度の良さにコードを書く価値というものも変化しているなかで、今後は設計の部分がより重要視されるのではないかと考えています。 もちろん昔からアーキテクトは大事ではあったと思いますが、コードを書くという所に集中が減った分、設計に時間をかけることができるのでここの理解を深めておく必要があると感じました。 またシンプルに開発思想を知ることに面白みを感じたというのも理由にあります。
業務内容
配属先は SaaS・DX事業部のkuroten で、バックエンドの機能追加を担当しました。
具体的には、kurotenのメッセージ内容が古いものが表示されていたので作成された日時のものを表示する タスクです。
各層の依存関係を見ながら、メッセージ内容を更新する実装をしました。
また、別のインターンでは質問のしづらさということがあり、学習のしづらさがあったので今回は質問の仕方を変えてみたり、積極的に質問することを意識しました。 やはり、自分で長時間考えてしまうより、長年プロジェクトに関わっている方に聞く方が早く、その分学びの量も増えるので積極的に質問するべきだと痛感しました。
学び①:アーキテクチャの責務の分離
この1ヶ月で最も大きく変わったのは、アーキテクチャの考え方です。
これまでは「MVC」や「レイヤードアーキテクチャ」をなんとなく理解して使っていたのですが、クリーンアーキテクチャの思想を意識して開発を進めたことで、責務の分離の重要性を強く実感しました。
たとえば、処理の流れを「UseCase(ビジネスロジック)→ OutputPort(出力用インターフェース)→ Presenter(表示変換)」のように明確に分けることで、「どの層が何を担当しているのか」が自然と見えるようになりました。
また責務を分離することでテストや使用している技術の変更に強くなること。現代のアプリケーション開発は多くの変更を取り入れることからクリーンアーキテクチャは適していると感じました。
自分が理解した各層の責務をまとめてみます。
UseCase(ユースケース層)
「アプリケーションの中で“何をしたいか”を定義する層」
たとえば「ユーザーを登録する」「お知らせを作成する」「ログインする」といった、
アプリの具体的な操作や処理の流れを司るのが UseCase 。
- 役割:処理の流れを組み立てる
- 例:
CreateUserUseCase→ ユーザー情報を受け取って登録処理を呼び出すSendNoticeUseCase→ メッセージ送信処理の順序を定義する
ポイント:
UseCase自体は「どのデータベースを使うか」や「どんなUIで表示するか」を具体的に知ってはいけない。
interfaceで定義されたメソッドを使い、抽象的に使用を徹底することでクリーンアーキテクチャの良さが発揮される。
あくまで“アプリの動き”だけを定義する。
Service(ドメインサービス層)
「業務的なルール(ビジネスロジック)の実装を担う層」
UseCaseが「やることの流れ」だとすれば、Serviceは「どうやるか」を担当する。
- 役割:ビジネスルール(ドメイン知識)をコードで表現する
- 例:
NoticeService→ 新しいお知らせを作成し、バリデーションや日時の整形を行うAuthService→ 認証トークンを検証してユーザー情報を返す
ポイント:
ServiceはUseCaseから呼ばれる存在で、
「どうやってドメインのルールを実現するか」を責務としている。
Infrastructure(インフラ層)
「外部とのやり取りを担当する層」
データベースやAPI、メールサーバーなど、
“外の世界”と通信する処理をまとめるのが Infrastructure の責務。
ポイント:
Infrastructureは「実装の詳細」を扱います。
クリーンアーキテクチャでは、この層を内側(UseCase・Service)から直接参照しないようにすること。
→ 代わりにRepositoryインターフェースを通じてアクセスします。
Repository(リポジトリ層)
「データの取得・保存を担当する層」
Repositoryは、「どんなDBを使ってもいいようにするための仲介役」。
- 役割:データの処理(CRUD)を抽象化する
- 例:
UserRepository→ ユーザー情報をDBから取得/保存NoticeRepository→ お知らせの一覧を返す
ポイント:
Repositoryはインターフェースとして定義し、 実際の実装は Infrastructure層 に置きます。
こうすることで、「使う側(UseCase)」は“どう保存するか”を知らなくてもよく、repository層だけを知っていればいいことになる。
ここで私的に、Repository と Infrastructureの違いがわかりずらかったのでまとめてみました。
Repository と Infrastructure の違い
| 観点 | Repository層 | Infrastructure層 |
|---|---|---|
| 目的 | データアクセスの抽象化を行う | 具体的な実装(SQL文, ORM文) |
| 内容 | 「どんな処理を行うか」をインターフェースとして定義 | 実際にDBや外部APIにアクセスする実装を書く |
| 依存関係 | UseCase層から呼ばれる | Repositoryインターフェースを実装し、DBなどに依存 |
| イメージ | 「契約書」 | 「契約書の内容から働く人」 |
まとめると:
Repositoryは「契約書」であり、Infrastructureは「実装する人」です。
この責務の分離があるからこそ、DBの種類(MySQL → DynamoDBなど)を変えても、他の部分を変更しなくても変更することが可能になります。
Controller(コントローラ層)
「外部(HTTPリクエスト)からアプリを動かすための入口」
Controllerは、「リクエストを受け取る入り口」です。
func (c *UserController) Create(ctx iris.Context) {
input := parseUserInput(ctx)
output := c.usecase.CreateUser(input)
ctx.JSON(output)
}
これによって、修正が非常にしやすくなり、「データをどう扱うか」と「どう見せるか」を完全に切り離して考えを持ったのは大きな収穫でした。
今後は個人開発でクリーンアーキテクチャ以外に挑戦し、ソフトウェア開発の思想を広げていきたいと思います。
学び②:テストコードとの出会い
もう一つの学びは、テストコードです。
恥ずかしながらバックエンド志望でありながら、テストコードの経験が皆無と言っていい程浅いです。
今回はkurotenのテストコードの書き方を見習い、そこで得た知見を業務時間外などで実装してみたりしテストに対して理解が深まったと感じています。
実務ではテストコードは多く書いていないですが、kurotenのテストコードを理解し、テストに対する知見を得られたことは本当に良かったです。
おわりに
1ヶ月の間、 "Booost!!! Excite Internship 2025" で貴重な経験を積ませていただきありがとうございました! バックエンド経験の浅い私を受け入れてくださった担当社員の方をはじめ、メンターの方には感謝申し上げます。