Tôi có nên quay lại từ một hàm sớm hay sử dụng câu lệnh if? [đóng cửa]


304

Tôi thường viết loại hàm này ở cả hai định dạng và tôi tự hỏi liệu một định dạng này có được ưu tiên hơn một định dạng không, và tại sao.

public void SomeFunction(bool someCondition)
{
    if (someCondition)
    {
        // Do Something
    }
}

hoặc là

public void SomeFunction(bool someCondition)
{
    if (!someCondition)
        return;

    // Do Something
}

Tôi thường viết mã với cái đầu tiên vì đó là cách mà bộ não của tôi hoạt động trong khi mã hóa, mặc dù tôi nghĩ rằng tôi thích cái thứ hai hơn vì nó xử lý mọi lỗi xử lý ngay lập tức và tôi thấy nó dễ đọc hơn


9
Tôi hơi muộn cho cuộc thảo luận này vì vậy tôi sẽ không đưa ra câu trả lời; Tôi cũng đã nghĩ về điều này hai năm trước: speecherror.com/articles/view/code-formatted-and-readability Tôi thấy thứ hai dễ đọc, sửa đổi, duy trì và gỡ lỗi hơn. Nhưng có lẽ đó chỉ là tôi :)
dr Hannibal Lecter


4
bây giờ câu hỏi này là một ví dụ điển hình cho câu hỏi dựa trên ý kiến
Rudolf Olah

2
Vậy nếu không có bằng chứng tuyệt đối theo hướng này hay hướng khác thì sao? Khi đủ lập luận được cung cấp theo hướng này và hướng khác và có một cuộc bỏ phiếu nếu câu trả lời là đúng - nó làm cho nó rất hữu ích. Tôi thấy những câu hỏi đóng như thế này có hại cho giá trị của trang web này.
gsf

9
Và tôi thích câu hỏi và câu trả lời dựa trên ý kiến. Họ cho tôi biết phần lớn thích gì và điều đó cho phép tôi viết mã cho người khác đọc.
Zygimantas

Câu trả lời:


402

Tôi thích phong cách thứ hai. Trước tiên, hãy đưa các trường hợp không hợp lệ ra ngoài, đơn giản là thoát hoặc đưa ra các ngoại lệ khi thích hợp, đặt một dòng trống vào đó, sau đó thêm phần thân "thực" của phương thức. Tôi thấy nó dễ đọc hơn.


7
Smalltalk gọi đây là "mệnh đề bảo vệ". Ít nhất đó là những gì Kent Beck gọi chúng trong Mô hình thực hành tốt nhất của Smalltalk; Tôi không biết đó là cách nói chung.
Frank Shearar

154
Thoát sớm cho phép bạn bật công cụ ra khỏi ngăn xếp tinh thần hạn chế của bạn. :)
Joren

50
Trước đây tôi đã nghe điều này được gọi là "Mô hình Bouncer" - loại bỏ các trường hợp xấu trước khi chúng vào cửa.
RevBingo

14
Tôi thậm chí còn đi xa và nói rằng đây chắc chắn là điều DUY NHẤT phải làm.
Oliver Weiler

38
Ngoài ra, bạn không tiếp tục thêm thụt lề nếu bạn thoát khỏi các trường hợp biên giới lúc đầu.
doppelgreener

170

Chắc chắn là cái sau. Cái trước trông không tệ lắm, nhưng khi bạn nhận được mã phức tạp hơn, tôi không thể tưởng tượng được ai sẽ nghĩ điều này:

