Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

2024年版 Kotlin サーバーサイドプログラミング実践開発

2024年版 Kotlin サーバーサイドプログラミング実践開発

2024年6月22日(土) 「Kotlin Fest 2024」の発表資料です。

Takehata Naoto

June 22, 2024
Tweet

More Decks by Takehata Naoto

Other Decks in Programming

Transcript

  1. 竹端 尚人 主にバックエンドエンジニア Twitter: @n_takehata • 2006.04〜 公務員 • 2007.12〜

    SES • 2011.04〜 モバイルゲーム開発(サーバーサイド Kotlinを始める) • 2020.12〜 フリーランス(バックエンド開発、 テックリード、技術顧問など) 概要 現在は主に、クラウド型電子カルテを開発している株式 会社ヘンリーでエンジニアとして従事 Kotlin愛好会というコミュニティの運営もやっています
  2. • CEDEC 2018、2019登壇 • Software Design 2019年2月号〜4月号で短期連載 「サーバーサイド開発の品質を向上させる Java→Kotlin移行のススメ」執筆 •

    2021年4月 書籍「Kotlin サーバーサイドプログラ ミング実践開発」出版 • 2023年4月 Techpitにて「Kotlin入門ガイドー言語 思想から特徴・歴史・使いどころまで、まるっと予 備知識がわかる教科書」執筆 • Kotlin Fest 2024登壇 ←New 登壇、執筆
  3. プラグインのインストール fun main() { embeddedServer(Netty, port = 8080, host =

    "0.0.0.0") { install(CORS) install(Authentication) }.start(wait = true) }
  4. class UserService @Inject constructor(private val userRepository: UserRepository) { fun getUser(id:

    Int): User = userRepository.findUser(id) } コンストラクタでDI
  5. class UserService(private val userRepository: UserRepository) { fun getUser(id: Int): User

    = userRepository.findUser(id) } コンストラクタでDI
  6. fun main() { val di = DI { import(appModule) }

    val userService: UserService by di.instance() // ・・・ } フィールドでDI
  7. // 全カラム指定して定義 object Users : Table() { val id: Column<String>

    = varchar("id", 10) val name: Column<String> = varchar("name", length = 50) val age = integer("age") override val primaryKey = PrimaryKey(id) } // 数値のIDを自動作成 object Users : IntIdTable() { val name = varchar("name", 50).index() val age = integer("age") } // UUIDを自動作成 object Users : UUIDTable() { val name = varchar("name", 50).index() val age = integer("age") } テーブルの定義
  8. transaction { // Insert Users.insert { it[id] = "kotlin" it[name]

    = "Kotlin Fest" it[age] = 3 } // Update Users.update({ Users.id eq "kotlin" }) { it[age] = 4 } // Select val users = Users.select(Users.name, Users.age).where { Users.age greaterEq 3 } // Delete Users.deleteWhere{ id eq "kotlin" } } DSLのコード
  9. transaction { // Insert User.new { name = "Kotlin Fest"

    age = 3 } // Update user.age = 4 // Select val user = User.find { Users.name eq "Kotlin Fest" }.first() // Delete user.delete() } DAOのコード
  10. // Insert dslContext.insertInto(USERS) .columns(USERS.ID, USERS.NAME, USERS.AGE) .values("kotlin", "Kotlin Fest", 3)

    .execute() // Update dslContext.update(USERS) .set(USERS.AGE, 4) .where(USERS.ID.eq("kotlin")) .execute() // Select val users = dslContext.selectFrom(USERS).where(USERS.AGE.ge(3)).fetch() // Delete dslContext.deleteFrom(USERS) .where(USERS.ID.eq("kotlin")) .execute() クエリ生成のDSLのコード
  11. object Users : Table<Nothing>("USERS") { val id = varchar("id").primaryKey() val

    name = varchar("name") val age = int("age") } テーブルの定義
  12. // Insert database.insert(Users) { set(it.id, "kotlin") set(it.name, "Kotlin Fest" )

    set(it.age, 3) } // Update database.update(Users) { set(it.age, 4) where { it.id eq "kotlin" } } // Select val users = database.from(Users).select().where { Users.age greaterEq 3 } // Delete database.delete(Users) { it.id eq "kotlin" } クエリ生成のDSLのコード
  13. val user = database.sequenceOf(Users).find { it.id eq "kotlin" } if

    (user != null) { user.age = 4 user.flushChanges() } DAOのような実装にすることも可能
  14. class NumberTestByStringSpec : StringSpec({ "isRange:: when value in range then

    return true" { val number = Number(5) number.isRange(1, 10) shouldBe true } }) StringSpec
  15. class NumberTestByDescribeSpec : DescribeSpec({ describe("isOdd test") { context("num is odd

    number" ) { val number = Number(1) it("return true") { number.isOdd() shouldBe true } } context("num is even number" ) { val number = Number(2) it("return false") { number.isOdd() shouldBe false } } } }) DescribeSpec
  16. class NumberTestByStringSpec : StringSpec({ "isRange:: when value in range then

    return true(using forAll)" { forAll( row(1), row(10) ) { value -> val number = Number(value) number.isRange(1, 10) shouldBe true } } }) データ駆動テスト
  17. object NumberTest : Spek({ describe("isOdd test") { context("num is odd

    number" ) { val number = Number(1) it("return true") { assertTrue(number.isOdd()) } } context("num is even number" ) { val number = Number(2) it("return false") { assertFalse(number.isOdd()) } } } }) テストコード