Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Java→Kotlinの移行率を算出するコマンドラインツールをKotlinで実装してみた話...
Search
yu mitsuhori
December 20, 2018
Technology
370
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Java→Kotlinの移行率を算出するコマンドラインツールをKotlinで実装してみた話.pdf
- コマンドラインツールをKotlinで実装してみた話です
- 2018.12.20 Kotlin愛好会で発表したスライドです
yu mitsuhori
December 20, 2018
More Decks by yu mitsuhori
See All by yu mitsuhori
【DroidKaigi版】ReactNativeとKotlinで叶える夢のリアルタイム音声配信
youmitsu
1
3.3k
ReactNativeとKotlinで叶える夢のリアルタイム音声配信
youmitsu
1
930
stand.fm(Android)におけるreact-native-track-playerの改善
youmitsu
1
2.3k
TargetSdkVersion29で BottomNavigationが点滅する件
youmitsu
1
1.7k
リリース前のリグレッションテストをUIテストで自動化、1年間運用した話
youmitsu
2
440
New features in RemoteConfig, Analytics at Google I/O 2019
youmitsu
1
780
FirebaseNotification,RemoteConfigでユーザセグメントごとにプッシュ通知を実装する
youmitsu
8
1.6k
Report from Google I/O 2019
youmitsu
1
120
OSSにコントリビュートした話
youmitsu
1
120
Other Decks in Technology
See All in Technology
HHKBエバンジェリストになる方法
941
0
110
Reactの設計論
uhyo
24
13k
Claude Code本って、 読む必要あるの?
oikon48
2
470
今話題のAI「Jev」って何? 宇宙最速で学ぶ会
minorun365
PRO
26
15k
ADKで始める業務改善 - AIエージェント開発時の考えと設計
harappa80
2
150
Genieを崇めよ
kameitomohiro
0
150
Deployment の 先にある AI Agent 基盤 - kagent vNext、Agent Substrate、Hermes から読み解く Agent Runtime の現在地 / k8s-matsuri-2-ai-agent-platform-amsy810
masayaaoyama
3
620
ユーザー価値を届け続けるためにウォンテッドリーが大切にしている文化
kotaminato
0
160
アプリをもっと"iOSアプリっぽく"する小さな工夫 / Small Touches That Make Your App Feel More Like an iOS App
matsuji
2
930
開発投資の期待値を上げるプロダクトロードマップづくり ~プロダクトエンジニアが越境して事業を伸ばす~
kekekenta
1
190
人間はどの意思決定を手放せるのか
kawasima
14
7.1k
Goodbye ShellScript, Hello File-based App
shunsock
0
110
Featured
See All Featured
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
280
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
540
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
240
Discover your Explorer Soul
emna__ayadi
2
1.3k
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
320
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
480
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.8k
Building a Scalable Design System with Sketch
lauravandoore
464
34k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
Music & Morning Musume
bryan
48
7.4k
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.4k
Embracing the Ebb and Flow
colly
88
5.2k
Transcript
Java→Kotlinの移行率を算出する コマンドラインツールを Kotlinで実装してみた話 Yu Mitsuhori
自己紹介 三堀 裕 Android Developer 女性向けのヘルスケアアプリを担当してます。 Twitter: @1013Youmeee GitHub: https://github.com/youmitsu
Qiita: https://qiita.com/youmeee
Question 皆さんKotlinで何を作りますか?
None
None
None
コマンドラインツールも作れます
Java→Kotlinの移行率を算出する コマンドラインツール を Kotlin で 作ってみました
KotlinReplaceSupporter
作ったもの 計算対象となるファイ ル一覧を出力 Projectルートで、 コマンド叩く 移行率の表示
本日のアジェンダ 1. 経緯 2. デモ 3. 実装方法 a. 環境構築 b.
実装 c. jarの実行 4. まとめ
経緯 ・会社の評価の際にKotlin→Javaのリプレース率を出さなければいけな い時があった ・一つ一つ手で計算するのもあれだし、Kotlinで書けるなら勉強も兼ねて やってみよう!どうせならツール化もしてみよう! (シェルとか書けば一発な気もしますがそこはスルーでお願いしま す。。)
デモ
開発環境 ・Mac Book Pro Sierra 10.12.6 ・IntelliJ IDEA Community 2017.3
・Kotlin 1.2.10
環境準備 1. File > New > Projectを押下 2. 左メニューからGradleを選択後、Kotlinのチェックを入れる 3.
そのまま必要項目を入力してプロジェクトを作成する ↑2の選択画面 3の 作成されるプロジェクト →
おおまかな処理フロー 1. 言語情報を保持するクラスを定義し、初期化する 2. 計算対象に入れたくないファイルをignoreするための Readerクラスを定義し、ロードする 3. ディレクトリの探索 4. 移行率の計算、ログの出力
実装①:言語情報を保持するオブジェクトの作成 /** * 言語の情報を保持するクラス * */ data class Language( val
name: String, //言語名 val extension: String //拡張子 ){ override fun toString() = name }
各言語のファイルリスト、移行元/先情報のクラス /** * 言語のlistを保持するクラス */ class SourceList( val language: Language,
val isReplaceTarget: Boolean, val list: MutableList<File> = mutableListOf()) { fun add(file: File){ list.add(file) } }
Main.kt(SourceListの初期化) val javaList = SourceList(Language("Java", "java"), false) val kotlinList =
SourceList(Language("Kotlin", "kt"), true) SourceListを初期化する 移行元がfalse, 移行先がtrue
実装②:計算対象に入れたくないファイルを無視する ・Androidだと自動生成されたファイル (R, DataBindingのファイルなど)を無視したい時あると思います。 ・.krsignoreというファイル名でProjectルートからの相対パスで記述する ことで、計算対象から外すように実装する
ignoreファイルを読み取るためのReaderクラスの作成 class IgnoreFileReader(ignoreFilePath: String, private val cd: String) { private
var fileReader: FileReader? = null var files: List<File> = mutableListOf() init { try { fileReader = FileReader(ignoreFilePath) } catch(e: FileNotFoundException) { } } fun read() { fileReader?.let { val filesStr = it.readLines() files = filesStr.map { File("$cd/$it") } } } }
Main.kt(ignoreファイル読み込み) val homeDir = System.getProperty("user.home") ?: "" val cd =
File(".").absoluteFile.parent val ignoreFileReader = IgnoreFileReader("$homeDir/.krsignore", cd) ignoreFileReader.read() .krsignoreファイルを参照して、プロジェクトのルートディレクトリ から初期化したFileオブジェクトを渡す
実装③:ディレクトリ探索用のクラス class SearchHandler( private val path: String, private val langList:
Array<SourceList>, private val ignoreDirList: List<File>) { lateinit var result: Result fun execute() { var sizeAll = 0 val rootDir = File(path) rootDir.walkTopDown() .filter { isNotIgnoreFile(it) }.forEach { file -> langList.map { langList -> if(isTargetFile(file, langList.language.extension)){ langList.add(file) println(file) sizeAll++ } } } result = Result(langList, sizeAll) } private fun isTargetFile(file: File, extension: String): Boolean = file.extension == extension /** * 対象外ファイルを無視する */ private fun isNotIgnoreFile(file: File): Boolean = ignoreDirList.none { file.startsWith(it) } }
ファイルを再帰的に探索する File.walkTopDown() Fileクラスに拡張関数として実装されている。 FileTreeWalkというクラスが返却される。これがSequenceイン ターフェースを実装しているためforEachで各Fileオブジェクトを ループで取得できる https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-fil e/walk-top-down.html
Main.kt(探索処理及び結果表示) val handler = SearchHandler(cd, arrayOf(javaList, kotlinList), ignoreFileReader.files) handler.execute() val
logger = ResultLogger(handler.result) logger.log() 画面表示についての説明は割愛します
最終的なmain.kt fun main(args: Array<String>) { val homeDir = System.getProperty("user.home") ?:
"" val cd = File(".").absoluteFile.parent val javaList = SourceList(Language("Java", "java"), false) val kotlinList = SourceList(Language("Kotlin", "kt"), true) val ignoreFileReader = IgnoreFileReader("$homeDir/.krsignore", cd) ignoreFileReader.read() val handler = SearchHandler(cd, arrayOf(javaList, kotlinList), ignoreFileReader.files) handler.execute() val logger = ResultLogger(handler.result) logger.log() }
jarをビルド task packJar(type: Jar) { manifest { attributes 'Main-Class': 'jp.co.youmeee.app.MainKt'
} from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } with jar } $ ./gradlew packJar 1. jarファイル生成のtaskを書いてあげて、 2. gradlew wrapperでタスク実行 3. build/libs配下にjarができる
jarを叩きやすくする ・生成されたjarを実行するには`java -jar krs.jar`みたいな感じで打つのは面 倒。。 ・今回は、homebrewで配布する方法で簡単に叩けるようにしました。(方法は 割愛します) $ ./AndroidStudio/HogeApp> krs
完成! 計算対象となるファイ ル一覧を出力 Projectルートで、 コマンド叩く 移行率の表示
まだKotlinにできるものがありますね、、? せっかくなので、、 build.gradle→build.gradle.kts にしてみました
build.gradle.ktsへの移行 ・GradleのビルドスクリプトをKotlinのDSLで書ける! ・既存のbuild.gradleファイルを消して、新たにbuild.gradle.ktsファイルを作成 ・こちらのマイグレーションガイドが参考になりました。 https://guides.gradle.org/migrating-build-logic-from-groovy-to-kotlin/
build.gradle buildscript { ext.kotlin_version = '1.2.10' repositories { mavenCentral() }
dependencies { classpath "org.jetbrains.kotlin: kotlin-gradle-plugin:$kotlin_version" } } plugins { id 'org.jetbrains.kotlin.jvm' version '1.1.51' id 'com.github.johnrengelman.shadow' version '2.0.1' } apply plugin: 'application' apply plugin: 'java' group 'jp.co.youmeee' version '1.2' sourceCompatibility = 1.8 repositories { mavenCentral() } dependencies { compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" testCompile group: 'junit', name: 'junit', version: '4.12' compile 'org.slf4j:slf4j-api:1.7.25' compile 'org.slf4j:jcl-over-slf4j:1.7.25' compile 'org.slf4j:jul-to-slf4j:1.7.25' compile 'ch.qos.logback:logback-classic:1.2.3' } task packJar(type: Jar) { manifest { attributes 'Main-Class': 'jp.co.youmeee.app.MainKt' } from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } with jar }
build.gradle.kts buildscript { val kotlinVersion = "1.2.10" repositories { mavenCentral()
} dependencies { classpath("org.jetbrains.kotlin:kotlin-gradle-plugin: $kotlinVersion") } } group = "jp.co.youmeee" version = "1.2" plugins { java application `kotlin-dsl` id("org.jetbrains.kotlin.jvm") version "1.1.51" id("com.github.johnrengelman.shadow") version "2.0.1" } java { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } repositories { mavenCentral() } dependencies { val kotlinVersion = "1.2.10" compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion") testCompile(group = "junit", name = "junit", version = "4.12") compile ("org.slf4j:slf4j-api:1.7.25") compile("org.slf4j:jcl-over-slf4j:1.7.25") compile("org.slf4j:jul-to-slf4j:1.7.25") compile("ch.qos.logback:logback-classic:1.2.3") } task("packJar", type = Jar::class) { archiveName = "krs.jar" manifest { attributes["Main-Class"] = "jp.co.youmeee.app.MainKt" } from(configurations.runtime.map({ if (it.isDirectory) it else zipTree(it) })) with(tasks["jar"] as CopySpec) }
全てKotlinで書くことができました!
まとめ、感想 ・Kotlinでもコマンドラインツールは作れる!! ・File系のクラスはAndroid書いてるとあまり触らないし、便利な拡張関数もあって、 勉強になりました。 ・エラーハンドリングとか甘い部分あるので、その辺りfixしていきたい。 ・もう少し汎用的にして、外からオプションで、言語の識別子を与えるようにすれば、 Java→Kotlinのようなこともできる(需要はない) https://github.com/youmitsu/KotlinReplaceSupport er
参考資料 ・Migrating build logic from Groovy to Kotlin https://guides.gradle.org/migrating-build-logic-from-groovy-to-kotlin/ ・JVMベースのコマンドラインツールをHomebrewで配布する
https://int128.hatenablog.com/entry/2015/02/27/220907