Tại sao là những người khác nếu Elif khác tuyên bố hầu như không bao giờ ở định dạng bảng?


73
if   i>0 : return sqrt(i)  
elif i==0: return 0  
else     : return 1j * sqrt(-i)

VS

if i>0:  
   return sqrt(i)  
elif i==0:  
   return 0  
else:  
   return 1j * sqrt(-i)  

Đưa ra các ví dụ trên, tôi không hiểu tại sao tôi hầu như không bao giờ thấy kiểu đầu tiên trong các cơ sở mã. Đối với tôi, bạn biến mã thành một định dạng bảng hiển thị rõ ràng những gì bạn muốn. Cột đầu tiên hầu như có thể được bỏ qua. Cột thứ hai xác định điều kiện và cột thứ ba cung cấp cho bạn đầu ra bạn muốn. Dường như, ít nhất là với tôi, thẳng thắn và dễ đọc. Tuy nhiên, tôi luôn thấy loại tình huống / trường hợp chuyển đổi đơn giản này xuất hiện ở định dạng thụt lề, mở rộng. Tại sao vậy? Mọi người có tìm thấy định dạng thứ hai dễ đọc hơn không?

Trường hợp duy nhất mà điều này có thể có vấn đề là nếu mã thay đổi và lâu hơn. Trong trường hợp đó, tôi nghĩ việc tái cấu trúc mã thành định dạng dài, thụt lề là hoàn toàn hợp lý. Có phải mọi người đều làm theo cách thứ hai đơn giản vì đó là cách nó luôn được thực hiện? Là người ủng hộ của quỷ, tôi đoán một lý do khác có thể là do mọi người tìm thấy hai định dạng khác nhau tùy thuộc vào mức độ phức tạp của các câu lệnh if / other gây nhầm lẫn? Bất kỳ cái nhìn sâu sắc sẽ được đánh giá cao.


91
Bởi vì mọi người tìm thấy tùy chọn thứ 2 dễ đọc hơn?
GrandmasterB

65
Trường hợp sử dụng của các nhánh loại trừ lẫn nhau mà tất cả trả về một giá trị cùng loại không xuất hiện thường xuyên trong các ngôn ngữ bắt buộc so với các nhánh không trả về giá trị, có thể kéo dài nhiều dòng và có thể có tác dụng phụ. Nếu bạn nhìn vào các ngôn ngữ lập trình chức năng, bạn sẽ thấy mã giống với ví dụ đầu tiên của bạn thường xuyên hơn nhiều.
Doval

47
@horta "Trường hợp duy nhất có thể có vấn đề là fi mã thay đổi và lâu hơn." - Bạn KHÔNG BAO GIỜ cho rằng một đoạn mã sẽ không bị thay đổi. Tái cấu trúc mã chiếm phần lớn trong vòng đời của phần mềm.
Charles Addis

7
@horta: Không có gì để làm với tôi. Đó là mã. Trong ngữ cảnh của cơ sở mã đang đọc, tôi muốn xem các câu lệnh (và các cấu trúc ngôn ngữ khác) có được định dạng nhất quán hay không, không có trường hợp cạnh nào. Không phải là tôi học cách đọc mã theo một cách cụ thể, tôi có thể đọc tốt, nhưng sẽ dễ đọc hơn nếu mọi thứ đều giống nhau. Một lần nữa, không giống với tôi, giống với phần còn lại của mã.
GManNickG

44
Ngoài ra, hầu hết các trình sửa lỗi là dựa trên dòng. Không thể đặt một điểm dừng trên một tuyên bố bên trong ifnếu nó nằm trên cùng một dòng.
isanae

Câu trả lời:


93

Một lý do có thể là bạn không sử dụng ngôn ngữ phổ biến.

Một vài ví dụ ngược lại:

Haskell với lính canh và với các mẫu:

sign x |  x >  0        =   1
       |  x == 0        =   0
       |  x <  0        =  -1

take  0     _           =  []
take  _     []          =  []
take  n     (x:xs)      =  x : take (n-1) xs

Erlang với các mẫu:

insert(X,Set) ->
    case lists:member(X,Set) of
        true  -> Set;
        false -> [X|Set]
    end.

