Lập trình phòng thủ: Là hoang tưởng hay mã hóa thông minh?

Tại sao lập trình phòng thủ là cách tốt nhất để mã hóa mạnh mẽ

Lập trình phòng thủ là chương trình thực sự duy nhất.

Tín dụng hình ảnh: Pixabay.com

Lập trình phòng thủ là khi một lập trình viên lường trước các vấn đề và viết mã để giải quyết chúng.

Nó giống như nhìn thấy một vụ tai nạn xe hơi trong tương lai .. và giữ bình tĩnh vì bạn đã bảo hiểm cho nó.

Điều đó nói rằng, toàn bộ quan điểm của lập trình phòng thủ là bảo vệ chống lại các lỗi mà bạn không mong đợi. Một lập trình viên phòng thủ đang gặp rắc rối, để tránh nó trước khi nó có thể gây ra vấn đề thực sự. Ý tưởng là không viết mã mà không bao giờ thất bại. Đó là một giấc mơ không tưởng. Ý tưởng để làm cho mã thất bại đẹp trong trường hợp có bất kỳ vấn đề bất ngờ. Thất bại đẹp có thể có nghĩa là bất kỳ một trong những điều sau đây.

· Thất bại sớm: mã của bạn phải đảm bảo tất cả các hoạt động quan trọng được chấm dứt trước đặc biệt là nếu các hoạt động đó đắt tiền về mặt tính toán hoặc có thể ảnh hưởng đến dữ liệu.

· Không an toàn: khi có lỗi, mã của bạn phải đảm bảo rằng nó từ bỏ tất cả các khóa và không thu được bất kỳ khóa mới nào, không ghi tệp, v.v.

· Thất bại rõ ràng: khi một cái gì đó bị hỏng, nó sẽ trả về một thông báo lỗi và mô tả rất rõ ràng có thể cho phép nhóm hỗ trợ giải quyết lỗi.

Đồng ý. Bạn có thể tranh luận ở đây.

Không có vấn đề trong hiện tại. Mã của tôi đang hoạt động rất đẹp. Tại sao tôi nên đầu tư thời gian và công sức vào một vấn đề được dự đoán trước trong tương lai? Rốt cuộc, chúng tôi đã nhiều lần được dạy cách sử dụng Hồi Bạn Ain Gon Gonna Need It xông (YAGNI). Và bạn là một lập trình viên chuyên nghiệp và không phải là người có sở thích có thể tiếp tục thêm mã theo ý muốn.

Chìa khóa ở đây là chủ nghĩa thực dụng.

Andrew Hunt trong cuốn sách Lập trình viên thực dụng của mình mô tả lập trình phòng thủ với tên là Thực dụng hoang tưởng Paranoia.

Bảo vệ mã của bạn khỏi những người khác Lỗi lầm và lỗi của bạn. Nếu nghi ngờ, xác nhận. Kiểm tra tính nhất quán và toàn vẹn dữ liệu. Bạn có thể kiểm tra lỗi cho mọi lỗi, vì vậy hãy sử dụng các xác nhận và xử lý ngoại lệ cho những điều mà có thể xảy ra.

Lập trình Paranoid lành mạnh là loại lập trình phù hợp. Nhưng hoang tưởng có thể được đưa quá xa. Chìa khóa là sự cân bằng đúng.

Và đây là một số cách để lập trình phòng thủ.

Hãy tự hỏi: Nếu điều này thất bại?

Mỗi dòng mã làm một cái gì đó để điểm phòng thủ đầu tiên là tự hỏi nếu mã không thành công, thì sao.

Ví dụ, hãy xem xét mã không tuân thủ sau đây.

TRƯỜNG HỢP SY-INDEX. // Không tuân thủ; thiếu mệnh đề KHI NGƯỜI KHÁC
KHI MỘT.
VIẾT Một người.
KHI 2.
VIẾT Hai người.
KẾT THÚC.

Ở đây chúng ta có thể hỏi những câu hỏi sau đây.

