0
0
Lập trình
Thaycacac
Thaycacac thaycacac

12 Điều Học Được Khi Viết Công Cụ CLI Bằng Crystal

Đăng vào 3 ngày trước

• 5 phút đọc

Chủ đề:

#crystal

Giới thiệu

Tôi rất yêu thích ngôn ngữ lập trình Crystal. Trong hai hoặc ba năm qua, tôi đã xây dựng nhiều công cụ dòng lệnh (CLI) bằng Crystal. Trong suốt thời gian này, tôi thường so sánh nó với Ruby và đã gặp nhiều khác biệt, khám phá và thử thách. Trong bài viết này, tôi sẽ chia sẻ những điều mà tôi đã học được.

1. Sự Tương Đồng với Ruby

Crystal trông rất giống với Ruby. Nhiều biểu thức phổ biến trong Ruby cũng hoạt động trong Crystal. Crystal là ngôn ngữ kiểu tĩnh, nhưng hầu hết thời gian bạn không cần viết kiểu một cách rõ ràng. Trình suy diễn kiểu sẽ thực hiện công việc đó cho bạn.

2. Sử Dụng DeepWiki

DeepWiki là một nguồn tài nguyên rất hữu ích để học Crystal. Đối với một ngôn ngữ ít người biết, nó là một trong những nguồn tốt nhất. Bạn thậm chí có thể đặt câu hỏi bằng ngôn ngữ mẹ đẻ của mình.

3. Mảng và Bảng Băm Không Thể Trộn Kiểu

Trong Crystal, bạn không thể tự do trộn các kiểu khác nhau trong một Array hoặc Hash. Ruby cho phép điều này, nhưng Crystal thì không. Bạn có thể sử dụng kiểu liên hợp, nhưng thường thì tốt hơn là tránh chúng. Thay vào đó, hãy xem xét một trong số các tùy chọn sau:

  • Tạo một lớp hoặc cấu trúc
  • Sử dụng một bản ghi
  • Sử dụng một Tuple cho dữ liệu tạm thời

Ban đầu, điều này có thể cảm thấy bất tiện, nhưng bạn sẽ quen với nó.

crystal Copy
# Mảng(Int32 | String | Symbol) - không được khuyến nghị
arr = [1, "hai", :ba]

# OK: Liên hợp được viết rõ ràng
arr : Array(Int32 | String | Symbol) = [1, "hai", :ba]

# OK: Tuple cho vị trí cố định
t = {1, "hai", :ba}

# OK: bản ghi cho dữ liệu có cấu trúc
record Item, id : Int32, name : String, tag : Symbol
items = [
  Item.new(1, "táo",  :trái_cây),
  Item.new(2, "cam", :trái_cây),
]

4. Không Có eval

Crystal không có eval. Đây là một sự khác biệt lớn so với Ruby. Nếu bạn thực sự cần đánh giá động, bạn nên sử dụng Ruby. Một lựa chọn khác là nhúng mruby hoặc sử dụng một thư viện như Anyolite. Crystal có một trình thông dịch, nhưng nó không thực tế và chậm hơn Ruby hoặc mruby.

ruby Copy
# Ruby
code = "1 + 2"
puts eval(code) # => 3
crystal Copy
# Crystal không có eval
# Bạn phải thiết kế khác đi

5. Nạp Phương Thức

Trong Ruby, việc phân nhánh dựa trên kiểu tham số trong một phương thức là điều phổ biến. Trong Crystal, việc sử dụng nạp phương thức là tự nhiên hơn. Điều này làm cho mã rõ ràng hơn.

crystal Copy
def square(x : Int32) : Int32
  x * x
end

def square(x : String) : Int32
  square(x.to_i)
end

puts square(12)     # => 144
puts square("12")   # => 144

6. Kiểu Trả Về Cần Phải Nhất Quán

Trong Ruby, một phương thức có thể trả về các giá trị của các kiểu khác nhau. Trong Crystal, nếu kiểu trả về không rõ ràng, bạn sẽ gặp rắc rối. Nếu bạn muốn trả về nhiều kiểu khác nhau, bạn nên tách phương thức. Bạn có thể sử dụng một kiểu liên hợp, nhưng không được khuyến nghị.

crystal Copy
# không được khuyến nghị
def maybe_value(flag : Bool) : Int32 | String
  flag ? 42 : "bốn mươi hai"
end
crystal Copy
def value_int : Int32
  42
end

def value_str : String
  "bốn mươi hai"
end

7. Xử Lý Nil

Chú ý xem biến có thể là Nil hay không. Nếu có, bạn cần xử lý nó với not_nil!, if val = maybe_val, hoặc toán tử điều hướng an toàn.

crystal Copy
name : String? = nil

if n = name
  puts n.upcase
else
  raise "tên là nil"
end

8. Thu Gom Rác

Crystal sử dụng LLVM và dựa vào một GC bên ngoài (libgc). Hiệu suất thường gần giống với Rust hoặc Nim, nhưng việc phân tích và điều chỉnh bộ nhớ có thể khó khăn. Hơn nữa, thời gian của GC không thể dự đoán được, vì vậy Crystal có thể không phù hợp cho các hệ thống thời gian thực.

9. I/O Không Đồng Bộ

I/O không đồng bộ có sẵn theo mặc định. Một số lập trình viên cảm thấy nó dễ sử dụng hơn so với Rust.

10. Liên Kết Khi Phân Phối

Các chương trình Crystal thường được liên kết với libgc và các thư viện khác như libpcre2. Hãy cẩn thận khi phân phối nhị phân.

  • Linux: Bạn có thể xây dựng các nhị phân liên kết tĩnh với GitHub Actions + Docker + musl
  • macOS: Bạn có thể chuẩn bị một Homebrew Tap, hoặc xây dựng các nhị phân di động với liên kết tĩnh cho libgc, libpcre2, và các thư viện khác

Xem thêm: workflow của GitHub actions trong lolcat.cr

11. Hỗ Trợ Windows

Crystal giờ đây hoạt động trên Windows (MSVC / MinGW64) ổn định hơn trước. Thực thi song song cũng hoạt động. Tuy nhiên, việc giải quyết các phụ thuộc thư viện C vẫn có thể gặp khó khăn. Nếu bạn không quen thuộc với Windows, bạn có thể cần hỏi AI để được trợ giúp.

12. Hạn Chế của OptionParser

OptionParser chuẩn không hỗ trợ các tùy chọn ngắn kết hợp. Vì vậy ls -l -h hoạt động, nhưng ls -lh thì không. Tôi dự định tạo một pull request để sửa điều này trong tương lai.

Kết Luận

Viết các công cụ dòng lệnh bằng Crystal đôi khi rất đau đầu. Nhưng đồng thời, bạn học được rất nhiều. Tôi tin rằng "những ngày tốt nhất" của ngôn ngữ Crystal không phải ở quá khứ hay hiện tại, mà ở tương lai.


Bài viết này ban đầu dựa trên phản hồi của tôi trong một chủ đề trên Reddit, sau đó mở rộng thành một bài viết tiếng Nhật trên Qiita, và giờ được dịch sang tiếng Việt với sự trợ giúp của ChatGPT.

  • Cân nhắc viết lại công cụ CLI của tôi từ Ruby sang Crystal - tôi nên chú ý đến điều gì?
  • Crystalでコマンドラインツールを作って気づいた12のこと
Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào