Có vấn đề gì khi có sự phụ thuộc giữa các đối tượng của cùng một lớp trong kiến ​​trúc phần mềm lớp không?


12

Xem xét một phần mềm trung bình lớn với kiến ​​trúc lớp n và tiêm phụ thuộc, tôi thoải mái nói rằng một đối tượng thuộc một lớp có thể phụ thuộc vào các đối tượng từ các lớp thấp hơn nhưng không bao giờ phụ thuộc vào các đối tượng từ các lớp cao hơn.

Nhưng tôi không biết phải nghĩ gì về các đối tượng phụ thuộc vào các đối tượng khác cùng lớp.

Ví dụ, giả sử một ứng dụng có ba lớp và một số đối tượng giống như một đối tượng trong ảnh. Rõ ràng phụ thuộc từ trên xuống (mũi tên xanh) là ok, từ dưới lên (mũi tên đỏ) không ổn, nhưng còn phụ thuộc bên trong cùng một lớp (mũi tên màu vàng) thì sao?

nhập mô tả hình ảnh ở đây

Không bao gồm sự phụ thuộc vòng tròn, tôi tò mò về bất kỳ vấn đề nào khác có thể phát sinh và bao nhiêu kiến ​​trúc phân lớp đang bị vi phạm trong trường hợp này.


Nếu bạn không có chu kỳ, trong một lớp nơi bạn có các liên kết horysontal tồn tại sự phân tách thành các lớp phụ chỉ có sự phụ thuộc giữa các lớp
max630

Câu trả lời:


10

Đúng, các đối tượng trong một lớp có thể có các phụ thuộc trực tiếp lẫn nhau, đôi khi thậm chí là các chu kỳ - đó thực sự là yếu tố tạo ra sự khác biệt cốt lõi đối với các phụ thuộc được phép giữa các đối tượng trong các lớp khác nhau, trong đó không cho phép phụ thuộc trực tiếp hoặc chỉ phụ thuộc chặt chẽ phương hướng .

Tuy nhiên, điều đó không có nghĩa là họ nên có sự phụ thuộc như vậy một cách tùy tiện. Nó thực sự phụ thuộc vào những gì các lớp của bạn đại diện, hệ thống lớn như thế nào và trách nhiệm của các bộ phận nên là gì. Lưu ý rằng "kiến trúc phân lớp" là một thuật ngữ mơ hồ, có một sự khác biệt lớn về ý nghĩa thực sự của các loại hệ thống khác nhau.

Ví dụ: giả sử bạn có "hệ thống xếp lớp theo chiều ngang", với lớp cơ sở dữ liệu, lớp doanh nghiệp và lớp giao diện người dùng (UI). Cho phép lớp UI chứa ít nhất vài chục lớp hộp thoại khác nhau.

Người ta có thể chọn một thiết kế trong đó không có lớp hộp thoại nào phụ thuộc trực tiếp vào lớp hộp thoại khác. Người ta có thể chọn một thiết kế trong đó "hộp thoại chính" và "hộp thoại phụ" tồn tại và chỉ có các phụ thuộc trực tiếp từ hộp thoại "chính" đến "phụ". Hoặc người ta có thể thích một thiết kế trong đó bất kỳ lớp UI hiện tại nào cũng có thể sử dụng / tái sử dụng bất kỳ lớp UI nào khác từ cùng một lớp.

Đây là tất cả các lựa chọn thiết kế có thể, có thể ít nhiều hợp lý tùy thuộc vào loại hệ thống bạn đang xây dựng, nhưng không có lựa chọn nào làm cho "lớp" hệ thống của bạn không hợp lệ.


Tiếp tục trên ví dụ UI, pro và nhược điểm của việc có các phụ thuộc bên trong là gì? Tôi có thể thấy rằng nó giúp tái sử dụng dễ dàng hơn và đưa ra các phụ thuộc theo chu kỳ, đây có thể là một vấn đề tùy thuộc vào phương pháp DI được sử dụng. Còn gì nữa không?
bracco23

@ bracco23: những ưu và nhược điểm của việc có phụ thuộc "bên trong" cũng giống như ưu điểm của nhược điểm là có phụ thuộc tùy ý. "Nhược điểm" là chúng làm cho các thành phần khó sử dụng hơn và khó kiểm tra hơn, đặc biệt là cách ly với các thành phần khác. Ưu điểm là, sự phụ thuộc rõ ràng làm cho những thứ đòi hỏi sự gắn kết dễ sử dụng, hiểu, quản lý và kiểm tra hơn.
Doc Brown

