paint-brush
Cách khắc phục sự cố Kotln khi xử lý các mục tiêu trang web sử dụngtừ tác giả@jesperancinha
106 lượt đọc

Cách khắc phục sự cố Kotln khi xử lý các mục tiêu trang web sử dụng

từ tác giả João Esperancinha10m2024/03/21
Read on Terminal Reader
Read this story w/o Javascript

dài quá đọc không nổi

Tại sao và ở đâu chúng ta nên sử dụng mục tiêu trang web sử dụng trong Kotlin và điều đó khác biệt như thế nào trong Kotlin khi sử dụng các khung như Spring Framework.
featured image - Cách khắc phục sự cố Kotln khi xử lý các mục tiêu trang web sử dụng
João Esperancinha HackerNoon profile picture
0-item
1-item
2-item
3-item


Một trong những điểm mạnh nhất của Kotlin cũng có thể là điểm yếu của nó. Khi chúng ta nói về các lớp dữ liệu ngày nay và theo cách tương tự như các bản ghi java, chúng ta có xu hướng tập trung, ít nhất là nhiều người mà tôi biết, vào việc loại bỏ hoàn toàn mã soạn sẵn. Mã soạn sẵn đã là thứ khiến các nhà phát triển khó chịu từ lâu. Nó không chỉ tồn tại trong Java mà các ngôn ngữ khác cũng có điều đó. Nếu chúng ta nghĩ đến việc tạo các đối tượng truy cập dữ liệu theo bất kỳ cách nào, thì việc chúng ta thực hiện bằng Kotlin, Java hay bất kỳ ngôn ngữ nào khác cũng không thực sự quan trọng.


Chúng tôi thường xuyên lặp lại quy trình tương tự: tạo kho lưu trữ, dịch vụ và bộ điều khiển. Phần lớn những gì chúng tôi làm vẫn chỉ là bản mẫu. Tuy nhiên, mã soạn sẵn có thể là một phần trong quyết định tạo các lớp dữ liệu hoặc bản ghi java, một mô hình quan trọng hơn của công nghệ phần mềm là tâm điểm thực sự của việc tạo ra các loại cấu trúc dữ liệu này.


Tất cả đều tập trung vào tính bất biến hoặc trong mọi trường hợp đều có khả năng xảy ra. Hãy quay ngược thời gian và quay trở lại năm 1995, nơi chúng ta đã bắt đầu tạo ra các cấu trúc dữ liệu trong đó chúng ta sẽ chỉ định những thứ khác nhau. Chúng ta sẽ xác định các trường, getters, setters, thuộc tính, bộ truy cập, thuộc tính và tham số theo cách để có thể truyền các đối số của mình cho các phương thức, hàm hoặc bộ điều khiển. Trong phần này, chúng ta sẽ có một số chương trình thú vị sử dụng các nhân vật của loạt phim giữa thập niên 80: Những cô gái vàng. Đã nói điều này, chúng ta hãy xem một lớp học sẽ trông như thế nào trong khoảng 15 năm:


 public class GoldenGirlsJava { public String goldenGirl1; private final String goldenGirl2; private final String goldenGirl3; private final String goldenGirl4; public GoldenGirlsJava() { this.goldenGirl1 = "Dorothy Zbornak"; this.goldenGirl2 = "Rose Nylund"; this.goldenGirl3 = "Blanche Devereaux"; this.goldenGirl4 = "Sophia Petrillo"; } public GoldenGirlsJava( String goldenGirl1, String goldenGirl2, String goldenGirl3, String goldenGirl4 ) { this.goldenGirl1 = goldenGirl1; this.goldenGirl2 = goldenGirl2; this.goldenGirl3 = goldenGirl3; this.goldenGirl4 = goldenGirl4; } public String getGoldenGirl1() { return goldenGirl1; } public void setGoldenGirl1(String goldenGirl1) { this.goldenGirl1 = goldenGirl1; } public String getGoldenGirl2() { return goldenGirl2; } public String getGoldenGirl3() { return goldenGirl3; } public String getGoldenGirl4() { return goldenGirl4; } @Override public String toString() { return "GoldenGirlsJava{" + "goldenGirl1='" + goldenGirl1 + '\'' + ", goldenGirl2='" + goldenGirl2 + '\'' + ", goldenGirl3='" + goldenGirl3 + '\'' + ", goldenGirl4='" + goldenGirl4 + '\'' + '}'; } }


