Bảo trì khôn ngoan, là 'khác trong khi' mà không can thiệp niềng răng được coi là an toàn?


26

else whilekhông can thiệp niềng răng được coi là bảo trì "an toàn" khôn ngoan?

Viết if-elsemã mà không cần niềng răng như dưới đây ...

if (blah)
    foo();
else
    bar();

... Rủi ro vì thiếu niềng răng khiến việc thay đổi ý nghĩa của mã vô tình rất dễ dàng.

Tuy nhiên, dưới đây cũng có rủi ro?

if (blah)
{
    ...
}
else while (!bloop())
{
    bar();
}

Hoặc là else whilekhông can thiệp niềng răng được coi là "an toàn"?


20
với tôi có else whilevẻ icky. Tôi sẽ sử dụng else { while (condition) { ... } }.
Joachim Sauer

7
Tôi nghĩ rằng nó quá chủ quan cho một câu trả lời thích hợp ... Tôi sẽ không làm điều đó vì tôi sẽ không mong đợi một vòng lặp ở đó, và nghĩ rằng tôi không mong đợi làm cho việc đọc trở nên khó khăn.
johannes

7
Tôi sẽ trích xuất phương thức cho while-Stuff
gnat

12
Thành thật mà nói, nó cho tôi cây leo. ifchỉ được đánh giá một lần, nhưng whilebiểu thị một vòng lặp, do đó, việc kết nối cả hai mang lại cho tôi cảm giác không có căn cứ rằng đó iflà một phần của vòng lặp ... bằng cách nào đó ...
user281377

4
Và nếu trong elsemệnh đề bạn muốn làm while làm gì đó nhiều hơn thì sao? Chỉ cần sử dụng niềng răng, xin vui lòng.
Carlos Campderrós

Câu trả lời:


57

Điều đó nhắc nhở tôi mã này:

if ( ... ) try {
..
} catch (Exception e) {
..
} else {
...
}

Mỗi khi bạn kết hợp hai loại khối, quên niềng răng và không tăng thụt, bạn đang tạo mã rất khó hiểu và duy trì.


18
Ví dụ tốt. Thật là một cách khủng khiếp để viết nó.
Leo

4
Wow, câu trả lời này là vô cùng thuyết phục!
Mehrdad

Bạn có thể dễ dàng thiết lập các IDE hiện đại để tự động định dạng mã khi lưu - bao gồm chèn niềng răng và sửa vết lõm. Vì vậy, đây chỉ là một nửa đối số. Việc thụt lề đúng cách này sẽ không gây ra vấn đề gì cho khả năng đọc, cho dù có niềng răng hay không.
Hans-Peter Störr

55

Có lẽ đó là vì tôi đã học được giao dịch của mình (từ khi trở về) bằng cách sử dụng phương pháp Sơ đồ cấu trúc thực thể Jackson , nhưng tôi đăng ký với quan điểm rằng thuật ngữ không liên kết chính xác duy nhất sau một ifhoặc một elselà tiếp theo if(nghĩa là cho phép một else ifbậc thang)

Bất cứ điều gì khác (không có ý định chơi chữ) đều tiềm ẩn những hiểu lầm và / hoặc vấn đề bảo trì. Đó là khía cạnh trung tâm của ý tưởng OP là "không an toàn".

Tôi cũng sẽ rất thận trọng trong việc bao gồm while()cùng một dòng với else- dù có giằng hay không. Nó không đọc đúng với tôi ... việc thiếu bất kỳ mặt nạ thụt đầu dòng nào mà nó là elsemệnh đề. Và thiếu rõ ràng làm cho sự hiểu lầm (xem ở trên).

Vì vậy, trong ví dụ tôi rất muốn khuyên / giới thiệu (và nhấn mạnh, trong nhóm của tôi) về:

if ( blah )
{
    ...
}
else
{
    while ( !bloop() )
    {
        bar();
    }
}

Tất nhiên, tôi cũng mong đợi để xem bình luận phù hợp quá.

-- Chỉnh sửa --

Gần đây, Apple đã bị một lỗ hổng SSL, gây ra bởi một bản sửa lỗi bảo trì kém - đã thêm một dòng thứ hai vào một dòng duy nhất không có dấu ngoặc. Vì vậy, hãy đặt ra ý tưởng rằng các dòng đơn không có dấu là OK?