Emacs lisp:

(pcase (get-return-code x)
  (`success       (message "Done!"))
  (`would-block   (message "Sorry, can't do it now"))
  (`read-only     (message "The shmliblick is read-only"))
  (`access-denied (message "You do not have the needed rights"))
  (code           (message "Unknown return code %S" code)))

Nói chung, tôi thấy định dạng bảng khá phổ biến với các ngôn ngữ chức năng (và trong các biểu thức dựa trên biểu thức chung), trong khi ngắt dòng là phổ biến nhất trong các ngôn ngữ khác (chủ yếu dựa trên câu lệnh).


10
Tôi ủng hộ điều này và thường đồng ý, nhưng cảm thấy bắt buộc phải chỉ ra rằng 1. Tất cả những điều này là lợi nhuận không đáng kể 2. Người bán hàng thích các định danh ngắn về mặt hài hước bên cạnh sự phức tạp của ngôn ngữ và 3. Ngôn ngữ chức năng có xu hướng dựa trên biểu thức và thậm chí các ngôn ngữ mệnh lệnh có các tiêu chuẩn khác nhau cho các biểu thức so với các câu lệnh. Nếu OP viết lại ví dụ ban đầu dưới dạng các ứng dụng chức năng, anh ta có thể nhận được lời khuyên khác ...
Jared Smith

3
@JaredSmith Cảm ơn sự phân chia dựa trên biểu thức / câu lệnh - Tôi nghĩ rằng nó có thể thậm chí phù hợp hơn chức năng / mệnh lệnh. Hơn nữa, ruby ​​gần như dựa trên biểu thức và không sử dụng quy ước đó thường xuyên. (ngoại trừ tất cả mọi thứ) Về điểm 1 và 2, tôi thấy 50% + mã Haskell thực sự là "lợi nhuận tầm thường" chỉ là một phần của một cái gì đó lớn hơn - đó chỉ là cách viết mã đó - không chỉ trong các ví dụ ở đây. Ví dụ, gần một nửa các chức năng ở đây chỉ là một / hai lớp lót. (một số dòng sử dụng bố trí bảng)
viraptor

Đúng. Tôi không phải là một Haskeller nhưng thực hiện một số ocaml và thấy rằng việc khớp mẫu có xu hướng ngắn gọn hơn nhiều so với các công tắc tương đương logic và các chức năng đa hình bao gồm rất nhiều vấn đề. Tôi tưởng tượng các lớp loại của Haskell sẽ mở rộng phạm vi đó hơn nữa.
Jared Smith

Tôi nghĩ rằng đó là cú pháp trường hợp mẫu thúc đẩy điều đó. Bởi vì nó ngắn gọn hơn và thường gần với vỏ công tắc ngắn hơn, nên việc thể hiện dưới dạng một lớp lót dễ dàng hơn. Tôi thường xuyên làm điều này với các báo cáo trường hợp chuyển đổi ngắn cũng vì lý do tương tự. if-elseMặc dù vậy, các tuyên bố theo nghĩa đen vẫn thường được trải rộng trên nhiều dòng khi không thực sự là một câu nói đơn giản.
Isiah Meadows

@viraptor Về mặt kỹ thuật, 50% khác - mã haskell là "lợi nhuận không tầm thường" vì tất cả các hàm haskell đều có chức năng thuần túy và không thể có tác dụng phụ. Ngay cả các hàm đọc từ và in ra dòng lệnh cũng chỉ là các câu lệnh return.
Pharap

134

