Một quy trình đơn giản để thiết kế một hệ thống OOP trước khi mã hóa nó là gì?


10

Bất cứ khi nào tôi được yêu cầu xây dựng một dự án, tôi luôn tìm cách xây dựng nó, không phải trước khi nghĩ ra một kế hoạch hay thiết kế, nhưng sau khi lần đầu tiên viết một lớp cần thiết, làm sáng tỏ toàn bộ dự án, xây dựng từ dưới lên. Bây giờ tôi biết đây không phải là cách thích hợp để tạo ra phần mềm, nhưng không dễ để tôi quấn đầu xung quanh cái được gọi là Phân tích và Thiết kế hướng đối tượng. Tôi có thể dễ dàng hiểu hơn về thiết kế thủ tục từ trên xuống, vì nó chỉ bao gồm việc chia nhỏ các nhiệm vụ thành các nhiệm vụ phụ, những thứ có đối tác của chúng trong mã, chức năng. Nhưng Phân tích và Thiết kế hướng đối tượng Tôi không thể dễ dàng hiểu được, vì tôi không hiểu làm thế nào người ta có thể biết họ sẽ cần những lớp nào và họ sẽ tương tác như thế nào, trừ khi họ biết họ sẽ mã hóa chúng như thế nào.

Lần đầu tiên chúng tôi đưa khái niệm về các lớp và các đối tượng vào quy trình thiết kế, chúng tôi không còn có thể thiết kế từ trên xuống, bởi vì chúng tôi không còn chia nhỏ các vấn đề của chúng tôi thành những điều có thể được thực hiện như các thủ tục. Thay vào đó, theo những gì tôi đã đọc về chủ đề này, chúng ta phải xác định những lớp nào là cần thiết và tạo ra các tạo phẩm khác nhau trong Ngôn ngữ mô hình thống nhất, sau đó chúng ta có thể sử dụng khi triển khai phần mềm. Nhưng loại quy trình thiết kế này tôi không hiểu. Vì làm thế nào để người ta biết họ sẽ cần những lớp nào và cách họ sẽ tương tác, trừ khi họ đã hình thành toàn bộ hệ thống?

Đây là vấn đề của tôi. Tôi không hiểu cách thiết kế Hệ thống hướng đối tượng, mặc dù tôi hiểu các khái niệm về lập trình hướng đối tượng và có thể sử dụng các khái niệm đó trong bất kỳ ngôn ngữ lập trình hướng đối tượng nào mà tôi biết. Do đó, tôi cần ai đó giải thích cho tôi quy trình đơn giản nào tôi có thể sử dụng để thiết kế Hệ thống hướng đối tượng theo cách có ý nghĩa với tôi.


8
"Bây giờ tôi biết đây không phải là cách thích hợp để tạo phần mềm" - ai nói với bạn điều này? Dường như bằng cách nào đó bạn rơi vào cái bẫy phổ biến khi tin rằng "thiết kế là thứ bạn làm trước khi mã hóa, có thể bằng cách vẽ sơ đồ UML lạ mắt". Để cứu bạn khỏi quan niệm sai lầm này, tôi khuyên bạn nên bắt đầu với "Code as Design" của Jack Reeves.
Doc Brown


@DocBrown. Bạn không nghĩ rằng thiết kế trong khi mã hóa là những gì làm cho công việc của chúng tôi rất nghệ thuật? Tôi không thể tưởng tượng các nhà máy khác làm việc như nhau. Hãy tưởng tượng một kiến ​​trúc sư đổ gạch và vữa và thiết kế tòa nhà / cây cầu trên đường.
Laiv

5
@Laiv: "mã hóa" là một phần của những gì trong các ngành kỹ sư khác được gọi là thiết kế. Trong xây dựng nhà, bước từ thiết kế đến sản phẩm cuối cùng được thực hiện bằng cách sử dụng gạch và vữa. Trong lập trình, bước này được trình biên dịch thực hiện khi dịch thiết kế (= chương trình) thành sản phẩm cuối (= nhị phân thực thi). Và đó không phải là một trí tuệ mới. Tiểu luận Reeves 25 tuổi.
Doc Brown

