Có bao nhiêu là quá nhiều giao diện trên một lớp? [đóng cửa]


28

Tôi có thể coi nó là một mùi mã hoặc thậm chí là một mô hình chống để có một lớp thực hiện 23 giao diện. Nếu nó thực sự là một mô hình chống, bạn sẽ gọi nó là gì? Hay chỉ đơn giản là không tuân theo nguyên tắc trách nhiệm duy nhất?


3
Vâng, đó là nghi vấn một trong hai cách. Nếu lớp có 23 phương thức mà tất cả đều phục vụ một trách nhiệm (không phải tất cả các lớp đều cần rất nhiều phương thức, nhưng điều đó không phải là không thể - đặc biệt nếu hầu hết là các hàm bao tiện lợi ba dòng xung quanh các phương thức khác), thì bạn chỉ có các giao diện chi tiết quá tốt; )

Lớp trong câu hỏi là một loại thực thể và các giao diện chủ yếu là các thuộc tính. Có 113 trong số đó và chỉ có bốn phương pháp.
Jonas Elfström

6
Tôi nghĩ rằng các giao diện về cơ bản được sử dụng để gõ vịt trong các ngôn ngữ được biên dịch tĩnh. Có vấn đề gì vậy? :)
tro999

2
chỉ là một câu hỏi: có phải tất cả 113 thuộc tính được điền cho mỗi phiên bản của thực thể này không? Hay đó là một loại "thực thể chung" được sử dụng trong các bối cảnh khác nhau với chỉ một số thuộc tính được điền?
David

1
Chúng ta hãy quay trở lại với sự hiểu biết khái niệm về những gì tạo thành một "lớp". Một lớp học là một điều duy nhất với trách nhiệm và vai trò được xác định rõ ràng. Bạn có thể định nghĩa đối tượng 23 giao diện của mình theo cách này không? Bạn có thể đăng một câu (không phải Joycean) tóm tắt đầy đủ về lớp học của bạn không? Nếu vậy, 23 giao diện là tốt. Nếu không, thì nó quá lớn, quá phức tạp.
Stephen Gross

Câu trả lời:


36

Hoàng gia: Họ không làm bất cứ điều gì đặc biệt điên rồ nhưng họ có một tỷ danh hiệu và có liên quan đến hầu hết các hoàng gia khác bằng cách nào đó.


:-)))))))))))))
Emilio Garavaglia

Tôi căng thẳngsomehow
Sói

23

Tôi gửi rằng mẫu chống này được đặt tên là Jack of All Trades, hoặc có lẽ là quá nhiều mũ.


2
Làm thế nào về con dao quân đội Thụy Sĩ?
Thất vọngWithFormsDesigner

Có vẻ như thuật ngữ này đã được sử dụng cho các giao diện có quá nhiều phương thức :-) Mặc dù điều đó cũng có ý nghĩa ở đây.
Jalayn

1
@FrustratedWithFormsDesigner Một con dao quân đội Thụy Sĩ sẽ không bao giờ có mùi vị xấu khi có một giao diện có tên IValue chứa 30 thuộc tính trong đó 20 thuộc tính trước từ khóa sửa đổi mới.
Jonas Elfström

3
+1 cho Quá nhiều mũ ... để che giấu đúng vị thần nhiều đầu
Newtopian

1
Một con dao quân đội Thụy Sĩ là một mô hình tái sử dụng. tức là một "lưỡi kiếm" duy nhất có thể thực hiện các phương pháp có thể vì vậy nó có thể là một sự tương tự xấu!
James Anderson

17

Nếu tôi phải đặt tên cho nó, tôi nghĩ tôi sẽ gọi nó là Hydra :

Hydra

Trong thần thoại Hy Lạp, Lernaean Hydra (tiếng Hy Lạp: Λερί α) là một con thú nước chthonic giống như con rắn cổ đại, với những đặc điểm của loài bò sát, (như tên gọi của nó) có nhiều đầu - các nhà thơ đề cập đến nhiều đầu hơn sơn, và với mỗi cái đầu bị cắt, nó lại mọc thêm hai lần nữa - và hơi thở độc đến nỗi độc tính ngay cả dấu vết của cô cũng chết người.

