2011-11-24 27 views
5

Tôi dường như gặp phải một vài vấn đề về thiết kế và tôi không bao giờ biết những gì là thực sự phù hợp. Một mặt tôi thường nghe rằng tôi nên hạn chế khớp nối và dính vào trách nhiệm duy nhất, nhưng khi tôi làm tôi thường thấy khó khăn để lấy thông tin cho một phần của chương trình khi cần thiết. Đối với dụ,Nguyên tắc Nguyên tắc Tốt nhất

class Singer 
    def initialize(name) 
    @name = name 
    end 
    attr :name 
end 

Sau đó nên Sông là:

class Song 
    def new(singer) 
    @singer = singer 
    end 
end 

hoặc

class Song 
    def new(singer_name) 
    @singer_name = singer_name 
    end 
end 

này sau đó còn ít khớp nối, vì vậy theo nguyên tắc tôi nên sử dụng nó. Nhưng nếu sau này tôi phát hiện ra điều gì đó trong bài hát cần biết thêm về ca sĩ , tôi đang ở trong tình trạng tồi tệ. ví dụ.

class Song 
    ... 
    def play 
    puts "Belting it out by #{@singer.name}, winner of 
    #{@singer.grammy_count} grammies!" 
    end 
end 

Tôi sẽ được sửa chữa nếu tôi đã sử dụng lớp Bài hát sau thay vì trước đây. Nhưng sau đó tôi nghi ngờ ai đó sẽ nhắc nhở tôi về SRP, đơn nguyên tắc trách nhiệm , và đề nghị thay vì:

class SongPlayer 
    def initialize(singer, song) 
     @singer, @song = singer, song 
    end 
    def play 
     puts "Belting it out by #{@singer.name}, winner of 
     #{@singer.grammy_count} grammies!" 
    end 
    end 

Và yea, tôi đoán có ý nghĩa, vì ca sĩ khác có thể làm một bìa của một số ai khác là bài hát, phải không? Nhưng sau đó, nó sẽ thực sự là chính xác cùng một bài hát ? Trong hầu hết các trường hợp của tôi, nó không bao giờ giống "bài hát" vì vậy tôi không bao giờ có rằng loại kịch bản. Vậy SRP có xứng đáng với các lớp phụ mà nó mang đến cho mã số sau đó không?

Đôi khi tôi nghĩ nhiều nguyên tắc OOP, RẮN hoặc cách khác, phát sinh ra các giới hạn của Java và không áp dụng tốt cho Ruby.

Trả lời

6

Coupling nên được tổ chức chống lại một khái niệm, cohesion. Bạn muốn tạo ra sự cân bằng giữa hai người, thay vì chỉ đưa một người đến mức cực đoan. Trong ví dụ của bạn, singer_name dường như thuộc về Singer, vì vậy để duy trì sự gắn kết, bạn nên chuyển đối tượng Singer đến Song, thay vì name.

Nói chung, bạn cần lưu ý rằng các nguyên tắc như vậy chỉ đơn thuần là hướng dẫn đường. Bạn luôn phải áp dụng ý thức chung và hiểu biết duy nhất của bạn về miền vấn đề. Ít khi có trường hợp cắt rõ ràng - Nó thậm chí có thể thay đổi khi ứng dụng của bạn phát triển hoặc khi bạn hiểu miền tốt hơn.

2

Chương trình hướng đối tượng nên mô hình hóa các đối tượng thực tế. Trong cuộc sống một bài hát thuộc về một ca sĩ, không phải tên của ca sĩ và trong các chương trình của bạn, bạn nên mô hình nó theo cách này.

Như @troelskn đã đề cập có khái niệm khớp nối, nhưng cũng có khái niệm về sự gắn kết ... Nguyên tắc rất tuyệt vời, nhưng thông thường nên được ưu tiên.

2

Ruby có lập trình viên hạnh phúc ở cốt lõi của nó.Bạn nên xem xét khả năng đọc mã của bạn và bao nhiêu mã của bạn (hoặc đồng nghiệp của bạn) não, đặc biệt là khi bạn phải trải qua và hiểu nó một lần nữa sau một thời gian dài.

Tôi muốn nói SRP nên được coi là đề xuất chứ không phải là quy tắc. Nếu SongPlayer làm cho việc tìm hiểu những gì đang diễn ra khó khăn hơn, chỉ cần thả SRP và gắn bó với Song#play, nếu nó dễ dàng hơn, bằng mọi cách, hãy sử dụng nó.

Và hãy nhớ, bạn luôn có thể cấu trúc lại. Tôi bắt đầu với Song#play và nếu Song bắt đầu trở nên cồng kềnh với mã có liên quan đến việc chơi, thì tôi sẽ cấu trúc lại nội dung đó thành lớp học SongPlayer.

0

Bạn nên chuyển ca sĩ đến bài hát, đây là cách OOP thực sự. Bởi vì, bạn đang tách mối quan tâm, đó là tốt.

Ví dụ: 'bạn nên nói, đừng hỏi'. Vì vậy, Song luôn luôn nói với Singer để quảng cáo chính nó như thế này:

class Song 
    ... 
    def play 
    # So that, singer will use the template and add the details 
    puts @singer.to_s("Belting it out by #{name}, winner of #{grammy_count} grammies!") 
    end 
end 

Đây là hai xu của tôi.

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