Tại sao tốt hơn cho một lập trình viên để thiết kế thuật toán trước khi bắt đầu viết mã?


12

Liệu một thuật toán thích hợp thực sự giúp cải thiện chất lượng và cuối cùng là hiệu quả của một chương trình?

Chúng ta vẫn có thể tạo ra một chương trình chất lượng tốt mà không cần thuật toán?

Là một thuật toán thích hợp là PHẢI trong lập trình hiện đại?


5
Theo định nghĩa, có một số thuật toán, ngay cả khi nó quá tệ, nó vẫn tốt .

5
Tôi không có lựa chọn nào khác ngoài việc viết mã thay vì suy nghĩ quá nhiều. Hầu hết thời gian không có thuật toán vinh quang theo bất kỳ tiêu chuẩn nào; Tôi chỉ đang cố gắng đánh bóng một bãi cỏ hôi thối;)
Công việc

13
Tôi không thể tin rằng đây là một câu hỏi nghiêm túc. Xem en.wikipedia.org/wiki/Alacticm
Steven A. Lowe

2
Tiêu đề là hợp lý, nhưng văn bản của câu hỏi ít như vậy. Tôi nghĩ rằng anh ta hỏi liệu thuật toán có phải được đóng đinh trước khi người ta có thể bắt đầu viết mã thực tế hay không.
Greg

9
Tôi nói không ... tốt hơn hết là lái xe xung quanh một cách vô mục đích cho đến khi bạn vô tình tìm thấy đích đến của mình hoặc hết xăng.
jmq

Câu trả lời:


29

Tôi nghĩ rằng câu hỏi này cầu xin một số quan điểm lịch sử.

Quay lại "thời xa xưa" (trong đó tôi không phải là nhân chứng cá nhân, vì vậy đây chỉ là sự tái tạo của tôi trong thời đại đó - hãy thoải mái sửa chữa cho tôi nếu bạn trải nghiệm những điều khác biệt) Không gian và hiệu suất của CT không bằng so với ngày nay. Vì vậy, mọi thứ mọi người viết sau đó phải rất hiệu quả. Do đó, họ cần phải suy nghĩ rất nhiều và nghiên cứu để phát minh ra các thuật toán tốt nhất để đạt được hiệu suất không gian / thời gian cần thiết để hoàn thành công việc. Một yếu tố khác trong đó là các nhà phát triển chủ yếu làm việc trên những gì bạn có thể gọi là cơ sở hạ tầng : hệ điều hành, ngăn xếp giao thức, trình biên dịch, trình điều khiển thiết bị, trình soạn thảo, v.v ... Tất cả những điều này được sử dụng rất nhiều bởi mọi người, vì vậy hiệu suất thực sự tạo ra sự khác biệt .

Ngày nay, chúng ta tha hồ có CTNH đáng kinh ngạc với bộ xử lý đa lõi và bộ nhớ Gigabyte ngay cả trong một máy tính xách tay cơ bản (quái, thậm chí trong điện thoại di động). Điều đó có nghĩa tự nhiên là trong nhiều trường hợp, hiệu suất - do đó là thuật toán - không còn là vấn đề chính, và điều quan trọng là cung cấp giải pháp nhanh hơn là cung cấp giải pháp nhanh. OTOH chúng tôi có rất nhiều khung công tác giúp chúng tôi giải quyết các vấn đề và đóng gói một số lượng lớn các thuật toán cùng một lúc. Vì vậy, ngay cả khi chúng ta không nghĩ về các thuật toán, chúng ta rất có thể đang sử dụng rất nhiều trong số chúng trong nền.

