Giải pháp nên càng chung chung càng tốt hoặc càng cụ thể càng tốt?


124

Nói rằng tôi có một thực thể có thuộc tính "loại". Có thể có hơn 20 loại có thể.

Bây giờ tôi được yêu cầu thực hiện một cái gì đó cho phép thay đổi loại từ A-> B, đây là trường hợp sử dụng duy nhất.

Vì vậy, tôi nên thực hiện một cái gì đó cho phép thay đổi loại tùy ý miễn là chúng là loại hợp lệ? Hoặc tôi chỉ nên cho phép nó thay đổi từ A-> B theo yêu cầu và từ chối mọi thay đổi loại khác như B-> A hoặc A-> C?

Tôi có thể thấy những ưu và nhược điểm từ cả hai phía, trong đó một giải pháp chung có nghĩa là ít công việc hơn trong trường hợp một yêu cầu tương tự xuất hiện trong tương lai, nhưng điều đó cũng có nghĩa là sẽ có nhiều cơ hội sai hơn (mặc dù chúng tôi kiểm soát 100% người gọi này điểm).
Một giải pháp cụ thể ít bị lỗi hơn, nhưng đòi hỏi nhiều công việc hơn trong tương lai nếu một yêu cầu tương tự phát sinh.

Tôi luôn nghe rằng một nhà phát triển giỏi nên cố gắng lường trước sự thay đổi và thiết kế hệ thống để dễ dàng mở rộng trong tương lai, nghe có vẻ như là một giải pháp chung chung?

Biên tập:

Thêm chi tiết vào ví dụ không cụ thể của tôi: Giải pháp "chung" trong trường hợp này đòi hỏi ít công việc hơn giải pháp "cụ thể", vì giải pháp cụ thể yêu cầu xác thực về loại cũ cũng như loại mới, trong khi giải pháp chung chỉ cần xác nhận loại mới.


97
Đó là một câu hỏi thú vị. Tôi đã có một cuộc thảo luận về một cái gì đó tương tự với gramp của tôi (một lập trình viên hẹn giờ rất, rất cũ) và câu trả lời của anh ấy là một cái gì đó trong "điều chung chung nhất giải quyết vấn đề cụ thể của bạn", làm cho nó trở nên lạ mắt " Nó phụ thuộc ". Các tuyên bố về chăn trong Phát triển phần mềm hiếm khi hoạt động - mọi thứ nên được thực hiện luôn trong từng trường hợp cụ thể.
T. Sar

2
@ T.Sar thêm này như là một câu trả lời và tôi sẽ upvote :-)
Christophe

4
Một giải pháp chung chung của người Viking là gì trong quan điểm của bạn? Ngoài ra, vui lòng làm rõ những gì bạn có ý nghĩa bởi các trường hợp chỉ sử dụng trường hợp. Bạn có nghĩa là chỉ cho phép chuyển đổi từ A-> B hoặc chỉ chuyển đổi đó được chỉ định và sẽ không phải là điều kiện lỗi để chuyển từ bất kỳ trạng thái nào sang trạng thái khác. Là nhà phát triển, bạn cần yêu cầu tác giả của ca sử dụng làm rõ. Nếu không có chuyển đổi nào khác được cho phép và mã của bạn cho phép nó bất kể ai điều khiển người gọi, mã của bạn đã không đáp ứng các yêu cầu.
RibaldEddie

5
Nguyên tắc rằng nếu X là một ý tưởng tốt, thì chỉ có X luôn luôn là tối ưu, dường như có một sức hấp dẫn đặc biệt đối với các nhà phát triển (hoặc ít nhất là một nhóm phát âm trong số họ), nhưng hãy xem xét điều này: quy tắc lập trình là giống như tục ngữ, trong đó bạn thường có thể tìm thấy một cặp có ý nghĩa ngược lại. Đây là một dấu hiệu cho thấy bạn nên sử dụng phán đoán của mình (như được ủng hộ bởi các câu trả lời ở đây) và hãy cẩn thận với giáo điều.
sdenham

2
Tổng quát hóa sớm có thể gây ra nhiều ợ nóng như Tối ưu hóa sớm - bạn sẽ viết rất nhiều mã có thể không bao giờ được sử dụng. Giải quyết vấn đề cụ thể trước, sau đó khái quát hóa khi có nhu cầu.
John Bode

Câu trả lời:


296

Quy tắc của tôi:

  1. lần đầu tiên bạn gặp phải vấn đề, chỉ giải quyết vấn đề cụ thể (đây là nguyên tắc YAGNI )
  2. lần thứ hai bạn gặp vấn đề tương tự, hãy xem xét khái quát hóa trường hợp đầu tiên, nếu nó không phải là nhiều việc
  3. một khi bạn có ba trường hợp cụ thể mà bạn có thể sử dụng phiên bản tổng quát, thì bạn nên bắt đầu thực sự lên kế hoạch cho phiên bản tổng quát - bây giờ, bạn nên hiểu rõ vấn đề đủ để thực sự có thể khái quát hóa nó.

Tất nhiên, đây là một hướng dẫn và không phải là một quy tắc khó và nhanh: câu trả lời thực sự là sử dụng phán đoán tốt nhất của bạn, trong từng trường hợp.