public int SomeFunction(bool cond1, string name, int value, AuthInfo perms)
{
    int retval = SUCCESS;
    if (someCondition)
    {
        if (name != null && name != "")
        {
            if (value != 0)
            {
                if (perms.allow(name)
                {
                    // Do Something
                }
                else
                {
                    reval = PERM_DENY;
                }
            }
            else
            {
                retval = BAD_VALUE;
            }
        }
        else
        {
            retval = BAD_NAME;
        }
    }
    else
    {
        retval = BAD_COND;
    }
    return retval;
}

dễ đọc hơn

public int SomeFunction(bool cond1, string name, int value, AuthInfo perms)
{
    if (!someCondition)
        return BAD_COND;

    if (name == null || name == "")
        return BAD_NAME;

    if (value == 0)
        return BAD_VALUE;

    if (!perms.allow(name))
        return PERM_DENY;

    // Do something
    return SUCCESS;
}

Tôi hoàn toàn thừa nhận tôi không bao giờ hiểu lợi thế của các điểm thoát đơn.


20
Ưu điểm của một điểm thoát duy nhất là ... có một điểm thoát duy nhất! Với ví dụ của bạn, có một số điểm có thể trở lại. Với một hàm phức tạp hơn, điều đó có thể biến thành một điểm truy tìm khi định dạng của giá trị trả về thay đổi. Tất nhiên, có những lúc buộc một điểm thoát duy nhất không có ý nghĩa.
JohnL

71
@JohnL chức năng lớn là vấn đề, không phải nhiều điểm thoát. Trừ khi bạn đang làm việc trong bối cảnh mà một lệnh gọi chức năng bổ sung sẽ làm chậm mã của bạn vô cùng, tất nhiên ...
Dan Rosenstark

4
@Yar: Đúng, nhưng điểm đứng. Tôi sẽ không cố gắng chuyển đổi bất kỳ ai, và tôi chỉ chỉ ra lợi thế của việc đi càng ít điểm thoát càng tốt (và ví dụ của Jason là loại người rơm). Ngay lần tới khi bạn nhổ tóc ra, cố gắng tìm hiểu tại sao Đôi khi một số chức năng lại trả về các giá trị kỳ lạ, có thể bạn sẽ ước mình có thể thêm một cuộc gọi đăng nhập ngay trước khi trả lại. Dễ dàng gỡ lỗi hơn nếu chỉ có một trong số các buggers! :)
JohnL

76
@Jason Viers Như thể một người return value;giúp đỡ!?! Sau đó, người ta phải săn một nửa tá value = ..., với nhược điểm là bạn không bao giờ chắc chắn rằng giá trị đó sẽ không bị thay đổi giữa nhiệm vụ này và lợi nhuận cuối cùng. Ít nhất một sự trở lại ngay lập tức là rõ ràng rằng không có gì sẽ thay đổi kết quả nữa.
Sjoerd

5
@Sjoed: Tôi thứ hai Sjoerd ở đây. Nếu bạn muốn đăng nhập kết quả, bạn có thể đăng nhập tại trang web của người gọi. Nếu bạn muốn biết lý do, bạn phải đăng nhập tại mỗi điểm thoát / bài tập để cả hai đều giống hệt nhau ở khía cạnh này.
Matthieu M.

32

Nó phụ thuộc - Nói chung tôi sẽ không cố gắng di chuyển một loạt mã xung quanh để thoát ra khỏi chức năng sớm - trình biên dịch nói chung sẽ đảm nhiệm việc đó cho tôi. Mặc dù vậy, nếu có một số thông số cơ bản ở trên cùng mà tôi cần và không thể tiếp tục nếu không, tôi sẽ thoát ra sớm. Tương tự như vậy, nếu một điều kiện tạo ra một ifkhối khổng lồ trong chức năng, tôi cũng sẽ phá vỡ nó sớm.

Mặc dù vậy, nếu một hàm yêu cầu một số dữ liệu khi nó được gọi, tôi thường sẽ ném một ngoại lệ (xem ví dụ) thay vì chỉ trả về.

public int myFunction(string parameterOne, string parameterTwo) {
  // Can't work without a value
  if (string.IsNullOrEmpty(parameterOne)) {
    throw new ArgumentNullException("parameterOne");
  } 
  if (string.IsNullOrEmpty(parameterTwo)) {
    throw new ArgumentNullException("parameterTwo");
  }

  // ...      
  // Do some work
  // ...

  return value;
}

9
Và nếu kết quả cuối cùng là duy trì, ai quan tâm phong cách nào đã được chọn?
Jeff Siver

