Khi nào đánh giá ngắn mạch là xấu?


12

Nói rõ hơn một chút, tôi sẽ nói rằng tôi đã dành nhiều thời gian với các ngôn ngữ khác nhau. Nhưng cho đến bây giờ, nó sẽ sử dụng nó mọi lúc hoặc hoàn toàn không hỗ trợ nó.

Bây giờ công việc đã cho tôi bắt đầu vào các dự án yêu cầu VB.net và tôi thấy nó cung cấp cả hai cách về ANDANDALSO . Cái thứ nhất không bị đoản mạch, và cái thứ hai thì không.

Vì vậy, điều này khiến tôi tự hỏi tại sao? Khi thiết lập nó như thế này dường như ngụ ý rằng nó sẽ xuất hiện khá thường xuyên mà người ta muốn chuyển đổi chế độ. Nhưng tôi không thể nghĩ ra bất kỳ tình huống nào sẽ là điều tồi tệ khi sử dụng Short Circuit .

Tôi biết điều này rất có thể có được nhiều thứ tùy chọn hơn, vì vậy nếu tôi cần đặt nó ở một nơi khác, chỉ cần cho tôi biết nơi.

Mặc dù tôi hy vọng có ít nhất một câu trả lời chính thức, nhưng tại sao có cả hai lựa chọn sẽ tốt hơn sau đó luôn luôn thực hiện Short Circuit , khi nó có sẵn.



Câu trả lời:


5

Một số thuật ngữ trong một biểu thức logic có thể có tác dụng phụ. Đôi khi cần phải đảm bảo tất cả các tác dụng phụ xảy ra theo thứ tự đã nêu và không có tác dụng nào bị bỏ qua và đó là kết quả đánh giá hướng dẫn logic:

if not (PushAirPlane(thrust) and TurnAirplane(vector)), SimulateCrash(severity)

Trong các trường hợp khác, bạn không muốn đánh giá bất kỳ điều khoản nào còn lại nếu đánh giá trước đó trả về sai.

if IsAirborne() and not (PushAirPlane(thrust) and TurnAirplane(vector)), SimulateCrash(severity)

Một số người sẽ / đã lập luận rằng việc dựa vào hành vi ngắn mạch trong ví dụ thứ hai là hình thức xấu, nhưng đó là đi vào phong cách mã hóa và hệ thống niềm tin. Có rất nhiều đoạn mã rất hay trên thế giới phụ thuộc vào gần như mọi tính năng mà ngôn ngữ cung cấp, và đó chính là cách nó diễn ra.

ANDALSO của VB rất sắc nét và dường như là một nỗ lực để thực hành dễ chấp nhận hơn.

Như JimmyJames chỉ ra trong câu trả lời của mình, có thể có những hàm ý hiệu suất có thể đo lường được xung quanh việc đánh giá ngắn mạch. Các ngôn ngữ không cung cấp cơ chế, luôn đánh giá mọi thuật ngữ của biểu thức, trong khi các ngôn ngữ cung cấp nó, có thể tạo ra các câu lệnh nhánh bổ sung. Dù bằng cách nào, phần lớn phụ thuộc vào số bước xử lý cần thiết để đánh giá từng điều khoản và cũng dựa trên kiến ​​trúc trình biên dịch và CPU. Thông thường bạn sẽ không quan tâm đến những điều như vậy cho đến khi bạn có một nút thắt được đo lường trong mã và cần tìm ra cách làm giảm bớt nó. Bất kỳ quy tắc nào hoặc không liên quan đến việc cho phép đánh giá ngắn mạch trong mã của bạn sẽ có khả năng gây ra mã chậm hơn và tối ưu hóa sớm có thể gây lãng phí toàn bộ thời gian, vì vậy hãy luôn đo lường, sau đó tối ưu hóa.


4
Trong khi thực tế chính xác, nó không phải là một thiết kế tuyệt vời.
Robert Harvey

2
@RobertHarvey, tôi không thể viết một hệ thống kiểm soát không có tác dụng phụ và tôi không thể điều khiển hệ thống chính xác nếu tôi không phản ứng với kết quả. Nói cách khác, vượt qua nó;).
jwdonahue

7
Không, nhưng bạn có thể gán kết quả của các hàm tác dụng phụ đó cho các biến boolean, kiểm tra các biến đó trong ifđiều kiện của bạn và vẫn bị đoản mạch. Tôi đồng ý rằng, theo một cách nào đó, đó là một sự khác biệt về phong cách, nhưng nó có đức tính làm cho mọi thứ rõ ràng.
Robert Harvey

