ワンダーソフトコーヒーでは、エンジニアさんやデザイナーさんにとって「相棒」となるような一杯を目指して、日々焙煎を続けています。
そんな私たちが開発しているScalaベースのAPIプロジェクトでは、http4s
や tapir
を活用しながら、自動生成ツール cline
によって、実装ルールの整備と開発スピードの両立を図っています。
フォルダ構成で cline を活かす
cline を最大限活用するためには、「どこに何があるか」が明確であることがとても大切です。
そのため、以下のように、役割ごとにディレクトリを整理したプロジェクト構成を心がけています。
まず、プロジェクトのディレクトリ(サブプロジェクト構成)は以下のとおりです。
.
├── http-server
├── usecase
├── adapter
└── domain
上記を実現するために、以下のようなファイル構成となっています。
.
├── .clinerules
├── README.md
├── doc
│ └── development-guide.md # 開発ガイド(cline用ルール含む)
├── compose.yml # 開発用Docker構成
├── db # マイグレーション・初期データ
│ ├── migrations
│ └── seeds
├── http-server # API定義やルーティング
├── usecase # ユースケース層(サービスレベル処理)
├── adapter # 外部接続層(DBやAPIとの連携)
├── domain # ドメイン層(ビジネスロジック)
├── .scalafmt.conf
├── build.sbt # SBTビルド定義
├── Justfile # コマンドエイリアス定義
├── project # SBTプロジェクト設定
│ ├── Dependencies.scala
│ └── plugins.sbt
└── scripts # 開発用スクリプト群
このように構成しておくことで、cline に対して以下のような的確なルール定義が可能になります。
# HTTP4S テンプレート開発ガイド
このドキュメントは、HTTP4S テンプレートプロジェクトの開発に関するガイドラインを提供します。
## 目次
- [プロジェクト概要](#プロジェクト概要)
- [アーキテクチャ](#アーキテクチャ)
- [開発環境のセットアップ](#開発環境のセットアップ)
- [データベース操作](#データベース操作)
- [APIエンドポイントの追加方法](#apiエンドポイントの追加方法)
- [テストの書き方](#テストの書き方)
- [認証の仕組み](#認証の仕組み)
- [デプロイ方法](#デプロイ方法)
- [トラブルシューティング](#トラブルシューティング)
## プロジェクト概要
このプロジェクトは、HTTP4S、Tapir、Scala 3を使用したRESTful APIのテンプレートです。クリーンアーキテクチャに基づいて設計されており、以下の特徴があります:
- Scala 3の最新機能(derives、enum、extension methodsなど)の活用
- HTTP4SとTapirによる型安全なAPIエンドポイント定義
- Auth0による認証・認可
- ScalikeJDBCによるデータベースアクセス
- クリーンアーキテクチャに基づいたモジュール構成
## アーキテクチャ
このプロジェクトはクリーンアーキテクチャに従い、以下のモジュールで構成されています:
### domain
ビジネスロジックの中心となるエンティティとリポジトリインターフェースを定義します。
```
domain/
└── src/main/scala/com/wonder_soft/http4s/template/domain/
├── auth/ # 認証関連のドメインモデル
├── config/ # アプリケーション設定
├── item/ # アイテム関連のドメインモデル
└── location/ # ロケーション関連のドメインモデル
├── Region.scala # 地域モデル
├── RegionRepository.scala
├── Prefecture.scala # 都道府県モデル
├── PrefectureRepository.scala
├── City.scala # 市区町村モデル
└── CityRepository.scala
```
ドメインモデルは外部依存を持たず、純粋なビジネスロジックのみを含みます。
### usecase
アプリケーションのユースケース(ビジネスロジック)を実装します。
このルールは doc/development-guide.md にまとめておき、開発者にも cline にもわかりやすく伝わるようにしています。
そしてこのルール自体も cline に相談しながら用意しています。
Routingの実装例(Scala × http4s × tapir)
以下は、/location/prefectures
というエンドポイントを定義したコードの一部です。
class LocationRoute(
cc: AppControllerContainer
) {
private val findAllPrefectureEndpoint: ServerEndpoint[Any, IO] =
endpoint.get
.in("location" / "prefectures")
.errorOut(statusCode and stringBody)
.out(
statusCode and jsonBody[
FindAllPrefectureEndpoint.FindAllPrefectureEndpointResponse
]
)
.serverLogic { _ =>
cc.Endpoint.findAllPrefectureEndpoint
.execute(FindAllPrefectureEndpoint.FindAllPrefectureEndpointRequest())
.map(_.toEndpointResponse)
}
val route = List(
findAllPrefectureEndpoint
)
}
こうしたAPIの定義も、ルールに従ってフォルダ構成と連携することで、cline
が的確にコードスケルトンを生成してくれます。
cline を使ってみて感じたこと
cline
を活用していく中で、その便利さには日々助けられていますが、一方で少し気をつけたいなと感じる場面もありました。
それは、すでにある程度アーキテクチャが定まっているプロジェクトで cline
を使ってアーキテクチャ自体の新たな変更(sub projectの追加や依存性を根っこから大きく変える変更)を加えようとしたとき。
そうしたケースでは、cline
が自動的に構成を判断してくれるがゆえに、意図とは少し違った場所にファイルが生成されてしまうことがありました。
もちろん、これは cline
の問題というよりも、「どんな構成にしたいのか」をこちらが明確に伝えきれていないことに起因する部分も多く、まだまだ開発者自身が判断すべき部分も残っていると感じます。
とはいえ、こういった体験も含めて、ツールとの対話を通じてアーキテクチャそのものを見直す良いきっかけになっているとも思っています。
これからも試行錯誤を続けながら、よりよい使い方を探っていきたいです。
参考にした記事
この clinerules
の考え方は、@karaage0703 さんのZenn記事
👉 AIコーディング時代の開発環境構築:VS Code × Cline(Roo Code)で爆速開発! を参考にしています。
そして気づけば
cline
がコーディングルールに沿ったファイルを自動生成しているあいだ、私たちはドリップコーヒーを淹れて一息つくようになりました。
コードとともに、いい香りの文化も自然と育ってきた気がしています。
今後も、ソフトウェア開発やデザインのあれこれについて、コーヒーとともにゆるく投稿していきますので、どうぞお楽しみに ☕✨
🔗 Wonder Soft Coffeeのオンラインストアはこちら:
👉 https://coffee.wonder-soft.com/collections/all