1
Bạn có thể giải thích YAGNI là gì không?
Bernhard

7
@Bernhard Bạn không cần nó . Một nguyên tắc thiết kế phần mềm rất hữu ích.
Angew

4
"Tại thing1, thing2, hãy nghĩ về việc có thể sử dụng một mảng. Tại thing1, thing2, thing3, gần như chắc chắn sử dụng thing[]mảng thay thế." là một quy tắc tương tự để quyết định giữa nhiều biến hoặc một mảng.
Joker_vD

15
Một cách khác để nêu quy tắc số 1: "Bạn không thể khái quát một điều."
Wayne Conrad

2
@SantiBailors: Như Doc Brown nói trong câu trả lời của anh ấy, chúng tôi thường đánh giá quá cao số tiền mà chúng tôi có thể bỏ ra bằng cách xây dựng cái đầu tiên để vứt đi. Trong Tháng huyền thoại , Fred Brooks nói: "Kế hoạch vứt bỏ một thứ - dù sao đi nữa, bạn sẽ làm được." Điều đó nói rằng: nếu bạn ngay lập tức gặp phải nhiều hơn một lần sử dụng cho một cái gì đó - ví dụ, bằng cách được cung cấp một tập hợp các yêu cầu trong đó bạn rõ ràng sẽ cần phải giải quyết cùng một vấn đề nhiều lần - thì bạn đã có nhiều hơn một trường hợp để khái quát hóa từ, và điều đó hoàn toàn tốt và không mâu thuẫn với câu trả lời của tôi.
Daniel Pryden

95

Một giải pháp cụ thể [...] đòi hỏi nhiều công việc hơn trong tương lai nếu cần yêu cầu tương tự

Tôi đã nghe cuộc tranh luận này vài chục lần, và - theo kinh nghiệm của tôi - nó thường xuyên trở thành ngụy biện. Nếu bạn khái quát hóa bây giờ hoặc sau này, khi yêu cầu tương tự thứ hai xuất hiện, công việc sẽ gần như giống nhau trong tổng số. Vì vậy, hoàn toàn không có điểm nào để đầu tư thêm nỗ lực vào việc khái quát hóa, khi bạn không biết nỗ lực này sẽ được đền đáp.

(Rõ ràng điều này không áp dụng khi một giải pháp tổng quát hơn ít phức tạp hơn và đòi hỏi ít nỗ lực hơn so với một giải pháp cụ thể, nhưng theo kinh nghiệm của tôi, đây là những trường hợp hiếm gặp. một câu trả lời của tôi là về).

Khi "trường hợp tương tự thứ hai" xuất hiện, đó là lúc bắt đầu suy nghĩ về việc khái quát hóa. Sau đó, việc khái quát hóa chính xác sẽ dễ dàng hơn nhiều , bởi vì yêu cầu thứ hai này cung cấp cho bạn một kịch bản mà bạn có thể xác nhận nếu bạn thực hiện đúng những điều chung chung. Khi cố gắng khái quát hóa chỉ cho một trường hợp, bạn đang chụp trong bóng tối. Rất có thể bạn phát triển quá mức một số thứ không cần phải khái quát hóa và bỏ lỡ những phần khác cần thiết. Và khi sau đó một trường hợp thứ hai phát sinh và bạn nhận ra bạn đã khái quát những điều sai trái, thì bạn còn nhiều việc phải làm để khắc phục điều này.

Vì vậy, tôi khuyên bạn nên trì hoãn mọi cám dỗ để làm những việc "chỉ trong trường hợp". Cách tiếp cận này sẽ chỉ dẫn đến nhiều nỗ lực bảo trì và làm việc hơn khi bạn bỏ lỡ cơ hội khái quát hóa ba, bốn lần trở lên và sau đó có một đống mã tương tự (trùng lặp) để duy trì.


2
Đối với tôi câu trả lời này không có ý nghĩa trong bối cảnh của OP. Anh ấy nói rằng anh ấy sẽ dành ít thời gian hơn để khái quát hóa bây giờ và ít thời gian hơn trong tương lai, trừ khi trong tương lai cần phải thực hiện cụ thể. Bạn đang tranh luận về việc "đầu tư thêm nỗ lực vào việc khái quát hóa", trong khi OP sẽ chỉ đầu tư thêm nỗ lực nếu họ không khái quát hóa. (nghĩ) .... lạ: $
msb

2
@msb: bối cảnh đó đã được thêm vào sau khi tôi viết câu trả lời của mình và đi ngược lại với những gì OP đã nói trước đó, đặc biệt là trong phần tôi đã trích dẫn. Xem chỉnh sửa của tôi.
Doc Brown

2
Ngoài ra, giải pháp tổng quát sẽ phức tạp hơn, do đó, khi bạn phải điều chỉnh nó cho trường hợp thứ hai, sẽ mất nhiều thời gian hơn để hiểu lại nó.
AndreKR

4
Doc, một bên, nhưng sẽ không bao giờ đoán bạn là một người không phải người bản xứ. Câu trả lời của bạn luôn được viết tốt và tranh luận tốt.
user949300

2
Tôi sẽ tưởng tượng giọng của bạn khi tôi đọc qua các câu trả lời trong tương lai của bạn. :-)
user949300

