2 điểm bởi GN⁺ 2023-12-07 | 1 bình luận | Chia sẻ qua WhatsApp
  • Jepsen là công cụ kiểm chứng các hệ thống đồng thời như cơ sở dữ liệu, nên mô hình đồng thời và khả năng hỗ trợ luồng thực tế của ngôn ngữ triển khai là tiêu chí lựa chọn quan trọng
  • Cấu trúc dữ liệu bất biến và bền vững của Clojure cùng các công cụ đồng thời của JVM giúp giảm khả năng lỗi trong mã kiểm thử, đồng thời phù hợp với các client cơ sở dữ liệu nền Java
  • Công việc với Jepsen gần với thử nghiệm và khám phá hơn là phát triển sản phẩm theo khuôn mẫu, nên các tính năng của Clojure như REPL, macro, threading macro và EDN có lợi cho việc xử lý dữ liệu phức tạp
  • Hiệu năng không thuộc nhóm cao nhất, nhưng Clojure viết theo lối idiomatic thường chỉ chậm hơn Java trong phạm vi một đến hai bậc độ lớn; những điểm cần thiết có thể xử lý bằng tối ưu hóa và công cụ profiling của JVM
  • Dù có các điểm yếu như cộng đồng nhỏ, thiếu một hệ thống kiểu tĩnh được chấp nhận rộng rãi và thành công, xử lý primitive bất tiện, thông báo lỗi chưa tốt, nhưng với Jepsen do 1–3 người duy trì và sử dụng, đây là sự đánh đổi có thể chấp nhận

Điều kiện ngôn ngữ phù hợp với công cụ kiểm thử đồng thời

  • Jepsen được tạo ra để kiểm thử các hệ thống đồng thời, và đối tượng kiểm thử phần lớn là cơ sở dữ liệu
  • Clojure đáp ứng tốt các điều kiện cơ bản cần có khi viết mã kiểm thử đồng thời
    • Cấu trúc dữ liệu bất biến và bền vững giúp giảm khả năng lỗi trong mã xử lý trạng thái chia sẻ
    • Có thể sử dụng luồng thực, promise, future, atom, lock, queue, cyclic barrier, java.util.concurrent, v.v.
    • Từng cân nhắc các ngôn ngữ kiểm soát tác dụng phụ nghiêm ngặt hơn như Haskell, nhưng cách tiếp cận ít giáo điều hơn của Clojure phù hợp với Jepsen hơn
  • Kiểm thử cơ sở dữ liệu cần kết nối với nhiều loại client khác nhau
    • Hầu như mọi cơ sở dữ liệu thường đều cung cấp client JVM viết bằng Java
    • Clojure có khả năng tương tác tốt với Java, nên dễ tận dụng các client này

Các tính năng Clojure có lợi cho thử nghiệm và khám phá dữ liệu

  • Kiểm thử Jepsen là công việc mang tính thử nghiệm, nên cần một ngôn ngữ ngắn gọn, dễ thay đổi và phù hợp để tạo prototype
    • Cú pháp ngắn gọn và hệ thống macro của Clojure rất phù hợp với cách làm này
    • Threading macro giúp các chuỗi biến đổi dễ đọc hơn
    • Macro giúp dễ triển khai xử lý lỗi có thể tái sử dụng và kiểm soát phạm vi tài nguyên
    • Clojure REPL hữu ích để khám phá tại chỗ dữ liệu kết quả chạy kiểm thử
  • Trong quá trình kiểm thử cần biểu diễn, biến đổi và kiểm tra các cấu trúc dữ liệu phức tạp, lồng nhau
    • Cấu trúc dữ liệu và các hàm thư viện chuẩn của Clojure rất mạnh cho việc này
    • Khi xuất nhiều dữ liệu có cấu trúc ra console và file, cú pháp dữ liệu EDN rất phù hợp

