Những mẫu thiết kế nào là tồi tệ nhất hoặc được xác định hẹp nhất? [đóng cửa]


28

Đối với mọi dự án lập trình, các nhà quản lý có kinh nghiệm lập trình trong quá khứ cố gắng tỏa sáng khi họ đề xuất một số mẫu thiết kế cho dự án của bạn. Tôi thích các mẫu thiết kế khi chúng có ý nghĩa hoặc nếu bạn cần một giải pháp mở rộng. Tôi đã sử dụng các mẫu Proxy, Quan sát viên và Lệnh theo cách tích cực, và làm như vậy mỗi ngày. Nhưng tôi thực sự do dự khi sử dụng mô hình Nhà máy nếu chỉ có một cách để tạo một đối tượng, vì một nhà máy có thể làm cho tất cả dễ dàng hơn trong tương lai, nhưng làm phức tạp mã và hoàn toàn là chi phí.

Vì vậy, câu hỏi của tôi liên quan đến nghề nghiệp tương lai của tôi và câu trả lời của tôi cho các loại người quản lý ném các tên mẫu ngẫu nhiên xung quanh:

Những mẫu thiết kế nào bạn đã sử dụng, điều đó đã đẩy bạn trở lại tổng thể? Những mẫu thiết kế tồi tệ nhất , những mẫu mà bạn nên xem xét ngoại trừ trong một tình huống duy nhất có ý nghĩa (đọc: mẫu thiết kế nào được xác định rất hẹp)? (Giống như tôi đang tìm kiếm các đánh giá tiêu cực về một sản phẩm tốt tổng thể của Amazon để xem những gì mọi người mắc lỗi nhất khi sử dụng các mẫu thiết kế.) Và tôi không nói về Anti-Forms ở đây, nhưng về các Mẫu thường được nghĩ đến như mô hình "tốt".

Chỉnh sửa: Như một số người đã trả lời, vấn đề thường gặp nhất là các mẫu không phải là "xấu" mà là "sử dụng sai". Nếu bạn biết các mẫu, thường được sử dụng sai hoặc thậm chí khó sử dụng, chúng cũng sẽ phù hợp như một câu trả lời.


Hầu hết các mô hình làm cho thay đổi trong tương lai dễ dàng trên một số trục thay đổi, nhưng chúng có thể làm thay đổi khó khăn hơn trên các trục thay đổi khác. Nhóm bốn cuốn sách đặc biệt tốt để nói khi một mô hình được áp dụng. Nhiều cuốn sách tiếp theo về các mẫu bỏ lỡ điểm này. Lấy mẫu Khách truy cập làm ví dụ. Nó giúp dễ dàng thêm các thuật toán truyền tải cây mới, nhưng làm cho việc thêm các loại nút mới vào cây trở nên khó khăn hơn. Nó cũng cho phép các thuật toán truyền tải ở một lớp cao hơn cây. Bạn cần xem xét trục thay đổi nào kém ổn định nhất và thiết kế để thực hiện thay đổi dọc theo trục đó dễ dàng.
Theodore Norvell

Tất cả những cái trong cuốn sách 'Gang of Four'.
Miles Rout

Câu trả lời:


40

Tôi không tin vào các mẫu xấu, tôi tin rằng các mẫu đó có thể được áp dụng rất tệ!

  • IMHO singleton là mẫu bị lạm dụng nhất và áp dụng sai nhất. Mọi người dường như mắc một bệnh đơn lẻ và bắt đầu nhìn thấy các khả năng cho những người độc thân ở khắp mọi nơi mà không xem xét các lựa chọn thay thế.
  • Mẫu khách truy cập IMHO có mức sử dụng hẹp nhất và hầu như sẽ không bao giờ phức tạp thêm vào. Một pdf đẹp có thể được nhận ở đây . Thực sự chỉ khi bạn có cấu trúc dữ liệu mà bạn biết sẽ bị vượt qua trong khi thực hiện các hoạt động khác nhau trên cấu trúc dữ liệu mà không biết trước tất cả các cách, hãy tạo cơ hội chiến đấu cho khách truy cập. Nó là đẹp mặc dù :)

Đối với câu trả lời này, tôi chỉ xem xét các mẫu GOF. Tôi không biết tất cả các mẫu có thể đủ tốt để xem xét chúng.


Tôi thấy rất ít sử dụng cho khách truy cập. Singletons ... đừng để tôi bắt đầu. Nếu tình huống không hoàn hảo cho một người, đừng sử dụng nó.
Michael K

