2008-11-06 40 views
15

Kể từ lần đầu tiên tôi đã viếtthực hành mã hóa phòng thủ

if ($a = 5) { 
    # do something with $a, e.g. 
    print "$a"; 
} 

và đã trải qua phiên đánh đố bình thường của

  • tại sao là kết quả luôn luôn đúng
  • tại sao là $ a luôn 5

cho đến khi tôi nhận ra, tôi đã chỉ định 5 đến $ a, thay vì thực hiện so sánh.

Vì vậy, tôi quyết định viết rằng loại tình trạng trên như

if (5 == $a) 

nói cách khác:

luôn đặt giá trị không đổi sang phía bên trái của toán tử so sánh, dẫn đến một lỗi biên dịch , bạn nên quên thêm dấu "=" thứ hai.

tôi có xu hướng để gọi mã hóanày phòng thủ và có xu hướng tin rằng đó là một người anh họ để phòng thủ-lập trình, không phải trên quy mô thuật toán, nhưng từ khóa theo từ khóa.

Bạn đã phát triển những phương pháp mã hóa phòng thủ nào?


Một tuần sau:

Một lớn "cảm ơn" để tất cả những ai đã trả lời hoặc có thể thêm câu trả lời khác trong tương lai.

Thật không may (hoặc khá may mắn thay!) Không có câu trả lời đúng nào. Đối với câu hỏi của tôi là để rộng, yêu cầu nhiều hơn cho ý kiến ​​hoặc học hỏi kinh nghiệm, chứ không phải là sự kiện.

+0

Tôi đã tìm ra, nếu tôi có thể nhớ làm điều đó, tôi có thể nhớ được == (đáng buồn) – gbarry

+7

Tôi không thích sự rung chuyển đối với con đường suy nghĩ bình thường; Tôi không thử nghiệm 5, tôi đang thử nghiệm $ a. Tôi tìm thấy nó dễ dàng hơn nếu số lượng được kiểm tra được liệt kê đầu tiên. Có lẽ tôi là một thiểu số - nhưng tôi không thích kỹ thuật này, mặc dù nó được đề nghị bởi những người tôi tôn trọng. –

+1

Sẽ tốt hơn nếu bạn không thể chỉ định bất kỳ thứ gì cho các biến trong nếu so sánh. Java và C# đã được tạo ra, bởi vì C++ có đầy đủ các bẫy như thế. Vậy tại sao vấn đề chuyển nhượng này vẫn tồn tại? – Silvercode

Trả lời

13

Đây là một cách đơn giản và rõ ràng, nhưng tôi KHÔNG BAO GIỜ BAO GIỜ KHÔNG BAO GIỜ lặp lại cùng một chuỗi hai lần trong mã của mình, vì tôi BIẾT rằng nếu tôi làm tôi sẽ đánh vần một trong số chúng sai :) Sử dụng hằng số, mọi người!

4

tôi đã ngừng sử dụng ngôn ngữ mà bạn có thể làm

if a = 5: print a 

này đã cứu tôi tấn đau đầu =).

Lưu ý nghiêm trọng hơn ... Bây giờ tôi luôn viết các dấu ngoặc nhọn ngay sau khi tôi viết các vòng if s và for của mình rồi điền vào sau đó. Điều này đảm bảo rằng các dấu ngoặc của tôi luôn được căn chỉnh.

+0

Tôi đồng ý ... nhưng trong thế giới không hoàn hảo như vậy, sự lựa chọn ngôn ngữ lập trình không phải là của tôi ... – lexu

8

Luôn đặt dấu ngoặc nhọn sau một if/for/while ... ngay cả khi chỉ có một câu lệnh duy nhất sau đó. BTW D. Crockford cũng nghĩ rằng nó tốt hơn: Required blocks

+0

Perl đã bắt buộc dấu ngoặc nhọn sau nếu (và elsif) và khác cho aeon. –

+0

Vâng, nhưng Perl cũng có một toán tử _ đơn, phải không? Đừng cố gắng và thuyết phục tôi rằng Perl là một ngọn hải đăng sáng của khả năng đọc :-) – endian

+0

Tôi vừa đăng một câu trả lời trên một câu hỏi khác chỉ ra rằng vấn đề "brace hoặc không brace" liên quan chặt chẽ đến thực hành thụt lề thích hợp. – staticsan

3

Trả lại bản sao của đối tượng có thể thay đổi, tức là bản sao của một mảng, không phải chính đối tượng có thể thay đổi.

+0