3
@jwdonahue Sử dụng "từ lớn" cũng không sao nếu nguy cơ nhầm lẫn thấp. Nguy cơ nhầm lẫn và thiếu các sắc thái đặc biệt của một khối mã như thế này là cực kỳ cao và có thể là thảm họa đối với logic. Không bao giờ tốt để làm cho nhà phát triển đọc suy nghĩ rất khó khăn.
jpmc26

5
"Một số thuật ngữ trong biểu thức logic có thể có tác dụng phụ" - Mặc dù tuyên bố mở đầu này là chính xác, tôi cảm thấy câu trả lời này không thành công khi không chỉ ra rằng dựa vào tác dụng phụ là xấu . Trên thực tế, tệ hơn nhiều so với việc dựa vào đánh giá ngắn mạch để ngăn chặn các đánh giá giả. Mà câu trả lời này không gợi ý có thể là hình thức xấu.
aroth

20

Rõ ràng, câu hỏi của bạn không phải là về việc ngắn mạch nói chung là tốt hay xấu, mà là về lý do tại sao VB.NET cung cấp các toán tử có và không có nó. Với suy nghĩ này, câu trả lời cho

Khi nào thì đánh giá ngắn mạch xấu?

chỉ đơn giản là: khi nó vi phạm khả năng tương thích ngược .

Ok, bây giờ bạn có thể nói VB.NET không tương thích ngược với VB6 hoặc VBA cũ, tuy nhiên ít nhất một số phần của ngôn ngữ là. Quyết định của Microsoft về việc giữ ngữ nghĩa AND và OR cũ (không bị đoản mạch) đã tạo ra một loại lỗi rất lớn ít xảy ra khi chuyển các chương trình VB cũ sang VB.NET.

Mặt khác, các nhà thiết kế ngôn ngữ VB.NET có thể đã chia sẻ ý kiến ​​của bạn về việc đoản mạch là một điều tốt. Khi tôi nhớ chính xác, các phiên bản tiền phát hành VB.NET đầu tiên cung cấp cho các toán tử AND hoặc OR bị đoản mạch, nhưng phản hồi của nhà phát triển phải rất tệ khi MS rút quyết định này trước khi VB.NET 1.0 xuất hiện. Vì vậy, các nhà thiết kế đã quyết định triển khai nó theo các từ khóa mới ANDALSOORELSEnhư một sự đánh đổi giữa tính tương thích và tính hữu dụng ngược.

IMHO đây là một quyết định tốt. Tôi đã phải chuyển một số chương trình cũ hơn trong thập kỷ qua và không phải phân tích tác động nặng nề cho mọi biểu hiện logic bao gồm AND và / hoặc OR (ý định chơi chữ) khiến cho công việc đó trở nên dễ dàng và kinh tế hơn rất nhiều. Mặt khác, bất cứ khi nào tôi phải viết một biểu thức logic mới trong VB.NET, lựa chọn mặc định của tôi cho các toán tử là các dạng ngắn mạch, đó là những gì tôi đã sử dụng từ C, C ++, C #, v.v. tôi viết một số thành ngữ ở dạng ngắn gọn hơn (ngay cả khi ANDALSO cần thêm 4 ký tự để gõ).

Nếu bạn không bị thuyết phục, tôi khuyên bạn nên đọc bài viết tuyệt vời của Joel Spolsky về Tai nghe sao Hỏa , đó là lý do tại sao các quyết định thiết kế ban đầu trong phát triển phần mềm có thể dễ dàng bị thu hồi sau khi thành phần hoặc ngôn ngữ hoặc API được đặt ở một cơ sở người dùng có kích thước nhất định .


Ok, điều này đủ điều kiện là một cơn thịnh nộ và liên kết đến Tai nghe sao Hỏa dường như không liên quan gì cả.
jwdonahue

6
@jwdonahue: Tôi không biết tại sao bạn lại nghĩ đây là một câu nói hay, hoàn toàn ngược lại. Và bài báo về Tai nghe sao Hỏa là về lý do tại sao một số quyết định thiết kế trong phát triển phần mềm được thực hiện vài thập kỷ trước không thể dễ dàng bị thu hồi sau khi thành phần hoặc ngôn ngữ hoặc API đã đạt đến một cơ sở người dùng có kích thước nhất định. Không phải là tương tự thực sự rất khó để nắm bắt? VB6 đã rất phổ biến trong quá khứ và tôi chắc chắn vẫn còn hàng trăm ngàn công ty trên thế giới có các ứng dụng quan trọng chạy trong VB6 hoặc VBA.
Doc Brown