1
Có thể có rất ít sử dụng cho Khách truy cập, nhưng khi có nó chắc chắn sẽ giải quyết được vấn đề. Sự hiểu biết của tôi là Vistor rất cần thiết cho LINQ.
quentin-starin

12
Mẫu khách truy cập rất quan trọng để giảm (hoặc loại bỏ) độ phức tạp chu kỳ trong một chương trình phần mềm. Bất cứ khi nào bạn có cây if / other hoặc câu lệnh chuyển đổi, tỷ lệ cược cao là Khách truy cập có thể thay thế chúng, cung cấp thực thi được đảm bảo và kiểm tra thời gian biên dịch. Khách truy cập là một trong những mẫu mạnh mẽ nhất mà tôi biết và chúng tôi sử dụng nó thường xuyên với hiệu quả tuyệt vời. Nó làm cho thử nghiệm là một giấc mơ là tốt.
Les Hazlewood

@LesHazlewood Không phải khách truy cập chỉ là một cách giải quyết cho các ngôn ngữ lập trình không đầy đủ? Các ngôn ngữ giống ML (Haskell, SML, OCaml, v.v.) có các kiểu dữ liệu đại số ("union on steroid") và khớp mẫu ("bật steroids") tạo mã đơn giản hơn Trình truy cập, nhưng trình biên dịch đã kiểm tra đầy đủ. So với khách truy cập, bạn không có nhiều phương thức có trạng thái chia sẻ mà bạn cần quản lý thủ công thông qua các thuộc tính đối tượng. Trong các ngôn ngữ giống ML, và tất cả các phân biệt trường hợp phải được hoàn thành, nếu không nó sẽ không được biên dịch.
vog

14

Ngoài Singleton và Khách truy cập đã được đề cập bởi những người trả lời khác, tôi không biết về các mẫu thiết kế "khét tiếng". IMHO các vấn đề lớn nhất không xuất phát từ một mẫu thiết kế cụ thể là "sai", mà là do các nhà phát triển áp dụng các mẫu quá háo hức.

Hầu như tất cả mọi người đều trải qua giai đoạn "sốt mẫu" khi làm quen với các mẫu. Nghĩ rằng các mẫu là điều tốt nhất kể từ khi bánh mì cắt lát, ban đầu người ta cố gắng áp dụng chúng bất cứ khi nào anh ta thấy một khả năng. Điều này dẫn đến việc mã bị chôn vùi dưới các mẫu, trong đó bản thân các mẫu không giúp được nữa, chỉ làm cho mã khó hiểu hơn và duy trì trong thời gian dài.

Cuối cùng, hầu hết chúng ta đều vượt qua giai đoạn này và bắt đầu học cách sử dụng các mô hình để giải quyết các vấn đề thực sự, không phải vì lợi ích của riêng họ. Các mẫu có giá của chúng, được thêm độ phức tạp và việc áp dụng bất kỳ mẫu cụ thể nào chỉ được chứng minh khi nó trả lại cho độ phức tạp thêm bằng cách giúp đơn giản hóa một số phần khác của hệ thống, do đó làm cho mã / cấu hình nói chung dễ hiểu và dễ bảo trì hơn. Nếu đây không phải là trường hợp, tốt hơn là nên tránh xa các mẫu, gắn bó với giải pháp đơn giản nhất có thể có thể làm việc.


Chắc chắn rồi. Mô hình không tốt cũng không xấu, chúng được áp dụng tốt hoặc áp dụng sai.

Tôi muốn dạy mọi người theo cách tôi đã học: OO trước tiên, hiểu cách đối tượng liên quan và sau đó học tên của các mẫu. Thật quá dễ dàng để nghĩ về các mẫu hơn những gì cần phải làm. Họ là một công cụ truyền thông.
Michael K

Các mẫu là một phương tiện để giao tiếp, không phải là một danh sách quy định. Nếu bạn bắt đầu với một mô hình trong tâm trí, bạn có thể đang sử dụng sai nó. Nếu bạn tìm thấy một, hoặc gợi ý của một, trong thiết kế của bạn, thì các danh mục mẫu có thể giúp bạn hiểu những gì bạn có thể cần.
Rob Crawford

14

Tôi sẽ đi ra ngoài ở đây và đề nghị sử dụng thừa kế. Chắc chắn áp dụng nhiều nhất trong các ngôn ngữ mà không cần hỗ trợ đa hình thời gian biên dịch vững chắc, như Java. Kế thừa thời gian chạy là một công cụ, không phải là một loại kỳ quan một tính năng phù hợp với tất cả.

