Là thích hợp hơn để thiết kế từ trên xuống hoặc từ dưới lên?


31

Theo tôi hiểu, thiết kế từ trên xuống là bằng cách tinh chỉnh khái niệm mức cao trừu tượng thành các phần cụ thể và dễ hiểu hơn, cho đến khi khối xây dựng nhỏ nhất được xác định. Mặt khác, từ dưới lên xác định các phần cấp thấp, sau đó dần dần xây dựng các khối cấp cao hơn cho đến khi toàn bộ hệ thống được hình thành.

Trong thực tế, tốt nhất nên kết hợp hai phương pháp: bắt đầu với đặc tả mức cao để xác định đầy đủ kiến ​​thức miền, mối quan hệ và các ràng buộc của nó. Khi vấn đề được hiểu rõ, các khối xây dựng nhỏ nhất được tạo để xây dựng hệ thống.

Quá trình:

  • Tạo đặc tả yêu cầu
  • Tạo một đặc tả thiết kế (có sơ đồ)
  • Triển khai thực hiện
  • Giao hàng
  • Lặp lại (trong quá trình phát triển lặp lại, thay vì thực hiện toàn bộ từng giai đoạn, chúng tôi thực hiện từng chút một và lặp lại cuộc họp hàng ngày để thích ứng với yêu cầu năng động của khách hàng)

trông tôi hoàn toàn bình thường (với thông số kỹ thuật như kế hoạch). Nó có những sai sót nhưng đó là lý do tại sao chúng ta có sự phát triển lặp đi lặp lại: thay vì dành thời gian cho một giai đoạn, phân tích yêu cầu để nghiên cứu mọi điều có thể trong kiến ​​thức miền có thể thay đổi (có thể hàng ngày), chúng ta thực hiện một chút phân tích, một chút thiết kế và sau đó thực hiện nó.

Một cách khác là mỗi lần lặp là một kiểu thác nước nhỏ, trong đó phân tích được thực hiện trong vài ngày (hoặc một tuần). Áp dụng tương tự cho thiết kế. Thời gian còn lại dành cho việc thực hiện. Có điều gì đó vốn đã sai với cách tiếp cận từ trên xuống kết hợp với phát triển lặp lại?

Trong bài tiểu luận Lập trình từ dưới lên , Paul Graham dường như khuyến khích xây dựng từ dưới lên hoàn toàn, hoặc lập trình từ dưới lên, nhưng không phải là giai đoạn phân tích / thiết kế yêu cầu:

Các lập trình viên Lisp có kinh nghiệm phân chia các chương trình của họ khác nhau. Cũng như thiết kế từ trên xuống, họ tuân theo một nguyên tắc có thể được gọi là thiết kế từ dưới lên - thay đổi ngôn ngữ cho phù hợp với vấn đề.

Theo như tôi nhận được, ý anh là Lisper vẫn thực hiện thiết kế từ trên xuống, nhưng chương trình từ dưới lên, điều đó có đúng không? Một điểm khác ông đã viết:

Cần nhấn mạnh rằng thiết kế từ dưới lên không có nghĩa là chỉ viết cùng một chương trình theo một thứ tự khác. Khi bạn làm việc từ dưới lên, bạn thường kết thúc với một chương trình khác. Thay vì một chương trình đơn, nguyên khối, bạn sẽ có được một ngôn ngữ lớn hơn với các toán tử trừu tượng hơn và một chương trình nhỏ hơn được viết trong đó. Thay vì một lintel, bạn sẽ có được một vòm.

Điều này có nghĩa là trong thời gian viết một chương trình bằng Lisp, bạn kết thúc với một công cụ chung?


Có lẽ nếu bạn cung cấp một liên kết đến cuốn sách, bài báo hoặc bài viết mà bạn đang đề cập, những người khác có thể có thể đưa ra một tuyên bố hợp lý hơn liên quan đến câu hỏi của bạn. Ngoài ra, không rõ câu hỏi của bạn cụ thể là gì. Bạn đang yêu cầu lời khuyên về một số chi tiết cụ thể liên quan đến một thiết kế bạn muốn thực hiện, hoặc đặt câu hỏi về bài viết bạn đang tham khảo. Có lẽ điều này sẽ dễ đọc và trả lời hơn nếu bạn chia nó thành một vài câu hỏi riêng biệt.
S.Robins

