Có phải sự đơn giản luôn cải thiện khả năng đọc?


32

Gần đây, tôi đang phát triển một bộ tiêu chuẩn mã hóa cho công ty chúng tôi. (Chúng tôi là một nhóm mới phân nhánh sang một ngôn ngữ mới cho công ty.)

Trong dự thảo đầu tiên của mình, tôi đặt mục đích của các tiêu chuẩn mã hóa của chúng tôi là cải thiện Khả năng đọc, Khả năng duy trì, Độ tin cậy và Hiệu suất. (Tôi bỏ qua khả năng ghi, tính di động, chi phí, khả năng tương thích với các tiêu chuẩn trước đó, v.v.)

Một trong những mục tiêu của tôi khi viết tài liệu này là đưa ra ý tưởng về tính đơn giản của mã. Ý tưởng là chỉ nên có một chức năng gọi hoặc hoạt động trên mỗi dòng. Hy vọng của tôi là điều này sẽ tăng khả năng đọc. Đó là một ý tưởng mà tôi đã thực hiện từ ngôn ngữ trước đây của chúng tôi.

Tuy nhiên, tôi đã đặt câu hỏi về giả định đằng sau cú hích này:

Có phải sự đơn giản luôn cải thiện khả năng đọc?

Có trường hợp viết mã đơn giản hơn làm giảm khả năng đọc?

Điều này là hiển nhiên, nhưng bằng cách "đơn giản hơn", tôi không có nghĩa là "dễ viết hơn", nhưng ít thứ đang diễn ra trên mỗi dòng.


16
Nếu thay thế là mã "thông minh", thì có ...
Oded

2
có - mỗi Occam's Razor - en.wikipedia.org/wiki/Occam%27s_razor
aggietech

17
Cố gắng tránh sử dụng các thuật ngữ cứng nhắc như mọi khi và không bao giờ. Điều này là để tránh tập trung vào các trường hợp cạnh và thay vào đó tập trung vào các vấn đề phổ biến nhất mà chúng ta gặp phải. Đây là những gì thực hành tốt nhất là tất cả về.
P.Brian.Mackey

thực tế, bạn muốn 2 chức năng / hoạt động trên mỗi dòng. a = blà một hoạt động, b + clà một hoạt động thứ hai, có nghĩa a = b + clà 2 hoạt động. Chuỗi 2 hàm / toán tử vẫn có thể đọc được : foo(bar()), hoặc a = foo().
zzzzBov

2
Ngoài ra, đừng quá lo lắng. Nếu bạn cố gắng loại bỏ mọi sự chủ quan khỏi những giải thích của mình, giống như nếu bạn cố gắng chỉ định mọi chi tiết có thể có của kiểu mã hóa trong một triệu quy tắc trở lên, các tiêu chuẩn của bạn sẽ bị phản ứng thái quá, không thể đọc được, bị bỏ qua và do đó là vô nghĩa.
Steve314

Câu trả lời:


47

"Đơn giản" là một từ được sử dụng quá mức. "Có thể đọc" có thể được định nghĩa một cách có lợi là "đơn giản để hiểu", trong trường hợp tăng (đơn vị đo lường) này theo định nghĩa sẽ tăng khả năng đọc, nhưng tôi không nghĩ đây là ý của bạn. Tôi đã viết về điều này ở nơi khác , nhưng nói chung một cái gì đó có thể được gọi là "đơn giản hơn" bằng cách trừu tượng hơn (trong trường hợp ít khái niệm có thể biểu hiện nhiều hiện tượng hơn) hoặc bằng cách cụ thể hơn (trong trường hợp đó, một khái niệm không đòi hỏi nhiều nền tảng kiến thức để hiểu ở nơi đầu tiên). Tôi cho rằng, tùy theo quan điểm, một khái niệm trừu tượng hơn có thể được gọi đơn giản hơn là một khái niệm cụ thể hơn, hoặc ngược lại . Điều này, mặc dù "trừu tượng" và "

Tôi sẽ sử dụng như một ví dụ về một số mã Haskell mà tôi đã viết cách đây một thời gian. Tôi đã hỏi một câu hỏi về stackoverflow về việc sử dụng danh sách đơn vị để tính toán một bộ đếm trong đó mỗi chữ số có thể có một cơ sở khác nhau. Giải pháp cuối cùng của tôi (không biết nhiều về Haskell) trông giống như:

count :: [Integer] -> [[Integer]]
count [] = [[]]
count (x:xs) =
  -- get all possible sequences for the remaining digits
  let
    remDigits :: [[Integer]]
    remDigits = count xs
  in
  -- pull out a possible sequence for the remaining digits
  do nextDigits <- remDigits
     -- pull out all possible values for the current digit
     y <- [0..x]
     -- record that "current digit" : "remaining digits" is
     -- a valid output.
     return (y:nextDigits)

Một trong những câu trả lời đã giảm điều này thành:

count = mapM (enumFromTo 0)

Cái nào trong số này là "đơn giản" hơn để hiểu (nghĩa là dễ đọc hơn) phụ thuộc hoàn toàn vào việc người đọc cảm thấy thoải mái như thế nào với các hoạt động đơn điệu (trừu tượng) (và, đối với vấn đề đó, mã không có điểm). Một người đọc rất thoải mái với các khái niệm trừu tượng này sẽ thích đọc phiên bản trừu tượng hơn (ngắn), trong khi một người không thoải mái với các hoạt động đó sẽ thích đọc phiên bản cụ thể hơn (dài). Không có câu trả lời về phiên bản nào dễ đọc hơn cho mọi người.


