Tôi nghĩ có một lợi ích khác khi sử dụng các phương pháp bên trong là rõ ràng. Hãy nghĩ về nó: một lớp với danh sách các phương thức là một danh sách các phương thức phẳng, không cấu trúc. Nếu bạn quan tâm đến việc tách mối quan tâm và giữ nội dung ở cùng một mức trừu tượng VÀ đoạn mã chỉ được sử dụng ở một nơi, các phương thức bên trong sẽ giúp đỡ trong khi gợi ý mạnh mẽ rằng chúng chỉ được sử dụng trong phương pháp kèm theo.
Giả sử bạn có phương pháp này trong một lớp học:
class Scoring
# other code
def score(dice)
same, rest = split_dice(dice)
set_score = if same.empty?
0
else
die = same.keys.first
case die
when 1
1000
else
100 * die
end
end
set_score + rest.map { |die, count| count * single_die_score(die) }.sum
end
# other code
end
Bây giờ, đó là loại đơn giản chuyển đổi cấu trúc dữ liệu và nhiều hơn nữa mã cấp cao hơn, thêm số điểm xúc xắc hình thành một bộ và những người mà không thuộc về bộ. Nhưng không phải là rất rõ ràng những gì đang xảy ra. Hãy làm cho nó mô tả hơn. Một refactoring đơn giản sau:
class Scoring
# other methods...
def score(dice)
same, rest = split_dice(dice)
set_score = same.empty? ? 0 : get_set_score(same)
set_score + get_rest_score(rest)
end
def get_set_score(dice)
die = dice.keys.first
case die
when 1
1000
else
100 * die
end
end
def get_rest_score(dice)
dice.map { |die, count| count * single_die_score(die) }.sum
end
# other code...
end
Idea của get_set_score() và get_rest_score() là tài liệu bằng cách sử dụng một mô tả (mặc dù không phải là rất tốt trong việc này được pha chế chẳng hạn) những gì những mảnh làm.Nhưng nếu bạn có nhiều phương thức như thế này, mã trong điểm() không dễ làm theo, và nếu bạn cấu trúc lại một trong hai phương pháp bạn có thể cần phải kiểm tra những phương pháp khác sử dụng chúng (ngay cả khi chúng là riêng tư - khác các phương thức của cùng một lớp có thể sử dụng chúng).
Thay vào đó, tôi bắt đầu thích này:
class Scoring
# other code
def score(dice)
def get_set_score(dice)
die = dice.keys.first
case die
when 1
1000
else
100 * die
end
end
def get_rest_score(dice)
dice.map { |die, count| count * single_die_score(die) }.sum
end
same, rest = split_dice(dice)
set_score = same.empty? ? 0 : get_set_score(same)
set_score + get_rest_score(rest)
end
# other code
end
Ở đây, nó phải được rõ ràng hơn rằng get_rest_score() và get_set_score() được gói vào phương pháp để giữ logic của điểm() chính nó trong mức độ trừu tượng tương tự, không có sự can thiệp với băm, vv
Lưu ý rằng về mặt kỹ thuật bạn có thể gọi chấm điểm # get_set_score và chấm điểm # get_rest_score, nhưng trong trường hợp này nó sẽ là phong cách xấu IMO, bởi vì ngữ nghĩa họ là phương pháp chỉ riêng cho điểm số phương pháp đơn lẻ()
Vì vậy, có cấu trúc này bạn luôn có thể đọc toàn bộ việc thực hiện điểm số() mà không tìm kiếm bất kỳ phương pháp nào khác được xác định bên ngoài Điểm số điểm số. Mặc dù tôi không thấy mã Ruby như vậy thường xuyên, tôi nghĩ rằng tôi sẽ chuyển đổi nhiều hơn thành phong cách có cấu trúc này với các phương pháp bên trong.
CHÚ Ý: Một tùy chọn khác không trông sạch sẽ nhưng tránh vấn đề xung đột tên chỉ đơn giản là sử dụng lambdas, đã được xung quanh trong Ruby từ get. Sử dụng ví dụ, nó sẽ biến thành
get_rest_score = -> (dice) do
dice.map { |die, count| count * single_die_score(die) }.sum
end
...
set_score + get_rest_score.call(rest)
Nó isn là như khá - một người nào đó nhìn vào các mã có thể tự hỏi tại sao tất cả những lambdas, trong khi sử dụng phương pháp nội là khá tự tài liệu. Tôi vẫn nghiêng về phía lambdas hơn, vì họ không có vấn đề rò rỉ những tên xung đột tiềm tàng với phạm vi hiện tại.
cộng đồng nhỏ các nhà phát triển ruby ở đây tôi đoán. – zengr
Bạn có biết rằng một khi bạn gọi 'outer_method', ai cũng có thể gọi' inner_method'? –