Tại sao không mã hóa tên của các đối số trong tên hàm phổ biến hơn? [đóng cửa]


47

Trong Clean Code , tác giả đưa ra một ví dụ về

assertExpectedEqualsActual(expected, actual)

đấu với

assertEquals(expected, actual)

với cái trước được tuyên bố là rõ ràng hơn bởi vì nó loại bỏ sự cần thiết phải nhớ nơi tranh luận và sự lạm dụng tiềm năng đến từ đó. Tuy nhiên, tôi chưa bao giờ thấy một ví dụ về sơ đồ đặt tên trước trong bất kỳ mã nào và luôn luôn thấy cái sau. Tại sao các lập trình viên không chấp nhận cái trước nếu như, như tác giả khẳng định, rõ ràng hơn cái sau?


9
Tôi nghĩ rằng đây là câu hỏi tuyệt vời cho một cuộc thảo luận. Nhưng không phải cái gì đó có thể được trả lời với câu trả lời khách quan. Vì vậy, câu hỏi này có thể được đóng lại như dựa trên ý kiến.
Euphoric

54
Nhiều người sẽ tranh luận chống lại kế hoạch đặt tên đầu tiên bởi vì nó quá dài dòng , vượt xa điểm mà nó sẽ giúp cho sự rõ ràng. Đặc biệt assertEquals(), phương pháp đó được sử dụng hàng trăm lần trong một cơ sở mã để người đọc có thể mong đợi làm quen với quy ước một lần. Các khung khác nhau có các quy ước khác nhau (ví dụ (actual, expected) or an agnostic (trái, phải) `), nhưng theo kinh nghiệm của tôi, đó hầu như là một nguồn gây nhầm lẫn nhỏ.
amon

5
Bởi vì lợi ích là rất nhỏ, so với lợi ích của nó, mà bất kỳ ai lành mạnh có thể sẽ bỏ đi. Nếu bạn muốn một cách tiếp cận trôi chảy hơn, bạn nên thử assert(a).toEqual(b)(ngay cả khi IMO, nó vẫn không cần thiết phải dài dòng), nơi bạn có thể xâu chuỗi một vài xác nhận liên quan.
Adriano Repetti

18
Làm thế nào để chúng ta biết rằng thực tế và dự kiến ​​là giá trị? Chắc chắn là nó phải assertExpectedValueEqualsActualValuekhông? Nhưng chờ đã, làm thế nào để chúng ta nhớ liệu nó sử dụng ==hay .equalshay Object.equals? Có nên assertExpectedValueEqualsMethodReturnsTrueWithActualValueParameterkhông?
dùng253751

6
Cho rằng, đối với phương pháp cụ thể này, thứ tự của hai đối số không thành vấn đề, có vẻ như là một ví dụ tồi để chọn tán thành lợi ích của sơ đồ đặt tên này.
Steven Rands

Câu trả lời:


66

Bởi vì nó là nhiều hơn để gõ và nhiều hơn để đọc

Lý do đơn giản nhất là mọi người thích gõ ít hơn và mã hóa thông tin đó có nghĩa là gõ nhiều hơn. Khi đọc nó, mỗi khi tôi phải đọc toàn bộ ngay cả khi tôi đã quen với thứ tự của các đối số nên là gì. Ngay cả khi không quen thuộc với thứ tự lập luận ...

Nhiều nhà phát triển sử dụng IDE

IDE thường cung cấp một cơ chế để xem tài liệu cho một phương thức nhất định bằng cách di chuột hoặc qua một phím tắt. Bởi vì điều này, tên của các tham số luôn trong tầm tay.

Mã hóa các đối số giới thiệu trùng lặp và khớp nối

Tên của các tham số nên ghi lại chúng là gì. Bằng cách viết tên trong tên phương thức, chúng tôi cũng đang sao chép thông tin đó trong chữ ký phương thức. Chúng tôi cũng tạo ra một khớp nối giữa tên phương thức và các tham số. Nói expectedactualgây nhầm lẫn cho người dùng của chúng tôi. Đi từ assertEquals(expected, actual)đến assertEquals(planned, real)không yêu cầu thay đổi mã máy khách bằng cách sử dụng chức năng. Đi từ assertExpectedEqualsActual(expected, actual)đến assertPlannedEqualsReal(planned, real)có nghĩa là một sự thay đổi đột phá đối với API. Hoặc chúng ta không thay đổi tên phương thức, điều này nhanh chóng trở nên khó hiểu.

Sử dụng các loại thay vì các đối số mơ hồ

Vấn đề thực sự là chúng ta có những lý lẽ mơ hồ dễ dàng chuyển đổi vì chúng cùng loại. Thay vào đó, chúng ta có thể sử dụng hệ thống loại và trình biên dịch của mình để thực thi đúng thứ tự:

class Expected<T> {
    private T value;
    Expected(T value) { this.value = value; }
    static Expected<T> is(T value) { return new Expected<T>(value); }
}

class Actual<T> {
    private T value;
    Actual(T value) { this.value = value; }
    static Actual<T> is(T value) { return new Actual<T>(value); }
}

static assertEquals(Expected<T> expected, Actual<T> actual) { /* ... */ }

// How it is used
assertEquals(Expected.is(10), Actual.is(x));

Điều này sau đó có thể được thi hành ở cấp độ trình biên dịch và đảm bảo rằng bạn không thể đưa chúng ngược lại. Tiếp cận từ một góc độ khác, đây thực chất là những gì thư viện Hamcrest làm cho các bài kiểm tra.


5
Chà, nếu bạn sử dụng một IDE, bạn có tên tham số trong bóng trợ giúp; nếu bạn không sử dụng một, việc nhớ tên hàm tương đương với việc nhớ các đối số, vì vậy không có gì đạt được cả.
Peter - Tái lập Monica

29
Nếu bạn phản đối assertExpectedEqualsActual"vì nó nhiều hơn để gõ và nhiều hơn để đọc", thì làm thế nào bạn có thể ủng hộ assertEquals(Expected.is(10), Actual.is(x))?
ruakh

9
@ruakh không thể so sánh được. assertExpectedEqualsActualvẫn yêu cầu lập trình viên quan tâm để xác định các đối số theo đúng thứ tự. Các assertEquals(Expected<T> expected, Actual<T> actual)chữ ký sử dụng trình biên dịch để thực thi việc sử dụng đúng, đó là một cách tiếp cận hoàn toàn khác nhau. Bạn có thể tối ưu hóa cách tiếp cận này cho ngắn gọn, ví dụ expect(10).equalsActual(x), nhưng đó không phải là câu hỏi
LỚN

6
Ngoài ra, trong trường hợp cụ thể này (==), thứ tự của các đối số thực sự không liên quan đến giá trị cuối cùng. Thứ tự chỉ quan trọng đối với một tác dụng phụ (báo cáo sự thất bại). Khi đặt hàng vấn đề, nó có thể làm cho (bên lề) có ý nghĩa hơn. Ví dụ strcpy (mệnh, src).
Kristian H

1
Không thể đồng ý nhiều hơn, đặc biệt là với phần trùng lặp và ghép nối ... Nếu mỗi khi tham số hàm thay đổi tên, tên hàm cũng sẽ phải thay đổi, bạn phải theo dõi tất cả các cách sử dụng hàm đó và cũng thay đổi chúng ... Điều đó sẽ tạo ra một khối lượng lớn các thay đổi cho tôi, nhóm của tôi và tất cả những người khác sử dụng mã của chúng tôi làm phụ thuộc ...
mrsmn

20

Bạn hỏi về một cuộc tranh luận lâu dài trong lập trình. Bao nhiêu là dài dòng là tốt? Như một câu trả lời chung, các nhà phát triển đã nhận thấy rằng tính dài dòng thêm vào việc đặt tên cho các đối số là không xứng đáng.

Độ dài không phải lúc nào cũng có nghĩa là rõ ràng hơn. Xem xét

copyFromSourceStreamToDestinationStreamWithoutBlocking(fileStreamFromChoosePreferredOutputDialog, heuristicallyDecidedSourceFileHandle)

đấu với

copy(output, source)

Cả hai đều chứa cùng một lỗi, nhưng chúng ta có thực sự làm cho việc tìm lỗi đó dễ dàng hơn không? Theo nguyên tắc chung, điều dễ dàng nhất để gỡ lỗi là khi mọi thứ đều cực kỳ ngắn gọn, ngoại trừ một vài điều có lỗi và những điều đó đủ dài để nói cho bạn biết điều gì đã xảy ra.

Có một lịch sử lâu dài về việc thêm tính dài dòng. Ví dụ, có " ký hiệu Hungary " không phổ biến đã cho chúng ta những cái tên tuyệt vời như thế lpszName. Điều đó nói chung đã giảm bởi các bên trong cộng đồng lập trình viên nói chung. Tuy nhiên, việc thêm ký tự vào tên biến thành viên (như mNamehoặc m_Namehoặc name_) tiếp tục phổ biến trong một số vòng kết nối. Những người khác đã bỏ nó hoàn toàn. Tôi tình cờ làm việc trên một cơ sở mã mô phỏng vật lý có tài liệu kiểu mã hóa yêu cầu bất kỳ hàm nào trả về một vectơ phải chỉ định khung của vectơ trong lệnh gọi hàm ( getPositionECEF).

Bạn có thể quan tâm đến một số ngôn ngữ được Apple phổ biến. Objective-C bao gồm các tên đối số như là một phần của chữ ký hàm (Hàm [atm withdrawFundsFrom: account usingPin: userProvidedPin]được viết trong tài liệu là withdrawFundsFrom:usingPin:. Đó là tên của hàm). Swift đã đưa ra một tập hợp các quyết định tương tự, yêu cầu bạn đặt các tên đối số trong các lệnh gọi hàm ( greet(person: "Bob", day: "Tuesday")).


13
Tất cả các điểm khác sang một bên, điều đó sẽ dễ đọc hơn nhiều nếu copyFromSourceStreamToDestinationStreamWithoutBlocking(fileStreamFromChoosePreferredOutputDialog, heuristicallyDecidedSourceFileHandle)được viết copy_from_source_stream_to_destination_stream_without_blocking(file_stream_from_choose_preferred_output_dialog, heuristically_decided_source_file_handle). Xem nó dễ hơn bao nhiêu ?! Đó là bởi vì quá dễ dàng để bỏ lỡ những thay đổi nhỏ giữa chừng mà humungousunbrokenwordsalad, và phải mất nhiều thời gian hơn để tìm ra ranh giới từ ở đâu. Đập vỡ nhầm lẫn.
tchrist

1
Cú pháp obj-C withdrawFundsFrom: account usingPin: userProvidedPinthực sự được mượn từ SmallTalk.
joH1

14
@tchrist hãy cẩn thận với việc chắc chắn bạn đúng về các chủ đề liên quan đến thánh chiến. Mặt khác không phải lúc nào cũng sai.
Cort Ammon

3
@tchrist Addingunderscoresnakesthingseasiertoreadnotharderasyouseeđang thao túng lập luận. Câu trả lời ở đây được sử dụng viết hoa, mà bạn đang bỏ qua. AddingCapitalizationMakesThingsEasyEnoughToReadAsYouCanSeeHere. Thứ hai, 9 lần trong số 10, một tên không bao giờ nên vượt quá [verb][adjective][noun](trong đó mỗi khối là tùy chọn), một định dạng có thể đọc được bằng cách sử dụng viết hoa đơn giản:ReadSimpleName
Flater

5
@tchrist - khoa học về nghiên cứu của bạn ( liên kết toàn văn miễn phí ) chỉ đơn giản cho thấy các lập trình viên được đào tạo để sử dụng kiểu gạch dưới nhanh hơn trong việc đọc kiểu gạch dưới so với trường hợp lạc đà. Dữ liệu cũng cho thấy sự khác biệt nhỏ hơn đối với các đối tượng có nhiều kinh nghiệm hơn (và hầu hết các đối tượng là sinh viên cho rằng ngay cả những đối tượng có khả năng không đặc biệt có kinh nghiệm). Điều này không có nghĩa là các lập trình viên đã dành nhiều thời gian sử dụng vỏ lạc đà cũng sẽ cho kết quả tương tự.
Jules

8

Tác giả của "Clean Code" chỉ ra một vấn đề hợp pháp, nhưng giải pháp được đề xuất của ông là không phù hợp. Thường có những cách tốt hơn để cải thiện tên phương thức không rõ ràng.

Anh ta đúng rằng assertEquals(từ các thư viện kiểm tra đơn vị kiểu xUnit) không làm rõ đối số nào là mong đợi và thực tế nào. Cái này cũng cắn tôi! Nhiều thư viện kiểm thử đơn vị đã lưu ý vấn đề và đã đưa ra các cú pháp thay thế, như:

actual.Should().Be(expected);

Hoặc tương tự. Mà chắc chắn là rõ ràng hơn nhiều assertEqualsnhưng cũng tốt hơn nhiều assertExpectedEqualsActual. Và nó cũng là nhiều composable hơn.


1
Tôi là hậu môn và tôi làm theo thứ tự được đề nghị nhưng dường như với tôi rằng nếu tôi mong đợi kết quả fun(x)là 5 thì điều gì có thể sai nếu đảo ngược thứ tự - assert(fun(x), 5)? Làm thế nào mà nó cắn bạn?
emory

3
@emory Tôi biết jUnit (ít nhất) xây dựng một thông báo lỗi từ các giá trị của expectedactualvì vậy việc đảo ngược chúng có thể dẫn đến một thông báo không chính xác. Nhưng tôi đồng ý rằng nó nghe có vẻ tự nhiên hơn :)
joH1

@ joH1 có vẻ yếu với tôi. mã thất bại sẽ thất bại và việc chuyển mã sẽ vượt qua cho dù bạn làm assert(expected, observed)hay assert(observed, expected). Một ví dụ tốt hơn sẽ là một cái gì đó như locateLatitudeLongitude- nếu bạn đảo ngược tọa độ, nó sẽ gây rối nghiêm trọng.
emory

1
@emory Những người không quan tâm đến các thông báo lỗi hợp lý trong các bài kiểm tra đơn vị là lý do tại sao tôi phải xử lý "Assert.IsTrue không thành công" trong một số cơ sở mã cũ. Đó là niềm vui to lớn để gỡ lỗi. Nhưng có trong trường hợp này, vấn đề có thể không quan trọng (trừ khi chúng ta so sánh mờ trong đó thứ tự các đối số thường có vấn đề). Xác nhận thông thạo thực sự là một cách tuyệt vời để tránh vấn đề này và cũng làm cho cách mã trở nên biểu cảm hơn (và cung cấp thông báo lỗi tốt hơn nhiều để khởi động).
Voo

@emory: Đảo ngược đối số sẽ làm cho các thông báo lỗi gây hiểu lầm và đưa bạn xuống đường dẫn sai khi gỡ lỗi.
JacquesB

5

Bạn đang cố gắng điều khiển con đường của mình giữa Scylla và Charybdis trở nên rõ ràng, cố gắng tránh sự dài dòng vô dụng (còn được gọi là lan man vô mục đích) cũng như sự ngắn gọn quá mức (còn được gọi là sự khó hiểu về mật mã).

Vì vậy, chúng ta phải xem xét giao diện mà bạn muốn đánh giá, một cách để thực hiện các xác nhận gỡ lỗi rằng hai đối tượng bằng nhau.

  1. Có bất kỳ chức năng nào khác mà nó có thể được xem xét arity và tên?
    Không, vì vậy tên của nó là đủ rõ ràng.
  2. Là các loại có ý nghĩa?
    Không, vì vậy hãy bỏ qua chúng. Bạn đã làm điều đó chưa? Tốt
  3. Là nó đối xứng trong các đối số của nó?
    Gần như, về lỗi, thông báo đặt mỗi đại diện đối số vào vị trí của riêng họ.

Vì vậy, hãy xem liệu sự khác biệt nhỏ đó có ý nghĩa gì không, và không được bao hàm bởi các quy ước mạnh mẽ hiện có.

Là khán giả dự định bất tiện nếu các đối số được trao đổi vô tình?
Không, các nhà phát triển cũng có được một stack-track và họ phải xem xét kỹ lưỡng mã nguồn để sửa lỗi.
Ngay cả khi không có dấu vết ngăn xếp đầy đủ, vị trí xác nhận sẽ giải quyết câu hỏi đó. Và nếu thậm chí còn thiếu và không rõ ràng từ thông điệp đó là gì, thì nhiều nhất nó sẽ nhân đôi khả năng.

Liệu các đối số có tuân theo quy ước?
Có vẻ là trường hợp. Mặc dù có vẻ như tốt nhất là một quy ước yếu.

Do đó, sự khác biệt trông khá không đáng kể và thứ tự đối số được bao phủ bởi quy ước đủ mạnh đến mức mọi nỗ lực để mã hóa nó vào tên hàm có tiện ích âm.


cũng thứ tự có thể quan trọng với jUnit, nó xây dựng một thông báo lỗi cụ thể từ các giá trị của expectedactual(ít nhất là với Chuỗi)
joH1

Tôi nghĩ rằng tôi đã bao gồm phần đó ...
Ded repeatator

bạn đề cập đến nó nhưng xem xét: assertEquals("foo", "doo")cung cấp cho các thông báo lỗi là ComparisonFailure: expected:<[f]oo> but was:<[d]oo>... Việc trao đổi các giá trị sẽ đảo ngược ý nghĩa của thông điệp, rằng âm thanh hơn chống đối xứng với tôi. Dù sao như bạn đã nói, một nhà phát triển có các chỉ số khác để khắc phục lỗi, nhưng nó có thể gây hiểu lầm cho IMHO và mất thêm một chút thời gian gỡ lỗi.
joH1

Ý tưởng rằng có một "quy ước" cho các lệnh đối số là buồn cười, vì cả hai phe (mệnh, src so với src, mệnh) đã tranh luận về điều này ít nhất là với cú pháp AT & T so với Intel đã tồn tại. Và các thông báo lỗi không có ích trong các bài kiểm tra đơn vị là một bệnh dịch nên được loại bỏ không được thi hành. Điều đó cũng tệ như "Assert.IsTrue fail" ("hey bạn phải thực hiện kiểm tra đơn vị bằng mọi cách để gỡ lỗi, vì vậy chỉ cần chạy lại và đặt điểm dừng ở đó", "dù sao bạn cũng phải xem mã chỉ cần kiểm tra xem thứ tự có đúng không ").
Voo

@Voo: Vấn đề là "thiệt hại" khi hiểu sai là rất nhỏ (logic không phụ thuộc vào nó và tiện ích tin nhắn không bị suy giảm ở bất kỳ mức độ đáng kể nào) và khi viết IDE sẽ hiển thị cho bạn tên tham số và gõ bằng mọi cách.
Ded repeatator

3

Thường thì nó không thêm bất kỳ sự rõ ràng logic nào.

So sánh "Thêm" với "AddFirstArgumentToSecondArgument".

Nếu bạn cần một sự quá tải đó, giả sử, thêm ba giá trị. Điều gì sẽ có ý nghĩa hơn?

Một "Thêm" với ba đối số?

hoặc là

"AddFirstAndSecondAndThirdArgument"?

Tên của phương thức nên truyền đạt ý nghĩa logic của nó. Nó sẽ nói những gì nó làm. Nói, ở cấp độ vi mô, những bước cần thực hiện không giúp người đọc dễ dàng hơn. Tên của các đối số sẽ cung cấp thêm chi tiết nếu cần. Nếu bạn cần thêm chi tiết, mã sẽ ở ngay đó cho bạn.


4
Addđề nghị một hoạt động giao hoán. OP quan tâm đến các tình huống trong đó có vấn đề.
Rosie F

Trong Swift, ví dụ, bạn sẽ gọi add (5, to: x) hoặc add (5, plus: 7, to: x) hoặc add (5, plus: 7, give: x) nếu bạn xác định hàm add () phù hợp.
gnasher729

Quá tải thứ ba nên được đặt tên là "Tổng"
StingyJack

@StringyJack Hmm .. Sum không phải là một hướng dẫn, nó là một danh từ làm cho nó không phù hợp với tên phương thức. Nhưng nếu bạn cảm thấy như vậy và Nếu bạn muốn trở thành một người theo chủ nghĩa thuần túy về nó, hai phiên bản đối số cũng nên được đặt tên là Sum. Nếu bạn có một phương thức Add, nó sẽ có một đối số được thêm vào chính thể hiện đối tượng (sẽ phải là một kiểu số hoặc vectơ). 2 hoặc nhiều loại đối số (bất cứ điều gì bạn đặt tên cho chúng) sẽ là tĩnh. Sau đó, 3 phiên bản đối số trở lên sẽ là dự phòng và chúng tôi đã triển khai toán tử cộng: - |
Martin Maat

1
@Martin Chờ gì? sumlà một động từ hoàn hảo cromulent . Nó đặc biệt phổ biến trong cụm từ "tổng hợp".
Voo

2

Tôi muốn thêm một cái gì đó được gợi ý bởi các câu trả lời khác, nhưng tôi không nghĩ đã được đề cập rõ ràng:

@puck nói "Vẫn không có gì đảm bảo đối số được đề cập đầu tiên trong tên hàm thực sự là tham số đầu tiên."

@cbojar nói "Sử dụng các loại thay vì các đối số mơ hồ"

Vấn đề là ngôn ngữ lập trình không hiểu tên: chúng chỉ được coi là biểu tượng nguyên tử mờ đục. Do đó, giống như với các nhận xét mã, không nhất thiết có bất kỳ mối tương quan nào giữa chức năng được đặt tên và cách thức hoạt động của nó.

So sánh assertExpectedEqualsActual(foo, bar)với một số lựa chọn thay thế (từ trang này và các nơi khác), như:

# Putting the arguments in a labelled structure
assertEquals({expected: foo, actual: bar})

# Using a keyword arguments language feature
assertEquals(expected=foo, actual=bar)

# Giving the arguments different types, forcing us to wrap them
assertEquals(Expected(foo), Actual(bar))

# Breaking the symmetry and attaching the code to one of the arguments
bar.Should().Be(foo)

Tất cả đều có cấu trúc nhiều hơn tên verbose, mang lại cho ngôn ngữ một cái gì đó không mờ đục để xem xét. Định nghĩa và cách sử dụng của hàm cũng phụ thuộc vào cấu trúc này, do đó, nó không thể không đồng bộ với những gì triển khai đang thực hiện (như tên hoặc bình luận có thể).

Khi tôi gặp phải hoặc thấy trước một vấn đề như thế này, trước khi tôi hét vào máy tính của mình trong sự thất vọng, trước tiên tôi dành một chút thời gian để hỏi liệu có công bằng không khi đổ lỗi cho máy. Nói cách khác, máy có được cung cấp đủ thông tin để phân biệt thứ tôi muốn với thứ tôi yêu cầu không?

Một cuộc gọi như assertEqual(expected, actual)có ý nghĩa nhiều như assertEqual(actual, expected)vậy, vì vậy chúng ta dễ dàng khiến chúng bị lẫn lộn để máy cày trước và làm sai. Nếu chúng ta sử dụng assertExpectedEqualsActualthay thế, nó có thể khiến chúng ta ít mắc lỗi hơn, nhưng nó không cung cấp thêm thông tin cho máy (nó không thể hiểu tiếng Anh và việc chọn tên sẽ không ảnh hưởng đến ngữ nghĩa).

Điều làm cho các cách tiếp cận "có cấu trúc" được ưa thích hơn, như đối số từ khóa, trường được gắn nhãn, loại khác biệt, v.v. là thông tin bổ sung cũng có thể đọc được bằng máy , vì vậy chúng ta có thể phát hiện ra cách sử dụng máy không chính xác và giúp chúng ta làm đúng. Các assertEqualtrường hợp không phải là quá xấu, vì vấn đề duy nhất là thông điệp không chính xác. Một ví dụ độc ác hơn có thể là String replace(String old, String new, String content), dễ nhầm lẫn với String replace(String content, String old, String new)nó có một ý nghĩa rất khác nhau. Một biện pháp khắc phục đơn giản là lấy một cặp [old, new], điều này sẽ gây ra lỗi gây ra lỗi ngay lập tức (ngay cả khi không có loại).

Lưu ý rằng ngay cả với các loại, chúng tôi có thể thấy mình không 'nói với máy những gì chúng tôi muốn'. Ví dụ, mô hình chống được gọi là "lập trình gõ chuỗi" coi tất cả dữ liệu là chuỗi, giúp dễ dàng có được các đối số lẫn lộn (như trường hợp này), để quên thực hiện một số bước (ví dụ: thoát), để vô tình phá vỡ bất biến (ví dụ: làm cho JSON không thể nhìn thấy), v.v.

Điều này cũng liên quan đến "mù boolean", trong đó chúng tôi tính toán một loạt các booleans (hoặc số, v.v.) trong một phần của mã, nhưng khi cố gắng sử dụng chúng trong một phần khác, chúng không rõ chúng thực sự đại diện cho cái gì chúng tôi đã có họ trộn lên, vv Hãy so sánh này để ví dụ như sự đếm riêng biệt có tên mô tả (ví dụ LOGGING_DISABLEDchứ không phải false) và gây một thông báo lỗi nếu chúng tôi nhận được chúng lẫn lộn.


1

bởi vì nó loại bỏ sự cần thiết phải nhớ nơi các đối số đi

Có thật không? Vẫn không có gì đảm bảo đối số được đề cập đầu tiên trong tên hàm thực sự là tham số đầu tiên. Vì vậy, tốt hơn nên tìm kiếm nó (hoặc để IDE của bạn làm điều đó) và ở lại với tên hợp lý hơn là mù quáng dựa vào một cái tên khá ngớ ngẩn.

Nếu bạn đọc mã, bạn sẽ dễ dàng thấy điều gì xảy ra khi các tham số được đặt tên như mong muốn. copy(source, destination)là dễ hiểu hơn nhiều so với những thứ như vậy copyFromTheFirstLocationToTheSecondLocation(placeA, placeB).

Tại sao các lập trình viên không chấp nhận cái trước nếu như, như tác giả khẳng định, rõ ràng hơn cái sau?

Bởi vì có nhiều quan điểm khác nhau về các phong cách khác nhau và bạn có thể tìm thấy x tác giả của các bài viết khác nói ngược lại. Bạn sẽ phát điên khi cố gắng làm theo mọi thứ mà ai đó viết ở đâu đó ;-)


0

Tôi đồng ý rằng mã hóa tên tham số thành tên hàm làm cho việc viết và sử dụng các hàm trực quan hơn.

copyFromSourceToDestination( // "...ahh yes, the source directory goes first"

Thật dễ dàng để quên thứ tự của các đối số trong các hàm và các lệnh shell và nhiều lập trình viên dựa vào các tính năng IDE hoặc tham chiếu hàm vì lý do này. Có các đối số được mô tả trong tên sẽ là một giải pháp hùng hồn cho sự phụ thuộc này.

Tuy nhiên, một khi được viết, việc mô tả các đối số sẽ trở thành lỗi cho người lập trình tiếp theo phải đọc câu lệnh, vì trong hầu hết các trường hợp, các biến được đặt tên sẽ được sử dụng.

copy(sourceDir, destinationDir); // "...makes sense"

Sự căng thẳng của điều này sẽ chiến thắng hầu hết các lập trình viên và cá nhân tôi thấy nó dễ đọc hơn.

EDIT: Như @Blrfl đã chỉ ra, các tham số mã hóa không phải là 'trực quan' vì bạn cần phải nhớ tên của hàm ở vị trí đầu tiên. Điều này đòi hỏi phải tra cứu các tham chiếu chức năng hoặc nhận trợ giúp từ IDE có khả năng sẽ cung cấp thông tin đặt hàng tham số.


9
Vì vậy, nếu tôi có thể chơi người ủng hộ của quỷ trong một phút: Nó chỉ trực quan khi bạn biết tên đầy đủ của chức năng. Nếu bạn biết có chức năng sao chép và bạn không nhớ là nó copyFromSourceToDestinationhay copyToDestinationFromSource, các lựa chọn của bạn đang tìm kiếm nó bằng cách dùng thử và lỗi hoặc đọc tài liệu tham khảo. IDE có thể hoàn thành tên một phần chỉ là phiên bản tự động của cái sau.
Blrfl

@Blrfl Điểm gọi của nó copyFromSourceToDestinationlà nếu bạn nghĩ nó copyToDestinationFromSource, trình biên dịch sẽ tìm thấy lỗi của bạn, nhưng nếu nó được gọi copy, nó sẽ không. Bắt các tham số của thói quen sao chép không đúng cách là dễ dàng, vì strcpy, strcat, v.v. đã tạo tiền lệ. Và là một terse dễ đọc hơn? Hợp nhấtLists (listA, listB, listC) có tạo listA từ listB & listC, hoặc đọc listA & listB và viết listC không?
Rosie F

4
@RosieF Nếu tôi không tích cực về ý nghĩa của các đối số, tôi sẽ đọc tài liệu trước khi viết mã. Bên cạnh đó, ngay cả với các tên hàm dài hơn, vẫn còn chỗ để giải thích về thứ tự thực sự là gì. Ai đó có cái nhìn lạnh lùng về mã sẽ không thể hiểu được rằng bạn đã thiết lập quy ước rằng những gì trong tên hàm phản ánh thứ tự của các đối số. Họ vẫn phải biết trước hoặc đọc tài liệu.
Blrfl

OTOH, DestinationDir.copy (sourceDir); // "... có ý nghĩa hơn"
Kristian H

1
@KristianH Hướng nào dir1.copy(dir2)làm việc? Không ý kiến. Thế còn dir1.copyTo(dir2)?
maaartinus
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.