Giải pháp đơn giản so với phức tạp (nhưng hiệu quả hiệu quả) - nên chọn cái nào và khi nào?


28

Tôi đã lập trình được một vài năm và thường thấy mình rơi vào tình huống khó xử.

Có hai giải pháp -

  • một là đơn giản một nghĩa là cách tiếp cận đơn giản, dễ hiểu và dễ bảo trì hơn. Nó liên quan đến một số dự phòng, một số công việc phụ (thêm IO, xử lý thêm) và do đó không phải là giải pháp tối ưu nhất.
  • nhưng khác sử dụng một cách tiếp cận phức tạp, khó thực hiện, thường liên quan đến sự tương tác giữa nhiều mô-đun và là một giải pháp hiệu quả hiệu quả.

Giải pháp nào tôi nên phấn đấu khi tôi không có SLA hiệu suất cao để đáp ứng và ngay cả giải pháp đơn giản cũng có thể đáp ứng SLA hiệu suất? Tôi đã cảm thấy khinh thường các nhà phát triển đồng nghiệp của tôi cho giải pháp đơn giản.

Có phải là một thực hành tốt để đưa ra giải pháp phức tạp tối ưu nhất nếu SLA hiệu suất của bạn có thể được đáp ứng bằng một giải pháp đơn giản?


10
xem: Làm cách nào để tránh Trực giác Tối ưu hóa xấu của Nhà phát triển? "Thật không may, các nhà phát triển thường có trực giác khủng khiếp về việc các vấn đề về hiệu năng trong ứng dụng thực sự sẽ xảy ra ở đâu ...."
gnat

1
"Không phải là tối ưu nhất" vẫn sẽ "đủ tốt" chứ? Sau đó ở lại với điều đó.

8
Vâng. " Le mieux est l'ennemi du bien. " Voltaire. ("Hoàn hảo là kẻ thù của điều tốt.") Đủ tốt là đủ tốt - cho đến khi thử nghiệm hiệu suất nói khác đi.
David Hammen

Tôi thấy rằng (nói chung) đơn giản ngụ ý hiệu quả. Vì vậy, thường không cần phải thỏa hiệp.
Dan

2
Có vẻ như sự hoàn hảo đạt được không phải khi không còn gì để thêm, mà là khi không còn gì để loại bỏ
.iết

Câu trả lời:


58

Giải pháp nào tôi nên phấn đấu khi tôi không có SLA hiệu suất cao để đáp ứng và ngay cả giải pháp đơn giản cũng có thể đáp ứng SLA hiệu suất?

Cái đơn giản. Nó đáp ứng thông số kỹ thuật, dễ hiểu hơn, dễ bảo trì hơn và có lẽ nó ít lỗi hơn rất nhiều.

Những gì bạn đang làm trong việc ủng hộ giải pháp hiệu quả hiệu suất là giới thiệu tính tổng quát đầu cơ và tối ưu hóa sớm vào mã của bạn. Đừng làm thế! Hiệu suất đi ngược lại với tất cả các kỹ thuật phần mềm khác, "tính bất hợp pháp" có (độ tin cậy, khả năng bảo trì, khả năng đọc, khả năng kiểm tra, tính dễ hiểu, ...). Theo đuổi hiệu suất khi kiểm tra chỉ ra rằng thực sự cần phải theo đuổi hiệu suất.

Đừng theo đuổi hiệu suất khi hiệu suất không thành vấn đề. Ngay cả khi nó có vấn đề, bạn chỉ nên theo đuổi hiệu suất trong những khu vực mà thử nghiệm chỉ ra rằng một nút cổ chai hiệu năng tồn tại. Đừng để vấn đề hiệu năng là cái cớ để thay thế simple_but_slow_method_to_do_X()bằng phiên bản nhanh hơn nếu phiên bản đơn giản đó không hiển thị dưới dạng nút cổ chai.

Hiệu suất nâng cao gần như chắc chắn bị vướng bận với một loạt các vấn đề về mùi mã. Bạn đã đề cập đến một số câu hỏi: Một cách tiếp cận phức tạp, khó thực hiện, khớp nối cao hơn. Là những người thực sự có giá trị kéo vào?


câu trả lời của bạn rất hữu ích
MoveFast