Nó dễ đọc hơn. Một vài lý do tại sao:

  • Gần như mọi ngôn ngữ đều sử dụng cú pháp này (không phải tất cả, hầu hết - ví dụ của bạn dường như là Python)
  • isanae đã chỉ ra trong một bình luận rằng hầu hết các trình sửa lỗi đều dựa trên dòng (không dựa trên câu lệnh)
  • Nó bắt đầu trông thậm chí còn xấu xí hơn nếu bạn phải dấu chấm phẩy nội tuyến hoặc niềng răng
  • Nó đọc từ trên xuống dưới trơn tru hơn
  • Nó trông khủng khiếp không thể đọc được nếu bạn có bất cứ điều gì khác ngoài các tuyên bố trở lại tầm thường
    • Bất kỳ cú pháp có ý nghĩa thụt lề nào sẽ bị mất khi bạn đọc lướt mã vì mã điều kiện không còn được phân tách trực quan (từ Dan Neely )
    • Điều này sẽ đặc biệt tệ nếu bạn tiếp tục vá / thêm các mục vào dòng 1 nếu câu lệnh
  • Nó chỉ có thể đọc được nếu tất cả các kiểm tra nếu của bạn có cùng độ dài
  • Điều đó có nghĩa là bạn không thể định dạng phức tạp nếu các câu lệnh thành các câu lệnh đa dòng, chúng sẽ phải là oneliners
  • Tôi có nhiều khả năng nhận thấy lỗi / luồng logic khi đọc từng dòng theo chiều dọc, không cố phân tích nhiều dòng với nhau
  • Bộ não của chúng ta đọc hẹp hơn, văn bản cao hơn NHIỀU nhanh hơn văn bản dài, ngang

Giây phút bạn cố gắng thực hiện bất kỳ điều gì trong số này, bạn sẽ kết thúc việc viết lại thành các câu lệnh đa dòng. Có nghĩa là bạn chỉ lãng phí thời gian!

Ngoài ra mọi người chắc chắn sẽ thêm một cái gì đó như:

if i>0:  
   print('foobar')
   return sqrt(i)  
elif i==0:  
   return 0  
else:  
   return 1j * sqrt(-i)  

Nó không thường xuyên làm điều này trước khi bạn quyết định định dạng này tốt hơn nhiều so với thay thế của bạn. Ah, nhưng bạn có thể nội tuyến tất cả trong một dòng! enderland chết ở bên trong .

Hoặc này:

if   i>0 : return sqrt(i)  
elif i==0 and bar==0: return 0  
else     : return 1j * sqrt(-i)

Đó là thực sự, thực sự gây phiền nhiễu. Không ai thích định dạng những thứ như thế này.

Và cuối cùng, bạn sẽ bắt đầu cuộc chiến thần thánh về vấn đề "có bao nhiêu khoảng trống cho các tab". Những gì hiển thị hoàn hảo trên màn hình của bạn dưới dạng định dạng bảng có thể không hiển thị trên màn hình của tôi tùy thuộc vào cài đặt.

Khả năng đọc không nên phụ thuộc vào cài đặt IDE.


14
@horta vì ban đầu bạn sẽ phải chuyển đổi nó nếu bạn định dạng nó theo cách đầu tiên? Tôi là tất cả về việc giảm thiểu công việc cho enderland tương lai. Tạo các bảng khoảng trắng đẹp và đếm khoảng trắng và tab để cập nhật định dạng trực quan khi tôi có thể thêm một số logic vào nếu kiểm tra không vui chút nào (bỏ qua các hàm ý dễ đọc).
enderland

14
@horta Anh ấy không nhất thiết phải nói rằng anh ấy sẽ không sửa nó, anh ấy nói rằng anh ấy phải sửa nó, và đó là rất nhiều thời gian dành cho định dạng tẻ nhạt, thay vì lập trình.
Phục vụ

11
@horta: IMHO theo cách của bạn thường ít dễ đọc hơn và chắc chắn sẽ khó chịu hơn rất nhiều khi định dạng. Ngoài ra, nó chỉ có thể được sử dụng khi "ifs" là một lớp lót nhỏ, đây là trường hợp hiếm khi xảy ra. Cuối cùng, bằng cách nào đó, IMHO, không mang theo hai loại hình "nếu" vì điều này.
dagnelies

9
@horta bạn dường như được ban phước khi làm việc trên các hệ thống mà các yêu cầu, hệ thống, API và nhu cầu của người dùng không bao giờ thay đổi. Bạn may mắn tâm hồn.
thúc vào

