Tĩnh tĩnh là một đầu mối ngữ nghĩa về tình trạng không quốc tịch?


11

Gần đây tôi đã thực hiện tái cấu trúc một dự án có kích thước trung bình trong Java để quay lại và thêm các bài kiểm tra đơn vị. Khi tôi nhận ra một nỗi đau là gì khi chế nhạo những người độc thân và thống kê, cuối cùng tôi đã "hiểu" những gì tôi đã đọc về họ suốt thời gian này. (Tôi là một trong những người cần học hỏi kinh nghiệm. Ồ tốt.)

Vì vậy, bây giờ khi tôi đang sử dụng Spring để tạo các đối tượng và nối chúng xung quanh, tôi sẽ loại bỏ các statictừ khóa trái và phải. (Nếu tôi có khả năng muốn chế giễu nó, thì nó không thực sự tĩnh theo nghĩa tương tự như Math.abs () phải không?) Điều này là, tôi đã có thói quen sử dụng staticđể biểu thị rằng một phương pháp không dựa vào trên bất kỳ trạng thái đối tượng. Ví dụ:

//Before
import com.thirdparty.ThirdPartyLibrary.Thingy;
public class ThirdPartyLibraryWrapper {
    public static Thingy newThingy(InputType input) {
         new Thingy.Builder().withInput(input).alwaysFrobnicate().build();
    }
}

//called as...
ThirdPartyLibraryWrapper.newThingy(input);
//After
public class ThirdPartyFactory {
    public Thingy newThingy(InputType input) {
         new Thingy.Builder().withInput(input).alwaysFrobnicate().build();
    }
}

//called as...
thirdPartyFactoryInstance.newThingy(input);

Vì vậy, đây là nơi mà nó trở nên nhạy cảm. Tôi thích cách cũ bởi vì chữ in hoa đã nói với tôi rằng, giống như Math.sin (x), ThirdPartyL LibraryWrapper.newT Breathy (x) luôn làm điều tương tự theo cách tương tự. Không có trạng thái đối tượng để thay đổi cách đối tượng thực hiện những gì tôi yêu cầu nó làm. Dưới đây là một số câu trả lời có thể tôi đang xem xét.

  • Không ai khác cảm thấy như vậy nên có gì đó không ổn với tôi. Có lẽ tôi chưa thực sự nội tâm hóa cách làm OO! Có thể tôi đang viết bằng Java nhưng suy nghĩ bằng FORTRAN hoặc somesuch. (Điều này sẽ rất ấn tượng vì tôi chưa bao giờ viết FORTRAN.)
  • Có lẽ tôi đang sử dụng tính tĩnh như một loại proxy cho tính bất biến cho mục đích suy luận về mã. Điều đó đang được nói, tôi nên có manh mối gì trong mã của mình cho ai đó đi cùng để duy trì nó để biết những gì trạng thái và những gì không?
  • Có lẽ điều này chỉ nên đến miễn phí nếu tôi chọn ẩn dụ đối tượng tốt? ví dụ thingyWrapperkhông có vẻ như nó có trạng thái độc lập với vỏ bọc Thingymà bản thân nó có thể thay đổi. Tương tự, một thingyFactoryâm thanh giống như nó là bất biến nhưng có thể có các chiến lược khác nhau được lựa chọn trong lúc sáng tạo.

Câu trả lời:


12

Tôi thích cách cũ bởi vì chữ in hoa đã nói với tôi rằng, giống như Math.sin (x), ThirdPartyL LibraryWrapper.newT Breathy (x) luôn làm điều tương tự theo cách tương tự. Không có trạng thái đối tượng để thay đổi cách đối tượng thực hiện những gì tôi yêu cầu nó làm.

Đó là cách đúng đắn để làm điều đó, vâng. Điều đó nói rằng, statickhông có đảm bảo về tính bất biến hoặc sự kiên trì của nhà nước. Rằng bạn sử dụng nó như một gợi ý cho những đảm bảo như vậy có ý nghĩa, nhưng nó không có nghĩa là được đảm bảo.

Hãy xem xét những điều sau đây:

public static class Logger
{
    public static int LogLevel { get; set; }

    public static void Log(string message, int logLevel)
    {
        if (logLevel >= LogLevel)
        {
            // logs the message, but only if it is important enough.
        }
    }
}

Lớp này không chỉ giữ trạng thái, mà hành vi của Logger.Log()phương thức thay đổi khi trạng thái đó được thay đổi. Đây là một bài tập hoàn toàn hợp pháp của một staticmẫu lớp, nhưng nó không có gì đảm bảo về mặt ngữ nghĩa mà bạn đang đề xuất.