11
Một số nhà phát triển sẽ tiến triển cho đến khi họ hiểu và thích một lớp lót. Khó có thể tưởng tượng một nhà phát triển hiểu được một lớp lót sẽ thích phiên bản dài hơn. Do đó IMO một lớp lót rõ ràng là tốt hơn.
kevin cline

7
@kevincline - giả sử nhà phát triển làm việc riêng rẽ, tôi đồng ý, phiên bản ngắn hơn (có thể) tốt hơn. Nếu cô ấy làm việc như một phần của một nhóm và nhóm đó không ở cấp độ mà họ hiểu và thích một lớp lót, và tất cả họ phải có khả năng duy trì mã, thì phiên bản dài sẽ tốt hơn trong trường hợp đó .
Aidan Cully

6
Như một phản biện: cho rằng bạn là một Haskeller có kinh nghiệm, bạn có thể đọc phiên bản thứ hai trong nháy mắt. Phiên bản đầu tiên, mặt khác, sẽ yêu cầu đọc và hiểu mã nhiều hơn đáng kể; bạn không thể làm điều đó trong nháy mắt. Tôi nghĩ rằng làm cho phiên bản thứ hai đơn giản hơn.
Tikhon Jelvis

6
@ Steve314: mapMlà thành ngữ khá, và enumFromTothực hiện chính xác những gì nó nói trên tin. Nói chung, tôi thấy thực sự dễ mắc lỗi hơn nếu bạn mở rộng mã ra - đơn giản là có nhiều mã hơn để mắc lỗi. Điều này đặc biệt rõ ràng với những điều như vòng lặp so với thủ tục bậc cao trong các ngôn ngữ khác , nhưng tôi thấy đó là một nguyên tắc chung.
Tikhon Jelvis

1
@Tikhon - nhưng điều đó không nhất thiết có nghĩa là đọc nhiều mã đó và mã ở ngay đó. Có nghĩa là có thể có một sự đánh đổi. Thông thường rất nhiều về một phía ủng hộ việc sử dụng các chức năng hiện có thay vì phát minh lại bánh xe, nhưng vẫn có trường hợp ngoại lệ. Điều này trở nên rất rõ ràng trong C ++, với một số "thuật toán" tầm thường hơn trong thư viện tiêu chuẩn - đôi khi sử dụng chúng có thể dài dòng hơn và ít rõ ràng hơn khi viết mã trực tiếp.
Steve314

13

Nếu tiêu chuẩn mã hóa của bạn là về "Khả năng đọc, Khả năng duy trì, Độ tin cậy và Hiệu suất" thì hãy nêu điều đó .

Đừng cố gắng và quy định làm thế nào để đạt được những điều này vì sẽ luôn có những tình huống có một ví dụ phản biện.

Những gì bạn cần phải kê đơn là những thứ sẽ khiến mã bị phá vỡ nếu không được tuân thủ quá. Các đặc điểm phong cách sẽ không phá vỡ mã và phải là đề xuất (miễn là phần lớn nhóm đồng ý rằng Khả năng đọc còn lại là tùy chọn của nhà phát triển (với đánh giá mã để áp lực ngang hàng nhắc nhở mọi người rằng người khác cần đọc mã)) .


Đó là mục tiêu mà tôi nhắm đến và đó là đối tượng đã nêu. Đơn giản (hay đúng hơn, một chức năng / hoạt động trên mỗi dòng) dường như tự nhiên đi theo mục tiêu đó. Tôi đang cố xác định xem sự hiểu biết của tôi có hợp lệ không. Khi bạn đang xây dựng một tiêu chuẩn mã hóa, thiết lập một bộ quy tắc và hướng dẫn là toàn bộ vấn đề của bài tập. Đặt quy tắc và hướng dẫn quá mơ hồ là vô ích. Như vậy, câu trả lời này thực sự không có ích.
Richard

5
Lập luận của tôi là việc thiết lập các quy tắc quá nghiêm ngặt sẽ tệ hơn vô dụng và thực sự có hại. Đặt quy tắc như một tuyên bố trên mỗi dòng là phong cách. Đây là điều chắc chắn KHÔNG nên có trong hướng dẫn mã. Nó cung cấp lợi ích không thực tế và có thể gây hại cho khả năng đọc và bảo trì nếu được áp dụng mà không cần suy nghĩ.
Martin York

3
+1 (vì tôi không thể +10) Một lỗi phổ biến tôi thấy với các nhà quản lý lập trình mới là họ cố gắng mã hóa mọi chi tiết cuối cùng. Các tiêu chuẩn mã hóa tốt nhất giống như bánh quy may mắn hơn là công thức nấu ăn.
JohnFx

"Phong cách và tiêu chuẩn mã hóa" là tên của tài liệu. Rõ ràng đây không phải là một tiêu chuẩn (như trong "Không bao giờ sử dụng GoTo" hoặc "Không bao giờ sử dụng ints ngắn") mà là một phong cách. Phong cách thống nhất là quan trọng để dễ đọc và duy trì.
Richard