14

Tôi thoải mái nói rằng một đối tượng thuộc một lớp có thể phụ thuộc vào các đối tượng từ các lớp thấp hơn

Thành thật mà nói, tôi không nghĩ bạn nên thoải mái với điều đó. Khi xử lý bất cứ thứ gì ngoại trừ một hệ thống tầm thường, tôi muốn đảm bảo tất cả các lớp chỉ phụ thuộc vào sự trừu tượng từ các lớp khác; cả thấp hơn và cao hơn.

Vì vậy, ví dụ, Obj 1không nên phụ thuộc vào Obj 3. Nó nên có một sự phụ thuộc vào ví dụ IObj 3và nên được cho biết việc thực hiện trừu tượng hóa đó là gì để làm việc với thời gian chạy. Việc thực hiện việc kể nên không liên quan đến bất kỳ cấp độ nào vì công việc của nó là lập bản đồ các phụ thuộc đó. Đó có thể là một bộ chứa IoC, mã tùy chỉnh được gọi là ví dụ mainsử dụng DI thuần túy. Hoặc tại một cú đẩy, nó thậm chí có thể là một công cụ định vị dịch vụ. Bất kể, sự phụ thuộc không tồn tại giữa các lớp cho đến khi điều đó cung cấp ánh xạ.

Nhưng tôi không biết phải nghĩ gì về các đối tượng phụ thuộc vào các đối tượng khác cùng lớp.

Tôi cho rằng đây là lần duy nhất bạn nên có sự phụ thuộc trực tiếp. Đó là một phần hoạt động bên trong của lớp đó và có thể thay đổi mà không ảnh hưởng đến các lớp khác. Vì vậy, nó không phải là một khớp nối có hại.


Cảm ơn câu trả lời. Vâng, lớp không nên phơi bày các đối tượng nhưng giao diện, tôi biết điều đó nhưng tôi đã bỏ nó đi vì đơn giản.
bracco23

4

Hãy nhìn vào điều này thực tế

nhập mô tả hình ảnh ở đây

Obj 3bây giờ biết Obj 4tồn tại. Vậy thì sao? Tại sao chúng ta quan tâm?

Dip nói

"Các mô-đun cấp cao không nên phụ thuộc vào các mô-đun cấp thấp. Cả hai nên phụ thuộc vào trừu tượng hóa."

OK, nhưng không phải tất cả các đối tượng trừu tượng?

Dip cũng nói

"Trừu tượng không nên phụ thuộc vào chi tiết. Chi tiết nên phụ thuộc vào trừu tượng."

OK, nhưng nếu đối tượng của tôi được đóng gói đúng cách không ẩn bất kỳ chi tiết nào?

Một số người thích mù quáng khẳng định rằng mọi đối tượng đều cần một giao diện từ khóa. Tôi không phải là một trong số họ. Tôi thực sự muốn mù quáng khẳng định rằng nếu bây giờ bạn sẽ không sử dụng chúng, bạn cần có một kế hoạch để đối phó với việc cần một cái gì đó giống như chúng sau này.

Nếu mã của bạn hoàn toàn có thể tái cấu trúc trên mỗi bản phát hành, bạn chỉ có thể trích xuất các giao diện sau nếu bạn cần chúng. Nếu bạn đã xuất bản mã mà bạn không muốn biên dịch lại và thấy mình muốn nói chuyện qua một giao diện, bạn sẽ cần một kế hoạch.

Obj 3biết Obj 4tồn tại Nhưng có Obj 3biết Obj 4là bê tông không?

Đây là lý do tại sao nó rất tốt để KHÔNG lan rộng newkhắp nơi. Nếu Obj 3không biết Obj 4là cụ thể, có thể là do nó không tạo ra nó, sau đó nếu bạn lẻn vào sau và biến Obj 4thành một lớp trừu tượng Obj 3sẽ không quan tâm.

Nếu bạn có thể làm điều đó thì Obj 4đã hoàn toàn trừu tượng tất cả cùng. Điều duy nhất làm cho một giao diện giữa chúng ngay từ đầu có được bạn là sự đảm bảo rằng ai đó sẽ không vô tình thêm mã mang lại sự Obj 4cụ thể ngay bây giờ. Các nhà xây dựng được bảo vệ có thể giảm thiểu rủi ro đó nhưng điều đó dẫn đến một câu hỏi khác:

Là Obj 3 và Obj 4 trong cùng một gói?