@ S.Robins Tóm lại, tôi đã trình diễn cách tiếp cận từ trên xuống thông thường của mình để phát triển phần mềm. Tuy nhiên, một số người thích từ dưới lên, và một trong số họ là Paul Graham, một người nổi tiếng. Tôi yêu cầu hiểu cách thiết kế từ dưới lên giúp nói chung, và cụ thể là ở Lisp vì nó có các tính năng đặc biệt để khuyến khích (như Paul đề xuất).
Amumu

1
Amumu tôi đã chỉnh sửa ví dụ, vì cả hai câu trả lời dường như đã bỏ qua nó. Hãy cố gắng giữ cho câu hỏi của bạn súc tích, và chỉ hỏi một câu hỏi cho mỗi câu hỏi .
yannis

Câu trả lời:


35

Từ trên xuống là một cách tuyệt vời để mô tả những thứ bạn biết hoặc để xây dựng lại những thứ bạn đã xây dựng.

Vấn đề lớn nhất từ ​​trên xuống là khá thường xuyên đơn giản là không có "đỉnh". Bạn sẽ thay đổi suy nghĩ về những gì hệ thống nên làm trong khi phát triển hệ thống và trong khi khám phá tên miền. Làm thế nào có thể là điểm khởi đầu của bạn một cái gì đó mà bạn không biết (tức là những gì bạn muốn hệ thống làm)?

Một "địa phương" từ trên xuống là một điều tốt ... một số suy nghĩ trước khi mã hóa rõ ràng là tốt. Nhưng suy nghĩ và lên kế hoạch quá nhiều thì không, bởi vì những gì bạn đang hình dung không phải là kịch bản thực sự (trừ khi bạn đã ở đó trước đó, tức là nếu bạn không xây dựng, mà là xây dựng lại). Từ trên xuống toàn cầu khi xây dựng những thứ mới chỉ là vô nghĩa.

Từ dưới lên phải là (trên toàn cầu) cách tiếp cận trừ khi bạn biết 100% vấn đề, bạn chỉ cần giải pháp đã biết để được mã hóa và bạn không quan tâm đến việc tìm kiếm các giải pháp thay thế khả thi.

Cách tiếp cận Lisp là từ dưới lên. Bạn không chỉ xây dựng từ dưới lên mà bạn còn có thể định hình các viên gạch theo cách bạn cần. Không có gì là cố định, tự do là toàn bộ. Tất nhiên tự do chịu trách nhiệm và bạn có thể tạo ra những điều khủng khiếp bằng cách lạm dụng sức mạnh này.

Nhưng mã khủng khiếp có thể được viết bằng bất kỳ ngôn ngữ nào. Ngay cả trong các ngôn ngữ được định hình là lồng cho tâm trí, được thiết kế với hy vọng rằng với những ngôn ngữ đó, ngay cả những con khỉ cũng có thể có được các chương trình tốt và chạy (một ý tưởng quá sai ở nhiều cấp độ đến nỗi chỉ đau khi nghĩ về nó).

Ví dụ của bạn là về một máy chủ web. Bây giờ trong năm 2012, đây là một vấn đề được xác định rõ, bạn có thông số kỹ thuật cần tuân thủ. Một máy chủ web chỉ là một vấn đề thực hiện. Đặc biệt là nếu bạn đang nhắm đến việc viết một máy chủ web hoàn toàn giống với các máy chủ web khác hiện có thì không có gì thực sự không rõ ràng, ngoại trừ một số chi tiết vụn vặt. Ngay cả nhận xét của bạn về RSA vẫn đang nói về một vấn đề được xác định rõ ràng, với các thông số kỹ thuật chính thức.

Với một vấn đề được xác định rõ ràng, với các thông số kỹ thuật chính thức và các giải pháp đã biết thì mã hóa chỉ là kết nối trong các dấu chấm. Từ trên xuống là ok cho điều đó. Đây là thiên đường quản lý dự án.

