Tạo các phương thức không phụ thuộc vào các trường mẫu, tĩnh?


19

Gần đây tôi đã bắt đầu lập trình trong Groovy cho một khung thử nghiệm tích hợp, cho một dự án Java. Tôi sử dụng Intellij IDEA với trình cắm Groovy và tôi ngạc nhiên khi thấy đây là một cảnh báo cho tất cả các phương thức không tĩnh và không phụ thuộc vào bất kỳ trường đối tượng nào. Tuy nhiên, trong Java, đây không phải là một vấn đề (ít nhất là theo quan điểm của IDE).

Có nên chuyển đổi tất cả các phương thức không phụ thuộc vào bất kỳ trường đối tượng nào thành các hàm tĩnh không? Nếu đúng, điều này cụ thể với Groovy hay nó có sẵn cho OOP nói chung? Và tại sao?


Các phương thức này có gọi các phương thức khác không? Hay họ thực sự không có gì để làm với một đối tượng của lớp đó? Bạn có thể đưa ra một ví dụ không?
Ray Toal

Câu trả lời:


26

Lưu ý rằng IDEA cũng có kiểm tra này đối với Java, nó được gọi là Phương thức có thể là 'tĩnh' ,

Kiểm tra này báo cáo bất kỳ phương pháp nào có thể được thực hiện tĩnh. Một phương thức có thể là tĩnh nếu nó không tham chiếu bất kỳ phương thức không tĩnh nào và các trường không tĩnh của lớp và không bị ghi đè trong một lớp con ...

Mặc dù vậy, đối với mã Java, việc kiểm tra này bị tắt theo mặc định (lập trình viên có thể bật nó theo ý của họ). Lý do cho điều này rất có thể là tính hợp lệ / hữu ích của việc kiểm tra như vậy có thể bị thách thức, dựa trên một vài nguồn khá có thẩm quyền.

Để bắt đầu, hướng dẫn Java chính thức khá hạn chế khi các phương thức nên tĩnh:

Một cách sử dụng phổ biến cho các phương thức tĩnh là truy cập các trường tĩnh.

Ở trên, người ta có thể lập luận rằng bật theo kiểm tra được đề cập theo mặc định không tuân thủ việc sử dụng công cụ sửa đổi tĩnh được đề xuất trong Java.

Bên cạnh đó, có một vài nguồn khác đi xa như đề xuất một cách tiếp cận hợp lý về việc sử dụng các ý tưởng ẩn đằng sau sự kiểm tra này hoặc thậm chí không khuyến khích nó.

Xem ví dụ bài viết Thế giới Java - Ông Happy Object dạy các phương thức tĩnh :

Bất kỳ phương thức nào độc lập với trạng thái cá thể là một ứng cử viên để được khai báo là tĩnh.

Lưu ý rằng tôi nói "ứng cử viên được tuyên bố là tĩnh." Ngay cả trong ví dụ trước, không có gì buộc bạn phải khai báo instances()là tĩnh. Khai báo nó dưới dạng tĩnh chỉ giúp gọi điện thuận tiện hơn vì bạn không cần một thể hiện để gọi phương thức. Đôi khi bạn sẽ có các phương thức dường như không dựa vào trạng thái cá thể. Bạn có thể không muốn làm cho các phương thức này tĩnh. Trong thực tế, có lẽ bạn sẽ chỉ muốn khai báo chúng là tĩnh nếu bạn cần truy cập chúng mà không cần một ví dụ.

Hơn nữa, mặc dù bạn có thể khai báo một phương thức như là tĩnh, nhưng bạn có thể không muốn vì các vấn đề kế thừa mà nó xen vào thiết kế của bạn. Hãy xem "Thiết kế hướng đối tượng hiệu quả" để thấy một số vấn đề mà bạn sẽ gặp phải ...

Một bài viết tại blog thử nghiệm của Google thậm chí còn đi xa tới mức tuyên bố Phương thức tĩnh là Cái chết đối với Khả năng kiểm tra :

