Các mẩu lời khuyên mâu thuẫn mà bạn đã đọc đều có ý nghĩa theo một cách nào đó, nhưng tất cả chúng đều đưa ra các giả định (khác nhau) hoặc các cụm từ mơ hồ. Đó là một trong những kiểu phân biệt "nói cùng một từ với các từ khác nhau".
một phương thức chỉ nên tĩnh nếu nó không sửa đổi trạng thái
Lưu ý sự mơ hồ của "sửa đổi một trạng thái". Ví dụ sau đây vi phạm quy tắc này (theo nghĩa đen), nhưng nó bảo tồn tinh thần (nghĩa bóng) của quy tắc:
public static void SetUserNameToBob(User u)
{
u.Name = "Bob";
}
Điều này sửa đổi trạng thái của User
đối tượng, vì vậy trên thực tế nó "sửa đổi một trạng thái".
Tuy nhiên, phương pháp này không dựa vào một trạng thái nội bộ cụ thể để quyết định luồng logic riêng của nó (ví dụ: u.Name = currentlySelectedDefaultName()
sẽ là vi phạm vì tên được chọn là trạng thái được chọn). Và tôi nghĩ đó là những gì có nghĩa là: không có trạng thái nội bộ được sửa đổi.
[một phương thức chỉ nên tĩnh nếu] kết quả của nó chỉ phụ thuộc vào các tham số được cung cấp cho nó
Nhìn vào mục trước, cái này có khá nhiều điều tương tự. Điều đó có nghĩa là gì:
public static string currentlySelectedDefaultName;
public static void SetUserNameToBob(User u)
{
u.Name = currentlySelectedDefaultName;
}
không nên tĩnh, vì tên "mặc định hiện tại" là trạng thái và do đó, nó không phải là biến / phương thức toàn cục.
Hãy nghĩ về những gì sẽ xảy ra nếu hai luồng riêng biệt đang chạy: một trong số chúng muốn mặc định là "Bob", cái còn lại muốn mặc định là "Jim". Họ sẽ kết thúc cuộc chiến về giá trị, có trách nhiệm tạo ra các vấn đề sửa lỗi lớn và hành vi bất ngờ.
Tuy nhiên, nếu mọi luồng đều có DefaultNameSetter
đối tượng riêng , thì chúng không chiến đấu trên cùng một tài nguyên.
Tuy nhiên, câu trả lời được bình chọn nhiều nhất trong bài đăng này nói rằng các phương pháp tĩnh nên được sử dụng bất cứ khi nào có thể.
Đây là loại thực thi một quy tắc bằng cách thử / thất bại. Chúng ta có thể đặt phương thức này thành tĩnh không?
- Vâng
=>
tốt! Cư giữ như thê đi!
- Không
=>
Điều này chứng tỏ rằng mã đang dựa vào một giá trị không tĩnh ở đâu đó và do đó không nên được tạo thành tĩnh.
Để gián tiếp trích dẫn Jeff Goldblum trong Công viên kỷ Jura , bạn không nên tranh luận về sự cần thiết phải làm một cái gì đó chỉ bằng cách chứng minh rằng nó có thể được thực hiện.
Một lần nữa, cách tiếp cận không nhất thiết (hoặc luôn luôn) sai, nhưng nó giả định một cách mù quáng rằng các phương pháp đã được viết là bất khả tri về mặt logic như có thể, điều này đơn giản không phải là trường hợp.
Ngay cả khi bạn đăng ký theo phương pháp phương pháp này, bạn vẫn chỉ có thể áp dụng nó khi dự án không còn được phát triển. Nếu dự án vẫn đang được phát triển, các phương thức hiện tại có thể là giữ chỗ cho việc thực hiện trong tương lai. Có thể có thể tạo Foo()
tĩnh hôm nay, nhưng không phải ngày mai, nếu logic phụ thuộc vào trạng thái đơn giản chưa được triển khai.
Nhiều câu trả lời trong bài này nói rằng người ta nên làm bất cứ điều gì hợp lý nhất.
Chà, họ không sai; nhưng đây không phải là một cụm từ nhỏ nói "làm điều đúng"? Đó không phải là lời khuyên hữu ích, trừ khi bạn đã biết khi nào nên sử dụng statics và khi nào nên tránh chúng. Đó là một cái bẫy 22.
Vậy khi nào bạn nên sử dụng statics?
Như bạn đã nhận thấy, không phải ai cũng đồng ý với quy tắc này, hoặc ít nhất là về cách diễn đạt quy tắc. Tôi sẽ thêm một nỗ lực khác ở đây, nhưng lưu ý rằng điều này thực sự tạo ra một tiêu chuẩn khác :
Ghi nhớ nó trong tâm trí.
Thống kê là những sự thật phổ quát.
Đó là mục đích của một không gian tên toàn cầu: những thứ chính xác trên toàn bộ lớp ứng dụng.
Có một đối số dốc trơn trượt ở đây. Vài ví dụ:
var myConfigKey = ConfigurationManager.AppSettings["myConfigKey"];
Đây là một ví dụ cắt rất rõ ràng. Cấu hình ứng dụng vốn đã ngụ ý rằng cấu hình đó là toàn cầu đối với ứng dụng và do đó, một phương pháp statis được bảo hành.
bool datesOverlap = DateHelper.HasOverlap(myDateA_Start, myDateA_End, myDateB_Start, myDateB_End);
Phương pháp này là phổ biến chính xác. Nó không quan tâm mà ngày bạn đang so sánh. Phương pháp không quan tâm đến ý nghĩa của ngày. Cho dù chúng là ngày làm việc, ngày hợp đồng, ... không quan trọng đối với thuật toán của phương pháp.
Lưu ý sự tương đồng về ngữ nghĩa giữa ngữ cảnh và trạng thái . Cả hai loại đều đề cập đến một trạng thái "không phổ quát". Điều này chứng tỏ rằng sự khác biệt theo ngữ cảnh do đó phụ thuộc vào nhà nước và không phù hợp để được thực hiện tĩnh.
var newPersonObject = Person.Create();
Đây là một sự thật phổ quát. Quá trình tạo tương tự được sử dụng trên tất cả các ứng dụng.
Tuy nhiên, dòng này có thể bị mờ:
var newManager = Person.CreateManager();
var newJanitor = Person.CreateJanitor();
Từ góc độ kỹ thuật, không có gì thay đổi. Trình quản lý (và người gác cổng) được tạo theo cùng một cách trên tất cả các ứng dụng. Tuy nhiên, điều này đã khéo léo tạo ra một nhà nước (quản lý / người gác cổng), mà chậm nhưng đều đặn làm giảm đi bao quát sự thật thực sự là.
Nó có thể được thực hiện? Từ góc độ kỹ thuật; vâng .
Có nên làm vậy không? Đó là vấn đề cho dù bạn đang tranh luận về nguyên tắc thuần túy, hay tính đến việc thỏa hiệp cần phải được thực hiện để không phấn đấu một cách vô nghĩa cho sự hoàn hảo hợp lý. Vì vậy, tôi sẽ nói nếu nó không tạo ra một vấn đề lớn hơn vấn đề dự định giải quyết .
Khi các tùy chọn mở rộng (người quản lý, người gác cổng, kế toán, nhân viên bán hàng, ...), vấn đề sẽ tăng lên. Đối với một vấn đề đủ lớn, một mô hình nhà máy là mong muốn.
Nếu bạn chỉ có hai tùy chọn và bạn không có lý do để nghi ngờ rằng danh sách các tùy chọn sẽ tăng lên, bạn có thể lập luận rằng các phương thức tạo tĩnh đủ. Một số có thể không đồng ý, và tôi cũng thấy quan điểm của họ. Nhưng tôi có xu hướng thực tế và không quá cầu toàn trong cách tiếp cận của mình.