Là các tham số tùy chọn hữu ích hoặc cản trở để bảo trì ứng dụng? [đóng cửa]


14

Như đã nêu trong tiêu đề, các tham số tùy chọn, chẳng hạn như các tham số được sử dụng trong C # có hữu ích hay chúng là một trở ngại cho việc bảo trì ứng dụng và nên tránh vì chúng có thể làm cho mã khó hiểu hơn?


3
Tuyên bố từ chối trách nhiệm: bất kỳ tính năng ngôn ngữ trong tay sai có thể bị lạm dụng. Nếu một ngôn ngữ thực hiện điều này một cách thông minh và tính năng ngôn ngữ này không trùng lặp quá nhiều với tính năng ngôn ngữ hiện có theo cách buồn tẻ, thì thực tế chúng rất tốt, thực tế khá hữu ích. Python có một số đóng gói / giải nén param gọn gàng và các "thủ thuật" tham số khác (thủ thuật theo nghĩa tốt, không phải là ý nghĩa Perl).
Công việc

Hãy thử viết một ứng dụng trong C # có giao diện với Excel mà không sử dụng các tham số tùy chọn. Điều đó sẽ trả lời câu hỏi của bạn ngoài bất kỳ nghi ngờ hợp lý.
Dunk

Câu trả lời:


22

Theo kinh nghiệm của tôi, các tham số tùy chọn là một điều tốt. Tôi chưa bao giờ thấy chúng khó hiểu (ít nhất là không khó hiểu hơn hàm thực tế), vì tôi luôn có thể nhận được các giá trị mặc định và biết những gì được gọi.

Một lần sử dụng cho chúng là khi tôi phải thêm một tham số khác vào một chức năng đã được sử dụng chung, hoặc ít nhất là trong giao diện công cộng. Không có chúng, tôi phải làm lại chức năng ban đầu để gọi một đối số có một đối số khác và điều đó có thể trở nên thực sự cũ nếu tôi kết thúc việc thêm các đối số nhiều lần.


1
+1 Và nó có giá trị với các phương thức quá tải có thêm một đối số như new Circle(size, color, filled, ellipseProportions)ở đâu sizecolorđược yêu cầu và phần còn lại là mặc định.
Michael K

15

Nói chung, nếu bạn cần nhiều tham số / tùy chọn thường xuyên, các chức năng của bạn đang hoạt động quá nhiều và nên bị phá vỡ. Bạn có khả năng phá vỡ SRP (Nguyên tắc trách nhiệm duy nhất).

Tìm các tham số có thể được nhóm lại, ví dụ (x và y, trở thành một điểm).

Là những cờ tham số tùy chọn với một mặc định? Nếu bạn đang sử dụng cờ, chức năng sẽ được tách ra.

Điều đó không có nghĩa là bạn không bao giờ nên có các tham số tùy chọn, nhưng nói chung, nhiều hơn một hoặc hai tham số gợi ý mùi mã.

Nó cũng có thể là một đầu mối rằng hàm, thực sự phải là một lớp, với các tham số tùy chọn được thay đổi thành các thuộc tính và một phần tham số bắt buộc của hàm tạo.


1
+1 vì đã cẩn thận. Bất kỳ tính năng nào, dù tốt đến đâu, đều có thể bị lạm dụng.
Michael K

3
Đây là lời khuyên tuyệt vời để sản xuất mã ravioli bị áp đảo, trong đó người dùng API của bạn phải sử dụng ít nhất 6 lớp và 15 hàm để thực hiện ngay cả điều đơn giản nhất.
dsimcha

1
@dsimcha, làm thế nào để bạn có được điều đó từ những gì tôi đã viết? Ồ Vui lòng giải thích? Đó sẽ là thiết kế tồi tệ không kém khi có một "siêu chức năng", đó là những gì bạn nhận được khi bạn có nhiều tham số tùy chọn. Đọc về các nguyên tắc thiết kế RẮN và viết mã thử nghiệm. Tốt nhất là sử dụng TDD. Sau đó quay lại và thử và giải thích cho tôi rằng giảm tham số trong các hàm là một điều xấu.
CaffGeek

1
Mã có thể kiểm tra là tốt, nhưng API sạch sẽ, có thể sử dụng được, không quá hạt mịn hoặc dài dòng và không đưa các lớp vào các tình huống trong đó một hàm là sự trừu tượng hóa thích hợp. Tôi tin vào nguyên tắc trách nhiệm duy nhất với các trách nhiệm được xác định ở mức độ trừu tượng cao. Nếu trách nhiệm được xác định ở mức quá thấp, các đơn vị riêng lẻ trở nên quá đơn giản sao cho tương tác của chúng quá phức tạp.
dsimcha