Tuy nhiên, trong nhiều trường hợp, không có cách tiếp cận nổi tiếng nào được chứng minh sẽ được sử dụng để kết nối các dấu chấm. Trên thực tế rất thường rất khó để nói ngay cả những gì là dấu chấm.

Ví dụ, giả sử bạn được yêu cầu hướng dẫn một máy cắt tự động căn chỉnh các bộ phận được cắt thành vật liệu in không hoàn toàn phù hợp với logo lặp đi lặp lại theo lý thuyết. Bạn được cung cấp các bộ phận và hình ảnh của vật liệu như được chụp bằng máy.

Một quy tắc liên kết là gì? Bạn quyết định. Một mô hình là gì, làm thế nào để đại diện cho nó? Bạn quyết định. Làm thế nào để sắp xếp các bộ phận? Bạn quyết định. Các bộ phận có thể được "uốn cong"? Nó phụ thuộc, một số không và một số có, nhưng tất nhiên không quá nhiều. Phải làm gì nếu vật liệu quá biến dạng đối với một phần để cắt nó chấp nhận được? Bạn quyết định. Có phải tất cả các cuộn vật liệu giống hệt nhau? Tất nhiên là không, nhưng bạn không thể sửa lỗi người dùng để điều chỉnh quy tắc căn chỉnh cho mỗi cuộn ... điều đó là không thực tế. Những hình ảnh đang nhìn thấy các máy ảnh? Các vật liệu, bất cứ điều gì có thể có nghĩa là ... nó có thể là màu sắc, nó có thể là màu đen hơn màu đen trong đó chỉ có phản xạ ánh sáng làm cho mô hình rõ ràng. Nó có nghĩa là gì để nhận ra một mô hình? Bạn quyết định.

Bây giờ hãy thử thiết kế cấu trúc chung của một giải pháp cho vấn đề này và đưa ra một báo giá, bằng tiền và thời gian. Đặt cược của tôi là ngay cả kiến ​​trúc hệ thống của bạn ... (vâng, kiến ​​trúc) sẽ sai. Dự toán chi phí và thời gian sẽ là những con số ngẫu nhiên.

Chúng tôi đã triển khai nó và bây giờ nó là một hệ thống làm việc, nhưng đã thay đổi suy nghĩ về hình dạng của hệ thống rất nhiều lần. Chúng tôi đã thêm toàn bộ hệ thống phụ mà thậm chí không thể truy cập được từ các menu. Chúng tôi đã chuyển đổi vai trò chủ / nô lệ trong các giao thức nhiều lần. Có lẽ bây giờ chúng tôi đã có đủ kiến ​​thức để cố gắng xây dựng lại nó tốt hơn.

Các công ty khác tất nhiên đã giải quyết vấn đề tương tự ... nhưng trừ khi bạn ở một trong những công ty này, rất có thể dự án chi tiết từ trên xuống của bạn sẽ là một trò đùa. Chúng tôi có thể thiết kế nó từ trên xuống. Bạn không thể bởi vì bạn chưa bao giờ làm điều đó trước đây.

Bạn có thể có thể giải quyết vấn đề tương tự quá. Làm việc từ dưới lên tuy nhiên. Bắt đầu với những gì bạn biết, học những gì bạn không và thêm vào.

Hệ thống phần mềm phức tạp mới được phát triển, không được thiết kế. Thỉnh thoảng ai đó bắt đầu thiết kế một hệ thống phần mềm phức tạp lớn mới từ đầu (lưu ý rằng với một dự án phần mềm phức tạp lớn, chỉ có ba khả năng: a] đặc tả là mờ, b] đặc tả sai và tự mâu thuẫn hoặc c] cả ... và thường xuyên nhất [c] là trường hợp).

Đây là những dự án lớn của công ty điển hình với hàng ngàn và hàng ngàn giờ được đưa vào các slide powerpoint và sơ đồ UML. Họ luôn thất bại hoàn toàn sau khi đốt một lượng tài nguyên đáng xấu hổ ... hoặc trong một số trường hợp rất đặc biệt, cuối cùng họ cũng cung cấp một phần mềm quá đắt chỉ thực hiện một phần nhỏ của thông số kỹ thuật ban đầu. Và phần mềm đó luôn bị người dùng ghét ... không phải là loại phần mềm bạn sẽ mua, mà là loại phần mềm bạn sử dụng vì bạn bị ép buộc.