Liên quan đặc biệt là thực tế là nó không chỉ có nhiều đầu, mà còn phát triển ngày càng nhiều trong số chúng và không thể bị giết vì nó. Đó là kinh nghiệm của tôi với những kiểu thiết kế này; Các nhà phát triển cứ tiếp tục gây nhiễu ngày càng nhiều giao diện vào nó cho đến khi nó có quá nhiều màn hình vừa vặn, và sau đó nó trở nên quá cố chấp trong thiết kế của chương trình và giả định rằng việc tách nó ra là một viễn cảnh vô vọng (nếu bạn thử, bạn thực sự sẽ thường kết thúc cần nhiều giao diện hơn để thu hẹp khoảng cách).

Một dấu hiệu ban đầu của sự diệt vong sắp xảy ra do "Hydra" là thường xuyên chuyển giao diện này sang giao diện khác, mà không cần kiểm tra nhiều và thường xuyên đến một mục tiêu vô nghĩa, như trong:

public void CreateWidget(IPartLocator locator, int widgetTypeId)
{
    var partsNeeded = locator.GetPartsForWidget(widgetTypeId);
    return ((IAssembler)locator).BuildWidget(partsNeeded);
}

Rõ ràng là khi được đưa ra khỏi bối cảnh có một cái gì đó đáng nghi về mã này, nhưng khả năng điều này xảy ra sẽ tăng lên khi có nhiều "đầu" hơn, bởi vì các nhà phát triển trực giác biết rằng họ luôn đối phó với cùng một sinh vật.

Chúc may mắn khi thực hiện bất kỳ bảo trì trên một đối tượng thực hiện 23 giao diện. Cơ hội bạn không gây ra thiệt hại tài sản thế chấp trong quá trình là không có gì.


16

Các Thiên Chúa đối tượng nói đến cái tâm; một đối tượng duy nhất biết cách làm MỌI THỨ. Điều này xuất phát từ việc tuân thủ thấp các yêu cầu "gắn kết" của hai phương pháp thiết kế chính; nếu bạn có một đối tượng với 23 giao diện, bạn có một đối tượng biết cách tạo ra 23 thứ khác nhau cho người dùng của nó và 23 thứ khác nhau đó có thể không nằm dọc theo một dòng của một nhiệm vụ hoặc khu vực của hệ thống.

Trong RẮN, trong khi người tạo ra đối tượng này rõ ràng đã cố gắng tuân theo Nguyên tắc phân chia giao diện, họ đã vi phạm quy tắc trước đó; Nguyên tắc trách nhiệm duy nhất. Có một lý do đó là "RẮN"; S luôn đến đầu tiên khi nghĩ về thiết kế, và tất cả các quy tắc khác tuân theo.

Trong GRASP, người tạo ra một lớp như vậy đã bỏ qua quy tắc "Độ gắn kết cao"; GRASP, không giống như RẮN, dạy rằng một đối tượng KHÔNG CÓ trách nhiệm duy nhất, nhưng nhiều nhất nó phải có hai hoặc ba trách nhiệm liên quan rất chặt chẽ.


Tôi không chắc chắn rằng đây là mô hình chống đối tượng của Chúa, vì Chúa không bị hạn chế bởi bất kỳ giao diện nào. Bị hạn chế bởi rất nhiều giao diện có thể làm giảm sức mạnh toàn năng của Chúa. ;) Có lẽ đây là một đối tượng Chimera?
Thất vọngWithFormsDesigner

Chúa có nhiều mặt, và có thể là nhiều điều đối với nhiều người. Nếu chức năng của các giao diện kết hợp làm cho đối tượng "hiểu biết tất cả" thì nó không thực sự ràng buộc Thiên Chúa, phải không?
KeithS