1
Hướng dẫn về Phong cách: "Dự án này sử dụng các tab / dấu cách (chọn một). Dự án này sử dụng kiểu dấu ngoặc K & R / Allman / BSD / GNU (chọn một). Vui lòng không thêm khoảng trắng ở cuối dòng. Vui lòng giữ lại Mọi thứ sẽ là mã được xem xét bởi hai thành viên trong nhóm và chính bạn: để dễ đọc / bảo trì, bạn cần đa số 2/3 để kiểm tra mã, về Độ tin cậy và Hiệu suất bạn cần 3/3 (Vui lòng cung cấp các bài kiểm tra phù hợp để chứng minh ). Nhiều quy tắc sẽ được thêm vào nếu những điều này bị lạm dụng :-) "Xong.
Martin York

7

Ít "công cụ trên mỗi dòng", đơn giản và dễ đọc không giống nhau. Người ta có thể sử dụng một thuật toán không có giấy tờ khó hiểu vô cùng phức tạp và mã hóa nó bằng 1 câu lệnh trên mỗi dòng thay vì 2, và nó sẽ không trở nên dễ đọc hơn nhiều.

Ít "công cụ trên mỗi dòng" cũng có thể yêu cầu các nhà phát triển cung cấp màn hình lớn rất lớn để thấy các khối mã giờ được trải rộng hơn theo chiều dọc. Hoặc gây căng thẳng mắt từ việc đọc phông chữ nhỏ hơn.

Khả năng đọc là số liệu rất riêng, thường đòi hỏi sự thỏa hiệp giữa một số số liệu dễ đo lường khác. Hạn chế trước tất cả các số liệu khác đó và sự thỏa hiệp không còn có thể trở thành có thể, dẫn đến mã ít đọc hơn.


5

Luôn luôn? - KHÔNG

Trớ trêu thay, đạt được mức độ đơn giản phù hợp có thể là một công việc phức tạp. Tôi nghĩ rằng chìa khóa là trong chừng mực. Sự đơn giản cũng có thể nằm trong mắt của kẻ si tình, vì vậy nếu bạn thấy mình suy nghĩ quá mức - hãy để nó một mình hoặc quay lại với nó sau.

Cá nhân, khi tôi cố gắng quay lại và đơn giản hóa một cái gì đó mà tôi đã viết, tôi tập trung vào những lĩnh vực mà tôi đã thay đổi suy nghĩ hoặc thử một vài điều để có được những gì tôi muốn. Những khu vực thường có thể được làm mịn. Sau đó, chỉ cần thực hiện một vài lần thông qua mã để làm cho nó dễ đọc hơn mà không cần phát tán ra nhiều thứ đến nỗi bạn đang nhảy khắp nơi để tìm hiểu những gì đang xảy ra trên một bản sửa lỗi.


5

Nếu tôi đơn giản, tôi có thể viết mã như thế này:

10000000000000000000000000000000000000000000

Nhưng nếu tôi đi để dễ đọc, tôi sẽ thích điều này:

1e43

Mặt khác, 1000dễ đọc và đơn giản hơn nhiều 1e3trừ khi bạn làm việc với các con số trong ký hiệu khoa học mọi lúc.

Đây là một ví dụ thoái hóa của mô hình tổng quát hơn nhiều mà bạn có thể tìm thấy ở hầu hết mọi nơi - xây dựng một cái gì đó từ các khối rất đơn giản có thể nhanh chóng trở nên không thể đọc được / không hiệu quả / xấu theo nhiều cách khác nhau. Mặt khác, việc khái quát hóa và tái sử dụng khó hơn ("wtf là egì ?! Họ có ý định viết 1343?" Ai đó có thể nói), nhưng về lâu dài có thể giúp ích rất nhiều.


Quan điểm của bạn về "1e3" là ít đọc hơn "100" cũng được đưa ra. Trong thực tế, đây là một ví dụ tuyệt vời về cách tải nhận thức ảnh hưởng đến khả năng đọc. "1e3" yêu cầu đọc 3 ký tự VÀ dịch số mũ. Đọc "100" yêu cầu đọc 3 ký tự và không cần đánh giá thêm.
Stephen Gross

Stephen, thực sự khi đọc một số có ba chữ số như 100bạn phải thực hiện hai phép nhân và hai phép cộng ( 0+10*(0+10*1)). Tuy nhiên, đã quen với ký hiệu này, bạn thậm chí không nhận thấy điều đó. Điều này một lần nữa cho thấy khái niệm chủ quan của sự đơn giản có thể như thế nào.
Rotsor

Hấp dẫn. Vì vậy, nói đúng ra, "100" yêu cầu 2 phép nhân (1 * 100, 0 * 10) và 2 phép toán cộng. "1e3" yêu cầu một thao tác nhân. Vì vậy, không có bất kỳ bối cảnh nhận thức nào , "100" khó đọc hơn "1e3". Nhưng! Nếu bạn bao gồm tải nhận thức chuyển đổi ngữ cảnh, tính toán sẽ khác. Vì chúng ta thường đọc các số nguyên ở dạng không khoa học, "100" dễ dàng hơn. Nhưng, nếu chúng ta đang viết một ứng dụng kỹ thuật trong đó tất cả các số được biểu thị bằng ký hiệu khoa học, thì mẫu "1e3" sẽ dễ dàng hơn!
Stephen Gross

2

Không cần thiết. Nếu bạn có một hoạt động phức tạp, sự phức tạp đó phải đi đâu đó. Giảm số lượng "nội dung" trên một dòng chỉ có nghĩa là nó sẽ chiếm nhiều dòng hơn, điều này thực sự có thể gây bất lợi cho khả năng đọc mã nếu nó làm cho thói quen của bạn quá "cao" để phù hợp với một màn hình.