Đánh đổi giữa hiệu năng và bảo trì dài hạn

  • Jepsen không phải hệ thống quá lớn, nhưng xử lý một lượng dữ liệu vừa phải nên cần hiệu năng “đủ tốt”
    • Clojure không phải ngôn ngữ nhanh nhất
    • Clojure viết theo lối idiomatic thường chỉ có chênh lệch hiệu năng trong phạm vi một đến hai bậc độ lớn so với Java
    • Ở các nút thắt quan trọng có thể thu hẹp khác biệt
    • Công cụ profiling của JVM hoạt động tốt với Clojure
  • Jepsen là dự án khoảng 10 năm tuổi, nên phần lõi trưởng thành và tính ổn định là quan trọng
    • Clojure ổn định cả ở mục tiêu JVM lẫn bản thân ngôn ngữ
    • Thư viện không “mục nát” nhanh như Scala hay Ruby

Những điểm yếu của Clojure cần chấp nhận

  • Clojure có những nhược điểm có thể chấp nhận ở quy mô Jepsen, nhưng có thể trở thành gánh nặng với các nhóm lớn hơn
    • Cộng đồng kỹ sư nhỏ
    • Không có hệ thống kiểu tĩnh được chấp nhận rộng rãi và thành công
    • Jepsen mỗi lần chỉ có 1–3 người duy trì và sử dụng, nên hạn chế này ít ảnh hưởng hơn
  • Khi xử lý primitive của JVM, nếu không chuyển xuống Java thì có thể khá khó chịu, và thực tế đôi khi vẫn dùng Java
  • Một số phần của hệ thống đa hình còn thiếu sót nhưng có thể đi đường vòng bằng thư viện, và thông báo lỗi cũng không tốt
  • Jepsen từng được tạo prototype bằng nhiều ngôn ngữ trước khi quyết định dùng Clojure, và sau 10 năm, đây vẫn là một sự đánh đổi khá tốt