2
Tôi đồng ý nếu là thuật ngữ chính xác duy nhất để theo dõi người khác. Nếu có một cái else whiletôi có lẽ thậm chí sẽ không nhận thấy có một vòng lặp trong việc lướt nhanh mã, đặc biệt là nếu điều kiện tôi đang tìm kiếm được thỏa mãn bởi nếu.
Drake Clarris

3
Thật buồn cười. Mọi người đều nói rằng nó dễ đọc hơn nếu mọi thứ đều trong niềng răng. Tôi thấy điều ngược lại là đúng. Nếu đó chỉ là một tuyên bố, việc giữ nó ra khỏi niềng răng sẽ giúp bạn dễ đọc hơn. Ít bừa bộn. Nó có thể chỉ bởi vì tôi đã luôn luôn làm theo cách đó.
Jeff Davis

2
@JeffDavis đó là một đánh bắt tốt. "Dễ đọc hơn" là một lời mời điển hình cho cuộc chiến thánh vô dụng. Tôi đối với một người thích niềng răng, nhưng không phải vì rác "dễ dàng" không liên quan (ví dụ với tôi là hoàn toàn ngược lại) mà vì khó phá vỡ hơn trong bảo trì mã. Bằng cách OP đánh vần nó tốt hơn trong câu hỏi của họ: else whilekhông can thiệp niềng răng được coi là "an toàn" ?
gnat

@JeffDavis - Tôi biết chủ đề này đã được hai năm tuổi, nhưng Apple gần đây đã phát hiện ra lý do tại sao không sử dụng niềng răng không phải là một ý tưởng hay andrewbanks.com / Kẻ
Andrew

@Andrew Nhân tiện, ngôn ngữ Swift của Apple hiện rõ ràng cấm kiểm soát luồng một dòng. Lỗi đó có thể là một trong những lý do để làm như vậy.
Sulthan

6

