Khi bạn mắc một lỗi ngữ nghĩa, lỗi đó có thể hoặc không thể nhận thấy ngay lập tức khi bạn chạy chương trình của mình. Một vấn đề có thể ẩn mà không bị phát hiện trong code của bạn trong một thời gian dài trước khi code mới được giới thiệu hoặc hoàn cảnh thay đổi khiến nó biểu hiện như một sự cố chương trình. Một lỗi nằm trong cơ sở code càng lâu trước khi nó được tìm thấy, thì càng khó tìm và một cái gì đó có thể dễ dàng sửa chữa ban đầu biến thành một cuộc phiêu lưu gỡ lỗi ăn hết thời gian và năng lượng.
Vậy chúng ta có thể làm gì về điều đó?
Nội dung chính
1. Đừng mắc lỗi
Vâng, điều tốt nhất là không mắc lỗi ngay từ đầu. Dưới đây là danh sách không đầy đủ những điều có thể giúp tránh mắc lỗi:
- Thực hiện theo các thực hành tốt nhất
- Đừng lập trình khi mệt mỏi.
- Hiểu nơi những cạm bẫy phổ biến trong một ngôn ngữ (tất cả những điều chúng ta cảnh báo bạn không nên làm)
- Giữ cho chương trình của bạn đơn giản
- Đừng để hàm của bạn quá dài
- Thích sử dụng thư viện chuẩn để viết code của riêng bạn, khi có thể.
- Comment tự do.
2. Chức năng tái cấu trúc
Khi bạn thêm các khả năng mới vào các chương trình của mình (Thay đổi hành vi của cải thiện), bạn sẽ thấy rằng một số chức năng của bạn phát triển theo chiều dài. Khi các chức năng trở nên dài hơn, chúng trở nên phức tạp hơn và khó hiểu hơn.
Một cách để giải quyết vấn đề này là chia một hàm dài thành nhiều hàm ngắn hơn. Quá trình thực hiện các thay đổi cấu trúc cho code của bạn mà không thay đổi hành vi của nó (thường là để làm cho nó dễ bảo trì hơn) được gọi là tái cấu trúc .
Vì vậy, bao lâu là quá dài cho một hàm? Một hàm chiếm một code giá trị màn hình dọc thường được coi là quá dài – nếu bạn phải cuộn để đọc toàn bộ hàm, tính dễ hiểu của hàm giảm đáng kể. Nhưng càng ngắn càng tốt – hàm ít hơn mười dòng là tốt. Các hàm ít hơn năm dòng thậm chí còn tốt hơn.
Cái nhìn sâu sắc
Khi thực hiện thay đổi code của bạn, hãy thực hiện thay đổi hành vi OR thay đổi cấu trúc và sau đó kiểm tra lại tính chính xác. Thực hiện thay đổi hành vi và cấu trúc cùng một lúc có xu hướng dẫn đến nhiều lỗi cũng như các lỗi khó tìm hơn.
3. Giới thiệu về lập trình phòng thủ
Lỗi có thể không chỉ do bạn tạo ra (ví dụ logic không chính xác), mà còn xảy ra khi người dùng của bạn sử dụng ứng dụng theo cách mà bạn không lường trước được. Ví dụ: nếu bạn yêu cầu người dùng nhập một số nguyên và thay vào đó họ nhập một chữ cái, chương trình của bạn sẽ hoạt động như thế nào trong trường hợp như vậy? Trừ khi bạn dự đoán điều này, và thêm một số xử lý lỗi cho trường hợp này, có lẽ không tốt lắm.
Lập trình phòng thủ là một thực tiễn trong đó lập trình viên cố gắng dự đoán tất cả các cách mà phần mềm có thể bị lạm dụng, bởi người dùng cuối hoặc bởi các developer khác (bao gồm cả chính lập trình viên) sử dụng code. Những lạm dụng này thường có thể được phát hiện và sau đó giảm nhẹ (ví dụ: bằng cách yêu cầu người dùng nhập dữ liệu xấu để thử lại).
Chúng ta sẽ khám phá các chủ đề liên quan đến xử lý lỗi trong các bài học trong tương lai.
4. Tìm lỗi nhanh
Vì việc không tạo ra lỗi là khó khăn trong các chương trình lớn, điều tốt nhất tiếp theo là bắt lỗi bạn thực hiện nhanh chóng.
Cách tốt nhất để làm điều này là lập trình từng chút một, sau đó kiểm tra code của bạn và đảm bảo nó hoạt động.
Tuy nhiên, có một vài kỹ thuật khác chúng ta cũng có thể sử dụng.
Giới thiệu về các hàm kiểm tra
Một cách phổ biến để giúp phát hiện ra các vấn đề với chương trình của bạn là viết các hàm kiểm tra vào tập thể dục, mã số mà bạn đã viết. Đây là một nỗ lực nguyên thủy, nhiều hơn cho mục đích minh họa hơn bất cứ điều gì:
/**
* Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
*
* @author cafedevn
* Contact: cafedevn@gmail.com
* Fanpage: https://www.facebook.com/cafedevn
* Instagram: https://instagram.com/cafedevn
* Twitter: https://twitter.com/CafedeVn
* Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
*/
#include <iostream>
int add(int x, int y)
{
return x + y;
}
void testadd()
{
std::cout << "This function should print: 2 0 0 -2\n";
std::cout << add(1, 1) << " ";
std::cout << add(-1, 1) << " ";
std::cout << add(1, -1) << " ";
std::cout << add(-1, -1) << " ";
}
int main()
{
testadd();
return 0;
}
Hàm testadd () kiểm tra hàm add () bằng cách gọi nó với các giá trị khác nhau. Nếu tất cả các giá trị phù hợp với mong đợi của chúng ta, thì chúng ta có thể tin tưởng một cách hợp lý hàm này hoạt động. Thậm chí tốt hơn, chúng ta có thể giữ hàm này xung quanh và chạy nó bất cứ khi nào chúng ta thay đổi hàm add để đảm bảo chúng ta không vô tình làm hỏng nó.
Đây là một hình thức kiểm tra đơn vị nguyên thủy , là một phương pháp kiểm thử phần mềm theo đó các đơn vị nhỏ của mã nguồn được kiểm tra để xác định xem chúng có đúng không.
Cũng như các khung đăng nhập, có nhiều khung kiểm tra đơn vị bên thứ 3 có thể được sử dụng. Bạn cũng có thể tự viết, mặc dù chúng ta sẽ cần nhiều tính năng ngôn ngữ hơn để chúng ta thực hiện công lý chủ đề. Chúng ta sẽ trở lại một số điều này trong một bài học trong tương lai.
5. Giới thiệu về các ràng buộc
Các kỹ thuật dựa trên các ràng buộc liên quan đến việc thêm một số code bổ sung (có thể được biên dịch trong bản dựng không gỡ lỗi, nếu muốn) để kiểm tra xem một số giả định hoặc kỳ vọng không bị vi phạm.
Ví dụ: nếu chúng ta đang viết một hàm để tính giai thừa của một số, dự kiến một đối số không âm, thì hàm có thể kiểm tra để đảm bảo người gọi chuyển qua một số không âm trước khi tiếp tục. Nếu người gọi chuyển qua một số âm, thì hàm có thể ngay lập tức bị lỗi thay vì tạo ra một số kết quả không xác định, giúp đảm bảo vấn đề được bắt gặp ngay lập tức.
Một phương pháp phổ biến để thực hiện điều này là thông qua assert và static_assert.
6. Các vấn đề chung
Các lập trình viên có xu hướng mắc một số loại lỗi phổ biến nhất định và một số lỗi có thể được phát hiện bởi các chương trình được đào tạo để tìm kiếm chúng. Các chương trình này, thường được gọi là công cụ phân tích tĩnh (đôi khi không chính thức gọi là xơ ) là những chương trình phân tích code của bạn để xác định các vấn đề ngữ nghĩa cụ thể (trong bối cảnh này, tĩnh phương tiện mà những công cụ phân tích mã nguồn). Các vấn đề được tìm thấy bởi các công cụ phân tích tĩnh có thể hoặc không thể là nguyên nhân của bất kỳ vấn đề cụ thể nào bạn đang gặp phải, nhưng có thể giúp chỉ ra các khu vực dễ vỡ của code hoặc các vấn đề có thể gây ra sự cố trong một số trường hợp nhất định.
Bạn đã có một công cụ phân tích tĩnh theo ý của bạn – trình biên dịch của bạn! Ngoài việc đảm bảo chương trình của bạn đúng về mặt cú pháp, hầu hết các trình biên dịch C ++ hiện đại sẽ thực hiện một số phân tích tĩnh nhẹ để xác định một số vấn đề phổ biến. Ví dụ: nhiều trình biên dịch sẽ cảnh báo bạn nếu bạn cố gắng sử dụng một biến chưa được khởi tạo. Nếu bạn chưa có, bật các mức cảnh báo và lỗi trình biên dịch có thể giúp hiển thị các mức này.
Các công cụ phân tích tĩnh khác tồn tại, một số trong đó có thể xác định hơn 300 loại lỗi lập trình. Và trên các chương trình lớn, điều này có thể giải quyết hàng chục hoặc hàng trăm vấn đề tiềm ẩn. Trên các chương trình học thuật nhỏ của chúng ta, không cần phải cài đặt hoặc chạy chúng, vì các cảnh báo của trình biên dịch thường sẽ đủ trong khi bạn đang học, nhưng trên cơ sở code lớn, điều này được khuyến nghị.