Điều gì xảy ra nếu chỉ số sy không phải là 1.

Điều gì xảy ra nếu chỉ số sy không phải là 2.

Để giải quyết vấn đề này, chúng tôi thêm một câu lệnh OTHERS.

TRƯỜNG HỢP SY-INDEX.
KHI MỘT.
VIẾT Một người.
KHI 2.
VIẾT Hai người.
KHI NGƯỜI KHÁC. // Tuân thủ
VIẾT Kết quả bất ngờ
KẾT THÚC.

Đơn giản. Có phải là nó không?

Chính điều này là gì nếu mà Nghĩ rằng cách biệt các lập trình viên giỏi với những người viết mã và hy vọng nó không bao giờ thất bại. Không bao giờ, luôn luôn đến sớm hơn dự kiến, và sau đó mã được chôn trong một phần bị lãng quên từ lâu của chương trình, với các thông báo lỗi không cho biết vấn đề là ở đâu và cách giải quyết.

Cái hay của kỹ thuật lập trình phòng thủ này là hầu như không tốn thời gian để thêm kiểm tra kiểu đầy đủ vào mã của bạn. Bạn không phải là người viết về mã hóa. Bạn chỉ cần bảo mật mã của bạn.

Kiểm tra các điều kiện biên cẩn thận.

Việc kiểm tra đầu tiên là xác định xem bạn có cần một điều kiện biên không vì tất cả các vòng lặp đều đắt đỏ.

Điều kiện biên (hoặc cạnh) là nơi tất cả các hành động xảy ra. Vòng lặp từ 0 đến 100 và các giá trị vòng lặp từ 1 đến 98 khá giống nhau (tất nhiên là không có điều kiện trong mã). Nhưng vòng 0 là nơi mã đi vào vòng lặp và các điều kiện khởi tạo được thiết lập (và có thể thiết lập sai). Tương tự như vậy, vòng lặp cuối cùng là nơi mọi thứ rời đi, và bất cứ điều gì vòng lặp đang làm với các giá trị, đều dừng lại.

Một vòng lặp có nhiều nhất một lần lặp tương đương với việc sử dụng câu lệnh IF để thực thi có điều kiện một đoạn mã. Không nhà phát triển nào mong đợi tìm thấy cách sử dụng câu lệnh lặp như vậy. Nếu ý định ban đầu của tác giả thực sự là thực thi có điều kiện một đoạn mã, thì nên sử dụng câu lệnh IF.

Xem xét các mã không tuân thủ và tuân thủ sau đây. Chúng tôi không cần một vòng lặp trong trường hợp này. Một IF đơn giản sẽ làm.

            Ví dụ mã không tuân thủ
DATA còn lại LOẠI i.
LÀM 20 LẦN.
phần còn lại = sy-index MOD 2.
cl_demoDefput => write văn ().
LỐI RA. Không tuân thủ, vòng lặp chỉ thực hiện một lần. Chúng ta có thể sử dụng IF
KẾT THÚC.
          Ví dụ về mã tuân thủ
DATA còn lại LOẠI i.
LÀM 20 LẦN.
phần còn lại = chỉ số sy 2.
cl_demoDefput => write văn ().
KẾT THÚC.

Luôn nhớ các vòng lặp gỡ lỗi luôn liên quan đến hầu hết các nỗ lực ở đầu và cuối, đảm bảo những gì đi vào và những gì đi ra là chính xác. Vì vậy, một khi bạn rõ ràng với các điều kiện biên, không có gì khác thực sự có thể sai với mã của bạn.

Sử dụng TDD (Phát triển dựa trên thử nghiệm)

Ý tưởng cơ bản của TDD là đầu tiên viết các bài kiểm tra đơn vị, sau đó viết mã, sau đó tái cấu trúc, sau đó lặp lại.

Kiểm tra đơn vị là các kiểm tra tự động kiểm tra xem các chức năng có hoạt động như mong đợi hay không. Bài kiểm tra đơn vị đầu tiên của bạn sẽ thất bại vì nó được viết trước khi bạn có bất kỳ cơ sở mã nào.

