Phức tạp hóa vấn đề: Làm sao để debug?

<- Quay về trang chủ

Mới đây, trong một cuộc phỏng vấn, mình được hỏi một câu hỏi là:

  • "Giả sử bạn đang vận hành một website e-commerce, và khách hàng report rằng chức năng 'Add to Cart' không chạy, thì bạn sẽ troubleshoot vấn đề này như thế nào?"

Đây là một dạng câu hỏi mà theo mình là khá hay, mặc dù hơi không rõ ràng một tí, không biết người hỏi mong muốn nhận được câu trả lời như thế nào, nhưng đây đúng là thứ công việc mình làm hằng ngày, và có hàng tỉ cách để trả lời.

Hiểu vấn đề

Việc đầu tiên là phải làm rõ vấn đề, theo như bug report thì việc "không chạy" nó rất là tối nghĩa , chúng ta cần thêm thông tin, nên phải viết mail chửi thằng user tìm cách lấy thêm thông tin từ phái user, nếu không được thì tự mình reproduce xem có bị y vậy không?

Nhưng cuộc đời thằng dev chỉ biết ngồi fix bug, thường nó không êm đẹp, chuyện bắt liên lạc với user để hỏi cho ra ngô ra khoai về một con bug, trong nhiều trường hợp, nó là không tưởng . Chuyện reproduce thì cũng hên xui, nhiều khi không một ai trong team có thể reproduce được bug, nhưng ngoài kia, hàng trăm ngàn user vẫn gặp con bug đó mỗi ngày, bài viết này đặt bạn vào trong hoàn cảnh éo le như thế, vậy phải làm gì tiếp?

Phân tích vấn đề

Thiếu thông tin, và thiếu luôn bug sample để có thể điều tra trực tiếp, cách tốt nhất là vẽ ra bức tranh tổng quát về các thành phần liên quan của chức năng đang bị lỗi, rồi mình ngồi làm thầy bói. Ví dụ với chức năng "Add to Cart", ta có:

Theo như hình trên, chức năng giỏ hàng của chúng ta gồm có phía client:

  • Frontend: Là giao diện web dành cho người dùng thực hiện các thao tác với giỏ hàng

Phía server, gồm có 2 thành phần:

  • Backend: Là một API server có nhiệm vụ giao tiếp với frontend và ghi dữ liệu về giỏ hàng của từng user vào database, ở đây bỏ qua tính hiệu quả của việc ghi DB liên tục cho một dạng thông tin có vòng đời ngắn như giỏ hàng, để cho bài viết nó đơn giản
  • Database: Là nơi lưu thông tin giỏ hàng

Kết nối từ phía client lên server, tạm gọi là network connection, có thể bao gồm đường truyền internet, tường lửa phía server, các thiết lập có khả năng ảnh hưởng đến connection từ browser của client,...

Truy tìm nguyên nhân

Sau khi đã hình dung ra bức tranh tổng quát, chúng ta có thể lần lượt đưa ra giả định về khả năng lỗi của từng thành phần, cần phải nói luôn là dưới đây chỉ là một vài giả định có thể xảy ra chứ không phải là toàn bộ những lỗi có thể có:

Nếu lỗi ở network connection

Lỗi có thể xảy ra ở kết nối từ client tới server, có thể chia ra làm 2 loại lỗi chính, là những lỗi chúng ta (phía vận hành sản phẩm) kiểm soát được, và những lỗi không kiểm soát được.

Những vấn đề chúng ta kiểm soát được có thể là:

  • Thiết lập tường lửa ở server: Có thể vì một lý do gì đó mà chúng ta block một hoặc một vài user từ một vài địa chỉ IP nào đó rồi.
  • Reverse proxy, (nếu có, thực ra phân loại vô network connnection cũng chưa đúng lắm) không hoạt động: Ví dụ nginx bị lỗi config.
  • User bật ad blocker: Về lý thuyết, đây là thiết lập từ phía người dùng, thì chúng ta không kiểm soát được, nhưng không có lý do gì user bật ad blocker mà app của chúng ta lại bị ảnh hưởng, trừ khi chúng ta đã làm gì đó sai thiệt sai rồi.

