07/09/2018, 15:45

Elixir cho dân Ruby - Phần 1

Tôi biết đây sẽ là câu hỏi đầu tiên của bất cứ lập trình viên nào trước khi quyết định dành thời gian học một ngôn ngữ nào đó. Có muôn vàn câu trả lời với nhiều quan điểm trái chiều nhưng tôi nghĩ các bạn đều đồng ý với tôi là mục tiêu tối thượng của lập trình là lựa chọn giải pháp hợp lý để ...

Tôi biết đây sẽ là câu hỏi đầu tiên của bất cứ lập trình viên nào trước khi quyết định dành thời gian học một ngôn ngữ nào đó.

Có muôn vàn câu trả lời với nhiều quan điểm trái chiều nhưng tôi nghĩ các bạn đều đồng ý với tôi là mục tiêu tối thượng của lập trình là lựa chọn giải pháp hợp lý để giải quyết một công việc nào đó.

Tôi viết bài này nhắm đến các bạn độc giả đang phải xử lý các công việc liên quan đến ứng dụng web trên nền tảng Ruby. Vậy chúng ta hãy cùng dành một ít phút để nhìn nhận về vấn đề mà chúng ta đang phải xử lý hàng ngày. Theo tôi thì ứng dụng web bao gồm 2 mảng, backend và frontend, mảng frontend cung cấp giao diện giúp người dùng tương tác và backend đóng vai trò phục vụ các logic của doanh nghiệp đến khách hàng.

Trong suốt 15 năm dưới cái nhãn Web 2.0 thì có hằng hà xa số các công nghệ và chuẩn ra đời để giúp lập trình viên giải quyết 2 mảng trên hiệu quả. Quay ngược thời gian về những năm 2005, cái tên DHH và Rails bắt đầu được biết đến trong làng web như một kẻ nổi loạn, Rails đã thực sự tao ra một cuộc cách mạng giúp đẩy ngôn ngữ Ruby lên hàng chiếu trên so với các ngôn ngữ chủ đạo như PHP hay Java vào thời điểm đó. Trung thành với triết lý CoC (Convention over Configuration) hay Thiên vị các giao ước so với việc cấu hình, Rails thực sự là công cụ giúp prototype nhanh, rút giảm tối đa thời gian phát triển ứng dụng cho doanh nghiệp. Và triết lý Test Driven Development của Ruby tăng chất lượng của code, giảm thiểu regression và là đề tài bôi nhọ PHP và Java mà các lập trình viên Ruby thường hay trao đổi với nhau. Nhưng lưu ý là sự dễ dàng có cái giá của nó, Rails codebase khá là phức tạp và nặng nề, cái chuyện ngốn RAM (vào cái thời RAM trên hosting đắt như vàng) là một bài toán nhiều doanh nghiệp phải cân nhắc vào cái thời đó. Dễ để phát triển nhưng không dễ để quản lý devops, nếu ai làm Ruby lâu thì có lẽ không lạ gì những chiêu như chạy supervisor để theo dõi Unicorn process và tự động giết process và khởi tạo lại nếu process chiếm quá nhiều RAM (nghe như là trò đùa). Một số doanh nghiệp cá cược vào Rails thành công trên thị trường và bắt đầu một cuộc chiến trả nợ và tính toán để bảo trì các hệ thống Ruby để đáp ứng với các yêu cầu gia tăng của khách hàng. Vấn đề scale up dịch vụ luôn luôn là nỗi lo và Ruby/Rails không giải quyết tốt lắm, hầu hết các doanh nghiệp đều phải scale bằng cách thêm vào nhiều server và resource. Còn một cách nữa để cải thiện vấn đề tốc độ là áp dụng threading, tiếc là threading là một vấn đề khá hóc cho các lập trình viên, tuy Rails đã là thread safe nhưng hầu hết các lập trình viên Ruby đều tránh threading vì không có gì bảo đảm codebase sẽ không tạo ra deadlock và debug lỗi thì...vâng, chúc may mắn. Ngoài ra thiết kế của ngôn ngữ Ruby không tuân theo luật immutability (tính không gây đột biến hay hiệu ứng phụ), khiến cho việc lập trình cho thiết kế concurrency khá là khó. Nhưng vào cái thời điểm đó, lập trình viên đắt hơn tiền hosting thì lựa chọn Ruby và Rails vẫn là lựa chọn hợp lý với nhu cầu.

Rồi thời gian trôi, ứng dụng và các trường phái phát triển ứng dụng web cũng tiến hoá theo yêu cầu của frontend và backend. Công nghệ như NodeJS được sử dụng rộng trong giới frontend và backend, khái niệm isomorphic app là đề tài được bàn bạc nhiều, các ứng dụng web không đơn thuần trả về HTML nữa, thay vào đó JSON được sử dụng như định dạng chung chuyển đến các công nghệ lớp frontend như ReactJS, AngularJS, vv. Chưa kể các công nghệ khác như WebSocket, vv. Nhưng Rails thì vẫn dậm chân tại chỗ để các công cụ phát triển khác bắt kịp về tính hiệu quả. Không có lý do gì bạn phải cá cược vào Ruby hay Rails để phát triển ứng dụng mới nữa cả.