@DocBrown, là nhà phát triển. * Không còn giám tuyển? Nút đăng ký bị hỏng chẳng hạn.
radarbob

Câu trả lời:


20

Kiểu thác nước từ trên xuống OOAD không đảm bảo rằng mã bạn viết hoàn toàn hướng đối tượng. Tôi đã thấy hàng núi mã OOAD được sản xuất nghiêm ngặt chứng minh điều đó. Nếu OO làm bạn bối rối, đừng tìm ở đây để được giúp đỡ. Bạn sẽ không tìm thấy nó. OO KHÔNG yêu cầu bạn thiết kế từ trên xuống.

Nếu lặn vào một lớp học là cách bạn muốn viết mã, vì vậy hãy là nó. Hãy để tôi nói cho bạn một gợi ý. Hoản lại.

Thật đáng kinh ngạc khi dễ dàng thiết kế các lớp bằng cách viết mã sử dụng chúng ngay cả khi chúng chưa tồn tại. Quên thủ tục. Quên cấu trúc. Chỉ cần có cho mình một mức độ trừu tượng nhất quán tốt đẹp và gắn bó với nó. Đừng cho vào cám dỗ và trộn thêm chi tiết vào đó. Bất cứ điều gì đưa bạn ra khỏi sự trừu tượng hiện tại có thể được thực hiện trong một số phương pháp có thể trên một đối tượng khác mà bằng cách nào đó biết bất cứ điều gì nó cần biết. Đừng xây dựng bất cứ thứ gì bạn có thể yêu cầu được trao cho bạn.

Học cách viết như vậy và bạn sẽ thấy mình đang làm OO mà không cần cố gắng nhiều. Điều này buộc bạn phải nhìn vào các đối tượng của mình từ quan điểm về cách chúng được sử dụng (giao diện của chúng) và đối tượng nào biết về những đối tượng khác. Đoán xem hai điểm chính của sơ đồ UML là gì?

Nếu bạn có thể đi vào chế độ suy nghĩ đó thì những gì còn lại là kiến ​​trúc. Tất cả chúng ta vẫn đang tìm ra điều đó. Từ MVC để làm sạch kiến ​​trúc để thiết kế định hướng tên miền. Nghiên cứu chúng và chơi. Sử dụng những gì làm việc. Nếu bạn tìm thấy một cái gì đó đáng tin cậy 100% hãy quay lại và cho tôi biết. Đã làm điều này trong nhiều thập kỷ và tôi vẫn đang tìm kiếm.


2
Hoặc bạn thấy mình không làm OO và mọi thứ "bằng cách nào đó" vẫn hoạt động tốt ...
Derek Elkins rời SE

2
"Thật đáng kinh ngạc khi dễ dàng thiết kế các lớp bằng cách viết mã sử dụng chúng ngay cả khi chúng chưa tồn tại" - Tôi gọi thiết kế từ trên xuống này, nhưng có vẻ như tôi đã sai. Thiết kế từ trên xuống là gì và thứ này tôi gọi là gì? Có phải nó đang lập trình đến một giao diện?
Piovezan

Nó không chỉ đơn giản là từ trên xuống. Bạn cũng phải sẵn sàng không xây dựng những thứ bạn có thể yêu cầu bằng cách chấp nhận các tham số.
candied_orange

@Piovezan bạn có thể làm điều này ngay cả khi giao diện chưa tồn tại. Chỉ cần bỏ qua trình biên dịch của bạn một chút. Sau đó, bạn sẽ làm cho nó tồn tại.
candied_orange

@CandiedOrange "Bạn cũng phải sẵn sàng không xây dựng những thứ bạn có thể yêu cầu bằng cách chấp nhận tham số." - Tôi không chắc là tôi hiểu, bạn có thể vui lòng làm rõ / cung cấp một ví dụ ngắn (hoặc ví dụ phản biện cho vấn đề đó) không?
Piovezan

