From an architect's perspective, should Kotlin be used for server-side development?

foreword

Since Oracle bought Sun, attempts to charge for or tighten control over Java have continued, and Google's battle with Oracle over the Java API has been ups and downs. Although Oracle only charges for the upgrade of Oracle JDK8, and released the goodwill of OpenJDK, which has always been open source, but without the JVM, JDK and many other JVM-based languages ​​of various major non-Oracle, it is hard to say how long the goodwill of Oracle can be maintained. .

Big factories should make plans at the level of JVM and JDK, while the majority of small and medium-sized enterprises can only first find a spare tire other than Oracle from the level of Java language. Since it was designated as the preferred language for Android development by Google, Kotlin, which adopts the Apache2.0 License, has gradually entered the public's field of vision. From domain languages ​​to general-purpose languages, there are many JVM-based languages ​​to choose from. Kotlin can stand out and be favored by Google. In addition to the friendliness of the license, it naturally has its own unique features (personally, Jython based on Python syntax was considered a strong alliance at that time. Of course, the advantages of Kotlin are obvious now). Let's first feel the characteristics of Kotlin from a paragraph from the Internet:

  • Scala: Want to solve the problem of insufficient expressiveness in Java
  • Groovy: Want to solve the problem of too verbose Java syntax
  • Clojure: wants to solve the problem of Java without functional programming
  • Kotlin: want to solve Java

Of course, team development has more issues to consider than individual development. This article examines whether Kotlin should be used in server-side development projects from the perspective of the R&D team. As for the details of the Kotlin language, please refer to the official Kotlin documentation or search engine for more details. This article will not go into details.

Reasons to choose Kotlin

1. Almost perfect compatibility with Java

As a technical pre-research team, I have used Kotlin to do two real online projects, including CI\CD, Spring Family Bucket, MyBatis, RDBMS, NoSQL, message queue, microservice, RESTful interface, In addition to the project code, Kotlin is also used to implement crawlers, operation and maintenance, and testing tools. Except for the BenchMark performance test, which needs to be compiled slightly more complicated than java because OpenJDK:jmh directly manipulates bytecode, all events can be done by people (Java) without me (Kotlin), and people (Java) with me (Kotlin) Strong, can complete the development and testing of a set of AI SaaS services from scratch with high quality in about ten days.

My own practice can show that Kotlin's use of Java's open source components, class libraries, and tool stacks is almost the same as the Java code itself (except for a slight difference in jmh), which is an incomparable advantage of other JVM-based languages.

2. Easier to write reliable code

2.1 Mandatory non-null check

// 所有变量默认不能为空
var a: String = "abc"
a = null //编译错误
// 如果想要允许变量为空,变量声明中的类型以"?"结尾
var b: String? = null
// 非空类型的变量,可以直接调用对象方法
println(a.length)
 // 可空类型的变量,可以用"?."替换"."来进行完全调用
println(b?.length) //如果b为null,则b?.length返回null,而不会抛出NPE
// "?."链式调用更显安全调用的威力
bob?.department?.head?.name //只要有一环为null,则整个表达式返回null
// 空类型不能直接赋值给非空类型
a = b //编译错误
// 可以使用非空断言"!!"来强制将b转换为其对应的非空类型
a = b!! //如果b为null,则抛出NPE,否则赋值成功
// 更安全的做法是使用"?:"赋值
a = b?:"Default"
// "?:"还可以接”throw“、"return"、"break"语句来提前结束函数或语句块
a = b?: throw MyException("自定义异常")

It can be seen that Kotlin avoids the most vulnerable NPE problem in Java by forcing the non-null verification mechanism, and it is easy to write null-safe code without adding additional null code. Of course, it also uses non-null assertions. The way of throwing NPE is reserved. For details, please refer to the official Kotlin documentation-null safety

2.2 Read-only variables

// 通过val可以方便声明只读变量,防止变量的误修改,类似于java的final
val a = "Hello"
//...
a = "world" //编译错误
// var用于声明可读写变量
var b = 1 //如果下方没有代码对b进行修改,则编译告警

