2011-08-15 24 views
18

Trong nghiên cứu mixins so với tiêm phụ thuộc, tôi thường nghe cụm từ "cách Ruby." Thường thì các nhà phát triển nói điều gì đó dọc theo các dòng của"Cách Ruby" (mixins và lớp mở lại) so với tiêm phụ thuộc

Ruby cho phép bạn mở lại lớp học và xác định lại các phương thức có nghĩa là bạn có thể "chèn" các tham chiếu mới vào mã của bạn tại thời điểm kiểm tra.

(xem # 6 tại http://weblog.jamisbuck.org/2007/7/29/net-ssh-revisited)

Nhưng thử nghiệm không phải là mối quan tâm chính của tôi; mối quan tâm của tôi là lớp tái sử dụng. Tôi muốn các lớp tôi có thể tái sử dụng trong nhiều ứng dụng Rails quy mô doanh nghiệp.

Vậy điều gì đã xảy ra với các lớp học REUSING? Sử dụng mixins và mở lại các lớp học dường như không cung cấp một cách để viết các lớp theo cách mà chúng được tách riêng khỏi các chi tiết ứng dụng cụ thể mà không cần thêm nhiều công việc. Nhưng có lẽ tôi đã sai. Nếu tôi có, ai đó có thể cung cấp liên kết đến một bài viết có chứa mã mẫu giải thích rõ ràng cách thực hiện điều này đúng cách sử dụng mixin và mở lại các lớp học không?

Như một ví dụ, các lớp Foo đây là cùng với các Logger lớp:

class Foo 
    def initialize 
    @logger = new_logger 
    end 

    def new_logger 
    Logger.new 
    end 
end 

Vâng, tôi có thể mở lại Foo và xác định lại new_logger, nhưng tôi chỉ không thể tin rằng đây được coi là một cách tiếp cận tiêu chuẩn thực tế để viết các lớp tái sử dụng có thể sử dụng bởi nhiều ứng dụng Rails.

Trả lời

1

Tôi hoàn toàn đồng ý. Ngôn ngữ động không thay thế cho tiêm phụ thuộc. Và không có gì ngăn bạn viết một cho ngôn ngữ động. Đây là khung tiêm phụ thuộc cho Smalltalk: http://www.squeaksource.com/Seuss.html

+0

Thực ra, các phương pháp xác định lại là sự phục hồi cục bộ của lớp tương tự. Sự chồng chéo giữa Seuss và Classbox là gì? – ewernli

2

Câu trả lời đơn giản là không có gì trong ngôn ngữ Ruby ngăn bạn viết các lớp có thể sử dụng lại được. Cách tiếp cận phổ biến để sử dụng mix-in và mở lại lớp không nhất thiết phải thúc đẩy nó, nhưng ngôn ngữ không thực sự ngăn chặn các cách tiếp cận khác. Hãy nghĩ về "Con đường Ruby" như một tập hợp con của "Những điều Ruby có thể làm". Điều đó nói rằng, tôi biết rằng nó thường là thích hợp hơn để thực thi một quyết định thiết kế với cấu trúc ngôn ngữ, và kiến ​​thức của tôi (mà tôi sẽ cảnh báo bạn là xa hoàn thành về chủ đề) DI hiện không phải là một cốt lõi Ruby-ism . Tuy nhiên, một số Googling đã tìm thấy một số bài viết về chủ đề này, khiến tôi tin rằng có những thư viện được tìm thấy để thêm DI vào Ruby, nếu bạn mong muốn (mặc dù dường như họ nhận được nhiều lời chỉ trích từ nhiều người theo chủ nghĩa Ruby). Các bài viết thông tin bao gồm thesetwothis SO question. Hy vọng rằng sẽ giúp.

+0

Cho đến nay, khung công tác Ruby DI yêu thích của tôi là micon: https://github.com/alexeypetrushin/micon –

9

Thực ra khi tôi đến từ thế giới Java đến thế giới ruby, điều đầu tiên tôi quan tâm là cách họ quản lý các phụ thuộc. Vào thời điểm đó tôi đã sử dụng Google Guice trong tất cả các dự án java và tôi đã thực sự lấy cảm hứng từ thiết kế thông minh và dễ sử dụng. Điều đầu tiên mà tôi đã làm trong ruby ​​là hộp chứa DI rất riêng của tôi có cùng một tập hợp các tính năng như Google Guice - (it is still here on github nhưng nó rất lỗi thời).

Nhưng bây giờ sau 2 năm làm việc với Rails/Ruby, tôi nghĩ rằng DI không cần thiết ở đây. Bài viết tốt về DI trong ruby ​​là http://weblog.jamisbuck.org/2008/11/9/legos-play-doh-and-programming nó thực sự là một bài viết về lý do tại sao DI không cần thiết bởi tác giả của một trong những thùng chứa DI đầu tiên cho ruby. Nó chắc chắn là giá trị đọc.

+1

+1 Điều tuyệt vời! – emboss

5

Cũng chỉ vì chúng tôi có thể mở lại các lớp học trong Ruby không có nghĩa là chúng tôi luôn phải làm, bạn có thể nghĩ đến việc mở lại lớp học như phương pháp cuối cùng. Bạn có một thư viện làm mọi thứ bạn cần ngoại trừ một phương pháp, thay vì bỏ toàn bộ thư viện vá nó và sử dụng fork của bạn, bạn có thể đơn giản mở lại lớp, xác định lại phương thức và bạn đang kinh doanh lại. Đây không phải là điều bạn sẽ làm, nhưng có khả năng làm điều này cực kỳ hữu ích.

Đã nói tất cả điều đó, trong Ruby, chúng tôi có một khái niệm hầu như luôn có thể thay thế tốt cho việc tiêm phụ thuộc - gõ vịt. Vì không có kiểu kiểm tra nào bạn có thể truyền bất kỳ đối tượng nào vào một hàm và miễn là đối tượng có các phương thức mà hàm sẽ mong đợi, mọi thứ sẽ hoạt động tốt.

Chúng ta hãy xem ví dụ của bạn - nó không thực sự là lớp có lợi cho tiêm phụ thuộc, bạn sẽ không viết nó như thế này trong Java, ví dụ, nếu bạn muốn tiêm một số phụ thuộc. Bạn chỉ có thể tiêm thông qua constructor hoặc thông qua getters và setters. Vì vậy, hãy viết lại lớp này theo cách đó:

class Foo 
    def initialize(logger) 
    @logger = logger 
    end 
end 

Tốt hơn chúng ta bây giờ có thể tiêm/vượt qua trong một logger vào lớp Foo của chúng tôi. Hãy thêm một phương pháp mà sẽ sử dụng logger này để chứng minh:

class Foo 
    def initialize(logger) 
    @logger = logger 
    end 

    def do_stuff 
    @logger.info("Stuff") 
    end 
end 

Trong java nếu bạn muốn tạo ra Foo đối tượng với các loại khác nhau của người khai thác gỗ, tất cả những người khai thác gỗ sẽ phải thực hiện cùng một giao diện theo ý nghĩa rất đen (ví dụ public class logger implements Loggable) hoặc ít nhất là các lớp con. Nhưng trong Ruby miễn là đối tượng có phương thức info chấp nhận một chuỗi, bạn có thể chuyển nó vào hàm tạo và Ruby tiếp tục chugging cùng một cách vui vẻ. Hãy chứng minh:

class Logger 
    def info(some_info) 
    end 
end 

class Widget 
    def info(some_widget_info) 
    end 
end 

class Lolcat 
    def info(lol_string) 
    end 
end 

Foo.new(Logger.new).do_stuff 
Foo.new(Widget.new).do_stuff 
Foo.new(Lolcat.new).do_stuff 

Với tất cả 3 của các trường hợp trên của lớp Foo gọi phương thức do_stuff, mọi thứ sẽ hoạt động tốt. Bạn có thể thấy từ ví dụ này tôn trọng các nguyên tắc của thiết kế OO vẫn còn quan trọng, nhưng Ruby có phần ít hạn chế hơn về những gì nó sẽ chấp nhận, miễn là các phương pháp đúng là mọi thứ sẽ ổn.

Tùy thuộc vào cách bạn nhìn vào nó gõ vịt hoặc làm cho phụ thuộc tiêm hoàn toàn không liên quan hoặc làm cho nó mạnh hơn bao giờ hết.

+0

Tuy nhiên, sự phụ thuộc phải được tiêm, bất kể loại vấn đề, vì vậy cá nhân tôi sẽ phải nói rằng tiêm phụ thuộc vẫn có vẻ có liên quan. –

+0

Tôi muốn nói rằng sự đảo ngược phụ thuộc vẫn còn có liên quan, tiêm ít hơn. Rất khó để giải thích mà không tham gia vào một chút nội tâm đầu tiên, nhưng nó là một thực tế là khi bạn mã nhiều hơn và nhiều hơn nữa Ruby và nhận được tốt hơn ở đó nhu cầu của bạn cho tiêm phụ thuộc giảm. Có lẽ đó là bởi vì bạn có thể nhận được cùng một lượng công việc được thực hiện với rất ít mã để các thư viện có xu hướng nhỏ hơn. – skorks

2

Bài viết về cách sử dụng IoC trong Ruby You underestimate the power of IoC

Với mẫu làm việc.

CẬP NHẬT

Link là chết bây giờ, đây là nguồn https://github.com/alexeypetrushin/rubylang/blob/master/draft/you-underestimate-the-power-of-ioc.md

tôi đã sử dụng mà IoC là một phần của khuôn khổ web của tôi, tôi kinda tái tạo Ruby on Rails và nó làm việc, nhưng , nó sẽ không mang lại lợi thế đáng kể so với RoR, có những đặc điểm tương tự. Vì vậy, nó đã trở thành một gánh nặng và tôi bỏ nó, một số chi tiết http://petrush.in/blog/2011/rad-web-framework.

+0

Liên kết đó dường như đã chết: (chỉ muốn chỉ ra nó ngay cả khi chuỗi nếu cũ, bởi vì tôi đã quan tâm đến việc đọc này. – conradkdotcom

+1

@conradk Tôi đã cập nhật liên kết. –

+1

[Here] (https: // web. archive.org/web/20120323152539/http://ruby-lang.info/blog/you-underestimate-the-power-of-ioc-3fh) là phiên bản được lưu trữ của liên kết được đề cập. – wintersolutions

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