Có một lý do để không sửa đổi giá trị của các tham số được truyền bởi giá trị?


9

Có các đối số kỹ thuật phần mềm khách quan, có thể hỗ trợ cho hoặc chống lại việc sửa đổi các giá trị của các tham số theo giá trị trong phần thân của hàm không?

Một spat định kỳ (chủ yếu là vui vẻ) trong nhóm của tôi là liệu các tham số được truyền theo giá trị có nên được sửa đổi hay không. Một vài thành viên của nhóm rất kiên quyết rằng các tham số không bao giờ được gán cho, để giá trị ban đầu được truyền cho hàm luôn có thể được hỏi. Tôi không đồng ý và cho rằng các tham số không có gì khác ngoài các biến cục bộ được khởi tạo bởi cú pháp gọi phương thức; nếu giá trị ban đầu của tham số theo giá trị quan trọng hơn biến cục bộ có thể được khai báo để lưu trữ rõ ràng giá trị này. Tôi không tự tin rằng một trong hai chúng tôi có hỗ trợ rất tốt cho vị trí của chúng tôi.

Đây có phải là một xung đột tôn giáo không thể giải quyết được không, hay có những lý do kỹ thuật phần mềm khách quan, tốt theo cả hai hướng?

Lưu ý: Câu hỏi về nguyên tắc vẫn không phụ thuộc vào chi tiết thực hiện của ngôn ngữ cụ thể. Trong JavaScript, ví dụ, trong đó danh sách đối số luôn động, các tham số có thể được coi là đường cú pháp để khởi tạo biến cục bộ từ argumentsđối tượng. Mặc dù vậy, người ta có thể coi các định danh khai báo tham số là "đặc biệt" bởi vì họ vẫn nắm bắt được việc truyền thông tin từ người gọi đến callee.


Nó vẫn là ngôn ngữ cụ thể; lập luận rằng đó là bất khả tri về ngôn ngữ bởi vì "nó là như vậy, theo quan điểm của tôi (ngôn ngữ yêu thích)" là một hình thức tranh luận không hợp lệ. Một lý do thứ hai tại sao nó là ngôn ngữ cụ thể là bởi vì một câu hỏi không có câu trả lời chung cho tất cả các ngôn ngữ là tùy thuộc vào văn hóa và chuẩn mực của mỗi ngôn ngữ; trong trường hợp này, các chuẩn mực ngôn ngữ cụ thể khác nhau dẫn đến các câu trả lời khác nhau cho câu hỏi này.
rwong

Nguyên tắc mà các thành viên trong nhóm của bạn đang cố gắng dạy cho bạn là "một biến, một mục đích". Thật không may, bạn cũng sẽ không tìm thấy bằng chứng dứt khoát. Đối với những gì nó có giá trị, tôi không nhớ đã bao giờ chọn một biến tham số cho một số mục đích khác, tôi cũng không nhớ mình đã từng xem xét nó. Nó chưa bao giờ xảy ra với tôi rằng nó có thể là một ý tưởng tốt, và tôi vẫn không nghĩ rằng nó là.
Robert Harvey

Tôi nghĩ rằng điều này phải được hỏi trước đây, nhưng câu bịp duy nhất tôi có thể tìm thấy là câu hỏi SO cũ hơn này .
Doc Brown

3
Nó được coi là ít có lỗi hơn đối với một ngôn ngữ để ngăn chặn sự đột biến của đối số, giống như các nhà thiết kế ngôn ngữ chức năng xem xét các bài tập của Let let để ít bị lỗi hơn. Tôi nghi ngờ bất cứ ai đã chứng minh giả định này bằng một nghiên cứu.
Frank Hileman

Câu trả lời:


15

Tôi không đồng ý và cho rằng các tham số không có gì khác ngoài các biến cục bộ được khởi tạo bởi cú pháp gọi phương thức

