Tâm sự của một Coder: Tìm bug phải dựa vào cả linh cảm lẫn quy tắc

Đừng chỉ dựa vào linh cảm nếu bạn muốn trở thành một "rock star coder".

Tôi bắt đầu viết những dòng code đầu tiên cách đây gần 32 năm – khi tôi lên 6 tuổi. Tôi phát triển năng khiếu coding rất mạnh. Tôi có thể hiểu rõ mọi vấn đề và ngay lập tức biết cách giải quyết chúng, chỉ bằng trực giác.

Theo thời gian, tôi kiếm sống bằng nghề "code dạo", tôi cảm thấy mình như một người nổi tiếng, một "rock star coder" thật sự. Tôi phát hiện và sửa lỗi (fix bug) nhanh hơn tất cả các đồng nghiệp. Trưởng nhóm bắt đầu giao cho tôi các nhiệm vụ khó nhất và các bug hóc búa nhất. Họ gọi tôi là "phù thủy".

Coder

Tuy nhiên, làm theo trực giác không thể đưa tôi tiến xa hơn. Tôi có những bước tiến rõ rệt nhưng sau đó dừng lại và chẳng có gì nổi bật nữa. Năng khiếu viết code cũng không thể nào đẩy tôi về phía trước.

Rắc rối khi tin vào linh cảm

Điều không may rằng, trực giác (hay linh cảm) là một kỹ thuật dựa vào nhận thức để giải quyết vấn đề không thể được sử dụng để làm một tiêu chuẩn đánh giá tốt được. Khi chỉ dựa vào trực giác và năng khiếu, bạn sẽ vướng phải một đường cong có dạng như hình dưới:

Coder
Mối quan hệ giữa sự phức tạp của vấn đề (Problem Complexity), kinh nghiệm (Experience) và giới hạn về khả năng giải quyết vấn đề của mỗi người

Chắc chắn là bạn có thể chọn chấp nhận giới hạn và chỉ giải quyết những vấn đề nằm dưới đường này. Mặc dù có vẻ khiến cho một "rock star coder" như bạn cảm thấy thích thú nhưng chính nó sẽ bắt đầu giới hạn sự tăng trưởng và sự nghiệp của bạn nhanh chóng. Thêm nữa, lựa chọn này cũng chẳng có gì thú vị cả.

Khi đẩy bản thân mình tiến xa hơn trong sự nghiệp, tôi bắt đầu cảm thấy khó khăn và không thể dựa vào linh cảm được nữa – tôi nhận ra đó là một hướng đi hỗn loạn. Tôi không còn là một đứa trẻ cảm thấy háo hức được học hỏi khi ở trong môi trường mới.

Tôi biết rằng cuối cùng, mình cũng sẽ phải đối mặt với những người thông minh và tài năng hơn tôi (Ảo tưởng của tôi về sự vĩ đại là thật. Tôi không phải là thiên tài).

Nhưng khi nhìn xung quanh, tôi nhận ra rằng một vài người đánh bại tôi không phải bằng cách sử dụng "siêu trí tuệ" hay đại loại là một thứ gì đó thuộc về khả năng code "bẩm sinh". Họ chỉ có một "vũ khí" bí mật mà tôi hoàn toàn thiếu: quy tắc.

Điều này chỉ ra rằng một cách tiếp cận kiên trì, có phương pháp, lặp đi lặp lại đối với quá trình nhận thức và giải quyết vấn đề cuối cùng sẽ tạo ra thành quả lớn gấp bội so với bất cứ thứ gì được gọi là "bẩm sinh" hay năng khiếu – mà có lẽ bạn đã phát triển được.

Hãy trang bị cho mình các kỹ năng giải quyết vấn đề

Bất kể bạn là ai, đam mê của bạn như thế nào hay có khả năng thiên bẩm về Coding thì cuối cùng, bạn cũng sẽ gặp phải một giới hạn nhất định. Tuy nhiên, với một vài kỹ thuật sau đây, tôi chắc chắn bạn sẽ cải thiện được các kỹ năng giải quyết vấn đề của mình rất lớn đấy.

Code

Giả sử, bạn có một chương trình debugger. Bạn đã chạy nó, "Google" thử kết quả và bạn không thể phát hiện ra lỗi.

Tiếp tục, giả sử nếu vấn đề đó đã được chỉ ra bởi ai đó, bạn cần lặp lại (reproduce) lỗi đó. Nếu không, bạn cần tạo ra lỗi trước. Sau đó, hãy so sánh bối cảnh và môi trường xuất hiện lỗi mà bạn đang cố gắng lặp lại. Hãy bắt đầu loại bỏ mọi sự khác biệt, từng cái một cho tới khi bạn lặp lại lỗi thành công.

RTFM (Read The File Manual)

Đọc nhanh tài liệu, bạn đã sai lầm!

Hãy đọc nó thực sự - nhiều hơn một lần nếu cảm thấy cần thiết. Đừng chỉ đọc lướt để tìm kiếm những thứ mà bạn có thể copy - paste và sau đó, hy vọng là chúng hoạt động được với hệ thống của bạn.

Vấn đề ở đây là bạn muốn đọc thật nhanh câu trả lời. Bạn muốn nhanh chóng có được kết quả. Bạn không sẵn sàng bỏ sức ra để làm việc. Thế nên, hãy chậm lại, thở, uống một tách café và đọc các tài liệu liên quan thật kỹ.

Nếu không có tài liệu, hãy tự xây dựng và chia sẻ nó với những người khác sau khi bạn đã giải quyết được vấn đề.

Kiểm tra các giả thuyết