Đây là thời điểm theo tôi cộng đồng Ruby nên cởi mở tìm một lối ra cho thời kỳ hậu Ruby. Câu hỏi bây giờ là chọn gì? Tôi cũng không biết, và đây cũng là câu hỏi mà nhiều lập trình viên Ruby trên thế giới đang tìm. Bắt đầu từ một vấn đề là tốc độ, một trong những hướng giải là giải quyết concurrency, đây là vấn đề được giải quyết hiệu quả với trường phái lập trình hướng chức năng (functional programming). Cộng đồng Ruby đang thử nghiệm Scala, Haskell, Clojures, Erlang và Elixir. Riêng tôi thì tôi thích ngôn ngữ Elixir nhất vì nó có cú pháp gần với Ruby hơn các ngôn ngữ kia, cộng thêm với lí do là cộng đồng Ruby Úc đang theo nhiều.

Tham gia hội Elixir tại VN ở đâu?

Hiện thì chưa có một sư phụ nào đứng ra mở trường dạy võ nên Elixir VN tạm thời sống núp dưới bóng của cộng đồng Ruby Vietnam. Tôi mong các bạn đam mê Elixir tham gia vào chat room #elixir của bên Ruby VN chat room http://chat.ruby.org.vn.

Giới thiệu Elixir

Ngôn ngữ Elixir là một ngôn ngữ hướng chức năng (functional programming) được tạo ra bởi kỹ sư José Valim (cũng là core-committer của dự án Rails). Anh dựa trên nền tảng của ngôn ngữ Erlang để phát triển một ngôn ngữ lập trình mới có cú pháp dề dùng và các công cụ kèm theo tiện lợi cho việc tạo gói (ứng dụng mix), test (với ExUnit), hay templating (với EEx), vv.

Ngôn ngữ chạy trên Erlang Virtual Machine với hiệu suất rất cao. Ứng dụng có thể chạy hàng trăm nghìn process chỉ trên cùng một server, và cái giá để tạo một process dường như là không. Nếu process không được dùng đến sẽ chiếm gần như không đáng kể tài nguyên, và thời gian để sống lại thì siêu nhanh. Đấy là bí quyết thành công của nền tảng Erlang, được sử dụng trong các ứng dụng viễn thông nên các bạn có thể yên tâm về mặt tốc độ.

Bên cạnh đấy có rất nhiều các web framework cho ngôn ngữ này. Phoenix chẳng hạn, nếu các bạn xem benchmark thì framework này chỉ thua mỗi framework Gin của Go thôi.

Bí quyết của trường phái lập trình hướng chức năng là tính "immutability", hay tính không bị đột biến. Các ngôn ngữ lập trình hướng đối tượng không thể đảm bảo rằng các dữ liệu không bị hiệu ứng phụ. Các bạn độc giả có thể tìm thêm các bài viết giải thích ưu điểm này trên mạng để hiểu sâu hơn.

Cài đặt

Tôi không muốn đi sâu quá về phần này vì mọi người đều có thể vào trang chủ của Elixir và xem hướng dẫn.

Riêng với môi trường OSX thì gói phần mềm có thể được cài đặt thông qua homebrew dễ dàng:

brew install elixir

Nếu cài đặt không có vấn đề gì thì bạn có thể:

$ elixir --version
Elixir 1.0.5

Cái câu chào thế giới ... lại nữa...

Vâng, như bất cứ ngôn ngữ nào, chúng ta muốn ngôn ngữ in ra màn hình câu chào "Hello world" truyền thống.

Dễ thôi, Elixir cung cấp REPL iex giống như là công cụ irb của Ruby vậy:

Gọi iex và bạn sẽ thấy:

$ iex
Erlang/OTP 18 [erts-7.0.3] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Interactive Elixir (1.0.5) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)>

Gõ vào

IO.puts "Hello world"

bạn sẽ thấy output:

Hello world
:ok

Elixir có module IO và hàm puts để in một String ra màn hình. Tôi sẽ bạn về module trong phần tiếp theo của loạt bài viết.

Để truy cập tài liệu về hàm này, bạn có thể dùng lệnh h:

h IO.puts

Hoặc bạn có thể nhảy vào trang tài liệu trên web.

Nếu các bạn muốn thoát ra khỏi iex thì chỉ cần ấn 2 lần Ctrl-C hoặc gọi hàm System.halt

Lưu trữ vào file

Theo mặc định thì file nguồn của Elixir sẽ có đuôi .ex, chúng ta có thể di chuyển nội dung trên vào một file hello_world.ex và chạy nó với iex:

iex hello_world.ex

Lời kết

Ngôn ngữ Ruby và framework Rails đang ở cái dốc đi xuống. Nhưng không vì thế chúng ta không sử dụng Ruby, nếu vấn đề nào phù hợp thì vẫn nên dùng. Nhưng đồng thời chúng ta không nên ngủ quên, Ruby có vấn đề về tốc độ và các nền tảng khác trên thị trường có thể giúp khắc phục. Một trong số đó là ngôn ngữ Elixir, kết hợp tinh tuý của cú pháp dễ dùng giống Ruby với sự ổn định và tốc độ của Erlang. Đây là một lựa chọn hợp lý mà các bạn độc giả nên dành thời gian học thêm.

Trong phần tiếp theo tôi sẽ giới thiệu cơ bản về modules của ngôn ngữ này.

Xem phần 2

0