it-swarm-vi.com

Có gì sai với tài liệu tham khảo thông tư?

Tôi đã tham gia vào một cuộc thảo luận lập trình ngày hôm nay khi tôi đưa ra một số tuyên bố về cơ bản giả định rằng các tham chiếu vòng tròn (giữa các mô-đun, các lớp, bất cứ điều gì) nói chung là xấu. Khi tôi đã vượt qua được bình luận của mình, đồng nghiệp của tôi đã hỏi, "có gì sai với các tham chiếu vòng tròn?"

Tôi đã có cảm xúc mạnh mẽ về điều này, nhưng thật khó để tôi có thể diễn đạt bằng lời một cách ngắn gọn và cụ thể. Bất kỳ lời giải thích nào mà tôi có thể đưa ra có xu hướng dựa vào các mục khác mà tôi cũng xem xét các tiên đề ("không thể sử dụng một cách cô lập, vì vậy không thể kiểm tra", "hành vi không xác định/không xác định là trạng thái đột biến trong các đối tượng tham gia", v.v. .), nhưng tôi rất muốn nghe một lý do ngắn gọn về lý do tại sao các tài liệu tham khảo vòng tròn là xấu mà không có những bước nhảy vọt mà bộ não của tôi làm, đã dành nhiều giờ trong nhiều năm để gỡ rối cho họ để hiểu, sửa chữa, và mở rộng các bit khác nhau của mã.

Chỉnh sửa : Tôi không hỏi về các tham chiếu vòng tròn đồng nhất, như các tham chiếu trong danh sách liên kết đôi hoặc con trỏ tới cha mẹ. Câu hỏi này thực sự hỏi về các tham chiếu vòng tròn "phạm vi lớn hơn", như libB gọi libB gọi lại libA. Thay thế 'mô-đun' cho 'lib' nếu bạn muốn. Cảm ơn tất cả các câu trả lời cho đến nay!

167
dash-tom-bang

Có rất nhiều nhiều những điều sai với tham chiếu vòng tròn:

  • Tham chiếu lớp tròn tạo khớp nối cao ; cả hai các lớp phải được biên dịch lại mỗi lần hoặc trong số chúng được thay đổi.

  • Tham chiếu Thông tư Hội ngăn liên kết tĩnh , vì B phụ thuộc vào A nhưng A không thể được lắp ráp cho đến khi B hoàn tất.

  • Tham chiếu đối tượng tròn có thể crash thuật toán đệ quy ngây thơ (chẳng hạn như tuần tự hóa, khách truy cập và máy in đẹp) với tràn ngăn xếp. Các thuật toán tiên tiến hơn sẽ có phát hiện chu kỳ và sẽ chỉ thất bại với thông báo ngoại lệ/lỗi mô tả nhiều hơn.

  • Các tham chiếu đối tượng tròn cũng làm cho việc tiêm phụ thuộc không thể , làm giảm đáng kể khả năng kiểm tra của hệ thống của bạn.

  • Các đối tượng có số lượng tham chiếu vòng tròn rất lớn thường là Các đối tượng của Chúa . Ngay cả khi họ không, họ có xu hướng dẫn đến Mã Spaghetti .

  • Tham chiếu Thông tư (đặc biệt là trong cơ sở dữ liệu, nhưng cũng trong các mô hình miền) ngăn chặn việc sử dụng các ràng buộc không vô hiệu , cuối cùng có thể dẫn đến tham nhũng dữ liệu hoặc ít nhất là không nhất quán.

  • Tham chiếu tròn nói chung chỉ đơn giản là gây nhầm lẫn và làm tăng đáng kể tải nhận thức khi cố gắng hiểu cách thức hoạt động của chương trình.

Xin hãy nghĩ về những đứa trẻ; tránh tham chiếu vòng tròn bất cứ khi nào bạn có thể.

228
Aaronaught

Một tham chiếu tròn là hai lần khớp nối của một tham chiếu không tròn.