1
Trừ khi tạo ra các giao diện sửa đổi chúng. Sau đó, Chúa có thể phải được thực hiện lại để phù hợp với những thay đổi giao diện.
Thất vọngWithFormsDesigner

3
Thật đau lòng khi bạn nghĩ rằng chính tôi đã tạo ra lớp học.
Jonas Elfström

Việc sử dụng "bạn" là số nhiều bạn, đề cập đến nhóm nhà phát triển của bạn. MỘT SỐ người trong nhóm đó, quá khứ hoặc hiện tại, đã tạo ra lớp này. Tôi sẽ chỉnh sửa, mặc dù.
KeithS

8

23 chỉ là một con số! Trong trường hợp rất có thể, nó đủ cao để báo động. Tuy nhiên, nếu chúng ta hỏi, số phương thức / giao diện cao nhất là bao nhiêu trước khi nó có thể nhận được một thẻ được gọi là "chống mẫu"? Là 5 hay 10 hay 25? Bạn nhận ra rằng con số đó thực sự không phải là một câu trả lời bởi vì nếu 10 là tốt, thì 11 cũng có thể - và sau đó là bất kỳ số nguyên nào sau đó.

Câu hỏi thực sự là về sự phức tạp. Và chúng ta nên chỉ ra rằng mã dài, số phương thức hoặc kích thước lớn của lớp bằng bất kỳ biện pháp nào thực sự KHÔNG phải là định nghĩa về độ phức tạp. Có, mã lớn hơn và lớn hơn (số lượng phương thức lớn hơn) sẽ gây khó khăn cho việc đọc và nắm bắt cho người mới bắt đầu. Nó cũng xử lý các chức năng có khả năng đa dạng, số lượng lớn các trường hợp ngoại lệ và các thuật toán khá phát triển cho các tình huống khác nhau. Điều này không có nghĩa là nó phức tạp - nó chỉ khó tiêu hóa.

Mặt khác, mã kích thước tương đối nhỏ mà người ta có thể hy vọng đọc được trong vài giờ vào và ra - vẫn có thể phức tạp. Đây là khi tôi nghĩ rằng mã là (không cần thiết) phức tạp.

Mọi trí tuệ của thiết kế hướng đối tượng có thể được đưa vào đây để định nghĩa "phức tạp" nhưng tôi sẽ hạn chế ở đây để hiển thị khi "rất nhiều phương thức" là một dấu hiệu của sự phức tạp.

  1. Kiến thức lẫn nhau. (còn gọi là khớp nối) Nhiều khi mọi thứ được viết dưới dạng các lớp, tất cả chúng ta đều nghĩ rằng đó là mã hướng đối tượng "đẹp". Nhưng giả định về lớp khác về cơ bản phá vỡ sự đóng gói thực sự cần thiết. Khi bạn có các phương thức "rò rỉ" chi tiết sâu về trạng thái bên trong của các thuật toán - và ứng dụng được xây dựng với giả định chính về trạng thái bên trong của lớp phục vụ.

  2. Quá nhiều lần lặp lại (đột nhập) Khi các phương thức có tên tương tự nhưng thực hiện công việc mâu thuẫn - hoặc mâu thuẫn với các tên có chức năng tương tự. Nhiều lần mã phát triển để hỗ trợ các giao diện hơi khác nhau cho các ứng dụng khác nhau.

  3. Quá nhiều vai trò Khi lớp tiếp tục thêm các chức năng phụ và tiếp tục mở rộng hơn khi mọi người thích nó, chỉ để biết rằng lớp thực sự bây giờ là một lớp. Đáng ngạc nhiên là tất cả bắt đầu với chính hãngyêu cầu và không có lớp khác tồn tại để làm điều này. Hãy xem xét điều này, có một Giao dịch lớp, cho biết chi tiết về giao dịch. Có vẻ tốt cho đến nay, bây giờ ai đó yêu cầu chuyển đổi định dạng vào "thời gian giao dịch" (giữa UTC và tương tự), sau này, mọi người thêm quy tắc để kiểm tra xem một số thứ nhất định vào một số ngày nhất định để xác thực các giao dịch không hợp lệ. - Tôi sẽ không viết toàn bộ câu chuyện nhưng cuối cùng, lớp giao dịch xây dựng toàn bộ lịch trong đó và sau đó mọi người bắt đầu sử dụng phần "chỉ lịch" của nó! Điều này rất phức tạp (để tưởng tượng) tại sao tôi sẽ khởi tạo "lớp giao dịch" để có chức năng mà "lịch" sẽ cung cấp cho tôi!

  4. (Trong) tính nhất quán của API Khi tôi làm book_a_ticket () - Tôi đặt vé! Điều đó rất đơn giản bất kể có bao nhiêu kiểm tra và quy trình để thực hiện. Bây giờ nó trở nên phức tạp khi dòng thời gian bắt đầu ảnh hưởng đến điều này. Thông thường, người ta sẽ cho phép "tìm kiếm" và trạng thái khả dụng / không khả dụng, sau đó để giảm thời gian quay lại, bạn bắt đầu lưu một số gợi ý ngữ cảnh bên trong vé và sau đó tham khảo để đặt vé. Tìm kiếm không phải là chức năng duy nhất - mọi thứ trở nên tồi tệ hơn sau nhiều "chức năng phụ" như vậy. Trong quá trình, ý nghĩa của book_a_ticket () ngụ ý book_that_ticket ()! và điều đó có thể phức tạp không thể tưởng tượng được.

