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.
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
,protected
và private
. 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