Tôi chấp nhận vị trí thứ ba: các tham số giống như các biến cục bộ: cả hai nên được coi là bất biến theo mặc định. Vì vậy, các biến được chỉ định một lần và sau đó chỉ đọc từ, không thay đổi. Trong trường hợp các vòng lặp, for each (x in ...)biến là bất biến trong bối cảnh của mỗi lần lặp. Những lý do cho điều này là:

  1. nó làm cho mã dễ dàng hơn để "thực thi trong đầu tôi",
  2. nó cho phép nhiều tên mô tả hơn cho các biến.

Đối mặt với một phương thức với một loạt các biến được gán và sau đó không thay đổi, tôi có thể tập trung vào việc đọc mã, thay vì cố gắng nhớ giá trị hiện tại của từng biến đó.

Đối mặt với cùng một phương thức đó, lần này với ít biến hơn, nhưng giá trị đó luôn thay đổi, giờ tôi phải nhớ trạng thái hiện tại của các biến đó, cũng như làm việc với những gì mã đang làm.

Theo kinh nghiệm của tôi, trước đây dễ dàng hơn nhiều đối với bộ não kém của tôi. Khác, thông minh hơn, dân gian hơn tôi có thể không có vấn đề này, nhưng nó giúp tôi.

Về điểm khác:

double Foo(double r)
{
    r = r * r;
    r = Math.Pi * r;
    return r;
}

đấu với

double Foo(int r)
{
    var rSquared = r * r;
    var area = Math.Pi * rSquared;
    return area;
} 

Ví dụ giả định, nhưng đối với tôi, nó rõ ràng hơn nhiều so với những gì đang diễn ra trong ví dụ thứ hai do các tên biến: chúng truyền tải nhiều thông tin đến người đọc hơn so với khối lượng của rví dụ đầu tiên.


"các biến cục bộ .... nên được coi là bất biến theo mặc định." - Gì?
whatsisname

1
Thật khó để chạy forcác vòng lặp với các biến không thay đổi. Đóng gói các biến trong hàm không đủ cho bạn? Nếu bạn gặp khó khăn khi theo dõi các biến của mình trong một hàm đơn thuần, có lẽ các hàm của bạn quá dài.
Robert Harvey

@RobertHarvey for (const auto thing : things)là một vòng lặp for và biến mà nó giới thiệu là (cục bộ) không thay đổi. for i, thing in enumerate(things):cũng không làm thay đổi bất kỳ người dân địa phương nào
Caleth

3
Đây là IMHO nói chung là một mô hình tinh thần rất tốt. Tuy nhiên, một điều tôi muốn thêm vào: thường thì có thể chấp nhận khởi tạo một biến trong hơn một bước và coi nó là bất biến sau đó. Điều này không chống lại chiến lược chung được trình bày ở đây, chỉ chống lại việc này luôn theo nghĩa đen.
Doc Brown

3
Wow, đọc những bình luận này, tôi có thể thấy rằng nhiều người ở đây rõ ràng chưa bao giờ nghiên cứu mô hình chức năng.
Joshua Jones

4

Đây có phải là một xung đột tôn giáo không thể giải quyết được không, hay có những lý do kỹ thuật phần mềm khách quan, tốt theo cả hai hướng?

Đó là một điều tôi thực sự thích (được viết tốt) C ++: bạn có thể thấy những gì mong đợi. const string& x1là một tài liệu tham khảo liên tục, string x2là một bản sao và const string x3là một bản sao liên tục. Tôi biết những gì sẽ xảy ra trong chức năng. x2 sẽ được thay đổi, bởi vì nếu không, sẽ không có lý do gì để biến nó thành không phải.

Vì vậy, nếu bạn có một ngôn ngữ cho phép nó, hãy khai báo những gì bạn sắp làm với các tham số. Đó nên là sự lựa chọn tốt nhất cho mọi người tham gia.

Nếu ngôn ngữ của bạn không cho phép điều này, tôi sợ rằng không có giải pháp viên đạn bạc. Cả hai đều có thể. Hướng dẫn duy nhất là nguyên tắc ít bất ngờ nhất. Thực hiện một cách tiếp cận và đi với nó trong suốt cơ sở mã của bạn, không trộn lẫn nó.