64

TL; DR: nó phụ thuộc vào những gì bạn đang cố gắng giải quyết.

Tôi đã có một cuộc trò chuyện tương tự với Gramp của tôi về điều này, trong khi chúng tôi đang nói về việc FuncAction trong C # tuyệt vời như thế nào . My Gramp là một lập trình viên hẹn giờ rất cũ, đó là xung quanh mã nguồn vì phần mềm được chạy trên các máy tính chiếm toàn bộ phòng.

Ông đã thay đổi công nghệ nhiều lần trong đời. Ông đã viết mã bằng C, COBOL, Pascal, BASIC, Fortran, Smalltalk, Java và cuối cùng bắt đầu C # như một sở thích. Tôi đã học được cách lập trình với anh ấy, ngồi trên đùi anh ấy khi tôi còn là một kẻ lầm đường lạc lối, khắc sâu những dòng mã đầu tiên của tôi trên trình soạn thảo màu xanh của SideKick của IBM. Khi tôi 20 tuổi, tôi đã dành nhiều thời gian viết mã hơn là chơi bên ngoài.

Đó là một chút ký ức của tôi, vì vậy xin lỗi nếu tôi không thực tế trong khi kể lại chúng. Tôi hơi thích những khoảnh khắc đó.

Đó là những gì anh ấy nói với tôi:


"Chúng ta có nên khái quát hóa một vấn đề, hoặc giải quyết nó trong phạm vi cụ thể, bạn có hỏi không? À, đó là một ... câu hỏi."

Gramp đã tạm dừng để suy nghĩ về nó trong một khoảnh khắc ngắn, trong khi cố định vị trí của kính trên mặt. Anh ta đang chơi một trò chơi match-3 trên máy tính, trong khi nghe LP của Deep Purple trên hệ thống âm thanh cũ.

"Chà, điều đó phụ thuộc vào vấn đề mà bạn đang cố gắng giải quyết", anh nói với tôi. "Thật hấp dẫn khi tin rằng một giải pháp duy nhất, thần thánh cho tất cả các lựa chọn thiết kế tồn tại, nhưng không có. Kiến trúc phần mềm giống như phô mai, bạn thấy đấy."

"... Pho mát, Gramp?"

"Không quan trọng bạn nghĩ gì về sở thích của mình, sẽ luôn có người cho rằng nó có mùi".

Tôi chớp mắt bối rối một lúc, nhưng trước khi tôi có thể nói bất cứ điều gì Gramp tiếp tục.

"Khi bạn đang chế tạo một chiếc xe hơi, làm thế nào để bạn chọn vật liệu cho một phần?"

"Tôi ... tôi đoán nó phụ thuộc vào chi phí liên quan và phần nên làm, tôi cho là vậy."

"Điều này phụ thuộc vào vấn đề mà bộ phận đang cố gắng giải quyết. Bạn sẽ không chế tạo lốp xe bằng thép hoặc kính chắn gió làm bằng da. Bạn chọn vật liệu giải quyết tốt nhất vấn đề bạn có trong tay. Bây giờ, cái gì là Bạn có nên sử dụng một cách tiếp cận đầy đủ chức năng, để cung cấp sự linh hoạt tối đa cho một mã sẽ chỉ được sử dụng một lần không? Một phần trong hệ thống của bạn sẽ thấy rất nhiều công dụng và có thể có nhiều thay đổi? Lựa chọn thiết kế giống như những vật liệu bạn chọn cho một phần trong xe hơi hoặc hình dạng của viên gạch Lego bạn chọn để xây dựng một ngôi nhà nhỏ Gạch Lego nào là tốt nhất? "

Lập trình viên cao tuổi với lấy một mô hình tàu Lego nhỏ mà anh ta có trên bàn trước khi tiếp tục.

"Bạn chỉ có thể trả lời rằng nếu bạn biết những gì bạn cần viên gạch đó. Làm thế quái nào bạn biết được giải pháp cụ thể tốt hơn giải pháp chung chung hay ngược lại, nếu bạn thậm chí không biết bạn đang gặp vấn đề gì cố gắng giải quyết? Bạn không thể nhìn thấy một lựa chọn mà bạn không hiểu. "

"..Bạn chỉ trích dẫn Ma trận? "

"Gì?"

"Không có gì, tiếp tục."

"Chà, giả sử bạn đang cố gắng xây dựng một cái gì đó cho Hệ thống Hóa đơn Quốc gia. Bạn biết API đó và tệp ba mươi nghìn dòng của nó trông như thế nào từ bên trong. Một giải pháp 'chung chung' để tạo tệp đó thậm chí sẽ trông như thế nào Tệp có đầy đủ các tham số tùy chọn, đầy đủ các trường hợp chỉ nên sử dụng các chi nhánh rất cụ thể của doanh nghiệp. Đối với hầu hết các trường hợp, bạn có thể bỏ qua chúng một cách an toàn. Bạn không cần tạo hệ thống hóa đơn chung nếu điều duy nhất bạn ' Sẽ bán được giày. Chỉ cần tạo một hệ thống bán giày và biến nó thành hệ thống hóa đơn bán giày tốt nhất hiện có. Bây giờ, nếu bạn phải tạo một hệ thống hóa đơn cho bất kỳ loại khách hàng nào, trên một ứng dụng rộng rãi hơn - được bán lại như một hệ thống bán hàng độc lập, chung chung,ví dụ - bây giờ thật thú vị khi thực hiện các tùy chọn chỉ được sử dụng cho Gas, thực phẩm hoặc rượu.Bây giờ đó là những trường hợp sử dụng có thể. Trước đây chúng chỉ là một số trường hợp sử dụng giả thuyết Đừng sử dụng và bạn không muốn triển khai các trường hợp không sử dụng . Đừng sử dụng là em trai của Đừng cần . "