Tuy nhiên, vẫn có những lĩnh vực mà hiệu suất quan trọng. Trong các lĩnh vực này, bạn vẫn cần suy nghĩ rất nhiều về thuật toán của mình trước khi viết mã. Lý do là thuật toán là trung tâm của thiết kế, xác định rất nhiều cấu trúc dữ liệu và các mối quan hệ trong mã xung quanh. Và nếu bạn phát hiện quá muộn rằng thuật toán của bạn không mở rộng tốt (ví dụ: O (n 3 ) nên nó trông đẹp và nhanh khi bạn thử nghiệm nó trên 10 mục, nhưng trong thực tế, bạn sẽ có hàng triệu), nó rất khó, dễ bị lỗi và tốn thời gian để thay thế nó trong mã sản xuất. Và tối ưu hóa vi mô sẽ không giúp bạn nếu thuật toán cơ bản không phù hợp với công việc.


1
Thật là một câu trả lời. Đó là đặc quyền của tôi để có bạn ở đây !!!
Janner

5
Ngoài ra máy tính đắt hơn nhiều so với lập trình viên, vì vậy nó có ý nghĩa để làm cho lập trình viên làm việc chăm chỉ hơn!

2
Bạn đúng rằng những gì chúng tôi đang tối ưu hóa đã thay đổi. Nhưng bây giờ chúng tôi dự kiến ​​sẽ thao túng các hệ thống phức tạp hơn nhiều so với con người trước đây. Sự thiếu suy nghĩ về lập kế hoạch, tổ chức và bảo trì vẫn sẽ giết chết bạn.
btilly

1
@btilly, tôi đồng ý rằng việc lên kế hoạch trước là rất quan trọng (càng nhiều càng tốt - nhưng không hơn) và suy nghĩ về việc bảo trì trước. Tuy nhiên, điều này không nhất thiết có nghĩa là dành nhiều thời gian cho thiết kế thuật toán. Ví dụ: nếu một chức năng được chạy mỗi tháng một lần và mất một giờ để hoàn thành, thì có lẽ sẽ mất quá nhiều thời gian để điều chỉnh thuật toán, ngay cả khi bạn quản lý để giảm thời gian thực hiện xuống còn 10 phút. Những lợi ích sẽ không biện minh cho chi phí.
Péter Török

2
Hai điều: Thứ nhất, thuật toán có thể xác định mức độ quy mô của chương trình và điều đó thường rất quan trọng. Thứ hai, rất nhiều phần mềm được chạy song song trên các máy chủ hiện nay. Điều đó có nghĩa là, nếu chương trình Z được sửa đổi để chạy nhanh gấp đôi, thì bất cứ ai đang chạy nó đều cần một nửa số máy chủ Z.
David Thornley

14

Chỉ để chỉ ra một cái gì đó:

Một thuật toán tự nó là một giải pháp từng bước chung cho vấn đề của bạn. Vì vậy, nếu bạn giải quyết được vấn đề, thực tế bạn đã sử dụng một thuật toán.

Điểm quan trọng nhất ở đây là bạn phải sử dụng các thuật toán để giải quyết vấn đề, bằng cách này hay cách khác. Hầu hết thời gian nên suy nghĩ về vấn đề của bạn trước khi bạn chuyển sang viết mã - giai đoạn này thường được gọi là thiết kế. Nhưng, bao nhiêu và theo cách nào bạn sẽ làm điều này phụ thuộc vào bạn.

Ngoài ra, bạn không nên kết hợp khái niệm thuật toán với sơ đồ (tôi nghi ngờ điều này đang diễn ra ở đây). Lưu đồ chỉ là một biểu diễn đồ họa có thể được sử dụng và được sử dụng trong những ngày cũ để minh họa một thuật toán. Nó khá nhiều phản đối ngày nay.

BIÊN TẬP:

Thực sự có nhiều cách để biểu diễn một thuật toán và bản thân mã ngôn ngữ lập trình là một trong số đó. Tuy nhiên, khá thường xuyên sẽ tốt hơn hoặc dễ dàng hơn khi không giải quyết toàn bộ vấn đề cùng một lúc mà chỉ là một phác thảo và sau đó điền vào chỗ trống khi bạn đi.

  • Sở thích cá nhân của tôi ở đây là mã giả, và chỉ để trình bày một phác thảo trừu tượng chung về thuật toán được đề cập - thật lố bịch khi đi vào chi tiết với mã giả , đó là mã thực sự để làm gì.

  • Nhưng mã thực sự có thể được sử dụng cho các phác thảo. Ví dụ, người TDD thích thiết kế thuật toán khi họ viết mã và vì họ không thể giải quyết tất cả cùng một lúc, họ thiết kế một phác thảo về thực thi chương trình trong mã thực và sử dụng các đối tượng giả (hoặc hàm, phương thức .. .) như khoảng trống để được điền vào sau.

  • Các sơ đồ Hoạt động của UML dường như là một hiện thân của các sơ đồ kiểu cũ với ký hiệu bổ sung cho các công cụ mới như đa hình và đa luồng. Tôi thực sự không thể nói nó hữu ích như thế nào, vì tôi không thực sự sử dụng chúng nhiều - tôi chỉ đề cập đến nó cho đầy đủ.

  • Ngoài ra, nếu bạn dựa trên thuật toán của mình để chuyển đổi giữa các trạng thái, thì sơ đồ trạng thái khá hữu ích.

  • Nói chung, bất kỳ điều gì có nghĩa là bạn chỉ cần phác thảo ý tưởng đằng sau một thuật toán nhất định là một cách tốt để đi.


Có nhiều cách khác nhau để trình bày thuật toán của một người, bạn có đề xuất gì không? Và tại sao?
Janner

@Jervis: Xem cập nhật của tôi, tôi liệt kê một số trong số họ.
Goran Jovic

Liên kết đâu?
Janner

4

Một tương tự tốt là bạn phải biết một công thức trước khi bạn bắt đầu nấu ăn. Ok bạn có thể điều chỉnh nó khi bạn đi, nhưng bạn vẫn cần biết những gì bạn muốn làm trước khi bạn bắt đầu. Nếu tôi muốn làm món thịt cừu hầm, tôi sẽ làm những việc rất khác so với việc tôi muốn nướng một ổ bánh mì.


Thuật toán = ý tưởng ???
Janner

Thuật toán == công thức !!

Nhưng các đầu bếp khác nhau có cách nấu khác nhau theo cùng một công thức.
Janner

Chắc chắn, khi tôi nướng bánh mì, nó khác với khi vợ tôi nướng bánh mì. Nhưng các phần cơ bản là như nhau (bột, nước, men, muối)
Zachary K

cũng có những cửa hàng nơi bạn có thể đi mua một ổ bánh mì được làm bởi một thợ làm bánh chuyên nghiệp
jk.

3

Mã thực hiện các thuật toán. Cố gắng viết mã mà không thiết kế thuật toán cũng giống như thử vẽ một ngôi nhà trước khi các bức tường được xây dựng. Các thuật toán đã là "PHẢI" kể từ khi bắt đầu lập trình.


ĐỒNG Ý. Vẽ một ngôi nhà dễ dàng như ABC, bạn có thể bắt đầu lên kế hoạch mà không có sự tồn tại của ngôi nhà.
Janner

2
@Jervis: Tương tự như vậy, bạn có thể lập kế hoạch cho một số phần mã mà không chỉ định thuật toán cho các phần khác (ví dụ: bạn có thể quyết định sẽ có một chức năng sắp xếp dữ liệu mà không cần quyết định cách thức hoạt động - nhưng bạn cần quyết định theo thời gian viết mã phân loại).
Jerry Coffin

1
Tôi thích sự tương tự của việc vẽ một bức tranh hơn là vẽ một ngôi nhà. Nếu tất cả mã hóa của tôi giống như vẽ một ngôi nhà, tôi sẽ tìm một công việc khác. Và vẽ một bức tranh có thể được lặp đi lặp lại. Tôi thường bắt đầu tạo mẫu trong mã thực trước khi thuật toán hoàn toàn rõ ràng với tôi. Trên thực tế, thường xuyên nhất.
Greg

3

