Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Ruby

Làm Chủ Debug Ruby: Sửa Nhanh Lỗi Phổ Biến

Chương trình bạn làm đúng ý muốn lần đầu bao nhiêu lần?

Nhiều lần chương trình không hoạt động như mong đợi, phải dùng nghệ thuật debug ruby tìm ra tại sao.

Bạn có thể quen thông báo lỗi:

undefined method 'some_method' for nil:NilClass

Đây nghĩa là giá trị nil lọt vào code.

Dùng kỹ thuật bài này bạn học xử lý vấn đề này và vấn đề tương tự!

Hiểu Lỗi & Stack Traces

Khi nhận lỗi từ trình thông dịch Ruby hoặc chương trình không làm đúng, đến lúc đội mũ debug.

Nếu vấn đề là chương trình crash, quan trọng chú ý thông báo lỗi, thường chứa manh mối gì sai.

Ví dụ:

def method1
  method2
end
def method2
  puts invalid_variable
end
method1

Chạy code cho lỗi sau:

/tmp/stack.rb:6:in 'method2': undefined local variable or method 'invalid_variable' for main:Object (NameError)
from /tmp/stack.rb:2:in 'method1'
from /tmp/stack.rb:9:in '
'

Đây gọi là stack trace.

Phân tích cùng nhau!

Bắt đầu dòng trên cùng.

Nơi lỗi thực sự xảy ra, nhưng không nghĩa điều kiện lỗi bắt nguồn đây.

Tuy nhiên, điểm khởi đầu tốt điều tra.

Thỏa thuận:

Văn bảnMô tả
/tmp/stack.rb:6Tệp và số dòng
in `method2‘Tên phương thức
undefined local variable or method ‘invalid_variable‘Thông báo lỗi
main:ObjectTên lớp
(NameError)Tên exception

Như thấy lỗi không đáng sợ khi phân tích cách này.

Bạn có thể tìm danh sách exception tại đây.

Bây giờ:

Mỗi dòng stack trace dưới dòng đầu nói code đến đây như thế nào.

Về cơ bản là chuỗi phương thức, nếu đi xuống cuối cùng tìm thấy phương thức main của app.

Thuật toán chung xử lý stack trace:

  1. Đọc dòng đầu stack trace
  2. Nếu tệp thuộc dự án: mở tệp lỗi tại số dòng chỉ định. Nếu không, tiếp tục xuống stack trace cho đến tham chiếu đầu tiên đến tệp nhận ra
  3. Xem có gì rõ ràng nhảy vào mắt và sửa (tìm thứ nhắc trong thông báo lỗi)
  4. Nếu không giúp thì cần tìm thêm thông tin, như giá trị biến ảnh hưởng.

Debug Ruby

Kỹ thuật debug cơ bản (không nhất thiết xấu) bạn quen là dump giá trị biến nghi ngờ.

Trong Ruby làm bằng puts hoặc p.

Dùng p tương đương puts variable.inspect, hữu ích xem đối tượng.

Ví dụ:

Book = Struct.new(:title)
def find_book(title)
  books = []
  books << Book.new('Eloquent Ruby')
  books.find { |b| b.title == title }
end
book = find_book('Eloquent Ruby')
p book # In đối tượng book
book = find_book('POODR')
p book # In nil
book.name # Đoán xem tiếp theo!

Đào Sâu Hơn Với Pry

Khi nhiều biến cần kiểm tra, thêm puts khắp nơi không thực tế.

Trường hợp đó thử pry.

Dùng pry dừng code tại dòng cụ thể (breakpoint) và thả vào môi trường giống irb, đánh giá code Ruby trong ngữ cảnh dự án, hoặc chạy lệnh pry hữu ích.

Dùng pry thật dễ:

Chỉ thả binding.pry nơi muốn cài breakpoint.

Cũng cần require pry vào dự án (require 'pry').

Nếu chỉ tạm thời, gọi script Ruby như:

ruby -rpry app.rb

Không hữu ích cho Rails app, nên thêm pry vào Gemfile.

Mình thích macro/snippet trên editor đã include require cùng dòng breakpoint, xóa thì xóa cả hai.

Đây là màn hình khi rơi vào phiên pry:

Làm Chủ Debug Ruby: Sửa Nhanh Lỗi Phổ Biến

Muốn thoát hoàn toàn phiên pry gõ exit!, exit thường chạy chương trình đến breakpoint tiếp.

Sức mạnh pry không dừng ở đây. Ví dụ, dùng lệnh ls xem phương thức và biến instance đối tượng có.

Làm Chủ Debug Ruby: Sửa Nhanh Lỗi Phổ Biến

Đừng quên chạy help liệt kê tất cả tiện ích!

Debugger Ruby Khác: Byebug

Byebug thay thế pry hoặc debugger kiểu gdb cho Ruby.

Muốn dùng cho mục đích trước thì thả byebug thay binding.pry nơi muốn dừng. Nhược điểm Byebug so pry là không highlight cú pháp.

Xem cách set breakpoint và debug code trong byebug!

Thường gọi help, nhưng trường hợp này thiếu thông tin:

Làm Chủ Debug Ruby: Sửa Nhanh Lỗi Phổ Biến

Phải tra tài liệu.

Thấy lệnh break và số dòng set breakpoint.

Lấy danh sách breakpoint dùng info breakpoint.

Set breakpoint xong, di chuyển thực thi chương trình bằng lệnh:

  • step (tiến một instruction, step vào gọi phương thức)
  • next (tiến một instruction, không vào bên trong phương thức)
  • continue (chạy đến cuối hoặc breakpoint tiếp)

Gõ enter không lệnh lặp lại lệnh trước, rất hữu ích duyệt code.

Khi Mọi Cách Đều Thất Bại

Nghỉ ngơi khi đã dành nhiều thời gian mà không thấy giải pháp, quay lại với mắt mới sẽ nhận ra giải pháp ngay trước mặt. Có thể giải thích vấn đề cho người khác.

Đôi khi không chắc vấn đề ở đâu, vẫn còn nhiều lựa chọn.

Ví dụ, comment block code để cô lập vấn đề.

Nếu vấn đề biến mất, uncomment phần code vừa comment.

Giải pháp low-tech nhưng có thể chính xác cần.

Nếu đến đây vẫn không giúp:

Đến lúc dùng vũ khí nặng.

Dưới đây công cụ hệ thống thường hữu ích.

Một công cụ là Wireshark, kiểm tra traffic mạng.

Nếu traffic SSL-encrypted, mitm proxy như mitmproxy có thể giúp.

Thử curl khởi tạo HTTP connection từ terminal, giúp debug phản hồi server không hợp lệ.

Công cụ khác hữu ích là strace (chỉ Linux).

Strace hiện tất cả system calls app làm.

Lọc system calls cụ thể dùng option -e. Thay thế hiện đại strace là sysdig.

Cảnh báo! Tránh strace production vì làm giảm nghiêm trọng hiệu năng hệ thống test.

Cuối cùng, nếu vấn đề từ gem bên ngoài, bước rõ ràng kiểm tra source code gem.

Dùng lệnh gem open mở source code trên editor cấu hình.

Kết Luận

Dù debug không hoạt động vui nhất nhưng nhiều công cụ và kỹ thuật làm dễ dàng hơn, dùng chúng giúp bạn.

Xin chia sẻ bài viết nếu thích để nhiều người học! 🙂

Cảm ơn.