Bạn thêm một chút vào mã trường hợp thử nghiệm. Bạn thêm một chút vào mã sản xuất. Hai luồng mã phát triển đồng thời thành các thành phần bổ sung. Các xét nghiệm phù hợp với mã sản xuất giống như một kháng thể phù hợp với một kháng nguyên.

Vấn đề với mã kiểm tra là bạn phải cách ly mã đó. Thường rất khó để kiểm tra một chức năng nếu chức năng đó gọi các chức năng khác. Để viết bài kiểm tra đó, bạn đã phải tìm ra một cách nào đó để tách rời chức năng khỏi tất cả những người khác. Nói cách khác, trước tiên cần phải kiểm tra buộc bạn phải suy nghĩ về thiết kế tốt.

Điều này tạo ra một thiết kế tách rời tốt hơn, trong đó bạn có quyền kiểm soát tốt hơn đối với mọi thứ khi mã phát triển.

Mặc dù viết các trường hợp kiểm tra trả trước có thể tiêu tốn thời gian ban đầu nhưng điều này mang lại rất nhiều lợi ích. Các nhà phát triển thừa nhận rằng trước đây họ từng viết các dòng mã, nhận ra rằng các giải pháp của họ không liên quan và sau đó bắt đầu mã hóa lại từ đầu.

Không giống như các thực tiễn mã hóa lỗi thời, TDD cho phép các nhà phát triển quay trở lại bảng vẽ và tập trung vào việc thiết kế một kiến ​​trúc gọn nhẹ, linh hoạt.

Và thực tế việc viết các trường hợp kiểm tra trả trước ngăn chặn bất kỳ lỗi nào có thể xuất hiện sau đó do đó tiết kiệm thời gian, công sức và ợ nóng.

Luôn viết mã tối ưu hóa.

Một số chương trình (và lập trình viên) thích tài nguyên rất nhiều. Nhưng bất cứ khi nào bạn có thể, sử dụng tối thiểu. Và để sử dụng tối thiểu, mã của bạn phải được tối ưu hóa nhất có thể.

Thông thường, một cách chắc chắn để tối ưu hóa là bật bất kỳ tối ưu hóa nào mà trình biên dịch cung cấp sẵn có.

Tối ưu hóa trình biên dịch thường cải thiện thời gian chạy từ một vài phần trăm đến hệ số 2. Đôi khi, nó cũng có thể làm chậm sản phẩm, vì vậy chỉ cần đo cẩn thận trước khi thực hiện cuộc gọi cuối cùng. Tuy nhiên, các trình biên dịch hiện đại làm rất tốt trong vấn đề này vì chúng làm giảm bớt phần lớn nhu cầu thay đổi quy mô nhỏ của các lập trình viên.

Bên cạnh việc tối ưu hóa trình biên dịch tiêu chuẩn, có một số kỹ thuật điều chỉnh khác có thể được sử dụng.

Thu thập các biểu hiện chung.

Nếu một tính toán đắt tiền xảy ra ở nhiều nơi, tốt hơn là tính toán ở một nơi và ghi nhớ kết quả. Don lồng đặt các tính toán như vậy trong một vòng lặp trừ khi được yêu cầu.

Thay thế các hoạt động đắt tiền bằng những người giá rẻ.

Thao tác chuỗi có lẽ là một trong những hoạt động phổ biến nhất trong bất kỳ chương trình nào. Tuy nhiên, nó có thể là một hoạt động đắt tiền nếu được thực hiện không chính xác. Tương tự, trong một số trường hợp, bạn có thể cải thiện hiệu suất bằng cách thay thế phép nhân bằng một loạt các thao tác thay đổi. Ngay cả khi điều này có hiệu quả (và luôn luôn là nó), nó tạo ra mã rất khó hiểu. Vì vậy, đưa ra quyết định xem xét khả năng đọc của mã cũng.