1 bình luận

 
GN⁺ 2023-12-07
Các ý kiến trên Hacker News
  • Từ góc nhìn của người đã vận hành SaaS bằng Clojure/ClojureScript khoảng 10 năm, tôi hoàn toàn đồng ý với bài viết của Kyle
    Một điểm nữa rất có giá trị là có thể đặt phần lớn mã miền nghiệp vụ trong các tệp cljc để biên dịch cho cả phía máy chủ lẫn máy khách; transducer và các pipeline transducer bị đánh giá thấp về hiệu năng, khả năng kết hợp và tái sử dụng; và đúng như một ngôn ngữ do Rich Hickey thiết kế, nó có độ ổn định và khả năng tương thích dài hạn xuất sắc
    Tương thích ngược rất quan trọng, nhờ đó có thể tập trung vào ứng dụng thay vì bị cuốn theo các công cụ liên tục thay đổi; tôi cũng không nghĩ việc lập trình viên Clojure trung bình có hơn 12 năm kinh nghiệm và nhận mức đãi ngộ thuộc tứ phân vị trên là ngẫu nhiên

    • Tôi cũng ở tình huống tương tự. SaaS của tôi cũng chạy bằng Clojure, và so với các ngôn ngữ khác thì việc bảo trì dễ như mơ
      Hầu như không hỏng và nâng cấp cũng dễ. Nhờ HMR, REPL và các tệp cljc, trải nghiệm lập trình viên cũng tuyệt vời, còn mã Clojure thì viết rất vui
    • Trong toàn bộ các lợi ích đó, bạn nghĩ phần nào đến từ JVM, và phần nào đến từ chính ngôn ngữ Clojure?
    • Clojure có web framework nào dùng ổn không?
    • Nếu tương thích ngược quan trọng đến vậy, tôi thắc mắc vì sao nó lại bị đối xử như ngoại lệ chỉ khi áp dụng cho C và C++
      Người ta nói việc bẻ cong ngôn ngữ và hệ thống để không phá vỡ những thứ đang hoạt động là ổn, nhưng tôi không hiểu vì sao lại kỳ vọng hai ngôn ngữ đang chống đỡ một phần lớn phần mềm thực sự đang chạy phải cắt đứt quá khứ huy hoàng và hiện tại của mình
  • Vấn đề lớn nhất của Clojure chắc chắn là hệ sinh thái
    Nhìn vào phân bố của các công cụ dễ tiếp cận và dùng được, hoặc chúng nằm quá xa bên trái nên vừa tệ hại nhưng dễ tiếp cận, hoặc quá xa bên phải đến mức README có trích dẫn Chúa tể những chiếc nhẫn, mọi thứ đều là dữ liệu tới bậc n, và chỉ những con rồng có thể bịt mắt, treo ngược mà vẫn viết được plugin Emacs mới tiếp cận nổi
    Bản thân ngôn ngữ thì tuyệt vời và khả năng tương tác với Java cũng tốt hơn nhiều so với những gì Aphyr nói, nhưng nếu Clojure có thứ gì đó như Rails hay Django, hoặc tốt hơn là Phoenix, thì sẽ dễ thuyết phục hơn nhiều và có lẽ đã được dùng rộng rãi hơn
    Đặc biệt, để thuyết phục một nhóm chuyển từ các ngôn ngữ mệnh lệnh họ Algol sang Lisp, thứ nhận được phải lớn hơn nỗi vất vả; hiện nay, ngoài các thành phần cơ bản như HTTP routing, gần như dự án nào cũng phải phát minh lại bánh xe
    Dù vậy, việc có thể dùng bất kỳ gói Maven nào và biên dịch thành jar là một lợi thế cực lớn, vì ở đâu chạy được jar thì Clojure cũng chạy được

    • Nhất định nên xem Calva, một plugin tuyệt vời cho VSCode. Nó cung cấp không chỉ REPL mà cả các tính năng như tài liệu thời gian thực, giúp dùng Clojure dễ dàng, và tôi dùng nó hằng ngày trong công việc
      https://calva.io
    • Có vẻ bạn chưa từng viết code Clojure để kiếm sống. Hệ sinh thái và cộng đồng Clojure được duy trì tốt
      Clojure có nhiều hình thái, chủ yếu là Clojure và ClojureScript; còn có Babashka, Scittle, v.v., nhưng tất cả đều phái sinh từ clj hoặc cljs
      Công cụ phát triển thay đổi tùy nền tảng và sở thích IDE, nên Emacs, Neovim, VSCode, IntelliJ đều có công cụ khác nhau; hệ thống build cũng tùy nhu cầu
      Với clj, deps.edn hiện được dùng nhiều nhất, sau đó là leiningen; với cljs, ngoài shadow-cljs còn có nhiều lựa chọn khác
      Với người mới tiếp cận thì có thể choáng ngợp, nhưng cộng đồng rất tốt và luôn giúp đỡ. Tôi đã lập trình chuyên nghiệp bằng nhiều ngôn ngữ, nhưng Clojure là ngôn ngữ tôi thích nhất rõ ràng
    • Tôi tò mò ví dụ về công cụ “tệ hại nhưng dễ tiếp cận” là gì
      Tôi dùng Clojure từ khoảng năm 2013 mà không nghĩ ra công cụ nào như vậy. Hầu hết thư viện phổ biến đều tuyệt vời, và về độ ổn định, tương thích ngược, sự đơn giản thì vượt xa phần lớn các hệ sinh thái mà tôi biết
    • Điều này trông giống một bình luận Clojure ngẫu nhiên hơn là liên quan đến Jepsen hay nội dung bài viết
    • Bổ sung cho những ai chưa rõ Clojure: như /u/jwr đã nói trong luồng này, nhờ ClojureScript, Clojure cũng chạy được ở nơi có trình duyệt
      Nhờ các tệp nguồn .cljc có thể dùng chung cho cả Clojure và ClojureScript, cùng một mã Clojure có thể chạy ở cả frontend lẫn backend
      Như Rich Hickey nói, không chỉ JVM “vươn tới” được mà JavaScript cũng vươn tới được
      Tôi đã dùng Emacs lâu năm và cuối cùng có thể cấu hình theo ý muốn hoặc viết được mã elisp cần thiết, nhưng hoàn toàn không thể nói mình giỏi elisp
      Tôi thừa nhận rằng với một người chưa từng học bất kỳ phương ngữ Lisp nào, việc học đồng thời Emacs, elisp và Clojure là khó và cũng rất khó thuyết phục
      Hiện nay đã có Clojure LSP server và nó hoạt động không chỉ với Emacs mà cả các IDE khác, nên dù nhiều lập trình viên Clojure dùng Emacs, Emacs không phải là điều bắt buộc để phát triển Clojure
  • Tôi đã chỉ dùng Clojure suốt 7 năm và đang tích cực làm việc với một codebase Clojure + ClojureScript hơn 500.000 dòng, và điều tôi bất mãn nhất là thiếu một hệ thống kiểu vững chắc
    Tôi đồng ý rằng Clojure có sức biểu đạt tốt, cho phép tiến nhanh và không cản đường, nhưng nó cũng cho phép những lỗi runtime lộn xộn, khó tái hiện và khó debug
    Nếu có một hệ thống kiểu tĩnh được chấp nhận rộng rãi và thành công, Clojure hẳn đã rất tuyệt. Hiện tại tôi thấy nó khá ổn nếu bạn thích Ruby hoặc Python nhưng muốn thứ gì đó mạnh hơn; còn giờ tôi lại tự hỏi liệu Go có phải con đường đúng không

    • Ở những phần đã đo lường được rằng kiểu tĩnh có ích, có thể tích hợp các ngôn ngữ JVM khác như Kotlin vào dự án Clojure
  • Clojure(Script) thực sự gần như là một phước lành, và tôi hoàn toàn đồng ý rằng dù dự án nhỏ hay lớn, nó đều là một lựa chọn tuyệt vời
    Sau khi dùng C, Python, PowerShell, Java, Bash, SQL mỗi thứ một chút cho bài tập đại học, quản trị hệ thống, phân tích traffic dump, v.v., ngôn ngữ đầu tiên tôi dùng để lập trình chuyên nghiệp là Clojure
    Tôi đang xây dựng OrgPad bằng Clojure+ClojureScript, và dù code đã vượt quá 100.000 dòng, tôi vẫn nghĩ đó là một quyết định đúng
    Nó dễ tiếp cận, và chỉ cần viết một chút code là tôi khá tin rằng nó sẽ hoạt động đúng như mình hình dung. Với Python, PowerShell, Bash thì tôi không có được mức độ này; tôi cảm thấy đây là một đẳng cấp hoàn toàn khác
    Quy trình làm việc với REPL cũng thật sự rất tốt, và đồng nghiệp của tôi đã làm một video liên quan: https://www.youtube.com/watch?v=4igO7Qbyj9o
    Ngày nay, ngay cả các hàm, tác vụ ngắn và dự án nhỏ mà trước đây có thể khiến bạn cân nhắc chuyển từ Bash sang Python cũng có thể xử lý bằng Babashka/nbb

  • Trước đây, khi tôi thử viết khoảng vài nghìn dòng Clojure và ClojureScript, vấn đề lớn nhất là phần lớn công cụ có trạng thái lỗi khá lộn xộn
    Python cũng có mặt tương tự, nên nếu ngắt hầu hết chương trình Python bằng Ctrl+C thì sẽ hiện ra stack trace lẫn những thứ không rõ ràng; nhưng với người mới bắt đầu, điều đó khiến việc tiến lên trở nên khó khăn
    Tôi nghĩ ngôn ngữ và hệ sinh thái này chứa nhiều ý tưởng đổi mới và thú vị. Ít nhất cũng đáng đọc các bài viết lịch sử về Clojure và thấm phần lớn bài học từ đó
    Nghe có vẻ dị giáo với mọi người, nhưng tôi nghĩ có một không gian hệ sinh thái nhỏ cho một ngôn ngữ scripting nghiêm túc về hiệu năng và ergonomics khi viết code như Clojure, nhưng không có ngoặc
    Cũng sẽ tốt nếu không có thói quen xử lý nil một cách đặc biệt, nhưng ít nhất ở đó vẫn có chút cơ sở
    Tôi biết (f x y) tốt hơn f(x, y), nhưng vấn đề của tôi gần với chuyện let form gây ra thụt lề hơn. Tôi không nghĩ để đặt tên cho một giá trị thì phải trả đồng thời cả chi phí thụt lề lẫn ngoặc
    Khi đến từ một ngôn ngữ như Python, nơi dùng chính phần thụt lề vốn dĩ sẽ đưa vào code làm thông tin, đôi khi những thứ này chỉ giống như nhiễu

    • Việc let form tạo ra thụt lề giống như một dấu hiệu cho thấy bạn đang dùng let quá nhiều
      Trong phong cách hàm, thường không cần đặt tên cho các đối số trung gian được truyền giữa các hàm
      Thông thường, bạn dùng threading macro ->, ->> để truyền ngầm đối số sang hàm tiếp theo, hoặc định nghĩa chính phép biến đổi thành hàm thuần và đặt ở cấp cao nhất
      Tuy vậy, tôi hiểu là trong một số code tương tác liên ngôn ngữ thì cần rất nhiều let. Đặc biệt là các thư viện Java JWT thay đổi đối số trong chuỗi thủ tục
    • Khi dùng quy trình làm việc với REPL trong Clojure hay Python, có những điều bạn học được từ sai lầm
      Kiểu như debug một hồi lâu rồi mới nhận ra mình chưa reload hoặc chưa khởi tạo lại
      Tôi cảm thấy phần lớn là bạn sẽ thêm điều này vào danh sách cần kiểm tra trong các tình huống “không thể nào như vậy được”. Ví dụ như “hãy thêm debug output để xác nhận thay đổi code của mình có thật sự được gọi không”
      Tất nhiên đây chỉ là lưới an toàn, và chủ yếu là tôi cố tránh những tình huống đó bằng các thói quen làm việc REPL khác
    • Đầu óc tôi thấy khó chịu vì nó có vẻ phải được đọc là (+ clojure clojurescript)
  • Clojure làm đúng rất nhiều thứ, nên tôi rất thích nó
    Một điều làm chậm các đội thực tế khi họ xây dựng công việc web thực tế bằng Clojure, theo tôi, là mong muốn gần như giáo điều về việc ghép vô số thư viện, mỗi thư viện một kiểu, để kết nối mọi thứ lại
    Nếu ngoài cách tiếp cận hiện tại, cộng đồng còn có một web framework được bảo trì tích cực, kèm sẵn pin và nói chung là dùng được, tôi nghĩ Clojure sẽ phổ biến hơn nhiều và dễ dùng hơn nhiều. Tôi tự hỏi Biff có phải là thứ đó không
    Sẽ tốt nếu có một con đường thay thế cho những người thích ngôn ngữ này nhưng không thích cách tự tay lắp ráp một con quái vật
    Cũng có phần là do tôi đã quen với Ruby on Rails

    • Với nhiều người, sức hấp dẫn của Clojure nằm ở việc không buộc những thứ không cần thiết lại với nhau
      Như bài nói chuyện nổi tiếng của Rich Hickey, cách tiếp cận là đừng complect, hãy compose: (https://github.com/matthiasn/talk-transcripts/blob/master/Hi...)
    • Biff rất gần với kiểu kèm sẵn pin, nhưng một vài mặc định của nó hơi khác dòng chính. Vì dùng XTDB thay vì SQL, và dùng HTMX/Hyperscript, người mới vẫn có thể thấy khó
      Học Clojure, cơ sở dữ liệu đồ thị, và trong một số trường hợp cả HTMX nữa là khá nhiều. Dù vậy, nhiều phần cấu hình đã được làm sẵn, xác thực được chăm chút và dễ dùng, các file cấu hình máy chủ cũng được chú thích tốt
      Nó còn có script triển khai để thiết lập server Linux và SSH vào production REPL. Nếu muốn dùng XTDB, cách Biff thiết lập kiểm chứng tài liệu thật sự rất hay
      Cá nhân tôi thích hướng này hơn các ứng dụng chạy bằng ClojureScript. Có nhiều wrapper ClojureScript bọc React, đến mức gần như thành meme, nhưng với tư cách một lập trình viên React, tôi chưa thấy cái nào trong số đó dễ hơn React
      Ngược lại, chúng có cảm giác phức tạp và không vừa tay. Trong khi đó, HTMX/Hyperscript lại rất hợp với Clojure vì cú pháp HTML chỉ là các mảng và object dễ thao tác
      Lần đầu tiên câu châm ngôn “code là dữ liệu” mà những người yêu Clojure hay lặp lại thật sự có cảm giác như thật
    • Như đã viết ở trên, bạn nên xem thử Luminus hoặc Kit
    • Trong những thứ tôi đã dùng, Biff là thứ tôi thích nhất
  • Trước đây tôi đã vài lần thử dùng OCaml một chút, nhưng không thích hệ thống kiểu quá nghiêm ngặt của nó
    Tôi tốn nhiều thời gian để làm hài lòng trình biên dịch hơn là viết code. Trong Clojure, Common Lisp và C, tôi có nhiều tự do hơn để uốn trình biên dịch hoặc hệ thống kiểu theo hướng mình muốn
    Tất nhiên cái gì cũng có ưu và nhược điểm, nhưng khi viết code tôi không muốn bị cản trở. Có thể đó chỉ là phong cách của tôi, nhưng tôi đã gặp nhiều người nghĩ giống vậy
    Tôi tin rằng hệ thống kiểu tĩnh là vấn đề sở thích, còn phe đối lập thì nghĩ khác. Dù vậy, có những phe đối lập nhau cũng tốt vì hai bên học được nhiều từ nhau
    Rich Hickey đã nhiều lần nói rằng vì Clojure là ngôn ngữ host, nên khi cần có thể đi xuống Java hoặc JavaScript cũng không sao
    Cá nhân tôi xem đây là một trong những tính năng mạnh nhất của hệ sinh thái Clojure. Vì nó thực dụng hơn nhiều
    Tôi đã thấy nhiều nỗ lực tái triển khai lặp đi lặp lại cùng một thứ bằng ngôn ngữ mình thích, chỉ vì không muốn đụng tới “thư viện viết bằng thứ ngôn ngữ bẩn thỉu khác kia”. Lý do thì đủ loại: chậm, không an toàn, không linh hoạt, v.v.
    Chuyện này từng và vẫn thường xảy ra trong Common Lisp, cũng như trong cộng đồng Rust

    • Kiểm tra kiểu thực sự là vấn đề sở thích. Cá nhân tôi khá thích việc ngôn ngữ ngăn được các lỗi vặt, nên tôi đưa khá nhiều khai báo kiểu vào code Common Lisp
      SBCL bảo đảm các khai báo đó hết mức có thể, và có lẽ đã giúp tôi tránh được vài phút đau đầu trong mỗi dự án
      Và CL rất thực dụng, chẳng hạn như chẳng ai bận tâm chuyện woo dựa trên thư viện C
    • Khi dẫn dắt nhóm độ tin cậy cao ở Big Tech, tôi đã muốn đưa kiểu tĩnh nghiêm ngặt vào mọi nơi ngay từ hôm qua
      Các vấn đề vận hành đều liên quan đến những lỗi nhỏ và tinh vi. Ví dụ như việc nâng cấp runtime làm thay đổi thứ tự key trong JSON, khiến các client cũ đang tự parse JSON thủ công bị hỏng; hoặc một thư viện nằm sâu trong stack bắt đầu trả mã HTTP dưới dạng số nguyên thay vì chuỗi, làm hỏng phần parse lỗi
      Ở quy mô vận hành đó, chỉ một tỷ lệ nhỏ khách hàng bị ảnh hưởng cũng dẫn tới hàng trăm báo cáo sự cố, nên sự cố nào cũng là chuyện lớn
      Hiện tôi làm ở một startup nhỏ thì hoàn toàn khác. Tôi chọn ngôn ngữ tĩnh vì đó là hướng thu hút sự chú ý và nhân lực, nhưng tôi nhớ những ngày làm với ngôn ngữ động
      Vì phát hành nhanh, chất lượng code thực sự trở nên tệ. Do thiếu thời gian, thay vì đối phó với hệ thống kiểu và refactor sạch sẽ, chúng tôi sao chép nhiều cấu trúc object gần giống nhau rồi dùng rải rác khắp nơi
      Vì hình dạng kiểu khiến việc tổng quát hóa trở nên rắc rối, nên thay vì tách chức năng ra để tham chiếu ở nhiều nơi, chúng tôi copy/paste cùng một logic vào 10 chỗ
      Tôi nghĩ tùy miền vấn đề mà lời giải phù hợp sẽ khác nhau. Nếu bạn bị gọi dậy lúc nửa đêm vì các lỗi tinh vi, nhiều khả năng kiểu tĩnh nghiêm ngặt là lựa chọn đúng
      Nếu bạn cần lặp nhanh và vấn đề có thể giải quyết bằng một email hoặc một tin nhắn Slack, kiểu động có thể tốt hơn
      Bí quyết là đừng tích lũy quá nhiều nợ trong mô hình động, để khi lớn lên và cần chuyển sang mô hình tĩnh thì vẫn còn xoay xở được
      Đáng tiếc là các ngôn ngữ có nhiều fan cuồng dường như rất dễ trượt sang thái độ “tôi không muốn dùng thư viện của ngôn ngữ khác”
  • Clojure cho đến nay là ngôn ngữ tôi thích nhất và cảm thấy tự nhiên nhất
    Tuy vậy, có hai thứ tôi thực sự nhớ từ các ngôn ngữ khác: thông báo lỗi dễ hiểu và type hint
    Ở công ty, tôi từng phải refactor một codebase lớn và việc đó rất đau đớn. Rất khó biết hàm nào sẽ ném exception hay chỉ trả về nil, và cũng khó biết một hàm cốt lõi sẽ trả về vector, sequence hay một collection khác
    Có các dự án cố giải quyết việc này như spec, malli, typed clojure, nhưng tôi không cảm thấy chúng là phương án thay thế gần với kiểu trong Python hay TypeScript

    • Có thể là vì tôi đã quen với các ngôn ngữ hiện đại có những tính năng này, hoặc vì các ngôn ngữ không có chúng đang bổ sung về sau giống Python/TypeScript, nhưng tôi tò mò làm sao mọi người chịu được điều đó
      Một ngôn ngữ không thể cho biết cái gì đi vào hàm và cái gì đi ra khỏi hàm thì với tôi gần như không còn giá trị trong các codebase lớn hơn vài file
      Nhìn vào những gì code hiện tại có vẻ có thể làm với một object rồi cố suy luận kiểu của nó là tự chuốc khổ vào thân
  • Nếu mới tiếp cận Clojure, bạn nên xem hướng dẫn tương tác này: https://tryclojure.org

    • https://4clojure.oxal.org/
      Đây là một bộ bài học tương tác tốt hơn, đi từ mức dễ đến trung bình rồi khó
  • Clojure rất vui

    • Điều này bị đánh giá thấp. Nghe có thể không chuyên nghiệp, nhưng niềm vui cũng là lý do Basecamp và Ruby on Rails được tạo ra bằng Ruby
      Rails đã thống trị phát triển web trong thập niên 2010, và rất nhiều startup cực kỳ thành công đã được xây dựng trên nó
      Nhiều người chế giễu rằng các kỹ sư đang “chơi đồ chơi”, nhưng phần lớn những thứ tốt đẹp chúng ta có hôm nay từng có lúc chỉ là đồ chơi. Linux cũng là một ví dụ hay
    • Cách diễn đạt này nắm bắt hoàn hảo cảm giác đó. Trước đây tôi cũng từng viết về cảm xúc ấy [1]
      Điểm khó của một ngôn ngữ rất “vui” là bạn bắt đầu giả định rằng mình có thể giải quyết mọi thứ bằng ngôn ngữ đó
      Cuối cùng bạn viết rất nhiều code, để rồi sau này nhìn lại có khi không viết code mới là một giải pháp hoàn toàn ổn
      [1] https://franz.hamburg/writing/clojure-makes-happy.html