Những người khác đã thể hiện tương tự như sự căm ghét cá nhân của tôi đối với Singletons, vì vậy tôi sẽ không mở rộng điều đó ở đây.


10

Người độc thân. Đó là trên các mẫu GOF mà ngày nay thường được gọi là chống mẫu. Một trong những lý do cho điều đó là Singleton làm cho mã khó kiểm tra hơn.


4
Có rất nhiều sai sót cơ bản trong mô hình singleton, hầu hết được minh họa rõ trong bài viết này của Steve Yegge - Singleton được coi là ngu ngốc
ocodo

Slomojo: Bài viết hay. Tôi sẽ gọi nó là 'mẫu đơn giản' từ bây giờ:-)
Không ai

2
Vâng, bởi vì một số kẻ ngu ngốc lạm dụng một mô hình và hoàn toàn bỏ lỡ con thuyền về tất cả những gì OO (đánh giá bởi tất cả các lớp Manager mà anh ta đưa ra), tất nhiên đó là lỗi của mẫu chứ không phải của các nhà phát triển.
Dunk

Tại sao mọi người lại liên kết việc triển khai chung (và rắc rối) của Singleton với mẫu Singleton? Một cái gần như luôn luôn xấu, cái kia thì không.
quentin-starin

1
@qes> Singleton đặt ra các vấn đề triển khai quan trọng (đặc biệt là với luồng). Đây là một điểm xấu. Nhưng, bạn cũng sẽ phát hiện ra rằng singleton là một mô hình về cách lớp bị kiện chứ không phải cách nó hoạt động. Làm thế nào lớp được sử dụng nên được xử lý bởi mã bằng cách sử dụng lớp, vì vậy Singleton là một sự phá vỡ các mối quan tâm.
deadalnix

7

Nếu bạn biết các mẫu, thường được sử dụng sai hoặc thậm chí khó sử dụng, chúng cũng sẽ phù hợp như một câu trả lời.

Theo mẫu MVVM cho WPF quá nghiêm ngặt, như được chỉ ra ví dụ bởi câu hỏi này . Một số người cố gắng làm theo hướng dẫn rằng không nên đặt mã vào mã phía sau quá nghiêm ngặt và đưa ra tất cả các loại hack kỳ lạ.

Và dĩ nhiên, MVVM khó như địa ngục và chỉ không xứng đáng với các dự án ngắn hạn nhỏ.

Tiến sĩ WPF đã làm một bài viết mỉa mai về nó trong bài viết MV-poo của mình .


@Akku: Bạn nên biết cách sử dụng nó, vì vậy bạn có thể quyết định xem nó có phù hợp với dự án của bạn không. Vì vậy, có, nó rất cần thiết cho sự phát triển WPF, và rất hữu ích.
Steven Jeuris

Một trong những vấn đề là mọi người hiểu sai về mẫu MVVM. Nó không "khó như địa ngục." Mọi người thực hiện theo cách đó bằng cách nghĩ rằng tất cả các mẫu khác như Mẫu lệnh và Mẫu hòa giải là một phần của nó. Theo riêng tôi, MVVM là một trong những mẫu đơn giản nhất, theo ý kiến ​​của tôi. Tôi đồng ý rằng việc làm theo bất cứ điều gì với t chỉ là ngớ ngẩn.
BK

5

Một số mẫu trong sách GOF là C ++ - cụ thể, theo nghĩa chúng ít được áp dụng trong các ngôn ngữ có sự phản chiếu, ví dụ mẫu Prototype ít có ý nghĩa hơn trong Java.

Tôi coi mẫu Phiên dịch là mẫu 'hẹp'. Bạn phải có một vấn đề chung đáng để phát triển một người giải quyết vấn đề chung. Nó chỉ hoạt động cho các vấn đề đặc biệt mà bạn có thể phát minh ra một ngôn ngữ, xác định ngữ pháp và viết một trình thông dịch. Các trường hợp vấn đề nên được biểu diễn dưới dạng câu trong ngữ pháp. Tôi không nghĩ rằng bạn gặp phải tình huống như vậy thường xuyên.


1
hầu hết GOF chỉ áp dụng cho OOP dựa trên lớp tĩnh. đi lạc một chút từ loại ngôn ngữ đó và cuốn sách trở thành một giai thoại giải trí.
Javier

5

Điều tôi rất tiếc nhất (mặc dù không kịch liệt nhất): Khi tôi vừa mới tạo một chức năng nhưng tôi đã triển khai một giải pháp OOP.


1
Tại sao? Điều gì làm bạn hối tiếc? Hãy mở rộng câu trả lời của bạn và thêm kinh nghiệm của bạn.
Walter