1
Càng đơn giản càng tốt, nhưng không đơn giản hơn; Nhanh nhất có thể, nhưng không nhanh hơn; v.v.
user606723

2
"Khi nghi ngờ, hãy sử dụng vũ lực";)
tdammers

Nhận xét trong mã có thể là cả cathartic và hữu ích ở đây. Một nhận xét nhỏ chỉ ra giải pháp phức tạp + nhanh và tại sao bạn không sử dụng nó, có thể cho phép bạn cảm thấy ít hơn như bạn đã bỏ qua thuật toán tối ưu. Và nó có thể giúp người bảo trì hiểu sự lựa chọn của bạn và chỉ cho họ đi đúng hướng nếu tối ưu hóa thực sự cần thiết sau này.
TheAtomicOption

12

Trả lời ngắn: Thích các giải pháp đơn giản hơn phức tạp và ghi nhớ các nguyên tắc KISS và YAGNI

Bởi vì các yêu cầu dự án ban đầu và phần mềm không bao giờ hoàn hảo, nó yêu cầu thay đổi khi ứng dụng được phát triển / sử dụng. Cách tiếp cận lặp lại trong các giai đoạn phát triển là một kết hợp rất tốt để bắt đầu mọi thứ đơn giản và mở rộng nó khi cần thiết. Các giải pháp đơn giản nhất có chỗ cho sự linh hoạt và dễ bảo trì hơn.

Ngoài ra, cố gắng trở nên thông minh và đặt một số tối ưu hóa bổ sung trong khi vẫn xây dựng ứng dụng của bạn không phải là một cách thực hành tốt và có thể làm phức tạp hóa giải pháp của bạn. Như đã biết, "premature optimization is the root of all evil"- từ cuốn sách của Knuth


1
@ManojGumber, không có vấn đề gì và nó thực sự là điều cốt yếu mà chúng tôi là lập trình viên nên quan tâm ngay từ đầu.
EL Yusubov

8

Lấy một bài học từ Knuth ở đây: "Chúng ta nên quên đi những hiệu quả nhỏ, nói khoảng 97% thời gian: tối ưu hóa sớm là gốc rễ của mọi tội lỗi".

Hãy suy nghĩ về các giải pháp của bạn theo thứ tự này: Đầu tiên, luôn luôn, chính xác. Thứ hai, cải thiện sự rõ ràng và đơn giản. Thứ ba, và chỉ khi bạn có thể chứng minh sự cần thiết, hiệu quả.

Thêm hiệu quả sẽ hầu như luôn luôn chi phí cho bạn một cái gì đó quan trọng, và vì vậy chỉ nên được theo đuổi khi bạn biết bạn cần.


4
Lưu ý rằng điều này không có nghĩa là bạn không nên viết một triển khai tốt ngay từ đầu.

@ ThorbjørnRavnAndersen: tất nhiên, đó là những gì hai điểm đầu tiên nói về.
simon

1
@simon trích dẫn thường được sử dụng như một cái cớ để chọn một cách

Về điểm thứ hai của bạn: Tôi có một đồng nghiệp, người thường xuyên nói rằng anh ta thích mã sạch và cấu trúc không chính xác trước khi ăn mì spaghetti đúng.
Buhb

@ ThorbjørnRavnAndersen những người không đủ năng lực sẽ sử dụng bất cứ điều gì cho một lý do. Không có bất kỳ tác động nào đến giá trị của suy nghĩ ban đầu.
simon

7

Đơn giản là điều kiện tiên quyết của độ tin cậy . Nếu bạn có một giải pháp đơn giản mà hiệu quả, bằng mọi cách hãy tìm nó! Việc tối ưu hóa một chương trình làm việc sẽ dễ dàng hơn nhiều so với việc làm cho một chương trình được tối ưu hóa hoạt động. Cũng đừng quên luật của Moore : nếu giải pháp đơn giản của bạn đáp ứng các mục tiêu hiệu suất ngày hôm nay, nó có thể sẽ nghiền nát họ 1 trong một hoặc hai năm.


1 Không có gì đảm bảo ở đó, vì như Jimmy Hoffa đã lưu ý trong bình luận của mình dưới đây, luật của Moore có giới hạn của nó.