Điều này có nghĩa là tôi nghĩ rằng bạn chỉ nên nghĩ về mã? Tất nhiên là không. Nhưng theo tôi, việc xây dựng nên bắt đầu từ dưới cùng (gạch, mã cụ thể) và nên đi lên ... và sự tập trung và chú ý của bạn đến chi tiết sẽ theo nghĩa "mờ dần" khi bạn đang đi xa hơn những gì bạn có. Từ trên xuống thường được trình bày như thể bạn nên đặt cùng một mức độ chi tiết cho toàn bộ hệ thống: chỉ cần giữ cho nó tách mọi nút cho đến khi mọi thứ rõ ràng ... trong các mô-đun thực tế, hệ thống con được "phát triển" từ chương trình con. Nếu bạn không có kinh nghiệm trước đây trong vấn đề cụ thể, thiết kế hệ thống con, mô-đun hoặc thư viện từ trên xuống của bạn sẽ rất kinh khủng. Bạn có thể thiết kế một thư viện tốt khi bạn biết những chức năng nào được đưa vào, chứ không phải cách khác.

Nhiều ý tưởng của Lisp đang trở nên phổ biến hơn (các hàm hạng nhất, đóng, gõ động như mặc định, thu gom rác, lập trình siêu dữ liệu, phát triển tương tác) nhưng Lisp vẫn ngày nay (trong số các ngôn ngữ tôi biết) khá độc đáo về cách dễ dàng định hình mã cho những gì bạn cần.

Ví dụ, các tham số từ khóa đã có sẵn, nhưng nếu chúng không có thì chúng có thể được thêm vào. Tôi đã làm điều đó (bao gồm xác minh từ khóa tại thời điểm biên dịch) cho trình biên dịch Lisp đồ chơi mà tôi đang thử nghiệm và nó không mất nhiều mã.

Thay vào đó, với C ++, hầu hết những gì bạn có thể nhận được là một nhóm các chuyên gia C ++ nói với bạn rằng các tham số từ khóa không hữu ích hoặc việc triển khai mẫu được hỗ trợ một nửa cực kỳ phức tạp, bị hỏng, thực sự không hữu ích. Là các lớp C ++ đối tượng hạng nhất? Không và không có gì bạn có thể làm về nó. Bạn có thể có nội tâm trong thời gian chạy hoặc tại thời gian biên dịch? Không và không có gì bạn có thể làm về nó.

Tính linh hoạt ngôn ngữ này của Lisp là điều làm cho nó tuyệt vời cho việc xây dựng từ dưới lên. Bạn có thể xây dựng không chỉ các chương trình con, mà cả cú pháp và ngữ nghĩa của ngôn ngữ. Và theo một nghĩa nào đó, bản thân Lisp là từ dưới lên.


Vâng, những gì tôi có nghĩa là một địa phương từ trên xuống. Bạn tiếp tục tinh chỉnh yêu cầu và phát triển nó thông qua các lần lặp. Điểm từ trên xuống là chúng tôi muốn có được cấu trúc mã càng chính xác càng tốt. Liên tục tái cấu trúc. Ví dụ, lúc đầu bạn muốn truyền một chuỗi cho một hàm, nhưng sau đó bạn cần cả một lớp để thỏa mãn các thay đổi và việc tái cấu trúc sẽ tốn thời gian nếu hàm này đã được sử dụng ở mọi nơi.
Amumu

Để xây dựng lại một cái gì đó được biết rõ ràng theo một cách rõ ràng sau đó từ trên xuống là ok. Trình duyệt web của bạn là một ví dụ về điều này. Ngay cả khi sử dụng ngôn ngữ như C ++, buộc bạn phải dự đoán và chính thức chỉ định (sử dụng cú pháp khủng khiếp), tất cả các loại cho các giá trị được giữ trong tất cả các biến của chương trình của bạn vẫn là một lựa chọn khả thi.
6502