11
Tôi muốn thêm: bất kỳ thay đổi nhỏ nào trong một điều kiện duy nhất có thể yêu cầu định dạng lại các :vị trí khác để phù hợp với vị trí -> thực hiện khác biệt trong CVS, điều đó đột nhiên trở nên khó hiểu hơn về những gì thực sự thay đổi. Điều này cũng đúng với điều kiện vs cơ thể. Có chúng trên các dòng riêng biệt có nghĩa là nếu bạn chỉ thay đổi một trong số chúng thì khác biệt rõ ràng cho thấy chỉ có điều kiện thay đổi, không phải cơ thể.
Bakuriu

55

Tôi là một người tin tưởng vững chắc vào 'mã được đọc nhiều lần, viết ít - vì vậy khả năng đọc là rất quan trọng.'

Một điều quan trọng giúp tôi khi tôi đọc mã của người khác là tuân theo các mẫu 'bình thường' mà mắt tôi được đào tạo để nhận ra. Tôi có thể đọc biểu mẫu thụt lề một cách dễ dàng nhất vì tôi đã thấy nó rất nhiều lần mà nó đăng ký gần như tự động (với một chút nỗ lực nhận thức từ phía tôi). Không phải vì nó 'đẹp hơn' - bởi vì nó tuân theo các quy ước mà tôi đã từng sử dụng. Nhịp đập 'tốt hơn' ...


3
Có liên quan: thecodlesscode.com/case/94
Kevin

11
Điều này giải thích tại sao mọi người bảo thủ. Nó không giải thích lý do tại sao mọi người chọn viết mã của họ theo một cách nhất định để bắt đầu.
Jørgen Fogh

8
Câu hỏi là "tại sao tôi thấy điều này thường xuyên", không phải phong cách này đến từ đâu. Cả hai câu hỏi đều thú vị; Tôi đã cố gắng trả lời câu hỏi mà tôi nghĩ đang được hỏi.
Nghệ thuật Swri

16

Cùng với các nhược điểm khác đã được đề cập, bố cục dạng bảng làm tăng tỷ lệ xung đột kiểm soát phiên bản yêu cầu can thiệp thủ công.

Khi một khối mã được sắp xếp theo bảng cần được sắp xếp lại, hệ thống kiểm soát phiên bản sẽ coi mỗi dòng đó đã được sửa đổi:

diff --git a/foo.rb b/foo.rb
index 40f7833..694d8fe 100644
--- a/foo.rb
+++ b/foo.rb
@@ -1,8 +1,8 @@
 class Foo

   def initialize(options)
-    @cached_metadata = options[:metadata]
-    @logger          = options[:logger]
+    @metadata = options[:metadata]
+    @logger   = options[:logger]
   end

 end

Bây giờ giả sử rằng trong thời gian trung bình, ở một nhánh khác, một lập trình viên đã thêm một dòng mới vào khối mã được căn chỉnh:

diff --git a/foo.rb b/foo.rb
index 40f7833..86648cb 100644
--- a/foo.rb
+++ b/foo.rb
@@ -3,6 +3,7 @@ class Foo
   def initialize(options)
     @cached_metadata = options[:metadata]
     @logger          = options[:logger]
+    @kittens         = options[:kittens]
   end

 end

Sáp nhập chi nhánh đó sẽ thất bại:

wayne@mercury:/tmp/foo$ git merge add_kittens
Auto-merging foo.rb
CONFLICT (content): Merge conflict in foo.rb
Automatic merge failed; fix conflicts and then commit the result.

Nếu mã được sửa đổi không được sử dụng căn chỉnh bảng, việc hợp nhất sẽ tự động thành công.

(Câu trả lời này là "đạo văn" từ bài viết của riêng tôi không khuyến khích căn chỉnh bảng trong mã).


1
Thú vị, nhưng đây không phải là một thất bại của các công cụ hợp nhất? Cụ thể là git trong trường hợp này? Đây là một datapoint hướng tới quy ước là cách dễ dàng để đi. Đối với tôi, đó là thứ có thể được cải thiện (từ phía công cụ).
horta

