Help us understand the problem. What is going on with this article?

Kotlinを何も知らない人間がKotlin+Spring BootでAPIサーバーを実装するメモ【1日目】

はじめに

完全に個人的な事情からですが、近い内に業務でサーバーサイドにおいてKotlinを使う可能性があるということで、予習がてら学習を始めました。

Kotlinは全くの未経験で、JavaはAndroidアプリを作ろうとほんの少し触れたことがあるだけで、ほとんど初学者レベルです。

この記事が初めて学習する方にとって有用であるかは心許ないですが、今後の学習コストやプロセスとして参考になる部分があるかもしれないと思い共有することにしました。

(間違っていることを書いている可能性が大いにあるので、その点はあらかじめご了承下さい🙏)

KotlinやJavaにまつわるメモ

Kotlingは「Better Java」と呼ばれることが多く、Javaでは表現できないことが多く実装されていたり、とりわけ辛いとされるnullを安全に扱うことができるのが特徴のようです。

ただしJavaと切り離して考えることは難しく、前提としてJava自体の知識やコツを抑えておく必要は大いにありそうです。以下、学習しながら取っていたメモになります。

アノテーション

@(アットマーク)がアノテーションを意味する。

@RestController
@RequestMapping(path = ["articles"])
class ArticleController(private val service: MemoService) {}

アノテーションは単なるラベリングに使用することもあれば、データを渡して振る舞いをもたせることもできる。
今回学習しているSpring Bootではラベルを用いてインジェクションすることが前提となるので、真っ先に理解する必要がありそう。

またアノテーションは@interface ~によって自作することもできる。

Gradle

ビルドの自動化システムで、プロジェクトに必要なライブラリを記述して依存関係を管理することもできる。

  • 依存性にはcompile、implementation、runtimeなど複数の属性がある。compileとimplementationの概念的な違いは分かっても、具体的に振る舞いがどう異なるかが理解できておらず。
  • 「kapt」とはjavaアノテーションをkotlinで使用するためのもの(?)
  • 「plugins」と「apply plugin」などバージョンによって記法が異なることがある
    • pluginsの方が新しい記法だが、gradle plugin repositoryにプラグインが存在する必要があったり、サブプロジェクトごとに適用を分岐するには古い記法を使用する必要があるらしい。
  • ./gradrewというコマンドもあり、ここから起動するとプロジェクト単位でgradleをインストールできるので、通常のgradleと違ってグローバルにインストールされている必要がないらしい。

JPA

JPAとは「Java Persistence API」の略称で、Java EE標準のORマッピングやDAOの技術仕様を定めたものとのこと。

「Hibernate」というKubernetesに似た名前のものがSpring Bootで利用されているが、これはJPAを実装したものの一つ。

SpringではJpaRepositoryというinterfaceを定義しており、データベースを操作する時にはこれを実装したRepositoryからCRUD操作を行う。

lateinit、by lazy、let

lateinitを使うことで、Nullを許可しないプロパティーの初期化をコンストラクタより後に遅らせられる。ただし完全なNonNullでなかったり、プリミティブ型には適用できないので注意。

Delegation Propertyという似た機能があるが、こちらはプリミティブ型にも対応しているものの、オブジェクトを生成することになるので、極力lateinitを使うことが望ましい。(大量にDelegation Propertyを利用するとパフォーマンス劣化が見られるとのこと)

by lazyは初めてオブジェクトが利用されたときに初期化され、以降は変更できない変数を意味する。

letは対象のオブジェクトをブロックで受け取り、ブロック内の返り値が代入される。Nullableな変数に対して使われることが多いらしい。

Serializable

interfaceの実装として「シリアライズすることができる」(ストリームの状態で書き出せる)と宣言すること。実装に際して必要なメソッド要件はなく、あくまで宣言に留まる。

プライマリコンストラクタ、セカンダリコンストラクタ

Javaと異なりKotlinではクラス名の後に()で指定するプライマリコンストラクタによって引数を受け取ることができる。
プライマリコンストラクタの処理内容はinit {}で実装する。

Javaでいうコンストラクタはセカンダリコンストラクタとして実装し、プライマリコンストラクタがある場合は必ずthis()によって呼び出す必要がある。なおプライマリコンストラクタを利用しなければならないわけではない。

dataクラス

処理は行わないけれど、データを保持するためのdata classがKotlinに用意されている。

通常のクラスと異なり、プライマリコンストラクタを必ず持っている必要があったり、値の同一性を確認するequals()などのメソッドが用意されている。

いかにもEntityとして使われることが想定されていそうな設計。

staticメソッドはない

Javaや他言語でいうstaticメソッドはKotlinでは意図的に実装されておらず、基本的にはpackage levelのfunctionとして実装することが望ましい。

どうしてもstaticメソッドを利用したい場合は、companion objectsを使うことで同様のことが実現できる。

またstaticメソッドがないためか、クラスインスタンスを生成する時にはnewではなくクラス名()となる。

