Làm thế nào để giảm số lượng lỗi khi mã hóa?


30

Không ai hoàn hảo, và dù chúng ta có làm gì đi nữa, chúng ta sẽ tạo ra mã có lỗi trong đó theo thời gian. Một số phương pháp / kỹ thuật để giảm số lượng lỗi bạn tạo ra, cả khi viết phần mềm mới và thay đổi / duy trì mã hiện có là gì?


Một phương pháp tốt là thực hiện thiết kế trả trước nhiều hơn (không quá nhiều, nhưng đủ để làm cho mã của bạn có cấu trúc hơn và dễ hiểu hơn).
Giorgio

Câu trả lời:


58

Tránh mã hóa ưa thích. Mã càng phức tạp, càng có nhiều lỗi. Thông thường trên các hệ thống hiện đại, mã được viết rõ ràng sẽ nhanh và đủ nhỏ.

Sử dụng các thư viện có sẵn. Cách dễ nhất để không gặp lỗi khi viết một thói quen tiện ích là không viết nó.

Tìm hiểu một vài kỹ thuật chính thức cho những thứ phức tạp hơn. Nếu có điều kiện phức tạp, đóng đinh chúng bằng bút và giấy. Lý tưởng nhất, biết một số kỹ thuật bằng chứng. Nếu tôi có thể chứng minh mã chính xác, nó hầu như luôn luôn tốt ngoại trừ các lỗi lớn, ngu ngốc, rõ ràng rất dễ sửa. Rõ ràng, điều này chỉ đi xa, nhưng đôi khi bạn có thể chính thức lý luận về những điều nhỏ nhưng phức tạp.

Đối với mã hiện có, hãy tìm hiểu cách cấu trúc lại: cách thực hiện các thay đổi nhỏ trong mã, thường sử dụng một công cụ tự động, giúp mã dễ đọc hơn mà không thay đổi hành vi.

Đừng làm gì quá nhanh. Dành một chút thời gian lên phía trước để làm mọi việc đúng đắn, để kiểm tra những gì bạn đã làm và suy nghĩ về những gì bạn đang làm có thể trả hết thời gian lớn sau đó.

Khi bạn đã viết mã, hãy sử dụng những gì bạn có để làm cho nó tốt. Bài kiểm tra đơn vị là tuyệt vời. Bạn có thể thường xuyên viết các bài kiểm tra trước thời hạn, đây có thể là phản hồi tuyệt vời (nếu được thực hiện một cách nhất quán, đây là sự phát triển dựa trên kiểm tra). Biên dịch với các tùy chọn cảnh báo và chú ý đến các cảnh báo.

Hãy nhờ người khác xem mã. Đánh giá mã chính thức là tốt, nhưng chúng có thể không ở thời điểm thuận tiện. Yêu cầu kéo hoặc tương tự nếu scm của bạn không hỗ trợ chúng cho phép đánh giá không đồng bộ. Kiểm tra bạn bè có thể là một đánh giá ít chính thức. Lập trình cặp đảm bảo hai cặp mắt nhìn mọi thứ.


x2 - những gì Ryan nói.
JBRWilkinson

2
hầu hết các ngôn ngữ có thể ít nhiều kén chọn. Bạn muốn nó càng cầu kỳ càng tốt.

1
"Tìm hiểu một vài kỹ thuật chính thức cho những thứ phức tạp hơn." ... chẳng hạn?
Dan Rosenstark

1
@Yar: Tôi mong đợi một cái gì đó giống như các hệ thống giải thích trong cuốn sách này: amazon.com/Verification-Sequential-Concurrent-Programs-Computer/... ; mặc dù tôi phải nói rằng cuốn sách cụ thể cực kỳ khô khan và buồn tẻ, vì vậy có lẽ có những cuốn hay hơn nhiều (nhưng đó là cuốn duy nhất tôi đã đọc).
Joeri Sebrechts

30

