2012-03-15 24 views
6

Tôi có hai ví dụ cho kết quả tương tự.Khi khối nào hữu ích hơn các hàm (ruby)?

Với khối:

def self.do_something(object_id) 
    self.with_params(object_id) do |params| 
    some_stuff(params) 
    end 
end 

def self.with_params(object_id, &block) 
    find_object_by_id 
    calculate_params_hash 
    block.call(params_hash) 
end 

và với phương pháp:

def self.do_something(object_id) 
    some_stuff(self.get_params(object_id)) 
end 

def self.get_params(object_id) 
    find_object_by_id 
    calculate_params_hash 
    params_hash 
end 

Giải pháp thứ hai có vẻ đơn giản hơn, nhưng tôi tìm thấy một số tập quán của người đầu tiên trong mã ứng dụng của chúng tôi. Câu hỏi của tôi là: trong đó tình huống đầu tiên được đề nghị? Những ưu và nhược điểm của mỗi loại là gì?

+0

Trong ví dụ của bạn, tôi không tin rằng có lý do để sử dụng đối tượng Proc. Toàn bộ điểm của các đối tượng Proc là làm cho chúng tồn tại trong môi trường từ vựng và chuyển chúng đến các hàm khác làm đối số. –

+0

đã thêm "proc" làm thẻ. –

+0

'some_stuff (params)' làm gì, nó có trả về gì không? – nkm

Trả lời

2

Sự khác biệt chính giữa một khối và chức năng theo ví dụ của bạn là khối chạy trong bối cảnh của các chức năng gọi điện thoại.

Vì vậy, nếu ví dụ của bạn là như sau:

def self.do_something(object_id) 
    x = "boogy on" 
    self.with_params(object_id) do |params| 
    some_stuff(params) 
    puts x 
    end 
end 

Đoạn mã nằm trong khối có thể truy cập vào biến x được định nghĩa bên ngoài khối. Điều này được gọi là đóng cửa. Bạn không thể làm điều này nếu bạn chỉ gọi một hàm theo ví dụ thứ hai của bạn.

Một điều thú vị khác về khối là chúng có thể ảnh hưởng đến luồng điều khiển của hàm bên ngoài.Vì vậy, có thể thực hiện:

def self.do_something(object_id) 
    self.with_params(object_id) do |params| 
    if some_stuff(params) 
     return 
    end 
    end 

    # This wont get printed if some_stuff returns true. 
    puts "porkleworkle" 
end 

Nếu cuộc gọi some_stuff trong khối trả về giá trị thực, khối sẽ trả về. Điều này sẽ trả về khối và ra khỏi phương pháp dosomething. porkleworkle sẽ không nhận được kết quả đầu ra.

Trong ví dụ của bạn, bạn không dựa vào một trong các ví dụ này, vì vậy việc sử dụng các cuộc gọi hàm có thể sạch hơn nhiều.

Tuy nhiên, có rất nhiều trường hợp sử dụng các khối để cho phép bạn tận dụng lợi thế của những điều này là vô giá.

3

Thông thường mọi người sử dụng các khối khi họ muốn chạy một đoạn mã bên trong một đoạn mã khác. Ví dụ:

DB.with_shard_for_user(user_id) do |db| 
    # perform operations on a user's shard 

end # shard is reverted back to original value 

File.new(filename) do |file| 
    # work with file 
end # file is closed automatically 

User.transaction do 
    # run some operations as a single transaction 
end 

Các khối này được đóng trên ngữ cảnh của chúng (chúng nắm bắt các biến từ nơi khối được khai báo và chuyển chúng đến vị trí khi khối được gọi).

Cấu trúc sơ đồ của phương thức chấp nhận một khối.

def transaction 
    open_transaction # pre- part 

    yield if block_given? # run provided code 

    commit_transaction # post- part 
rescue 
    rollback_transaction # handle problems 
end 

Trong ví dụ đầu tiên của bạn, sử dụng một khối có lẽ là phi lý (IMHO). Quá phức tạp không có lý do rõ ràng.

1

Khi bạn gọi with_params(), bạn không chỉ gửi dữ liệu, bạn cũng đang cung cấp một số mã để chạy. Xem nếu khối khác nhau được gửi vào with_params() gọi:

... 
self.with_params(object_id) do |params| 
    some_other_stuff() 
    some_stuff(params) 
end 
... 

và ở một nơi khác:

... 
self.with_params(object_id) do |params| 
    even_more_stuff(params) 
end 
... 

Nếu các khối đều giống nhau hoặc with_params() chỉ là gọi từ một nơi sau đó bạn có thể xem xét loại bỏ các khối.

Tóm lại: sử dụng khối nếu bạn muốn chuyển vào phương thức các bit khác nhau của mã (khối) cũng như dữ liệu: hey with_params, lấy dữ liệu này (object_id) và, nhân tiện, hãy chạy mã này (khối) trong khi bạn ở đó.

BTW bạn đang làm những việc khác nhau trong hai ví dụ: with_params() trả về

some_stuff(params_hash) 

sau khi đánh giá khối. Và get_params() chỉ trả về

params_hash 
1

Một khối hoàn toàn dựa vào mã của bạn, nhưng một hàm có mã riêng.

Vì vậy, nếu mã của bạn thay đổi tình hình theo hoàn cảnh, hãy sử dụng khối. Nếu không, hãy xây dựng một chức năng và sử dụng nó làm hộp chặn.

Các vấn đề liên quan