Gramp đặt con tàu lego trở lại vị trí của nó và quay lại trò chơi match-3 của mình.

"Vì vậy, để có thể chọn một giải pháp chung chung hoặc cụ thể cho một vấn đề nhất định, trước tiên bạn cần phải hiểu vấn đề đó là cái quái gì. Nếu không, bạn chỉ đoán và đoán là công việc của các nhà quản lý, không phải lập trình viên. tất cả mọi thứ trong CNTT, nó phụ thuộc. "


Vì vậy, có bạn có nó. "Nó phụ thuộc". Đó có lẽ là cách diễn đạt hai từ mạnh mẽ nhất khi nghĩ về thiết kế phần mềm.


14
Tôi chắc chắn có điều gì đó hữu ích trong câu chuyện đó nhưng thật khó để đọc, xin lỗi
GoatInTheMachine

28
Bài đăng đầu tiên của bạn là một giai thoại vui ngắn - và tất nhiên đó là vấn đề về quan điểm - nhưng trừ khi tôi thực sự thích phong cách viết của ai đó, tôi thấy những câu chuyện dài như thế này thực sự tự do và một chút không phù hợp bên ngoài blog cá nhân
GoatInTheMachine

16
@ T.Sar đừng nghe những người ghét, bài viết của bạn là một lời khuyên hữu ích từ một đạo sư. +1
LLlAMnYP

7
Phần "kiến trúc phần mềm giống như phô mai" hoàn toàn tuyệt vời. Thật vậy, câu trả lời này là một viên ngọc quý!
Mathieu Guindon

3
Có lẽ câu trả lời này cũng giống như phô mai? ;) Nhưng làm ơn, "Smalltalk" cần được "Smalltalk", và vâng, tôi là rằng anh chàng, xin lỗi.
fede s.

14

Chủ yếu, bạn nên cố gắng dự đoán liệu có khả năng một sự thay đổi như vậy sẽ xảy ra hay không - không chỉ là một khả năng từ xa ở đâu đó.

Nếu không, tốt hơn hết là bạn nên tìm giải pháp đơn giản ngay bây giờ và mở rộng nó sau. Hoàn toàn có khả năng bạn sẽ có một bức tranh rõ ràng hơn nhiều về những gì cần thiết sau đó.


13

Nếu bạn đang làm việc trong miền mới đối với bạn, thì nên áp dụng Quy tắc ba mà Daniel Pryden đã đề cập. Rốt cuộc, bạn phải xây dựng những thứ trừu tượng hữu ích như thế nào nếu bạn là người mới trong khu vực đó? Mọi người thường tự tin vào khả năng nắm bắt trừu tượng của mình, mặc dù điều đó hiếm khi xảy ra. Theo kinh nghiệm của tôi, sự trừu tượng sớm không kém phần xấu xa so với sao chép mã. Trừu tượng sai là thực sự đau đớn để hiểu. Đôi khi còn đau đớn hơn để tái cấu trúc.

Có một cuốn sách đề cập đến quan điểm của tôi về một nhà phát triển khu vực không xác định đang làm việc. Bao gồm các tên miền cụ thể với các tóm tắt hữu ích được trích xuất.


Câu hỏi là rõ ràng về một vấn đề cụ thể.
RibaldEddie

4
Câu trả lời đủ chung chung để giải quyết vấn đề cụ thể này. Và câu hỏi không đủ cụ thể để được đưa ra một biên nhận cụ thể: như bạn có thể thấy, không có chi tiết tên miền nào được đề cập trong một câu hỏi. Ngay cả tên lớp cũng không được chỉ định (A và B không được tính).
Zapadlo

7
"Câu trả lời stackoverflow nên chung chung nhất có thể hoặc càng cụ thể càng tốt?"
Lyndon White

@LyndonWhite một câu hỏi stackoverflow nên chung chung nhất có thể (quá rộng!) Hoặc càng cụ thể càng tốt (bất cứ điều gì mà thất bại được gọi là!)? Hà.

4

Với bản chất của nội dung câu hỏi của bạn, giả sử tôi hiểu chính xác, tôi thực sự xem đây là một câu hỏi thiết kế về tính năng hệ thống trung tâm hơn là một câu hỏi về các giải pháp chung chung và cụ thể.

Và khi nói đến các tính năng và khả năng của hệ thống trung tâm, những tính năng đáng tin cậy nhất là những thứ không có ở đó. Nó trả cho sai lầm ở khía cạnh tối giản, đặc biệt là xem xét việc bổ sung chức năng tập trung, mong muốn lâu dài, hơn là loại bỏ chức năng có vấn đề, không mong muốn lâu, với nhiều phụ thuộc vì nó làm việc với hệ thống trở nên khó khăn hơn nhiều hơn nó cần phải trong khi đưa ra các câu hỏi thiết kế vô tận với mỗi tính năng mới.