Sự phức tạp không phải là không thể giảm được. Chúng tôi có "trừu tượng" và "chunking" và "tổ chức" để cố gắng quản lý sự phức tạp. Tôi nghĩ rằng một hoạt động phức tạp có thể được mô tả trong một số bước đơn giản hơn. Nó hoạt động cho nhiều quy trình vật lý trong thế giới thực: tóm tắt, tổng quan, v.v.
S.Lott

1
@ S.Lott: Đúng, nhưng việc cuộn và nhấp Ctrl đủ có thể khiến quá trình "đơn giản hóa" trở nên khó thực hiện hơn. Tôi đã thấy nó xảy ra một hoặc hai lần (nó không phổ biến nhưng có thể rất khó chịu khi làm việc khi nó đi quá xa).
Thất vọngWithFormsDesigner

3
@ S.Lott - vẫn còn giới hạn về mức độ phức tạp có thể giảm đến mức nào. Bạn có thể loại bỏ sự phức tạp không cần thiết, nhưng bạn chỉ có thể quản lý (không loại bỏ) sự phức tạp cần thiết - sự phức tạp vốn có trong các yêu cầu. Có thể cho rằng, các cơ chế để quản lý độ phức tạp cũng làm tăng độ phức tạp - một số độ phức tạp được thêm vào có liên quan đến việc di chuyển độ phức tạp không liên quan ra khỏi đường để tiết lộ tốt hơn các chi tiết có liên quan cho một khía cạnh / vấn đề / cấu trúc cụ thể.
Steve314

1
@ S.Lott - Chà, chắc chắn là bạn có thể đại diện cho bất kỳ yêu cầu nào bạn muốn với tệp nguồn không phức tạp (hoàn toàn trống rỗng). Nhưng vì bạn cần một ngôn ngữ rất cụ thể để đáp ứng các yêu cầu của bạn, tất cả những gì bạn đang làm là chuyển các yêu cầu của bạn sang đặc tả ngôn ngữ.
Steve314

1
@ S.Lott - nếu bạn cho rằng bạn có thể dự đoán vị trí của Sao Mộc vào ngày Giáng sinh mà không sử dụng gì G=0, nhưng tôi nghĩ bạn đang điên. Nếu bạn không, bạn đang thiếu quan điểm của tôi. Chắc chắn bạn có thể trừu tượng hóa chi tiết không liên quan, nhưng nó không liên quan nếu các yêu cầu của bạn nói rằng nó có liên quan. Nếu bạn đọc lại, tôi không bao giờ tuyên bố rằng tất cả sự phức tạp là cần thiết - chỉ có một số sự phức tạp vốn có trong các yêu cầu và không thể được loại bỏ.
Steve314

2

Rõ ràng + Tiêu chuẩn + Sử dụng lại mã + Nhận xét tốt + Thiết kế tốt có thể cải thiện khả năng đọc .

Sự đơn giản không phải lúc nào cũng nằm trong tay nhà phát triển vì bản chất của thuật toán và sự phức tạp của cấu trúc ứng dụng ngày nay.

Lấy các trang web đơn giản thực hiện các nhiệm vụ đơn giản. Đưa ra một thói quen sắp xếp, không thể đơn giản hóa logic, nhưng bạn có thể làm cho nó rõ ràng hơn bằng các bình luận, sử dụng các tên biến có ý nghĩa, viết nó theo cách có cấu trúc, v.v.


2

Có phải sự đơn giản luôn cải thiện khả năng đọc?

Không. Tôi đã thấy nhiều trường hợp thực hiện nhiều việc đơn giản trên một dòng ít phức tạp hơn so với việc có nhiều dòng.

Có một sự đánh đổi giữa ít mã hơn và mã đơn giản hơn.

Nói chung, tôi khuyên bạn nên sử dụng mã đơn giản hơn trừ khi bạn chắc chắn thực hiện nó trong ít dòng hơn là tốt hơn. Tôi rất muốn có mã "quá dài dòng" trên mã "quá phức tạp".


1

"Làm cho mọi thứ đơn giản nhất có thể, nhưng không đơn giản hơn" - Một cách diễn giải thường xuyên của Albert Einstein

Đơn giản cải thiện mọi thứ . Đối với các giá trị khác nhau của sự đơn giản, tất nhiên. Có ít dòng mã hơn không? Có lẽ. Nó có phải là một thực thi nhỏ hơn? Có thể. Đó có phải là điều mà nhóm của bạn cần phải đồng ý? Hoàn toàn đúng .


+1 cho trích dẫn, nhưng sự đơn giản có cải thiện khả năng đọc không?
Richard

"Làm cho mọi thứ đơn giản nhất có thể sau đó đơn giản hóa chúng" là một cách diễn giải tốt hơn vì các kỹ sư SW có xu hướng vượt qua kỹ thuật.
mattnz

1
Tôi ước mọi người sẽ ngừng nói "làm mọi thứ đơn giản nhất có thể, nhưng không đơn giản hơn". Ít nhất chúng ta có thể khái quát hóa thành MakeAsoodAsPossibleButNoMoreSo <Thing, Attribution> khi chúng ta đi đến mẹo kỹ thuật chung vô dụng? (Xin lỗi @Jlie C. Choper, bạn ở xa người duy nhất trích dẫn điều này, vì vậy bạn không thực sự xứng đáng với những lời tán tỉnh nhỏ hơn bất kỳ ai khác).
psr