Tôi đã đưa cho bạn dấu kiểm vì bạn đưa ra một phản biện hữu ích dựa trên trực giác của tôi, nhưng tôi vẫn muốn biết suy nghĩ của bạn về cách tôi nên trình bày hợp đồng / kỳ vọng đó về việc thiếu trạng thái và thiếu tác dụng phụ thông qua mã hóa quy ước.
leoger

1
Thông thường những kỳ vọng như vậy được bao gồm trong tài liệu cho phương pháp; điều tương tự cũng đúng với sự an toàn của luồng.
Robert Harvey

5

Theo ý kiến ​​của tôi, những gì bạn đang nói - tất cả các hàm tĩnh là nullipotent - là cách viết mã OO tốt trong hầu hết các trường hợp nhưng tôi không tin rằng khi bạn nhìn vào một hàm tĩnh, bạn nên tự động cho rằng nó không có tác dụng phụ . Tình hình có thể phức tạp hơn; lấy ví dụ hàm Class.forName(String)có vẻ như không trạng thái nhưng nó thực sự tải một lớp vào bộ nhớ và cuối cùng khởi tạo các trường tĩnh / chạy trình khởi tạo tĩnh; đây là một ví dụ về chức năng idempotent (các cuộc gọi cuối cùng sau lần đầu tiên không tạo ra sự khác biệt) nhưng nó không phải là một chức năng thuần túy (không thể nói rằng nó không có tác dụng phụ). Đây cũng là một lựa chọn tốt, nhưng có thể có trường hợp ba lệnh gọi riêng biệt cho cùng một hàm mang lại ba kết quả khác nhau; ví dụ nếu bạn gọiThread.currentThread() trong một ứng dụng đa luồng, không có gì đảm bảo bạn sẽ nhận được cùng một luồng mỗi lần.

Điều đó đang được nói, tôi nên có manh mối gì trong mã của mình cho ai đó đi cùng để duy trì nó để biết những gì trạng thái và những gì không?

Một giải pháp thích hợp là viết tài liệu (ví dụ Javadoc); Ngoài ra, từ tên của hàm và từ những gì nó làm đôi khi có thể suy ra rằng hàm tĩnh là một hàm thuần túy. Ví dụ, không có lý do để ai đó tin rằng Assert.assertTrue(boolean)từ JUnit sẽ thay đổi một số trạng thái ở đâu đó. Mặt khác, khi một chức năng như System.clearProperty(String)được gọi, khá rõ ràng là sẽ có tác dụng phụ.


Sự khác biệt giữa "nullipotent" và "statless" là gì?
Pacerier 10/03/2015

@Pacerier Không nên có sự khác biệt.
m3th0dman

4

Điều đó đang được nói, tôi nên có manh mối gì trong mã của mình cho ai đó đi cùng để duy trì nó để biết những gì trạng thái và những gì không?

Bạn có thể làm cho chúng tĩnh. FxCop trong thế giới C # sẽ thúc đẩy bạn biến mọi thứ thành tĩnh mà không có biến thành viên tham chiếu. Đây là điều chính xác để làm (thường).

Khi tôi nhận ra một nỗi đau là gì khi chế nhạo những người độc thân và thống kê, cuối cùng tôi đã "hiểu" những gì tôi đã đọc về họ suốt thời gian này.

Di chuyển tất cả chúng đến các trường hợp có lẽ không phải là phương pháp đúng đắn. Thay vào đó, tách rời các phụ thuộc vào các phương thức tĩnh từ các lớp sử dụng chúng. Bạn có thể kiểm tra các phương thức tĩnh một cách cô lập, và sau đó thay thế sự phụ thuộc ở người tiêu dùng khi chúng cần được kiểm tra.


Bạn có thể vẽ cho tôi một ví dụ về "tách rời các phụ thuộc vào các phương thức tĩnh" không? Tôi không rõ bạn đang kích hoạt cái gì. Tôi đã ẩn các chi tiết thực hiện trong một phương thức tĩnh. Vào cuối ngày, lớp sử dụng nó cần phải đạt được chức năng đó. Bạn có nói rằng tôi nên tạo một đối tượng có các hàm bao mỏng cho tất cả các phương thức tĩnh không?
leoger

1
@leoger - lớp sử dụng phương thức tĩnh không cần phải tiếp cận chức năng nếu bạn đang kiểm tra lớp đó, nếu không bạn sẽ không chế nhạo phương thức tĩnh.
Telastyn
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.