4

Bạn tuyên bố có thể sử dụng các kỹ thuật hướng đối tượng trong mã của mình, do đó bạn đã biết cách thiết kế một hệ thống hướng đối tượng rồi , tôi tin rằng vấn đề của bạn là vấn đề khi nào , không phải là bạn có thể hay không. Bạn có vẻ thoải mái với thiết kế hướng đối tượng theo cách lặp ngắn hạn, thay vì cách lập kế hoạch dài hạn.

Khi lần đầu tiên phát triển một dự án, có thể rất khó lập kế hoạch và thiết kế, đó là khi phát triển nhanh được ưa chuộng hơn so với phát triển thác nước , vì phạm vi lớn của kế hoạch thác nước thường sẽ không nắm bắt được tất cả sự phức tạp của dự án phần mềm.

Bạn khẳng định rằng việc phát triển nhanh chóng mà không có "kế hoạch ban đầu" là:

"... không phải là cách thích hợp để tạo phần mềm ..."

Nếu vấn đề của bạn là kế hoạch ban đầu của bạn không đủ chi tiết, hãy dành thêm một chút thời gian để giải thích những suy nghĩ đầu tiên của bạn. Phần đầu tiên của chương trình bạn dự định viết là gì? Nó sẽ cần gì? Có lẽ thậm chí không nghĩ về những đối tượng để bắt đầu, thay vào đó hãy nghĩ về những tính năng và kế hoạch từ đó.

Nếu vấn đề của bạn là bạn không tự tin vào các kỹ năng tài liệu / thiết kế / UML của mình , hãy thực hành bằng cách ghi lại một dự án hiện có.

Cá nhân tôi khuyên bạn không nên lo lắng về việc thiết kế của bạn hoàn toàn hướng đối tượng, hầu hết các hệ thống không hướng đối tượng 100%. Mục tiêu là tạo ra sự hiểu biết và hình dung tốt hơn về hệ thống, chứ không phải sự trừu tượng hoàn hảo. Hướng đối tượng không phải là viên đạn bạc, nó chỉ là một công cụ khác trên vành đai.


Tôi cũng muốn đề cập, mặc dù hơi lạc đề cho câu trả lời ... Kế hoạch của bạn không cần phải quá lớn! Đôi khi một kế hoạch chỉ là vấn đề "Tôi muốn chạy nó và nó thực hiện một điều." Thế là đủ rồi, nếu đó thực sự là tất cả những gì nó sẽ làm.
Erdrik Ironrose

2

OOAD là một điều không tưởng. Điều đó không có nghĩa là đó là cách tiếp cận tốt nhất, ý tôi là nó không bao giờ thực sự đạt được theo quan điểm khiêm tốn của tôi. Theo kinh nghiệm của tôi, một cái gì đó luôn thay đổi, cho dù đó là yêu cầu hoặc chi tiết cụ thể, hoặc thậm chí là xung đột phụ thuộc buộc bạn phải thay thế hoàn toàn một phụ thuộc. Cho dù đó là vì tôi học theo cách này hay vì đó là điều tự nhiên nhất đối với tôi, ý tưởng của tôi về thiết kế đến dễ dàng nhất khi tôi đang viết mã. Nếu tôi sắp viết mã và tôi không có ý tưởng rõ ràng về cách tôi sẽ cấu trúc mã, tôi sẽ dành thời gian để thực sự hiểu vấn đề trước, mặc dù thường xuyên hơn là không, tôi thấy cần thiết cho một lớp học và tôi sẽ làm cho nó.

Lời khuyên của tôi là điều tốt nhất bạn có thể làm cho chính mình là sử dụng mã mặt tiền , cung cấp giao diện đơn giản cho đầu vào và đầu ra và hy vọng rằng đầu vào và đầu ra không thay đổi thường xuyên. Mặc dù ngay cả khi họ làm như vậy, hãy biết rằng đó không phải là vấn đề thiết kế nhiều vì đây là vấn đề về thông số kỹ thuật (thay đổi về sự cần thiết / hoạt động / chức năng). Điều này sẽ làm cho chương trình của bạn phần nào chống lại các vấn đề cộng hưởng trong chương trình của bạn đối với những người gọi chương trình hoặc phần mã của bạn và ngược lại.