3
@Jeff Siver - Vì vậy, tại sao điều này có xu hướng là một câu hỏi kiểu "chiến tranh thần thánh", vào cuối ngày nó đi theo sở thích cá nhân và bất cứ điều gì một hướng dẫn phong cách nội bộ nói.
rjzii

1
Điểm mấu chốt ở đây là anh ấy đang ném một ngoại lệ thay vì trở về sớm. Giá trị trả lại không nên được lọc lại để kiểm tra tính hợp lệ. Điều gì xảy ra nếu bạn có nhiều điều kiện khác nhau và muốn cho mã sử dụng phương thức biết tại sao nó thất bại? Đột nhiên bạn có thể trả về dữ liệu kinh doanh thực tế, không có gì (kết quả trống) hoặc nhiều chuỗi, mã, số, ... khác nhau từ một phương thức duy nhất. Chỉ để mô tả tại sao nó thất bại. Không, cám ơn.
DanMan

Điều gì về độ phức tạp chu kỳ như trình biên dịch của tôi gợi ý? không phải là tốt hơn để không làm tổ mã nếu người ta có thể giúp nó?
l --'''''--------- '' '' '' '' '' ''

24

Tôi thích sự trở lại sớm.

Nếu bạn có một điểm vào và một điểm thoát thì bạn luôn phải theo dõi toàn bộ mã trong đầu cho đến điểm thoát (bạn không bao giờ biết nếu một đoạn mã khác dưới đây có làm gì khác với kết quả không, vì vậy bạn phải theo dõi nó cho đến khi tồn tại). Bạn làm điều đó không có vấn đề mà chi nhánh xác định kết quả cuối cùng. Điều này là khó theo dõi.

Với một mục nhập và nhiều mục tồn tại, bạn quay lại khi bạn có kết quả của mình và không bận tâm theo dõi nó để thấy rằng không ai làm gì khác với nó (vì sẽ không có gì khác kể từ khi bạn quay lại). Nó giống như việc cơ thể phương pháp chia thành nhiều bước hơn, mỗi bước có khả năng trả về kết quả hoặc để bước tiếp theo thử vận ​​may.


13

Trong lập trình C, nơi bạn phải dọn dẹp thủ công, có rất nhiều điều để nói về lợi nhuận một điểm. Ngay cả khi không có nhu cầu ngay bây giờ để dọn dẹp thứ gì đó, ai đó có thể chỉnh sửa chức năng của bạn, phân bổ thứ gì đó và cần dọn dẹp trước khi trả lại. Nếu điều đó xảy ra, đó sẽ là một công việc ác mộng khi xem qua tất cả các tuyên bố trở lại.

Trong lập trình C ++, bạn có các hàm hủy và thậm chí bây giờ các trình bảo vệ thoát phạm vi. Tất cả những điều này cần phải có ở đây để đảm bảo mã an toàn ngoại lệ ngay từ đầu, vì vậy mã được bảo vệ tốt trước lối ra sớm và do đó làm như vậy không có nhược điểm logic và hoàn toàn là vấn đề về kiểu dáng.

Tôi không đủ hiểu biết về Java, liệu mã khối "cuối cùng" có được gọi hay không và liệu trình hoàn thiện có thể xử lý tình huống cần thiết để đảm bảo điều gì đó xảy ra hay không.

C # Tôi chắc chắn không thể trả lời.

Ngôn ngữ D cung cấp cho bạn các trình bảo vệ thoát phạm vi tích hợp thích hợp và do đó được chuẩn bị tốt để thoát sớm và do đó không nên trình bày một vấn đề nào khác ngoài phong cách.

Các hàm tất nhiên không nên quá dài ở vị trí đầu tiên và nếu bạn có một câu lệnh chuyển đổi lớn, mã của bạn có lẽ cũng bị ảnh hưởng xấu.


1
C ++ cho phép một cái gì đó gọi là tối ưu hóa giá trị trả về, cho phép trình biên dịch bỏ qua hoạt động sao chép thường xảy ra khi bạn trả về một giá trị. Tuy nhiên, trong các điều kiện khác nhau, điều đó khó thực hiện và nhiều giá trị trả về là một trong những trường hợp đó. Nói cách khác, sử dụng nhiều giá trị trả về trong C ++ thực sự có thể làm cho mã của bạn chậm hơn. Điều này chắc chắn có trên MSC và được cho là khá khó (nếu không thể) thực hiện RVO với nhiều giá trị trả về có thể, đó có thể là một vấn đề trong tất cả các trình biên dịch.
Eamon Nerbonne

1
Trong C, chỉ cần sử dụng gotovà, có thể, trả về hai điểm. Ví dụ (không thể định dạng mã trong nhận xét):foo() { init(); if (bad) goto err; bar(); if (bad) goto err; baz(); return 0; err: cleanup(); return 1; }
mirabilos

1
Thay vì một goto tôi thích "Phương pháp trích xuất". Khi bạn nghĩ rằng bạn cần triển khai biến giá trị trả về hoặc goto, trong nỗ lực để đảm bảo mã dọn dẹp của bạn luôn được gọi, đó là Mùi mà bạn cần chia thành nhiều chức năng. Điều này cho phép bạn đơn giản hóa mã điều kiện phức tạp của mình bằng cách sử dụng các khoản bảo vệ và các kỹ thuật hoàn trả sớm khác, trong khi vẫn đảm bảo mã dọn dẹp của bạn luôn chạy.
BrandonLWhite

"Ai đó có thể chỉnh sửa chức năng của bạn" - đây là một lời giải thích vô lý cho việc ra quyết định. Bất cứ ai cũng có thể làm bất cứ điều gì trong tương lai. Điều đó không có nghĩa là bạn nên làm một cái gì đó cụ thể ngày hôm nay để ngăn chặn ai đó phá vỡ mọi thứ trong tương lai.
Victor Yarema

Được gọi là làm cho mã của bạn có thể duy trì. Trong thế giới thực, mã được viết cho mục đích kinh doanh và đôi khi một nhà phát triển sau này cần phải thay đổi nó. Vào thời điểm đó, tôi đã viết câu trả lời đó mặc dù tôi đã vá CURL để giới thiệu bộ nhớ đệm và nhớ lại mớ hỗn độn spaghetti rằng nó thực sự cần viết lại đúng cách trong C ++ hiện đại
CashCow

9

Trả lại sớm cho chiến thắng. Chúng có vẻ xấu, nhưng xấu hơn nhiều so với ifgiấy gói lớn , đặc biệt nếu có nhiều điều kiện để kiểm tra.


9

Tôi sử dụng cả hai.

Nếu DoSomethinglà 3-5 dòng mã thì mã chỉ trông đẹp khi sử dụng phương thức định dạng đầu tiên.

Nhưng nếu nó có nhiều dòng hơn thế, thì tôi thích định dạng thứ hai. Tôi không thích khi dấu ngoặc mở và đóng không nằm trên cùng một màn hình.


2
Đẹp không đời nào! Quá nhiều vết lõm!
JimmyKane

@JimmyKane Chỉ có quá nhiều vết lõm có thể xảy ra trong 3-5 dòng, đặc biệt là khi bạn cần 2 (?) Mỗi ​​cấp độ, phần còn lại được thụt lề: Một cho cấu trúc điều khiển và bắt đầu khối, một cho cuối khối.
Ded repeatator

8

Một lý do kinh điển cho lối ra một lần duy nhất là vì nếu không thì ngữ nghĩa chính thức trở nên xấu đến mức không thể tin được (lý do tương tự GOTO được coi là có hại).

Nói cách khác, lý do dễ dàng hơn là khi nào phần mềm của bạn sẽ thoát khỏi thói quen nếu bạn chỉ có 1 lần trả lại. Đó cũng là một lập luận chống lại các ngoại lệ.

Điển hình là tôi giảm thiểu cách tiếp cận sớm.


nhưng đối với một công cụ phân tích chính thức, bạn có thể tổng hợp một hàm ngoài với ngữ nghĩa mà công cụ cần và giữ cho mã con người có thể đọc được.
Tim Williscroft

@Tim. Điều đó phụ thuộc vào mức độ bạn muốn làm và những gì bạn đang phân tích. Tôi thấy SESE khá dễ đọc nếu người viết mã đã lành mạnh về mọi thứ.
Paul Nathan

Thái độ của tôi đối với phân tích được hình thành bởi sự tối ưu hóa từ dự án Tự. 99% các cuộc gọi phương thức động có thể được giải quyết và loại bỏ tĩnh. vì vậy sau đó bạn có thể phân tích một số mã đường thẳng khá. Là một lập trình viên làm việc, tôi có thể tin tưởng rằng hầu hết các mã tôi sẽ làm việc được viết bởi các lập trình viên trung bình. Vì vậy, họ sẽ không viết mã rất tốt.
Tim Williscroft

@Tim: Đủ công bằng. Mặc dù tôi cảm thấy bắt buộc phải chỉ ra rằng các ngôn ngữ tĩnh vẫn có rất nhiều trò chơi.
Paul Nathan

Một lý do không giữ được các trường hợp ngoại lệ. Đó là lý do tại sao lối thoát đơn là tuyệt vời trong C, nhưng không mua cho bạn bất cứ thứ gì trong C ++.
peterchen

7

Cá nhân, tôi thích kiểm tra điều kiện đạt / không ngay từ đầu. Điều đó cho phép tôi nhóm hầu hết các lỗi phổ biến nhất ở đầu hàm với phần còn lại của logic để theo dõi.


6

Nó phụ thuộc.

Quay trở lại sớm nếu có một số điều kiện cụ thể rõ ràng để kiểm tra ngay lập tức sẽ khiến việc chạy phần còn lại của chức năng trở nên vô nghĩa. *

Đặt Retval + trả về một lần nếu hàm phức tạp hơn và có thể có nhiều điểm thoát khác (vấn đề dễ đọc).

* Điều này thường có thể chỉ ra một vấn đề thiết kế. Nếu bạn thấy rằng rất nhiều phương thức của bạn cần kiểm tra một số trạng thái bên ngoài / paramater hoặc như vậy trước khi chạy phần còn lại của mã, đó có lẽ là điều mà người gọi nên xử lý.


6
Khi tôi viết mã có thể được chia sẻ, câu thần chú của tôi là "Giả sử không có gì. Không tin ai cả." Bạn phải luôn xác nhận đầu vào của bạn và bất kỳ trạng thái bên ngoài nào bạn phụ thuộc vào. Tốt hơn là ném một ngoại lệ hơn là có thể làm hỏng thứ gì đó vì ai đó đã cung cấp cho bạn dữ liệu xấu.
TMN

@TMN: Điểm tốt.
Bàn Bobby

2
Điểm mấu chốt ở đây là trong OO bạn ném một ngoại lệ , không quay lại . Nhiều trả về có thể là xấu, nhiều lần ném ngoại lệ không nhất thiết phải là mùi mã.
Michael K

2
@MichaelK: Một phương pháp nên là một ngoại lệ nếu điều kiện hậu kỳ không thể được đáp ứng. Trong một số trường hợp, một phương thức nên thoát sớm vì điều kiện hậu đã đạt được ngay cả trước khi chức năng bắt đầu. Ví dụ: nếu người ta gọi phương thức "Đặt nhãn điều khiển" để thay đổi nhãn của điều khiển thành Fred, nhãn của cửa sổ đã có sẵn Fredvà đặt tên của điều khiển về trạng thái hiện tại sẽ buộc vẽ lại (trong trường hợp có thể hữu ích trong một số trường hợp gây khó chịu trong một lần), sẽ là hoàn toàn hợp lý khi có phương thức đặt tên sớm thoát nếu tên cũ và tên mới khớp.
supercat

3

Sử dụng một Nếu

Trong cuốn sách của Don Knuth về GOTO, tôi đã đọc anh ta đưa ra một lý do cho việc luôn luôn có điều kiện có khả năng nhất đến trước trong một tuyên bố if. Theo giả định rằng đây vẫn là một ý tưởng hợp lý (và không phải là một trong những cân nhắc thuần túy cho tốc độ của thời đại). Tôi nói rằng trả về sớm không phải là thực hành lập trình tốt, đặc biệt là xem xét thực tế rằng chúng thường xuyên hơn không được sử dụng để xử lý lỗi, trừ khi mã của bạn có nhiều khả năng thất bại hơn là không thất bại :-)

Nếu bạn làm theo lời khuyên ở trên, bạn cần đặt trả về đó ở dưới cùng của hàm, và sau đó bạn thậm chí có thể không gọi nó là trả về ở đó, chỉ cần đặt mã lỗi và trả lại hai dòng. Qua đó đạt được mục nhập 1 lối thoát lý tưởng.

Delphi cụ thể ...

Tôi nghĩ rằng đây là một thực hành lập trình tốt cho các lập trình viên Delphi, mặc dù tôi không có bất kỳ bằng chứng nào. Trước D2009, chúng tôi không có cách nguyên tử để trả về giá trị, chúng tôi có exit;result := foo;hoặc chúng tôi chỉ có thể ném ngoại lệ.

Nếu bạn phải thay thế

if (true) {
 return foo;
} 

cho

if true then 
begin
  result := foo; 
  exit; 
end;

bạn có thể phát ốm khi thấy điều đó ở đầu mỗi chức năng của bạn và thích

if false then 
begin
  result := bar;

   ... 
end
else
   result := foo;

và chỉ cần tránh exithoàn toàn.


2
Với Delphis mới hơn, nó có thể được viết tắt là if true then Exit(foo);tôi sử dụng thường xuyên các kỹ thuật đầu tiên khởi resultđể nilhoặc FALSEtương ứng, sau đó kiểm tra các điều kiện lỗi và chỉ Exit;nếu ai đáp ứng. Trường hợp thành công resultsau đó (thường) được đặt ở đâu đó ở cuối phương thức.
JensG

vâng, tôi thích tính năng mới này mặc dù có vẻ như nó chỉ là kẹo để xoa dịu các lập trình viên Java, điều tiếp theo bạn biết họ sẽ cho phép chúng tôi xác định các biến của chúng tôi trong các thủ tục.
Peter Turner

Và lập trình viên C #. Vâng, thành thật mà nói, tôi sẽ thấy điều đó thực sự hữu ích vì nó làm giảm số lượng dòng giữa khai báo và sử dụng (IIRC thậm chí còn có một số liệu cho điều đó, quên tên).
JensG

2

Tôi đồng ý với tuyên bố sau:

Cá nhân tôi là một fan hâm mộ của các mệnh đề bảo vệ (ví dụ thứ hai) vì nó làm giảm sự thụt dòng của hàm. Một số người không thích chúng vì nó dẫn đến nhiều điểm trả về từ chức năng, nhưng tôi nghĩ nó rõ ràng hơn với họ.

Lấy từ câu hỏi này trong stackoverflow .


+1 Đối với mệnh đề bảo vệ. Tôi cũng thích một người bảo vệ có định hướng tích cực, ví dụ: if (condition = false) trở lại trái ngược với if (! Condition) return
JustinC

1

Tôi sử dụng lợi nhuận sớm gần như độc quyền những ngày này, đến mức cực đoan. Tôi viết cái này

self = [super init];

if (self != nil)
{
    // your code here
}

return self;

như

self = [super init];
if (!self)
    return;

// your code here

return self;

nhưng nó thực sự không quan trọng. Nếu bạn có nhiều hơn một hoặc hai cấp độ lồng trong các chức năng của mình, chúng cần được tăng cường.


Tôi đồng ý. Lõm là nguyên nhân gây ra rắc rối trong việc đọc. Càng ít thụt càng tốt. Ví dụ đơn giản của bạn có cùng mức độ thụt đầu dòng nhưng ví dụ đầu tiên đó chắc chắn sẽ phát triển thành nhiều vết lõm hơn đòi hỏi nhiều năng lực não hơn.
user441521

1

Tôi muốn viết:

if(someCondition)
{
    SomeFunction();
}

2
eww Đó có phải là xác nhận trước? Hoặc là trong một mehtod dành riêng xác nhận DoSomeFunctionIfSomeCondition?
STW

Làm thế nào điều này giữ cho mối quan tâm của bạn tách biệt?
justkt

2
Bạn đang vi phạm đóng gói bằng cách thực hiện chức năng (logic phụ thuộc của nó) bên ngoài.
TMN

1
Nếu điều này được chạy trong một phương thức công khai và someFunction () là một phương thức riêng tư trong cùng một lớp thì nó có thể ổn. Nhưng nếu bất cứ ai khác đang gọi một số chức năng (), bạn sẽ phải sao chép các kiểm tra ở đó. Tôi thấy tốt hơn là làm cho mỗi phương thức quan tâm đến những gì nó cần để thực hiện công việc của nó, không ai khác phải biết điều đó.
Mỗi Wiklander

2
Đây chắc chắn là phong cách mà Robert C. Martin đề xuất trong "Clean Code". Một chức năng chỉ nên làm một việc. Tuy nhiên, trong "Các mô hình triển khai", Kent Beck gợi ý, trong hai tùy chọn được đề xuất trong OP, thứ hai là tốt hơn.
Scott Whitlock

1

Giống như bạn, tôi thường viết cái đầu tiên, nhưng thích cái cuối cùng. Nếu tôi có nhiều kiểm tra lồng nhau, tôi thường cấu trúc lại phương thức thứ hai.

Tôi không thích cách xử lý lỗi được chuyển khỏi kiểm tra.

if not error A
  if not error B
    if not error C
      // do something
    else handle error C
  else handle error B
else handle error A

Tôi thích điều này:

if error A
  handle error A; return
if error B
  handle error B; return
if error C
  handle error C; return

// do something

0

Các điều kiện trên cùng được gọi là "điều kiện tiên quyết". Bằng cách đặt if(!precond) return;, bạn đang liệt kê trực quan tất cả các điều kiện tiên quyết.

Sử dụng khối "if-other" lớn có thể làm tăng chi phí thụt lề (tôi quên trích dẫn về thụt lề 3 cấp).


2
Gì? Bạn không thể quay lại sớm trong Java? C #, VB (.NET và 6) và rõ ràng là Java (mà tôi giả sử đã làm, nhưng phải tìm kiếm vì tôi đã không sử dụng ngôn ngữ này trong 15 năm) đều cho phép trả lại sớm. vì vậy đừng buộc tội 'ngôn ngữ được gõ mạnh' là không có tính năng này. stackoverflow.com/questions/884429/ từ
ps2goat

-1

Tôi thích giữ nếu báo cáo nhỏ.

Vì vậy, lựa chọn giữa:

if condition:
   line1
   line2
    ...
   line-n

if not condition: return

line1
line2
 ...
line-n

Tôi sẽ chọn những gì bạn mô tả là "trở về sớm".

Nhắc bạn, tôi không quan tâm đến lợi nhuận sớm hay bất cứ điều gì, tôi chỉ thực sự muốn đơn giản hóa mã, rút ​​ngắn các nội dung của câu lệnh if, v.v.

Lồng nhau nếu và cho và trong khi là khủng khiếp , tránh chúng bằng mọi giá.


-2

Như những người khác nói, nó phụ thuộc. Đối với các hàm nhỏ trả về giá trị, tôi có thể mã trả về sớm. Nhưng đối với các hàm có kích thước lớn, tôi muốn luôn có một vị trí trong mã nơi tôi biết tôi có thể đặt một cái gì đó sẽ được thực thi trước khi nó trả về.


-2

Tôi thực hành thất bại nhanh ở cấp độ chức năng. Nó giữ mã nhất quán và sạch sẽ (với tôi và những người tôi đã làm việc cùng). Vì điều đó tôi luôn trở về sớm.

Đối với một số điều kiện được kiểm tra, bạn có thể triển khai các khía cạnh cho các kiểm tra đó nếu bạn sử dụng AOP.

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.