การย้ายไปใช้ภาษาใหม่ๆ อาจเป็นเรื่องที่น่ากังวล เคล็ดลับสู่ความสำเร็จคือการเริ่มต้นอย่างช้าๆ ย้ายข้อมูลเป็นส่วนๆ และทดสอบบ่อยๆ เพื่อให้ทีมพร้อมรับความสำเร็จ Kotlin ช่วยให้การย้ายข้อมูลเป็นเรื่องง่าย เนื่องจากคอมไพล์เป็น JVM Bytecode และทำงานร่วมกับ Java ได้อย่างสมบูรณ์
การสร้างทีม
ขั้นตอนแรกก่อนย้ายข้อมูลคือการสร้างความเข้าใจพื้นฐานร่วมกันสำหรับทีม เคล็ดลับต่อไปนี้อาจเป็นประโยชน์ในการเร่งการเรียนรู้ของทีม
จัดตั้งกลุ่มศึกษา
กลุ่มศึกษาเป็นวิธีที่มีประสิทธิภาพในการส่งเสริมการเรียนรู้และการจดจำ การศึกษาชี้ให้เห็น ว่าการท่องสิ่งที่ได้เรียนรู้ในสภาพแวดล้อมแบบกลุ่มช่วย เสริมเนื้อหา ซื้อหนังสือ Kotlin หรือสื่อการเรียนรู้อื่นๆ ให้สมาชิกแต่ละคนในกลุ่ม และขอให้กลุ่มอ่านหนังสือ 2-3 บทต่อสัปดาห์ ในแต่ละครั้งที่พบกัน กลุ่มควรเปรียบเทียบสิ่งที่ได้เรียนรู้และพูดคุยเกี่ยวกับคำถามหรือข้อสังเกตต่างๆ
สร้างวัฒนธรรมการสอน
แม้ว่าไม่ใช่ทุกคนจะคิดว่าตัวเองเป็นครู แต่ทุกคนก็สามารถสอนได้ ตั้งแต่หัวหน้าทีมหรือหัวหน้าฝ่ายเทคโนโลยีไปจนถึงผู้ร่วมงานแต่ละคน ทุกคนสามารถส่งเสริมสภาพแวดล้อมการเรียนรู้ที่จะช่วยให้มั่นใจได้ถึงความสำเร็จ วิธีหนึ่งในการดำเนินการนี้คือการจัดงานนำเสนอเป็นระยะๆ โดยกำหนดให้คนในทีม 1 คนพูดถึงสิ่งที่ได้เรียนรู้หรือต้องการแชร์ คุณสามารถใช้ประโยชน์จากกลุ่มศึกษาโดยขออาสาสมัครนำเสนอบทใหม่ทุกสัปดาห์จนกว่าทีมจะรู้สึกสบายใจกับภาษา
กำหนดแชมเปี้ยน
สุดท้าย ให้กำหนดแชมเปี้ยนเพื่อเป็นผู้นำความพยายามในการเรียนรู้ บุคคลนี้สามารถทำหน้าที่เป็น ผู้เชี่ยวชาญเฉพาะเรื่อง (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?)
จากนั้นคุณสามารถทดสอบหน่วยโค้ดนี้กับชุดการทดสอบปัจจุบันได้ แนวคิดในที่นี้คือการเริ่มต้นจากเล็กๆ ด้วยโมเดลทีละรายการ และเปลี่ยนผ่านคลาสที่เป็นสถานะส่วนใหญ่และไม่ใช่ลักษณะการทำงาน อย่าลืมทดสอบบ่อยๆ
ย้ายข้อมูลการทดสอบ
เส้นทางการเริ่มต้นอีกเส้นทางหนึ่งที่ควรพิจารณาคือการแปลงการทดสอบที่มีอยู่และเริ่มเขียนการทดสอบใหม่ใน 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
}
สุดท้าย ให้เพิ่ม Annotation 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 และคลาสอื่นๆ ที่เกี่ยวข้องกับตรรกะทางธุรกิจ
ข้อควรพิจารณา
Kotlin มีรูปแบบเฉพาะของตัวเองที่ช่วยให้กระชับเช่นเดียวกับ Java อย่างไรก็ตาม ในตอนแรกคุณอาจพบว่าโค้ด Kotlin ที่ทีมสร้างขึ้นมีลักษณะคล้ายกับโค้ด Java ที่จะนำมาแทนที่ ซึ่งจะเปลี่ยนแปลงไปเมื่อทีมมีประสบการณ์การใช้ Kotlin มากขึ้น อย่าลืมว่าการเปลี่ยนแปลงทีละน้อยคือกุญแจสู่ความสำเร็จ
ต่อไปนี้คือสิ่งที่คุณทำได้เพื่อให้โค้ด Kotlin มีความสอดคล้องกันมากขึ้นเมื่อฐานของโค้ดเติบโตขึ้น
มาตรฐานการเขียนโค้ดทั่วไป
อย่าลืมกำหนดชุดรูปแบบการเขียนโค้ดมาตรฐานตั้งแต่เนิ่นๆ ในกระบวนการนำไปใช้ คุณสามารถเบี่ยงเบนจากคู่มือแนะนำเกี่ยวกับ Kotlin ของ Android ได้หากเหมาะสม
เครื่องมือวิเคราะห์แบบคงที่
บังคับใช้มาตรฐานการเขียนโค้ดที่กำหนดไว้สำหรับทีมโดยใช้ Android Lint และเครื่องมือวิเคราะห์แบบคงที่อื่นๆ klint ซึ่งเป็น Linter ของ Kotlin จากบุคคลที่สามยังมีกฎเพิ่มเติมสำหรับ Kotlin ด้วย
การรวมอย่างต่อเนื่อง
ตรวจสอบว่าคุณปฏิบัติตามมาตรฐานการเขียนโค้ดทั่วไปและมีการทดสอบโค้ด Kotlin อย่างเพียงพอ การทำให้การทดสอบเป็นส่วนหนึ่งของกระบวนการสร้างอัตโนมัติจะช่วยให้มั่นใจได้ถึงความสอดคล้องและการปฏิบัติตามมาตรฐานเหล่านี้
ความสามารถในการทำงานร่วมกัน
Kotlin ทำงานร่วมกับ Java ได้อย่างราบรื่นในกรณีส่วนใหญ่ แต่โปรดทราบสิ่งต่อไปนี้
ความสามารถในการเว้นว่าง
Kotlin อาศัย Annotation ความสามารถในการเว้นว่างในโค้ดที่คอมไพล์แล้วเพื่ออนุมานความสามารถในการเว้นว่างในฝั่ง Kotlin หากไม่มี Annotation 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 มีการรองรับในตัวเพื่อใช้ลักษณะการทำงานผ่าน การมอบสิทธิ์ เพื่อช่วยลดความซับซ้อนของการประกอบ
ลักษณะการทำงานนี้ก่อให้เกิดปัญหาสำหรับเฟรมเวิร์กการจำลอง เช่น Mockito ซึ่งอาศัยการติดตั้งใช้งานอินเทอร์เฟซหรือการสืบทอดเพื่อลบล้างลักษณะการทำงานระหว่างการทดสอบ สำหรับการทดสอบหน่วย คุณสามารถเปิดใช้ฟีเจอร์ Mock Maker Inline ของ Mockito ซึ่งช่วยให้คุณจำลองคลาสและเมธอดสุดท้ายได้ หรือคุณจะใช้ ปลั๊กอินคอมไพเลอร์ All-Open เพื่อเปิดคลาส Kotlin และสมาชิกที่ต้องการทดสอบเป็นส่วนหนึ่งของ กระบวนการคอมไพล์ก็ได้ ข้อดีหลักของการใช้ปลั๊กอินนี้คือปลั๊กอินทำงานได้กับการทดสอบหน่วยและการทดสอบแบบมีเครื่องมือ
ข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้ Kotlin ได้ที่ลิงก์ต่อไปนี้
- แนวทาง Kotlin-First ของ Android
- แหล่งข้อมูลสำหรับการเริ่มต้นใช้งาน Kotlin
- แหล่งข้อมูลสำหรับผู้ใช้ Java ที่เรียนรู้ Kotlin
- เส้นทางการเรียนรู้จาก Java ไปเป็น Kotlin, ซึ่งเป็นชุดแหล่งข้อมูลที่จะช่วยให้นักเขียนโปรแกรม Java เรียนรู้และเขียน Kotlin ได้อย่างคล่องแคล่ว