Đối với những gì liên quan đến việc thiết kế một hệ thống hướng đối tượng, nên nói điều gì đó để cố gắng làm cho mọi thứ hướng đối tượng khi không nên. Đó là một lỗi phổ biến giữa các ngôn ngữ lập trình OOP như C # và Java là cố gắng coi mọi thứ là một đối tượng, điều này thường dẫn đến việc tạo ra một thể hiện của một lớp để thực hiện những phương thức tĩnh không thay đổi trạng thái nào. Điều đó nói rằng, tất nhiên bạn nên sử dụng thiết kế OOP khi áp dụng, mặc dù không cảm thấy như bạn đang làm sai khi cảm thấy tự nhiên hơn khi viết một phương thức tĩnh. Đó không phải lúc nào cũng là bản năng sai.

Bạn nên cân nhắc sử dụng một lớp học khi bạn trả lời có cho bất kỳ câu hỏi nào sau đây:

  • Tôi có một nhóm thông tin liên quan đến cùng một khái niệm (ví dụ tên, họ, địa chỉ) không?
  • Tôi có cần thực hiện một thao tác yêu cầu một vài thông tin (nghĩa là calculatePrice(basePrice, quantity, tax)) không?
  • Tôi có khác không nếu với các khối mã lớn thực hiện các hoạt động hơi khác nhau với cùng thông tin hoặc tương tự (ví dụ if(type == "cat") { meow(name); } else if (type == "dog") { bark(name); }==> animal.speak())
  • Tôi có một lớp hiện có thực hiện nhiều hơn một nhiệm vụ cụ thể và đang phát triển quá lớn không?

Sau một thời gian, nó sẽ trở thành bản chất thứ hai để tạo các lớp. Đừng ngại sử dụng chúng nếu mã của bạn rơi vào một trong những trường hợp trên. Tôi hy vọng điều đó sẽ giúp!


2

Tôi nghĩ rằng những điểm mà Doc Brown đưa ra trong các bình luận xứng đáng được nhìn thấy nhiều hơn so với một nhận xét vì anh ấy hoàn toàn đúng:

" Bây giờ tôi biết đây không phải là cách thích hợp để tạo phần mềm " - ai nói với bạn điều này? Dường như bằng cách nào đó bạn rơi vào cái bẫy phổ biến khi tin rằng "thiết kế là thứ bạn làm trước khi mã hóa, có thể bằng cách vẽ sơ đồ UML lạ mắt". Để cứu bạn khỏi quan niệm sai lầm này, tôi khuyên bạn nên bắt đầu với "Code as Design" của Jack Reeves. - Doc Brown ngày 21 tháng 6 lúc 5:27

@Laiv: "mã hóa" là một phần của những gì trong các ngành kỹ sư khác được gọi là thiết kế. Trong xây dựng nhà, bước từ thiết kế đến sản phẩm cuối cùng được thực hiện bằng cách sử dụng gạch và vữa. Trong lập trình, bước này được trình biên dịch thực hiện khi dịch thiết kế (= chương trình) thành sản phẩm cuối (= nhị phân thực thi). Và đó không phải là một trí tuệ mới. Tiểu luận Reeves 25 tuổi. - Doc Brown ngày 21 tháng 6 lúc 6:39

Tình cảm tương tự này cũng được lặp lại ở những nơi khác. Hãy xem xét các cuộc nói chuyện của Glenn Vanderburg về "Kỹ thuật phần mềm thực sự", và ở một mức độ nào đó các bài nói chuyện "Thủ công, Kỹ thuật và Tinh hoa lập trình" và "Kỹ thuật phần mềm và thủ công" của ông. Cũng nên có WhatIsSoftwareDesignTheSourceCodeIsTheDesign trang / thảo luận trên wiki C2.