Nếu Foo biết về Bar và Bar biết về Foo, bạn có hai điều cần thay đổi (khi có yêu cầu là Foos và Bars không còn biết về nhau nữa). Nếu Foo biết về Bar, nhưng một Bar không biết về Foo, bạn có thể thay đổi Foo mà không cần chạm vào Bar.

Tham chiếu theo chu kỳ cũng có thể gây ra sự cố bootstrapping, ít nhất là trong các môi trường tồn tại trong một thời gian dài (dịch vụ được triển khai, môi trường phát triển dựa trên hình ảnh), trong đó Foo phụ thuộc vào Bar hoạt động để tải, nhưng Bar cũng phụ thuộc vào Foo hoạt động để tải.

22
Frank Shearar

Khi bạn buộc hai bit mã lại với nhau, bạn thực sự có một đoạn mã lớn. Khó khăn trong việc duy trì một chút mã ít nhất là bình phương kích thước của nó, và có thể cao hơn.

Mọi người thường nhìn vào độ phức tạp của lớp đơn (/ hàm/tệp/v.v.) và quên rằng bạn thực sự nên xem xét độ phức tạp của đơn vị tách rời (đóng gói) nhỏ nhất. Có một phụ thuộc vòng tròn làm tăng kích thước của đơn vị đó, có thể là vô hình (cho đến khi bạn bắt đầu cố gắng thay đổi tệp 1 và nhận ra rằng cũng yêu cầu thay đổi trong tệp 2-127).

17
Alex Feinman

Chúng có thể xấu không phải bởi bản thân chúng mà là một chỉ báo về một thiết kế kém có thể. Nếu Foo phụ thuộc vào Bar và Bar phụ thuộc vào Foo, thì thật hợp lý khi đặt câu hỏi tại sao chúng là hai thay vì một FooBar độc đáo.

14
mouviciel

Hmm ... điều đó phụ thuộc vào ý của bạn bởi sự phụ thuộc vòng tròn, bởi vì thực sự có một số phụ thuộc vòng tròn mà tôi nghĩ là rất có lợi.

Hãy xem xét một DOM DOM - thật hợp lý khi mọi nút có một tham chiếu đến cha mẹ của chúng và cho mọi cha mẹ có một danh sách các con của nó. Cấu trúc này là một cây logic, nhưng theo quan điểm của thuật toán thu gom rác hoặc tương tự cấu trúc là hình tròn.

10
Billy ONeal

Giống như vấn đề Gà hoặc Trứng .

Có nhiều trường hợp trong đó tham chiếu vòng tròn là không thể tránh khỏi và hữu ích, nhưng, ví dụ, trong trường hợp sau, nó không hoạt động:

Dự án A phụ thuộc vào dự án B và B phụ thuộc vào A. A cần được biên dịch để được sử dụng trong B yêu cầu B được biên dịch trước A yêu cầu B được biên dịch trước A mà ...

9
Victor Hurdugaci

Mặc dù tôi đồng ý với hầu hết các ý kiến ​​ở đây, tôi muốn đưa ra một trường hợp đặc biệt cho tham chiếu vòng tròn "cha mẹ"/"con".

Một lớp thường cần biết một cái gì đó về lớp cha hoặc lớp sở hữu của nó, có lẽ là hành vi mặc định, tên của tệp dữ liệu đến từ, câu lệnh sql đã chọn cột hoặc vị trí của tệp nhật ký, v.v.

Bạn có thể làm điều này mà không cần tham chiếu vòng tròn bằng cách có một lớp chứa để cái mà trước đây "cha mẹ" bây giờ là anh chị em, nhưng không phải lúc nào cũng có thể xác định lại mã hiện có để làm điều này.

Một cách khác là truyền tất cả dữ liệu mà một đứa trẻ có thể cần trong hàm tạo của nó, cuối cùng chỉ đơn giản là khủng khiếp.

6
James Anderson

