LoginSignup
0

More than 3 years have passed since last update.

ことりんと一緒 Springもね - 7. サービス層

Last updated at Posted at 2019-01-19

概要 / 説明

Kotlinでサーバーサイドアプリケーションを作ってきましたが、まだきちんとした構成にはなっていない状態です。
ことりんと一緒 Springもね - 2. RestController と Data Class」 でコントローラクラスを作り、直接データを扱うような構成のままです。
そこで、少しずつ変更を行っていきます。
まず、ここでは「サービス」層を考えていきます。

service-layer.png

Webアプリケーションでは大きく分けて次のような機能が必要となります。

  • リクエスト/レスポンスの処理
  • アプリケーションロジックの処理
  • データの処理

今まではこれらの機能を単一レイヤで担当していました。
このままの構成だと、扱うロジックが増え、データモデルが複雑になってくると、
1つのクラスが巨大になり開発/保守効率が悪くなってしまいます。

それぞれの機能を分離して、複数のレイヤに分けていきます。

さて、作っていたクラスが RestController ということで、
本来はリクエスト/レスポンスを扱うことを責務とします。
そこで、それ以外の処理を切り出し、それを サービス とします。

前提 / 環境

ランタイムバージョン

  • Kotlin : 1.3.0
  • SpringBoot : 2.1.0.RELEASE

Spring Dependencies

  • Web
  • Actuator

開発環境

  • OS : Mac
  • IDE : IntelliJ IDEA
  • Build : Gradle

手順 / 解説

変更前のコントローラクラス

元々は以下のようにコントローラクラスの中でデータの生成など、リクエスト/レスポンスの処理以外のことを行っていました。

@RestController
@RequestMapping("/messages")
class SimpleController {

    @GetMapping
    fun getMessages() : List<Message> {
        return listOf(
                Message(
                        UUID.randomUUID().toString(),
                        "First Message",
                        "This is a 1st message on ${getDate()}."
                ),
                Message(UUID.randomUUID().toString(),
                        "Second Message",
                        "This is a 2nd message on ${getDate()}."
                )
        )
    }

    private fun getDate() : String {
        val simpleDateFormat = SimpleDateFormat("yyyy/MM/dd HH:mm:ss")
        return simpleDateFormat.format(Date())
    }
}

サービスクラス

元々コントローラクラスに実装していた内容を以下のようにサービスクラスに移します。

@Service("Message Service")
class MessageService {

    fun getMessages() : List<Message> {
        return listOf(
                Message(
                        UUID.randomUUID().toString(),
                        "First Message",
                        "This is a 1st message on ${getDate()}."
                ),
                Message(UUID.randomUUID().toString(),
                        "Second Message",
                        "This is a 2nd message on ${getDate()}."
                )
        )
    }

    private fun getDate() : String {
        val simpleDateFormat = SimpleDateFormat("yyyy/MM/dd HH:mm:ss")
        return simpleDateFormat.format(Date())
    }
}

サービスクラスには @Service アノテーションを付与します。
これによりコントローラクラスの中で Dependency Injection により利用できるようになります。

@Autowired
private lateinit var service: MessageService

lateinit キーワードは、インスタンスを初期化せずに宣言するときに使用します。

変更後のコントローラクラス

サービスクラスを使用するコントローラクラスでは、リクエスト/レスポンスに関する処理だけを担当するようにします。
以下のようにサービスクラスで実装している処理を呼び出すように変更を行います。

@RestController
@RequestMapping("/messages")
class MessageController() {

    @Autowired
    private lateinit var service: MessageService

    @GetMapping
    fun getMessages() = service.getMessages()
}

まとめ / 振り返り

責務ごとにレイヤを分けてアプリケーションを開発するのことは、今や定石ですね。
まだ、この状態ではサービスレイヤからデータ処理を直接行うようになっているので、
次はその部分を分離していきます。

今回のソース

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
0