7
@horta Để công cụ hợp nhất sửa đổi khoảng trắng theo cách mà hầu như không phải lúc nào cũng phá mã, nó sẽ phải hiểu theo cách nào nó có thể sửa đổi khoảng trắng mà không thay đổi ý nghĩa của mã. Nó cũng sẽ phải hiểu sự liên kết bảng cụ thể đang được sử dụng. Điều đó sẽ không chỉ phụ thuộc vào ngôn ngữ (Python!), Mà có lẽ yêu cầu công cụ hiểu mã ở một mức độ nào đó. Mặt khác, việc hợp nhất dựa trên dòng có thể được thực hiện mà không cần AI và thường không phá vỡ mã.
Wayne Conrad

Gotcha. Vì vậy, như đã đề cập ở các bình luận khác, cho đến khi chúng ta có các định dạng đầu vào của IDE hoặc lập trình kết hợp các bảng trực tiếp vào định dạng, các vấn đề về công cụ sẽ luôn gây khó khăn cho những người trong chúng ta thích bảng.
horta

1
@horta Đúng. Hầu hết sự phản đối của tôi đối với việc căn chỉnh bảng trong mã có thể biến mất với các công cụ đủ tiên tiến.
Wayne Conrad

8

Các định dạng bảng có thể rất đẹp nếu mọi thứ luôn vừa với chiều rộng được phân bổ. Tuy nhiên, nếu có thứ gì đó vượt quá chiều rộng được phân bổ, thì thường cần phải có một phần của bảng không được xếp cùng với phần còn lại của bảng hoặc điều chỉnh bố cục của mọi thứ khác trong bảng để khớp với mục dài .

Nếu các tệp nguồn được chỉnh sửa bằng các chương trình được thiết kế để hoạt động với dữ liệu định dạng bảng và có thể xử lý các mục quá dài bằng cách sử dụng cỡ chữ nhỏ hơn, chia chúng thành hai dòng trong cùng một ô, v.v. thì có thể sử dụng bảng định dạng thường xuyên hơn, nhưng hầu hết các trình biên dịch muốn các tệp nguồn không có các loại đánh dấu mà các trình soạn thảo như vậy sẽ cần lưu trữ để duy trì định dạng. Sử dụng các dòng có số lượng thụt lề khác nhau nhưng không có bố cục nào khác không đẹp như định dạng bảng trong trường hợp tốt nhất, nhưng nó không gây ra gần như nhiều vấn đề trong trường hợp xấu nhất.


Thật. Tôi đã nhận thấy trình soạn thảo văn bản tôi sử dụng (vim) có hỗ trợ khủng khiếp cho định dạng bảng hoặc thậm chí văn bản rộng. Tôi chưa thấy các trình soạn thảo văn bản khác làm tốt hơn nhiều.
horta

6

Có một tuyên bố 'chuyển đổi' cung cấp loại điều này cho các trường hợp đặc biệt, nhưng tôi đoán đó không phải là những gì bạn đang hỏi về.

Tôi đã thấy nếu các câu lệnh ở định dạng bảng, nhưng phải có một số lượng lớn các điều kiện để làm cho nó đáng giá. 3 nếu các câu lệnh được hiển thị tốt nhất ở định dạng truyền thống, nhưng nếu bạn có 20, thì việc hiển thị chúng trong một khối lớn được định dạng để làm cho nó rõ ràng hơn nhiều.

Và có một điểm: sự rõ ràng. Nếu nó làm cho nó dễ nhìn hơn (và ví dụ đầu tiên của bạn không dễ thấy nơi: dấu phân cách) thì hãy định dạng nó cho phù hợp với tình huống. Mặt khác, hãy gắn bó với những gì mọi người mong đợi, vì điều đó luôn dễ nhận ra hơn.


1
OP dường như đang sử dụng Python, nên không switch.
Jared Smith

2
"3 nếu các câu lệnh được hiển thị tốt nhất ở định dạng truyền thống, nhưng nếu bạn có 20" ... thì bạn có vấn đề lớn hơn để suy nghĩ! :)
Grimm The Opiner

@GrimmTheOpiner Nếu bạn đang viết một trình phân tích cú pháp ngôn ngữ hoặc trình xâu chuỗi AST, đó là một điều rất khả thi để giải quyết. Ví dụ: tôi đã từng đóng góp cho trình phân tích cú pháp JavaScript khi tôi chia một hàm với 15-20 trường hợp, một trường hợp cho mỗi loại biểu thức. Tôi đã phân đoạn hầu hết các trường hợp theo chức năng riêng của họ (để tăng sự hoàn hảo đáng chú ý), nhưng lâu dài switchlà một điều cần thiết.
Isiah Meadows

