inicio mail me! sindicaci;ón

Archive for Ruby

Ruby và thú vui “code 1 dòng”

Từ hồi tớ học Ruby, lại bị tiêm nhiễm thêm một thói quen vừa tốt vừa xấu. Đó là khi thực hành giải mấy bài toán vớ vửn đơn giản, tớ toàn bị ám ảnh phải làm sao để code của mình ít dòng, ít chữ cái nhất có thể. Dần dần CodeGolf trở thành chỗ chơi của mình lúc nào không biết.

Thói quen đó xấu, là bởi vì nhiều khi … mất thời gian. Có nhiều bài chỉ mang tính ôn tập lại mấy cái chức năng của Ruby, thì mình lại bỏ ra 1 tiếng đồng hồ vò đầu bứt tai xem có cách nào ngon và ngắn hơn không.

Nhưng từ khi có thói quen đó, thấy đầu óc mình được optimized hẳn. Trước khi làm gì cũng bỏ ra vài trăm mili giây để đánh giá xem có cách nào nhanh hơn không, và nhờ đó mà nhiều khi lại tiết kiệm được thời gian. Quan trọng nhất là nó thay đổi tư duy của mình khi lập trình: đó là có nhiều cách để giải quyết 1 vấn đề, và không có cách nào là ngắn nhất cả, chỉ có cách ngắn nhất tạm thời, hoặc nói chính xác là “cách ngắn hơn”. Kể cả khi tớ tìm được cách để giải 1 bài mà chỉ dùng có 1 dòng code, tớ cũng chả thấy hài lòng: “chắc chắn còn cách cần ít chữ cái hơn”.

Tất nhiên khi lập trình thì có nhiều tiêu chí để nói code của mình đã được “tối ưu hoá” (không kể đến việc phải giải quyết được vấn đề):

- Chạy nhanh nhất.
- Ít dòng code nhất.
- Thuật giải rõ ràng và đẹp.

Gần như không có ai đạt được cả 3 tiêu chí đó 1 lúc cả. Và thường mọi người khi giải quyết vấn đề thường dựa vào tiêu chí thứ nhất và tiêu chí thứ ba nhiều hơn.

Giờ thì tớ muốn nhét thêm cái tiêu chí thứ 2 đó và phương trình của tớ:

code-tối-ưu = nhanh + đẹp + ngắn

Hồi gì học Ruby trên mạng, tớ gặp 1 bài khá đơn giản như sau:

Cho 1 dãy số từ 1 đến 100. In ra lần lượt cho từng số:
- Fizz nếu số đó chia hết cho 3
- Buzz nếu số đó chia hết cho 5
- FizzBuzz nếu số đó chia hết cho 15
- nếu không phải các trường hợp trên thì in ra chính số đang xét.

Bài này có thể gọi là “siêu dễ”. Thế nhưng mà phần lớn dân tốt nghiệp lập trình không giải được bài này (hô hô).

Cách đơn giản nhất là mà phần lớn học viên ở rubylearning.org đưa ra là như sau:


1.upto(100) do |number|
  if number % 15 == 0 then
    puts 'FizzBuzz'
  elsif number % 5 == 0 then
    puts 'Fizz'
  elsif number % 15 == 0 then
    puts 'Buzz'
  else
    puts number
  end
end

Như vậy là 11 dòng code. Có thể gọi đây là bản thô, chưa tinh xảo.

Một học viên khác (Marcos Ricardo) có vẻ đã quen với việc lập trình trong python từ trước, đưa ra lời giải khá là “pythonish” như thế này:


1.upto(100) do |number|
  message = ''
  message << "#{'Fizz' if(number % 3 == 0)}#{'Buzz' if(number % 5 == 0)}"
  puts message.empty? ? number.to_s : message
end

Như vậy là đỡ đi 1 lệnh điều kiện number % 15, vỏn vẹn 5 dòng.