1

Có phải sự đơn giản luôn cải thiện khả năng đọc? Vâng. Là một tuyên bố trên mỗi dòng luôn đơn giản hơn? Không. Khá nhiều ngôn ngữ có toán tử ternary, một khi đã nắm bắt được, nó đơn giản và dễ hiểu hơn so với các phép gán if / other tương đương.

Trong các ngôn ngữ cho phép đặt nhiều biến trên một dòng, làm như vậy thường đơn giản và dễ hiểu hơn bất cứ thứ gì tương đương.

Một ví dụ khác: các biểu thức chính quy làm rất nhiều, thường chỉ trong một dòng và tương đương không có biểu thức chính quy thường khó đọc hơn nhiều . / \ d {3} [-] \ d {3} - \ d {4} / tương đương với một lệnh gọi hàm với ít nhất một số nhận xét và dễ hiểu hơn thân hàm tương ứng.


1

Dễ đọc và đơn giản là các thuật ngữ chủ quan, tùy thuộc vào con người và bối cảnh, thông thường nhưng không phải lúc nào cũng đi cùng nhau.

Một thuật ngữ khách quan hơn là sự đồng nhất - về nguyên tắc bạn có thể đếm bằng cách đếm các ký tự, mặc dù có một số sai sót trong đó. Sự đồng nhất dường như ngụ ý sự đơn giản và dễ đọc, nhưng có (ít nhất là theo ý kiến ​​của tôi).

Một đoạn mã dài hơn (và có thể phức tạp hơn) có thể dễ đọc hơn nếu nó thể hiện tốt hơn ý định. Cho dù định nghĩa của bạn về sự đơn giản quan tâm đến ý định là một điều chủ quan khác - bạn có thể định nghĩa sự phức tạp về mặt cấu trúc cú pháp và entropy lý thuyết thông tin, chẳng hạn, không liên quan đến ý định nào cả.

Vì vậy, một tên biến dài hơn được chọn tốt có thể ...

  • Cải thiện khả năng đọc bằng cách thể hiện tốt hơn ý định
  • Giảm sự đồng nhất - nó dài hơn, sau tất cả
  • Hoàn toàn không ảnh hưởng đến tính đơn giản cú pháp - cấu trúc cú pháp của mã không thay đổi

Tương tự, tôi có thể viết if (some_boolean == true). So với giải pháp thay thế tương đương if (some_boolean), ...

  • Giảm sự đồng nhất
  • Giảm tính đơn giản cú pháp, nhưng
  • Có thể cải thiện khả năng đọc bằng cách thể hiện tốt hơn ý định.

Tất nhiên điều này sẽ gây ra một cuộc biểu tình rầm rộ - với nhiều người, điều này luôn gây thiệt hại cho khả năng đọc. Đối với tôi, nó phụ thuộc rất nhiều vào nguồn của boolean - ví dụ tên biến (hoặc tên phương thức hoặc bất cứ thứ gì) có thể không thể hiện rõ ràng rằng giá trị là "giá trị thật". Chắc chắn, ifcho bạn biết một cái gì đó, nhưng nó vẫn có mùi. Nhưng nhiều người sẽ gọi tôi là thằng ngốc vì tin vào điều này.

Đó là bằng chứng thêm về tính chủ quan tổng thể, tất nhiên.


1

Tất cả các bạn đang thiếu một số định nghĩa cơ bản . Đơn giản, từ gốc sim-plex , có nghĩa là một lần . Đơn giản có nghĩa là làm một việc . Dễ dàng, từ gốc dễ dàng , có nghĩa là nằm gần . Dễ dàng có nghĩa là nó ở gần tầm tay . Các ví dụ về mã đơn giản được đưa ra trong các câu trả lời khác không chính xác những gì chúng xuất hiện.

Hãy hiển thị giá trị rất lớn của rotsor . Ông nói điều này thật đơn giản . Không, trong ước tính của tôi, đơn giản. Dễ thôi. Nó ở gần để nhập số 0 yêu cầu.

10000000000000000000000000000000000000000000

Các thể đọc được phiên bản rất đơn giản. Nó làm một điều. Nó biểu thị số bằng cách mô tả kích thước của nó trong một mục đích ký hiệu được xây dựng cho chức năng này.

1e43

Bạn có thể mô tả đoạn mã "đơn giản" của Aidan là làm một việc không? Nó chứa 10 dòng mã (không tính bình luận) và ít nhất 7 khối (như tôi đã đếm chúng). Nếu bạn theo dõi các bình luận, bạn sẽ thấy rằng nó thực hiện ít nhất 4 điều!

count :: [Integer] -> [[Integer]]
count [] = [[]]
count (x:xs) =
  -- get all possible sequences for the remaining digits
  let
    remDigits :: [[Integer]]
    remDigits = count xs
  in
  -- pull out a possible sequence for the remaining digits
  do nextDigits <- remDigits
     -- pull out all possible values for the current digit
     y <- [0..x]
     -- record that "current digit" : "remaining digits" is
     -- a valid output.
     return (y:nextDigits)

Nhưng, một trong những khuyến nghị để viết lại mã này là một tuyên bố. Aidan tuyên bố rằng một người đọc sẽ phải hoặc trở nên quen thuộc với các câu lệnh đơn âm, mã miễn phí con trỏ, v.v ... Điều đó tốt. Những khái niệm này là số ít và độc lập để tìm hiểu.