coroutine

Kotlin 1.1から導入された機能で、「特定のスレッドに束縛されない、中断可能な計算インスタンス」のこと。
実行途中で処理を中断・再開することができるので、重たい処理をブロックせずに利用するときに便利と思われる。

参考: https://qiita.com/AtsushiUemura/items/fa3e84a9f6eacd509205

その他分からなかった用語

  • Java EE…「Java Platform, Enterprise Edition」の略
  • Java SE…「Java Platform, Standard Edition」の略
  • kotlin-stdlib…Kotlinのスタンダードなライブラリのこと
  • kotlin-reflection…JavaのリフレクションをKotlinで使用するためのもの。リフレクションとはクラスやメソッドを変数として動的に実行するためのもの。
  • class.java…Javaでいう「クラス名.class」を意味する

Spring Bootにまつわるメモ

今回はJVM系で最もポピュラーなフレームワークの一つであるSpring Bootを使ってみました。
Spring自体はまだ4時間ほどしか触っていませんが、感覚的には実装が否が応でも疎結合になり、テストも含めて凄く開発しやすいという印象を受けました。

Spring BootはSpring Frameworkというフレームワークを前身としており、Spring FrameworkがDI(依存性注入)コンテナとして始まっていたそうです。

DIについてはGolangで実装経験がありますが、暗黙的にinterfaceを実装するとinterface変更時に何かと辛かったり、アーキテクチャがフレームワーク単位で提供されているわけではないので、注入の実装自体に気を使う必要がありました。

Springではその部分がフレームワーク単位で提供されており、レールに沿って実装していけば自然と良い感じの疎結合が実現される(気がする)ので個人的にはかなりの好感触です。

さすがに短期的な生産性ではLL言語には敵わないものの、Spring BootによってXML地獄から開放されたらしく、またやラベルによるコード量削減によって全体的にシンプルに実装できるので、安定開発がもたらされる割に生産性はむしろ高いのではないかと感じました。

@Bean

SpringがDIコンテナである利点を象徴する機能(?)のようで、@Beanが記述されるとSpringがインスタンスを生成して管理し、それを@Autowiredを通じて変数に注入することができます。

まだこのありがたみを十分に享受できていませんが、各レイヤーごとのやりとりをDIコンテナによって代替することで、依存関係を気にすることなく、疎結合なアプリケーションが担保されるのではないかと考えています。

@Componentアノテーション

DIコンテナへの登録・取り出しという点では@Beanと同じだが、振る舞いとしては大きく異なる。

例えば@Beanはメソッドレベルの付与だが、@Componentはクラスレベルで付与し、@Beanのように@Configureを伴う必要がない。

また@Componentを実際に利用する時には各レイヤーごとに@Service@Repository@Controllerといったようにアノテーションを使い分ける。おそらくこれらの機能に違いはなく、役割を明示することに意義があると思われる。

application.yml

アプリケーションのプロパティをyaml形式で管理することができる。(プロパティファイルでも可)
InterlliJを使うとyamlすらプロパティの補完が聞くので安心感が凄い。

@RequestMapping

コントローラーに付与することでルーティングや出力形式を指定することができる。
同様にコントローラー内のメソッドにも@GetMapping@PostMappingなどを付与することで、各アクション(※)ごとのルーティングやフォーマットを規定できる。

producesとconsumesという似たプロパティがあるが、producesは出力形式、consumesは受け取るHTTPメソッドの形式を規定できる。

(※アクションという呼び方はRailsが染み付いた自分が勝手に呼んでいるだけで、Springでどのように呼ぶかは不明)

ResponseEntity

コントローラーのアクションが返す型を定義する。
プレーンなStringはもちろん、型をキッチリと定義した上でJSONを返すようにも規定できる。

とくに型をキッチリと守ることが求められるAPIサーバーでは安心感が凄い。

@Transactional

JPAを通じてデータベース操作を行うRepositoryで使うことがおそらく通常で、メソッドに@Transactionalというラベルを付けるだけでトランザクション処理をすることができる。

Golangで同様のことをすると結構手間になるが、Spring Bootを使うとこの宣言だけでトランザクション対応になることに感動しました。(意外と使ってみると辛いのかもしれませんが)

自動リロード

Gradleを使用している場合はspring-boot-devtoolsをdependenciesにruntimeで追加すると、開発用に自動リロードが有効になるそうです。

またIntelliJ IDEAを使用している場合は、「Build Project Automatically」を有効にした上で、Registryから「compiler.automake.allow.when.app.running」にチェックを入れる必要があります。

自動起動に関しては快適ですが、Golangではほぼ一瞬くらいの規模感でも、Spring Bootだと5秒~10秒くらい再起動に時間がかかるので、プロジェクトが大きくなった時に反映されるまでの時間が気になるところ。

関連記事

Kotlinを何も知らない人間がKotlin+Spring BootでAPIサーバーを実装するメモ
1日目 / 2日目

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした