Những cú sốc của lập trình viên Java khi bắt đầu học Ruby
Tác giả: Nakaide Ngày post: 8/4/2015 Nguồn: https://moneyforward.com/engineers_blog/2015/04/08/to-ruby-from-java/ Người dịch: Phạm Cẩm Anh Tác giả vốn quen thuộc với các ngôn ngữ biên dịch như C/C++/Java nhưng đã bắt đầu làm Ruby (Ruby on Rails) từ khi gia nhập công ty Money Forward. Tác ...
Tác giả: Nakaide
Ngày post: 8/4/2015
Nguồn: https://moneyforward.com/engineers_blog/2015/04/08/to-ruby-from-java/
Người dịch: Phạm Cẩm Anh
Tác giả vốn quen thuộc với các ngôn ngữ biên dịch như C/C++/Java nhưng đã bắt đầu làm Ruby (Ruby on Rails) từ khi gia nhập công ty Money Forward. Tác giả mới làm quen với Ruby on Rails được gần tháng nhưng đã học được rất nhiều thứ. Bài viết này tác giả nói về các cú sốc tác giả gặp phải khi lập trình ngôn ngữ Ruby.
1.Full object
Ruby thật sự là một ngôn ngữ lập trình hướng đối tượng.
Ở các ngôn ngữ hướng đối tượng phổ thông, đối tượng của tất cả các hành động là object và được xử lý với tư cách alà một object. Tuy nhiên, có rất nhiều ngôn ngữ hướng đối tượng vẫn có trường hợp dữ liệu giá trị số chẳng hạn không được xử lý như một object. Ví dụ với Java, có rất nhiều phê bình về sự sử dụng của int (wrapper class của Integer khi được xử lý như 1 object) hay C# phát triển sau đó thì có sự phân biệt về kiểu giá trị, kiểu tham chiếu.
Đây có thể nói là kết quả của việc trade off giữa tính dễ hiểu, tính nhất quán và tính năng/ hiệu suất xử lý.
Ví dụ, biến loop của vòng lặp for thường xuyên thay đổi giá trị. Nếu muốn ưu tiên một yêu cầu đặc biệt là dùng class immutable để hiện thị giá trị (và do đó kiểu số của Ruby là immutable) thì mỗi lần lặp sẽ tạo mới một instance mới của object và như thế hiệu suất sẽ thấp.
Ngoài ra, nhìn từ quan điểm quản lý bộ nhớ thì instance của object nó được quản lý trong heap chứ không phải trong stack (Ngoại trừ các ngoại lệ như biến tự động của C++ ) Với các dữ liệu được quản lý bằng stack thì sẽ tránh được việc lãng phí các tham chiếu địa chỉ. Ngoài ra các ngôn ngữ mới nhất (hệ xử lý) thường thực hiện xử lý thu gom rác (GC) nhưng các dữ liệu ở trong Stack thì không thuộc đối tượng của GC nên sẽ tiết kiệm hơn. Do lịch sử, các tác giả của các ngôn ngữ hướng đối tượng thường có cùng một lựa chọn nên thường ưu tiên sự tiện lợi của tính năng nên ruby cũng là full object.
2.Open class
Trong Ruby, có thể extend các class đã định nghĩa và do đó có thể thay đổi hành vì của class nên được gọi là class mở. Cụ thể, có thể thêm vào các method chưa được nghĩa, định nghĩa lại các method đã định nghĩa (ghi đè). Có thể đến đây bạn sẽ thắc mắc mắc liệu đó có phải là kế thừa và mở rộng class? Câu trả lời là open class không phải là kế thừa mà là trực tiếp mở rộng một class đã có sẵn. Và hành vi đó gọi là monkey patch. Cái tên này khiến tác giả ngạc nhiên như đang nhìn thấy Lupin III.
Khi sử dụng các ngôn ngữ lập trình từ trước đến nay, các lập trình viên nhiều khi muốn thay đổi hay fix bug của các class ở bên trong các thư viện của bên thứ 3, kế thừa class hay thay đổi collator pattern nhưng phần lớn các trường hợp không thể thay đổi dù là nhỏ nhất.
Open class được tạo ra để giải quyết vấn đề này. Có thể tưởng tượng Open class như một trái cấm. Có thể thay đổi định nghĩa class ở chỗ khác. Và cũng không có bằng chứng nào chứng tỏ một định nghĩa class được monkey patch. Ngoài ra, khi một lập trình viên sử dụng class được monkey patch, cũng không cần quan tâm xem nó có đang được monkey patch hay không. Nếu không thử chạy thì sẽ không biết được định nghĩa có bị thay đổi hay không. Vì thế, open class là một vũ khí sắc biến của lập trình viên Ruby.
3. Ghost method
Một lần nữa, cái tên gây sốc được sử dụng. Tác giả đã có kinh nghiệm sau. Tác giả muốn kiểm tra spec của method của code mà tôi đang đang đọc. Tác gỉa đã thử grep source code. Tuy nhiên, tác giả đã không tìm thấy method. Khi làm rõ tên method này thì thấy nó được dùng và hoạt động không có lỗi những không tồn tại ở đâu cả. Phải chăng là bản thân đã grep sai nên đã thử grep lại nhiều lần. Thực tế, có thể gọi ra method chưa được định nghĩa trong ruby. Người không rõ về ruby đều không biết điều này.
Khi thực hiện gọi method trong ruby, nếu đi đến Object kế thừa cuối cùng mà không tìm thấy thì sẽ gọi method_missing(). Với method_missing(), biến thứ nhất để gọi ra là method name, biến thứ 2 khi gọi method là biến của method. Nếu định nghĩa lại method_missing và có xử lý thích hợp cho method name và biến nhận được thì có thể làm được mọi thứ.
Một cảm giác thật ảo diệu. Và chắc rằng có nhiều người cũng chung cảm giác như tác giả. Khi bảo trì hệ thống sẽ gặp tương đổi khó khăn nếu dùng method_missing. Tuy nhiên do có nhiều chức năng nên ruby on rails rất mềm dẻo và đang sử dụng phổ biến kỹ thuật này.
Nếu sử dụng thích hợp, thì đây cũng giống như open class, là một vũ khí lợi hại.
Tóm lại, trên đây đã tổng hợp lại 3 điểm mà tác giả đã sốc khi bắt đầu làm Ruby. Ruby đã vượt qua được những tồn tại của nhiều ngôn ngữ, là một ngôn ngữ rất mềm dẻo, linh hoạt. Tuy rằng tôi mới chỉ bắt đầu tìm hiểu ngôn ngữ này nhưng trong tương lai sẽ tiếp tục cố gắng, khám phá thật nhiều.