@JaredSmith: Rõ ràng switchlà xấu xa, nhưng bắt đầu từ điển sau đó thực hiện tra cứu trên đó để thực hiện việc phân nhánh tầm thường không phải là xấu xa ...
Mark K Cowan

1
@MarkKCowan oh tôi bắt gặp sự mỉa mai nhưng nghĩ rằng bạn đang sử dụng nó để chế giễu tôi. thiếu bối cảnh trên internet và không có điều gì.
Jared Smith

1

Nếu biểu thức của bạn thực sự dễ dàng thì hầu hết các ngôn ngữ lập trình đều cung cấp toán tử phân nhánh ?:

return  ( i > 0  ) ? sqrt( i)
      : ( i == 0 ) ? 0
        /* else */ : 1j * sqrt( -i )

Đây là một định dạng bảng ngắn có thể đọc được. Nhưng phần quan trọng là: Tôi nhìn thoáng qua hành động "chính" là gì. Đây là một tuyên bố trở lại! Và giá trị được quyết định bởi các điều kiện nhất định.

Mặt khác, nếu bạn có các nhánh thực thi các mã khác nhau, tôi thấy nó dễ đọc hơn rất nhiều để thụt các khối này. Bởi vì bây giờ có các hành động "chính" khác nhau tùy thuộc vào câu lệnh if. Trong một trường hợp chúng tôi ném, trong một trường hợp chúng tôi đăng nhập và trả lại hoặc chỉ trả lại. Có một luồng chương trình khác nhau tùy thuộc vào logic, vì vậy các khối mã đóng gói các nhánh khác nhau và làm cho chúng nổi bật hơn cho nhà phát triển (ví dụ: đọc tốc độ một chức năng để nắm bắt luồng chương trình)

if ( i > 0 )
{
    throw new InvalidInputException(...);
}
else if ( i == 0 )
{
    return 0;
}
else
{
    log( "Calculating sqrt" );
    return sqrt( -i );
}

7
Trên thực tế, tôi thấy "định dạng bảng ngắn có thể đọc được" của bạn khá là một cơn ác mộng để đọc, trong khi định dạng do OP đề xuất là hoàn toàn tốt.
Matteo Italia

@MatteoItalia làm thế nào về phiên bản chỉnh sửa này?
Falco

5
Xin lỗi, vẫn tệ hơn; Tôi nghĩ rằng nó xuất phát từ thực tế là ?:khó phát hiện hơn so với if/ elsetừ khóa và / hoặc do "tiếng ồn" của các biểu tượng được thêm vào.
Matteo Italia

@MatteoItalia: Tôi đã gặp trường hợp với hơn trăm giá trị khác nhau. Giá trị bảng làm cho nó có thể kiểm tra lỗi. Với nhiều dòng, điều đó là không thể.
gnasher729

1
@ gnasher729 - Đối với 100 "giá trị" khác nhau, tôi thường thấy rằng sẽ tốt hơn nhiều khi khai báo cấu trúc dữ liệu của từng "mục" và liệt kê tất cả dưới dạng bảng trong phần khởi tạo cho một mảng các cấu trúc dữ liệu này. (Tất nhiên giới hạn ngôn ngữ có thể áp dụng ở đây). Nếu bất kỳ mục nào yêu cầu khía cạnh "tính toán", cấu trúc mục có thể chứa một con trỏ hoặc tham chiếu đến một hàm để thực hiện hành động cần thiết. Đối với các ứng dụng có thể, điều này có thể đơn giản hóa rất nhiều mã và giúp bảo trì dễ dàng hơn nhiều.
Michael Karas

1

Như enderland đã nói, bạn cho rằng bạn chỉ có một lần "trả lại" là hành động và bạn có thể gắn thẻ "trả lại" đó vào cuối điều kiện. Tôi muốn cung cấp thêm một số chi tiết về lý do tại sao điều này sẽ không thành công.