Có thể có nhiều tình huống như vậy bạn sẽ thấy trong một mã rất phát triển và tôi chắc chắn rằng nhiều người có thể thêm các kịch bản, trong đó "rất nhiều phương pháp" chỉ không có ý nghĩa hoặc không làm những gì bạn rõ ràng sẽ nghĩ. Đây là mô hình chống.

Kinh nghiệm cá nhân của tôi là khi các dự án bắt đầu từ dưới lên một cách hợp lý , nhiều thứ đáng lẽ phải có các lớp chính hãng tự mình bị chôn vùi hoặc tệ hơn vẫn bị phân chia giữa các lớp khác nhau và tăng khớp nối. Hầu hết những gì có thể xứng đáng với 10 lớp, nhưng chỉ có 4 lớp, có khả năng nhiều trong số chúng có nhiều mục đích khó hiểu và số lượng lớn các phương thức. Gọi nó là THIÊN CHÚA và DRAGON, đây là BAD.

NHƯNG bạn bắt gặp các lớp RẤT LỚN nhất quán, chúng có 30 phương thức - và vẫn rất SẠCH. Họ có thể tốt.


Lớp trong các câu hỏi có 23 giao diện và chúng có chứa tất cả, 113 thuộc tính công cộng và bốn phương thức. Chỉ một số trong số họ là chỉ đọc. C # có các thuộc tính được triển khai tự động, đó là lý do tại sao tôi khác nhau giữa các phương thức và thuộc tính msdn.microsoft.com/en-us/l
Library / bb384054.aspx

7

Các lớp nên có chính xác số lượng giao diện chính xác; không nhiều không ít.

Nói "quá nhiều" sẽ là không thể nếu không xem liệu tất cả các giao diện đó có phục vụ mục đích hữu ích trong lớp đó hay không. Khai báo rằng một đối tượng thực hiện một giao diện có nghĩa là bạn phải thực hiện các phương thức của nó nếu bạn muốn lớp biên dịch. (Tôi đoán rằng lớp bạn đang xem.) Nếu mọi thứ trong giao diện được triển khai và các triển khai đó làm một cái gì đó liên quan đến các bộ phận của lớp, thật khó để nói rằng việc triển khai không nên ở đó. Trường hợp duy nhất tôi có thể nghĩ về nơi một giao diện đáp ứng các tiêu chí đó sẽ không thuộc về bên ngoài: khi không ai sử dụng nó.

Một số ngôn ngữ cho phép các giao diện được "phân lớp" bằng cách sử dụng một cơ chế như extendstừ khóa của Java và bất cứ ai đã viết nó có thể không biết điều đó. Cũng có thể là tất cả 23 đều đủ xa để tổng hợp chúng không có ý nghĩa.