1
@dsimcha, bạn đang thiếu điểm. Các đơn vị riêng lẻ nên duy trì các đơn vị riêng lẻ và không được gộp chung trong một chức năng. Điều đó cũng không có nghĩa là tất cả chúng đều có chức năng truy cập công khai. API của bạn là cổng vào mã và phải rõ ràng và súc tích. Một hàm với một vài tham số tùy chọn là không sạch, cũng không súc tích. Tuy nhiên, quá tải một chức năng duy nhất với các tham số logic rõ ràng hơn nhiều. Ví dụ: có các hàm trong nhiều API trong đó, hai parm là tùy chọn, nhưng một hoặc hai là bắt buộc. Điều gì rõ ràng về điều đó khi cả hai được đánh dấu tùy chọn?
CaffGeek

4

Thông số tùy chọn là tốt

Thông thường, lời biện minh là a) bạn biết rằng bạn có rất nhiều đối số có thể có cho phương thức của mình nhưng bạn không muốn quá tải vì sợ làm mờ API của mình hoặc b) khi bạn không biết tất cả các đối số có thể nhưng bạn không muốn buộc người dùng của bạn cung cấp một mảng. Trong mỗi trường hợp, các tham số tùy chọn đến cứu hộ một cách gọn gàng và thanh lịch.

Dưới đây là một số ví dụ:

1. Bạn muốn tránh quá tải và không muốn chỉ định một mảng

Hãy xem printf () từ C, Perl, Java, v.v ... Đó là một ví dụ tuyệt vời về sức mạnh của các tham số tùy chọn.

Ví dụ:

printf("I want %d %s %s",1,"chocolate","biccies");

printf("I want %d banana",1);

Không quá tải, không có mảng, đơn giản và trực quan (một khi bạn đã nắm được các mã định dạng chuỗi tiêu chuẩn). Một số IDE thậm chí sẽ cho bạn biết nếu chuỗi định dạng của bạn không khớp với các tham số tùy chọn của bạn.

2. Bạn muốn cho phép sử dụng mặc định và giữ chúng ẩn khỏi người dùng phương thức

sendEmail ("test@example.org");

Phương thức sendEmail phát hiện ra rằng các giá trị thiết yếu khác nhau bị thiếu và điền vào chúng bằng cách sử dụng các giá trị mặc định đã xác định (chủ đề, cơ thể, cc, bcc, v.v.). API được giữ sạch sẽ, nhưng linh hoạt.

Một lưu ý về quá nhiều thông số

Tuy nhiên, như những người khác đã tuyên bố, việc có quá nhiều tham số bắt buộc đối với một phương thức cho thấy rằng bạn có thể có điều gì đó không đúng với thiết kế của bạn. Điều này đặc biệt đúng nếu chúng chia sẻ cùng loại vì chúng có thể được nhà phát triển chuyển đổi một cách tình cờ dẫn đến kết quả lạ khi chạy:

String myMethod(String x, String y, String z, String a, int b, String c, int d) {}

là một ứng cử viên lý tưởng cho việc tái cấu trúc Đối tượng tham số giới thiệu để tạo

String myMethod(ParameterObject po) {}

class ParameterObject {
  // Left as public for clarity
  public String x;
  public String y;
  ... etc

}

Điều này đến lượt nó có thể dẫn đến một thiết kế tốt hơn dựa trên mẫu Factory với đặc tả được cung cấp làm đối tượng tham số.


1
Các hàm định dạng chuỗi như printf là ngoại lệ của quy tắc, người ta có thể lập luận rằng trong khi họ sử dụng danh sách không giới hạn các tham số tùy chọn, thì nó giống như đối số là một mảng hơn là tham số tùy chọn, mặc dù cách nó được triển khai.
CaffGeek

@Chad Tôi đã điều chỉnh câu trả lời của mình để phân biệt tốt hơn giữa các tham số tùy chọn và khi chúng chuyển sang mùi mã (như bạn đã đề cập trong câu trả lời của mình).
Gary Rowe

@Gary Rowe, quá nhiều tham số tùy chọn cũng không tốt trong hầu hết các trường hợp.
CaffGeek

@Chad Tôi đồng ý, nhưng hầu hết các ngôn ngữ không cung cấp cách chỉ định giới hạn về số lượng đối số tùy chọn để đó là cách tiếp cận tất cả hoặc không có gì. Bạn buộc phải để nó cho phương thức của mình để thực thi và rõ ràng nếu phương thức của bạn đang xử lý 500 biến thì chắc chắn nó sẽ cần phải được cấu trúc lại.
Gary Rowe

@Gary Rowe, ý bạn là gì "hầu hết các ngôn ngữ không cung cấp cách chỉ định giới hạn số lượng đối số tùy chọn"? Trong hầu hết các ngôn ngữ, bạn đánh dấu chúng là như vậy hoặc không cung cấp cho chúng các giá trị khi gọi hàm, nhưng tiêu đề hàm vẫn có các tham số được xác định. Cấp, trong một số ngôn ngữ bạn có thể thêm bao nhiêu tham số bạn muốn sau khi bạn điền vào những ngôn ngữ đã xác định, nhưng tôi không nghĩ đó là loại tham số tùy chọn mà chúng ta đang nói ở đây. (ngoài ngoại lệ định dạng chuỗi)
CaffGeek