Loại bỏ các vòng lặp.

Vòng lặp chủ yếu là chi phí chung. Cố gắng tránh các vòng lặp bất cứ nơi nào có thể nếu số lần lặp không nhiều.

Cache giá trị sử dụng thường xuyên.

Bộ nhớ đệm tận dụng lợi thế của địa phương, xu hướng của các chương trình và người dân sử dụng lại dữ liệu được sử dụng gần đây. Bộ nhớ đệm chỉ là ký tự hoặc dữ liệu được sử dụng nhiều nhất cải thiện đáng kể hiệu suất của chương trình.

Viết lại bằng ngôn ngữ cấp thấp hơn.

Đây nên là phương sách cuối cùng. Các ngôn ngữ cấp thấp hơn có xu hướng hiệu quả hơn, mặc dù tốn nhiều thời gian hơn từ quan điểm của lập trình viên. Đôi khi, chúng tôi nhận được những cải tiến đáng kể bằng cách viết lại mã quan trọng bằng các ngôn ngữ cấp thấp hơn nhưng điều này đi kèm với chi phí giảm tính di động và việc bảo trì trở nên rất khó khăn. Vì vậy, hãy quyết định cẩn thận.

Hãy nhớ trong tối ưu hóa, lựa chọn có lẽ là 90% của trò chơi. Nó có giá trị dành thời gian để quyết định những gì bạn đang làm và làm điều đó đúng. Tất nhiên: Rằng cũng là nơi ma thuật đen nằm!

Và cuối cùng, không tin ai.

Có những điều đã biết có những điều chúng ta biết chúng ta biết, Keith Donald Rumsfeld, Bộ trưởng Quốc phòng trong chính quyền Bush thứ hai, từng nói trong một cuộc họp báo. Chúng tôi cũng biết có những ẩn số đã biết; điều đó có nghĩa là chúng ta biết có một số điều chúng ta không biết. Nhưng cũng có những ẩn số chưa biết - những người mà chúng tôi không biết, chúng tôi không biết.

Rumsfeld đã nói về cuộc chiến ở Iraq, nhưng điều tương tự cũng đúng với dữ liệu. Tóm lại, điều này có nghĩa là để xác minh tất cả dữ liệu mà bạn không có quyền kiểm soát hoàn toàn.

Rõ ràng, dữ liệu người dùng luôn bị nghi ngờ. Người dùng rất có thể hiểu sai những gì bạn nghĩ là rõ ràng. Hãy thử và dự đoán các vấn đề, và xác minh hoặc dọn dẹp mọi thứ xuất hiện.

Dữ liệu cài đặt chương trình cũng dễ bị lỗi. Các tệp INI từng là một cách phổ biến để lưu cài đặt chương trình. Bởi vì chúng là một tệp văn bản, nhiều người có thói quen chỉnh sửa chúng bằng tay với trình soạn thảo văn bản và có thể (có thể) làm hỏng các giá trị. Dữ liệu đăng ký, tệp cơ sở dữ liệu - ai đó có thể và sẽ điều chỉnh chúng vào một ngày nào đó, vì vậy phải trả tiền để xác minh ngay cả những điều đó.

Nói tóm lại, dữ liệu đến phải sạch sẽ nếu bạn có bất kỳ hy vọng nào về mã của mình làm những gì nó có nghĩa là làm. Nếu bạn đã từng nghe cụm từ Rác Rác trong, Rác ra thì đây là nơi nó đến.

Như Edward Demming đã nói đúng.

"Chúng ta tin vào Chúa. Tất cả những người khác phải mang theo dữ liệu.
Giới thiệu về tác giả-:
Ravi Rajan là một người quản lý chương trình CNTT toàn cầu có trụ sở tại Mumbai, Ấn Độ. Ông cũng là một blogger nhiệt tình, nhà văn thơ Haiku, người đam mê khảo cổ học và người mê lịch sử. Kết nối với Ravi trên LinkedIn, Medium và Twitter.