Khi tôi đọc mã với nhiều phương pháp rất ngắn, tôi thấy rằng thường mất nhiều thời gian hơn để hiểu cách mọi thứ khớp với nhau. Một số lý do được minh họa độc đáo trong mã ví dụ của bạn.Chúng ta hãy thử phá vỡ nó thành phương pháp nhỏ:
def cart
if user_signed_in?
process_current_user
else
setup_cart
end
end
private
def process_current_user
@user = current_user
if @user.cart.present?
assign_cart_when_user_present
else
assign_cart_when_user_not_present
end
end
def assign_cart_when_user_present
@cart = @user.cart
end
def assign_cart_when_user_not_present
@cart = false
end
def setup_cart
cart_id = session[:cart_id]
if cart_id.present?
assign_cart_when_id_present
else
assign_cart_when_id_present
end
end
def assign_cart_when_id_present
@cart = Cart.find(cart_id.to_i)
end
def assign_cart_when_id_not_present
@cart = false
end
Ngay lập tức có một vài vấn đề lớn:
- Sau khi đọc các phương pháp
cart
Tôi không có ý kiến gì nó có. Đó là một phần vì các giá trị được gán cho các biến mẫu thay vì trả về các giá trị cho phương thức được gọi là cart
.
- Tôi muốn tên của các phương pháp
process_current_user
và setup_cart
để cho người đọc biết họ làm gì. Những cái tên đó không làm điều đó. Họ có lẽ có thể được cải thiện, nhưng họ là tốt nhất tôi có thể nghĩ ra. Vấn đề là không phải lúc nào cũng có thể đưa ra các tên phương thức thông tin.
Tôi muốn thực hiện tất cả các phương thức khác ngoài cart
riêng tư. Điều đó giới thiệu một vấn đề khác. Tôi có đặt tất cả các phương thức riêng vào cuối cùng không - trong trường hợp nào tôi có thể phải di chuyển qua một số phương thức không liên quan để tìm chúng - hoặc tôi có luân phiên giữa các phương thức công cộng và riêng tư thông qua mã? (Tất nhiên, vấn đề này có thể được giảm nhẹ bằng cách giữ các tệp mã nhỏ và sử dụng mixin, giả sử tôi có thể nhớ tệp mã nào làm gì.)
Hãy xem xét điều gì đã xảy ra với số dòng mã. Với nhiều dòng mã hơn, có nhiều cơ hội hơn cho các lỗi. Nó có thể dễ dàng hơn để kiểm tra các phương pháp riêng lẻ, nhưng bây giờ chúng ta cần phải kiểm tra xem nhiều phương thức riêng biệt có hoạt động đúng với nhau hay không.
Bây giờ chúng ta hãy so sánh với phương pháp của bạn tinh chỉnh một chút:
def cart
if user_signed_in?
@user = current_user
@cart = case @user.cart.present?
when true then @user.cart
else false
end
else
cart_id = session[:cart_id]
@cart = case cart_id.present?
when true then Cart.find(cart_id.to_i)
else false
end
end
end
này cho người đọc trong nháy mắt những gì đang xảy ra:
@user
được thiết lập để current_user
nếu người dùng đang ký trong; và
@cart
được chỉ định cho một giá trị phụ thuộc vào việc người dùng có đăng nhập hay không và trong từng trường hợp, cho dù có id hay không.
Tôi không nghĩ rằng việc thử nghiệm một phương pháp có kích thước này khó khăn hơn kiểm tra phân tích mã trước đó của tôi theo các phương thức nhỏ hơn. Trong thực tế, nó có thể được dễ dàng hơn để đảm bảo rằng các bài kiểm tra là toàn diện.
Chúng tôi cũng có thể trở cart
hơn là gán nó vào một biến Ví dụ, và tránh gán một giá trị để @user
nếu nó chỉ cần phải xác định cart
nếu người dùng đang đăng nhập:
def cart
if user_signed_in?
cart = current_user.cart
case cart.present?
when true then cart
else false
end
else
cart_id = session[:cart_id]
case cart_id.present?
when true then Cart.find(cart_id.to_i)
else false
end
end
end
Thật không may, điều này đã được hoãn lại như được dựa vào ý kiến. Nhưng chắc chắn là không. Các phương pháp ngắn hơn luôn tốt hơn. Các lý do thực tế cụ thể được đưa ra ở đây: https://www.cqse.eu/en/blog/the-real-benefits-of-short-methods/ –