Nếu mong đợi điều gì xảy ra và kết quả là không thì đó là bởi vì bạn đã đưa ra một giả thuyết sai lầm ở một giai đoạn nào đó trong quá trình. Do vậy, hãy cố gắng kiểm định nhiều giả thuyết và chứng minh một cái đúng.

Hãy bắt đầu với các giả thuyết đơn giản nhất mà có thể kiểm tra nhanh nhất. Máy chủ có thực sự hoạt động không? Đã được kết nối mạng chưa? Mọi thứ có được đánh vần chính xác? Tất cả các dấu chấm phẩy và dấu ngoặc đơn đã được đặt đúng chỗ?

Nếu không bắt đầu với những thứ đơn giản nhưng cuối cùng một trong số chúng lại đúng là cái bạn cần tìm thì bạn có thể "phát điên" vì đã tốn quá nhiều thời gian đấy. Thế nên, đừng phức tạp hóa vấn đề.

Disassemble (tháo gỡ) và Reassemble (lắp ráp)

Hãy loại bỏ các thành phần trong giải pháp cho tới khi nó hoạt động trở lại, sau đó, lần lượt đặt chúng trở về vị trí ban đầu để tìm ra yếu tố bị phá vỡ.

Điều này có vẻ nhạt nhẽo và nhàm chán nhưng đây là một trong những cách hiệu quả nhất và có tính kỷ luật nhất để phát hiện nguyên nhân gây ra lỗi trong code của bạn. Tuy nhiên, hãy chắc chắn là đã thực hiện sao lưu trước khi bắt đầu.

Nếu rơi vào tình cảnh không biết cách lắp ráp các mã trở về đúng thứ tự ban đầu của nó thì dấu hiệu này cho thấy bạn đang đối mặt với một vấn đề nghiêm trọng hơn: bạn không hiểu codebase mà mình đang làm việc. Lúc này, cách tốt nhất là nhờ ai đó giải thích hoặc không thì bạn phải dành cả đêm để tìm hiểu về nó cũng như cách mà mã này làm việc.

Loại bỏ các biến (Variable)

Bất cứ thứ gì mà thay đổi từ lần thử đầu sang lần thử tiếp theo thì cũng nên được đặt ở trạng thái tĩnh trong khi bạn đang debug.

Đây chính là cách Test Driven Development (TDD) làm việc. Nếu đang sử dụng TDD thì bạn nên có một vài đối tượng giả định (mock object) trong quá trình loại bỏ.

Lập trình

Các mock object đều là những đối tượng "giả vờ" mà có thể bắt chước hành vi của những đối tượng thực theo nhiều cách có thể kiểm soát. Một lập trình viên đặc thù có thể tạo ra một mock để test hành vi của các đối tượng khác theo cách giống như một nhân viên thiết kế xe hơi sử dụng một hình nhân trong các bài test tai nạn để kích thích hành vi của con người dưới tác động của các vụ va chạm xe cộ.

Nếu không thực hiện TDD, bạn cần giả định một biến bất kỳ để có thể phát hiện ra lỗi trong điều kiện các yếu tố khác không thay đổi.

Lưu ý: Nếu bạn giả một đối tượng và bug đột nhiên biến mất thì khi đó nhiều khả năng lỗi nằm trong đối tượng mà bạn đã giả định.

Sử dụng kỹ thuật "Saff Squeeze"

Đây là một kỹ thuật được đặt tên và phổ biến bởi Kent Back, phát triển từ 2 ý tưởng trên.

Kent Back mô tả như sau: "Để tìm ra được sai sót, hãy bắt đầu kiểm tra ở cấp hệ thống và tiếp tục như vậy cho tới khi bạn tiến hành một bài test với khả năng nhỏ nhất sẽ xuất hiện sai sót đó".

Thế nên thay vì tháo rời các mock hay mã thì đơn giản là thêm các chức năng mà bạn đang kiểm tra vào trong chính các bài test, sau đó, giảm mức độ của các xác nhận (assertions) cho tới khi lỗi biến mất.

Điều này rất có lợi trong việc giúp bạn có thể thực hiện các bài test cụ thể và quy mô nhỏ hơn.

Sau khi sửa lỗi, lặp lại nó và sửa lại một lần nữa

Đừng bao giờ bỏ qua một lỗi cho tới khi bạn hoàn toàn hiểu rõ về cách sửa nó. Bạn nên lặp lại lỗi và tiếp tục sửa.

Đừng cảm thấy căng thẳng bởi vì nếu sửa một bug và bạn không chắc chắn chính xác nguyên nhân hay làm thế nào mà bạn đã sửa được nó thì lỗi có khả năng sẽ xuất hiện ở một thời điểm khác mà bạn không hề ngờ tới.

Năng khiếu thì sao?

Bạn đã học được các kỹ thuật debug quan trọng rồi đấy và vấn đề đặt ra là luôn luôn sử dụng chúng đầu tiên thay vì dựa vào năng khiếu của mình? Không, tuyệt đối không!

Nếu bạn có linh cảm mạnh về vấn đề xảy ra và có thể kiểm tra nó rất nhanh thì hãy thực hiện điều này đầu tiên. Nếu lỗi nằm dưới đường màu xanh trong biểu đồ trên thì khả năng lớn là dựa vào trực giác sẽ giúp bạn tìm ra giải pháp nhanh nhất.

Một khi bạn đã thử dựa trên linh cảm nhưng lại tìm sai lỗi thì hãy áp dụng các quy tắc mà tôi đã đề cập.

Linh cảm và các quy tắc sẽ giúp bạn trở thành một trong những Coder nổi trội nhất của bất kỳ một Team làm việc nào, miễn là bạn biết phát huy cả hai điều đó.

Thứ Bảy, 16/07/2016 20:30
51 👨 1.151