The syntax for declaring read-only variables is more concise, and with var unmodified compilation warnings, developers are forced to declare variables unambiguously

3. Simple and efficient, the amount of code can be reduced by more than 50%

3.1 Default parameters and data classes

// 默认参数,大多数情况可以代替函数重载
fun a(name: String, age: Int = 0) {
  //...
}

// data关键字会自动为类型增加hashCode(),equals(),copy(),toString()方法
// val关键字会自动生成只读成员变量及get方法
// var关键字会自动生成成员变量及get和set方法
data class Person(val id: Int, var name: String, var age: Int = 0)
//以上就是Person实体的完整声明,它等价于十行以上的java代码

The combination of default parameters, data classes, and primary constructors allows us to save more than 90% of the entity declaration code, and the expression is clearer and more maintainable.

3.2 Type inference

when(val u = request.session.getAttribute("user")){
  is String -> println(u.toUpperCase())
  is Map<*, *> -> println(u["name"])
  !is List<*> -> println(u)
}

After the type judgment code, the variable is automatically converted to the required type, eliminating the need for variable declaration and type conversion code.

In addition, Kotlin has rich set operations, as well as class extensions, more concise lambdas, string templates, operator overloading, destructuring, etc., which almost contain all the excellent features of the current language, saving business code by more than 50%, and Stronger expressive ability.

4. Spring's bonus

Spring-Boot has promoted kotlin to the recommended language after Java, which is enough to show that Spring attaches great importance to Kotlin

4.1 Constructor Injection

Spring constructor injection configures kotlin's main constructor syntax, Spring+Kotlin is a natural fit

@Service
class SMSService(
  @Value("\${sms.appId}") private val appId: String,
  @Value("\${sms.appSecret}") private val appSecurity: String,
  private val webClient: WebClient
) {
  //...
}

4.2 Extensions for Kotlin
There are also some extensions specifically for Kotlin in Spring, such as: SpringApplicationExtension:

@SpringBootApplication
class SpringBootApplicationStarter

fun main(args: Array<String>) {
  //拉起Spring-Boot应用
  runApplication<SpringBootApplicationStarter>(*args)
}

4.3 Example code for Kotlin

The Spring documentation has written sample code specifically for Kotlin, which is a treatment that Groovy, the old language supported by Spring, has not enjoyed for many years:

Kotlin's natural friendliness to Spring, and Spring's emphasis on and addition to Kotlin, it is foreseeable that Kotlin's status in the field of server development will become higher and higher in the future.

Questions to consider when choosing Kotlin

1. IDE & Toolchain

The preferred development tool for Kotlin is IDEA, which belongs to jetbrain company.
Eclipse+Kotlin Plugin is also a good choice
. The development experience of both Kotlin and Java is not inferior to the development experience of Java.
However, there are two problems with Eclipse's Kotlin plug-in:
1) Debug cannot be automatically recognized The main method of Kotlin needs to manually fill in the Class name;

注:此为Eclipse Kotlin Plugin 0.8.15.v20190619-1212引入的Bug,
 0.8.16.v20190703-1421版本已解决,请升级插件并重新导入工程。

2) Debug does not support the allopen option compiled by Kotlin, all Bean and Configuration types must be explicitly declared as open

@SpringBootApplication
open class SpringBootApplicationStarter

@Configuration
open class BeanConfig

@Service
open class TestService

@RestController
open class TestController

In addition to IDE, Kotlin can run perfectly on Maven and Gradle, CI/CD tool Jenkins is no problem, JUnit, Swagger and other Java original toolchains run the same, between bytecode and jar package Whether other tools can run, in theory, does not depend on whether the project code is Kotlin or Java; perhaps the biggest problem is that the original code inspection tools can no longer be used.

2. Coding Specifications

Kotlin loosens many restrictions such as:

  • Can declare global variables and global methods
  • A file can have multiple classes
  • Can be extended to add new methods to existing classes