Tôi luôn được dạy giữ mọi thứ trong niềng răng, thụt lề và bình luận. Tôi tin rằng nó dễ dàng hơn nhiều để đọc và phát hiện lỗi. Cá nhân tôi cảm thấy tính mô đun là chính vì vậy tôi sẽ luôn viết mã như thế này:

    if(blah)
    {
     ....
    }
    else
    {
       while(!bloop()
       {
        bar;
       }
    }

6

Tôi sẽ trích xuất phương pháp và làm cho nó

if ( blah )
{
    ...
}
else
{
   newMethod();
}

Xem cách tiếp cận "phương pháp trích xuất" được giải thích tại trang Danh mục tái cấu trúc :

Bạn có một đoạn mã có thể được nhóm lại với nhau.

Biến đoạn này thành một phương thức có tên giải thích mục đích của phương thức.

void printOwing() {
    printBanner();

    //print details
    System.out.println ("name:    " + _name);
    System.out.println ("amount    " + getOutstanding());
}

                                                                                                         http://www.refactoring.com/catalog/arrow.gif

void printOwing() {
    printBanner();
    printDetails(getOutstanding());
}

void printDetails (double outstanding) {
    System.out.println ("name:    " + _name);
    System.out.println ("amount    " + outstanding);
}

Phụ thuộc ... nếu ví dụ, vòng lặp while đã sử dụng dữ liệu mức chức năng, giờ đây bạn phải thêm dữ liệu đó vào cấp mô-đun (hoặc lớp, nếu sử dụng mức C ++). Và nếu chỉ là một đoạn mã nhỏ, bạn sẽ tham gia vào các phương thức tầm thường. Nhưng đôi khi, tùy thuộc vào hoàn cảnh, tôi đồng ý.
Andrew

1
+1 Trình biên dịch C ++ thông minh có thể nội tuyến một chức năng. Trong môi trường .Net, các chức năng nhỏ sẽ tốt hơn do JIT.
Công việc

4

Tôi sẽ coi đó là một thói quen xấu của tiền mã hóa. Đôi khi nó hoạt động hoàn toàn tốt và bạn sẽ không gặp vấn đề gì trong việc biên dịch và chạy mã. Vào những thời điểm khác, nó có thể gây ra lỗi nghiêm trọng và cuối cùng bạn sẽ mất hàng giờ để sửa lỗi đó.

Nó luôn luôn được khuyến nghị để mô đun hóa mã của bạn. Nếu bạn phải đặt một vòng lặp while trong phần khác, hãy đặt nó vào một khối để những người khác, khi làm việc với mã của bạn có thể dễ dàng hiểu được logic.

if ( blah )
{
    ...
}
else
{
    while ( !bloop() )
    {
        bar();
    }
}

Đó là một thực hành tốt để đặt mã trong các khối. Nó làm cho nó đơn giản và dễ hiểu hơn và gỡ lỗi là tốt.


4

Có thể sẽ ổn nếu nó vẫn đơn giản như vậy mặc dù cá nhân tôi không thích nó và sở thích của tôi là sử dụng niềng răng ngay cả đối với các khối mã if / other đơn giản nhất. Nó chỉ gọn gàng hơn đối với tôi.

Tuy nhiên, nơi điều này trở nên lộn xộn là khi bạn đã lồng vào nhau nếu / khác lặp một số vòng có một số không có. Một vòng lặp While ở giữa tất cả các spaghetti! Tôi đã làm việc với mã xấu và đó là một cơn ác mộng để gỡ lỗi và hiểu. Điều này tiếp nối từ điểm đầu tiên, nó ổn khi nó đơn giản và bạn hài lòng với nó, nhưng sau đó các lập trình viên khác xuất hiện và thêm mọi thứ vào đó, có thể là một thứ khác trong vòng lặp while. Nếu nó được viết sạch ở nơi đầu tiên thì sẽ ít có cơ hội điều này xảy ra.

Vấn đề là làm cho mọi thứ rõ ràng để các lập trình viên khác có thể thấy trong nháy mắt những gì đúng và sai. Viết mã để mô hình trông đúng và không bình.

Mặt trái của điều này là có lẽ tôi có thể thấy một số người tuyên bố rằng trong một số trường hợp nhất định, điều này đọc tốt. Nếu tôi có tài nguyên tôi cần thực hiện việc xử lý này trong khi tôi đang chờ đợi một cái gì đó làm điều này. Ngay cả với tôi vẫn không có sự khác biệt nào trong việc lồng vòng lặp while bên trong khối khác.


3

Chà, mặc dù mọi người tranh cãi về việc sử dụng niềng răng và dường như yêu thích chúng, tôi thực sự thích điều ngược lại. Tôi chỉ sử dụng niềng răng khi tôi phải bởi vì tôi thấy nó dễ đọc và súc tích hơn mà không có.

if (...)
   foo();
else while(...)
   bar();

... Tôi thực sự tìm thấy điều này " else while(...)" đáng chú ý có thể đọc được! Nó thậm chí đọc như tiếng Anh đơn giản! Nhưng tôi đoán tất cả mọi người sẽ thấy lạ vì ít nhất là không bình thường.

Cuối cùng, tất cả chúng ta đều có xu hướng làm cho nó trở nên ngớ ngẩn với niềng răng mặc dù ... bởi vì, bạn biết đấy.


3
điều đó sẽ đặc biệt dễ đọc sau khi một số người bảo trì vô tội thay đổi else while(...) bar();thành một cái gì đó như else while(...) foobar(); bar();:)
gnat

3
tốt, tôi sẽ nói rằng đó là một người duy trì vô tội khá ngu ngốc và nguy hiểm . Tôi biết nguyên tắc làm giảm nó xuống để tránh những lỗi ngu ngốc ... nhưng đến nay vẫn còn khá buồn. Nhưng tôi biết tôi sẽ nhận được những bình luận và đánh giá thấp như vậy. Không vấn đề gì.
dagnelies

2
"Luôn luôn mã như thể người sẽ duy trì mã của bạn là một kẻ tâm thần bạo lực, người biết bạn sống ở đâu." ( Alan Braggins )
gnat

1
Chà, mọi thứ sôi sùng sục đến mức bạn cho rằng mức độ ngu ngốc nhất của một người làm việc với mã của bạn sẽ là. Tôi lập luận rằng nếu "người bảo trì" của bạn bị nhầm lẫn bởi bốn dòng mã này ... thì bạn có vấn đề lớn trong tay. Và nếu đó là một tâm lý bạo lực, bạn có hai. ;)
dagnelies