Trên thực tế, thiếu dự đoán mạnh mẽ về việc liệu điều này có cần thiết thường xuyên trong tương lai hay không, tôi sẽ tìm cách tránh xem đây là sự thay thế loại từ A sang B nếu có thể, và thay vào đó chỉ tìm cách biến đổi trạng thái của A. Ví dụ: đặt một số trường trong A để biến nó thành hình thái và xuất hiện như B cho người dùng mà không thực sự thay đổi thành một loại 'khác' - bạn có thể tạo A lưu trữ B một cách riêng tư bằng cách sử dụng chức năng gọi và bố cục trong B khi trạng thái A được thiết lập để chỉ ra rằng nó nên bắt chước B để đơn giản hóa việc thực hiện nếu có thể. Đó phải là một giải pháp xâm lấn rất đơn giản và tối thiểu.

Vì vậy, dù sao, lặp lại nhiều người khác, tôi đề nghị sai lầm trong việc tránh các giải pháp chung trong trường hợp này, nhưng vì vậy tôi cho rằng điều này đang được cân nhắc trong việc bổ sung một khả năng rất táo bạo cho hệ thống trung tâm, và ở đó tôi sẽ đề nghị để lỗi ở bên bỏ nó ra, đặc biệt là bây giờ.


"bạn bỏ lỡ tất cả các lỗi bạn không mã." (từ poster bóng rổ: bạn bỏ lỡ tất cả các bức ảnh bạn không chụp)

3

Thật khó để đưa ra một câu trả lời chung chung cho vấn đề cụ thể này ;-)

Càng chung chung, bạn càng có nhiều thời gian cho những thay đổi trong tương lai. Ví dụ, vì lý do này, nhiều chương trình trò chơi sử dụng mô hình thành phần thực thể thay vì xây dựng một hệ thống loại rất phức tạp nhưng cứng nhắc của các nhân vật và đối tượng trong trò chơi.

Mặt khác, làm cho một cái gì đó chung chung đòi hỏi một sự đầu tư thời gian và nỗ lực trước mắt vào thiết kế cao hơn nhiều so với một cái gì đó rất cụ thể. Điều này chịu rủi ro của kỹ thuật quá mức, và thậm chí bị lạc trong các yêu cầu tiềm năng trong tương lai.

Luôn luôn đáng để xem nếu có một sự khái quát tự nhiên sẽ giúp bạn có một bước đột phá. Tuy nhiên, cuối cùng, đó là một câu hỏi về sự cân bằng, giữa nỗ lực mà bạn có thể dành bây giờ và nỗ lực mà bạn có thể cần trong tương lai.


3
  1. Hỗn hợp. Đây không phải là một hoặc / hoặc câu hỏi. Bạn có thể thiết kế API cho các chuyển đổi loại chung trong khi chỉ thực hiện chuyển đổi cụ thể mà bạn cần ngay bây giờ. (Chỉ cần đảm bảo rằng nếu ai đó gọi API chung của bạn bằng chuyển đổi không được hỗ trợ, thì nó không thành công với trạng thái lỗi "không được hỗ trợ".)

  2. Kiểm tra. Đối với chuyển đổi A-> B, tôi sẽ phải viết một (hoặc một số lượng nhỏ) các bài kiểm tra. Đối với một chuyển đổi x-> y chung, tôi có thể phải viết toàn bộ ma trận kiểm tra. Đó là công việc đáng kể hơn, ngay cả khi tất cả các chuyển đổi chia sẻ một triển khai chung chung.

    Mặt khác, nếu hóa ra là một cách chung để kiểm tra tất cả các chuyển đổi có thể, thì sẽ không có nhiều việc hơn và tôi có thể có xu hướng đi đến một giải pháp chung sớm hơn.

  3. Khớp nối. Bộ chuyển đổi từ A sang B có thể cần phải biết chi tiết triển khai về A và B (khớp nối chặt chẽ). Nếu A và B vẫn đang phát triển, điều này có nghĩa là tôi có thể phải tiếp tục xem lại trình chuyển đổi (và các thử nghiệm của nó), điều này thật tệ, nhưng ít nhất nó chỉ giới hạn ở A và B.

    Nếu tôi đi với một giải pháp chung chung mà cần truy cập vào các chi tiết của tất cả các loại, sau đó ngay cả khi D's tiến hóa của C và, tôi có thể cần phải giữ tinh chỉnh bộ chuyển đổi generic (và một loạt các xét nghiệm), có thể làm chậm tôi xuống thậm chí mặc dù không ai chưa cần phải chuyển đổi sang một C hoặc D .

    Nếu cả chuyển đổi chung và chuyển đổi cụ thể có thể được thực hiện theo cách chỉ được kết hợp lỏng lẻo với các chi tiết của các loại, thì tôi sẽ không lo lắng về điều này. Nếu một trong những điều đó có thể được thực hiện theo cách liên kết lỏng lẻo nhưng cách khác đòi hỏi sự liên kết chặt chẽ, thì đó là một lập luận mạnh mẽ cho phương pháp liên kết lỏng lẻo ngay ngoài cổng.