Một điều tốt là nó int f(const T x)int f(T x)chỉ khác nhau trong cơ thể chức năng.
Ded repeatator

3
Hàm C ++ có tham số như const int xchỉ để làm rõ x không bị thay đổi bên trong? Trông giống như một phong cách rất lạ với tôi.
Doc Brown

@DocBrown Tôi không phán xét phong cách nào cả, tôi chỉ nói rằng ai đó nghĩ rằng không nên thay đổi tham số có thể khiến trình biên dịch đảm bảo điều đó và ai đó nghĩ rằng thay đổi chúng là tốt cũng có thể làm như vậy. Cả hai ý định đều có thể được truyền đạt rõ ràng thông qua chính ngôn ngữ đó và đó là một lợi thế lớn so với ngôn ngữ không thể đảm bảo theo bất kỳ cách nào và bạn phải dựa vào các hướng dẫn tùy ý và hy vọng mọi người đọc chúng và tuân thủ chúng.
nvoigt

@nvoigt: nếu ai đó thích sửa đổi tham số hàm ("theo giá trị"), anh ta chỉ cần loại constbỏ khỏi danh sách tham số nếu nó cản trở anh ta. Vì vậy, tôi không nghĩ rằng điều này trả lời câu hỏi.
Doc Brown

@DocBrown Sau đó, nó không còn là const. Không quan trọng là nó có hay không, điều quan trọng là ngôn ngữ bao gồm một cách để truyền đạt điều đó đến nhà phát triển mà không nghi ngờ gì. Câu trả lời của tôi là nó không quan trọng, miễn là bạn giao tiếp rõ ràng , điều mà C ++ làm cho dễ dàng, những người khác có thể không và bạn cần các quy ước.
nvoigt

1

Vâng, đó là một "xung đột tôn giáo", ngoại trừ việc Chúa không đọc các chương trình (theo như tôi biết), vì vậy nó bị hạ cấp thành một cuộc xung đột dễ đọc trở thành vấn đề phán xét cá nhân. Và tôi chắc chắn đã làm nó, và thấy nó được thực hiện, cả hai cách. Ví dụ,

void tuyên truyền (đối tượng * *, double t0, double dt) {
  gấp đôi t = t0; / * bản sao cục bộ của t0 để tránh thay đổi giá trị của nó * /
  trong khi (bất cứ điều gì) {
    timestep_the_object (...);
    t + = dt; }
  trở về; }

Vì vậy, ở đây, chỉ vì tên đối số t0 , tôi có thể chọn không thay đổi giá trị của nó. Nhưng giả sử thay vào đó, chúng tôi chỉ thay đổi tên đối số thành tNow hoặc một cái gì đó tương tự. Sau đó, nhiều khả năng tôi đã quên mất một bản sao cục bộ và chỉ viết tNow + = dt; cho câu nói cuối cùng

Nhưng ngược lại, giả sử tôi biết rằng khách hàng mà chương trình được viết sắp thuê một số lập trình viên mới với rất ít kinh nghiệm, họ sẽ đọc và làm việc với mã đó. Sau đó, tôi có thể lo lắng về việc nhầm lẫn chúng với giá trị truyền qua so với giá trị, trong khi tâm trí của chúng bận rộn 100% khi cố gắng tiêu hóa tất cả logic kinh doanh. Vì vậy, trong trường hợp này, tôi luôn tuyên bố một bản sao cục bộ của bất kỳ đối số nào sẽ được thay đổi, bất kể nó có dễ đọc hơn hay ít hơn đối với tôi hay không.

Câu trả lời cho các loại câu hỏi phong cách xuất hiện với kinh nghiệm, và hiếm khi có một câu trả lời tôn giáo kinh điển. Bất cứ ai nghĩ rằng có một câu trả lời duy nhất (và rằng anh ta biết điều đó :) có lẽ cần thêm một số kinh nghiệm.

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.