Tôi đoán câu hỏi này là bất khả tri ngôn ngữ. Mã thực tế là trong C #.
Jonas Elfström

Tôi chưa thực hiện bất kỳ C # nào, nhưng dường như nó hỗ trợ một hình thức kế thừa giao diện tương tự.
Blrfl

Có, một giao diện có thể "kế thừa" các giao diện khác, v.v.
Jonas Elfström

Tôi thấy thú vị khi nhiều cuộc thảo luận tập trung vào những gì các lớp nên làm, hơn là những trường hợp nên làm. Một robot có nhiều cảm biến hình ảnh và âm thanh được gắn vào khung chung nên được mô hình hóa như một thực thể có vị trí và hướng, và có thể nhìn, nghe và liên kết các điểm tham quan và âm thanh. Tất cả logic thực sự đằng sau các chức năng đó có thể thuộc các lớp khác, nhưng bản thân robot nên hỗ trợ các phương thức như "xem có vật thể nào ở phía trước không", "lắng nghe bất kỳ tiếng động nào trong khu vực" hay "xem vật thể phía trước có giống như nó không tạo ra âm thanh được phát hiện. "
supercat

Cũng có thể là một robot cụ thể nên chia nhỏ chức năng của nó thành các hệ thống con theo một cách cụ thể, nhưng ở mức độ mã thực tế sử dụng robot không cần phải biết hoặc quan tâm đến cách phân chia chức năng của một robot cụ thể. Nếu "đôi mắt" và "đôi tai" tiếp xúc với thế giới bên ngoài như những vật thể riêng biệt, nhưng các cảm biến tương ứng nằm trên một nhánh mở rộng chung, mã bên ngoài có thể yêu cầu "đôi tai" lắng nghe âm thanh ở mặt đất cùng lúc với nó yêu cầu "đôi mắt" nhìn phía trên một chướng ngại vật.
supercat

1

Nghe có vẻ như họ có một cặp "getter" / "setter" cho mỗi thuộc tính, như bình thường đối với một "bean" điển hình và đã quảng bá tất cả các phương thức này lên giao diện. Vì vậy, làm thế nào về việc gọi nó là " có đậu ". Hoặc "đầy hơi" của Rabelaisian sau khi ảnh hưởng nổi tiếng của quá nhiều đậu.


Nó ở C # và nó có Thuộc tính được triển khai tự động. 23 giao diện này, tất cả trong tất cả, chứa 113 thuộc tính như vậy.
Jonas Elfström

1

Số lượng giao diện thường phát triển khi một đối tượng chung được sử dụng trong các môi trường khác nhau. Trong C #, các biến thể của IComparable, IEqualityComparer và IComparer cho phép sắp xếp theo các thiết lập riêng biệt, do đó bạn có thể sẽ thực hiện tất cả chúng, một số trong số chúng có thể nhiều hơn một lần vì bạn có thể thực hiện các phiên bản được gõ mạnh chung cũng như các phiên bản không chung chung , ngoài ra, bạn có thể thực hiện nhiều hơn một trong những khái quát.

Hãy lấy một kịch bản ví dụ, giả sử một webshop nơi bạn có thể mua các khoản tín dụng mà bạn có thể mua một thứ khác (các trang web ảnh chứng khoán thường sử dụng chương trình này). Bạn có thể có một lớp "Valuta" và một lớp "Tín dụng" kế thừa cùng một cơ sở. Valuta có một số quá tải toán tử tiện lợi và thói quen so sánh cho phép bạn thực hiện các phép tính mà không phải lo lắng về tài sản "Tiền tệ" (ví dụ như thêm bảng Anh vào đô la). Tín dụng được phân bổ đơn giản hơn nhưng có một số hành vi khác biệt. Muốn có thể so sánh chúng với nhau, cuối cùng bạn có thể triển khai IComparable cũng như IComparable và các biến thể khác của giao diện so sánh trên cả hai (mặc dù chúng sử dụng một triển khai chung cho dù đó là trong lớp cơ sở hay ở nơi nào khác).