1
nếu - cũng là liên kết mà tôi giới thiệu ở trên, đã mở rộng phiên bản của trích dẫn này: Lập trình viên 1: 'Có một câu trích dẫn hay ở đây - "Luôn luôn viết mã như thể người sẽ duy trì mã của bạn là một kẻ tâm thần bạo lực biết bạn sống ở đâu"' . Lập trình viên 2: (Nhìn qua người bảo trì) 'Ý bạn là gì "như thể"?'
gnat

2

Tôi luôn đặt niềng răng, chỉ vì bạn có thể thêm một dòng khác khi vội vàng, thụt nó, quên niềng răng và gãi đầu những gì đang xảy ra. Tôi giữ khung mở trên cùng một dòng, nhưng nó không thành vấn đề. Tôi cả hai trường hợp tốt hơn là có chúng.

if(blah) {
    foo();
}
else {
    bar();
}

Định vị niềng răng có thể gây ra tranh luận nhiều hơn bất cứ điều gì ngoài (hoặc có thể bao gồm) tôn giáo!
Andrew

Đã đồng ý. Sẽ chỉnh sửa câu trả lời của tôi để nhấn mạnh vào sự tồn tại của họ, không phải vị trí.
Tsvetomir Dimitrov

2

Có gì sai với niềng răng mà rất nhiều người đang cố gắng tránh viết chúng?

Vấn đề gì làm chính xác else while giải quyết ?

Niềng răng là rẻ và tốt, và họ làm cho ý định mã rõ ràng và rõ ràng trái ngược với thông minh và dí dỏm.

Trích dẫn triết lý Unix:

Quy tắc rõ ràng: Rõ ràng tốt hơn thông minh.

Bởi vì bảo trì rất quan trọng và tốn kém, hãy viết các chương trình như thể giao tiếp quan trọng nhất họ làm không phải là máy tính thực thi chúng mà là con người sẽ đọc và duy trì mã nguồn trong tương lai (bao gồm cả chính bạn).


1

Không có gì sai với

if (blah)
    foo();
else
    bar();

giống như không có gì sai với

if (blah) foo(); else bar();

trong trường hợp phù hợp (hoàn cảnh của bạn có thể khác nhau, nhưng phong cách cụ thể đó được sử dụng tốt nhất khi bạn có nhiều mã lặp đi lặp lại - thì chế độ xem của mỗi dòng quan trọng hơn thụt lề kiểu cách)

Nhưng nếu bạn chọn một cách, hãy giữ vững - sự nhất quán là vua. Vì vậy, ví dụ thứ hai của bạn là rất xấu, vì biểu thức if có dấu ngoặc cho câu lệnh của nó, câu lệnh while phải nằm trong dấu ngoặc cho mệnh đề khác, không nằm ngoài nó.


Ngoài ra, tôi đã thấy mã này trước đây:

if (x) foo()
{
  bar();
}

và nó được viết bởi chính tiêu chuẩn mã hóa nazi (người khăng khăng đòi ngoặc cho mọi thứ).


1

Các IDE hiện đại có thể dễ dàng được cấu hình để định dạng lại (bao gồm loại bỏ hoặc thêm các dấu ngoặc không cần thiết) và / hoặc giới thiệu lại mã khi lưu tệp. Do đó, ví dụ của bạn sẽ tự động trông giống như ví dụ

if (blah) {
  blub();
} else
  while (!bloop()) {
    bar();
  }

Các vết lõm luôn làm cho việc làm tổ dễ dàng nhìn thấy, ngay cả khi không có niềng răng không cần thiết. Vì vậy, nếu bạn quản lý để thực thi các cài đặt IDE như vậy, tôi thấy không có rủi ro.

Cá nhân, tôi thấy mã bỏ qua các dấu ngoặc nhọn và ngắt dòng dễ đọc hơn nhiều vì nó tránh được sự lộn xộn:

if (blah) blub();
else while (!bloop()) bar();

Nhưng tất nhiên, nhiều nhà phát triển rất vui khi tranh luận về những điều như vậy mãi mãi và một ngày.

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.