Kiểm tra đơn vị cho phép bạn giảm số lượng lỗi xuất hiện lần thứ hai. Nếu bạn tìm thấy một lỗi trong mã của mình, viết một bài kiểm tra đơn vị sẽ đảm bảo nó không quay lại sau. (Thêm vào đó, nghĩ về tất cả các trường hợp và viết hàng ngàn bài kiểm tra đơn vị lên phía trước đôi khi rất khó để thực hiện)


3
"Suy nghĩ về tất cả các trường hợp lên phía trước" dẫn đến các giao diện sạch sẽ, được chỉ định đầy đủ, chỉ có thể là một điều tốt. Các bài kiểm tra đơn vị chỉ khó viết nếu bạn trang bị thêm chúng vào mã không được thiết kế để kiểm tra.
Mike Seymour

1
Nếu bạn có thể, bạn nên. Thật không may, hầu hết mọi nơi tôi đã từng xem các bài kiểm tra đơn vị là một cái gì đó có giá cao hơn là chỉ "sửa lỗi thực sự nhanh chóng". Vì vậy, nếu bạn có thể, thì bạn nên viết các bài kiểm tra trước, nhưng nếu nó không được coi là "hiệu quả về chi phí" thì việc viết chúng cùng với các bản sửa lỗi giúp bạn xây dựng nó theo thời gian mà không mất quá nhiều ngân sách cho việc viết bài kiểm tra đơn vị .
Ryan Hayes

4
"Thử nghiệm cho thấy sự hiện diện, không phải là không có lỗi." - E. Dijkstra. Điều đó đang được nói, kiểm tra tự động chắc chắn là một cách rất hữu ích để duy trì và tăng chất lượng phần mềm.
limist

9

+1 trên cả hai ý kiến ​​kiểm tra đơn vị.

Ngoài ra, hãy đặt mức cảnh báo cao nhất mà trình biên dịch của bạn đưa ra và đảm bảo các cảnh báo được coi là lỗi. Lỗi thường ẩn trong những lỗi "sai lầm" đó.

Tương tự, đầu tư vào các công cụ phân tích tĩnh chạy trong thời gian biên dịch (tôi xem chúng là một mức cảnh báo trình biên dịch bổ sung).


+1 cho nhận xét phân tích tĩnh. Thật là vô giá khi có được tất cả thông tin đó miễn phí :)
Morten Jensen

9

Ngoài những gì đã được đề cập:

  • Đừng bỏ qua mã lỗi - ví dụ: đừng cho rằng bạn có kết quả hợp lệ, rằng một tệp đã được tạo thành công, v.v ... Bởi vì một ngày nào đó, điều gì đó sẽ xảy ra.
  • Đừng cho rằng mã của bạn sẽ không bao giờ nhập một số điều kiện và do đó "an toàn để bỏ qua điều kiện đó".
  • Kiểm tra mã của bạn, sau đó kiểm tra nó bởi người khác. Tôi thấy tôi là người tồi tệ nhất để kiểm tra mã của riêng tôi.
  • Hãy nghỉ ngơi, sau đó đọc lại mã của bạn và xem nếu bạn "bỏ lỡ điều hiển nhiên". Thường xảy ra với tôi.

Nhiều thứ khác tôi đang quên vào lúc này, nhưng những thứ khác chắc chắn sẽ nghĩ về chúng. :)


7
Và nếu bạn chắc chắn rằng điều kiện X sẽ không bao giờ xảy ra ... hãy sử dụng một xác nhận để đảm bảo rằng khi điều kiện X xảy ra, bạn sẽ biết về điều đó (thông qua một ngoại lệ, hoặc đăng nhập hoặc bất cứ điều gì).
Frank Shearar

@MetalMikester: Bài kiểm tra đơn vị là tốt. Nhưng với các ngôn ngữ cấp cao và thư viện tốt, hầu hết các lỗi cứng yêu cầu kiểm tra tích hợp và hồi quy để đóng đinh.
Vector

9

Tôi đã phát triển một phong cách lập trình khá chức năng, mặc dù ngôn ngữ chính của tôi là C ++ và Python. Tôi thấy rằng nếu tôi chuyển tất cả ngữ cảnh cho một hàm (hoặc phương thức) mà hàm đó cần để thực hiện công việc của nó và trả về dữ liệu có ý nghĩa mà tôi đang tìm kiếm, thì mã của tôi đã trở nên mạnh mẽ hơn nhiều.