2
Kiểm tra là một điểm tốt. Đó là một lợi thế lớn nếu bạn thiết kế các giải pháp chung dựa trên các khái niệm từ lý thuyết danh mục , bởi vì sau đó bạn thường nhận được các định lý miễn phí chứng minh rằng việc triển khai duy nhất có thể cho một chữ ký (mà trình kiểm tra loại của trình biên dịch chấp nhận) là đúng , hoặc ít nhất là rằng nếu thuật toán hoạt động cho bất kỳ loại cụ thể nào thì nó cũng phải hoạt động cho tất cả các loại khác.
leftaroundabout

Tôi đoán rằng có một lý do cụ thể cho tên miền tại sao chỉ yêu cầu một loại chuyển đổi, nghĩa là hầu hết các chuyển đổi loại sẽ là hành động không hợp lệ trong miền sự cố và vì lý do đó, không nên được ứng dụng hỗ trợ cho đến khi chúng được hỗ trợ được chính thức cho phép. Câu trả lời này đến gần nhất với lập luận đó.
Ralf Kleberhoff

3

Giải pháp nên càng chung chung càng tốt hoặc càng cụ thể càng tốt?

Đó không phải là một câu hỏi có thể trả lời.

Điều tốt nhất bạn có thể nhận được một cách hợp lý là một vài phương pháp phỏng đoán để quyết định mức độ chung hoặc cụ thể để đưa ra một giải pháp nhất định. Làm việc thông qua một cái gì đó giống như quy trình dưới đây, thường là xấp xỉ bậc một là chính xác (hoặc đủ tốt). Khi không, lý do có thể là quá cụ thể theo miền để được đề cập chi tiết một cách hữu ích ở đây.

  1. Xấp xỉ bậc một: quy tắc YAGNI thông thường của ba như được mô tả bởi Daniel Pryden, Doc Brown, et al .

    Đây là một heuristic thường hữu ích vì có lẽ đó là cách tốt nhất bạn có thể làm mà không phụ thuộc vào tên miền và các biến khác.

    Vì vậy, giả định ban đầu là: chúng tôi làm điều cụ thể nhất.

  2. Xấp xỉ bậc hai: dựa trên kiến ​​thức chuyên môn của bạn về miền giải pháp , bạn nói

    Giải pháp "chung chung" trong trường hợp này đòi hỏi ít công việc hơn giải pháp "cụ thể"

    vì vậy chúng tôi có thể diễn giải lại YAGNI như khuyến nghị chúng tôi tránh làm việc không cần thiết , thay vì tránh sự chung chung không cần thiết. Vì vậy, chúng tôi có thể sửa đổi giả định ban đầu của chúng tôi và thay vào đó làm điều dễ dàng nhất.

    Tuy nhiên, nếu kiến ​​thức về miền giải pháp của bạn chỉ ra rằng giải pháp đơn giản nhất có khả năng mở ra nhiều lỗi hoặc khó kiểm tra đầy đủ hoặc gây ra bất kỳ vấn đề nào khác, thì việc viết mã dễ dàng hơn không nhất thiết là lý do đủ tốt để thay đổi lựa chọn ban đầu.

  3. Xấp xỉ bậc ba: kiến thức miền vấn đề của bạn cho thấy giải pháp đơn giản nhất thực sự chính xác hay bạn đang cho phép nhiều chuyển đổi mà bạn biết là vô nghĩa hay sai?

    Nếu giải pháp dễ nhưng chung chung có vấn đề hoặc bạn không tự tin vào khả năng phán đoán những rủi ro này, thì làm thêm và làm theo dự đoán ban đầu của bạn có lẽ tốt hơn.

  4. Xấp xỉ bậc bốn: kiến ​​thức của bạn về hành vi của khách hàng, hoặc tính năng này liên quan đến người khác như thế nào, hoặc ưu tiên quản lý dự án, hoặc ... bất kỳ cân nhắc kỹ thuật không nghiêm ngặt nào khác có làm thay đổi quyết định làm việc hiện tại của bạn không?


2

Đây không phải là một câu hỏi dễ trả lời với một câu trả lời đơn giản. Nhiều câu trả lời đã đưa ra các heuristic được xây dựng xung quanh quy tắc 3 hoặc một cái gì đó tương tự. Bước ra ngoài quy tắc như vậy là khó khăn.

Để thực sự trả lời câu hỏi của bạn, bạn phải xem xét rằng công việc của bạn rất có thể không thực hiện điều gì đó thay đổi A-> B. Nếu bạn là nhà thầu, có thể đó là yêu cầu, nhưng nếu bạn là nhân viên, bạn được thuê để thực hiện nhiều nhiệm vụ nhỏ hơn cho công ty. Thay đổi A-> B chỉ là một trong những nhiệm vụ đó. Công ty của bạn sẽ quan tâm đến việc những thay đổi trong tương lai có thể được thực hiện tốt như thế nào, ngay cả khi điều đó không được nêu trong yêu cầu. Để tìm "TheBestImcellenceation (tm)", bạn phải nhìn vào bức tranh lớn hơn về những gì bạn thực sự được yêu cầu, và sau đó sử dụng điều đó để diễn giải yêu cầu nhỏ mà bạn đã đưa ra để thay đổi A-> B.

