Stop Using Case Statements in Ruby
Đã bao giờ bạn nghĩ mình đã sử dụng hết sức mạnh của OOP hay là bạn đã bỏ lỡ một số tính năng nào đó? Nếu bạn đang viết code và đưa ra các quyết định dựa trên từng loại đối tượng cụ thể thì bạn đang bỏ lỡ một tính năng quan trọng của OOP: polymorphism Checking For Types Đầu tiên tôi sẽ bắt đầu ...
Đã bao giờ bạn nghĩ mình đã sử dụng hết sức mạnh của OOP hay là bạn đã bỏ lỡ một số tính năng nào đó? Nếu bạn đang viết code và đưa ra các quyết định dựa trên từng loại đối tượng cụ thể thì bạn đang bỏ lỡ một tính năng quan trọng của OOP: polymorphism
Checking For Types
Đầu tiên tôi sẽ bắt đầu bằng một ví dụ mà chúng ta không tận dụng tính đa hình. Giả sử chúng ta đang implement “Rock, Paper, Scissors” game. Tôi quyết định có 1 class Game và các class khác cho các loại Rock, Paper, Scissors có trong game. Kiểm tra xem ai là người thắng bằng việc implement method play trong class Game.
class Game def self.play(move1, move2) return :tie if move1 == move2 move1.wins_against?(move2) end end
Và đây là một trong những hành động, các class Paper, Scissors khác implement tương tự.
class Rock def wins_against?(other_move) case other_move when Paper then false when Scissors then true end end end
Bây giờ chúng ta chơi game như sau.
p Game.play(Rock.new, Paper.new) # false
Các implement trên vẫn làm việc được, nhưng chúng ta có thể làm cho nó tốt hơn không?
Polymorphism Instead of Type Checking
Chúng ta có thể sử dụng các nguyên tắc của OOP để thay thế cho các câu lệnh case trong 3 class Rock Paper Scissors.
In Ruby, polymorphism is the ability to send any method calls (also know as messages, in OOP parlance) to any object without having to check the object’s class. This is also known as “duck typing”, but I don’t like that term
Chúng ta sẽ sử dụng method đặc trưng cho lớp cụ thể. Ví dụ class Rock có thể định nghĩa method do_you_beat_rock?
class Rock def wins_against?(other_move) other_move.do_you_beat_rock? end def do_you_beat_paper? false end def do_you_beat_scissors? true end end class Paper def wins_against?(other_move) other_move.do_you_beat_paper? end def do_you_beat_rock? true end def do_you_beat_scissors? false end end class Scissors def wins_against?(other_move) other_move.do_you_scissors_rock? end def do_you_beat_paper? true end def do_you_beat_rock? false end end
Các câu lệnh case statement đã được thay thế bằng 1 method gọi và 2 method định nghĩa.
Conclusion
Trong bài viết này bạn đã học được việc tránh sử dụng case statements cho việc kiểm tra loại class. Thay vào đó là tận dụng lợi ích của tính đa hình trong OOP. Điều này sẽ giúp bạn viết code tốt hơn, có thể được mở rộng bằng cách thêm mã mới thay vì thay đổi mã hiện có. Nhưng không có nghĩa là tôi đang ủng hộ để loại bỏ hoàn toàn case statements, bạn nên coi đây là chú ý trong khi viết code, đảm bảo đó là giải pháp tốt nhất để giải quyết vấn đề.
Bài viết được dịch từ:
https://www.blackbytes.info/2017/04/stop-using-case-statements-in-ruby/