Tớ thích cách này, vì trông nó rất là … nói chung là mã miếc các thứ lằng nhằng trông prồ. Với cả cách sử dụng lồng biểu thức khá là hay. Nhưng liệu mình có làm được cách nào ngắn gọn hơn và hay hơn không nhỉ?

Cùng lúc đó tớ đang học Drupal. Trong Drupal có 1 cái hệ thống xét loại menu item dựa trên thuộc tính khá là hay: sử dụng cờ (flag).

Các thuộc tính của menu item được biểu diễn dưới dạng các hằng, chứa giá trị thập phân tương ứng với các cờ nhị phân. Và mỗi loại menu đều là một tập hợp nhất định của 1 số thuộc tính nhất định. Chỉ cần cộng các cờ nhị phân của các thuộc tính này sẽ xác định được giá trị định nghĩa của mỗi loại menu item.

Áp dụng với bài toán fizzbuzz này, nếu tớ sử dụng 2 cờ là “chia hết cho 3″ và “chia hết cho 5″, thì tớ chỉ cần cộng giá trị của 2 cờ này với nhau sẽ biết được liệu số này có chia hết cho 3, cho 5, cho cả 2 hay không cho số nào cả. Lời giải của tớ cho bài này trong Ruby chỉ có 2 dòng như sau:


a = nil, 'fizz', 'buzz', 'fizzbuzz'
1.upto(100) { |a[0]| puts a[(a[0]%3 == 0 ? 1 : 0) + (a[0]%5 == 0 ? 2 : 0)] }

Dòng đầu tiên tớ định nghĩa “loại” cho các số.
Ở dòng thứ 2, trong quá trình xét từ 1 đến 100, tớ gán luôn số đang xét cho a[0]. Sau đó tớ cộng tổng của 2 cờ a[0]%3 và a[0]%5, và lôi giá trị “loại” của nó ra từ chính mảng a.

Đến lúc này bạn Marcos Ricardo lại có 1 cách nữa, chỉ mất 1 dòng


1.upto(100) {|number| puts "#{'Fizz' if(number % 3 == 0)}#{'Buzz' if(number % 5 == 0)}".empty? ? number.to_s : "#{'Fizz' if(number % 3 == 0)}#{'Buzz' if(number % 5 == 0)}" }

Ngắn thì ngắn thật. Nhưng hơi bị rối mắt. Và mặc dù cho độ ngắn của lời giải này vượt lời giải của tớ, độ “đẹp” và “nhanh” của nó thì không bằng của tớ được.

Đó là bởi vì cách này phải dùng tới 4 lệnh điều kiện, trong khi của tớ chỉ mất có 2. Và nó phạm phải nguyên tắc DRY (Don’t Repeat Yourself - đừng tự lặp lại mình). Lời giải của tớ thì không mắc phải vấn đề như vậy. Nó hoàn toàn không bị lặp lại, và hoàn toàn có thể được mở rộng để đáp ứng được những yêu cầu mới của bài toán nếu có.

Ví dụ như mở rộng thêm điều kiện cho bài toán như sau:

Cho 1 dãy số từ 1 đến 100. In ra lần lượt cho từng số:
- Fizz nếu số đó chia hết cho 3
- Blah nếu số đó chia hết cho 4
- Buzz nếu số đó chia hết cho 5
- FizzBuzz nếu số đó chia hết cho 15
- FizzBlah nếu số đó chia hết cho 12
- BlahBuzz nếu số đó chia hết cho 20
- FizzBuzzBlah nếu số đó chia hết cho 60
- nếu không phải các trường hợp trên thì in ra chính số đang xét.

Giả sử tớ thích dùng cách “thô” (cái cách mà mất những 11 dòng lúc nãy), tớ sẽ phải thêm đến 4 lệnh điều kiện nữa, và độ dài của chương trình khéo phải đến 20 dòng. Và nếu dùng cách “1 dòng” như trên thì chắc phải mất đến 14 câu điều kiện nhồi nhét vào trong 1 dòng đó. Còn nếu dùng cách của tớ? Chỉ mất 2 dòng và 3 câu điều kiện:


a = nil, 'Fizz', 'Buzz', 'FizzBuzz', 'Blah', 'FizzBlah', 'BlahBuzz', 'FizzBuzzBlah'
1.upto(100) { |a[0]| puts a[(a[0]%3 == 0 ? 1 : 0) + (a[0]%5 == 0 ? 2 : 0) + (a[0]%4 == 0 ? 4 : 0)] }

Như vậy có thể coi lời giải của tớ có độ tối ưu hơn so với các lời giải khác cho đến … 1 tuần sau đó, khi tớ khám phá ra bài viết này:
Oh, Go Ahead. Overthink FizzBuzz

Trong đó có lời giải chỉ mất 1 dòng, mà trông vẫn ngắn gọn, chỉ cần 1 lệnh điều kiện:


(1..100).map {|i| srand(1781773465) if (i%15)==1; [i, "Fizz", "Buzz", "FizzBuzz"][rand(4)]}

Hãy nhìn kĩ nhé: srand(1781773465), và tác giả nói tìm ra con số 1781773465 mất 12 tiếng. Để nói thêm về cách làm này, có lẽ cho tớ khất đến một bài viết sau, vì có lẽ nó … quá sáng tạo (đối với tớ) (tất nhiên nếu mở rộng đề bài như tớ nói ở trên thì có lẽ nó hơi bị mất công, nhưng thực sự cách làm này quá sáng tạo và không ai … dám nghĩ đến). Ta sẽ nói đến lời giải này khi tìm hiểu về Pseudorandom number generator (thuật toán mô phỏng tạo số ngẫu nhiên) trong một bài viết sắp tới của tớ nhé ;)

OK, tớ cuốn xuống phần comment của bài viết, và bắt gặp thêm 1 lời giải 1 dòng nữa, và số kí tự còn ngắn hơn lời giải vừa rồi:


puts (1..100).map{|i|(s=(i%3==0?’Fizz’:”)+(i%5==0?’Buzz’:”))==”?i:s}

I’m speechless!! Sao cách giải đơn giản như vậy mà mình không nghĩ ra!! Và lại còn có bác ngồi mất 12 tiếng để tìm ra con số seed cho hàm random nữa chứ. =))

Và còn đây nữa:


1.upto(100){|i|puts"FizzBuzz#{i}"[i%3<1?0:i%5<1?4:8,i%15<1?8:4]}

Nhìn cách này chỉ muốn đập đầu vào tường! Những cách sáng tạo nhất và ngắn gọn nhất lại là những cách dựa trên những kiến thức cơ bản nhất.

Giờ nhìn lại miếng code 2 dòng mình viết trông thật tội. Áp dụng những cái quá phức tạp cho một bài đơn giản, trong khi có những cách cơ bản khác mà vẫn đạt được độ ngắn như thế. Tuy thế nhưng mà cũng rút ra được khá là nhiều bài học quan trọng:

1. Phải nắm vững lí thuyết và thực hành thành thạo trước khi bắt tay vào làm cái gì.

2. Phức tạp hơn chưa chắc đã là tốt hơn.

3. Nên nhìn nhận vấn đề một cách đơn giản, dựa trên những gì mình đã biết và đã học.

Nghĩ lại thì trò “code 1 dòng” này khá là bổ ích, vì nó vắt kiệt bộ não của lập trình viên và thúc đẩy sự sáng tạo, đồng thời cũng khiến cho việc lập trình trở nên thú vị hơn. Tớ tin chắc là còn có nhiều cách ngắn hơn cho bài này, nhưng có lẽ cũng nên biết điểm dừng thôi nhỉ :P. Tổng thời gian tớ dành ra cho bài toán này:

lời giải đơn giản nhất: 3 phút
tham khảo lời giải của người khác: 30 phút
lời giải 2 dòng: 5 phút
tìm kiếm bài viết liên quan: 30 phút
đọc bài viết và comments của bài “Overthink FizzBuzz”: 30 phút
viết bài blog này: 30 phút