Các đối tượng thường được nhóm theo một cách nào đó (gói, không gian tên, v.v.). Khi được nhóm một cách khôn ngoan sẽ thay đổi nhiều khả năng tác động trong một nhóm hơn là giữa các nhóm.

Tôi thích nhóm theo tính năng. Nếu Obj 3Obj 4ở trong cùng một nhóm và lớp, rất có thể bạn sẽ không xuất bản một bản và không muốn cấu trúc lại nó trong khi chỉ cần thay đổi một bản khác. Điều đó có nghĩa là những đối tượng này ít có khả năng hưởng lợi từ việc có một sự trừu tượng hóa giữa chúng trước khi nó có nhu cầu rõ ràng.

Nếu bạn đang vượt qua một ranh giới nhóm mặc dù đó thực sự là một ý tưởng tốt để cho các đối tượng ở hai bên thay đổi độc lập.

Nó nên đơn giản nhưng thật không may, cả Java và C # đã đưa ra những lựa chọn đáng tiếc làm phức tạp điều này.

Trong C #, truyền thống đặt tên cho mọi giao diện từ khóa bằng Itiền tố. Điều đó buộc khách hàng BIẾT họ đang nói chuyện với một giao diện từ khóa. Điều đó gây rối với kế hoạch tái cấu trúc.

Trong Java, truyền thống sử dụng một mẫu đặt tên tốt hơn: FooImple implements FooTuy nhiên, điều này chỉ giúp ở cấp mã nguồn do Java biên dịch các giao diện từ khóa thành một nhị phân khác. Điều đó có nghĩa là khi bạn tái cấu trúc Footừ các máy khách cụ thể sang các máy khách trừu tượng không cần một ký tự mã đã thay đổi vẫn phải được biên dịch lại.

Đó là những L BUI trong các ngôn ngữ cụ thể này giúp mọi người không thể đưa ra sự trừu tượng hóa chính thức cho đến khi họ thực sự cần nó. Bạn không nói ngôn ngữ nào bạn đang sử dụng nhưng hiểu rằng có một số ngôn ngữ đơn giản là không có những vấn đề này.

Bạn không nói ngôn ngữ nào bạn đang sử dụng vì vậy tôi sẽ thôi thúc bạn phân tích ngôn ngữ và tình huống của bạn một cách cẩn thận trước khi bạn quyết định đó sẽ là giao diện từ khóa ở mọi nơi.

Nguyên tắc YAGNI đóng một vai trò quan trọng ở đây. Nhưng "Làm ơn hãy tự bắn vào chân mình".


0

Ngoài các câu trả lời ở trên, tôi nghĩ nó có thể giúp bạn xem xét nó từ các quan điểm khác nhau.

Ví dụ: từ quan điểm Quy tắc phụ thuộc . DR là một quy tắc được đề xuất bởi Robert C. Martin cho Kiến trúc sạch nổi tiếng của ông .

Nó nói rằng

Các phụ thuộc mã nguồn phải chỉ hướng nội, hướng tới các chính sách cấp cao hơn.

Theo chính sách cấp cao hơn , ông có nghĩa là mức độ trừu tượng cao hơn . Các thành phần rò rỉ trên các chi tiết triển khai, như các giao diện ví dụ hoặc các lớp trừu tượng tương phản với các lớp cụ thể hoặc cấu trúc dữ liệu.

Vấn đề là, quy tắc không bị giới hạn trong sự phụ thuộc giữa các lớp. Nó chỉ chỉ ra sự phụ thuộc giữa các đoạn mã, bất kể vị trí hoặc lớp mà chúng thuộc về.

Vì vậy, không có gì sai khi có sự phụ thuộc giữa các thành phần của cùng một lớp. Tuy nhiên, sự phụ thuộc vẫn có thể được thực hiện để truyền đạt với nguyên tắc phụ thuộc ổn định .

Một quan điểm khác là SRP.

Decoupling là cách của chúng tôi để phá vỡ các phụ thuộc có hại và truyền đạt với một số thực tiễn tốt nhất như đảo ngược phụ thuộc (IoC). Tuy nhiên, những yếu tố chia sẻ lý do thay đổi họ không đưa ra lý do tách rời vì các yếu tố có cùng lý do thay đổi sẽ thay đổi cùng một lúc (rất có thể) và chúng cũng sẽ được triển khai cùng một lúc. Nếu đó là trường hợp giữa Obj3Obj4sau đó, một lần nữa, không có gì sai.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.