Tôi không nghĩ ví dụ của tôi là một cách được biết rõ ràng, bởi vì tôi cho rằng nó được tạo ra bởi một người có kiến ​​thức cơ bản về giao tiếp dữ liệu và mã C ++ là kết quả của thiết kế rất cơ bản từ kiến ​​thức tên miền (trong trường hợp này là kết nối mạng) . Đó là một ví dụ về thiết kế tiến hóa. Trong lần lặp lại tiếp theo, nhà phát triển tìm hiểu thêm về kiến ​​thức tên miền, vì vậy anh ta mở rộng thiết kế của mình để phù hợp với kiến ​​thức đã phát triển (chẳng hạn như các khía cạnh bảo mật được thêm vào trong mỗi lớp của máy chủ web). Sau đó, ông tinh chỉnh việc thực hiện theo thiết kế mới.
Amumu

Vấn đề ở đây là giải pháp thực tế bắt nguồn từ một ngôn ngữ độc lập miền (như ngôn ngữ tự nhiên, ngôn ngữ toán học ... phụ thuộc vào miền). Hành động mã hóa chỉ là một ánh xạ chi tiết từ giải pháp được tạo thành mã.
Amumu

1
Chào Mr.6502. Sau một năm, khi tôi học được nhiều thứ hơn, tôi bắt đầu thấy những gì bạn nói trở thành người xác thực. Tôi đã tạo một chủ đề khác: lập trình viên.stackexchange.com /questions / 17000 / // . Nếu bạn có thời gian, tôi hy vọng bạn sẽ làm rõ suy nghĩ của tôi một lần nữa: D.
Amumu

6

Tôi không chắc câu trả lời này sẽ áp dụng như thế nào với Lisp, nhưng tôi vừa đọc xong Nguyên tắc, mô hình và thực tiễn Agile , và tác giả, chú Bob , ủng hộ mạnh mẽ cách tiếp cận từ trên xuống cho C # (cũng áp dụng cho C ++) mà tôi hoàn toàn áp dụng đồng ý.

Tuy nhiên, không giống như một số câu trả lời khác đưa ra kết luận rằng cách tiếp cận từ trên xuống có nghĩa là trong lần tương tác đầu tiên bạn chỉ cung cấp tài liệu và thiết kế tổng thể, cuốn sách chỉ ra một phương pháp khác: TDD kết hợp với thiết kế tiến hóa.

Ý tưởng là bạn bắt đầu từ đầu và xác định mức độ trừu tượng cao nhất của bạn (hoặc cao nhất cục bộ) và ngay khi chúng được xác định, bạn làm cho chúng thực hiện công việc hữu ích để tính năng số 1 ngay lập tức hoạt động. Sau đó, khi bạn thêm ngày càng nhiều tính năng, bạn cấu trúc lại mã của mình và phát triển thiết kế khi cần trong khi luôn nhận thức được các nguyên tắc RẮN. Bằng cách này, bạn sẽ không có quá nhiều lớp trừu tượng và bạn sẽ không kết thúc thiết kế cấp thấp không phù hợp với kiến ​​trúc tổng thể. Nếu bạn không chắc điều này có nghĩa là gì, cuốn sách tôi đã đề cập ở trên có cả một chương với một ví dụ nơi các nhà phát triển lấy các khái niệm và bắt đầu với các sơ đồ UML và các lớp cấp thấp, chỉ để nhận ra một nửa các lớp đó là không cần thiết khi mã hóa thực sự bắt đầu. Về bản chất với cách tiếp cận này, mã cấp thấp được giảm xuống một cách tự nhiên khi có nhiều chi tiết cấp cao hơn được xác định trong dự án.

Và cuối cùng, nếu bạn thực hành RẮN, bạn không nên gặp phải tình huống có sự trừu tượng hóa ở mức độ cao và sau đó đi vào chi tiết và tất cả đều thấy rằng không có sự trừu tượng nào. Đó thực sự không phải là lỗi của thiết kế từ trên xuống, mà là kỹ thuật lười biếng.

Nếu bạn muốn đọc thêm về XP và thiết kế tiến hóa, thì đây là một bài đọc hay từ Martin Fowler, một tác giả tuyệt vời khác: "Is Design Dead?"