Tôi không biết ngôn ngữ ưa thích của bạn là gì, nhưng tôi đã mã hóa bằng C trong một thời gian dài. Có một số tiêu chuẩn mã hóa nhằm tránh một số lỗi mã hóa tiêu chuẩn bằng cách không tuân theo các cấu trúc mã dễ bị lỗi, trong mã hóa ban đầu hoặc trong quá trình bảo trì sau này. Tôi quen thuộc nhất với MISRA-C, nhưng có những người khác, và nói chung tất cả họ đều có các quy tắc tương tự vì họ đang giải quyết các vấn đề tương tự trong cùng một ngôn ngữ.

Một lỗi phổ biến mà các tiêu chuẩn mã hóa thường mắc phải là lỗi nhỏ này: -

if (x == 10)
    do_something();
    do_something_else();

Điều này không làm những gì bạn nghĩ nó làm. Theo như C có liên quan, nếu x là 10 thì bạn gọi do_something(), nhưng sau đó do_something_else()được gọi bất kể giá trị của x . Chỉ hành động ngay sau câu lệnh "nếu" là có điều kiện. Đây có thể là những gì các lập trình viên dự định, trong trường hợp đó có một bẫy tiềm năng cho các nhà bảo trì; hoặc nó có thể không phải là những gì lập trình viên dự định, trong trường hợp đó có một lỗi. Đó là một câu hỏi phỏng vấn phổ biến.

Giải pháp trong các tiêu chuẩn mã hóa là bắt buộc niềng răng xung quanh tất cả các hành động có điều kiện, ngay cả khi chúng là dòng đơn. Bây giờ chúng tôi nhận được

if (x == 10)
{
    do_something();
    do_something_else();
}

hoặc là

if (x == 10)
{
    do_something();
}
do_something_else();

và bây giờ nó hoạt động chính xác và rõ ràng cho người bảo trì.

Bạn sẽ nhận thấy rằng điều này hoàn toàn không tương thích với định dạng kiểu bảng của bạn.

Một số ngôn ngữ khác (ví dụ Python) đã xem xét vấn đề này và quyết định rằng vì các lập trình viên đang sử dụng khoảng trắng để làm cho bố cục rõ ràng, nên sử dụng khoảng trắng thay vì dấu ngoặc. Vì vậy, trong Python,

if x == 10:
    do_something()
    do_something_else()

thực hiện các cuộc gọi đến cả hai do_something()và có do_something_else()điều kiện trên x == 10, trong khi đó

if x == 10:
    do_something()
do_something_else()

có nghĩa là chỉ do_something()có điều kiện trên x và do_something_else()luôn được gọi.

Đó là một khái niệm hợp lệ và bạn sẽ tìm thấy một vài ngôn ngữ sử dụng nó. (Lần đầu tiên tôi nhìn thấy nó trong Occam2, trở lại khi.) Một lần nữa, bạn có thể dễ dàng thấy rằng định dạng kiểu bảng của bạn không tương thích với ngôn ngữ.


1
Tôi nghĩ rằng bạn bị mất điểm. Vấn đề bạn nói đến là một cơn ác mộng phi tiêu chuẩn cụ thể C kỳ lạ gây ra vấn đề bạn nói đến. Nếu mã hóa bằng C, tôi sẽ không bao giờ khuyên bạn nên sử dụng phương pháp đơn giản thay thế với định dạng bảng mà tôi đề xuất. Thay vào đó, vì bạn đang sử dụng C, bạn sẽ sử dụng tất cả các dấu ngoặc trên một dòng. Các dấu ngoặc nhọn thực sự sẽ làm cho định dạng bảng thậm chí rõ ràng hơn vì chúng đóng vai trò là các dấu phân cách.
horta

Ngoài ra, các báo cáo trả lại trong trường hợp này chỉ là một ví dụ. Nói chung, đó có thể là mùi mã trong chính nó. Tôi chỉ đề cập đến định dạng của các câu lệnh đơn giản, không nhất thiết phải có câu lệnh return.
horta