2

Một trong những vấn đề với các tham số mặc định trong C # (Tôi đang nghĩ void DoS Something (int x = 1)) là chúng là hằng số. Điều đó có nghĩa là nếu bạn thay đổi mặc định, bạn sẽ phải biên dịch lại bất kỳ người tiêu dùng nào của cuộc gọi phương thức đó. Trong khi điều này là đủ dễ dàng để làm, có những lúc điều này là nguy hiểm.


1

Nó phụ thuộc vào những gì mã của bạn đang làm. Nếu có mặc định hợp lý thì bạn nên sử dụng các tham số tùy chọn nhưng nếu không có mặc định hợp lý thì việc thêm tham số tùy chọn sẽ làm cho mã của bạn phức tạp hơn. Trong nhiều trường hợp, các tham số tùy chọn là một cách gọn gàng để kiểm tra nil và cắt bỏ logic phân nhánh. Javascript không có các tham số tùy chọn nhưng có một cách để mô phỏng chúng với | | (logic hoặc) và tôi sử dụng nó mọi lúc khi thực hiện các công việc liên quan đến cơ sở dữ liệu vì nếu người dùng không cung cấp một số giá trị thì tôi thay thế các giá trị của riêng tôi bằng sự trợ giúp của || Điều này giúp tôi tiết kiệm được những rắc rối khi viết cả đống câu lệnh if.


1

Các tham số tùy chọn là một cách tuyệt vời để làm cho những điều đơn giản trở nên đơn giản và những điều phức tạp có thể xảy ra đồng thời. Nếu có một mặc định hợp lý rõ ràng mà hầu hết người dùng sẽ muốn, ít nhất là trong các trường hợp sử dụng nhanh và bẩn, thì họ không cần phải viết bản tóm tắt để chỉ định thủ công mỗi khi họ gọi hàm của bạn. Mặt khác, nếu mọi người có thể có lý do chính đáng để muốn thay đổi nó, thì nó cần phải được phơi bày.

Sử dụng một lớp học là IMHO một giải pháp khủng khiếp, vì nó dài dòng, không hiệu quả và không phù hợp với mô hình tinh thần điển hình của những gì một lớp học làm. Một chức năng là sự trừu tượng hoàn hảo cho một động từ, tức là làm một cái gì đó và trở lại. Một lớp là sự trừu tượng đúng cho một danh từ, tức là một cái gì đó có trạng thái và có thể được thao tác theo nhiều cách. Nếu trước đây phải là mô hình tinh thần của người dùng API, thì đừng biến nó thành một lớp.


1

Vấn đề với các đối số tùy chọn là mọi người có xu hướng chỉ đưa vào ngày càng nhiều (và nhiều hơn) đối số cho hàm thay vì trích xuất mã có liên quan vào một hàm mới. Điều này được đưa đến cực đoan trong php . Ví dụ:

bool array_multisort ( array &$arr [, mixed $arg = SORT_ASC
                      [, mixed $arg = SORT_REGULAR [, mixed $... ]]] )

1

Các tham số tùy chọn về cơ bản là một cách khác nhau để nạp chồng một hàm. Vì vậy, điều này về cơ bản đi xuống: "quá tải một chức năng xấu"?


1

Ban đầu tôi rất thích tính năng này trong python và đã sử dụng nó để 'mở rộng' các phương thức đã sử dụng. Và nó trông đẹp và dễ dàng, nhưng nó sẽ sớm quay lại; bởi vì khi tôi thêm một tham số tùy chọn, điều này đã sửa đổi hành vi của một phương thức hiện có mà máy khách cũ dựa vào và theo cách không bị bắt bởi các trường hợp kiểm thử đơn vị hiện có. Về cơ bản làm điều này là phá vỡ Nguyên tắc Đóng mở; mã được mở để mở rộng nhưng đóng để sửa đổi. Vì vậy, tôi tin rằng việc sử dụng tính năng này để sửa đổi mã hiện tại không phải là một ý tưởng tốt; nhưng không sao nếu được sử dụng từ đầu


0

Tôi nghĩ sẽ tốt hơn khi quá tải một hàm với các chữ ký khác nhau (tức là các tham số) hơn là sử dụng các tham số tùy chọn.


Tại sao? Tôi nghĩ sẽ sạch hơn nếu bạn có thể kết hợp một loạt các phương thức bị quá tải thành một phương thức bằng cách sử dụng các tham số mặc định nếu tất cả các phương thức có cùng chức năng cơ bản
Amit Wadhwa

Bạn có thể nghĩ rằng. Tôi không nghĩ Microsoft làm mọi thứ đúng cách, nhưng nếu bạn chính xác, thì tôi sẽ không bao giờ thấy quá tải khi sử dụng .NET framework, chỉ là một chữ ký hàm lớn - như trong VB6 của ol.
HardCode
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.