count = mapM (enumFromTo 0)

Bạn sẽ thấy rằng mã thực sự đơn giản dễ đọc hơn mã dễ dàng bởi vì nó chỉ làm một điều. Bạn có thể cần phải tắt và tìm hiểu thêm "một điều" để hiểu mã đơn giản. Nhưng nó phải luôn luôn dễ đọc hơn.


1

Có phải sự đơn giản luôn cải thiện khả năng đọc?

Tôi có thể nói, có thể với một chút tranh cãi, hoàn toàn không .

Bạn có thể đưa cho tôi một lớp học với 200 chức năng thành viên trong giao diện công cộng của nó và nó có thể là giao diện công cộng dễ đọc nhất ở ngoài kia. Nó có thể là một niềm vui chỉ tình cờ đọc qua mã như vậy và tài liệu của nó. Tuy nhiên, tôi sẽ không gọi nó là "đơn giản", vì mặc dù dễ đọc, tôi sẽ phải quan tâm đến việc tất cả các chức năng này tương tác với nhau như thế nào, và có khả năng coi chừng các trường hợp khó khăn do sử dụng sai.

Tôi thích một lớp có 20 hàm thành viên không dễ đọc đến 200, vì "khả năng đọc" không phải là ưu tiên hàng đầu đối với tôi trong việc ngăn ngừa lỗi của con người và cải thiện khả năng duy trì mã (dễ dàng trong đó chúng ta có thể thay đổi nó, tức là).

Tuy nhiên, đây là tất cả sẽ xoay quanh định nghĩa cá nhân của chúng tôi về "sự đơn giản". "Độ khó" thường không thay đổi đó một cách hoang dại giữa chúng ta, trừ khi ai đó đã mua rất nhiều kinh nghiệm và thành thạo mà họ xem xét regex là rất "dễ đọc", ví dụ như, quên phần còn lại của chúng tôi chỉ mortals.

Sự đơn giản

Có một thời gian, từ lâu, nơi tôi nghĩ "đơn giản" có nghĩa là "dễ đọc nhất có thể". Vì vậy, tôi sẽ viết mã C với rất nhiều chức năng tiện lợi, cố gắng cải thiện cú pháp và làm cho mọi thứ dễ đọc và viết nhất có thể.

Kết quả là tôi đã thiết kế các thư viện cấp cao, phong phú, rất phong phú, cố gắng mô hình hóa một chức năng cho mọi suy nghĩ tự nhiên của con người: người trợ giúp khi người trợ giúp, tất cả để định hình mã khách hàng thành cú pháp dễ đọc hơn. Mã tôi đã viết lại sau đó có thể là "dễ đọc" nhất, nhưng nó cũng là "không thể nhầm lẫn" và "phức tạp" nhất.

Lisp

Tuy nhiên, tôi đã có một niềm đam mê ngắn với LISP vào khoảng giữa những năm 90 (latecomer). Nó thay đổi toàn bộ ý tưởng của tôi về "sự đơn giản".

LISP không phải là ngôn ngữ dễ đọc nhất. Hy vọng rằng không ai nghĩ rằng trích xuất CDR và ​​CAR trong khi gọi hàm đệ quy với một khối dấu ngoặc đơn lồng nhau là rất "dễ đọc".

Tuy nhiên, sau khi vật lộn để khiến bộ não của tôi xoay quanh cú pháp kỳ quặc của ngôn ngữ và cách thức hoàn toàn đệ quy, nó đã thay đổi vĩnh viễn ý tưởng về sự đơn giản của tôi.

Điều tôi tìm thấy với mã tôi đã viết trong LISP là tôi không còn mắc lỗi tinh vi nữa, mặc dù sự khó khăn trong suy nghĩ theo cách đó đã khiến tôi mắc nhiều lỗi trắng trợn hơn (nhưng chúng rất dễ phát hiện và sửa chữa). Tôi đã không hiểu những gì một chức năng đang làm và bỏ lỡ một tác dụng phụ tinh tế, không lường trước được. Tôi chỉ có một thời gian dễ dàng hơn trong việc thay đổi và viết chương trình chính xác.

Sau LISP, sự đơn giản đối với tôi trở thành về sự tối giản, tính đối xứng, tính linh hoạt, ít tác dụng phụ hơn, ít chức năng hơn nhưng linh hoạt hơn kết hợp với nhau theo nhiều cách khác nhau.

Tôi đã đánh giá cao suy nghĩ rằng mã đáng tin cậy nhất là mã không tồn tại. Mặc dù nó chỉ là một số liệu thô, tôi có xu hướng thấy tiềm năng không đáng tin cậy của mã dựa trên số lượng của nó. Tìm kiếm sự thuận tiện cú pháp tối đa và khả năng đọc có xu hướng tăng số lượng đó bằng một yếu tố lớn.

Chủ nghĩa tối giản

Với tư duy LISP được nhúng trong tôi, tôi đã thích các API tối giản hơn. Tôi thích một thư viện có ít chức năng hơn nhưng đáng tin cậy hơn, linh hoạt hơn, ít tiện lợi hơn và tiềm năng khó đọc hơn thư viện cung cấp một lượng lớn người trợ giúp "thuận tiện" và điều đó có thể giúp mã dễ "đọc" nhưng có khả năng bị vấp nhiều vấn đề hơn với sự không đáng tin cậy và bất ngờ xuất phát từ việc hiểu sai những gì một trong số hàng ngàn chức năng này làm.

