Upgrade to Pro — share decks privately, control downloads, hide ads and more …

10年前のレガシーシステムをサーバーサイドKotlinでフルリニューアルしている話 #jjug_ccc #ccc_g2

10年前のレガシーシステムをサーバーサイドKotlinでフルリニューアルしている話 #jjug_ccc #ccc_g2

JJUG CCC 2017 Fall での発表資料です
◆githubにサンプルプロジェクトあげてます
https://github.com/maeharin/kotlin-dvd-rental-dev

◆Kotlinのイベント「どこでもKotlin」を開催してます!
https://m3-engineer.connpass.com/event/70561/

Hidenori Maehara

November 18, 2017
Tweet

More Decks by Hidenori Maehara

Other Decks in Technology

Transcript

  1. 10年前のレガシーシステムを
    サーバーサイドKotlinで
    フルリニューアルしている話
    #jjug_ccc #ccc_g2
    2017/11/18 JJUG CCC 2017 FALL
    エムスリー株式会社 前原
    @maeharin

    View full-size slide

  2. ● 前原 秀徳
    ● @maeharin(まえはりん)
    ● エムスリー株式会社
    ● エンジニアチームリーダー、グループ会社取締役等を歴任
    ● 好きな言語等:Kotlin、Ruby、Vue.js
    ● 好きな漫画:ベルセルク(心の支え。悩んだら読む)
    ● 自慢:ブログ記事が、はてぶ1200超えた
    ○http://maeharin.hatenablog.com/
    自己紹介

    View full-size slide

  3. ・医療に関するWebサービスを多数展開
    ・全世界で約400万人の医師会員
    ・日本で約25万人の医師会員
    エムスリーって何の会社?

    View full-size slide

  4. 今回のゴールド・コーヒースポンサーです!

    View full-size slide

  5. Kotlin本、好評発売中!
    日本Kotlinユーザグループ代表、長澤太郎が在籍

    View full-size slide

  6. 1. リニューアルの背景・概要
    2. 経営会議承認までの道
    3. 技術選定の理由
    4. Kotlin APIサーバーの作り方
    5. イベント「どこでもKotlin」の紹介
    アジェンダ

    View full-size slide

  7. 1. リニューアルの背景・概要

    View full-size slide

  8. 今、私たちは10年に一度の
    システムリニューアルをしてます!

    View full-size slide

  9. 医師のキャリア支援事業
    (年間売上、数十億規模)
    システムリニューアルの対象システム

    View full-size slide

  10. とある事業の今期開発予定だけで
    約600人日(2年半)
    という見積りが!
    開発スピードの低下が課題

    View full-size slide

  11. ● 複数のサブシステムが存在。データとロジックが重複
    ● 長年の改修でアーキテクチャが限界
    データ重複
    200テーブル・2000カラムのう
    ち、半分くらい重複
    ※DB以外に生Luceneも
    ロジック重複
    複雑な依存関係
    原因1: 複雑なアーキテクチャ

    View full-size slide

  12. ● 複数のサブシステムが存在。データとロジックが重複
    ● 長年の改修でアーキテクチャが限界
    データ重複
    規模感:
    200テーブル・2000カラム
    ※DB以外に生Luceneも
    ロジック重複
    複雑な依存関係
    かなり簡素化してこれ...(^ω^)
    原因1: 複雑なアーキテクチャ

    View full-size slide

  13. 主要システム
    Ruby on Rails
    ● ビジネス上優先度の高いシステムはRuby on Rails
    ● 優先度低いシステムは10年前のシステム
    ○ → だが、この部分の優先度が高まってきた
    10年前の
    Javaシステム
    7年前の
    Javaシステム
    原因2: 10年前のシステムが...
    Javaの独自FW
    viewの部分はXSLT!

    View full-size slide

  14. 補足:XSLTとは

    View full-size slide

  15. 補足:XSLTとは

    View full-size slide

  16. 2001〜2002年頃の技術...(^ω^)
    補足:XSLTとは

    View full-size slide

  17. つらい_(:3」∠)_

    View full-size slide

  18. リニューアルだ!

    View full-size slide

  19. 重複DBや重複ロ
    ジックを廃止し、API
    に一元化!
    リニューアル後のアーキテクチャ

    View full-size slide

  20. 控えめに見積もって
    生産性2倍以上!
    WEBアプリ
    APIサーバー
    リニューアル後の技術スタック

    View full-size slide

  21. 5月 6月 7月 8月 9月 10月 11月 12月 1月 2月 3月
    12月上旬に
    10年前の部分の
    リニューアルを
    リリース!
    今の進捗
    開発
    ▲プロトタイプ作成
    ▲経営会議承認
    ▲リリース1
    開発 ▲リリース2
    ▼NOW
    ※ エンジニア3名で頑張ってます

    View full-size slide

  22. 2. 経営会議承認までの道

    View full-size slide

  23. 少し触ると障害が起きる
    何をやるにも時間がかか
    りすぎる
    DBの設計にアンチパ
    ターンが...
    アーキテクチャが複雑す
    ぎる
    100テーブルくらい
    重複してる...
    プロジェクト提案前の私の悩み...
    _(:3」∠)_

    View full-size slide

  24. 12人月以上
    必要だよな...
    やるべきだけど、
    どこまでスコープにする
    べきか..
    プロジェクト提案前の私の悩み...
    ビジネスメンバーを
    どうやって
    説得するか... 経営陣をどうやって
    説得するか...
    _(:3」∠)_

    View full-size slide

  25. 色々悩んだが、経営会議でプレゼンし、承認!
    \承認/

    View full-size slide

  26. 1. 最優先イシューを、粘り強く見極めた
    ● 一気に何もかもやろうとすると、終わらない
    ● とはいえ、局所的な改善では意味がない
    ● 周りの人に何度も相談し、イシューを定めていく
    踠き 挑み 足掻く!!
    それこそが死と対峙する者の唯一の剣!!
    ゆめゆめ忘れぬことだ!!
    by ベルセルク

    View full-size slide

  27. 2. 複数案検討し、可能な限り数値化した
    ● 経営陣を説得する際、数値化は必須と考えた
    ● 複数案考え、各案のコストやメリットを数値化した
    ○ 1案だと自分の視野も狭くなるし、経営陣も決められない
    ● 開発効率化だけでなく、エンドユーザーへの提供価値も織り込
    めると話は進みやすい
    言葉にすることだけが
    気持ちを伝えるすべてではなくてよ
    ファルネーゼさん
    by ベルセルク

    View full-size slide

  28. ● 私がRuby on Railsで全部で作った
    ● UIにはVue.jsやmaterial-components-webを使用
    ● 早期にリスクを発見できることも
    ● 自分への自信 → 経営陣への説得力
    3. プロトタイプで不確実性をコントロールした
    言葉は無粋!!押し通れ!!
    by ベルセルク

    View full-size slide

  29. 3. 技術選定

    View full-size slide

  30. ● APIサーバー
    ○ 重複ロジック・DBを一元化したい
    ○ 型を用いてカッチリとやりたい
    ● フロントサーバー
    ○ 複数のサービスがある
    1. メインサイト(Rails、1年前にリプレイス済)
    2. サテライトサイト(Java、7年もの...)
    3. 管理画面:3種類(Java、10年もの...)
    ○ 頻繁に改修が入る
    ○ リッチなUIへのニーズが強い
    技術選定のポイント

    View full-size slide

  31. postgresql
    ElasticSearch
    メインサイト
    サテライトサイト postgresql
    管理画面(3種)
    10年もの
    7年もの
    生Lucene
    生Lucene
    リニューアル前の技術スタック

    View full-size slide

  32. postgresql
    ElasticSearch
    メインサイト
    サテライトサイト postgresql
    管理画面(3種)
    10年もの
    7年もの
    生Lucene
    生Lucene
    リニューアル前の技術スタック
    廃止
    フルリプレイス

    View full-size slide

  33. postgresql
    ElasticSearch
    メインサイト
    サテライトサイト
    管理画面(3種) APIサーバー
    リニューアル後の技術スタック

    View full-size slide

  34. なぜAPIサーバーにKotlin?
    Kotlin

    View full-size slide

  35. Kotlinとは
    Kotlin
    ● 静的型付けオブジェクト指向言語
    ● いわゆる「JVM言語」
    ● 開発元:JetBrains
    ● 2016年2月に正式リリース
    ○ 2017/11/18 現在、ver1.1.60
    ● Apache License ver2.0
    ● 特に、Google I/O 2017以降、爆発的な広がり

    View full-size slide

  36. Google I/O 2017
    https://twitter.com/Jayroo5245/status/926120722539282432

    View full-size slide

  37. Kotlin
    ※長澤太郎さんの発表資料より抜粋
    スリムなコードベース

    View full-size slide

  38. Kotlin
    Null安全

    View full-size slide

  39. Kotlin
    型推論

    View full-size slide

  40. ● 背景:
    ● チームのRubyエンジニア7-8名(Javaもたまに触る)
    ● 対象システムの規模感
    ○200テーブル、2000カラム(100テーブルがサブシステム重複)
    ○ソースコード行数:数十万行
    ● フロントはゆるく。コアはカッチリやりたい
    ○型が欲しいという声がメンバーから噴出したことも
    ○通称:型一揆
    Kotlin選択理由

    View full-size slide

  41. ● 型:あり(型推論、null safetyも嬉しい)
    ● エムスリーにはたろう (@ngsw_taro) がいる!
    ● フレームワーク:Spring Boot(問題なし)
    ● Java製の社内ライブラリは使えるか:使える
    ● IDE:IntelliJ IDEA
    ● 学習コスト:RubyENGは親しみやすい構文(後述)
    Kotlin選択理由
    Kotlin Webアプリケーション
    新しいサーバサイドプログラミング
    絶賛発売中!
    エムスリー株式会社
    日本Kotlinユーザーグループ代表
    長澤 太郎
    たろう(@ngsw_taro)
    ● 言語の将来性:きっとある(Google I/O 2017)

    View full-size slide

  42. Ruby Kotlin
    a.map {i -> i * 10}
    a.reduce {sum,n -> sum + n}
    a.groupBy {i -> i % 2}
    a.filter {i -> i % 2 == 0}
    a.map {|i| i * 10}
    a.reduce {|sum,n| sum + n}
    a.group_by {|i| i % 2}
    a.select {|i| i % 2 == 0}
    (参考)Rubyエンジニアに親しみやすい構文

    View full-size slide

  43. ● SpringはオフィシャルにKotlinサポートを宣言
    Spring Boot

    View full-size slide

  44. ● JavaのDBアクセスフレームワーク
    ● 2Way-SQL(SQLを外出しできる)
    ● 社内のJavaプロジェクトでも利用多い
    ● 「Domaの開発で大切にしている10のこと」に共感
    ○ https://qiita.com/nakamura-to/items/099cf72f5465d0323521
    Doma2

    View full-size slide

  45. ● Rails5.1でwebpackerが導入された
    ○ Vue.js等のjsライブラリを用いた開発が楽
    ● メインサイトはRuby on Railsで書かれており、リニューアル後も
    流用する
    Ruby on Rails

    View full-size slide

  46. ● 仮想DOMを活用したリアクティブなjsライブラリ
    ● 学習しやすい(チームメンバーからの評価)
    ● リッチなUIニーズに対応しやすい
    Vue.js

    View full-size slide

  47. ● Vue.jsのフレームワーク
    ● フォームなどのパーツが大量に用意されている
    ● 管理画面に導入
    Element

    View full-size slide

  48. ● サーバーサイドKotlinは自分のチームでは正解
    ○Kotlinの特徴はチームにフィット
    ○Kotlin x Spring Bootは問題なく動く
    ○Kotlin自体の学習コストは問題にならなかった
    ● Kotlinかわいい(^ω^)ペロペロ
    技術選定の所感

    View full-size slide

  49. 4. Kotlin APIサーバーの作り方

    View full-size slide

  50. githubにあげてます
    サンプルプロジェクト
    https://github.com/maeharin/kotlin-dvd-rental-dev

    View full-size slide

  51. postgresql
    ElasticSearch
    customer-front
    admin-front
    api
    APIクライアントgem
    swagger-codegenで自動生

    サンプルプロジェクトの構成
    Kotlin: 1.1.60
    Spring Boot: 1.5.8
    spring-security-oauth2: 2.2.0
    doma: 2.18.0
    rails: 5.1.4
    vue: 2.5.3
    element-ui: 2.0.4
    typescript: 2.6.1
    rails: 5.1.4

    View full-size slide

  52. DBスキーマ
    http://www.postgresqltutorial.com/postgresql-sample-database/

    View full-size slide

  53. ● hello worldはたった3ステップ
    1) SPRING INITIALIZRからDLしたzipを解凍
    2) KotlinでRestControllerを作成
    3) 起動
    hello world

    View full-size slide

  54. Kotlinを選ぶ
    https://start.spring.io
    hello world
    1) SPRING INITIALIZRからDLしたzipを解凍

    View full-size slide

  55. package com.example.demo.controller
    import org.springframework.web.bind.annotation.*
    @RestController
    class HelloController {
    @GetMapping
    fun index():String = "hello!"
    }
    Kotlinで書く
    hello world
    2) KotlinでRestControllerを作成

    View full-size slide

  56. $ ./gradlew bootRun
    hello world
    3) 起動

    View full-size slide

  57. hello world
    以上!

    View full-size slide

  58. Springの各種機能

    View full-size slide

  59. @RestController
    @RequestMapping("/api/v1/films")
    class FilmRestController(
    private val filmRepository: FilmRepository
    ) {
    @GetMapping
    fun index(): List = ...
    @PostMapping
    fun create(
    @RequestBody @Validated filmParam: FilmParam
    Springのアノテーション
    ● 問題なく使える

    View full-size slide

  60. @Configuration
    @EnableAuthorizationServer
    class Oauth2AuthorizationServerConfig(
    private val authManager: AuthenticationManager,
    private val dataSource: DataSource
    ) : AuthorizationServerConfigurerAdapter() {
    @Bean
    fun passwordEncoder(): BCryptPasswordEncoder
    = BCryptPasswordEncoder()
    spring-security-oauth2
    ● 問題なく使える

    View full-size slide

  61. SpringFox
    ● 問題なく使える

    View full-size slide

  62. @RestController
    @RequestMapping("/api/v1/films")
    open class FilmRestController(
    都度openするの大変。。。
    kotlin-springプラグイン
    ● Kotlinのクラスはデフォルトでfinal
    ● 普通ならopenが必要だが...

    View full-size slide

  63. classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
    classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}")
    apply plugin: 'kotlin'
    apply plugin: 'kotlin-spring'
    compileKotlin {
    kotlinOptions.jvmTarget = "1.8"
    }
    compileTestKotlin {
    kotlinOptions.jvmTarget = "1.8"
    }
    ※Spring Initializr経由で作成す
    るとデフォルトで入る
    ↑Spring Initializr経由で作成したbuild.gradle(抜粋)
    kotlin-springプラグイン
    ● kotlin-springプラグインでopen不要に

    View full-size slide

  64. jackson-module-kotlin
    ● Kotlinでのjsonの扱いをしやすくする

    View full-size slide

  65. data class FilmResource(
    var name: String = "",
    var isAdmin: Boolean = false,
    var companyId: Int = 0
    )
    Jacksonは
    デフォルト値ありの
    コンストラクタを要

    デフォルト値は使い
    たくないのに。。
    jackson-module-kotlin
    ● APIリクエスト(JSON)をKotlinへマッピング

    View full-size slide

  66. data class FilmResource(
    val name: String,
    val isAdmin: Boolean,
    val companyId: Int
    )
    jackson-module-kotlin
    ● こうしたい

    View full-size slide

  67. compile "com.fasterxml.jackson.module:jackson-module-kotlin:2.9.0"
    ※Spring4.3より依存ライブラリに入れれば自動的に registerされるようになった
    https://spring.io/blog/2016/02/15/developing-spring-boot-applications-with-kotlin#jackson-kotlin-module
    jackson-module-kotlin
    ● jackson-module-kotlinを入れるだけ

    View full-size slide

  68. ● JavaのDBアクセスフレームワーク
    ● 2Way-SQL(SQLを外出しできる)
    https://qiita.com/nakamura-to/items/099cf72f5465d0323521
    Doma 2

    View full-size slide

  69. ● Spring BootでDoma 2を使うためのstarterあり
    ● doma-spring-boot-starter
    Doma 2

    View full-size slide

  70. http://doma.readthedocs.io/ja/stable/kotlin-support/
    Doma 2
    ● Doma 2はKotlin 1.1.2を実験的にサポート

    View full-size slide

  71. http://doma.readthedocs.io/ja/stable/kotlin-support/
    Doma 2
    ● EntityをKotlinで書ける

    View full-size slide

  72. http://doma.readthedocs.io/ja/stable/kotlin-support/
    Doma 2
    ● とはいえ、バージョンアップ時にハマるリスクを少なく
    したい
    ● Domaの層は全てJavaで書く。という選択肢

    View full-size slide

  73. ● 私達の選択・・・DomaはJava。それ以外はKotlin
    ○よく触るのはDomaの層ではなく、それを「使う層」
    ○「使う層」を全てKotlinにすれば、ほとんどKotlin
    ○Domaのコード(Java)はdoma-genで自動生成も可能
    ■生成されるコードをconfigでカスタマイズ可能
    ■さらに細かく制御したければ、テンプレートのカスタマイズも可能
    Doma 2

    View full-size slide

  74. @Entity(naming = NamingType.SNAKE_LOWER_CASE)
    @Table(name = "film")
    public class FilmEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @SequenceGenerator(sequence = "film_film_id_seq")
    public Integer filmId;
    public String title;
    public String description;
    SQL実行結果のマッピ
    ングと捉え、ロジックを
    書かないようにした
    Doma 2
    ● Doma 2のEntity(Java)

    View full-size slide

  75. @ConfigAutowireable
    @Dao
    public interface FilmEntityDao {
    @Select
    FilmEntity selectById(Integer filmId);
    @Select
    List selectAll();
    @Insert
    int insert(FilmEntity entity);
    Doma 2
    ● Doma 2のDao(Java)

    View full-size slide

  76. レイヤー構造
    application domain infrastructure
    RestController
    ApplicationService Model, ValueObject
    Repository(interface) Repository(impl)
    Doma(Dao, Entity)
    doma-genでDBスキーマから
    自動生成も可能
    Kotlin
    Java
    Doma 2
    よく触る部分は
    全部Kotlin!

    View full-size slide

  77. swagger-codegen

    View full-size slide

  78. postgres
    ElasticSearch
    customer-front
    admin-front
    api
    APIクライアント
    gem
    swagger-codegen
    で自動生成
    swagger-codegen
    ● APIクライアントを手動で作るのは中々しんどい
    ● swagger-codegenで自動生成できる

    View full-size slide

  79. Spring Boot
    (APIサーバー)
    API定義ファイル(json)
    Swagger UI
    (WEB GUI)
    SpringFoxで
    API定義ファイル生成
    API定義ファイルを利用
    swagger-codegen
    コマンド
    Rubyクライアント
    自動生成
    swagger-codegen
    ● SpringFoxでswagger definition(json)を生成
    ● そのjsonをswagger-codegenに食わせる

    View full-size slide

  80. Rails側コードイメージ

    View full-size slide

  81. ● 詳しくはこちらのスライドをご参照ください
    少しだけハマりどころ(回避可能)がある
    https://speakerdeck.com/juntaki/swagger-codegende-apikuraiantogem-zi-dong-sheng-cheng-number-m3kt

    View full-size slide

  82. ● Kotlin x Spring BootでAPIサーバーは問題なく作れる
    ● kotlin-springプラグインでopen不要
    ● jackson-module-kotlinでjsonの扱いが楽に
    ● 私達はDoma 2の層をJavaにした
    ○→ よく触る部分はKotlin
    ● Kotlinかわいい(^ω^)ペロペロ
    Kotlin APIサーバーの所感

    View full-size slide

  83. 5. 「どこでもKotlin」の紹介

    View full-size slide

  84. エムスリー主催のKotlinのイベント「どこでもKotlin」を開催
    どこでもKotlin
    イベント発足の想い

    View full-size slide

  85. 今年の8月からはじめて、計3回開催
    どこでもKotlin
    フリー素材と化す
    たろうさん...

    View full-size slide

  86. Kotlinに関する様々な話題を取り上げる
    どこでもKotlin
    Deeplerning4jの作者
    Adamさんが突然参

    サーバーサイドKotlin
    Android
    Kotlin/Native
    機械学習
    sendgrid
    拡張関数 Spring Boot
    Ktor
    etc...

    View full-size slide

  87. 第3回目のLT大会では社外の方々がご登壇
    どこでもKotlin
    Retty 石田 憲幸さん
    Kotlinで型安全なSQLを書こう
    サイバーエージェント 木村 正弘さん
    運用中のJavaプロジェクトにKotlinを導入した話
    構造計画研究所 菊田 洋一さん
    Kotlin x SendGridでメール送信してみた
    FiNC Matthew Vernさん
    Android Things me to Sleep

    View full-size slide

  88. 11/22(水)19:30〜
    どこでもKotlin#4 〜秋のLT大会 その弐〜
    @クラウドワークス(恵比寿)
    どこでもKotlin
    connpassにて
    参加受付中!

    View full-size slide

  89. ● Kotlinいいですよ!
    ● リニューアルがきっかけでKotlinerの輪が広がった
    ● 社内の別プロジェクトもサーバーサイドKotlin導入決定!
    まとめ

    View full-size slide

  90. ご清聴
    ありがとうございました
    Have a nice Kotlin!

    View full-size slide