Khái niệm mã là thiết kế không cụ thể cho bất kỳ mô hình nào. Nó có thể được áp dụng như nhau cho hướng đối tượng, chức năng, thủ tục, logic hoặc bất cứ điều gì khác. Ý tưởng cơ bản là như nhau - thiết kế là chính mã nguồn. Hành động xây dựng là quá trình mà mã nguồn (thiết kế) được biến thành một thứ có thể sử dụng được bởi một trình thông dịch hoặc trình biên dịch.

Trong một hệ thống phức tạp, có khả năng sẽ có một số thiết kế kiến ​​trúc tăng cấp - xác định các hệ thống con, thành phần, mô-đun, dịch vụ và phân bổ các yêu cầu cho chúng trước khi bạn bắt đầu viết mã. Bạn có thể sử dụng UML như một cách để tạo, tài liệu và hỗ trợ cho các cuộc thảo luận xung quanh thiết kế kiến ​​trúc này. Hãy xem xét ý tưởng về các Chế độ UML mà Martin Fowler thảo luận , đặc biệt là UML dưới dạng Phác thảoUML là Ghi chú . Cũng xem xét một số ý tưởng từ Mô hình hóa Agile - Mô hình kiến ​​trúc ban đầu , Mô hình lặpcác mô hình chỉ đủ tốt .

Tất cả điều này có nghĩa là cách đúng đắn để xây dựng phần mềm không phải là để bổ sung cho toàn bộ dự án. Đó là dành đủ thời gian để hiểu các yêu cầu quan trọng nhất (tại thời điểm hiện tại), xác định các phụ thuộc kỹ thuật và sự đánh đổi giữa các yêu cầu và sau đó tận dụng thực tế là phần mềm mềm. Cũng nhận ra rằng chi phí lấy thiết kế của bạn và sản xuất một cái gì đó là cực kỳ thấp (đặc biệt là so với việc thiết kế và sản xuất một cái gì đó trong nhiều ngành kỹ thuật khác). Vì vậy, lặp đi lặp lại các hoạt động thiết kế (mã hóa) của bạn và tận dụng mức độ dễ dàng và rẻ tiền để xây dựng hoặc sửa đổi dần dần những gì bạn đã làm.


1

OOAD là về việc xác định các thực thể và mô hình hóa các đối tượng hoặc khái niệm trong cuộc sống thực đến một mức độ trừu tượng. Ban đầu, bạn sẽ cảm thấy nó dễ dàng hơn nếu thay vì viết các lớp giao diện bằng văn bản, vì bạn không thực sự phải triển khai chúng, nhưng mã vẫn biên dịch.

OOAD không loại trừ khả năng suy nghĩ trong hệ thống như các mô-đun lớn. Bạn vẫn có thể làm điều đó. Mỗi mô-đun tồn tại để đáp ứng một tập các câu chuyện của người dùng (trường hợp sử dụng). Những câu chuyện người dùng như vậy cần các lớp cộng tác để hoàn thành chúng.

Một điểm khác biệt chính giữa các phương pháp tiếp cận OO theo thủ tục là thường suy nghĩ theo thủ tục ánh xạ các yêu cầu đối với màn hình, trong khi đó, Jim có xu hướng nghĩ về những gì xảy ra dưới mui xe do người khác thực hiện hoặc theo kiểu không phải OO.

Có một kỹ thuật trong Lập trình cực đoan được gọi là Thẻ CRC . CRC là viết tắt của "lớp-trách nhiệm-cộng tác viên".

Về cơ bản, bạn xác định các lớp rõ ràng và gán một thẻ cho mỗi người. Nói, lớp Invoicecó thẻ riêng của mình.

Đối với mỗi lớp giữ thẻ, bạn viết khả năng đáp ứng của lớp đó là gì, ví dụ "tính tổng cộng" .

