0

Tại sao khi mình dạy OOP, mình chọn dạy bằng Ruby chứ không phải Python?

Xin chào các bạn.

Lời nói đầu

Dạo gần đây, công việc của mình bắt đầu bao gồm cả việc đào tạo cho các bạn intern. Đặc điểm các bạn intern mà mình nhận là du học sinh của các trường tiếng Nhật, trường chuyên môn về IT ở Tokyo, nền tảng kiến thức và kỹ năng lập trình hầu như phải đào tạo từ đầu. Với các bạn này, mình lại thêm 1 phần khó hơn khi giới hạn thời gian đào tạo cho các bạn ấy chỉ có 3 tháng. Vì vậy, cần tìm 1 cách nào đó dạy các bạn ấy căn bản về lập trình, đặc biệt là Lập trình Hướng Đối Tượng trong vòng 2 tháng và 1 tháng còn lại cho làm project... Và vì lý do cần nhanh nên chắc chắn mấy hàng khó như Java và C# sẽ không thể lựa chọn được lần này(Hồi sinh viên thì dù OOP là môn học năm 3, tức trước khi học OOP mình cũng có 1 nền tảng về lập trình nếu học nghiêm túc, mà Java mình còn toát mồ hôi hột về syntax phải để bạn gánh. Nếu dạy Java luôn cho các bạn hầu như đào tạo từ đầu như trên thì thật sự mất thời gian). Ban đầu, ngôn ngữ mình chọn để đào tạo là Python vì cấu trúc dễ hiểu, dễ dùng và có nhiều bạn trẻ học theo và làm nhanh. Nhưng đến khi làm thật thì mình phát hiện ra 1 điểm trừ của Python, dẫn đến việc chuyển sang Ruby và có bài viết này.

Lời trước khi xuống thân bài

  • Bài viết nhằm so sánh 2 ngôn ngữ 1 cách khách quan. Cái nào cũng có điểm mạnh và điểm chưa mạnh riêng.
  • Mình sẽ cố gắng tuân theo ý trên 1 cách nghiêm túc nhất vì bản thân mình - người viết bài này là 1 Ruby coder và có nguy cơ ý kiến mình sẽ bênh nhiều cho việc sử dụng Khoáng chất thay vì chơi Rắn. Vì vậy mình đã làm Github Profile có thống kê đầy đủ rằng mình đã code nhiều nhất là gì. Như các bạn có thể thấy bên dưới thì phần lớn là Ruby, phần tiếp là Python.

Screenshot 2024-03-13 at 1.08.07.png

Ruby và Python trong việc dạy Lập trình Hướng Đối Tượng

Tổng quan Lập Trình Hướng Đối Tượng(OOP)

Lập trình hướng đối tượng (tiếng Anh: Object-oriented programming - OOP) là một mẫu hình lập trình dựa trên khái niệm "đối tượng", mà trong đó, đối tượng chứa đựng các dữ liệu, trên các trường, thường được gọi là các thuộc tính; và mã nguồn, được tổ chức thành các phương thức.

Mình nêu ngắn gọn từ Wikipedia thế thôi. Bài này coi như mọi người đều nắm được khái niệm về OOP rồi.

Khởi tạo Class

Python

Ở Python, 1 class được khởi tạo như sau:

class Dog:
    pass

Ruby

Với Ruby:

class Dog
end

Nhận xét

Chúng ta có thể thấy về syntax, 2 bên khá giống nhau. Tuy nhiên, Python luôn có đặc trưng không có keyword kết thúc đoạn code, không dấu ;. Muốn tạo 1 class/method rỗng thì Python phải dùng keyword pass. Còn Ruby thì có keyword end để kết thúc 1 đoạn code. Cá nhân mình thì việc này mang tính chặt chẽ hơn, nhất là với việc học OOP.

4 thuộc tính của OOP

Mình xin được tách phần riêng để vừa ôn bài cho các bạn, vừa để chuyển tiếp phần sau. OOP có 4 thuộc tính: Tính Đa Hình, Tính Kế Thừa, Tính Trừu Tượng và Tính Đóng Gói. Chúng ta sẽ lần lượt điểm qua 4 thuộc tính ở các phần sau và xem Ruby và Python đã thể hiện các thuộc tính ấy ra sao.

Tính Kế Thừa

Tính Kế Thừa là việc 1 class này có thể được kế thừa từ 1 class khác nhằm tái sử dụng lại code

Python

1 class ở Python kế thừa từ 1 class khác theo syntax sau:

class Animal:
  def __init__(self, name):
    self.name = name

  def speak(self):
    print("Generic animal sound")

# Example Usage (Base Class)

animal = Animal("Generic Animal")
animal.speak()  # Output: Generic animal sound
class Dog(Animal):
  def __init__(self, name, breed):
    super().__init__(name)  # Call base class constructor
    self.breed = breed

  def speak(self):
    print(f"{self.name} (the {self.breed}) barks!")

# Example Usage (Sub Class)
dog = Dog("Buddy", "Labrador")
dog.speak()  # Output: Buddy (the Labrador) barks!

Ruby

Dưới đây là code Ruby thể hiện tính Kế Thừa

class Animal
  attr_reader :name

  def initialize(name)
    @name = name
  end

  def speak
    puts "Generic animal sound"
  end
end

# Example Usage (Base Class)
animal = Animal.new("Generic Animal")
animal.speak  # Output: Generic animal sound

class Dog < Animal
  attr_reader :breed

  def initialize(name, breed)
    super(name)  # Call base class constructor with arguments
    @breed = breed
  end

  def speak
    puts "#{name} (the #{breed}) barks!"
  end
end

# Example Usage (Sub Class)
dog = Dog.new("Buddy", "Labrador")
dog.speak  # Output: Buddy (the Labrador) barks!

