Có phải là thực hành xấu để sử dụng lại các tham số phương pháp?


12

Đôi khi tôi sẽ cần phải sửa đổi một giá trị được truyền vào một phương thức từ bên trong chính phương thức đó. Một ví dụ sẽ là vệ sinh một chuỗi như phương thức này ở đây:

void SanitizeName(string Name)
{
    Name = Name.ToUpper();

    //now do something here with name
}

Điều này hoàn toàn vô hại vì Nameđối số không được thông qua bởi tham chiếu. Tuy nhiên, nếu vì một lý do nào đó, một nhà phát triển trong tương lai quyết định chuyển tất cả các giá trị bằng ref, thì việc khử trùng chuỗi sẽ ảnh hưởng đến giá trị bên ngoài phương thức có thể có kết quả bất lợi.

Do đó, thay vì tự gán lại cho đối số, tôi luôn tạo một bản sao cục bộ như vậy:

void SanitizeName(string Name)
{
    var SanitizedName = Name.ToUpper();

    //now do something here with name
}

Điều này đảm bảo rằng việc thay đổi giá trị được truyền vào sẽ không bao giờ ảnh hưởng đến các phương pháp bên ngoài phương thức, nhưng tôi tự hỏi liệu tôi có bị hoang tưởng quá mức về điều này không.


1
Vâng, đó là thực tế xấu; và không, nó không vô hại. Dòng này Name = Name.ToUpper();làm cho mã khó theo dõi hơn trong đầu bạn khi giá trị của các Namethay đổi. Ví dụ thứ hai của bạn không chỉ là bằng chứng trong tương lai, dễ dàng hơn để lý giải những gì nó đang làm.
David Arno

2
Nhưng còn cái gì if (param == NULL) param = default_value;?
aragaer

Tôi nghĩ nó không dễ như có / không.
MrSmith42

3
Nếu "một nhà phát triển trong tương lai quyết định có tất cả các giá trị được chuyển qua bởi ref" , tôi có thể sẽ có một đối số với dev đó, sử dụng lại tham số có liên quan hay không ;-) Thành thật mà nói, khi một người quyết định chuyển một giá trị by refkhông được thông qua Vì lý do nào đó, và vì vậy chuyển đổi quyền truy cập cục bộ sang quyền truy cập không phải cục bộ vì một số lý do, anh ta luôn phải kiểm tra hậu quả một cách cẩn thận.
Doc Brown

2
Tôi chủ yếu làm việc trong một mô hình mà chúng tôi không bao giờ gán lại bất kỳ biến nào . Không bao giờ. Thật buồn cười khi tưởng tượng ai đó đang vật lộn với việc liệu họ có nên gán lại một số lượng nhỏ các biến số và sau đó không lo lắng về việc đi hoang với phần còn lại.
Karl Bielefeldt

Câu trả lời:


10

Tôi nghĩ rằng nó phụ thuộc vào các quy ước mã hóa trong dự án của bạn.

Cá nhân tôi để nhật thực tự động thêm final từ khóa vào mọi biến và tham số. Bằng cách này bạn sẽ thấy ngay từ cái nhìn đầu tiên nếu một tham số được sử dụng lại.

Trong dự án trong công việc của tôi, chúng tôi không khuyên bạn nên sử dụng lại các tham số, nhưng nếu bạn chỉ muốn gọi ví dụ .trim()hoặc đặt mặc định trongnull trường hợp, chúng tôi thường sử dụng lại tham số đó, bởi vì việc giới thiệu một biến mới là trong những trường hợp như vậy ít đọc hơn hơn việc sử dụng lại tham số.

Bạn thực sự không nên sử dụng lại một tham số để lưu trữ một nội dung rất khác vì tên sẽ không còn đề cập đến nội dung của nó. Nhưng điều này đúng với mọi đánh giá lại một biến và không bị giới hạn ở các tham số.

Vì vậy, hãy kết hợp với nhóm của bạn và xây dựng các quy ước mã hóa bao gồm vấn đề này.


0

Nếu bạn sử dụng bộ phân tích mã tĩnh cho mục đích bảo mật, nó có thể bị nhầm lẫn và nghĩ rằng bạn chưa xác thực hoặc vệ sinh biến tham số đầu vào trước khi sử dụng. NameVí dụ, nếu bạn sử dụng truy vấn SQL, nó có thể yêu cầu lỗ hổng SQL tiêm, điều này sẽ khiến bạn mất thời gian để giải thích. Thật tệ. Mặt khác, sử dụng một biến được đặt tên riêng cho đầu vào được khử trùng, mà không thực sự khử trùng đầu vào, là một cách nhanh chóng để làm im lặng các máy phân tích mã ngây thơ (tìm lỗ hổng âm tính giả).


