การย้ายไปใช้ภาษาใหม่เป็นเรื่องที่ท้าทาย หากต้องการเตรียมทีมให้พร้อมรับความสำเร็จ ให้เริ่มอย่างช้าๆ ย้ายข้อมูลทีละส่วนเล็กๆ และทดสอบบ่อยๆ Kotlin จะคอมไพล์เป็น JVM bytecode และทำงานร่วมกับ Java ได้อย่างเต็มรูปแบบ ซึ่งทำให้การย้ายข้อมูลง่ายขึ้น
การสร้างทีม
ขั้นตอนแรกก่อนย้ายข้อมูลคือการสร้างความเข้าใจพื้นฐานร่วมกันสำหรับทีม เคล็ดลับต่อไปนี้อาจเป็นประโยชน์ในการเร่งการเรียนรู้ของทีม
จัดตั้งกลุ่มศึกษา
กลุ่มศึกษาเป็นวิธีที่มีประสิทธิภาพในการอำนวยความสะดวกในการเรียนรู้และการจดจำ การศึกษาชี้ให้เห็น ว่าการท่องสิ่งที่เรียนรู้ในสภาพแวดล้อมแบบกลุ่มช่วย เสริมเนื้อหา ซื้อหนังสือ Kotlin หรือ สื่อการเรียนรู้อื่นๆ ให้สมาชิกแต่ละคนในกลุ่ม และขอให้กลุ่มอ่านหนังสือ 2-3 บทในแต่ละสัปดาห์ ในระหว่างการพบปะกันแต่ละครั้ง กลุ่มควรเปรียบเทียบสิ่งที่ได้เรียนรู้และพูดคุยเกี่ยวกับคำถามหรือข้อสังเกตต่างๆ
สร้างวัฒนธรรมการสอน
แม้ว่าไม่ใช่ทุกคนจะคิดว่าตัวเองเป็นครู แต่ทุกคนก็สอนได้ ตั้งแต่หัวหน้าทีมหรือหัวหน้าฝ่ายเทคโนโลยีไปจนถึงผู้ร่วมงานแต่ละคน ทุกคนสามารถส่งเสริมสภาพแวดล้อมการเรียนรู้ที่จะช่วยให้มั่นใจได้ถึงความสำเร็จ วิธีหนึ่งในการอำนวยความสะดวกในเรื่องนี้คือการจัดงานนำเสนอเป็นระยะๆ โดยกำหนดให้บุคคลหนึ่งในทีมพูดถึงสิ่งที่ได้เรียนรู้หรือต้องการแชร์ คุณสามารถใช้ประโยชน์จากกลุ่มศึกษาได้โดยขออาสาสมัครให้นำเสนอบทใหม่ในแต่ละสัปดาห์จนกว่าทีมจะรู้สึกคุ้นเคยกับภาษา
กำหนดแชมเปียน
สุดท้าย ให้กำหนดแชมเปียนเพื่อเป็นผู้นำความพยายามในการเรียนรู้ บุคคลนี้สามารถทำหน้าที่เป็น ผู้เชี่ยวชาญเฉพาะเรื่อง (SME) เมื่อคุณเริ่มกระบวนการนำไปใช้ คุณควรเชิญบุคคลนี้เข้าร่วมการประชุมฝึกซ้อมทั้งหมดที่เกี่ยวข้องกับ Kotlin บุคคลนี้ควรมีความกระตือรือร้นเกี่ยวกับ Kotlin อยู่แล้วและมีความรู้ในการทำงานบ้าง
ผสานรวมอย่างช้าๆ
การเริ่มต้นอย่างช้าๆ และคิดอย่างมีกลยุทธ์เกี่ยวกับส่วนใดของระบบนิเวศที่จะย้ายก่อนเป็นสิ่งสำคัญ โดยส่วนใหญ่มักจะดีที่สุดหากจำกัดการย้ายข้อมูลไว้ที่แอปเดียวภายในองค์กรแทนที่จะเป็นแอปหลัก ในส่วนของการย้ายข้อมูลแอปที่เลือกนั้น แต่ละสถานการณ์จะแตกต่างกัน แต่ต่อไปนี้คือจุดเริ่มต้นทั่วไปบางส่วน
โมเดลข้อมูล
โมเดลข้อมูลของคุณน่าจะประกอบด้วยข้อมูลสถานะจำนวนมากพร้อมกับเมธอด 2-3 รายการ โมเดลข้อมูลอาจมีเมธอดทั่วไป เช่น toString, equals และ hashCode ด้วย โดยปกติแล้วคุณจะย้ายข้อมูลเมธอดเหล่านี้และทดสอบหน่วยแยกกันได้
ตัวอย่างเช่น สมมติว่าคุณมีข้อมูลโค้ด Java ต่อไปนี้
public class Person {
private String firstName;
private String lastName;
// ...
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return Objects.equals(firstName, person.firstName) &&
Objects.equals(lastName, person.lastName);
}
@Override
public int hashCode() {
return Objects.hash(firstName, lastName);
}
@Override
public String toString() {
return "Person{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
'}';
}
}
คุณสามารถแทนที่คลาส Java ด้วย Kotlin บรรทัดเดียวได้ดังที่แสดงในตัวอย่างต่อไปนี้
data class Person(var firstName: String?, var lastName: String?)
จากนั้นคุณสามารถทำ Unit Test โค้ดนี้กับชุดโปรแกรมทดสอบปัจจุบันได้ เริ่มจากโมเดลเดียวในแต่ละครั้ง และย้ายข้อมูลคลาสที่เป็นสถานะส่วนใหญ่แทนที่จะเป็นลักษณะการทำงาน และทดสอบบ่อยๆ
ย้ายข้อมูลการทดสอบ
อีกจุดเริ่มต้นหนึ่งคือการทดสอบ โดยแปลงการทดสอบที่มีอยู่และเขียนการทดสอบใหม่ใน Kotlin วิธีนี้จะช่วยให้ทีมมีเวลาทำความคุ้นเคยกับภาษาก่อนที่คุณจะเขียนโค้ดที่เผยแพร่พร้อมกับแอป
ย้ายข้อมูลเมธอดของยูทิลิตีไปยังฟังก์ชันส่วนขยาย
คุณสามารถแสดงคลาสยูทิลิตีแบบคงที่ เช่น StringUtils,
IntegerUtils, DateUtils หรือ YourCustomTypeUtils เป็น
ฟังก์ชันส่วนขยายของ Kotlin
และใช้ฟังก์ชันเหล่านั้นจากฐานโค้ด Java ที่มีอยู่
ตัวอย่างเช่น สมมติว่าคุณมีคลาส StringUtils ที่มีเมธอด 2-3 รายการดังนี้
package com.java.project;
public class StringUtils {
public static String foo(String receiver) {
return receiver...; // Transform the receiver in some way
}
public static String bar(String receiver) {
return receiver...; // Transform the receiver in some way
}
}
จากนั้นเมธอดเหล่านี้อาจใช้ที่อื่นในแอปดังที่แสดงในตัวอย่างต่อไปนี้
...
String myString = ...
String fooString = StringUtils.foo(myString);
...
การใช้ฟังก์ชันส่วนขยายของ Kotlin จะช่วยให้คุณมีอินเทอร์เฟซ Utils เดียวกันสำหรับผู้เรียกใช้ Java พร้อมทั้งมี API ที่กระชับมากขึ้นสำหรับฐานโค้ด Kotlin ที่กำลังเติบโต
หากต้องการทำเช่นนี้ คุณสามารถเริ่มต้นด้วยการแปลงคลาส Utils นี้เป็น Kotlin โดยใช้การแปลงอัตโนมัติที่ IDE มีให้ เอาต์พุตตัวอย่างอาจมีลักษณะคล้ายกับตัวอย่างต่อไปนี้
package com.java.project
object StringUtils {
fun foo(receiver: String): String {
return receiver...; // Transform the receiver in some way
}
fun bar(receiver: String): String {
return receiver...; // Transform the receiver in some way
}
}
จากนั้นนำคำจำกัดความของคลาสหรือออบเจ็กต์ออก ใส่คำนำหน้าชื่อฟังก์ชันแต่ละรายการด้วยประเภทที่ฟังก์ชันนี้ควรใช้ และใช้คำนำหน้านี้เพื่ออ้างอิงประเภทภายในฟังก์ชันดังที่แสดงในตัวอย่างต่อไปนี้
package com.java.project
fun String.foo(): String {
return this...; // Transform the receiver in some way
}
fun String.bar(): String {
return this...; // Transform the receiver in some way
}
สุดท้าย ให้เพิ่มคำอธิบายประกอบ JvmName ที่ด้านบนของไฟล์ต้นฉบับเพื่อให้ชื่อที่คอมไพล์แล้วเข้ากันได้กับส่วนอื่นๆ ของแอปดังที่แสดงในตัวอย่างต่อไปนี้
@file:JvmName("StringUtils")
package com.java.project
...
เวอร์ชันสุดท้ายควรมีลักษณะคล้ายกับตัวอย่างต่อไปนี้
@file:JvmName("StringUtils")
package com.java.project
fun String.foo(): String {
return this...; // Transform `this` string in some way
}
fun String.bar(): String {
return this...; // Transform `this` string in some way
}
โปรดทราบว่าตอนนี้คุณสามารถเรียกใช้ฟังก์ชันเหล่านี้ได้โดยใช้ Java หรือ Kotlin ด้วยรูปแบบที่ตรงกับแต่ละภาษา
Kotlin
// ... val myString: String = "hello" val fooString = myString.foo() // ...
Java
... String myString = ... String fooString = StringUtils.foo(myString); ...
ย้ายข้อมูลให้เสร็จสิ้น
หลังจากที่ทีมคุ้นเคยกับ Kotlin แล้วและคุณได้ย้ายข้อมูลส่วนเล็กๆ แล้ว คุณสามารถย้ายไปใช้คอมโพเนนต์ขนาดใหญ่ขึ้น เช่น Fragment, Activity, ออบเจ็กต์ ViewModel และคลาสอื่นๆ ที่เกี่ยวข้องกับตรรกะทางธุรกิจ
ข้อควรพิจารณา
เช่นเดียวกับที่ Java มีสไตล์เฉพาะ Kotlin ก็มีสไตล์เฉพาะของตัวเองซึ่งช่วยให้ภาษาดูกระชับ อย่างไรก็ตาม ในตอนแรกคุณอาจพบว่าโค้ด Kotlin ที่ทีมเขียนมีลักษณะคล้ายกับโค้ด Java ที่กำลังจะแทนที่ ซึ่งจะเปลี่ยนแปลงไปเมื่อทีมได้รับประสบการณ์การใช้งาน Kotlin มากขึ้น การเปลี่ยนแปลงแบบค่อยเป็นค่อยไปคือกุญแจสู่ความสำเร็จ
ต่อไปนี้คือสิ่งที่คุณทำได้เพื่อรักษาความสอดคล้องของฐานโค้ด Kotlin เมื่อฐานโค้ดเติบโตขึ้น
มาตรฐานการเขียนโค้ดทั่วไป
กำหนดชุดมาตรฐานการเขียนโค้ดตั้งแต่เนิ่นๆ ในกระบวนการนำไปใช้ คุณสามารถเบี่ยงเบนจากคู่มือสไตล์ Kotlin ของ Android ได้หากสมเหตุสมผล
เครื่องมือวิเคราะห์แบบคงที่
บังคับใช้ชุดมาตรฐานการเขียนโค้ดที่กำหนดไว้สำหรับทีมโดยใช้ Android Lint และเครื่องมือวิเคราะห์แบบคงที่อื่นๆ ktlint ซึ่งเป็น Linter ของ Kotlin จากบุคคลที่สาม ยังมีกฎเพิ่มเติมสำหรับ Kotlin ด้วย
การรวมอย่างต่อเนื่อง
ตรวจสอบว่าคุณปฏิบัติตามมาตรฐานการเขียนโค้ดทั่วไปและมีการทดสอบโค้ด Kotlin อย่างครอบคลุม การทำให้การทดสอบเป็นส่วนหนึ่งของกระบวนการสร้างอัตโนมัติจะช่วยให้มั่นใจได้ถึงความสอดคล้องและการปฏิบัติตามมาตรฐานเหล่านี้
ความสามารถในการทำงานร่วมกัน
Kotlin ทำงานร่วมกับ Java ได้อย่างราบรื่นในกรณีส่วนใหญ่ แต่โปรดคำนึงถึงประเด็นต่อไปนี้
ความสามารถในการเว้นว่าง
Kotlin อาศัยคำอธิบายประกอบความสามารถในการเว้นว่างในโค้ดที่คอมไพล์แล้วเพื่ออนุมานความสามารถในการเว้นว่างในฝั่ง Kotlin หากไม่มีคำอธิบายประกอบ Kotlin จะใช้ประเภทแพลตฟอร์มเริ่มต้นที่ถือได้ว่าเป็นประเภทที่เว้นว่างได้หรือไม่เว้นว่างก็ได้ หากคุณไม่จัดการประเภทแพลตฟอร์มอย่างระมัดระวัง อาจทำให้เกิดปัญหา NullPointerException ขณะรันไทม์
นำฟีเจอร์ใหม่ไปใช้
Kotlin มีไลบรารีใหม่ๆ และไวยากรณ์ที่กระชับมากมายเพื่อลดโค้ดซ้ำ ซึ่งช่วยเพิ่มความเร็วในการพัฒนา อย่างไรก็ตาม โปรดระมัดระวังและเป็นระบบเมื่อใช้ฟังก์ชันไลบรารีมาตรฐานของ Kotlin เช่น ฟังก์ชันคอลเล็กชัน, Coroutine และ Lambda
ต่อไปนี้คือข้อผิดพลาดทั่วไปที่นักพัฒนาแอปที่เพิ่งเริ่มใช้ Kotlin มักพบ ลองพิจารณาโค้ด Kotlin ต่อไปนี้
val nullableFoo: Foo? = Foo() // This lambda executes only if nullableFoo is not null // and `foo` is of the non-nullable Foo type nullableFoo?.let { foo -> foo.baz() foo.zap() }
ความตั้งใจในตัวอย่างนี้คือการเรียกใช้ foo.baz และ foo.zap หาก nullableFoo ไม่เป็น Null เพื่อหลีกเลี่ยง NullPointerException แม้ว่าโค้ดนี้จะทำงานได้ตามที่คาดไว้ แต่ก็อ่านได้ยากกว่าการตรวจสอบ Null และ
การแคสต์อัจฉริยะดังที่แสดงในตัวอย่างต่อไปนี้
val nullableFoo: Foo? = null if (nullableFoo != null) { nullableFoo.baz() // Using !! or ?. isn't required; the Kotlin compiler infers non-nullability nullableFoo.zap() // from guard condition; smart casts nullableFoo to Foo inside this block }
การทดสอบ
ใน Kotlin คลาสและฟังก์ชันของคลาสจะปิดไม่ให้มีการขยายโดยค่าเริ่มต้น คุณต้องเปิดคลาสและฟังก์ชันที่ต้องการสร้างคลาสย่อยอย่างชัดเจน Kotlin เลือกใช้การออกแบบนี้เพื่อส่งเสริมการประกอบมากกว่าการสืบทอด Kotlin มีการรองรับในตัวสำหรับการติดตั้งใช้งานลักษณะการทำงาน ผ่าน การมอบสิทธิ์เพื่อช่วย ลดความซับซ้อนของการประกอบ
ลักษณะการทำงานนี้ก่อให้เกิดปัญหาสำหรับเฟรมเวิร์กการจำลอง เช่น Mockito ซึ่งอาศัยการติดตั้งใช้งานอินเทอร์เฟซหรือการสืบทอดเพื่อลบล้างลักษณะการทำงานระหว่างการทดสอบ สำหรับการทำ Unit Test คุณสามารถเปิดใช้ฟีเจอร์ Mock Maker Inline ของ Mockito ซึ่งช่วยให้คุณจำลองคลาสและเมธอดสุดท้ายได้ หรือคุณจะใช้ ปลั๊กอินคอมไพเลอร์ All-Open เพื่อเปิดคลาส Kotlin และสมาชิกของคลาสที่ต้องการทดสอบเป็นส่วนหนึ่งของ กระบวนการคอมไพล์ก็ได้ ข้อได้เปรียบหลักของการใช้ปลั๊กอินนี้คือปลั๊กอินทำงานได้กับการทดสอบหน่วยและการทดสอบการวัดคุม
ข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้ Kotlin ได้ที่ลิงก์ต่อไปนี้
- แนวทาง Kotlin เป็นหลักของ Android
- แหล่งข้อมูลสำหรับการเริ่มต้นใช้งาน Kotlin
- แหล่งข้อมูลสำหรับผู้ใช้ Java ที่เรียนรู้ Kotlin
- เส้นทางการเรียนรู้จาก Java ไปเป็น Kotlin, ซึ่งเป็นชุดแหล่งข้อมูลที่จะช่วยให้นักเขียนโปรแกรม Java เรียนรู้และเขียน Kotlin ได้อย่างคล่องแคล่ว