Hãy làm một bài tập tinh thần. Giả sử ứng dụng của bạn không có gì ngoài các phương thức tĩnh. (Có, mã như thế có thể viết, nó được gọi là lập trình thủ tục.) Bây giờ hãy tưởng tượng biểu đồ cuộc gọi của ứng dụng đó. Nếu bạn cố gắng thực hiện một phương thức lá, bạn sẽ không gặp vấn đề gì khi thiết lập trạng thái của nó và khẳng định tất cả các trường hợp góc. Lý do là một phương pháp lá không thực hiện thêm các cuộc gọi. Khi bạn di chuyển ra xa khỏi lá và càng gần main()phương pháp gốc , sẽ càng khó hơn để thiết lập trạng thái trong bài kiểm tra của bạn và khó hơn để khẳng định mọi thứ. Nhiều thứ sẽ trở nên không thể khẳng định. Các bài kiểm tra của bạn sẽ ngày càng lớn hơn. Một khi bạn đạt đếnmain()phương pháp bạn không còn có bài kiểm tra đơn vị (vì đơn vị của bạn là toàn bộ ứng dụng) bây giờ bạn có bài kiểm tra kịch bản. Hãy tưởng tượng rằng ứng dụng bạn đang cố kiểm tra là một trình xử lý văn bản. Không có nhiều thứ bạn có thể khẳng định từ phương thức chính ...

Đôi khi một phương thức tĩnh là một nhà máy cho các đối tượng khác. Điều này càng làm tăng thêm vấn đề thử nghiệm. Trong các thử nghiệm, chúng tôi dựa vào thực tế là chúng ta có thể nối các vật thể khác nhau thay thế các phụ thuộc quan trọng bằng các giả. Khi một newtoán tử được gọi, chúng ta không thể ghi đè phương thức với một lớp con. Một người gọi của một nhà máy tĩnh như vậy bị ràng buộc vĩnh viễn với các lớp cụ thể mà phương thức nhà máy tĩnh tạo ra. Nói cách khác, thiệt hại của phương thức tĩnh vượt xa chính phương thức tĩnh. Kết nối dây biểu đồ đối tượng và mã xây dựng vào phương thức tĩnh là cực kỳ xấu, vì nối dây biểu đồ đối tượng là cách chúng ta cô lập mọi thứ để thử nghiệm ...


Bạn thấy, được đưa ra ở trên có vẻ tự nhiên rằng kiểm tra được đề cập bị tắt theo mặc định cho Java.

Các nhà phát triển IDE sẽ có một thời gian thực sự khó khăn để giải thích lý do tại sao họ nghĩ rằng nó rất quan trọng để đặt nó theo mặc định, chống lại các khuyến nghị được công nhận rộng rãi và thực tiễn tốt nhất.

Đối với Groovy, mọi thứ hoàn toàn khác. Không có đối số nào được liệt kê ở trên áp dụng, đặc biệt là đối số về khả năng kiểm tra, như được giải thích, ví dụ như trong Mocking Phương thức tĩnh trong bài viết Groovy tại Javalulk:

Nếu lớp Groovy mà bạn đang kiểm tra thực hiện gọi một phương thức tĩnh trên một lớp Groovy khác, thì bạn có thể sử dụng ExpandoMetaClass cho phép bạn tự động thêm các phương thức, hàm tạo, thuộc tính và phương thức tĩnh ...

Sự khác biệt này có thể là lý do tại sao cài đặt mặc định cho kiểm tra được đề cập ngược lại trong Groovy. Mặc dù trong Java mặc định "bật" sẽ là nguồn gây nhầm lẫn cho người dùng, nhưng trong Groovy, một cài đặt ngược lại có thể gây nhầm lẫn cho người dùng IDE.

"Này phương thức không sử dụng các trường mẫu, tại sao bạn không cảnh báo tôi về nó?" Câu hỏi đó sẽ dễ trả lời cho Java (như đã giải thích ở trên), nhưng đối với Groovy, không có lời giải thích thuyết phục nào.