Trong thuật ngữ cơ sở dữ liệu, các tham chiếu vòng tròn với các mối quan hệ PK/FK thích hợp làm cho không thể chèn hoặc xóa dữ liệu. Nếu bạn không thể xóa khỏi bảng a trừ khi bản ghi bị xóa khỏi bảng b và bạn không thể xóa khỏi bảng b trừ khi bản ghi bị xóa khỏi bảng A, bạn không thể xóa. Tương tự với chèn. đây là lý do tại sao nhiều cơ sở dữ liệu không cho phép bạn thiết lập cập nhật xếp tầng hoặc xóa nếu có tham chiếu vòng vì tại một số điểm, điều đó trở nên không thể. Có, bạn có thể thiết lập các loại mối quan hệ này với việc PK/Fk được tuyên bố chính thức nhưng sau đó bạn sẽ (100% thời gian theo kinh nghiệm của tôi) có vấn đề về tính toàn vẹn dữ liệu. Đó chỉ là thiết kế tồi.

5
HLGEM

Tôi sẽ đưa câu hỏi này từ quan điểm mô hình hóa.

Miễn là bạn không thêm bất kỳ mối quan hệ nào không thực sự ở đó, bạn sẽ an toàn. Nếu bạn thêm chúng, bạn sẽ nhận được ít tính toàn vẹn hơn trong dữ liệu (vì có sự dư thừa) và mã được liên kết chặt chẽ hơn.

Điều đặc biệt với các tài liệu tham khảo vòng tròn là tôi chưa thấy trường hợp nào thực sự cần thiết ngoại trừ một tài liệu tham khảo tự. Nếu bạn mô hình cây hoặc đồ thị, bạn cần điều đó và nó hoàn toàn ổn vì tự tham chiếu là vô hại theo quan điểm chất lượng mã (không thêm phụ thuộc).

Tôi tin rằng tại thời điểm bạn bắt đầu cần một tham chiếu vô ngã, ngay lập tức bạn nên hỏi liệu bạn không thể mô hình hóa nó dưới dạng biểu đồ (thu gọn nhiều thực thể thành một nút). Có thể có một trường hợp ở giữa nơi bạn tạo một tham chiếu tròn nhưng mô hình hóa nó dưới dạng biểu đồ là không phù hợp nhưng tôi rất nghi ngờ điều đó.

Có một mối nguy hiểm mà mọi người nghĩ rằng họ cần một tài liệu tham khảo vòng tròn nhưng thực tế họ không có. Trường hợp phổ biến nhất là "Vụ án có một không hai". Chẳng hạn, bạn đã có một khách hàng có nhiều địa chỉ mà từ đó một địa chỉ sẽ được đánh dấu là địa chỉ chính. Rất hấp dẫn khi mô hình hóa tình huống này thành hai mối quan hệ riêng biệt has_address is_primary_address_of nhưng nó không đúng Lý do là là địa chỉ chính không phải là mối quan hệ riêng giữa người dùng và địa chỉ mà thay vào đó là một thuộc tính của mối quan hệ có địa chỉ . Tại sao vậy? Bởi vì tên miền của nó được giới hạn trong các địa chỉ của người dùng và không phải tất cả các địa chỉ có. Bạn chọn một trong các liên kết và đánh dấu nó là mạnh nhất (chính).

(Bây giờ sẽ nói về cơ sở dữ liệu) Nhiều người chọn giải pháp hai mối quan hệ vì họ hiểu "chính" là một con trỏ duy nhất và khóa ngoại là một loại con trỏ. Vì vậy, khóa ngoại nên là thứ để sử dụng, phải không? Sai lầm. Khóa ngoại đại diện cho các mối quan hệ nhưng "chính" không phải là mối quan hệ. Đây là một trường hợp suy biến của một đơn đặt hàng trong đó một yếu tố là trên hết và phần còn lại không được đặt hàng. Nếu bạn cần lập mô hình tổng thứ tự, tất nhiên bạn sẽ coi đó là thuộc tính của mối quan hệ vì về cơ bản không có lựa chọn nào khác. Nhưng tại thời điểm bạn thoái hóa nó, có một sự lựa chọn và khá kinh khủng - để mô hình hóa một thứ không phải là mối quan hệ như một mối quan hệ. Vì vậy, ở đây nó đến - sự dư thừa mối quan hệ mà chắc chắn không phải là một cái gì đó để được đánh giá thấp. Yêu cầu về tính duy nhất nên được áp đặt theo một cách khác, ví dụ bằng các chỉ mục một phần duy nhất.