Thông thạo ngôn ngữ của bạn giúp cải thiện chất lượng và năng suất. Và giải quyết các vấn đề thuật toán nhỏ sẽ hữu ích hơn nhiều so với việc lặp lại cùng một công cụ MVC 100 lần.
Mặc dù, tôi cho rằng có nhiều cách khác để đạt được sự trôi chảy.

Thuật toán sẽ trở thành PHẢI trong lĩnh vực lập trình hiện đại?
Nó đã là 'phải', trừ khi bạn là một 'ninja ninja' viết 'codez tuyệt vời'. Tất cả các công ty 'tốt nhất' (Google, Amazon, v.v.) kiểm tra kinh nghiệm thuật toán của bạn khi phỏng vấn và tôi tưởng tượng họ sẽ không làm điều đó mà không có lý do.

Nhưng trở về điểm ban đầu, bạn nên liên tục thử thách bản thân nếu muốn cải thiện. Và vì các công việc bình thường (hay còn gọi là "bây giờ hãy viết các trình quản lý CRUD cho hơn 100 đối tượng") không phải lúc nào cũng cung cấp một thách thức tốt, các thuật toán bù đắp cho điều đó.


1

Tôi muốn nói rằng bạn cần ít nhất một ý tưởng ban đầu về thuật toán trước khi bạn bắt đầu viết mã. Bạn có thể sẽ sửa đổi ý tưởng của mình trong khi mã hóa dựa trên cấu trúc dữ liệu, v.v.

Sau đó, bạn có thể sửa lại mã một lần nữa nếu hồ sơ cho thấy có vấn đề về hiệu năng trong khu vực đó.


1

Lý do là nhanh hơn để sửa lỗi trước khi bạn viết mã nhầm.

Chính xác hơn, thường xuyên đo được 10 đến 1 chênh lệch năng suất giữa các lập trình viên khác nhau. Khi bạn nhìn vào các lập trình viên là những người có mức năng suất gấp 10 lần, họ dành phần nhỏ khoảng thời gian ngắn họ thực sự mã hóa. Thời gian để nhập mã không nên là nút cổ chai. Thay vào đó, họ dành phần lớn thời gian của mình để đảm bảo rằng họ có yêu cầu thẳng, lập kế hoạch, thử nghiệm, v.v.

Ngược lại, khi bạn nhìn vào các lập trình viên lặn vào mã hóa mà không tạm dừng, họ chắc chắn phải viết đi viết lại nhiều lần vì họ gặp phải những vấn đề hoàn toàn có thể thấy trước, và kết quả cuối cùng là ít bảo trì hơn và nhiều lỗi hơn. (Ngẫu nhiên bạn đã biết rằng trung bình 80% số tiền dành cho phát triển phần mềm đang trong giai đoạn bảo trì? Làm cho mọi thứ có thể duy trì được vấn đề. Rất nhiều.)


Bạn hoàn toàn đúng.
Janner

1

Nói chung các thuật toán và cấu trúc dữ liệu trước, mã sau. Nhưng nó phụ thuộc rất nhiều vào lĩnh vực lập trình. Tôi đã từng làm rất nhiều công cụ toán học ứng dụng, và thực sự nhìn xuống mô hình thác nước thịnh hành. Đó là bởi vì các thuật toán cấp thấp đến trung bình hiếm khi được coi là điều hiển nhiên. Thiết kế một cấu trúc lớn xung quanh sự tồn tại của các hệ thống con không được cấp phép, sau đó phát hiện muộn trong trò chơi rằng toán học cho một trong những hệ thống con quan trọng đó không hoạt động (không ổn định hoặc bất cứ điều gì). Vì vậy, tôi luôn nghĩ về các chương trình con thử thách nhất trước tiên và nếu có bất kỳ lý do nào để nghi ngờ, tôi đã viết và đơn vị đã thử nghiệm chúng trước. Nhưng, đối với một số miền có vấn đề, bạn chỉ có thể cày trước mà không có nhiều kế hoạch.


Tôi đồng ý với bạn.
Janner