Hoàn hảo. Đây là những gì tôi đang nói về. Ngoài ra, thật tuyệt khi biết về nguyên tắc RẮN và Agile hỗ trợ cách tiếp cận từ trên xuống (tôi nghĩ rằng với TDD và XP, mọi người nhảy vào mã càng sớm càng tốt và tránh tài liệu).
Amumu

@Amumu: Tôi đã thêm một liên kết đến một bài viết khác được viết bởi Fowler. Bạn có thể đọc thêm về sự khác biệt giữa mã hóa cao bồi không có thiết kế / tài liệu so với những gì XP / Agile thực sự đang quảng bá. Về mặt cá nhân, tôi hoàn toàn tin rằng tài liệu có giá trị và tôi đã tích cực thúc đẩy nhóm của mình theo kịp các tài liệu thiết kế của mình, tôi đã dần thay đổi quan điểm của mình. Bây giờ "nhiệm vụ thiết kế" của chúng tôi là tất cả các loại bảng trắng / khăn ăn, trong khi các tài liệu thực tế chỉ được cập nhật sau khi câu chuyện được viết. Chúng tôi cũng đã thu nhỏ lại những gì thực sự được ghi lại để các tài liệu chỉ bao gồm các công cụ kiến ​​trúc / cấp cao
DXM

3

Đối với tôi, những nhận xét quan trọng nhất mà Paul Graham đưa ra trong bài viết của mình là:

[...] Lập trình viên Lisp [...] tuân theo một nguyên tắc có thể được gọi là thiết kế từ dưới lên-- thay đổi ngôn ngữ cho phù hợp với vấn đề. Trong Lisp, bạn không chỉ viết chương trình của mình xuống ngôn ngữ, bạn cũng xây dựng ngôn ngữ theo hướng chương trình của mình.

Hoặc, như được biết đến trong các vòng tròn C ++: Thiết kế thư viện là Thiết kế ngôn ngữ (Bjarne Stroustrup)

Ý tưởng chính của thiết kế từ trên xuống là: đầu tiên bạn lên kế hoạch, sau đó bạn viết mã. Beanow là chính xác khi ông viết , rằng có vấn đề khi mã thực thi đến muộn trong quá trình. Trong thiết kế từ dưới lên, bạn luôn có mã và mã đó có thể được kiểm tra.

Ngoài ra, mã của bạn không bằng phẳng. Ý tôi là, nó có xu hướng có nhiều mức độ trừu tượng nhỏ hơn. Trong thiết kế từ trên xuống, mọi người thường kết thúc với sự trừu tượng lớn xuống một mức độ tùy ý và bên dưới không có sự trừu tượng nào cả. Mã được thiết kế từ dưới lên OTOH thường chứa các cấu trúc dữ liệu và kiểm soát mức độ thấp hơn vì chúng có khả năng bị trừu tượng hóa.


2

Lý tưởng nhất là viết một chương trình bằng bất kỳ ngôn ngữ nào, không chỉ Lisp, cho phép bạn viết cả bộ công cụ chung có thể tăng tốc cho bạn trong chương trình tiếp theo hoặc cải tiến tốc độ cho chương trình hiện tại của bạn.

Trong thực tế, việc theo dõi các công cụ này có thể khó khăn. Tài liệu kém và vô tổ chức và những người biết về họ rời đi. Trong thực tế, việc sử dụng lại mã thường rắc rối hơn giá trị của nó. Nhưng nếu mã được ghi lại và tổ chức đúng cách, và các lập trình viên bám sát (hoặc giữ nguồn cung cấp mã hữu ích của riêng họ), một lượng lớn công việc có thể được lưu bằng cách lấy mã từ kho thay vì xây dựng lại mã.

Tất cả các thiết kế phải từ trên xuống hoặc bạn sẽ không biết những gì bạn đang làm. Bạn đang xây dựng một nhà kho hoặc một chiếc xe hơi? Bạn không thể tìm ra cái nào có thiết kế từ dưới lên. Nhưng nếu bạn định chế tạo một bánh trước bên trái, bạn có thể nghĩ rằng bạn có thể cần nhiều bánh xe hơn sau này, cho cả dự án này và cho những người khác. Và nếu bạn xây dựng một bánh xe có thể tái sử dụng, bạn sẽ có bốn cái với giá một chiếc. (Và 18 cho đoạn giới thiệu máy kéo mà bạn đang xây dựng tiếp theo, tất cả đều miễn phí.)