Trạng thái tiềm ẩn là kẻ thù và theo kinh nghiệm của tôi là nguồn lỗi số 1. Trạng thái này có thể là biến toàn cục hoặc biến thành viên, nhưng nếu kết quả phụ thuộc vào thứ gì đó không được truyền cho hàm bạn đang yêu cầu sự cố. Rõ ràng việc loại bỏ trạng thái là không khả thi, nhưng giảm thiểu nó có tác động tích cực rất lớn đến độ tin cậy của chương trình.

Tôi cũng muốn nói với đồng nghiệp của mình rằng mọi chi nhánh (nếu, trong, trong khi ,? :) là một lỗi có thể xảy ra. Tôi không thể nói biểu hiện của lỗi sẽ là gì, nhưng mã của bạn càng ít có điều kiện, thì càng có nhiều khả năng không có lỗi đơn giản do thực tế là phạm vi bảo hiểm mã trong khi thực thi sẽ phù hợp hơn.

Hãy hình dung, tất cả những điều này cũng có tác động tích cực đến hiệu suất. Thắng lợi!


Theo kinh nghiệm của tôi, nó có thể nhanh chóng trở nên tẻ nhạt khi chuyển qua tất cả trạng thái cho mỗi cuộc gọi, nếu các phương thức này nhỏ như chúng cần phải có. Vấn đề này có thể được giải quyết bằng cách sử dụng nhiều lớp nhỏ bất biến với thời gian sống đối tượng ngắn. Bằng cách đó bạn có thể lưu trữ trạng thái tạm thời dưới dạng các trường và loại bỏ đối tượng khi bạn không còn cần trạng thái nữa. :-)
Jørgen Fogh

Một cân nhắc khác cho trường hợp đó trở nên tẻ nhạt là có lẽ bạn đang cố gắng vượt qua quá nhiều trạng thái. :)
dash-tom-bang

Trong nhiều trường hợp điều đó đúng nhưng thường thì không. Trong một số miền, bạn cần truy cập vào nhiều trạng thái, ngay cả khi bạn không có nhiều trạng thái có thể thay đổi . Tôi hiện đang làm việc trên một trình tạo mã nơi tôi cần truy cập vào một số bảng biểu tượng. Tôi không muốn truyền chúng cho mọi phương pháp.
Jørgen Fogh

8
  • Viết ít mã mà làm nhiều hơn.
  • Hãy suy nghĩ về những hàm ý cấp thấp và sự phân nhánh cấp cao
  • Chiêm ngưỡng sự trừu tượng mà bạn đang tạo trong mã của mình.
  • Chỉ viết phức tạp cần thiết nếu có thể.

Tôi sẽ viết một bài lớn tóm tắt là "viết ít mà làm được nhiều hơn" (IOW biết và sử dụng các công cụ có sẵn cho bạn). Thay vào đó tôi sẽ chỉ +1 cái này.
Kaz Dragon

1
Nhưng hãy cẩn thận để không nhận được mã ưa thích khi cố gắng để đạt được ít mã hơn.
gablin

1
@gablin: Fancy là trong mắt của kẻ si tình ở nhiều khía cạnh. Tôi có thể viết và đọc mã ngày hôm nay rằng tôi sẽ bị choáng váng vào 4 năm trước. Haskell hôm nay là lạ mắt với tôi. :)
Paul Nathan

8

Một câu trả lời ít kỹ thuật hơn: không lập trình khi bạn mệt mỏi (9h / ngày là đủ), say rượu hoặc 'nướng'. Khi tôi mệt mỏi, tôi không đủ kiên nhẫn để viết mã sạch.


2
Nó thường mất hầu hết các lập trình viên vài năm để nhận ra điều này. Đó là một điểm quan trọng.
Jeff Davis

7

Viết bài kiểm tra đơn vịkiểm tra tích hợp .


5

Một số câu trả lời tuyệt vời ở đây liên quan đến thử nghiệm đơn vị và các công cụ. Điều duy nhất tôi có thể thêm vào chúng là:

Thu hút người kiểm tra của bạn sớm nhất có thể

Nếu bạn có một nhóm thử nghiệm, đừng rơi vào cái bẫy coi họ là người giữ cửa cho chất lượng mã của bạn và nắm bắt các khiếm khuyết của bạn cho bạn. Thay vào đó, hãy làm việc với họ và liên quan đến họ càng sớm càng tốt (đối với các dự án nhanh, điều này sẽ bắt đầu từ dự án, nhưng chúng ta luôn có thể tìm cách liên quan đến họ sớm hơn nếu chúng ta thực sự cố gắng).

  • Tìm hiểu kế hoạch kiểm tra của họ là gì. Xem xét các trường hợp thử nghiệm của họ với họ - bạn có bao gồm tất cả chúng bằng mã của bạn không?
  • Yêu cầu họ cho sự hiểu biết của họ về các yêu cầu. Nó có giống như của bạn không?
  • Cung cấp cho họ các bản dựng hoạt động sớm để thực hiện thử nghiệm khám phá trên - bạn sẽ ngạc nhiên về những cải tiến mà họ sẽ đề xuất.

Có mối quan hệ làm việc tốt với những người thử nghiệm của bạn có nghĩa là bạn có thể nắm bắt những giả định và khiếm khuyết thực sự sớm, trước khi họ có thể gây ra bất kỳ thiệt hại nào. Điều đó cũng có nghĩa là những người thử nghiệm cảm thấy được trao quyền để giúp thiết kế sản phẩm và nắm bắt các vấn đề về khả năng sử dụng khi có thời gian để khắc phục chúng.


4

Công cụ phân tích tĩnh

Các plugin và ứng dụng như FindBugs thu thập mã của bạn và tìm những nơi có lỗi tiềm ẩn . Những nơi mà các biến không được khởi tạo và sử dụng hoặc chỉ là những thứ điên rồ 9 lần trong số 10, giúp cho việc phát sinh lỗi dễ dàng hơn. Các công cụ như thế này giúp tôi ngăn chặn xương đầu của tôi di chuyển xuống đường ngay cả khi nó chưa phải là một lỗi.

PS: Hãy nhớ luôn luôn nghiên cứu lý do tại sao một công cụ cho bạn biết điều gì đó là xấu. Không bao giờ đau để học (và không phải mọi thứ đều đúng trong mọi tình huống).


3

Kiểm tra mã hoặc các hình thức đánh giá ngang hàng khác như lập trình cặp.

Các đánh giá mã có cấu trúc như kiểm tra Fagan có thể ít nhất có hiệu lực và hiệu quả như kiểm thử đơn vị và thậm chí đã được chứng minh là tốt hơn kiểm thử đơn vị trong một số trường hợp. Kiểm tra cũng có thể được sử dụng sớm hơn trong vòng đời phần mềm và với các tạo phẩm khác ngoài mã.

Nhận xét ngang hàng trong phần mềm của Karl Wiegers là một cuốn sách tuyệt vời về chủ đề này.


2

Ngoài tất cả các đề xuất khác ở đây, hãy bật tất cả các cảnh báo có thể lên mức độ nhạy cảm cao nhất và coi chúng là lỗi. Cũng sử dụng bất kỳ công cụ linting ngôn ngữ có.

Bạn sẽ ngạc nhiên khi có bao nhiêu lỗi đơn giản có thể bị bắt bởi các cảnh báo và có bao nhiêu trong số những điều đơn giản đó chuyển thành các lỗi thực sự trong mã của bạn.


2

Rất nhiều câu trả lời hay ở đây, nhưng một vài điều tôi muốn thêm vào. Hãy chắc chắn rằng bạn thực sự hiểu yêu cầu. Tôi đã thấy rất nhiều lỗi khi người dùng nghĩ rằng yêu cầu có nghĩa là X và lập trình viên nghĩ rằng nó có nghĩa là Y. Đẩy lùi để làm rõ các yêu cầu kém hoặc mơ hồ. Tôi biết tất cả chúng ta đều thích nhảy vào và viết mã nhưng càng dành nhiều thời gian để đảm bảo sự hiểu biết, sẽ càng ít làm lại và sửa lỗi.