Ngoài ra, đối với mỗi lớp giữ thẻ, bạn viết những lớp khác mà lớp đó phải yêu cầu một cái gì đó để thực hiện các khả năng đáp ứng của chính nó. Ở đây bạn có thể khám phá sự Invoicecần thiết của sự hợp tác InvoiceDetailhoặc thậm chí khám phá ra rằng một lớp như vậy là cần thiết ở nơi đầu tiên.

Bạn có thể khám phá ra rằng một số khả năng đáp ứng mà bạn nghĩ thuộc về Invoce, thực sự thuộc về một trong những cộng tác viên của nó.

Sau bài tập, mọi thẻ trở thành một lớp, mọi khả năng đáp ứng đều trở thành một phương thức và mọi mối quan hệ hợp tác có thể trở thành một thành phần, một sự kết hợp hoặc một cuộc gọi đơn thuần.

Điều đó có thể (và nên) được thực hiện trong một nhóm, trong đó ngay cả những người kinh doanh cụ thể.

Bạn có thể tìm hiểu thêm về kỹ thuật này trong các liên kết sau:

http://en.wikipedia.org/wiki/Class-responsibility-collaboration_card

http://www.extremeprogramming.org/rules/crccards.html

Ví dụ về thẻ CRC:

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây


0

Thách thức chính đối với chúng tôi, là một cộng đồng của những người thực hành phần mềm; cụ thể hơn là những người thực hành thiết kế hướng đối tượng, là việc cụ thể hóa tất cả các vấn đề / nhiệm vụ của chúng ta thành một đối tác lập trình. Có thể là nhiệm vụ - biểu diễn dưới dạng các chức năng hoặc có thể là diễn viên trong những nhiệm vụ - biểu diễn dưới dạng các giao diện / lớp học [lái xe về phía OOAD]. Khi chúng tôi phát triển thói quen thiết kế phần mềm của mình, bằng cách liên tục có được kiến ​​thức về các phương pháp / khung khác nhau. Quan điểm của chúng tôi ngày càng được cải tiến theo hướng tách biệt rõ ràng các đối tượng và đối tượng nào sẽ thực hiện chức năng nào.

Đối với việc chia nhỏ các vấn đề của bạn thành các vấn đề phụ với sự hiện diện của các vật thể xung quanh, bạn vẫn có thể thực hiện điều đó một cách thuận tiện, vì BẠN có toàn quyền kiểm soát tất cả các đối tượng bạn muốn có mặt. Bạn cũng có sự tiện lợi của việc truyền đạt bản chất và mục đích cho các đối tượng và giao diện của bạn. Tất cả bạn phải làm là, hình dung ra tuyên bố vấn đề và nghĩ về mục đích / chức năng nào có thể được truyền vào đối tượng nào.

Tôi sẽ cố gắng giải thích xa hơn với sự giúp đỡ của một ví dụ về phạm vi của ô tô và tôi sẽ làm nổi bật hai cách khác nhau để hình dung cùng một mô hình đối tượng.

Lấy một ví dụ về nhà sản xuất ô tô trải dài trên nhiều loại ô tô khác nhau: xe thương mại, xe tiêu dùng (xe mui trần, xe hatchback, toa xe ga), v.v.

Để nhà sản xuất rõ ràng có sự tách biệt về chủng loại và mục đích, có nhiều cách họ có thể tạo ra các lớp ở đó.

Nhà sản xuất xe OOAD

  1. Dựa trên danh mục (khu vực thị trường) của xe: Xe hạng nặng, xe tiêu dùng [sedan, hatchback, ga-wagon, v.v.]

  2. Dựa trên công suất động cơ & cách lái xe: 800-1500 CC,> 1500 CC, v.v.

Theo cách tốt nhất mà nhà sản xuất có thể truyền riêng các chức năng cho các đối tượng thuộc từng phân loại này, họ có thể chọn một thiết kế đối tượng cơ bản phù hợp và xây dựng mô hình trên đó.


Bạn bắt đầu ổn, nhưng sau đó, bit cuối cùng trông giống như ngụy biện mà OOD nói về việc phân loại mọi thứ thay vì nhóm các hành vi tương tự.
Pete Kirkham
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.