Tổng cộng là 2 tiếng 8 phút :o omfg!

Ruby kỷ niệm sinh nhật tròn 15 tuổi

Ruby Programming LanguageYukihiro MatsumotoHic, hôm qua quên béng mất, hôm nay nhìn lại lịch thì đã là 25 mất rồi. Nói chung là các thứ mốc thời gian quan trọng tớ đều toàn bỏ lỡ cả :P

Vào ngày 25/02/1993, Ruby được chính thức … “thụ thai” bởi Yukihiro Matsumoto (tên gọi trên mạng là Matz) nhờ tình yêu mãnh liệt giữa anh và cái máy tính. Nói đúng hơn là anh ấy bắt đầu xây dựng Ruby kể từ ngày đó, và sau 2 năm, đến năm 1995 thì Ruby mới được chính thức ra đời. Có nghĩa là nói 25/02 là ngày sinh nhật của Ruby thì cũng không chính xác, nhưng mặc kệ, dẫu sao thì cũng là 1 ngày đáng nhớ.

Vậy tại sao Matz lại chọn Ruby làm cái tên cho ngôn ngữ của mình tạo ra?

Ruby không phải một cái tên viết tắt. Đơn giản chỉ là vì Ruby chịu nhiều ảnh hưởng từ Perl, và khi hoàn tất ngôn ngữ này, anh đã đùa với một người bạn rằng nên đặt tên thế nào nghe cho nó giống một thứ đá quý nào đó (Perl lúc đầu cũng được đặt tên là Pearl - ngọc trai). Và bạn của anh đã gợi ý cái tên Ruby. Sau này Matz cũng bất ngờ khi phát hiện ra Pearl là viên đá quý tượng trưng cho những người sinh tháng 6, còn Ruby thì tượng trưng cho những người sinh tháng 7. Anh cho rằng cái tên Ruby như thế là phù hợp vì Ruby kế thừa và phát triển nhiều đặc tính từ Perl.

Một số cột mốc quan trọng trong quá trình phát triển Ruby

  • 24/02/1993: Matz bắt tay vào công việc “sáng tạo” ra ngôn ngữ Ruby.
  • Tháng 12/1994: Phiên bản alpha đầu tiên của ngôn ngữ được hoàn tất.
  • 1997: Tài liệu hỗ trợ cho ngôn ngữ Ruby được chuyển sang tiếng Anh
  • Cuối năm 1998: thành lập mailing list ruby-talk cho cộng đồng người sử dụng Ruby ngoài Nhật Bản. Cho đến trước thời điểm này, không có nhiều lập trình viên nước ngoài biết đến Ruby, trong khi Ruby đã khá thành công ở Nhật. Từ đây, cơn bão Ruby dần dần hình thành.
  • 2001: JRuby ra đời, đánh dấu bước tiến mới của Ruby. JRuby là trình dịch Ruby viết bằng Java, và giúp cho việc lập trình kết hợp giữa Ruby và Java trở nên dễ dàng hơn.
  • Tháng 7/2004: Ruby on Rails ra mắt cộng đồng lập trình viên ứng dụng web. Rails là một framework hỗ trợ xây dựng một cách nhanh chóng các ứng dụng web dựa trên nền tảng kiến trúc MVC (Model-View-Controller). Sau này Rails thu hút được rất nhiều sự chú ý từ các web developer nhờ tốc độ phát triển ứng dụng cũng như tính mềm dẻo của framework này, đồng thời cũng là do những đặc tính thú vị của Ruby. Từ đó trở đi, Rails trở nên phổ biến ngang ngửa với PHP, và Ruby nhờ đó cũng được càng nhiều người biết đến.
  • Tháng 5/2006: JRuby hỗ trợ Rails
  • 30/4/2007: IronRuby được Microsoft chính thức công bố. IronRuby là nỗ lực của các lập trình viên nhằm đưa Ruby vào .NET framework của Microsoft.
  • 23/7/2007: Bản pre-alpha của IronRuby ra mắt trước công chúng
  • 25/12/2007: Ruby 1.9 chính thức ra mắt với nhiều tính năng mới (hỗ trợ Unicode tốt hơn, sử dụng YARV .v.v.), tuy nhiên các phiên bản số lẻ thường là phiên bản dành cho cộng đồng phát triển và thử nghiệm. Phải chờ đến phiên bản 2.0 thì lập trình viên mới có thể sẵn sàng tận dụng các tính năng mới mẻ cho sản phẩm của mình.