Nếu bạn là một lập trình viên cấp thấp mới ra trường, bạn thường nên làm chính xác những gì bạn được bảo phải làm. Nếu bạn được thuê làm kiến ​​trúc sư phần mềm với 15 năm kinh nghiệm, bạn nên nghĩ về những điều lớn lao. Mọi công việc thực tế sẽ rơi vào đâu đó giữa "làm chính xác nhiệm vụ hẹp" và "nghĩ về bức tranh lớn". Bạn sẽ cảm thấy nơi công việc của bạn phù hợp với phổ đó nếu bạn nói chuyện với mọi người đủ và làm đủ việc cho họ.

Tôi có thể đưa ra một vài ví dụ cụ thể trong đó câu hỏi của bạn có câu trả lời dứt khoát dựa trên ngữ cảnh. Hãy xem xét trường hợp bạn đang viết phần mềm quan trọng an toàn. Điều này có nghĩa là bạn có một nhóm thử nghiệm đứng lên để đảm bảo sản phẩm hoạt động như đã hứa. Một số trong các nhóm thử nghiệm này được yêu cầu kiểm tra mọi đường dẫn có thể thông qua mã. Nếu bạn nói chuyện với họ, bạn có thể thấy rằng nếu bạn khái quát hành vi, bạn sẽ thêm 30.000 đô la vào chi phí thử nghiệm của họ vì họ sẽ phải kiểm tra tất cả các đường dẫn bổ sung đó. Trong trường hợp đó, không thêm chức năng tổng quát, ngay cả khi bạn phải sao chép công việc 7 hoặc 8 lần vì nó. Tiết kiệm tiền của công ty và làm chính xác những gì yêu cầu đã nêu.

Mặt khác, hãy xem xét rằng bạn đang tạo API để cho phép khách hàng truy cập dữ liệu trong chương trình cơ sở dữ liệu mà công ty bạn thực hiện. Một khách hàng yêu cầu cho phép thay đổi A-> B. API thường có một khía cạnh của còng tay vàng đối với chúng: một khi bạn thêm chức năng vào API, bạn thường không cần phải xóa chức năng đó (cho đến số phiên bản chính tiếp theo). Nhiều khách hàng của bạn có thể không sẵn sàng trả chi phí nâng cấp lên số phiên bản chính tiếp theo, vì vậy bạn có thể bị mắc kẹt với bất kỳ giải pháp nào bạn chọn trong một thời gian dài. Trong trường hợp này, tôi đánh giá cao khuyên bạn nên tạo các giải pháp chung chung từ đầu. Bạn thực sự không muốn phát triển một API xấu có đầy đủ các hành vi một lần.


1

Hmm ... không có nhiều bối cảnh để tiếp tục cho một câu trả lời ... lặp lại câu trả lời trước đó, "Nó phụ thuộc".

Theo một nghĩa nào đó, bạn phải rút lại kinh nghiệm của bạn. Nếu không phải của bạn, thì ai đó cao cấp hơn trong miền. Bạn có thể ngụy biện về những gì các tiêu chí chấp nhận nêu. Nếu đó là thứ gì đó dọc theo dòng 'người dùng sẽ có thể thay đổi loại từ "A" thành "B"' so với 'người dùng sẽ có thể thay đổi loại từ giá trị hiện tại thành bất kỳ giá trị thay thế được phép nào'.

Các tiêu chí chấp nhận thường xuyên là đối tượng để giải thích, nhưng nhân viên QA giỏi có thể viết các tiêu chí phù hợp với nhiệm vụ trong tay, giảm thiểu việc giải thích cần thiết.

Có giới hạn tên miền nào không cho phép thay đổi từ "A" sang "C" hoặc bất kỳ tùy chọn nào khác, nhưng chỉ "A" thành "B" không? Hay đây chỉ là một yêu cầu cụ thể hẹp mà không phải là "suy nghĩ chuyển tiếp"?

Nếu trường hợp chung khó khăn hơn tôi sẽ hỏi trước khi bắt đầu công việc, nhưng trong trường hợp của bạn nếu tôi có thể 'dự đoán' rằng các yêu cầu thay đổi 'loại' khác sẽ đến trong tương lai, tôi sẽ bị cám dỗ: a) viết một cái gì đó có thể tái sử dụng cho trường hợp chung và b) bọc nó trong một điều kiện chỉ cho phép A -> B bây giờ.

Đủ dễ dàng để xác minh cho trường hợp hiện tại trong thử nghiệm tự động và đủ dễ dàng để mở ra các tùy chọn khác sau này nếu / khi các trường hợp sử dụng khác nhau phát sinh.


1

Đối với tôi, một hướng dẫn mà tôi đã thiết lập cách đây một thời gian là: "Đối với các yêu cầu giả định chỉ viết mã giả thuyết". Đó là - nếu bạn dự đoán các yêu cầu bổ sung, bạn nên suy nghĩ một chút về cách triển khai chúng và cấu trúc mã hiện tại của bạn để nó không chặn theo cách đó.