Nhận định

Cả Ruby lẫn Python khi viết theo OOP để thể hiện khá rõ ràng Tính Kế thừa với syntax dễ hiểu.

Tính Đa Hình

Tính Đa Hình là việc các class khác nhau gọi cùng 1 phương thức theo những cách khác nhau

Python

class Animal:
  def make_sound(self):
    print("Generic animal sound")

class Dog(Animal):
  def make_sound(self):
    print("Woof!")

class Cat(Animal):
  def make_sound(self):
    print("Meow!")

def play_sound(animal):
  animal.make_sound()  # Polymorphic call

# Usage
dog = Dog()
cat = Cat()
play_sound(dog)  # Output: Woof!
play_sound(cat)  # Output: Meow!

Ruby

class Animal
  def speak
    puts "Generic animal sound"
  end
end

class Dog < Animal
  def speak
    puts "Woof!"
  end

class Cat < Animal
  def speak
    puts "Meow!"
  end

def play_sound(animal)
  animal.speak  # Polymorphic call
end

# Usage
dog = Dog.new
cat = Cat.new
play_sound(dog)  # Output: Woof!
play_sound(cat)  # Output: Meow!

Nhận định

Ruby và Python đều thể hiện đặc tính này rất rõ ràng và dễ hiểu

Tính Trừu Tượng

Python

Python thể hiện tính trừu tượng thông qua module có sẵn abc

from abc import ABC, abstractmethod   
class Car(ABC):   
    def mileage(self):   
        pass  
  
class Tesla(Car):   
    def mileage(self):   
        print("The mileage is 30kmph")   
class Suzuki(Car):   
    def mileage(self):   
        print("The mileage is 25kmph ")   
class Duster(Car):   
     def mileage(self):   
          print("The mileage is 24kmph ")   
  
class Renault(Car):   
    def mileage(self):   
            print("The mileage is 27kmph ")   
          
# Driver code   
t= Tesla ()   
t.mileage()   
  
r = Renault()   
r.mileage()   
  
s = Suzuki()   
s.mileage()   
d = Duster()   
d.mileage() 

Ruby

Với Ruby, chúng ta sẽ define module

module Car
    def mileage; end
end

class Tesla   
    include Car
    def mileage
        print("The mileage is 30kmph")  
    end
end
class Suzuki
    include Car
    def mileage
        print("The mileage is 25kmph ") 
    end
end   
class Duster
    include Car
    def mileage
          print("The mileage is 24kmph ")   
    end
end     
  
class Renault 
    include Car
    def mileage
            print("The mileage is 27kmph ")   
    end
end     
# Driver code   
t= Tesla.new.mileage  
r = Renault.new.mileage  
s = Suzuki.new.mileage  
d = Duster.new.mileage  

Nhận định

Đây là bước có sự khác biệt. Nếu như Python cho phép đa hình kiểu Đa kế thừa thông qua 1 class ABC(Viết tắt của ABstract Class), thì Ruby lại không. Thay vào đó, Ruby có khái niệm module cho phép Đa kế thừa vẫn thoả mãn tính đa hình.

Tính Đóng Gói

Giữ cái hay nhất ở phần cuối, chúng ta có Tính Đóng Gói :v Đây là cách để 1 class cho phép phương thức nào được truy cập công khai, phương thức nào là chỉ nội bộ trong class hoặc giữa các object cùng class với nhau

Ruby

Ruby thể hiện Tính Đóng Gói thông qua public,protectedprivate. Nếu không có từ khoá nào, mặc định method là public

class Example
  def public_method
  end
  
  protected
  
  def protected_method
  end
  
  private
  
  def private_method
  end
end

Python

Với Python, ta chỉ có mỗi cái prefix _ để nhận diện. _ là protect, __ là private. Còn lại là public.

class Example:
  def public_method:
    pass
  
  def _protected_method:
    pass
   
  def __private_method:
    pass
end

Nhận định

Với syntax của Python, nó không có sự tương đồng về định nghĩa public, protected và private so với các ngôn ngữ khác. Đồng thời việc định nghĩa bằng mỗi các _ như kia khá nhanh, nhưng cũng rất gây khó hiểu. Và đây là lý do chính mình ưa Ruby hơn.

Tổng kết

Với đặc điểm syntax hơi ngắn gọn quá, Tính Đóng Gói gây khó hiểu và về gu thì mình ko thích lắm việc phải gọi 1 module ngoài, với mình thì Python hợp với việc dùng để làm 1 ngôn ngữ hướng thủ tục hơn là 1 ngôn ngữ hướng đối tượng. Và thật sự với tình trạng thực tế mình gặp phải, sau khi chuyển sang dạy bằng Ruby, các em intern/part-time mình hướng dẫn đã nắm OOP ổn hơn, làm các bài tập OOP chuyển từ code Python sang code Ruby tốt hơn.

Lời cuối thì mình xin gửi tặng các bạn link Youtube này:

Trong đó có câu này mình thấy tâm đắc:

Ngôn ngữ nào rồi cũng có trend. Quan trọng là bạn yêu thích nó không và nó còn được cộng đồng phát triển tiếp không. Muốn chạy theo ngôn ngữ hot, hay công nghệ mới,... thực ra cũng chỉ là đu trend. Và mình thì ngoài đi code ra cũng có đầu tư Chứng khoán và chơi Coin đủ để có cảm giác về theo đuổi trend rồi.

Chúc các bạn phát triển sự nghiệp tốt.

Sẵn thì mình mới có kênh donate. Rất mong các bạn ủng hộ mình cafe để sắp tới mình có động lực tham gia MayFest thường niên: https://www.buymeacoffee.com/gryqhon


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.