Đây là một lượng mã khổng lồ chỉ cần nhập vào để tạo ra hai bộ điều khiển. Mặc dù mã băm và bằng không nhất thiết phải bắt buộc trong mọi trường hợp, nhưng chúng tôi hầu như luôn phải cài đặt một hàm tạo không có đối số bên cạnh một hàm tạo tổng quát hơn. Điểm hay của việc tạo tất cả mã soạn sẵn này là chúng tôi biết rất rõ ràng mọi thứ sẽ trông như thế nào sau khi biên dịch thành mã byte.


Tuy nhiên, trong mọi trường hợp, mã soạn sẵn luôn là vấn đề gây tranh cãi đối với nhiều nhà phát triển và vì vậy vào năm 2009, lombok đã xuất hiện và cách mạng hóa cách chúng ta tạo cấu trúc dữ liệu. Nó đưa ra khái niệm sử dụng bộ xử lý chú thích và diễn giải các chú thích cụ thể để mang lại những phẩm chất mà chúng tôi cần cho các lớp của mình và do đó, một lớp được chú thích lombok sẽ trông như thế này:

 @Getter @Setter @AllArgsConstructor @ToString public class GoldenGirlsLombok { public String goldenGirl1; private final String goldenGirl2; private final String goldenGirl3; private final String goldenGirl4; public GoldenGirlsLombok() { this.goldenGirl1 = "Dorothy Zbornak"; this.goldenGirl2 = "Rose Nylund"; this.goldenGirl3 = "Blanche Devereaux"; this.goldenGirl4 = "Sophia Petrillo"; } }


Và trong một thời gian, mọi người rất hài lòng về Lombok! Cuối cùng, gánh nặng của việc phải tạo tất cả mã soạn sẵn đó đã không còn nữa. Nhưng sự đốn hạ đó kéo dài khoảng 7 năm thì có người chơi mới đến và lần này là điều mà ngành phát triển phần mềm không hề mong đợi. Nó được gọi là Kotlin và vào năm 2016, nó đã ra mắt với việc giới thiệu ngay các lớp dữ liệu. Quá trình triển khai các cô gái vàng của chúng ta trong Kotlin giờ đây sẽ như thế này:

 data class GoldenGirls( var goldenGirl1: String = "Dorothy Zbornak", private val goldenGirl2: String = "Rose Nylund", private val goldenGirl3: String = "Blanche Devereaux", private val goldenGirl4: String = "Sophia Petrillo" )


Mặc dù Kotlin dần dần bắt đầu thu hút người hâm mộ, mặt khác, Java nhận ra rằng có thứ gì đó khác đang có mặt trên thị trường và một số phát triển ở khía cạnh đó bắt đầu thu hút được một số động lực như dự án Loom vốn đã được thực hiện nhưng cũng bị bỏ lại trong một thời gian. Đó là lý do tại sao, với việc phát hành Java 14 vào năm 20202, Java đã giới thiệu các bản ghi java và cấu trúc dữ liệu trong Java giờ đây sẽ trông như thế này:

 public record GoldenGirlsRecord( String goldenGirl1, String goldenGirl2, String goldenGirl3, String goldenGirl4 ) { public GoldenGirlsRecord() { this( "Dorothy Zbornak", "Rose Nylund", "Blanche Devereaux", "Sophia Petrillo" ); } }