Khi thực hiện tuần tự hóa, ISerializable, IDeserializationCallback được triển khai. Sau đó thực hiện ngăn xếp hoàn tác lại: IClonable được thêm vào. Chức năng IsDenty: IObservable, INotifyPropertyChanged. Cho phép người dùng chỉnh sửa các giá trị bằng chuỗi: IConvertable ... Danh sách có thể tiếp tục và bật ...

Trong các ngôn ngữ hiện đại, chúng ta thấy một xu hướng khác nhau giúp phân tách các khía cạnh này và đặt chúng trong các lớp riêng của chúng, bên ngoài lớp cốt lõi. Lớp bên ngoài hoặc khía cạnh sau đó được liên kết với lớp đích bằng cách sử dụng chú thích (thuộc tính). Thông thường có thể làm cho các lớp khía cạnh bên ngoài ít nhiều chung chung.

Việc sử dụng các thuộc tính (chú thích) có thể được phản ánh. Một nhược điểm là mất hiệu suất nhỏ (ban đầu). Một nhược điểm (thường là cảm xúc) là các nguyên tắc như đóng gói cần phải được thư giãn.

Luôn luôn có các giải pháp khác, nhưng đối với mọi giải pháp tiện lợi đều có sự đánh đổi hoặc nắm bắt. Ví dụ: sử dụng giải pháp ORM có thể yêu cầu tất cả các thuộc tính được khai báo ảo. Các giải pháp tuần tự hóa có thể yêu cầu các nhà xây dựng mặc định trên các lớp của bạn. Nếu bạn đang sử dụng phép nội xạ phụ thuộc, bạn có thể sẽ thực hiện 23 giao diện trên một lớp.

Trong mắt tôi, 23 giao diện không phải là xấu theo định nghĩa. Có thể có một kế hoạch được cân nhắc kỹ lưỡng đằng sau nó, hoặc một số xác định nguyên tắc như tránh sử dụng sự phản ánh hoặc niềm tin đóng gói cực đoan.

Bất cứ khi nào chuyển đổi một công việc, hoặc phải xây dựng trên một kiến ​​trúc hiện có. Lời khuyên của tôi là trước tiên hãy làm quen hoàn toàn, đừng cố gắng cấu trúc lại mọi thứ quá nhanh. Lắng nghe nhà phát triển ban đầu (nếu anh ta vẫn ở đó) và cố gắng tìm ra những suy nghĩ và ý tưởng đằng sau những gì bạn nhìn thấy. Khi đặt câu hỏi, làm như vậy không phải vì mục đích phá vỡ nó, mà để tìm hiểu ... Vâng, mọi người đều có búa vàng của riêng mình, nhưng càng nhiều búa bạn có thể thu thập càng dễ dàng hơn với các đồng nghiệp.


0

"Quá nhiều" là chủ quan: phong cách lập trình? hiệu suất? sự phù hợp với tiêu chuẩn? tiền lệ? chỉ đơn giản là cảm giác thoải mái / tự tin?

Miễn là mã của bạn hoạt động đúng và không có vấn đề về khả năng bảo trì, 23 thậm chí có thể là chuẩn mực mới. Một ngày nào đó tôi có thể nói: "Bạn có thể thực hiện một tác phẩm xuất sắc với 23 giao diện, xem: Jonas Elfström".


0

Tôi sẽ nói rằng giới hạn phải là một số nhỏ hơn 23 - giống như 5 hoặc 7,
tuy nhiên, điều này không bao gồm bất kỳ số giao diện nào mà các giao diện đó kế thừa hoặc bất kỳ số giao diện nào được thực hiện bởi các lớp cơ sở.

(Vì vậy, hoàn toàn, N + bất kỳ số lượng giao diện được kế thừa, trong đó N <= 7.)

Nếu lớp của bạn thực hiện quá nhiều giao diện, nó có thể là một lớp thần .

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.