An toàn

Một điều khác về LISP là sự an toàn. Nó phát huy tác dụng phụ tối thiểu và các chức năng thuần túy, và đó là nơi tôi không còn thấy mình mắc lỗi tinh vi, mặc dù khó đọc và viết bằng ngôn ngữ đã tăng thêm những lỗi trắng trợn hơn tôi có thể nhận ra 10 giây sau.

Các hàm thuần túy và trạng thái bất biến trở nên thích hợp hơn với tôi bất cứ khi nào tôi có thể mua được, ngay cả khi cú pháp của:

sword = sharpen(sword)

... Là một chút ít đơn giản và tách rời khỏi suy nghĩ của con người hơn:

sharpen(sword)

Khả năng đọc VS. Sự đơn giản

Một lần nữa, LISP không phải là ngôn ngữ "dễ đọc" nhất. Nó có thể gói rất nhiều logic vào một phần nhỏ của mã (có thể nhiều hơn một suy nghĩ của con người trên mỗi dòng). Tôi có xu hướng lý tưởng thích một suy nghĩ của con người trên mỗi dòng cho "khả năng đọc", nhưng nó không nhất thiết là "đơn giản".

Với định nghĩa "đơn giản" này, đôi khi "đơn giản" thực sự có thể phần nào cạnh tranh với "có thể đọc được". Điều này đang xem xét mọi thứ nhiều hơn từ quan điểm thiết kế giao diện.

Một giao diện đơn giản có nghĩa là bạn cần học ít thứ hơn để sử dụng nó, và có khả năng có độ tin cậy cao hơn và ít vấn đề hơn do sự tối giản của nó. Một tài liệu toàn diện về chủ đề này có thể phù hợp với một cuốn sách nhỏ hơn là một khối lượng sách khổng lồ. Tuy nhiên, nó có thể yêu cầu một số công việc nặng nề hơn và mang lại mã ít đọc hơn.

"Đơn giản" đối với tôi cải thiện khả năng hiểu chức năng trong hệ thống của chúng tôi ở mức độ rộng. "Có thể đọc được" đối với tôi cải thiện khả năng kết nối từng dòng mã nhỏ với ngôn ngữ tự nhiên và suy nghĩ và có thể tăng tốc độ hiểu biết của chúng tôi về một dòng mã, đặc biệt là nếu chúng tôi không thông thạo ngôn ngữ.

Regex là một ví dụ về những gì tôi cho là "cực kỳ đơn giản". Đó là "quá đơn giản và quá khó đọc" cho sở thích cá nhân của tôi. Có một hành động cân bằng giữa tôi giữa các thái cực này, nhưng regex có chất lượng đơn giản giống như LISP như tôi định nghĩa: tối giản, đối xứng, linh hoạt đáng tin cậy, đáng tin cậy, v.v. Vấn đề đối với tôi với regex là nó quá đơn giản đã trở nên khó đọc đến mức tôi không nghĩ mình sẽ trở nên thông thạo nó (bộ não của tôi không hoạt động theo cách đó và tôi ghen tị với những người có thể viết mã regex trôi chảy).

Vì vậy, dù sao, đó là định nghĩa của tôi về "đơn giản", và nó hoàn toàn độc lập với "khả năng đọc" và đôi khi thậm chí có thể can thiệp vào cái khác, dẫn đến một hành động cân bằng giữa một thư viện "thuận tiện hơn về mặt cú pháp" và dễ đọc hơn hoặc "về mặt cú pháp" bất tiện ", thư viện ít đọc hơn nhưng nhỏ hơn. Tôi luôn luôn tìm thấy các ưu tiên "tiện lợi của sự hiểu biết" và "khả năng duy trì" thực sự để phù hợp với điều kiện sau, với sự ưu tiên mạnh mẽ đối với chủ nghĩa tối giản thậm chí với một số chi phí dễ đọc và cú pháp tự nhiên hơn (nhưng không đến mức regex) . YMMV.


0

Luôn luôn? - VÂNG

Đạt được mức độ đơn giản phù hợp là một công việc phức tạp và khó khăn. Nhưng luôn luôn có giá trị vì nó luôn cải thiện khả năng đọc. Tôi nghĩ rằng chìa khóa là sự hiểu biết sâu sắc. Tính đơn giản là tuyệt đối, được đo bằng "khái niệm mới" trên mỗi "đoạn" mã. Một vài khái niệm mới có nghĩa là đơn giản hơn.

Tập trung vào các khu vực có một cụm các khái niệm dày đặc và tìm cách "chunk" hoặc "tóm tắt" hoặc "trừu tượng". Thực hiện một vài lần thông qua mã để làm cho nó đơn giản và dễ đọc hơn.

Một sự trừu tượng tốt có giá trị của nó bằng vàng. Một sự trừu tượng tốt làm cho điều này đơn giản hơn - và do đó dễ đọc hơn.


Tôi không thể không nghĩ rằng những câu trích dẫn đáng sợ của bạn ở đó bởi vì bạn biết rằng "khái niệm" và "chunk" là chủ quan. Một người khái niệm duy nhất là một người khác hợp nhất ba ý tưởng khác biệt. Thật khó để có một thước đo tuyệt đối và khách quan của những thứ chủ quan.
Steve314

