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/

0ff63a1cf64b2501566f37581000bd9b?s=128

Hidenori Maehara

November 18, 2017
Tweet

Transcript

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

    エムスリー株式会社 前原 @maeharin
  2. • 前原 秀徳 • @maeharin(まえはりん) • エムスリー株式会社 • エンジニアチームリーダー、グループ会社取締役等を歴任 •

    好きな言語等:Kotlin、Ruby、Vue.js • 好きな漫画:ベルセルク(心の支え。悩んだら読む) • 自慢:ブログ記事が、はてぶ1200超えた ◦http://maeharin.hatenablog.com/ 自己紹介
  3. ・医療に関するWebサービスを多数展開 ・全世界で約400万人の医師会員 ・日本で約25万人の医師会員 エムスリーって何の会社?

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

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

  6. 1. リニューアルの背景・概要 2. 経営会議承認までの道 3. 技術選定の理由 4. Kotlin APIサーバーの作り方 5.

    イベント「どこでもKotlin」の紹介 アジェンダ
  7. 1. リニューアルの背景・概要

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

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

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

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

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

    かなり簡素化してこれ...(^ω^) 原因1: 複雑なアーキテクチャ
  13. 主要システム Ruby on Rails • ビジネス上優先度の高いシステムはRuby on Rails • 優先度低いシステムは10年前のシステム

    ◦ → だが、この部分の優先度が高まってきた 10年前の Javaシステム 7年前の Javaシステム 原因2: 10年前のシステムが... Javaの独自FW viewの部分はXSLT!
  14. 補足:XSLTとは

  15. 補足:XSLTとは

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

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

  18. リニューアルだ!

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

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

  21. 5月 6月 7月 8月 9月 10月 11月 12月 1月 2月

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

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

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

    説得するか... _(:3」∠)_
  25. 色々悩んだが、経営会議でプレゼンし、承認! \承認/

  26. 1. 最優先イシューを、粘り強く見極めた • 一気に何もかもやろうとすると、終わらない • とはいえ、局所的な改善では意味がない • 周りの人に何度も相談し、イシューを定めていく 踠き 挑み

    足掻く!! それこそが死と対峙する者の唯一の剣!! ゆめゆめ忘れぬことだ!! by ベルセルク
  27. 2. 複数案検討し、可能な限り数値化した • 経営陣を説得する際、数値化は必須と考えた • 複数案考え、各案のコストやメリットを数値化した ◦ 1案だと自分の視野も狭くなるし、経営陣も決められない • 開発効率化だけでなく、エンドユーザーへの提供価値も織り込

    めると話は進みやすい 言葉にすることだけが 気持ちを伝えるすべてではなくてよ ファルネーゼさん by ベルセルク
  28. • 私がRuby on Railsで全部で作った • UIにはVue.jsやmaterial-components-webを使用 • 早期にリスクを発見できることも • 自分への自信

    → 経営陣への説得力 3. プロトタイプで不確実性をコントロールした 言葉は無粋!!押し通れ!! by ベルセルク
  29. 3. 技術選定

  30. • APIサーバー ◦ 重複ロジック・DBを一元化したい ◦ 型を用いてカッチリとやりたい • フロントサーバー ◦ 複数のサービスがある

    1. メインサイト(Rails、1年前にリプレイス済) 2. サテライトサイト(Java、7年もの...) 3. 管理画面:3種類(Java、10年もの...) ◦ 頻繁に改修が入る ◦ リッチなUIへのニーズが強い 技術選定のポイント
  31. postgresql ElasticSearch メインサイト サテライトサイト postgresql 管理画面(3種) 10年もの 7年もの 生Lucene 生Lucene

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

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

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

  35. Kotlinとは Kotlin • 静的型付けオブジェクト指向言語 • いわゆる「JVM言語」 • 開発元:JetBrains • 2016年2月に正式リリース

    ◦ 2017/11/18 現在、ver1.1.60 • Apache License ver2.0 • 特に、Google I/O 2017以降、爆発的な広がり
  36. Google I/O 2017 https://twitter.com/Jayroo5245/status/926120722539282432

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

  38. Kotlin Null安全

  39. Kotlin 型推論

  40. • 背景: • チームのRubyエンジニア7-8名(Javaもたまに触る) • 対象システムの規模感 ◦200テーブル、2000カラム(100テーブルがサブシステム重複) ◦ソースコード行数:数十万行 • フロントはゆるく。コアはカッチリやりたい

    ◦型が欲しいという声がメンバーから噴出したことも ◦通称:型一揆 Kotlin選択理由
  41. • 型:あり(型推論、null safetyも嬉しい) • エムスリーにはたろう (@ngsw_taro) がいる! • フレームワーク:Spring Boot(問題なし)

    • Java製の社内ライブラリは使えるか:使える • IDE:IntelliJ IDEA • 学習コスト:RubyENGは親しみやすい構文(後述) Kotlin選択理由 Kotlin Webアプリケーション 新しいサーバサイドプログラミング 絶賛発売中! エムスリー株式会社 日本Kotlinユーザーグループ代表 長澤 太郎 たろう(@ngsw_taro) • 言語の将来性:きっとある(Google I/O 2017)
  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エンジニアに親しみやすい構文
  43. • SpringはオフィシャルにKotlinサポートを宣言 Spring Boot

  44. Spring Boot

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

    Doma2
  46. Doma2

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

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

  49. Vue.js

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

  51. Element

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

    技術選定の所感
  53. 4. Kotlin APIサーバーの作り方

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

  55. 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
  56. DBスキーマ http://www.postgresqltutorial.com/postgresql-sample-database/

  57. hello world

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

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

  60. 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を作成
  61. $ ./gradlew bootRun hello world 3) 起動

  62. hello world 以上!

  63. Springの各種機能

  64. @RestController @RequestMapping("/api/v1/films") class FilmRestController( private val filmRepository: FilmRepository ) {

    @GetMapping fun index(): List<FilmResource> = ... @PostMapping fun create( @RequestBody @Validated filmParam: FilmParam Springのアノテーション • 問題なく使える
  65. @Configuration @EnableAuthorizationServer class Oauth2AuthorizationServerConfig( private val authManager: AuthenticationManager, private val

    dataSource: DataSource ) : AuthorizationServerConfigurerAdapter() { @Bean fun passwordEncoder(): BCryptPasswordEncoder = BCryptPasswordEncoder() spring-security-oauth2 • 問題なく使える
  66. SpringFox • 問題なく使える

  67. @RestController @RequestMapping("/api/v1/films") open class FilmRestController( 都度openするの大変。。。 kotlin-springプラグイン • Kotlinのクラスはデフォルトでfinal •

    普通ならopenが必要だが...
  68. 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不要に
  69. jackson-module-kotlin • Kotlinでのjsonの扱いをしやすくする

  70. data class FilmResource( var name: String = "", var isAdmin:

    Boolean = false, var companyId: Int = 0 ) Jacksonは デフォルト値ありの コンストラクタを要 求 デフォルト値は使い たくないのに。。 jackson-module-kotlin • APIリクエスト(JSON)をKotlinへマッピング
  71. data class FilmResource( val name: String, val isAdmin: Boolean, val

    companyId: Int ) jackson-module-kotlin • こうしたい
  72. 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を入れるだけ

  73. Doma 2

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

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

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

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

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

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

  80. @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)
  81. @ConfigAutowireable @Dao public interface FilmEntityDao { @Select FilmEntity selectById(Integer filmId);

    @Select List<FilmEntity> selectAll(); @Insert int insert(FilmEntity entity); Doma 2 • Doma 2のDao(Java)
  82. レイヤー構造 application domain infrastructure RestController ApplicationService Model, ValueObject Repository(interface) Repository(impl)

    Doma(Dao, Entity) doma-genでDBスキーマから 自動生成も可能 Kotlin Java Doma 2 よく触る部分は 全部Kotlin!
  83. swagger-codegen

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

    • APIクライアントを手動で作るのは中々しんどい • swagger-codegenで自動生成できる
  85. Spring Boot (APIサーバー) API定義ファイル(json) Swagger UI (WEB GUI) SpringFoxで API定義ファイル生成

    API定義ファイルを利用 swagger-codegen コマンド Rubyクライアント 自動生成 swagger-codegen • SpringFoxでswagger definition(json)を生成 • そのjsonをswagger-codegenに食わせる
  86. Rails側コードイメージ

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

  88. • Kotlin x Spring BootでAPIサーバーは問題なく作れる • kotlin-springプラグインでopen不要 • jackson-module-kotlinでjsonの扱いが楽に •

    私達はDoma 2の層をJavaにした ◦→ よく触る部分はKotlin • Kotlinかわいい(^ω^)ペロペロ Kotlin APIサーバーの所感
  89. 5. 「どこでもKotlin」の紹介

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

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

  92. Kotlinに関する様々な話題を取り上げる どこでもKotlin Deeplerning4jの作者 Adamさんが突然参 加 サーバーサイドKotlin Android Kotlin/Native 機械学習 sendgrid

    拡張関数 Spring Boot Ktor etc...
  93. 第3回目のLT大会では社外の方々がご登壇 どこでもKotlin Retty 石田 憲幸さん Kotlinで型安全なSQLを書こう サイバーエージェント 木村 正弘さん 運用中のJavaプロジェクトにKotlinを導入した話

    構造計画研究所 菊田 洋一さん Kotlin x SendGridでメール送信してみた FiNC Matthew Vernさん Android Things me to Sleep
  94. 11/22(水)19:30〜 どこでもKotlin#4 〜秋のLT大会 その弐〜 @クラウドワークス(恵比寿) どこでもKotlin connpassにて 参加受付中!

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

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