Bạn đã quên về luật khác của Moore, trong đó nêu rõ, "Rất tiếc, về luật đầu tiên của tôi .." Xin lỗi ông chủ, luật của Moore không còn nữa (chơi chữ trừng phạt). Tôi không đồng ý với quan điểm còn lại của bạn, tôi sẽ chỉ nói ít nhất là phần cuối cùng ở đó.
Jimmy Hoffa

2
Xin lỗi, nhưng trong tất cả kinh nghiệm của tôi trong ngành công nghiệp này. "Bộ công việc" đang tăng FAR nhanh hơn tốc độ phần cứng của chúng tôi, được nâng cấp liên tục. Thực sự, tôi sẽ chỉ loại bỏ điểm luật của Moore.
dùng606723

@ user606723 Sự tăng trưởng của điểm "tập hợp công việc" là trực giao cho câu hỏi "tối ưu hóa hay đơn giản": khối lượng công việc sẽ bắt kịp với họ bất kể họ thực hiện giải pháp nào. Quan điểm đưa luật của Moore vào hỗn hợp là chỉ ra rằng ngay cả khi giải pháp đơn giản chịu áp lực hiệu suất tại thời điểm viết, áp lực sẽ giảm khi phần cứng nhanh hơn có sẵn.
dasblinkenlight

@dasblinkenlight, sự tăng trưởng của workset không trực giao với câu hỏi hơn luật của moore. Vấn đề khiến vấn đề trở nên khó khăn là nếu một giải pháp đơn giản chịu áp lực hiệu năng tại thời điểm phát hành, hiệu suất sẽ không đủ trong tương lai rất gần vì workset ngày càng phá hủy mọi cải tiến hiệu suất đạt được nhờ phần cứng được cải thiện. Mặc dù tôi chỉ dành cho phần mềm đơn giản, đáng tin cậy và có thể bảo trì, nhưng việc phát hành phần mềm đã chịu áp lực về hiệu suất khi phát hành và mong đợi luật pháp của moore thậm chí là một triết lý tồi tệ.
dùng606723

3

Có phải là một thực hành tốt để đưa ra giải pháp phức tạp tối ưu nhất nếu SLA hiệu suất của bạn có thể được đáp ứng bằng một giải pháp đơn giản?

Tối ưu là một từ mơ hồ!

Cuối cùng, nếu có nhiều rủi ro trong việc phải duy trì cái phức tạp, và nếu cái đơn giản là "đủ tốt" thì tôi luôn luôn đứng về phía người đơn giản.

Thêm vào bất kỳ rủi ro nào về sự phức tạp không đủ tốt, thì KISS có lẽ là câu trả lời đúng.


2

Tôi thích cái đơn giản hơn. Theo tôi, việc tối ưu hóa sớm gây ra nhiều vấn đề như họ giải quyết. Trong nhiều trường hợp, thiết kế tốt cho phép bạn thay đổi các triển khai đã cho trong tương lai, nếu chúng trở thành nút cổ chai.

Vì vậy, ở điểm mấu chốt - tôi sẽ thiết kế nó linh hoạt nhất có thể, nhưng sẽ không hy sinh sự đơn giản vì tính linh hoạt quá nhiều.


2

Cái nào giá rẻ hơn?

Hầu hết thời gian, một giải pháp đơn giản chậm hơn một chút sẽ hoàn toàn chấp nhận được về mặt hiệu suất và sự đơn giản giúp cho việc phát triển, bảo trì và cuối cùng thay thế rẻ hơn.

Mặt khác, đôi khi tốc độ thực sự quan trọng và lợi ích tài chính đến từ những cải tiến tốc độ nhỏ thậm chí có thể lớn hơn nhiều so với chi phí gia tăng của một giải pháp phức tạp hơn. Ví dụ, cạo 0,01 giây để hoàn thành giao dịch có thể giúp hệ thống giao dịch chứng khoán có lợi hơn nhiều. Cải thiện 10% về hiệu quả của một hệ thống hỗ trợ vài triệu người dùng có thể đồng nghĩa với việc giảm đáng kể chi phí máy chủ.