Bạn đang nói ở đây về sự khác biệt giữa thiết kế từ trên xuống và từ dưới lên, đây là một vấn đề khác. Khi bạn "chỉ cày trước", bạn vẫn đang thực hiện một thuật toán nào đó. Bạn có thể không nghĩ về nó theo các thuật ngữ đó, có lẽ vì thuật toán có vẻ rõ ràng đối với bạn hoặc vì bạn đã rất quen thuộc với vấn đề này, nhưng điều đó không có nghĩa là thuật toán vẫn không còn.
Caleb

0

Thiết kế một thuật toán trong các phần, sau đó phân chia các phần đó và mã từng phần một. Bằng cách đó bạn có thể kết hợp cả hai quan điểm:

  1. Sử dụng khả năng ngôn ngữ của bạn để làm cho thuật toán hoạt động
  2. Hãy thử suy nghĩ trước khi viết mã, để ý tưởng của bạn không hợp nhất với ngôn ngữ (một ngày nào đó bạn cần chuyển thuật toán của mình sang ngôn ngữ khác và bạn sẽ kết thúc bằng spagetthi)

Yap! Tôi biết rằng thuật toán là độc lập với ngôn ngữ. Đúng là bạn có thể sử dụng bất kỳ ngôn ngữ lập trình hiện có nào để diễn đạt cùng một thuật toán.
Janner

0

Đối với tôi, đó là khá nhiều mã. Tôi nghĩ điều đó đúng với hầu hết các lập trình viên có năng suất cao. Tôi có thể viết mã về dễ dàng như tôi viết văn bản.

Càng nhiều càng tốt, tôi cố gắng nắm bắt các yêu cầu như các bài kiểm tra thực thi (mã). Thiết kế chỉ là mã hóa cấp cao. Nó nhanh hơn và chính xác hơn để nắm bắt thiết kế bằng ngôn ngữ đích hơn là chụp nó ở một số dạng khác và sau đó dịch nó.

Tôi đã thấy rằng hầu hết người dùng không thể xem xét hiệu quả các yêu cầu về văn bản. Chúng hoạt động tốt với các trường hợp sử dụng tuần tự, nhưng các trường hợp sử dụng không thể nắm bắt mọi khía cạnh của giao diện người dùng. Tốt nhất cho đến nay là thực hiện một cắt giảm đầu tiên khi thực hiện, cho phép người dùng thử nó, nhận ý kiến ​​của họ và sửa đổi mã cho phù hợp.


0

Khi bạn ngồi xuống và bắt đầu viết mã, bạn có một thuật toán trong đầu, cho dù "được thiết kế" hay không.

Nếu bạn ngồi xuống và bắt đầu viết mã mà không có thuật toán hoàn chỉnh trong đầu, bạn sẽ thực hiện một trong những điều sau đây:

1) các phím nghiền ngẫu nhiên. Điều này có thể sẽ tạo ra một lỗi biên dịch

2) viết mã có thể biên dịch có thể làm bất cứ điều gì ngoại trừ việc bạn muốn nó làm

3) viết mã để giải quyết các phần nhỏ của vấn đề và xây dựng nó khi bạn đi theo kiểu tổng hợp, nhưng không thực sự nghĩ trước - vì vậy cuối cùng vấn đề đã được giải quyết - nhưng mã không phải là cách rất hiệu quả, và với khả năng phải quay lại và lãng phí thời gian trên đường đi

Vì vậy, mọi người thường lập trình với một thuật toán trong đầu của họ. Nó có thể đã được bổ sung hoặc lý luận về giấy hoặc một số phương tiện khác.