Tôi đồng ý, trong các thế giới mà tốc độ và bộ nhớ không phải là vấn đề. – billjamesdev

+0

... và điều này hầu như không phải là thực hành * mã hóa * phòng thủ ... – Rich

+0

Các bạn có bao giờ gặp phải vấn đề với tham chiếu bị rò rỉ không? – dhiller

16

Luôn luôn sử dụng niềng răng:

if(boolean) 
    oneliner(); 
nextLineOfCode(); 

là không giống nhau như:

if(boolean) 
{ 
    oneliner(); 
} 
nextLineOfCode(); 

Nếu oneliner() là một hàm #defined, và nó không được định nghĩa thì dòng tiếp theo của bạn mã đột nhiên trở thành đối tượng if(). Điều tương tự cũng áp dụng đối với cho vòng vv Với niềng răng thì mảnh tiếp theo của mã không bao giờ vô tình trở thành điều kiện trên nếu/cho, vv

+1

Nếu oneliner() được cho là #defined nhưng không phải, thì bạn có một cuộc gọi đến một hàm undeclared (một lỗi trong C++, được cho phép trong C). Nếu oneliner() là #defined với một thân trống, thì bạn có một dấu chấm phẩy cho một câu lệnh trống sau khi if. Trong cả hai trường hợp, các cấu trúc đều giống nhau. –

+1

Ôi Chúa ơi, CÓ! Luôn sử dụng niềng răng! – endian

14

Các top 3 thực hành mã hóa phòng thủ tôi sử dụng là

  1. kiểm tra đơn vị
  2. kiểm tra đơn vị
  3. kiểm tra đơn vị

không có bảo vệ tốt hơn về chất lượng mã của bạn hơn là một thử nghiệm đơn vị tốt để trở lại bạn lên.

+1

Nhưng một thử nghiệm đơn vị là điều gì đó xảy ra sau khi mã hóa, không phải trong quá trình mã hóa. Đó là một điều tốt để làm, nhưng không phải là một thực hành mã hóa. – Treb

+0

Trong thử nghiệm đơn vị ý kiến ​​của tôi là một thực hành lập trình phòng thủ (một người nhập khẩu, không đi mà không có!), Nhưng không phải là một ví dụ mã hóa phòng thủ ... một lỗi "opps-ative" mã hóa trong thử nghiệm của bạn không bị bắt ... phụ thuộc vào định nghĩa của "mã hóa" và "lập trình" – lexu

+4

trong nhiều trường hợp, một thử nghiệm đơn vị được viết trước khi thực hiện. Vâng, đó là một thực hành mã hóa. –

2

Tránh kiểm tra không cần thiết. Ví dụ

  1. if (bool == true)
  2. kiểm tra Pointer if (con trỏ)

EDIT: if (con trỏ) là không thể đọc được vì hiện nay tôi thích if (NULL = con trỏ)

+0

Tôi đồng ý hết lòng với điểm 1, nhưng đối với điểm 2, tôi thích nếu (con trỏ! = NULL) vì nó làm cho mã dễ đọc hơn. – RobH

2

Couple điều:

  • Vâng, các khối 1-line. Sử dụng niềng răng ... heck, hầu hết các IDE tốt sẽ làm cho bạn cho bạn.
  • Nhận xét mã của bạn sau khi bạn viết hoặc đọc lại nhận xét của bạn nếu bạn đã đọc trước. Hãy chắc chắn rằng mã của bạn vẫn làm những gì các ý kiến ​​nói.
  • Kiểm tra đơn vị là một dự phòng tuyệt vời để đọc lại mã của bạn.
  • Luôn đăng nhập ngoại lệ ... hoặc, KHÔNG BAO GIỜ bắt ngoại lệ mà không nói như vậy, ít nhất là trong gỡ lỗi.
5
  • Luôn khởi tạo các biến
  • Sử dụng const bất cứ nơi nào tôi có thể (không sử dụng mutable)
  • Tránh giao năng động trần bộ nhớ hoặc các nguồn lực khác
  • Luôn luôn sử dụng dấu ngoặc nhọn
  • Mã trường hợp sử dụng và kiểm tra cho bất kỳ lớp nào trước khi thực hiện mã hóa
  • Bật nhiều cảnh báo hữu ích nhất có thể (Tối thiểu)
  • Sử dụng công cụ đơn giản nhất giải quyết được vấn đề (trong môi trường hiện tại của tôi, đó là bash ->grep -> awk -> Python -> C++).
+1

+1 để luôn khởi tạo biến và dấu ngoặc nhọn. –

5

