Gần hai mươi năm trước, tôi đã hiểu rất nhiều về điều này từ cuốn sách tuyệt vời "Không có lỗi: Cung cấp mã không có lỗi trong C và C ++" của David Thielen, hiện đang có sẵn dưới dạng PDF miễn phí .
Anh ấy dạy tôi hai ý tưởng tuyệt vời ...
Lỗi không đến từ đâu. Tất cả các lập trình viên của chúng tôi ngồi xuống và viết chúng vào mã của chúng tôi bằng ngón tay của chúng tôi.
"Lỗi" hàm ý rằng một số cơ quan bên ngoài đã quyết định phá hoại chương trình của bạn với lỗi và nếu bạn sống một cuộc sống sạch sẽ và hy sinh những con thú lông nhỏ dưới chân máy tính của bạn, chúng sẽ biến mất ... Khái niệm này rất quan trọng vì nó có màu sắc cách tiếp cận của bạn để gỡ lỗi mã của bạn. Nếu bạn xem lỗi là "lỗi", bạn hy vọng không tìm thấy lỗi nào. (Bạn hy vọng bà tiên tốt bụng đến, rắc bụi pixie và những con bọ còn sót lại.)
Lỗi không nên được gọi là lỗi, chúng nên được gọi là lỗi lớn [MFU] ... MFU tồn tại bởi vì các chương trình được viết bởi mọi người và mọi người mắc lỗi ... Bạn sẽ viết MFU. Bạn sẽ ngồi xuống và với ác ý hoàn toàn về việc suy nghĩ, hãy đặt MFU vào mã của bạn. Hãy suy nghĩ về nó - bạn biết rằng bạn là người đưa các lỗi vào đó. Vì vậy, nếu bạn ngồi xuống mã, bạn sẽ chèn một số lỗi.
Vì đó là định mệnh không thể tránh khỏi của các lập trình viên để viết lỗi, tôi cần mã hóa phòng thủ, bao gồm cả những thứ sẽ nhảy lên, hét lên và vẫy cờ đỏ khi họ phát hiện ra lỗi.
Được viết vào đầu những năm 90, những chi tiết cụ thể về điều này trong cuốn sách của Thielen khá là cũ. Chẳng hạn, trên Linux và Mac OS X, bạn không còn cần phải viết trình bao bọc của riêng mình cho toán tử mới C ++; bạn có thể sử dụng valgrind cho điều đó.
Nhưng có một vài điều tôi thường làm cho C / C ++ / ObjC:
- Khi tôi có thể hợp lý, hãy bật tùy chọn "Cảnh báo là lỗi" của trình biên dịch và sửa tất cả. (Tôi duy trì một dự án cũ mà việc sửa tất cả các dự án đó sẽ mất vài tuần, vì vậy tôi chỉ sửa một tệp mỗi vài tuần - và trong vài năm, tôi có thể bật tùy chọn đó lên.)
- Sử dụng một công cụ phân tích mã tĩnh, như PC-Lint của Gimpel hoặc công cụ rất tiện lợi hiện được tích hợp trong Xcode của Apple. Coverity thậm chí còn tốt hơn, nhưng chi phí dành cho các tập đoàn lớn, không chỉ là người phàm trần.
- Sử dụng các công cụ phân tích động, như valgrind, để kiểm tra các vấn đề về bộ nhớ, rò rỉ, v.v.
- Như Thielen nói (và chương này vẫn đáng đọc): Khẳng định thế giới . Tất nhiên, không ai ngoài một thằng ngốc sẽ gọi hàm của bạn bằng một con trỏ không - và điều đó có nghĩa là ai đó, ở đâu đó, là một thằng ngốc sẽ làm việc đó. Nó thậm chí có thể là bạn trong ba năm khi những gì bạn đang làm hôm nay trở nên mờ mịt. Vì vậy, chỉ cần thêm một xác nhận ở đầu hàm để xác thực đối số con trỏ đó - phải mất ba giây để nhập và biến mất trong bản thực thi phát hành.
- Trong C ++, RTTI là bạn của bạn. Một lần nữa, không ai khác ngoài một tên ngốc sẽ gọi hàm của bạn bằng một con trỏ đến loại đối tượng sai - điều đó có nghĩa là, chắc chắn, một số kẻ ngốc sẽ - và chi phí để chống lại điều đó là không đáng kể. Trong mã dựa trên C có nguồn gốc từ GObject, bạn có thể làm điều tương tự với các macro đúc động phòng thủ.
- Các bài kiểm tra đơn vị và hồi quy tự động hiện là một phần quan trọng trong tiết mục của tôi. Trong một dự án, chúng là một phần không thể thiếu của hệ thống xây dựng phát hành và bản dựng sẽ không hoàn thành trừ khi tất cả chúng đều vượt qua.
- Một phần quan trọng khác là ghi nhật ký mã trong cả hai tệp thực thi gỡ lỗi và phát hành có thể được kích hoạt trong thời gian chạy bằng một cái gì đó giống như một biến môi trường.
- Viết các bài kiểm tra phòng thủ để các lập trình viên chạy các chương trình thực thi gỡ lỗi không thể bỏ qua chúng nếu chúng thất bại. Tin nhắn thời gian chạy đến bàn điều khiển có thể được bỏ qua. Chương trình bị sập với một xác nhận không thể bỏ qua.
- Khi thiết kế, cung cấp API công khai và các triển khai riêng tư mà mã bên ngoài không thể có được. Theo cách đó, nếu bạn phải cấu trúc lại, không ai dựa vào một số biến trạng thái nội tâm kỳ diệu hay thứ gì đó. Trong các lớp C ++, tôi là một fan hâm mộ lớn của sự bảo vệ và riêng tư cho việc này. Tôi cũng nghĩ rằng các lớp proxy là tuyệt vời, nhưng bản thân tôi không thực sự sử dụng chúng.
Tất nhiên, những gì bạn sẽ làm cho một ngôn ngữ hoặc công nghệ mới sẽ thay đổi trong các chi tiết. Nhưng một khi bạn nghĩ đến những khái niệm rằng bọ là những con quái vật khổng lồ bạn viết bằng ngón tay của chính mình, và mã của bạn bị tấn công liên tục từ một đội quân ngu ngốc, với bạn là người đứng đầu, tôi chắc chắn bạn Sẽ tìm ra các kỹ thuật phòng thủ phù hợp.