Thật vậy, tôi nghĩ rằng một lớp với các biến cục bộ và các phương thức rõ ràng sẽ dễ sử dụng hơn so với một hàm 200 dòng duy nhất chỉ có thể được áp dụng lại thông qua dán sao chép và sau đó không chỉ có một nơi để trông xấu xí và không toàn diện.
Akku

2
KISS ngụ ý bạn biến nó thành một hàm trước, sau đó cấu trúc lại thành một lớp nếu cần.
Eva

5

Nhà máy. Tôi đã thấy mã thực hiện nó chỉ tạo một loại. Đó là mã IMO hoàn toàn vô dụng. Nó không giúp ích gì cho nhiều ví dụ trực tuyến hoàn toàn bị chiếm đoạt. Nhà máy pizza?

Có lẽ nhà máy dễ kiểm tra hơn vì tiêm phụ thuộc. Nhưng để thêm mã đó khi bạn không cần nó là vô nghĩa đối với tôi và đối số thử nghiệm sẽ biến mất khi bạn có thể sử dụng các khung giả như JMockit. Đơn giản hơn bạn có thể làm một chương trình, tốt hơn. Các nhà máy chỉ thực sự có ý nghĩa với số lượng lớn hơn các loại (bởi lớn hơn, ý tôi là ít nhất hơn 2).


Vâng, nhà máy Pizza, cảm ơn vì Mẫu thiết kế đầu tiên ~
Niing

2

Người độc thân

Tôi đồng ý với những người khác về Singleton. Không phải là bạn không bao giờ nên sử dụng chúng, chỉ là nó nên được giới hạn trong rất ít trường hợp. Chúng được sử dụng như những quả cầu lười biếng rất nhiều thời gian.

An toàn chủ đề là một vấn đề với singletons. Xử lý ngoại lệ là một cách khác - nếu singleton không tạo đúng - bạn không biết liệu mình có thể bắt lỗi một cách an toàn hay không, đặc biệt nếu đó là một trong những đối tượng được tạo "trước chính". Và sau đó là vấn đề dọn dẹp sau đó.

Tôi có xu hướng thích sử dụng một singleton và có tất cả các singletons "Wannabe" khác "đăng ký" cho bạn. Cách sử dụng đơn lẻ phổ biến nhất của tôi là xử lý "shout event": bạn chỉ "phát ra thế giới" rằng một sự kiện đã diễn ra và bất cứ ai nghe sẽ xử lý sự kiện đó. Bằng cách đó, bạn tách rời các sự kiện thực sự xảy ra với những gì đang lắng nghe chúng. (Ghi nhật ký, tín hiệu, v.v.)

Khách thăm quan

Điều xấu xí mà tôi tìm thấy về điều này, ngoài việc các nhà phát triển không thể nghĩ ra những cái tên có ý nghĩa và chỉ gọi phương thức visit (), là nó bổ sung khả năng mở rộng theo một hướng trong khi loại bỏ nó theo hướng khác, tức là nó bổ sung thêm chức năng nhưng hạn chế số lượng đối tượng mà khách truy cập của bạn cần biết về tất cả các loại đối tượng mà nó có thể truy cập.

Mặc dù có thể lộn xộn, cho phép mở rộng theo cả hai hướng nhưng điều này không hoàn toàn sử dụng mẫu khách truy cập ở dạng thông thường. Ứng dụng phổ biến nhất cho việc này là in các đối tượng: bạn có nhiều cách khác nhau để in các đối tượng và các đối tượng khác nhau cần được in. Bạn sẽ có thể mở rộng điều này theo cả hai hướng. (In có nghĩa là bất kỳ loại biến đối tượng nào thành luồng: lưu trữ trong tệp / ghi vào bàn điều khiển / GUI .. vv).

(Lưu ý: bạn không nên nhầm lẫn điều này với kiến ​​trúc xem tài liệu, đây là một mẫu hơi khác).


2
Giải pháp của bạn sử dụng cái cũ nó tách ra những điều tranh luận. Cụ thể, bạn đăng một sự kiện và một số anh chàng khác xử lý sự kiện và ghi lại nó. Đó là một điều tốt, bởi vì tất cả mọi người được tách ra! SAI RỒI! Tôi đã từng làm điều đó, thật là một nỗi đau hoàng gia. Tôi nhận ra rằng nếu tôi muốn một cái gì đó được ghi lại, tôi muốn nói rõ ràng ghi nhật ký chính xác điều này, ngay tại đây, ngay bây giờ, trong mã tại thời điểm nó xảy ra. Không có một số đối tượng khác tìm ra những gì nên được ghi lại, với các sự kiện khác có thể được xen kẽ bởi các trình xử lý khác, nếu nó thậm chí được ghi lại. Nó không có gì ngoài sự quá mức phức tạp.
Dunk