Cá nhân, tôi không thích kiểu phòng thủ này, nó làm cho mã khó đọc.

Mức cảnh báo trình biên dịch VC 4 sẽ phát hiện lỗi này (có thể).
"cảnh báo C4706: phân công trong biểu thức điều kiện"

Bạn có thể bật chỉ cảnh báo trình biên dịch cụ thể này, tại bất kỳ cấp độ:

#pragma warning(3,4706) 
+0

GCC sẽ cảnh báo bạn theo mặc định khi bạn thực hiện việc này; nó khuyên bạn nên đặt một nhiệm vụ bên trong parens lồng nhau để làm cho ý định của bạn rõ ràng. – Rich

+0

Trình biên dịch C# cũng sẽ phàn nàn về điều này: Không thể chuyển đổi hoàn toàn kiểu 'xyz' thành 'bool'. –

7

Khi so sánh một chuỗi với một hằng số, viết

if ("blah".equals(value)){} 

thay vì

if (value.equals("blah")){} 

để ngăn chặn một NullPointerException. Nhưng đây là lần duy nhất tôi sử dụng kiểu mã hóa được đề nghị (nguyên nhân "nếu (a = 1) ..." là không thể trong Java).

+0

Mmm, đẹp, tôi thích nó. – endian

+0

Chỉ cần cẩn thận nếu ngôn ngữ lập trình của bạn thực hiện các so sánh chuỗi ** case sensitivie ** bằng cách sử dụng toán tử bình đẳng (hoặc bằng phương thức equals). –

+0

Tôi không thích nó vì nó không bắt được giá trị null, mà có thể hoặc không thể là một lỗi. – Cojones

7

Một trong những điều tôi luôn cố gắng nhớ khi tôi ở trong thế giới Javascript là luôn luôn bắt đầu giá trị trả về của một hàm trên cùng một dòng với từ khóa trả về.

function one(){ 
    return { 
     result:"result" 
    }; 
} 

function two(){ 
    return 
    { 
     result:"result" 
    }; 
} 

Hai chức năng này sẽ không trả lại cùng một giá trị. Hàm đầu tiên sẽ trả về một đối tượng có kết quả thuộc tính được đặt thành "kết quả". Hàm thứ hai sẽ trả về undefined. Đó là một sai lầm thực sự đơn giản và điều đó xảy ra vì chiến lược Chèn-Đại Toàn cầu của Ghen. Bán dấu hai chấm là bán tùy chọn trong Javascript và vì điều này, công cụ Javascript sẽ thêm các dấu chấm than bán ở nơi mà nó cho là cần. Bởi vì return thực sự là một câu lệnh hợp lệ, một dấu chấm phẩy sẽ được chèn sau câu lệnh return và phần còn lại của hàm về cơ bản sẽ bị bỏ qua.

+4

Một lý do nữa khiến Javascript là Evil. – endian

+2

Tôi rất không đồng ý. Tôi nghĩ rằng nó đã được đổ xô vào thị trường và không có thời gian trong một phòng thí nghiệm cho sự tinh tế. Các populatiry nó bùng nổ có nghĩa là nó không thể được cố định mà không phá vỡ mọi thứ. Được sử dụng chính xác đó là một ngôn ngữ thích ứng và mạnh mẽ tuyệt vời. Rant Over. –

+0

Wow - Tôi không bao giờ biết điều đó! Cảm ơn bạn về thông tin. Điều đó tự đánh giá một câu hỏi/trả lời. –

5

Từ blog của tôi:

  1. suy nghĩ tích cực và trở về đầu cộng tránh làm tổ sâu. Thay vì

    if (giá trị! = Null) { ... làm điều gì đó có giá trị ... } trở

    ghi

    if (giá trị == null) { trở } ... làm điều gì đó có giá trị ...

  2. Tránh "hằng số chuỗi" (nghĩa là văn bản giống nhau trong dấu ngoặc kép ở nhiều nơi). Luôn xác định một hằng số thực (với tên và chú thích tùy chọn ý nghĩa của nó) và sử dụng nó.

1

cài đặt Resharper;) Sau đó, tôi không cần phải viết "5 == một" để cảnh báo nếu tôi đã làm điều gì sai :)

+0

Điều đó có hoạt động với perl/python/bash ... kỷ luật tự giác .. và có, đó là một đối số què theo một cách .- ( – lexu

+0

@lexu: không, nhưng đó là một câu hỏi chủ quan, và tôi không sử dụng perl, python hoặc bash :) – badbadboy

Các vấn đề liên quan