Và cho đến ngày nay việc đơn giản hóa mã và giảm bớt mã dường như vẫn tiếp tục. Tuy nhiên, với việc giảm bớt mã soạn sẵn, các khái niệm về trường, getters, setters, thuộc tính, bộ truy cập, thuộc tính và tham số trở nên ít trực quan hơn và khó lập bản đồ hơn trong tâm trí chúng ta. Dù chúng ta có thích hay không thì những khái niệm đó vẫn là cách JVM hoạt động và tổ chức mã bằng mã byte. Nhưng việc đơn giản hóa mã thực sự là làm cho mã dễ đọc hơn và trong trường hợp các lớp dữ liệu và bản ghi java, ý tưởng cũng là tạo ra các cấu trúc dữ liệu đó là bất biến hoặc bất biến một phần.


Các bản ghi Java thực sự bất biến theo nghĩa là tất cả các giá trị mà nó chứa hoặc các tham chiếu chứa trong đó đều không thể sửa đổi được. Các lớp dữ liệu Kotlin cũng có thể thực sự bất biến vì những lý do tương tự nhưng chúng không nhất thiết phải cho phép các nhà phát triển tạo ra mã phức tạp và tệ nhất là mã có thể thay đổi. Trong mọi trường hợp, điều này đều ổn cho đến khi chúng ta cần để làm việc với các khung công tác như Spring Framework, vốn phụ thuộc nhiều vào các chú thích. Đây là một ví dụ:

 @Entity @Table(name = "shelf_case") data class Case( @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) val id: Long?, var designation: String?, var weight: Long? ) { constructor() : this(0L, null, null) override fun toString(): String { return super.toString() } }


Ví dụ này hoạt động tốt. Đối với con mắt không nghi ngờ, không có nhiều điều đặc biệt đang diễn ra ở đây. Tính năng này hoạt động trong Kotlin, giống như cách nó hoạt động trong Java. Nhưng bây giờ chúng ta hãy xem một ví dụ tương tự, nhưng lần này có chú thích của Jackson:

 data class AccountNumbersPassiveDto( @NotNull val accountNumberLong: Long?, val accountNumberNullable: Long?, @DecimalMax(value = "10") @DecimalMin(value = "5") val accountNumber: BigDecimal, val accountNumberEven: Int, val accountNumberOdd: Int, @Positive val accountNumberPositive: Int, @Negative val accountNumberNegative: Int, @DecimalMax(value = "5", groups = [LowProfile::class]) @DecimalMax(value = "10", groups = [MiddleProfile::class]) @DecimalMax(value = "15", groups = [HighProfile::class]) @DecimalMax(value = "20") val accountNumberMaxList:Int )