Những vấn đề chúng ta không kiểm soát được:

  • Đường truyền internet của user bị cá mập cắn
  • Hệ thống mạng của user chặn kết nối đến API của chúng ta
  • ...

Nếu lỗi ở Frontend

Đứng ở góc độ frontend, những lỗi có khả năng xảy ra trong trường hợp này là:

Giả sử backend hoạt động tốt, thì phía frontend:

  • Quên xử lý sự kiện click của nút Add to Card (quên code)
  • Không handle đúng dữ liệu trả về của backend để render ra màn hình cho đúng

Hoặc nếu có lỗi từ backend, thì lỗi của phía frontend là:

  • Không handle trường hợp xảy ra lỗi khi gọi API
  • Không handle luôn cả request timeout,...

Hoặc cũng có trường hợp cả backend và frontend đều chạy đúng, nhưng có một lỗi không liên quan làm ảnh hưởng đến chức năng hiện tại, ví dụ như một lỗi ất ơ nào đó khi load trang, làm break cả frontend app, vì thế nên sự kiện click của nút Add to Card không chạy nữa,...

Nếu lỗi phía Backend

Từ phía backend, những lỗi có khả năng xảy ra là:

  • Quên không validate dữ liệu request lên từ phía frontend
  • Code logic để thêm một item vô cart bị sai, hoặc add lộn vô cart của một user khác
  • Không kết nối được với database, hoặc kết nối được nhưng viết raw SQL query nên khi insert vô DB thì bị lỗi cú pháp, hoặc bị SQL injection luôn mà không biết
  • Hoặc là mọi thứ hoạt động trơn tru, nhưng quên gửi data trả về cho frontend

Nếu lỗi phía Database

Nếu là từ phía database thì có thể là:

  • Quên bật database
  • Bị tràn dung lượng đĩa cứng (ai xài Wordpress với MySQL trên mấy con free host ngày xưa chắc gặp cái này hoài)

Đưa ra phương án khắc phục

Sau khi đã biết được nguyên nhân thì chúng ta có thể dễ dàng đưa ra cách khắc phục, nhưng quan trọng hơn hết là phải đưa ra được phương án hành động để không lặp lại vấn đề như thế này trong tương lai.

Cụ thể vấn đề lớn nhất có thể thấy từ đầu bài đó là vì sao phải ngồi vẽ rồng vẽ rắn rồi đoán mò từng bước như thế? Đó là vì chưa ai đề cập đến việc cần có một hệ thống tracking, monitoring từ cả frontend lẫn backend.

Trên thực tế, có rất nhiều công cụ giúp monitor, tracking lỗi hiệu quả, như Sentry, FullStory, hay các công cụ phân tích log như Splunk,...

Đáng ra phải đề cập luôn từ đầu bài nhưng tại viết tới đây rồi mới nhớ ra nên thôi, lười.

Kết

Tóm lại, sau khi đã có bức tranh toàn cảnh, thì việc chẩn đoán rất dễ, chỉ cần một ít nghi ngờ về bản thân và đồng đội, chúng ta có thể đưa ra hàng trăm giả thuyết để có thể blame nhau, rồi cùng nhau tìm cách reproduce, rồi fix, rồi commit, rồi test, rồi deploy, rồi xách cặp đi về nhà.

Nhưng việc đó chỉ đúng nếu bạn không phải là một frontend developer.

Trong bất cứ trường hợp nào, dù vấn đề xảy ra ở phía backend, database hay thậm chí là từ phía người dùng, nếu như có một dòng thông báo cụ thể trên màn hình thì cả team đã không mất thời gian vẽ rồng vẽ rắn và chỉ trỏ blame nhau như thế này, cho nên mọi tội lỗi đều có thể đổ lên đầu các bạn frontend developer (nếu biết trước cái nghề nó bạc vậy thì mình đã không theo).