Nó có thể là kỷ luật tốt để suy nghĩ về cuộc tấn công của bạn vào một vấn đề ra khỏi bàn phím, đặc biệt là trong những ngày đầu của bạn là một lập trình viên. Như các câu trả lời khác đã lưu ý, khi bạn có nhiều kinh nghiệm hơn, bạn có thể trở nên tốt hơn trong việc mã hóa một số vấn đề dễ quản lý hơn "nhanh chóng". Tuy nhiên, đối với các vấn đề khó hoặc lớn, suy nghĩ và thiết kế cách xa bàn phím rất hữu ích: khi sử dụng mã, bạn có nhiều khả năng suy nghĩ về các cấu trúc của ngôn ngữ và cách tiếp cận nhiệm vụ tức thời nhất trong vấn đề. Trong khi suy nghĩ về vấn đề với, giả sử, một cây bút và tờ giấy, sẽ giải phóng bạn nhiều hơn từ khía cạnh ngôn ngữ của mã và cho phép bạn suy nghĩ ở mức độ trừu tượng cao hơn.


0

Bạn cần ngừng xem việc xây dựng phần mềm như một cái gì đó cơ bản từ việc xây dựng bất cứ thứ gì khác có giá trị. Không phải vậy. Vì vậy, giống như bất cứ điều gì khác, một kế hoạch hay thiết kế chu đáo, tuy nhiên không thể thiếu, luôn luôn cần thiết.

Liệu một thuật toán thích hợp thực sự giúp cải thiện chất lượng và cuối cùng là hiệu quả của một chương trình?

Liệu một kế hoạch / sơ đồ xây dựng phù hợp có giúp xây dựng một ngôi nhà chất lượng một cách hiệu quả?

Chúng ta vẫn có thể tạo ra một chương trình chất lượng tốt mà không cần thuật toán?

Bạn có thể xây dựng một ngôi nhà chất lượng tốt một cách hiệu quả mà không có kế hoạch xây dựng phù hợp? Theo Định lý Khỉ vô hạn , theo xác suất, vâng (giống như một triệu con khỉ gõ ngẫu nhiên vĩnh viễn cuối cùng sẽ gõ các tác phẩm hoàn chỉnh của Shakespeare.

Là một thuật toán thích hợp là PHẢI trong lập trình hiện đại?

Nếu bạn không muốn trở thành một con khỉ mã và bạn muốn đảm bảo rằng bạn không cung cấp phần mềm trông giống và hoạt động như shit, vâng, đó là điều bắt buộc. Mỗi dự án mà tôi đã phải trục vớt (vì mã trông giống như một thứ rác rưởi) đã bắt đầu bất biến với một câu trả lời tiêu cực cho câu hỏi đó.

Trong thực tế, lập trình hiện đại đã tránh xa kỹ sư phần mềm lập trình cao bồi, nơi lập kế hoạch của một số loại nếu phải.

Ngay cả khi bạn có một thư viện các thuật toán và cấu trúc dữ liệu theo ý của bạn (.ie. Boost trong C ++ hoặc thư viện bộ sưu tập Java), bạn phải biết công cụ đó hoạt động như thế nào để sử dụng nó một cách hợp lý và để hợp lý nó, hợp lý hơn, cao hơn thuật toán cấp độ.


-2

Nó không tốt hơn. Tốt hơn là không "thiết kế" bất cứ điều gì. Đó là cho những người không viết chương trình. Bạn biết đấy, những người có kinh nghiệm thực sự về vấn đề trong tầm tay. Nếu bạn là một nhà toán học, kỹ sư hoặc một nhà logistic, tốt, bạn cần phải làm việc với quy trình ở nơi khác. Nhưng đó không phải là "lập trình".

Đặt một số loại thử nghiệm và điểm chuẩn ở vị trí đầu tiên.

Sau đó viết một cái gì đó, bất cứ điều gì. Thực hiện tái cấu trúc-viết lại -loop cho đến khi bạn hết thời gian hoặc không thể cải thiện được nữa.

Trong khi nhiều người dường như nghĩ rằng một người có thể làm mọi thứ với máy tính mà không thực sự làm bất cứ điều gì trên máy tính, tôi nghĩ đây là một trong những huyền thoại phổ biến nhất ngoài kia. Kiến trúc du hành vũ trụ.

Ngoài ra, bạn không thể tối ưu hóa thuật toán của mình trước khi nó được viết.

IOW, "ở gần kim loại".

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.