This brings convenience, as entities of the same domain can be declared in one file:

//WebResponses.kt
open class WebResponse(var errorCode: Int = 0, var errorMsg: String? = null)

open class DataResponse<T>(var data: T?) : WebResponse()

open class MapResponse<K, V>(map: Map<K, V>) : DataResponse<Map<K, V>>(map) {
    constructor(vararg pairs: Pair<K, V>) : this(mutableMapOf(*pairs))
}

Existing class libraries can be easily extended

// StringExtensions.kt
val REGEX_Digits = Regex("\\\d+")
fun String.isDigits(): Boolean {
    return this.matches(REGEX_Digits)
}
// ACLInterceptor
val appId = request.getParameter("appId")
if (!appId.isNullOrBlank() && appId.isDigits()) {
//...
}

But without restrictions, it's hard to guarantee that developers don't do what they want. Therefore, some coding standards should be developed for Kotlin projects (which can be shared with Android projects), such as:

  • Only data entities can be defined in the same file
  • Type extensions should end with an "Extensions" suffix, such as "StringExtensions"
  • Business logic should not appear in global methods and should be organized in a class-by-file manner
  • The extension of business logic should not use the Kotlin type extension mechanism, but should use interfaces, abstract classes, and subclasses

3. People skills

For Java developers, learning Kotlin is not difficult. In my personal experience, if you start directly with a small project, the coding efficiency will significantly exceed Java within a week.

Of course, language tools are not the decisive factor for the success or failure of a project. Those who use tools may wish to let the core members of the project team learn about Kotlin before making a decision.

To get started quickly, it is recommended to start with Koans . If you want to master it more deeply, you still need to read the official Kotlin documentation .

4. Dependency size

Using Kotlin in a Spring project will increase the dependency by about 4.18MB

Before the rise of Spring-Boot, this was indeed a problem for me. Six years ago, a war package was only 3~5MB in size, and it was necessary to deploy multiple services for Tomcat without overflowing the code space, so the war package was further slimmed down. - Put all public jar packages under Tomcat/lib.

Now, the Spring-Boot project starts at 30MB, which makes me no longer consider the problem of server resources, but enjoys the improvement of development efficiency brought by various components and tools.

Of course, this question varies depending on the actual situation of the project, and it needs to be left to you as the architect to make a decision.

5. BenchMark

The specific details are not the discussion goal of this article, and it is not so difficult to perform BenchMark performance tests on Kotlin, but there is not much BenchMark information in Kotlin. Here I attach a concise tutorial:

  • Step 1: Use maven to generate a Kotlin benchmark project
mvn archetype:generate \
          -DinteractiveMode=false \
          -DarchetypeGroupId=org.openjdk.jmh \
          -DarchetypeArtifactId=jmh-kotlin-benchmark-archetype \
          -DgroupId=org.sample \
          -DartifactId=test \
          -Dversion=1.0
  • Step 2: Write Test Code
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
open class MyBenchmark {
	@Benchmark
	fun testMethod1() {
		//...
	}

	@Benchmark
	fun testMethod2() {
		//...
	}
}
  • Step 3: Compile & Run
mvn clean package
java -jar target/benchmarks.jar

For more performance test details, please refer to

Which project types are suitable for using Kotlin

  1. Existing Java projects, not recommended ;
  2. Small or verification projects are highly recommended ;
  3. For micro-service projects, it is recommended to carry out partial pilots first , and gradually improve coding standards and personnel skills;
  4. Large-scale single projects are recommended when there is a strong and stable core team, but are not recommended when personnel are mainly recruited ;
  5. Public components, not recommended , except for Kotlin-specific components.

Epilogue

In any case, language tools are not the decisive factor for the success or failure of a project. The person who uses the tools is the one who might as well let the core members of the project team learn about Kotlin before making a decision.

{{o.name}}
{{m.name}}

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=324083635&siteId=291194637