Trong hầu hết các trường hợp, bạn cũng có thể sử dụng một số loại chú thích hoặc nhận xét đặc biệt để chỉ ra cho bộ phân tích mã rằng đây là mục đích và không phải là rủi ro không được chú ý.
MrSmith42

0

Câu trả lời cho điều này phụ thuộc 100% vào người sẽ đọc mã của bạn. Những phong cách nào họ thấy hữu ích nhất?

Tôi đã tìm thấy trường hợp chung nhất là người ta tránh việc gán lại các giá trị cho các đối số hàm vì quá nhiều nhà phát triển có các mô hình tinh thần về cách gọi hàm hoạt động mà cho rằng bạn không bao giờ làm điều này. Vấn đề này có thể được làm trầm trọng hơn bởi các trình gỡ lỗi in các giá trị của các đối số bạn gọi cho mỗi hàm. Thông tin này là về mặt kỹ thuật không chính xác nếu bạn chỉnh sửa các đối số và điều đó có thể dẫn đến một số sự thất vọng kỳ lạ.

Điều đó đang được nói, mô hình tinh thần thay đổi. Trong môi trường phát triển cụ thể của bạn, có thể mong muốn trở namethành "đại diện tốt nhất của tên tại thời điểm này." Có thể mong muốn liên kết rõ ràng hơn các biến bạn đang làm việc với các đối số của chúng, mặc dù bạn đã thực hiện một số sửa đổi đối với các giá trị của chúng trên đường đi. Thậm chí có thể có những lợi thế đáng kể về thời gian chạy để sử dụng lại một số biến cụ thể thay vì tạo ra các đối tượng cồng kềnh hơn. Xét cho cùng, khi bạn làm việc với chuỗi 4GB, thật tuyệt khi giảm thiểu số lượng bản sao bổ sung bạn phải tạo!


-1

Tôi có một vấn đề hoàn toàn khác với ví dụ mã của bạn:

Tên phương thức của bạn là SanitizeName. Trong trường hợp này, tôi hy vọng nó sẽ vệ sinh một cái tên ; bởi vì đó là những gì bạn nói với người đọc về chức năng của bạn.

Điều duy nhất, mà bạn hoạt động nên làm , là vệ sinh một tên cụ thể . Nếu không đọc mã của bạn, tôi sẽ mong đợi như sau:

string SanitizeName(string Name)
{
    //somehow sanitize the name
    return Result;
}

Nhưng bạn ngụ ý rằng phương pháp của bạn làm được nhiều hơn một chút so với chỉ sanitizng. Đó là một mùi mã và nên tránh.

Câu hỏi của bạn không phải là về: Có phải thực hành xấu khi sử dụng lại các tham số của phương thức? Đó là nhiều hơn: là tác dụng phụ và hành vi không được thực hiện xấu thực hành?

Câu trả lời rõ ràng là: có!

Điều này hoàn toàn vô hại vì đối số Tên không được truyền vào bởi tham chiếu. Tuy nhiên, nếu vì một lý do nào đó, một nhà phát triển trong tương lai quyết định chuyển tất cả các giá trị bằng ref, thì việc khử trùng chuỗi sẽ ảnh hưởng đến giá trị bên ngoài phương thức có thể có kết quả bất lợi

Bạn đánh lừa độc giả của bạn bằng cách không trả lại bất cứ điều gì. Tên phương thức của bạn chỉ rõ rằng bạn đang làm gì đó Name. Vậy, kết quả nên đi đâu? Chữ ký hàm của bạn voidđọc tôi sử dụng Namenhưng không gây hại gì cho id, cũng không cho bạn biết kết quả (rõ ràng). Có lẽ có một ngoại lệ ném, có thể không; nhưng Namekhông bị thay đổi . Đây là ngữ nghĩa ngược với tên phương thức của bạn.

Vấn đề là ít tái sử dụng hơn các tác dụng phụ . Để ngăn chặn tác dụng phụ không sử dụng lại một biến. Nếu bạn không có tác dụng phụ thì không có vấn đề gì.


4
-1 Điều này không trả lời câu hỏi ban đầu. Mã được cung cấp chỉ là một mã mẫu để hiển thị câu hỏi trong tầm tay. Vui lòng trả lời câu hỏi, thay vì "tấn công" / xem lại mã mẫu được cung cấp.
Niklas H

1
@NiklasH Điều này trả lời câu hỏi một cách hoàn hảo: nếu bạn thao tác tham số bên trong hàm và như TO đã đề cập, bạn vô tình làm việc với một tham chiếu thay vì một bản sao, điều này gây ra tác dụng phụ (như tôi đã nói) và điều này thật tệ. Để ngăn điều đó cho thấy rằng bạn sẽ thay đổi biến bằng cách cẩn thận chọn tên phương thức (nghĩ về '!' Của Ruby và / hoặc chọn loại trả về. Nếu bạn không thay đổi biến, chỉ làm việc với các bản sao.
Thomas Junk
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.