Sau 15 năm kể từ khi được xây dựng từ những dòng code đầu tiên, Ruby đã có những bước tiến khá xa. Nhiều người vẫn phủ nhận sự thành công của ngôn ngữ này với lí do sau những 15 năm mà Ruby mới tiến tới phiên bản 1.9. Nhiều người khác thì lại trở nên dị ứng với cái tên Ruby vì sự nổi đình nổi đám của nó những năm gần đây. Dân học lập trình Việt Nam thì càng không muốn động tay vào ngôn ngữ có cái tên lạ hoắc này. Nhưng tớ tin là trong 1 thời gian ngắn nữa, Ruby sẽ là cái tên được nhắc đến rất nhiều tại Việt Nam, và sẽ ngày càng có nhiều người học Ruby hơn.

Ruby - có thật sự “Mọi thứ đều là đối tượng”

Hồi tớ mới bắt đầu học Ruby, hầu như quyển sách nào tớ đọc, câu đầu tiên trong định nghĩa về Ruby cũng là “In Ruby, everything is an object”. Và khắp mọi nơi trên net tớ search, ai cũng bảo thế cả. Tớ cũng dần dần tự mình cho thế là đúng.

Cho đến một hôm lôi quyển “Programming Ruby 2nd Edition” ra đọc đến phần Variable, mới biết “Everything is an object” là không hoàn toàn chính xác.

Có 1 thứ không phải là đối tượng…

Chắc bạn cũng có thể đoán ra mang máng rồi. Đó chính là Biến.
Trong Ruby, biến có cách làm việc khác với một số ngôn ngữ khác. Hãy cùng thử ví dụ này nhé:

string = 'aha'
str = string
string[2] = 'o'
puts str
puts string

Bạn thử đoán xem kết quả cho ra màn hình là thế nào? Kết quả là cả 2 biến str và string sẽ đều mang giá trị là ‘aho’.

Nhưng trong đoạn code trên ta chỉ thay đổi biến string, chứ không hề động đến biến str1. Và ta thay đổi đó xảy ra sau khi str được gán giá trị cũ của string. Nếu như biến là đối tượng, thì khi ta gán string = ‘aha’, đối tượng string sinh ra với giá trị ‘aha’. Tương tự gán str = string sẽ tạo thêm ra một đối tượng nữa có giá trị mà string đang mang. Khi thay đổi giá trị của đối tượng string, đối tượng str sẽ không bị vạ lây.

Biến không phải là đối tượng, thì biến là cái chi?

Biến là giá trị tham chiếu. Khi ta gán cho một biến một giá trị mới, một đối tượng mới sẽ được tạo ra trong bộ nhớ, và biến đó sẽ “trỏ” vào đối tượng đó. Tưởng tượng mỗi lần bạn truy vấn giá trị của biến, biến sẽ lại truy vấn giá trị của đối tượng, và trả lại cho bạn giá trị của đối tượng. Vậy có nghĩa là, biến và đối tượng không phải là một.

Còn khi bạn gán cho một biến giá trị của một biến đã có sẵn, điều gì xảy ra? Biến mới sẽ lập tức được tham chiếu vào đối tượng mà biến có sẵn kia “trỏ” tới. Tóm lại, cả 2 biến này “trỏ” tới cùng 1 giá trị giống nhau.

Khi bạn thay đổi (thay đổi thôi nhé, chứ không phải là gán cho giá trị mới) giá trị của một biến, thực chất là bạn thay đổi giá trị của đối tượng gốc. Xin xem hình minh họa sẽ rõ:

01.png

Thế nếu tôi gán cho biến string một giá trị mới, str1 có thay đổi theo không?

Cùng xem đoạn code này nhé:

string = 'aha'
str = string
string = 'oho'
puts str
puts string

Bạn sẽ thấy ngay str1 vẫn “trỏ” đến giá trị ‘aha’, trong khi string thì lại là ‘oho’. Tại sao lại có sự khác biệt này?

Đơn giản là do khi gán string = ‘oho’, ruby nhận ra là string có 1 giá trị mới hoàn toàn (chứ không phải là chỉ thay đổi 1 chữ cái như ở ví dụ trên). Do đó ruby sẽ tạo ra 1 đối tượng mới (oho) để string “trỏ” vào.

02.png

Cách sao chép biến đúng trong Ruby

Để thực sự sao chép giá trị của một biến, thay vì chỉ tham chiếu đến giá trị của biến đó, ta dùng phương thức “dup”. Câu lệnh gán sẽ phải như sau:

str = string.dup

“Not everything is an object”

Tóm lại, Ruby vẫn là một ngôn ngữ thuần túy hướng đối tượng, bởi vì “Although not everything is an object, Everything you manipulate is an object” (Mặc dù không phải cái gì cũng là đối tượng, nhưng trong Ruby tất cả các thứ bạn tác động tới đều là đối tượng).

Giáo trình “Tự học Ruby”

Hị, sau một tuần dịch lấy đà, về cơ bản tớ đã dịch xong 4 chương đầu, nhưng mà còn chưa format lại để post lên trên blog. Tớ sẽ dần dần post lên sau.

Giáo trình của bác Satish này khá hay. Không mất thời gian giải thích lòng vòng, bác ấy đi thẳng luôn vào vấn đề và dùng nhiều code mẫu. Thế nên tớ nghĩ là những bạn mới học lập trình, hoặc mới biết đến Ruby sẽ không gặp nhiều khó khăn cho lắm.

Tuy thế dịch một tài liệu tin học từ tiếng Anh sang tiếng Việt không phải là chuyện đơn giản. Kiến thức tin học lập trình của tớ thì cũng chưa phải là sâu rộng gì, nên chắc sẽ có một số chỗ tớ dịch không chuẩn xác. Ai bắt gặp lỗi nào thì bảo cho tớ biết nhá ;)

Tài liệu tớ dịch được post tại đây:

Tự học Ruby

Tự học Ruby trên Internet

Học gì chứ học lập trình, mà đặc biệt là Ruby, thì không bao giờ phải sợ tốn tiền mua sách. Lí do đơn giản: Có rất nhiều sách điện tử về Ruby được cung cấp miễn phí trên mạng (ý tớ là miễn phí hoàn toàn, chứ không phải hàng pirate đâu nhé ;) ). Hầu hết những sách này được viết bởi những lập trình viên có nhiều kinh nghiệm và lên trình prồ rồi, nên chất lượng sách của họ thì cũng khỏi phải bàn.

Quyển đầu tiên tớ muốn nói đến là quyển “Why’s (Poignant) Guide to Ruby” của _why - một trong những thành viên kì cựu trong cộng đồng Ruby (đấy là tớ nói thế, chứ thật sự tớ chỉ đọc sách của bác này, chứ không biết gì nhiều về bác ấy).

Quyển này khá thú vị và vui nhộn. Tác giả còn vẽ cả truyện tranh chèn vào, các ví dụ không nhất thiết là phải giải thích kĩ lưỡng, nhưng mà người đọc vẫn thấy dễ hiểu. Đọc quyển này thấy khá là có hứng. Bác _why này cũng làm cả trang try ruby! Cũng nhờ trang này mà tớ thấy thích thú với ngôn ngữ Ruby mới này. Bạn nào chưa biết, hoặc mới nghe đến Ruby chứ chưa thử, thì vào try it out đi đã ;) Đảm bảo sẽ thấy thích thú ngay. Bạn cũng có thể download bản mp3 của quyển sách này. Nhưng mà cách này thì tớ chưa thử, mà cũng chả tưởng tượng là ông ấy sẽ đọc code bằng mồm hay là thế nào nữa :P