Tôi hoàn toàn không thấy bài báo "Những người đứng đầu sao Hỏa" thực sự phù hợp như thế nào. Điều cần thiết để đảm bảo khả năng tương tác giữa X và Y (ví dụ: đai ốc và bu lông) là phải có các tiêu chuẩn riêng cho X và Y, sao cho đai ốc trong trường hợp xấu nhất sẽ chứa một bu-lông kém hơn so với chỉ định và ngược lại. Người ta nên cố gắng viết các thông số kỹ thuật để tránh làm cho các đai ốc hoặc bu lông trở nên đắt đỏ không cần thiết, hoặc có một lượng trượt không cần thiết giữa các đai ốc và bu lông, nhưng chỉ định cả hai nửa riêng biệt để có thể đảm bảo khả năng tương tác đáng tin cậy hơn nhiều so với cố gắng có một thông số kỹ thuật Phục vụ cả hai bên.
supercat

3
@supercat: đây là về việc đã có hàng nghìn tỷ hạt (hoặc dòng mã VB6) hiện có và đang sử dụng, và bây giờ các bu lông (hoặc trong trường hợp này là trình biên dịch VB) sẽ được thay thế bằng thế hệ mới hơn. Nếu các đai ốc hiện có chỉ phù hợp với các bu lông phi số liệu, thì việc tạo ra các hệ thống bu lông mới hơn chỉ là kinh tế.
Doc Brown

tl; dr: VB là một phương ngữ của BASIC, một ngôn ngữ có từ năm 1964 và trong BASIC, Andhoạt động này không bị đoản mạch, cũng không phải là SQL (1974), cũng không phải FORTRAN (1956), cũng không phải Pascal (1970).
Bến

3

Khi nào đánh giá ngắn tuần hoàn xấu?

Chúng trở nên xấu , ngay khi bạn bắt đầu dựa vào các tác dụng phụ của các biểu thức mà bạn mong đợi sẽ được thực hiện trong việc đánh giá kết quả tổng thể boolean.


1

Hãy cẩn thận: Đây là một chút bí truyền trong hầu hết các trường hợp, các nhà phát triển không nên lo lắng về nó. Nhưng ... có thể có một cú đánh hiệu suất do đánh giá có điều kiện vì nó tạo ra sự phân nhánh trong thực thi. Một hoạt động không ngắn mạch không phân nhánh và dễ dự đoán hơn.

Lý do điều này hiếm khi quan trọng là chi phí thường nhỏ và cũng thường vượt trội so với chi phí đánh giá điều kiện thứ hai (hoặc thứ ba, v.v.). Điều này sẽ chỉ trở thành vấn đề trong các thói quen đắt tiền tính toán khi cần hiệu suất cao và nó vẫn có thể không còn quan trọng nữa.


Tôi nghĩ rằng bạn chỉ có thể tối ưu hóa một tuyên bố hợp lý cho đến nay, cuối cùng bạn phải lấy chi nhánh.
jwdonahue

@jwdonahue Tôi không hiểu ý bạn. Lấy làm tiếc.
JimmyJames

Chúng ta đang nói về logic tổ hợp ở đây. Đánh giá ngắn mạch hay không, bạn có một hoặc nhiều thuật ngữ phải được đánh giá tùy thuộc vào kết quả của một thuật ngữ trước đó. Do đó, phân nhánh có liên quan.
jwdonahue

1
@jwdonahue Tất nhiên nhưng mỗi lần ngắn mạch là một nhánh bổ sung. Trong một số trường hợp nhất định, việc thực hiện hai biểu thức (ví dụ) nhanh hơn kiểm tra kết quả của lần đầu tiên trước khi thực hiện lần thứ hai ngay cả khi trường hợp thứ hai không liên quan. Một lần nữa, điều này hiếm khi quan trọng. Trường hợp ai đó làm cho tôi vì điều này là cho những thứ như nhân ma trận trong đó bạn có rất nhiều đánh giá đơn giản.
JimmyJames

1
Tôi cập nhật câu trả lời của tôi với tín dụng cho bạn.
jwdonahue

0

Pascal không xác định liệu AND và OR có sử dụng đánh giá ngắn mạch hay không, mang lại cho bạn điều tồi tệ nhất của cả hai thế giới.

C và C ++ có các phép toán bitwise & và | trong thực tế cung cấp cho bạn các hoạt động không ngắn mạch. Và trình biên dịch có thể tự do đánh giá bất kỳ cách nào họ thích nếu nó không tạo ra sự khác biệt có thể quan sát được.


@Ded repeatator: Như đã lưu ý, Pascal không xác định liệu AND / OR có sử dụng đánh giá ngắn mạch hay không. Điều đó có nghĩa là "không biết".
supercat
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.