@ Steve314: Báo giá sợ? Không en.wikipedia.org/wiki/Chunking tất cả dường như giống nhau ở chỗ họ mô tả đơn giản hóa thông qua chunking. (Ngoại trừ kỹ thuật guitar, có vẻ khác nhau.) Các trích dẫn ở đó bởi vì có rất nhiều thuật ngữ thay thế cho trừu tượng, chunking, tóm tắt, v.v. Các trích dẫn ở đó để nhấn mạnh rằng điều này bằng cách nào đó gây tranh cãi. Chưa. Nó rõ ràng được thực hiện mọi lúc và dường như là một xu hướng tự nhiên của con người.
S.Lott

Những gì tôi không phủ nhận - chunking được thực hiện mọi lúc và là một ý tưởng tốt. Điều tôi phủ nhận - rằng có một quy tắc khách quan dứt khoát về nơi ranh giới nên nằm giữa các khối. Lập luận của tôi có thể mang tính mô phạm nhiều hơn là hữu ích, nhưng tôi vẫn nghi ngờ "luôn luôn" trong "luôn cải thiện khả năng đọc".
Steve314

@ Steve314: Chúng tôi luôn trừu tượng, chunk và tóm tắt để giúp bản thân hiểu mọi thứ. Luôn luôn. Chunking, trừu tượng hóa, tóm tắt ("đơn giản hóa") là điều chúng tôi luôn luôn làm. Chúng tôi chỉ làm. Đó là cách bộ não của chúng ta nắm bắt thực tế. Đơn giản hóa luôn cải thiện khả năng đọc, và luôn luôn có thể được thực hiện.
S.Lott

vâng, chúng tôi làm. Tôi không bao giờ nói khác.
Steve314

-2

Các câu hỏi nhắc nhở tôi về câu trả lời này trên Stack Overflow, đặc biệt là trích dẫn này (chất lượng thay thế bằng sự đơn giản):

Chất lượng - bạn biết nó là gì, nhưng bạn không biết nó là gì. Nhưng đó là mâu thuẫn. Nhưng một số thứ tốt hơn những thứ khác, nghĩa là chúng có chất lượng hơn. Nhưng khi bạn cố gắng nói chất lượng là gì, ngoài những thứ có nó, tất cả đều gặp sự cố! Không có gì để nói. Nhưng nếu bạn không thể nói Chất lượng là gì, làm sao bạn biết nó là gì hoặc làm thế nào để bạn biết rằng nó thậm chí còn tồn tại? Nếu không ai biết nó là gì, thì với tất cả các mục đích thực tế, nó hoàn toàn không tồn tại. Nhưng đối với tất cả các mục đích thực tế, nó thực sự tồn tại. Những gì khác là các lớp dựa trên? Tại sao người khác lại trả vận may cho một số thứ và ném những thứ khác vào đống rác? Rõ ràng một số thứ tốt hơn những thứ khác - nhưng '`tốt hơn' 'là gì? - Vì vậy, tròn và vòng bạn đi, quay bánh xe tinh thần và không nơi nào tìm thấy bất cứ nơi nào để có được lực kéo. Chất lượng là gì? Nó là gì?

Tôi nghĩ rằng điều quan trọng là bạn phải nhớ rằng một tiêu chuẩn mã hóa được mã hóa cho tất cả các lợi ích của nó sẽ không làm cho các lập trình viên giỏi thoát khỏi những điều xấu. Một từ như 'đơn giản' có thể được giải thích khác nhau bởi những người khác nhau (xem câu trả lời của Aidan Cully), nhưng đó có thể không phải là một điều tồi tệ. Các lập trình viên trẻ sẽ vẫn cần phải xem xét mã của họ bởi các lập trình viên cao cấp và tìm hiểu lý do tại sao các lập trình viên cao cấp giải thích 'đơn giản' lại tốt hơn mã của họ.


1
Đây là lý do tại sao tôi định nghĩa sự đơn giản trong câu hỏi.
Richard

-2

Một cuộc gọi chức năng trên mỗi dòng là đơn giản hơn? Hãy thử một ví dụ!

=== One call per line ===
x = y.getThis()
a = x.getThat()
b = a.getSomethingElse()

=== Less "simple" version ===
b = y.getThis().getThat().getSomethingElse()

Bạn nghĩ sao? Là một cuộc gọi trên mỗi dòng thực sự đơn giản hơn?


Vâng. Một cuộc gọi trên mỗi dòng đơn giản và dễ đọc hơn đối với tôi. Tuy nhiên, khả năng đọc chủ quan. (Ngoài ra, điều này thậm chí không đến gần để trả lời câu hỏi.)
Richard

Xin chào Stephen, bạn có thể giải thích về cách bạn nghĩ câu trả lời này không? Không rõ bạn đang cố gắng chỉ ra điều gì ở đây.

@MarkTrapp Không có vấn đề. Câu hỏi ban đầu đề xuất cách tiếp cận một chức năng trên mỗi dòng. Ví dụ tôi đã đăng cho thấy hai đoạn mã giống nhau, một đoạn được triển khai dưới dạng một hàm trên mỗi dòng, đoạn còn lại là các cuộc gọi phương thức chuỗi. Tôi nghĩ rằng cuộc gọi xích dễ đọc hơn rất nhiều: ngắn, không có các biến tạm thời không cần thiết và thanh lịch.
Stephen Gross

Nếu bạn phải xâu chuỗi getters thì mã của bạn được thiết kế rộng rãi
Mùa đông
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.