Vì vậy, câu hỏi bạn phải tự hỏi mình là: Liệu sử dụng giải pháp phức tạp có đủ tác động đến điểm mấu chốt để trả cho chi phí bổ sung của nó không? Trên thực tế, có lẽ bạn nên yêu cầu khách hàng của mình quyết định vì họ đang trả các hóa đơn và gặt hái những lợi ích tiềm năng. Một lựa chọn tốt là đi trước với giải pháp đơn giản và đưa ra giải pháp phức tạp hơn như một sự cải tiến có thể. Điều đó cho phép bạn khởi động hệ thống của mình và cung cấp cho khách hàng của bạn một thứ gì đó để bắt đầu thử nghiệm và kinh nghiệm đó có thể cho biết quyết định thực hiện (hoặc không triển khai) giải pháp phức tạp hơn.


2

Khi đánh giá hai cách tiếp cận, một cách đơn giản hơn nhưng kém hiệu quả hơn trong khi phương pháp khác phức tạp hơn và hiệu quả hơn, người ta phải xem xét vấn đề và miền dự án.

Hãy xem xét một dự án phần mềm trị giá hàng tỷ đô la cho ngành chăm sóc sức khỏe đã lên kế hoạch trọn đời trong hơn 15 năm bảo trì và hơn 20 năm sử dụng. Trong một hiệu suất dự án như vậy chắc chắn sẽ không phải là một mối quan tâm, nhưng sự phức tạp và cấu trúc dự án có thể gây ra vấn đề lớn cho việc bảo trì dự án, kéo dài tối thiểu 15 năm. Bảo trì và đơn giản đến trước bất cứ điều gì.

Sau đó, xem xét một ví dụ khác. Một công cụ trò chơi console được cho là sẽ cung cấp năng lượng cho các trò chơi sắp tới của công ty trong hơn 5 năm tới. Bởi vì các trò chơi là các chương trình cực kỳ hạn chế về tài nguyên, hiệu quả đi trước khả năng bảo trì trong nhiều trường hợp. Viết các cấu trúc dữ liệu và thuật toán rất cụ thể của riêng bạn cho một số tác vụ có thể rất quan trọng ngay cả khi nó đi ngược lại bất kỳ "thực tiễn tốt nhất" nào về phát triển phần mềm. Một ví dụ điển hình cho điều này có thể là Thiết kế hướng dữ liệu trong đó bạn lưu trữ dữ liệu của mình trong các mảng dữ liệu tương tự, thay vì trong các đối tượng thực tế. Điều này là để tăng tham chiếu của địa phương và do đó tăng hiệu quả bộ đệm CPU. Không thực tế, nhưng rất quan trọng trong lĩnh vực nhất định.


1

Đây luôn là một câu hỏi khó và tôi thấy các câu trả lời xoay theo một chiều, vì vậy tôi sẽ chơi trò chơi cho phía bên kia, mặc dù tôi không khẳng định câu trả lời nào là đúng, đây là một chủ đề rất tình huống và mềm mại.

Một điều về một giải pháp phức tạp nhưng hiệu suất cao là bạn luôn có thể ghi lại những điều chưa từng thấy từ nó. Tôi nói chung là một người hâm mộ mã tự viết tài liệu, nhưng tôi cũng là một người hâm mộ phần mềm phản hồi trong một khoảng thời gian khiến tôi cảm thấy như nó không làm tôi chậm lại. Nếu bạn thực hiện với giải pháp phức tạp nhưng hiệu suất cao, hãy xem xét những gì bạn có thể làm để làm cho nó không quá tệ:

Gói nó trong một giao diện, đặt nó trong một hội đồng riêng, thậm chí có thể là một quá trình tất cả những gì nó sở hữu. Làm cho nó càng lỏng lẻo càng tốt với một bức tường trừu tượng càng dày càng tốt để tránh rò rỉ . Viết nhiều bài kiểm tra đơn vị cho nó để lưu hồi quy trong tương lai.

Tài liệu nó trong mã, thậm chí xem xét viết một số tài liệu thực sự. Hãy suy nghĩ về các cấu trúc dữ liệu phức tạp và cách chúng được ghi lại, hãy tưởng tượng cố gắng hiểu việc thực hiện một trong số chúng từ mã mà không có bài viết về sách / wikipedia cấu trúc dữ liệu để giải thích nó. Tuy nhiên, tất cả chúng ta đều chấp nhận rằng các cấu trúc dữ liệu phức tạp này thực tế là những điều tốt và thật có lợi khi ai đó đã thực hiện chúng bằng ngôn ngữ của chúng ta.