Lưu ý rằng không giống như xe thật và bánh xe thật, nếu bạn đã tạo một "bánh xe" phần mềm, bạn đã tạo được vô số phần mềm.

Thông tin thêm về thiết kế từ trên xuống: trong khi bạn phải bắt đầu với điều này, tôi cảm thấy bắt buộc phải chỉ ra rằng nếu bạn không thể chế tạo một bánh xe, bạn cần tìm hiểu điều đó trước khi bạn làm nhiều việc trên xe. Vì vậy, bạn cần phải làm việc từ dưới lên gần như song song với làm việc từ trên xuống. Ngoài ra, biết rằng bạn có thể chế tạo một bánh xe có thể gợi ý rất nhiều dự án mà bạn chưa từng nghĩ đến trước đây, như xe đầu kéo. Tôi nghĩ rằng cách tiếp cận từ trên xuống phải chiếm ưu thế, nhưng với một cú chạm rất nhẹ.

Vì vậy, để tiếp tục diễn giải Paul Graham, lý tưởng nhất là khi bạn viết một chương trình, bạn kết thúc với rất nhiều phần có thể tái sử dụng có thể tiết kiệm nhiều thời gian cho cả chương trình gốc và trong các chương trình khác. Để tránh xa Paul Graham một chút, điều này hoạt động trong bất kỳ ngôn ngữ nào (mặc dù một số khuyến khích quá trình này hơn những ngôn ngữ khác).

Kẻ thù của quá trình gần như kỳ diệu này là các lập trình viên với triển vọng rất ngắn hạn. Điều này có thể xuất phát từ những khiếm khuyết về tính cách, nhưng phổ biến hơn là do chuyển đổi công việc và phản hồi quá nhanh, cả bên trong và giữa các công ty tuyển dụng.


Ồ, tôi đã nhận được trả lời từ ngày 16 tháng 2 và hộp thư đến không hiển thị gì cả. Tôi đồng ý với bạn, luôn cần có một kế hoạch, thậm chí là rất nhẹ, và sau đó xây dựng một chút, và sau đó tinh chỉnh kế hoạch. Nó hoàn toàn hợp lý. Tuy nhiên, tôi dường như không hiểu tại sao nhiều nhà phát triển thích lập kế hoạch cho mọi thứ trong đầu họ trong khi viết mã. Một lượng thời gian hợp lý có thể được lưu và họ có thể tập trung để làm việc nhiều hơn với vấn đề thực sự thay vì liên tục cấu trúc lại kiến ​​trúc mã trong quá trình thực hiện.
Amumu

@Amumu Một lý do để lập kế hoạch trong khi viết: Một số lập trình viên biết rất nhiều về những gì họ đang làm bàn phím và chuột là nút cổ chai mã hóa của họ, chứ không phải quá trình lập kế hoạch. (Mã tái sử dụng sẽ cho phép họ thực hiện công việc mới, sáng tạo để cho phép suy nghĩ trở thành phần khó khăn một lần nữa.)
RalphChapin

@Amumu Một lý do khác để lập kế hoạch trong khi viết: với một số kết hợp ngôn ngữ / lập trình viên / vấn đề, ngôn ngữ là cách tốt nhất để suy nghĩ về vấn đề. Ngôn ngữ là cách dễ nhất để đặt suy nghĩ của bạn lên "tờ giấy". Tôi chỉ đọc những mẩu nhỏ ở đây và về Lisp, nhưng từ đó tôi nghi ngờ nó đặc biệt tốt cho việc này. (Một số ngôn ngữ được tạo trước tiên như một cách để diễn đạt vấn đề thay vì sử dụng máy để giải quyết vấn đề đó.) Nếu việc sắp xếp lại mã của bạn theo suy nghĩ của bạn cũng dễ dàng như vậy, cũng có thể mã. Nhưng lập trình viên, ngôn ngữ và vấn đề phải kết hợp tốt để làm việc này.
RalphChapin