2
Quan điểm của tôi là điều này làm cho một định dạng bảng thậm chí còn cồng kềnh hơn. Ngẫu nhiên, nó không dành riêng cho C - nó được chia sẻ bởi tất cả các ngôn ngữ có nguồn gốc từ C, vì vậy C ++, C #, Java và JavaScript đều cho phép cùng một hình ảnh xác thực.
Graham

1
Tôi không bận tâm rằng đó là tuyên bố trả lại - Tôi hiểu rằng ý định của bạn là hiển thị các tuyên bố đơn giản. Nhưng nó trở nên cồng kềnh hơn. Và tất nhiên ngay khi bất kỳ câu lệnh nào trở nên không đơn giản, thì bạn cần thay đổi định dạng vì không thể duy trì định dạng bảng. Trừ khi bạn đang thực hiện mã obfuscation, các dòng mã dài là một mùi theo cách riêng của họ. (Giới hạn ban đầu là 80 ký tự, ngày nay, thông thường là khoảng 130 ký tự, nhưng nguyên tắc chung vẫn cho rằng bạn không cần phải cuộn để xem cuối dòng.)
Graham

1

Bố cục dạng bảng có thể hữu ích trong một số trường hợp giới hạn, nhưng có vài lần nó hữu ích với if.

Trong trường hợp đơn giản ?: Có thể là một lựa chọn tốt hơn. Trong trường hợp trung bình, một công tắc thường phù hợp hơn (nếu ngôn ngữ của bạn có). Trong các trường hợp phức tạp, bạn có thể thấy rằng một bảng gọi phù hợp hơn.

Đã nhiều lần khi tái cấu trúc mã mà tôi đã sắp xếp lại thành dạng bảng để làm cho nó rõ ràng. Rất hiếm khi tôi để nó như vậy trong hầu hết các trường hợp, có một cách tốt hơn để giải quyết vấn đề một khi bạn hiểu nó. Đôi khi, một tiêu chuẩn thực hành hoặc bố cục mã hóa cấm nó, trong trường hợp đó một nhận xét là hữu ích.

Có một số câu hỏi về ?:. Vâng, đó là toán tử ternary (hoặc như tôi muốn nghĩ về nó nếu giá trị). trong lần đầu tiên, ví dụ này hơi phức tạp đối với ?: (và quá lạm dụng? giải pháp.

if i==0: return 0
return i>0?sqrt(i):(1j*sqrt(-i))

1
Bạn có thể phải làm rõ "?:" Dành cho người không quen biết (ví dụ: với một ví dụ, có thể liên quan đến câu hỏi).
Peter Mortensen

Tôi cho rằng đó là toán tử ternary. Tôi cảm thấy như bị xa lánh vì lý do chính đáng rằng nhà điều hành ternary có xu hướng sắp xếp lại tiêu chuẩn nếu, làm công cụ, khác, làm định dạng công cụ khác mà mọi người thấy ngày này qua ngày khác và do đó có thể đọc dễ dàng.
horta

@PeterMortensen: Nếu người không quen biết điều này có nghĩa là gì, họ nên tránh xa mã cho đến khi họ hỏi câu hỏi rõ ràng và học được.
gnasher729

@horta Ternary là if ? do stuff : do other stuff. Tương tự như một if / khác.
Navin

1
@Navin À, có lẽ đó chỉ là sự thất bại của ngôn ngữ tôi sử dụng nhiều nhất (python). stackoverflow.com/questions/394809/
trộm

-3

Tôi không thấy bất cứ điều gì sai với định dạng bảng. Sở thích cá nhân, nhưng tôi sẽ sử dụng một ternary như thế này:

return i>0  ? sqrt(i)       :
       i==0 ? 0             :
              1j * sqrt(-i)

Không cần lặp lại returnmỗi lần :)


1
Như đã đề cập trong một vài bình luận, các tuyên bố trả lại không lý tưởng hoặc điểm chính của bài đăng, chỉ đơn giản là một đoạn mã tôi tìm thấy trên mạng và định dạng một vài cách.
horta

Chim nhạn Python là do_something() if condition() else do_something_else(), không condition() ? do_something() : do_something_else().
Isiah Meadows

@IsiahMeadows OP không bao giờ đề cập đến Python.
Navin
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.