Hãy nhớ rằng tất cả chúng ta đều gửi tin nhắn trên ngăn xếp TCP / IP có khả năng gây phiền nhiễu như mã có thể nhận được nếu bất kỳ ai trong chúng ta nhìn vào nó, vì vậy nó thực hiện theo cách mà tất cả chúng ta cũng yêu cầu. Có lẽ vấn đề của bạn không yêu cầu mức độ tối ưu hóa này, có lẽ là có, nhưng hãy cẩn thận khi giải quyết câu hỏi này vì tất cả chúng ta thỉnh thoảng phải có: Có những con rồng ở đó.


0

Tôi đang đến đây làm việc ở những khu vực không có SLA hiệu suất. Khi nói đến trình kết xuất ngoại tuyến trong đồ họa máy tính, không có "hiệu suất thỏa đáng" cho người dùng, vì họ đã bỏ ra số tiền khổng lồ để phân phối điện toán trên các đám mây và kết xuất trang trại ngay cả với trình kết xuất hiện đại để tạo ra hình ảnh và khung chất lượng sản xuất cho phim, vd

Nhưng tôi phải nói rằng một người làm việc trong lĩnh vực này trong nhiều năm rằng bất kỳ giải pháp nào làm giảm đáng kể khả năng bảo trì có lợi cho hiệu quả thực sự đang hoạt động chống lại các yêu cầu hiệu suất luôn thay đổi. Bởi vì nếu bạn không thể duy trì hiệu quả giải pháp của mình trong nhiều năm tới vì mọi thứ đang thay đổi dưới chân bạn (cả về mã xung quanh và những gì người dùng mong đợi khi các đối thủ cạnh tranh tốt hơn nhau), thì giải pháp của bạn đã hoạt động theo hướng lỗi thời và trong cần thay thế bán buôn.

Tôi không thấy mục đích cuối cùng của các trình biên dịch như VTune là cách để làm cho mã của tôi chạy nhanh hơn. Giá trị cuối cùng của chúng là đảm bảo rằng tôi không làm giảm năng suất của mình để đáp ứng nhu cầu hiệu suất ngày càng leo thang. Nếu tôi hoàn toàn phải áp dụng một số tối ưu hóa vi mô trông có vẻ thô thiển, thì trình lược tả, kết hợp với việc chạy nó với các trường hợp người dùng trong thế giới thực (và không phải là một trường hợp thử nghiệm nào đó tôi tưởng tượng thể quan trọng), hãy chắc chắn rằng tôi áp dụng một cách chắc chắn như vậy tối ưu hóa rất, rất thận trọng đối với chỉ các điểm nóng hàng đầu xuất hiện cũng như ghi chép rất cẩn thận vì tôi chắc chắn sẽ phải xem lại và duy trì và điều chỉnh và thay đổi chúng trong những năm tiếp theo nếu giải pháp đó vẫn khả thi.

Và đặc biệt nếu giải pháp tối ưu hóa của bạn liên quan đến nhiều khớp nối hơn, thì tôi thực sự không muốn sử dụng nó. Trong số các số liệu có giá trị nhất mà tôi đã đánh giá cao trong các lĩnh vực quan trọng nhất về hiệu năng của cơ sở mã là tách rời (như để giảm thiểu lượng thông tin cần phải làm việc, điều này cũng giảm thiểu khả năng nó cần thay đổi trừ khi nó cần thay đổi trực tiếp ), bởi vì những khu vực quan trọng đó nhân lên đáng kể lý do cho những thứ thay đổi. Điều đó có nghĩa là càng ít thông tin cần phải hoạt động, càng ít lý do để thay đổi và giảm thiểu lý do thay đổi thực sự là một phần rất lớn trong việc cải thiện năng suất trong các lĩnh vực tập trung cụ thể của tôi vì dù sao mọi thứ sẽ phải thay đổi liên tục (chúng tôi Sẽ trở nên lỗi thời trong một năm nếu không),

Đối với tôi, các giải pháp tốt nhất và hiệu quả nhất mà tôi đã tìm thấy là những giải pháp mà hiệu quả và khả năng duy trì và năng suất không đối nghịch nhau. Nhiệm vụ đối với tôi là cố gắng làm cho các khái niệm này hài hòa như người ta có thể làm cho 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.