Nhân tiện, ReSharper (do JetBrains sản xuất cho C # / Visual Studio) gợi ý điều tương tự
Konrad Morawski

6
Có một sự khác biệt quan trọng giữa các phương thức tĩnh có và không có tác dụng phụ. Các trích xuất Google thực sự giải quyết trước đây.
assylias

@assylias Nó cũng vậy, nhưng nó cũng thảo luận về cách các phương thức của nhà máy có thể làm cho việc kiểm tra khó khăn hơn (vì nó kết hợp chặt chẽ các phụ thuộc trong ứng dụng). Sử dụng khung tiêm phụ thuộc là một trong những cách giải quyết tốt nhất cho việc này và nó cũng giải quyết được nhiều vấn đề khác.
Per Lundberg

5

Thật khó để tưởng tượng rằng điều này sẽ làm cho bất kỳ hiệu ứng rõ rệt về hiệu suất. Lợi ích duy nhất mà tôi có thể thấy để tạo ra chúng staticlà nó cung cấp một dấu hiệu trực quan rằng trạng thái thể hiện không bị ảnh hưởng. Nói cách khác, nó nói với người đang đọc mã nguồn một cái gì đó ... "thú vị" về phương pháp đó, chỉ nhờ vào nó ở đó. Câu hỏi thực sự là, nó làm rõ hay nhầm lẫn? "Tại sao phương thức này tĩnh? Đây có phải là phương thức xuất xưởng không? Khả năng gọi nó mà không cần một đối tượng cần thiết?"

Ngoài ra, một số người không thích các phương thức tĩnh, vì họ cho rằng bạn không thể chế giễu họ, và do đó họ không thể kiểm tra được, hoặc một cái gì đó dọc theo các dòng đó. Chắc chắn, nếu bạn đang làm cho nó tĩnh vì bất kỳ lý do thông thường nào, chẳng hạn như cung cấp một phương thức xuất xưởng, thì tôi sẽ làm tất cả vì điều đó. Tôi chỉ không chắc chắn rằng làm cho các phương thức tĩnh chỉ vì chúng không chạm vào trạng thái cá thể là một nhiệm vụ.


5
Hãy xem xét rằng (trong Java) một phương thức tĩnh không thể bị ghi đè. Mặc dù không thường xuyên là một vấn đề, điều đó có nghĩa là một số lớp con sau này không thể thay đổi việc thực hiện đó. Điều này không có nghĩa là một phương pháp tĩnh không phải là câu trả lời đúng mà là một phần của các cân nhắc thiết kế.

2
@ user40980 đáng để xem xét, đúng, nhưng cũng đáng xem xét rằng tính kế thừa có thể là một công cụ vụng về thường bị sử dụng sai và một số nhân vật nổi bật cho rằng tất cả các lớp nên được finalthiết kế đặc biệt có tính kế thừa.
sara

3

Tôi nghĩ rằng nó là để cho phép tái cấu trúc có thể được phát hiện .

Một khi phương thức đã được thực hiện tĩnh, rõ ràng là nó có thể được chuyển ra khỏi lớp, nói với một lớp thống nhất.

Nó cũng dễ dàng chuyển đổi nó thành một phương thức thể hiện của một trong các tham số của nó, thường thì đây là nơi mã phải được.


-1

Lưu ý rằng bạn có thể có các lớp không trạng thái thực hiện một số giao diện (ví dụ: java.lang.Runnablebạn không thể làm cho các phương thức của chúng tĩnh. Một số mẫu (ví dụ Chiến lược) cũng có thể tạo ra các đối tượng không trạng thái thậm chí có thể có một số phương thức.

Statics là anh em họ đầu tiên của singletons. Sẽ rất khó để chuyển từ trạng thái sang trạng thái không thống kê vào thời điểm sau - vì vậy khi bạn cần thêm trạng thái, bạn sẽ bị cám dỗ bắt đầu đưa ra các biến tĩnh.


Làm thế nào để trả lời câu hỏi này?
gnat

1
Tại sao khó đi từ tiểu bang này sang tiểu bang khác? Tôi muốn nói đó là cách khác. dễ dàng làm nhiễm bẩn thứ gì đó tinh khiết hơn là làm sạch thứ gì đó bị ô nhiễm.
sara
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.