2

Tôi nghĩ vấn đề với một số mẫu phức tạp hơn là có rất nhiều biến thể trên chúng đến nỗi chúng mất đi nhiều giá trị như một thiết bị liên lạc.

Người phạm tội tồi tệ nhất tôi có thể nghĩ trong danh mục này là mẫu MVC. Ngay cả khi chúng tôi bỏ qua MVP, có rất nhiều biến thể trong vai trò của từng mục này mà bạn phải dành một giờ trong mỗi khung mới để tìm ra ranh giới nằm ở đâu.


Tôi cũng nghĩ rằng MVC nên được sử dụng ở mọi nơi, nhưng không được triển khai theo cùng một cách ở mọi nơi. Và nhiều người không hiểu nó. Khi tôi lần đầu tiên muốn sử dụng nó, tôi đã tạo ra ba lớp có tên Model, View (một dạng cửa sổ) và Trình điều khiển. Đó là một mớ hỗn độn, vì các hình thức không được tạo ra cho MVC.
Akku

1

Không có mẫu xấu chỉ có người xấu.

Tôi muốn thừa hưởng mã dễ đọc có thể làm một cái gì đó rõ ràng nhưng hơi dài dòng hoặc không (xếp hàng âm nhạc dân làng độc ác) có thể sử dụng lại (thở hổn hển!) Hơn một số mash của InheritAbstractTemplateFaucetSink<Kitchen>.

Mã sử ​​dụng lại là tuyệt vời! Có thể bạn không viết mã sẽ được sử dụng lại hoặc viết lại logic tương tự cho một ứng dụng khác sẽ khiến bạn mất ít thời gian hơn so với một số nỗ lực điên rồ để sử dụng lại mã của một số ứng dụng khác.

Để đọc thêm, hãy mở một số mã C trong phần triển khai lành mạnh của các tiêu đề posix hoặc clibs và phát hiện mẫu. Mã này được viết bởi một số lập trình viên thông minh và tận tâm nhất trên thế giới. Bạn có biết bạn sẽ nhìn thấy bao nhiêu mẫu nhà máy trừu tượng không? ... KHÔNG AI!. Cơ hội tốt hơn nữa là nếu bạn hiểu các phần khác của những gì đang diễn ra, bạn sẽ thấy logic rất dễ hiểu và theo dõi.

Quan điểm của tôi là hầu hết các "mẫu" không được tạo ra để làm cho mã tốt hơn chúng được tạo ra để bán sách và phần mềm mô hình hóa. Nếu bạn giỏi lập trình, có lẽ bạn sẽ tránh hầu hết những điều này và viết mã rõ ràng, súc tích và được thiết kế khéo léo để giải quyết vấn đề của bạn. Khi bạn có một vấn đề khác, bạn sẽ viết mã rõ ràng, súc tích, được thiết kế khéo léo để giải quyết vấn đề đó. Nếu mục tiêu của bạn là viết ít mã hơn tôi nghĩ bạn không thể trở thành một lập trình viên. Tôi thích viết mã và muốn viết nó càng nhiều càng tốt. Khi tôi viết lại một cái gì đó tôi đã viết, tôi làm nó nhanh gấp hàng chục lần và thoát khỏi tất cả những điều tôi không hài lòng với lần đầu tiên tôi làm.

Với điều đó tôi sẽ để lại cho bạn với trích dẫn (có liên quan) tốt nhất trong khoa học máy tính.

" Có hai cách để xây dựng một thiết kế phần mềm: Một cách là làm cho nó đơn giản đến mức rõ ràng là không có thiếu sót, và cách khác là làm cho nó phức tạp đến mức không có thiếu sót rõ ràng. Phương pháp đầu tiên khó khăn hơn nhiều . "

  • Tony Hoare (người phát minh ra quicksort, cha đẻ của thiết kế hệ điều hành hiện đại, người tạo ra logic Hoare và người nhận giải thưởng Turing)

0

Tôi chắc chắn đồng ý rằng có một thời gian cho hầu hết các mẫu và bạn có thể lạm dụng nhiều mẫu. Tôi biết cái mà tôi đã lạm dụng nhiều nhất trong quá khứ là mẫu Tóm tắt. Được sử dụng ở mức độ đầy đủ, nó được gọi là dạng web ASP.NET.

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.