Ví dụ này sẽ thất bại và lý do cho điều đó là trong Kotlin, không có cách nào để cho trình biên dịch biết chính xác nơi chúng ta muốn áp dụng chú thích của mình vào. Trong ví dụ trước với chú thích @Entity , là chú thích duy trì jakarta, các chú thích được áp dụng chính xác cho các trường. Nếu chúng tôi dịch ngược mã đó, chúng tôi sẽ tìm thấy mã này:

 public final class Case { @Id @GeneratedValue( strategy = GenerationType.SEQUENCE ) @Nullable private final Long id; @Nullable private String designation; @Nullable private Long weight;


Nhưng đối với ví dụ sau, là ví dụ xác thực jakarta, chúng tôi thấy điều này:

 public final class AccountNumbersPassiveDto { @Nullable private final Long accountNumberLong; @Nullable private final Long accountNumberNullable; @NotNull private final BigDecimal accountNumber; private final int accountNumberEven; private final int accountNumberOdd;



Điều này có nghĩa là AccountNumbersDto không bị ảnh hưởng bởi những chú thích đó trên các trường của nó. Chúng tôi chỉ may mắn trong ví dụ đầu tiên. Nó thực sự có thể đã thất bại. Để chỉ định nơi chú thích của chúng ta cần đến, Kotlin cung cấp cho chúng ta khả năng sử dụng mục tiêu trang web sử dụng làm tiền tố cho bất kỳ chú thích nào. Yêu cầu tất nhiên là phải đáp ứng được điều kiện. Trong trường hợp này, một cách để khắc phục điều này là thêm @field vào tiền tố tất cả các chú thích như thế này:

 data class AccountNumbersPassiveDto( @field:NotNull val accountNumberLong: Long?, val accountNumberNullable: Long?, @field:DecimalMax(value = "10") @field:DecimalMin(value = "5") val accountNumber: BigDecimal, val accountNumberEven: Int, val accountNumberOdd: Int, @field:Positive val accountNumberPositive: Int, @field:Negative val accountNumberNegative: Int, @field:DecimalMax(value = "5", groups = [LowProfile::class]) @field:DecimalMax(value = "10", groups = [MiddleProfile::class]) @field:DecimalMax(value = "15", groups = [HighProfile::class]) @field:DecimalMax(value = "20") val accountNumberMaxList:Int )


Nếu bây giờ chúng ta cố gắng dịch ngược mã byte kết quả bằng IntelliJ, chúng ta sẽ thấy rằng kết quả là mã này trong Java:

 public final class AccountNumbersPassiveDto { @NotNull @Nullable private final Long accountNumberLong; @Nullable private final Long accountNumberNullable; @DecimalMax("10") @DecimalMin("5") @org.jetbrains.annotations.NotNull


Điều này có nghĩa là các chú thích đã được áp dụng cho trường và mã của chúng tôi hoạt động như mong đợi.


Đến đây bạn có thể tưởng tượng rằng những người đã làm việc trên Java lâu năm sẽ không gặp vấn đề gì trong việc thích nghi với Kotlin vì tất cả chúng ta đều biết trường, tham số, thuộc tính, v.v. là gì. Những gì chúng ta quan sát ngày hôm nay và tôi cũng chứng kiến điều đó, đó là có vẻ như việc đơn giản hóa mã có khả năng gây tác dụng ngược. Đã có khá nhiều trường hợp tôi nhận thấy mình đã dành thời gian cho các dự án để cố gắng tìm hiểu xem tại sao trong một số dự án hoặc mô-đun, các chú thích dường như không hoạt động. Và tất cả dường như bắt nguồn từ việc không tận dụng được các mục tiêu của địa điểm sử dụng.


Lý thuyết của tôi về điều rất có thể là các thế hệ nhà phát triển mới có thể sẽ xem những thứ mà thế hệ của tôi không cho là phức tạp và học được theo bản năng, như một tài liệu thực sự phức tạp. Đó là trường hợp với các mục tiêu sử dụng trang web. Đây từng là những thứ mà chúng ta có thể dễ dàng hình dung. Tuy nhiên, trong thời điểm hiện tại, sự nhầm lẫn nảy sinh với điều này dường như đang làm trì hoãn việc phát triển dự án đúng thời hạn trong một số trường hợp. Tất nhiên, tôi không thể khái quát hóa nhưng có tiềm năng tốt và có tiềm năng xấu với các bản ghi java và các lớp dữ liệu. Thật khó để nói trước các lớp dữ liệu và bản ghi sẽ định hình tương lai của chúng ta như thế nào, nhưng có một điều rõ ràng là vì vấn đề này, các khung công tác khác đang đặt cược vào việc hoàn toàn không có chú thích như trường hợp của Ktor.


Tôi đã tạo tài liệu về vấn đề này trên Scribed: Fields-in-Java-and-Kotlin-and-What-to-Expectvà cũng trên slide-share: Fields-in-Java-and-kotlin-and-what-to-expect .


Bạn cũng có thể tìm thấy các ví dụ tôi đã đưa ra trên GitHub. Bạn có thể tìm thấy ví dụ về các cô gái vàng tại đây: jeorg-kotlin-test-drives và các ví dụ về chú thích xác thực và kiên trì jakarta tại đây: https://github.com/jesperancinha/jeorg-spring-master-test-drives .


Cuối cùng tôi cũng đã tạo một video về điều này trên YouTube mà bạn có thể xem ngay tại đây:

Cũng được xuất bảnở đây .