Quyển thứ hai là quyển “Humble Little Ruby Book” của Jeremy McAnally. Quyển này cũng có thể download free trên mạng nốt, nhưng có thêm một lựa chọn nữa là mua bản in của quyển này (chỉ có tầm 9$, quá rẻ so với những quyển khác).

Quyển này thì tớ chưa có động đến. Nhưng đọc qua mục lục cũng đoán được style của tác giả này khá là dễ đọc và không bị nhàm chán. Chỉ có điều đọc lướt qua tớ phát hiện ra hình như nó viết cho ruby 1.8.5, trong khi bản mới nhất bây giờ là 1.8.6, và sắp tới là 1.9 đến nơi rồi. Tuy nhiên thay đổi giữa version cũ và version mới của một ngôn ngữ không thành vấn đề lắm, miễn là bạn nắm được cái core philosophy của ngôn ngữ này.

Để down quyển này bạn cần đăng ký tài khoản tại InfoQ (trang này tổng hợp tin tức và các bài viết về CNTT và lập trình khá hay!). Hoặc là bạn cũng có thể đọc nó online trên scribd.

Quyển thứ ba, không hẳn là quyển sách, mà là một khóa học free về Ruby trên mạng của bác Satish Talim. Bác này 29 năm làm trong ngành rồi. Khóa học đầu tiên bác ấy mở là vào tháng 8 năm 2005 (nếu tớ không nhầm). Sắp tới từ ngày 7/1/2008 sẽ có khóa học mới, bạn nào không ngại học bằng tiếng Anh thì nhanh tay vào đăng ký khóa học từ bây giờ. Chương trình học và giáo trình thì có cả trên trang của bác này rồi, bạn có thể tham khảo trước. Tớ thì chưa học bác này bao giờ, nên không biết là online course của bác ấy thế nào, nhưng chắc chắn là sẽ có tương tác giữa học sinh và thày giáo. Cái này hay, bởi vì sách bình thường thì chỉ tự đọc tự ngẫm thôi, còn có thày dắt theo thì sẽ đỡ bị mất thì giờ vào những vướng mắc không đâu. Bạn cũng nhớ đọc các bài viết trên blog của trang đó nhé, nhiều bài khá bổ ích.

Tớ cũng vừa đăng ký course của bác này (chờ mãi). Trước đó tớ đã xin phép bác ấy dịch giáo trình của bác sang tiếng Việt, để các bạn mới học lập trình, hoặc mới làm quen với Ruby ở Việt Nam có cơ hội tiến nhanh với Ruby hơn, mà đó cũng là một cách để tớ vừa học vừa ôn. Bác ấy đã nhận lời cho phép, và hiện tại tớ đã dịch xong phần … mục lục. Sẽ dần dần post lên blog này để mọi người theo dõi và góp ý chỉnh sửa :D

Ngoài việc tự học theo sách, hoặc là học theo course như trên, bạn cũng có thể tìm “gia sư” Ruby cho mình. Rất đơn giản, chỉ cần chọn lấy một bác trong list và gửi email cho người ta (bằng tiếng Anh). Mỗi người sẽ có hình thức dẫn dắt khác nhau. Nhưng học cái gì đó mà có người định hướng cho mình thì bao giờ cũng dễ dàng và đỡ tốn thời gian vô ích hơn.

Tất nhiên là để học Ruby hiệu quả thì chỉ có thế chưa đủ. Bạn còn phải subscribe một đống blog về Ruby, lướt các forum .v.v. rất nhiều nữa. Bài viết này tớ chỉ giới thiệu vài nguồn tài liệu Ruby miễn phí trên mạng để bạn có thể khởi đầu với ngôn ngữ khá thú vị và cũng đang “hot” này.