Nhận biết doanh nghiệp bạn đang hỗ trợ, bạn sẽ thường thấy những điều trong yêu cầu còn thiếu hoặc cần giải thích thêm sau đó. Biết rằng nếu bạn thực hiện nhiệm vụ Y như đã nêu, nó sẽ phá vỡ tính năng Z.

Hiểu cấu trúc cơ sở dữ liệu của bạn. Nhiều lỗi là kết quả của một truy vấn đúng về mặt cú pháp, nhưng trả về kết quả sai. Tìm hiểu làm thế nào để nhận ra khi kết quả của bạn trông buồn cười. Nếu tôi đang viết một truy vấn báo cáo phức tạp, tôi luôn nhờ chuyên gia kỹ thuật xem xét kết quả của mình trước khi tôi đánh dấu nó là sẵn sàng, chắc chắn họ sẽ thấy một cái gì đó trong dữ liệu tôi đã bỏ lỡ. Sau đó ghi lại cho chính bạn những gì họ bắt được mà bạn đã không làm và hãy nhớ rằng lần sau khi bạn làm một cái gì đó tương tự.


1

Tôi nghĩ rằng kỹ thuật quan trọng nhất là mất thời gian của bạn . Nếu bạn cảm thấy bạn cần hai ngày để mã hóa một mô-đun mới, nhưng ông chủ của bạn buộc bạn chỉ mã hóa trong một ngày ... mã của bạn sẽ có nhiều lỗi hơn.

Một trong những cuốn sách tôi đọc cách đây một thời gian đã nói rằng bạn không nên sống với cửa sổ bị vỡ , bởi vì mọi người sẽ không quan tâm nếu người khác bị phá vỡ ... Mã hóa là như nhau, mọi người sẽ quan tâm đến việc là người đầu tiên làm điều gì đó tồi tệ nhưng nhanh , nhưng không ai quan tâm đến một mã địa ngục , với rất nhiều lỗi, và thiết kế và kiểu dáng rất kém.


1

Tôi tuân theo thực tiễn của Test-Code-Test thay vì Code-test-code-test. Điều này giúp tôi nghĩ về các trường hợp sử dụng và đóng khung logic


1

Sử dụng các công cụ kiểm tra mã như ReSharper hoặc IDE như IntelliJ IDEA để cảnh báo về nhiều lỗi sao chép và dán và các lỗi khác bằng cách chỉ ra các biến "được ghi, nhưng không bao giờ đọc". Đã tiết kiệm cho tôi rất nhiều thời gian.


1

Đáng ngạc nhiên, ba điểm rất quan trọng sau đây chưa được đề cập:

  • Sử dụng khẳng định một cách tự do. Câu hỏi bạn nên luôn tự hỏi mình là "tôi có nên khẳng định điều này không?" nhưng "có gì tôi quên khẳng định không?"

  • Lựa chọn không thay đổi. (Sử dụng cuối cùng / chỉ đọc một cách tự do.) Bạn càng có ít trạng thái đột biến, càng ít điều có thể sai.

  • Đừng tối ưu hóa sớm. Nhiều lập trình viên bị theo dõi bởi các mối quan tâm về hiệu năng, khiến họ phải phân tích mã một cách không cần thiết và bastard hóa thiết kế của họ mà không biết trước liệu hiệu năng có phải là vấn đề hay không. Đầu tiên, xây dựng sản phẩm phần mềm của bạn theo cách học thuật, coi thường hiệu suất; Sau đó, xem nếu nó thực hiện kém; (Có lẽ sẽ không.) Nếu có bất kỳ vấn đề về hiệu suất nào, hãy tìm một hoặc hai nơi bạn có thể cung cấp tối ưu hóa thuật toán chính thức và tốt đẹp để sản phẩm của bạn đáp ứng các yêu cầu về hiệu suất thay vì điều chỉnh và hack toàn bộ cơ sở mã của bạn bóp chu kỳ đồng hồ ở đây và ở đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.