Vì vậy, tôi sẽ không cho phép một tham chiếu vòng tròn xảy ra trừ khi hoàn toàn rõ ràng rằng nó xuất phát từ thứ tôi đang làm người mẫu.

(lưu ý: điều này hơi thiên về thiết kế cơ sở dữ liệu nhưng tôi cá là nó cũng có thể áp dụng được cho các lĩnh vực khác)

4
clime

Tôi sẽ trả lời câu hỏi đó bằng một câu hỏi khác:

Tình huống nào bạn có thể cho tôi khi giữ mô hình tham chiếu vòng tròn là mô hình tốt nhất cho những gì bạn đang cố gắng xây dựng?

Từ kinh nghiệm của tôi, mô hình tốt nhất sẽ không bao giờ liên quan đến các tham chiếu vòng tròn theo cách tôi nghĩ bạn muốn nói. Điều đó đang được nói, có rất nhiều mô hình mà bạn sử dụng tài liệu tham khảo vòng tròn mọi lúc, nó cực kỳ cơ bản. Cha mẹ -> Mối quan hệ con cái, bất kỳ mô hình đồ thị, v.v., nhưng đây là những mô hình nổi tiếng và tôi nghĩ bạn đang đề cập đến một cái gì đó hoàn toàn khác.

2
Joseph

Một số người thu gom rác gặp khó khăn trong việc dọn dẹp chúng, bởi vì mỗi đối tượng đang được người khác tham chiếu.

EDIT: Như đã lưu ý bởi các bình luận bên dưới, điều này chỉ đúng với một cực kỳ nỗ lực ngây thơ tại một công cụ thu gom rác, không phải là một điều mà bạn sẽ gặp trong thực tế.

1
shmuelp

Cấu trúc tham chiếu vòng tròn có vấn đề, không chỉ từ quan điểm thiết kế, mà còn từ quan điểm bắt lỗi.

Xem xét khả năng của một lỗi mã. Bạn chưa đặt lỗi bắt đúng trong cả hai lớp, vì bạn chưa phát triển phương thức của mình cho đến nay hoặc bạn lười biếng. Dù bằng cách nào, bạn không có thông báo lỗi để cho bạn biết những gì đã xảy ra và bạn cần gỡ lỗi nó. Là một nhà thiết kế chương trình giỏi, bạn biết các phương thức nào có liên quan đến các quy trình, vì vậy bạn có thể thu hẹp nó thành các phương thức có liên quan đến quy trình gây ra lỗi.

Với các tham chiếu tròn, vấn đề của bạn đã tăng gấp đôi. Vì các quy trình của bạn bị ràng buộc chặt chẽ, bạn không có cách nào biết được phương thức nào trong đó lớp nào có thể gây ra lỗi, hoặc do lỗi xảy ra, bởi vì một lớp phụ thuộc vào lớp kia phụ thuộc vào lớp kia. Bây giờ bạn phải dành thời gian kiểm tra cả hai lớp kết hợp để tìm ra cái nào thực sự chịu trách nhiệm cho lỗi.

Tất nhiên, việc bắt lỗi thích hợp sẽ giải quyết vấn đề này, nhưng chỉ khi bạn biết khi nào có khả năng xảy ra lỗi. Và nếu bạn đang sử dụng thông báo lỗi chung, bạn vẫn không khá hơn nhiều.

1
Zibbobz

Tham chiếu tròn trong cấu trúc dữ liệu đôi khi là cách tự nhiên để thể hiện một mô hình dữ liệu. Mã hóa khôn ngoan, nó chắc chắn không lý tưởng và có thể (ở một mức độ nào đó) được giải quyết bằng cách tiêm phụ thuộc, đẩy vấn đề từ mã sang dữ liệu.

1
Vatine