Nhưng đừng viết mã thực tế cho những thứ này ngay bây giờ - chỉ cần suy nghĩ một chút về những gì bạn làm. Nếu không, bạn thường sẽ khiến mọi thứ trở nên phức tạp không cần thiết và có thể sẽ bị làm phiền sau này khi các yêu cầu thực tế khác với những gì bạn dự đoán.

Bốn ví dụ của bạn: nếu bạn có tất cả các cách sử dụng phương thức chuyển đổi dưới sự kiểm soát của mình, bạn có thể gọi nó là convertAToB ngay bây giờ và lên kế hoạch sử dụng "tái cấu trúc phương thức" trong IDE để đổi tên nếu bạn cần thêm chức năng chung sau này. Tuy nhiên, nếu phương thức chuyển đổi là một phần của API công khai, thì điều này có thể hoàn toàn khác: việc cụ thể đó sẽ chặn việc khái quát hóa sau này, vì thật khó để đổi tên mọi thứ trong trường hợp đó.


0

Tôi luôn nghe rằng một nhà phát triển giỏi nên cố gắng lường trước sự thay đổi và thiết kế hệ thống để dễ dàng mở rộng trong tương lai,

Về nguyên tắc, có. Nhưng điều này không nhất thiết dẫn đến các giải pháp chung chung.

Có hai loại chủ đề trong phát triển phần mềm, theo như tôi quan tâm, nơi bạn nên dự đoán sự thay đổi trong tương lai:

  • Thư viện dự định sẽ được sử dụng bởi các bên thứ 3 và
  • kiến trúc phần mềm tổng thể.

Trường hợp đầu tiên được giải quyết bằng cách xem sự gắn kết / khớp nối của bạn, tiêm phụ thuộc hoặc bất cứ điều gì. Trường hợp thứ hai là ở mức độ trừu tượng hơn, ví dụ: chọn một kiến ​​trúc hướng dịch vụ thay vì một khối mã đơn sắc lớn cho một ứng dụng lớn.

Trong trường hợp của bạn, bạn đang yêu cầu một giải pháp cụ thể cho một vấn đề cụ thể, không có tác động có thể thấy trước nào trong tương lai. Trong trường hợp này, YAGNI và DRY là phương châm tốt để chụp:

  • YAGNI (bạn sẽ không cần nó) bảo bạn thực hiện những thứ cơ bản, tối thiểu mà bạn cần và sử dụng ngay bây giờ . Điều này có nghĩa là triển khai mức tối thiểu làm cho bộ thử nghiệm hiện tại của bạn chuyển từ màu đỏ sang màu xanh lá cây, nếu bạn nên sử dụng phát triển kiểu TDD / BDD / FDD. Không một dòng nào nữa.
  • DRY (không lặp lại chính mình) có nghĩa là nếu bạn gặp lại một vấn đề tương tự, thì bạn hãy xem xét kỹ xem bạn có cần một giải pháp chung chung hay không.

Kết hợp với các thực tiễn hiện đại khác (như bảo hiểm thử nghiệm tốt để có thể tái cấu trúc một cách an toàn) điều này có nghĩa là bạn kết thúc với mã được viết nhanh, nạc, có nghĩa là phát triển khi cần.

mà âm thanh như một giải pháp chung là cách để đi?

Không, có vẻ như bạn nên có môi trường lập trình, ngôn ngữ và công cụ để giúp tái cấu trúc dễ dàng và thú vị khi bạn cần. Các giải pháp chung không cung cấp điều đó; họ tách ứng dụng khỏi miền thực tế.

Hãy xem các ORM hoặc khung MVC hiện đại, ví dụ Ruby on Rails; ở cấp độ ứng dụng, tất cả tập trung vào làm công việc không chung chung. Các thư viện đường ray rõ ràng là gần như 100% chung, nhưng mã miền (mà câu hỏi của bạn là về) nên được thực hiện tối thiểu các shenanigans trong khía cạnh đó.


0

Một cách khác để suy nghĩ về vấn đề là xem xét những gì có ý nghĩa.

Ví dụ, có ứng dụng tôi đang phát triển có các phần gần như tương tự nhưng có các quy tắc cho phép không nhất quán. Vì không có lý do gì để giữ chúng khác nhau, khi tôi tái cấu trúc phần đó, tôi đã khiến tất cả chúng thực hiện các quyền theo cùng một cách. Việc làm cho mã tổng thể nhỏ hơn, đơn giản hơn và giao diện phù hợp hơn.

Khi quản lý quyết định cho phép người khác truy cập vào một tính năng, chúng tôi có thể làm điều đó bằng cách thay đổi cờ.

Rõ ràng nó có ý nghĩa để thực hiện chuyển đổi loại cụ thể. Liệu nó cũng có ý nghĩa để thực hiện chuyển đổi loại bổ sung?

Hãy ghi nhớ, nếu giải pháp chung nhanh hơn để thực hiện, thì trường hợp apecific cũng dễ dàng, chỉ cần kiểm tra xem đó là chuyển đổi loại duy nhất bạn đang cho phép.

Nếu ứng dụng nằm trong khu vực được quy định cao (ứng dụng y tế hoặc tài chính), hãy cố gắng lôi kéo nhiều người hơn vào thiết kế của bạ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.