Nó đáng tin cậy. Ý tưởng của việc lập kế hoạch là tách biệt kiến ​​thức miền và nhận dạng mối quan hệ giữa các khái niệm miền với quy trình lập trình thực tế. Hãy tưởng tượng nếu một lớp được sử dụng bởi hàng tá các lớp khác, mà không có kế hoạch tốt trong việc tạo giao diện để giao tiếp với các lớp khác, chúng ta có thể dễ dàng hòa nhập và tái cấu trúc địa ngục. Trong trường hợp này, thời gian lãng phí cho việc gõ và cấu trúc lại mã vượt quá nhiều thời gian dành cho việc xác định trên giấy.
Amumu

Hãy lấy một ví dụ: Giả sử chúng ta đang viết một ứng dụng khách / máy chủ. Điều đầu tiên chúng ta phải xác định giao thức bằng cách xác định các thông điệp trao đổi, cách thông báo được trình bày trong bộ nhớ (tức là tiêu đề 16 byte, id 4 byte ....). Sơ đồ không bằng mô hình hóa / lập kế hoạch: abstratt.com/blog/2009/05/03/on-code-being-model . Chúng ta không cần sử dụng UML hoặc sơ đồ để mô hình hóa, vì UML chỉ tập trung khá nhiều vào OOP và thời gian gõ vào sơ đồ lớp UML không ít hơn so với nhập mã thực tế, nếu không muốn nói là nhiều hơn.
Amumu

1

Có gì sai với cách tiếp cận từ trên xuống kết hợp với phát triển lặp?

Sử dụng cách tiếp cận từ trên xuống với phát triển lặp không cung cấp bất kỳ mã làm việc nào trong các lần lặp đầu tiên. Nó cung cấp các tài liệu thiết kế và như vậy khách hàng sẽ có một thời gian khó khăn với việc đưa ra phản hồi. Các phản hồi như, "vâng tôi đoán (điều này quá trừu tượng đối với tôi)" sẽ không giúp bạn tiếp tục xác định cụ thể hệ thống mong muốn của khách hàng.

Thay vào đó bạn chỉ tạo một cái nhìn tổng quan về những gì được yêu cầu. (Yêu cầu) để sử dụng làm hướng dẫn chung cho những gì xác định thành phẩm và những gì xứng đáng được ưu tiên thực hiện. Từ đó, bạn tạo ra các sản phẩm làm việc cho mỗi lần lặp mà khách hàng thực sự có thể chơi với để xem liệu đây có phải là những gì họ có trong tâm trí. Nếu không, thì đó sẽ không phải là vấn đề vì đã không dành hàng trăm giờ để thiết kế một hệ thống hoạt động khác với những gì khách hàng yêu cầu bây giờ.

Paul Graham có khuyến khích xây dựng từ dưới lên hoàn toàn không? Hoặc chỉ lập trình nó từ dưới lên, nhưng không phải là giai đoạn phân tích / desing yêu cầu?

Tôi sẽ không nói cho người khác. Ngoài ra tôi đã không đọc bài luận của anh ấy. Câu trả lời tôi đưa ra cho bạn đến từ giáo dục cũng như kinh nghiệm của tôi.

Điều này có nghĩa là, trong giai đoạn viết một chương trình ở Lisp, bạn kết thúc với một công cụ chung có thể được sử dụng để viết các chương trình tương tự của chương trình gốc, phải không?

Sử dụng phương pháp này có nghĩa là bạn sẽ kết thúc với các khối xây dựng trừu tượng hơn. Đơn giản là vì bạn sẽ phải xây dựng các hệ thống con độc lập có thể được trình bày ngay lập tức, bạn không thể tạo ra một thiết kế từ trên xuống đan xen nhiều và phải được thực hiện cùng một lúc. Nó cải thiện khả năng sử dụng lại, khả năng bảo trì nhưng hầu hết tất cả cho phép phản ứng linh hoạt hơn để thay đổi.


1
Boldface, trong mắt tôi, là không cần thiết khi bạn đã chặn trích dẫn
mk12
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.