Tôi nghĩ rằng @JackAidley đã nói ý chính của nó rồi , nhưng hãy để tôi xây dựng nó như thế này:
không có ngoại lệ (ví dụ C)
Trong dòng mã thông thường, bạn có:
if (condition) {
statement;
} else if (less_likely_condition) {
less_likely_statement;
} else {
least_likely_statement;
}
more_statements;
Trong trường hợp lỗi ra khỏi trường hợp sớm, mã của bạn đột nhiên đọc:
/* demonstration example, do NOT code like this */
if (condition) {
statement;
} else {
error_handling;
return;
}
Nếu bạn phát hiện ra mẫu này - một return
khối else
(hoặc thậm chí if
), hãy xử lý lại ngay lập tức để mã được đề cập không có else
khối:
/* only code like this at University, to please structured programming professors */
function foo {
if (condition) {
lots_of_statements;
}
return;
}
Trong thế giới thực…
/* code like this instead */
if (!condition) {
error_handling;
return;
}
lots_of_statements;
Điều này tránh việc làm tổ quá sâu và hoàn thành trường hợp đột phá sớm (giúp giữ cho tâm trí - và dòng mã - sạch sẽ) và không vi phạm các điều có thể xảy ra với if
phần nhiều vì phần đơn giản là không có else
phần nào .
C
và dọn dẹp
Lấy cảm hứng từ một câu trả lời cho một câu hỏi tương tự (đã hiểu sai), đây là cách bạn dọn dẹp với C. Bạn có thể sử dụng một hoặc hai điểm thoát ở đó, đây là một cho hai điểm thoát:
struct foo *
alloc_and_init(size_t arg1, int arg2)
{
struct foo *res;
if (!(res = calloc(sizeof(struct foo), 1)))
return (NULL);
if (foo_init1(res, arg1))
goto err;
res.arg1_inited = true;
if (foo_init2(&(res->blah), arg2))
goto err;
foo_init_complete(res);
return (res);
err:
/* safe because we use calloc and false == 0 */
if (res.arg1_inited)
foo_dispose1(res);
free(res);
return (NULL);
}
Bạn có thể thu gọn chúng vào một điểm thoát nếu có ít việc dọn dẹp hơn:
char *
NULL_safe_strdup(const char *arg)
{
char *res = NULL;
if (arg == NULL)
goto out;
/* imagine more lines here */
res = strdup(arg);
out:
return (res);
}
Việc sử dụng goto
này là hoàn toàn tốt, nếu bạn có thể đối phó với nó; Lời khuyên để không sử dụng goto
là hướng đến những người chưa thể tự quyết định xem việc sử dụng là tốt, chấp nhận được, xấu, mã spaghetti, hoặc một cái gì khác.
Ngoại lệ
Ở trên nói về các ngôn ngữ không có ngoại lệ, điều mà tôi rất thích bản thân mình (tôi có thể sử dụng xử lý lỗi rõ ràng tốt hơn nhiều và ít gây ngạc nhiên hơn). Để trích dẫn igli:
<igli> exceptions: a truly awful implementation of quite a nice idea.
<igli> just about the worst way you could do something like that, afaic.
<igli> it's like anti-design.
<mirabilos> that too… may I quote you on that?
<igli> sure, tho i doubt anyone will listen ;)
Nhưng đây là một gợi ý về cách bạn làm tốt nó trong một ngôn ngữ có ngoại lệ và khi bạn muốn sử dụng chúng tốt:
trả lại lỗi khi đối mặt với ngoại lệ
Bạn có thể thay thế hầu hết những người đầu tiên return
bằng cách ném một ngoại lệ. Tuy nhiên , luồng chương trình bình thường của bạn , tức là bất kỳ luồng mã nào trong đó chương trình không gặp phải, ngoại trừ một điều kiện lỗi hoặc somesuch, sẽ không đưa ra bất kỳ ngoại lệ nào.
Điều này có nghĩa rằng…
# this page is only available to logged-in users
if not isLoggedIn():
# this is Python 2.5 style; insert your favourite raise/throw here
raise "eh?"
Giáo dục thì không sao, nhưng
/* do not code like this! */
try {
openFile(xyz, "rw");
} catch (LockedException e) {
return "file is locked";
}
closeFile(xyz);
return "file is not locked";
… không phải. Về cơ bản, một ngoại lệ không phải là một yếu tố dòng điều khiển . Điều này cũng làm cho các hoạt động trở nên kỳ lạ đối với bạn (các lập trình viên Java ™ luôn nói với chúng tôi rằng những ngoại lệ này là bình thường) và có thể cản trở việc gỡ lỗi (ví dụ: bảo IDE chỉ phá vỡ mọi ngoại lệ). Các trường hợp ngoại lệ thường yêu cầu môi trường thời gian chạy để giải phóng ngăn xếp để tạo ra các dấu vết, v.v. Có lẽ có nhiều lý do hơn để chống lại nó.
Điều này nắm rõ: trong một ngôn ngữ hỗ trợ các ngoại lệ, sử dụng bất cứ điều gì phù hợp với logic và phong cách hiện có và cảm thấy tự nhiên. Nếu viết một cái gì đó từ đầu, hãy đồng ý sớm. Nếu viết một thư viện từ đầu, hãy nghĩ về người tiêu dùng của bạn. (Đừng, bao giờ, sử dụng abort()
trong thư viện hoặc)) Nhưng bất cứ điều gì bạn làm, đừng, như một quy tắc, sẽ có một ngoại lệ được ném nếu hoạt động tiếp tục (ít nhiều) bình thường sau nó.
tư vấn chung wrt. Ngoại lệ
Trước tiên, hãy thử sử dụng tất cả các ngoại lệ trong chương trình được toàn bộ nhóm nhà phát triển đồng ý. Về cơ bản, lập kế hoạch cho họ. Không sử dụng chúng trong phong phú. Đôi khi, ngay cả trong C ++, Java ™, Python, trả về lỗi vẫn tốt hơn. Đôi khi không phải vậy; sử dụng chúng với suy nghĩ.