12/08/2018, 15:16

Migrate Gradle Plugin từ Groovy sang Kotlin

Groovy là một ngôn ngữ lập trình hướng đối tượng trên nền Java. Nó là một ngôn ngữ lập trình động với các tính năng tương tự như Python, Ruby, Perl, và Smalltalk. Hơn nữa, nó cũng có thể được sử dụng như là một ngôn ngữ kịch bản chạy trên nền máy ảo Java. Để migrate Gradle Plugin từ Groovy sang ...

Groovy là một ngôn ngữ lập trình hướng đối tượng trên nền Java. Nó là một ngôn ngữ lập trình động với các tính năng tương tự như Python, Ruby, Perl, và Smalltalk. Hơn nữa, nó cũng có thể được sử dụng như là một ngôn ngữ kịch bản chạy trên nền máy ảo Java.

Để migrate Gradle Plugin từ Groovy sang Kotlin, cần làm theo 4 bước sau:

  1. Update file build.gradle
  2. Sửa cấu trúc project
  3. Convert code Groovy sang Kotlin
  4. Migrate JUnit test

build.gradle file

Điều đầu tiên chúng ta cần làm la update file build.grafle của plugin. Chúng ta sẽ remove Groovy dependencies và thêm các method của Kotlin:

buildscript {
    ext.kotlin_version = '1.1.1'

    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

apply plugin: 'kotlin'

dependencies {
    compile gradleApi()
    compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}

Project Structure

Bước tiếp theo là tiến hành update thư mục cấu trúc của project. Ở dây, chúng ta đổi tên thư mục chính, dưới src từ groovy sang kotlin. Sau đó. chúng ta sẽ đổi tên mỗi file extension từ .groovy sang .kt. Nếu bạn đang làm việc với IntelliJ IDEA, việc đổi tên này sẽ thay đổi biểu tượng được hiển thị bên cạnh mỗi tệp.

Groovy sang Kotlin

Với cấu truc folder đã được update, chúng ta cần bắt đầu migrate code từ Groovy sang Kotlin. Hãy bắt đàu với một simple class, Extension class. Đó là một lớp Groovy đơn giản mà tổ chức một vài chuỗi. Các chuỗi này có các giá trị mặc định.

class QualityChecksExtension {
    String pmdConfigFile = 'quality-checks/pmd-ruleset.xml'
    String checkstyleConfigFile = 'quality-checks/checkstyle.xml'
    String findBugsExclusionFile  = 'quality-checks/findbugs-exclude.xml'
}

Và đây là Kotlin version của class:

import info.adavis.qualitychecks.QualityChecksPlugin.Companion.CHECKSTYLE_FILE_NAME
import info.adavis.qualitychecks.QualityChecksPlugin.Companion.FINDBUGS_FILE_NAME
import info.adavis.qualitychecks.QualityChecksPlugin.Companion.PMD_FILE_NAME

open class QualityChecksExtension(var pmdConfigFile: String = "quality-checks/$PMD_FILE_NAME",
                                  var checkstyleConfigFile: String = "quality-checks/$CHECKSTYLE_FILE_NAME",
                                  var findBugsExclusionFile: String = "quality-checks/$FINDBUGS_FILE_NAME")

Điểm khác nhau chính ở đây là cách chúng ta khai báo các trường của Kotlin, sử dụng:

var fieldName: String = "default value"

Chúng ta cũng thêm một số constant vào class QualityChecksPlugin và import chúng ở đây để sử dụng trong các giá trị strings mặc định. Các constant ở trong Companion object. Nó cho phép ta sử dụng ở mọi nơi trong code giống như public static trong Java:

companion object {
    const val PMD_FILE_NAME = "pmd-ruleset.xml"
    const val CHECKSTYLE_FILE_NAME = "checkstyle.xml"
    const val FINDBUGS_FILE_NAME = "findbugs-exclude.xml"
    const val WRITE_PMD_CONFIG_FILE_TASK = "writePmdConfigFile"
    const val WRITE_CHECK_STYLE_CONFIG_FILE_TASK = "writeCheckStyleConfigFile"
    const val WRITE_FIND_BUGS_EXCLUSION_FILE_TASK = "writeFindBugsExclusionFile"
    const val VERIFICATION_GROUP = "verification"
    const val PLUGIN_EXTENSION_NAME = "qualityChecks"
}

Chuyển qua một class phức tạp hơn chút: class CheckstyleTask . Đây là những thứ chúng ta cần thay đổi:

//groovy
class CheckstyleTask extends Checkstyle {
//kotlin
open class CheckstyleTask : Checkstyle() {

Chúng ta bắt đầu bằng cách thay đổi cách class được khai báo. Chúng ta thêm từ khóa open và thay thế extends với : (dấu hai chấm) và tên của class cơ sở với constructor trống của nó. Tiếp theo chúng ta cần thay đổi cách khởi tạo các trường của class Checkstyle. Trước đây chúng ta tạo ra constructor và sau đó khởi tạo tất cả chúng. Kotlin không cho phép bạn có mã trong Constructor chính. Thay vào đó, chúng ta sẽ sử dụng một khối init để đạt được mục tiêu tương tự.

init {
    project.plugins.apply(CheckstylePlugin::class.java)

    description = "Run Checkstyle"
    group = VERIFICATION_GROUP

    configFile = getCheckstyleConfigFile()
    classpath = project.files()
    ignoreFailures = false
    includes.add("**/*.java")
    excludes.add("**/gen/**")
    source.add("src")
}

Bên trong khối init có những thay đổi nhỏ; thay vì áp dụng cách CheckStylePlugin Groovy:

project.plugins.apply CheckstylePlugin

Chúng ta sử dụng Kotlin version và cung cấp kiểu CheckStylePlugin:

project.plugins.apply(CheckstylePlugin::class.java)

Sự khác biệt đáng chú ý tiếp theo là cách chúng ta truy cập vào lớp QualityChecksExtension. Trong Groovy sẽ như sau:

project?.qualityChecks

Nhưng trong Kotlin:

val extension = project?.extensions?.findByType(QualityChecksExtension::class.java)

Rõ ràng qua "Groovy-fu", Gradle đã có thể nhận ra rằng chúng ta muốn phần mở rộng được thêm vào với tên "qualityChecks". Với Kotlin chúng ta phải cụ thể hơn.

JUnit Tests

Tiến hành để kiểm kiểm thử. Kotlin có sẵn Specification Framework riêng được gọi là Spek. Nhưng chúng ta sẽ đi với di chuyển các test JUnit hiện có từ Groovy đến Kotlin. Đây là một ví dụ test:

@Test
    fun `plugin should add tasks when applied`() {
        with(project) {
            pluginManager.apply(QualityChecksPlugin::class.java)

            assertNotNull(tasks.findByName(WRITE_CHECK_STYLE_CONFIG_FILE_TASK))
            assertNotNull(tasks.findByName(WRITE_FIND_BUGS_EXCLUSION_FILE_TASK))
            assertNotNull(tasks.findByName(WRITE_PMD_CONFIG_FILE_TASK))
        }
    }

Một vài điều để chỉ ra. Thứ nhất, không có public void cho các khai báo method chỉ cần fun là cần thiết. Thứ hai, chúng ta có thể có một String cho tên thử nghiệm. Điều này cho phép chúng ta mô tả nhiều hơn và thực sự đánh vần tất cả những gì về mỗi bài test. Thứ ba, chúng ta có thể tận dụng Kotlin với chức năng thực hiện nhiều phương pháp trên cùng một đối tượng. Trong thực tế, có một số idiom có ích khi làm việc với Kotlin. Tôi nhận thấy những lợi ích của việc sử dụng các chức năng apply và úe cũng như trong quá trình migrate.

Nguồn: http://adavis.info/2017/04/migrate-a-gradle-plugin-from-groovy-to-kotlin.html

0