OOP có thực hiện đúng lời hứa sử dụng lại mã không? Có những lựa chọn thay thế nào để đạt được việc tái sử dụng mã?


56

Có lẽ lời hứa lớn nhất của việc sử dụng mô hình hướng đối tượng là tái sử dụng mã. Một số tranh chấp rằng điều này đã đạt được. Tại sao nó (không) đạt được?

Liệu mã tái sử dụng như OOP định nghĩa nó, làm cho các dự án hiệu quả hơn?

Hoặc dễ quản lý hơn? Hoặc dễ dàng hơn để duy trì? Hoặc với chất lượng hơn?

Có lẽ tất cả chúng ta đều đồng ý rằng tái sử dụng mã là một điều tốt, nhưng có một số cách để đạt được mục tiêu này. Câu hỏi là về phương pháp tái sử dụng mã được cung cấp bởi OOP. Đó có phải là một điều tốt? Có phương pháp nào tốt hơn để sử dụng lại mã so với định hướng đối tượng, phân lớp, đa hình, v.v.? Cách nào tốt hơn? Tại sao ?

Hãy cho chúng tôi kinh nghiệm của bạn với việc tái sử dụng OOP hoặc tái sử dụng mô hình khác.


3
Nhưng đó là một bản sao: lập trình
viên.stackexchange.com/questions/1059

7
Nó bổ sung, không trùng lặp chính xác. Tôi đọc lại để hiểu rõ hơn về sự khác biệt.
Maniero

Nếu bạn có thể bỏ phiếu và nghĩ rằng đây là một câu hỏi hữu ích hoặc nó có câu trả lời hữu ích dưới đây, vui lòng bỏ phiếu. Các trang web StackExchange cần phiếu bầu để xây dựng một cộng đồng tốt. Bạn có thể cho 30 phiếu mỗi ngày, đừng lãng phí chúng. Người dùng đặc biệt có uy tín cao và số phiếu bầu thấp được đưa ra xin vui lòng đọc này: meta.programmers.stackexchange.com/questions/393/ mẹo
Maniero

2
Một câu hỏi tương tự ở đây: lập trình
George Marian

2
@j_random_hacker: đọc các bình luận.
Maniero

Câu trả lời:


34

Tái sử dụng mã là một ý tưởng khá tốt. Không phải là một trong những tuyệt vời .

Tôi có một viễn cảnh được rút ra từ khoảng 30 năm công nghệ phần mềm, cố gắng "tái sử dụng".

Tôi bắt đầu nghiên cứu "tái sử dụng mã" như một chủ đề nghiên cứu từ những năm 80, sau khi phát hiện ra tôi đã sử dụng lại thiết kế của một hệ điều hành tôi xây dựng vào đầu những năm 70, cho một hệ điều hành khác mà tôi đã xây dựng vào cuối những năm 70.

Phần tốt của việc tái sử dụng mã là khả năng đôi khi sử dụng lại mã có từ trước trung thực. Nhưng thế giới đầy mã; Làm thế nào có thể tìm thấy những gì bạn muốn? Đây là những gì tôi gọi là Lời nguyền tái sử dụng :

Tôi là Santa Claus (ok Mã nguồn mở) và tôi có một túi gồm 1 tỷ thành phần phần mềm. Bạn có thể có bất kỳ một trong số họ.

Chúc may mắn lựa chọn.

Để giải quyết vấn đề tái sử dụng tốt:

  • người tái sử dụng cần xác định bằng cách nào đó những gì anh ta cần (chức năng, hiệu suất, ngôn ngữ đích, giả định môi trường, ...)
  • phải có một thư viện mã "tái sử dụng" được lập chỉ mục theo nhiều cách khác nhau theo các tiêu chí tiềm năng này
  • một số cơ chế phải tồn tại để chọn ra các yếu tố ứng cử viên (ở một tỷ yếu tố, bạn không thể xem xét tất cả các yếu tố cá nhân)
  • cần phải có một cách để mô tả đặc điểm cách xa các đặc điểm kỹ thuật của các ứng cử viên được chọn
  • một số quy trình thông thường nên tồn tại để cho phép người sử dụng sửa đổi mã có thể sử dụng lại được chọn (đây là đóng góp lớn nhất của OOP: bạn có thể chỉnh sửa một thành phần / đối tượng hiện có bằng cách ghi đè các vị trí của nó. OOP không cung cấp bất kỳ trợ giúp nào khác).
  • tất cả điều này rõ ràng phải rẻ hơn đơn giản là mã hóa lại

Hầu hết những gì đã được phát hiện trong nhiều năm qua là để mã có thể được sử dụng lại, nó phải được thiết kế cho mục đích đó hoặc nó chứa quá nhiều giả định ngầm định. Các thư viện tái sử dụng mã thành công nhất thực sự là khá nhỏ. Các thư viện và khung công tác có thể là mã "tái sử dụng" và chúng cực kỳ thành công; Java và C # thành công không phải vì chúng là những ngôn ngữ máy tính khá tốt, mà là vì chúng có sẵn các thư viện được thiết kế, triển khai và tài liệu rất lớn. Nhưng mọi người không nhìn vào mã nguồn trong các thư viện; họ chỉ đơn giản gọi một API có tài liệu tốt (được thiết kế để có thể sử dụng được).

Việc tái sử dụng mã nào chưa được thực hiện (OOP cũng không) cung cấp các lệnh cải thiện cường độ trong khả năng của chúng tôi đối với các hệ thống mã.

Tôi nghĩ lỗ hổng quan trọng là bất kỳ loại tái sử dụng mã nào đều bị hạn chế về cơ bản vì mã có quá nhiều giả định được xây dựng . Nếu bạn làm cho mã nhỏ, bạn giảm thiểu các giả định, nhưng sau đó chi phí để xây dựng từ đầu không quá lớn và lợi ích tái sử dụng không hiệu quả. Nếu bạn làm cho các đoạn mã lớn, chúng sẽ trở nên vô dụng trong một bối cảnh mới. Giống như Gulliver, chúng bị buộc vào bãi biển bởi hàng triệu sợi dây nhỏ và bạn chỉ đơn giản là không đủ khả năng để cắt tất cả.

Những gì chúng ta nên làm việc là sử dụng lại kiến ​​thức để xây dựng mã . Nếu chúng ta có thể làm điều này, thì chúng ta có thể áp dụng kiến ​​thức đó để xây dựng mã mà chúng ta cần, xử lý các giả định hiện tại.

Để làm điều này, người ta vẫn cần khả năng đặc tả tương tự để mô tả các thành phần phần mềm (bạn vẫn phải nói những gì bạn muốn!). Nhưng sau đó, bạn áp dụng kiến ​​thức "xây dựng" này vào các thông số kỹ thuật để tạo mã bạn muốn.

Là một cộng đồng, chúng tôi chưa giỏi về điều này. Nhưng mọi người làm điều đó mọi lúc; Tại sao chúng ta không thể tự động hóa nó? Có rất nhiều nghiên cứu, và điều này cho thấy nó có thể được thực hiện trong nhiều trường hợp.

Một phần chính của máy móc cần thiết cho việc này là các công cụ cơ học để chấp nhận "mô tả thành phần" (đây chỉ là các tài liệu chính thức và có thể được phân tích cú pháp như ngôn ngữ lập trình) và áp dụng các biến đổi chương trình cho chúng.

Trình biên dịch đã làm điều này: -} Và họ thực sự giỏi trong lớp vấn đề mà họ giải quyết.

Các mô hình UML với việc tạo mã là một nỗ lực để làm điều này. Không phải là một nỗ lực rất tốt; hầu như những gì người ta nói trong hầu hết các mô hình UML là "Tôi có dữ liệu giống như thế này". Khá khó để tạo ra một chương trình thực sự nếu chức năng bị bỏ qua.

Tôi đang cố gắng xây dựng các hệ thống chuyển đổi chương trình thực tế, một công cụ gọi là DMS . Đã bị phân tâm khá tốt bằng cách áp dụng các biến đổi chương trình không quá nhiều vào các đặc tả trừu tượng để tạo mã, mà thay vào đó là mã kế thừa để dọn sạch nó. (Đây là cùng một vấn đề trong bản tóm tắt!). (Để xây dựng các công cụ như vậy tốn rất nhiều thời gian; tôi đã làm việc này trong 15 năm và trong thời gian đó bạn phải ăn).

Nhưng DMS có hai thuộc tính chính mà tôi đã mô tả ở trên: khả năng xử lý các thông số kỹ thuật chính thức tùy ý và khả năng nắm bắt "kiến thức tạo mã" dưới dạng biến đổi và áp dụng chúng theo yêu cầu. Và đáng chú ý, chúng tôi tạo ra trong một số trường hợp đặc biệt, một số mã khá thú vị từ thông số kỹ thuật; DMS phần lớn được xây dựng bằng cách sử dụng chính nó để tạo ra việc thực hiện. Điều đó đã đạt được cho chúng tôi ít nhất một số lời hứa về việc sử dụng lại (kiến thức): tăng năng suất cực kỳ đáng kể. Tôi có một đội ngũ khoảng 7 người kỹ thuật; chúng tôi đã viết 1-2 MSLOC về "thông số kỹ thuật" cho DMS, nhưng có một số 10MSLOC mã được tạo.

Tóm tắt: tái sử dụng kiến ​​thức thế hệ là chiến thắng, không sử dụng lại mã .


4
IMHO, Câu trả lời tốt nhất. Điều quan trọng là tái sử dụng kiến ​​thức / ý tưởng, không phải mã.
kravemir 15/03/2015

4
Mostly what has been discovered over the years is that for code to be reusable, it sort of has to be designed for that purpose, or it contains too many implicit assumptions.Tôi đã đi đến một kết luận tương tự nhưng tôi không thể diễn đạt nó quá ngắn gọn.
biziclop

36

Sử dụng lại mã được đạt được trong OOP nhưng nó cũng đạt được trong lập trình chức năng. Bất cứ khi nào bạn lấy một khối mã và làm cho nó có thể gọi được bằng phần còn lại của mã để bạn có thể sử dụng chức năng này ở nơi khác là sử dụng lại mã.

Loại mã này sử dụng lại cũng làm cho mã dễ quản lý hơn vì việc thay đổi một khối có thể gọi này sẽ thay đổi tất cả các vị trí mà nó được gọi. Tôi muốn nói rằng kết quả này cũng tăng chất lượng và dễ đọc.

Tôi không chắc chắn OOP chỉ đơn giản là ở đó để cung cấp tái sử dụng mã. Tôi xem OOP như một cách để tương tác với các đối tượng và trừu tượng hóa các chi tiết của cấu trúc dữ liệu.

Từ Wikpedia:

Lập trình hướng đối tượng có nguồn gốc có thể bắt nguồn từ những năm 1960. Khi phần cứng và phần mềm ngày càng phức tạp, khả năng quản lý thường trở thành mối quan tâm. Các nhà nghiên cứu đã nghiên cứu các cách để duy trì chất lượng phần mềm và phát triển lập trình hướng đối tượng một phần để giải quyết các vấn đề phổ biến bằng cách nhấn mạnh mạnh vào các đơn vị logic lập trình rời rạc, có thể tái sử dụng [cần dẫn nguồn]. Công nghệ tập trung vào dữ liệu thay vì các quy trình, với các chương trình bao gồm các mô-đun tự cung cấp ("lớp"), mỗi trường hợp trong đó ("đối tượng") chứa tất cả thông tin cần thiết để thao tác cấu trúc dữ liệu của chính nó ("thành viên"). Điều này trái ngược với lập trình mô-đun hiện có, đã chiếm ưu thế trong nhiều năm, tập trung vào chức năng của một mô-đun, thay vì cụ thể là dữ liệu, nhưng được cung cấp đồng đều để sử dụng lại mã, và các đơn vị logic lập trình có thể tái sử dụng, cho phép cộng tác thông qua việc sử dụng các mô-đun được liên kết (chương trình con). Cách tiếp cận thông thường hơn, vẫn còn tồn tại, có xu hướng xem xét dữ liệu và hành vi một cách riêng biệt.


9
Lập trình chức năng +1 có thể là cách để sử dụng lại mã.
Jonas

1
@Matthieu M.: Chà, tái sử dụng như thế nào double sqrt (double x)? Các chức năng thuần túy là nguyên mẫu của tái sử dụng.
Joonas Pulakka

3
@Joonas: double sqrt(double x), float sqrt(float x), int sqrt(int x)bạn có thể định nghĩa rất nhiều trong số họ, trong khi với một ngôn ngữ lập trình Generic bạn sẽ có Number sqrt(Number x)và được thực hiện với nó.
Matthieu M.

1
@Matthieu M.: Thật vậy, thuốc generic làm giảm sự sao chép mã, vì vậy nó "tái sử dụng nhiều hơn", vâng. Tuy nhiên, tôi nghĩ rằng chìa khóa thực sự của khả năng sử dụng lại là xác định các hàm đơn giản, nhỏ, lành mạnh (thuần túy là hướng "lập trình chức năng") và chuyển chúng xung quanh, điều này có thể có trong C. Đó là về phong cách lập trình chung hơn là về khả năng của ngôn ngữ
Joonas Pulakka

1
@Joonas: Ah, tôi đã bỏ lỡ từ thuần túy , bạn nói đúng, việc soạn các hàm thuần túy nhỏ cũng rất tuyệt và thậm chí C còn có các con trỏ cho các hàm cho điều đó.
Matthieu M.

15

Có và không

Tái sử dụng mã là một thuật ngữ bắt tất cả cho nhiều hoạt động khác nhau.

  1. Mã tái sử dụng trong một dự án duy nhất. OO hoàn toàn phù hợp cho việc này, một ứng dụng được thiết kế tốt sẽ lập bản đồ các mối quan hệ của thế giới được mô hình hóa chặt chẽ, do đó loại bỏ mã trùng lặp càng nhiều càng tốt và nên làm. Tuy nhiên, bạn có thể lập luận rằng các công nghệ tiền OO có thể đạt được điều tương tự, đó là sự thật, nhưng OO theo nhiều cách thuận tiện hơn.
  2. Thư viện của bên thứ ba Điều này dường như hoạt động tốt như nhau có hoặc không có OO.
  3. Tái sử dụng mã đa mục đích Lời hứa tái sử dụng mã lớn nhất của OO là mã đó, một khi được viết cho một ứng dụng sau đó có thể được sử dụng lại cho một ứng dụng khác, mà nó đã được thiết kế riêng. Đây là tất cả những cơn thịnh nộ khi khái niệm OO được lọc qua cánh cửa của các văn phòng quản lý cao hơn và OO hoàn toàn không đạt được nó. Hóa ra mục đích đó là một khía cạnh quan trọng của thiết kế OO (và có thể là tất cả các mã thủ tục, nhưng đó chỉ là lý thuyết của tôi) và các nỗ lực tái sử dụng mã đã kết thúc trong thảm họa bảo trì. (Các antipotype nổi tiếng của một khung cũ không ai dám sửa đổi và người bạn của nó, các khung hơi khác nhau cho mọi ứng dụng thường xuất phát từ đây.)

13

Tôi sẽ đăng một câu trả lời dài nhưng tại sao? Udi Dahan giải thích nó tốt hơn nhiều so với tôi có thể.

http://www.udidahan.com/2009/06/07/the-fallacy-of-reuse/

Đây là phần đầu của bài viết:

Ngành công nghiệp này được sử dụng trước với tái sử dụng.

Có niềm tin rằng nếu chúng ta chỉ sử dụng lại nhiều mã hơn, mọi thứ sẽ tốt hơn.

Một số người thậm chí còn đi xa hơn khi nói rằng toàn bộ quan điểm hướng đối tượng là tái sử dụng - không phải vậy, đóng gói là vấn đề lớn. Sau đó, định hướng thành phần là thứ được cho là sử dụng lại. Rõ ràng điều đó cũng không thành công lắm bởi vì ở đây chúng ta hiện đang ghim những hy vọng tái định hướng của mình vào định hướng dịch vụ.

Toàn bộ sách về các mẫu đã được viết về cách sử dụng lại với định hướng trong ngày. Các dịch vụ đã được phân loại theo mọi cách để cố gắng đạt được điều này, từ các dịch vụ thực thể và dịch vụ hoạt động, thông qua các dịch vụ quy trình và dịch vụ điều phối. Dịch vụ soạn thảo đã được quảng cáo là chìa khóa để tái sử dụng và tạo ra các dịch vụ có thể sử dụng lại.

Tôi cũng có thể cho bạn biết về bí mật bẩn thỉu:

Tái sử dụng là một ngụy biện


4
-1. Ông Dahan đang bận tâm với những người rơm; không ai nghiêm túc sử dụng lại mã không chung chung như anh ta ngụ ý, và nếu bạn loại bỏ lập luận đó khỏi bài viết của anh ta, thì thực tế anh ta đang ủng hộ hoặc sử dụng lại mã một cách thích hợp .
Steven A. Lowe

3
@Steven A. Lowe Vâng, tôi ước điều đó là sự thật. Tôi ước tôi có được may mắn của bạn vì tôi đã thấy việc sử dụng lại mã ở dạng không chung chung. Nó không đẹp
Tony

1
Tôi chắc chắn là không - nhưng họ có nghiêm túc không? Dilbert.com/strips/comic/1996-01-31
Steven A. Lowe

1
Đồng ý, chi phí để tạo mã có thể tái sử dụng là rất cao, vì vậy nó không được đền đáp trừ khi bạn đang nói về quy mô của các lớp cơ sở Java hoặc .NET. Xem youtube.com/watch?v=aAb7hSCtvGw
Andomar

13

Tôi đồng ý với Chris, lập trình chức năng là một cách tốt để sử dụng lại mã.

Nhiều chương trình có cấu trúc mã được định kỳ. Đối với điều này, một số mẫu thiết kế được sử dụng trong thế giới OOP, nhưng điều này có thể đạt được bằng các hàm đệ quykhớp mẫu trong các ngôn ngữ lập trình chức năng. Để biết thêm về điều này, xem chương đầu tiên trong Lập trình chức năng thế giới thực .

Tôi nghĩ rằng sự kế thừa sâu sắc trong OOP có thể gây hiểu nhầm trong nhiều trường hợp. Bạn có một lớp và nhiều phương thức liên quan chặt chẽ được triển khai trong các tệp khác nhau. Như Joe Armstrong đã nói về OOP:

Vấn đề với các ngôn ngữ hướng đối tượng là chúng có tất cả môi trường ngầm mà chúng mang theo bên mình. Bạn muốn có một quả chuối nhưng những gì bạn nhận được là một con khỉ đột đang giữ quả chuối và toàn bộ khu rừng.

Các hàm bậc cao cũng rất hữu ích khi sử dụng lại mã, ví dụ mapfoldrđó là nền tảng cho MapReduce của Google .

Truyền tin nhắn không đồng bộ cũng là một cách tốt để tổ chức phần mềm phức tạp và một số nhà khoa học máy tính nói rằng các đối tượng được giả định là giao tiếp với nhau không đồng bộ như trong nguyên tắc Tell, đừng hỏi nguyên tắc OOP. Xem thêm về điều này trong Lập trình hướng đối tượng: Con đường sai? Joe Armstrong được trích dẫn:

Tôi bắt đầu tự hỏi về lập trình hướng đối tượng là gì và tôi nghĩ Erlang không hướng đối tượng, đó là ngôn ngữ lập trình chức năng. Sau đó, người giám sát luận án của tôi nói "Nhưng bạn đã sai, Erlang cực kỳ hướng đối tượng". Ông nói các ngôn ngữ hướng đối tượng không hướng đối tượng. Tôi có thể nghĩ, mặc dù tôi không chắc là mình có tin hay không, nhưng Erlang có thể là ngôn ngữ hướng đối tượng duy nhất bởi vì 3 nguyên lý lập trình hướng đối tượng là dựa trên thông điệp truyền qua , rằng bạn có sự cô lập giữa các đối tượng và có tính đa hình .

Thông điệp không đồng bộ truyền như trong các hệ thống hướng sự kiện và trong Erlang cũng là một cách rất tốt để tách rời các hệ thống và khớp nối lỏng lẻo rất quan trọng trong các hệ thống phức tạp. Với một hệ thống tách rời đủ, bạn có thể phát triển hệ thống trong khi nó đang chạy, có thể trên các nút khác nhau. Unibet đã trình bày tuyệt vời về điều này: Kiến trúc hướng sự kiện miền

Tuy nhiên tôi nghĩ rằng hầu hết việc sử dụng lại mã được thực hiện bằng cách sử dụng các thư viện và khung.


2
Tôi thích câu nói đó của Gorilla. ^^
gablin

Tôi nghĩ rằng câu hỏi là về tái sử dụng mã, không đúng ngữ nghĩa ..?
Daniel Lubarov

6

Ống unix khiêm tốn đã làm nhiều hơn cho việc tái sử dụng mã hơn bất kỳ thứ gì khác đến và đi. Các đối tượng chỉ là một cách trực quan để cấu trúc mã khi chúng xuất hiện và sau đó mọi người bắt đầu giải quyết mọi thứ và mọi thứ trên đó. Trong các đối tượng chung là để đóng gói và không sử dụng lại mã, việc sử dụng lại mã đòi hỏi một cái gì đó nhiều hơn và hệ thống phân cấp kế thừa lớp là một sự thay thế kém cho cơ chế sử dụng lại mã thực sự.


4

OOP không có gì đặc biệt; bạn có thể tạo mã có thể tái sử dụng có hoặc không có OOP. Các hàm thuần túy có thể tái sử dụng đặc biệt : ví dụ: java.lang.math.sqrt(double)lấy một số trong và đưa ra một số. Không có OOP, nhưng chắc chắn có thể tái sử dụng nhiều hơn hầu hết các mã ngoài kia.


4

Từ quan điểm lập trình chức năng, OOP chủ yếu là về quản lý trạng thái.

Trong lập trình chức năng, bạn có thể dễ dàng có hàng trăm chức năng hữu ích cho danh sách: http://haskell.org/ghc/docs/6.12.1/html/lologists/base-4.2.0.0/Data-List.html .

Bạn có hàng trăm phương thức trong một lớp List không? Các phương thức công khai được coi là một giao diện cho trạng thái bên trong mà bạn muốn giữ nhỏ.

Đáng buồn thay, thay vì (tái) sử dụng nhiều chức năng nhỏ, một số người lại nhân đôi chức năng. Đối với tôi đó là vì OOP không khuyến khích tái sử dụng mã nhiều như lập trình chức năng.


1
Kết luận của bạn đều sai, @ Lenny222. Không có gì về OOP yêu cầu các lớp duy trì trạng thái. Đó là một câu hỏi về kiến ​​trúc của nó cho dù nó lưu trữ trạng thái bên trong hoặc, như các lớp Integer của Smalltalk, khởi tạo các đối tượng mới với trạng thái mới.
Huperniketes

1
Tôi xin lỗi vì tôi đã không thể hiện bản thân theo cách ngăn chặn sự hiểu lầm này: điều tôi muốn nói là sự khác biệt giữa OOP và FP không phải là OOP ecourages sử dụng lại mã nhiều hơn FP (điều mà tiêu đề ngụ ý). Tôi đã trải nghiệm tái sử dụng mã tốt hơn nhiều với FP. Nếu bạn chỉ có các lớp bất biến, bạn đang mô phỏng FP, tại sao lại bắt đầu OOP? Trong POV của tôi, đó là về quản lý nhà nước bắt buộc.
LennyProgrammer

3

Đối với tôi, có, nhưng không phải tất cả thời gian, và nó có thể đã được thực hiện theo những cách khác.

Hầu hết thời gian bằng cách tạo ra một lớp cơ sở trừu tượng và tạo ra các triển khai cụ thể của lớp đó.

Ngoài ra, nhiều khung công tác sử dụng tính kế thừa để cung cấp việc sử dụng lại mã (Delphi, Java, .Net chỉ là một số mà ngay lập tức nảy ra trong đầu).

Điều đó không có nghĩa là rất nhiều thư viện tiện ích và đoạn mã không thể thực hiện được công việc, nhưng có điều gì đó làm hài lòng về hệ thống phân cấp đối tượng được thiết kế tốt.


3

Theo kinh nghiệm của tôi, tôi đã thành công hơn khi tận dụng mã "tái sử dụng" thông qua các cơ sở lập trình chung (như các mẫu C ++) so với việc tôi đã sử dụng các nguyên tắc OOP như hệ thống phân cấp thừa kế.


2

OOP quá mở để tái sử dụng hiệu quả.

Có quá nhiều cách để sử dụng lại. Mỗi lớp học công khai hỏi: "tạo một ví dụ mới về tôi!" , mỗi phương thức công khai nói: "hãy gọi cho tôi!" , mỗi phương thức được bảo vệ mang lại: "ghi đè lên tôi!" - và tất cả các cách sử dụng lại này đều khác nhau , chúng có các tham số khác nhau, chúng xuất hiện trong các ngữ cảnh khác nhau, tất cả đều có các quy tắc khác nhau, cách gọi / mở rộng / ghi đè lên nó.

API tốt hơn, đó là một tập hợp con nghiêm ngặt của các điểm OOP (hoặc không phải là oop), nhưng trong thực tế, các API bị quá tải và phát triển mãi mãi, vẫn còn quá nhiều điểm kết nối. Ngoài ra, một API tốt có thể giúp cuộc sống dễ dàng hơn, đó là cách tốt nhất để cung cấp giao diện cho OOP.


Mô hình Datadlow cung cấp một giao diện nghiêm ngặt cho các thành phần, chúng có các cổng thuộc các loại sau:

  • người tiêu dùng (đầu vào), và
  • nhà sản xuất (đầu ra).

Phụ thuộc vào tên miền, có một số loại gói, vì vậy người tiêu dùng và nhà sản xuất có thể được kết nối với họ có cùng cổng (hoặc tương thích). Phần đẹp nhất của nó, nó có thể được thực hiện một cách trực quan, bởi vì không có thông số hoặc điều chỉnh orher nào trên các kết nối, chúng thực sự chỉ kết nối người tiêu dùng và nhà sản xuất.

Tôi đã không rõ ràng một chút, bạn có thể xem thẻ "dataflow" trên StackOverflow hoặc Wikipedia "lập trình datafow" hoặc Wikipedia "lập trình dựa trên dòng chảy" .

(Ngoài ra, tôi đã viết một hệ thống dataflow, bằng C ++. Vì vậy, OOP và DF không phải là kẻ thù, DF là một cách tổ chức cấp cao hơn.)


2

Trong CommonLisp có rất nhiều phương tiện để đạt được mục đích sử dụng lại:

  • gõ động, có mã của bạn là chung theo mặc định

  • trừu tượng bắt buộc, tức là chương trình con

  • hướng đối tượng, với nhiều kế thừa nhiều công văn

  • trừu tượng cú pháp, khả năng xác định cấu trúc cú pháp mới hoặc viết tắt mã nồi hơi

  • trừu tượng chức năng, đóng cửa và chức năng bậc cao

Nếu bạn cố gắng so sánh trải nghiệm CommonLisp với các ngôn ngữ khác, bạn sẽ thấy rằng tính năng chính giúp giảm bớt việc sử dụng lại mã là sự hiện diện của cả trừu tượng hướng đối tượng và chức năng. Chúng bổ sung hơn là thay thế: không có một trong số chúng, bạn buộc phải thực hiện lại các tính năng còn thiếu một cách vụng về. Xem, ví dụ, các lớp functor được sử dụng như các bao đóng và khớp mẫu để có được phương thức không thể mở rộng.


1

Thực sự không có thứ gọi là "tái sử dụng" theo cách mà mọi người mô tả. Tái sử dụng là một tài sản tình cờ của bất cứ điều gì. Thật khó để lên kế hoạch cho nó. Điều mà hầu hết mọi người có nghĩa là khi họ nói về "tái sử dụng" là "sử dụng". Đó là một thuật ngữ kém hấp dẫn và thú vị. Khi bạn sử dụng một thư viện, thông thường bạn đang sử dụng nó cho mục đích của nó. Bạn không tái sử dụng nó trừ khi bạn đang làm điều gì đó thực sự điên rồ với nó.

Theo nghĩa đó, tái sử dụng trong thế giới thực là về việc tái sử dụng mọi thứ. Tôi có thể tái sử dụng những chỗ ngồi này ở đây và sắp xếp lại chúng để tạo thành ... một chiếc giường! Không phải là một chiếc giường rất thoải mái, nhưng tôi có thể làm điều đó. Đó không phải là sử dụng chính của họ. Tôi đang tái sử dụng chúng bên ngoài phạm vi ứng dụng ban đầu của chúng. [...] Ngày mai, tôi sẽ bay trở lại Vương quốc Anh. Tôi sẽ không sử dụng lại máy bay. Tôi sẽ chỉ sử dụng nó cho mục đích mà nó đã được dự định, không có gì lạ mắt hay thú vị về điều đó.

- Kevlin Henney


3
Mọi người sẽ tin bất cứ điều gì họ nhìn thấy trong bản in. Kevlin Henney không chính xác và dựa trên lý luận của ông về việc thiếu bối cảnh lịch sử và diễn giải ngữ nghĩa kém. Sử dụng lại mã là một nguyên tắc lập trình cơ bản từ thời của máy tính ống chân không UNIVAC và IBM. Việc sử dụng lại mã không phải là về việc tái sử dụng nó cho một số chức năng khác với chức năng mà nó đã được lên kế hoạch . Bạn đã viết và tập hợp (sau này nó được biên dịch) các thường trình con của bạn để tạo mã đối tượng mà sau đó được liên kết vào chương trình của bạn. Tái sử dụng thực sự có nghĩa là những gì nó thường được hiểu là trong ngành công nghiệp ngày nay.
Huperniketes

Nếu bạn viết hai hàm thực hiện chính xác cùng một thứ, bạn KHÔNG sử dụng lại mã cho dù bạn đã sử dụng chúng bao nhiêu lần.
JeffO

Sự tương tự ghế là tốt đẹp và tất cả những điều đó nhưng chỉ một từ: Lego.
biziclop

1

Tôi sẽ mạo hiểm chế giễu và thú nhận, tôi mới chỉ sử dụng OOP gần đây. Nó không tự động đến với tôi. Hầu hết kinh nghiệm của tôi liên quan đến cơ sở dữ liệu quan hệ, vì vậy tôi nghĩ trong các bảng và tham gia. Có những tuyên bố rằng tốt hơn là học nó ngay từ đầu để tránh phải điều chỉnh lại suy nghĩ của bạn khi nói đến lập trình. Tôi không có sự xa xỉ đó và từ chối bỏ sự nghiệp của mình qua một số lý thuyết tháp ngà. Giống như mọi thứ khác, tôi sẽ tìm ra nó.

Lúc đầu, tôi nghĩ rằng toàn bộ khái niệm này không có ý nghĩa. Nó chỉ có vẻ không cần thiết và quá nhiều rắc rối. Tôi biết, đây là một cuộc nói chuyện điên rồ. Rõ ràng nó cần một mức độ hiểu biết nhất định trước khi bạn có thể đánh giá cao lợi ích của bất cứ điều gì hoặc loại bỏ nó cho các phương pháp tốt hơn.

Tái sử dụng mã có sẵn sàng không lặp lại mã, sự hiểu biết về cách thực hiện nó, lập kế hoạch trả trước. Bạn có nên tránh sử dụng lại mã khi bạn quyết định rằng bạn có một trường hợp không xứng đáng? Và không có ngôn ngữ nào nghiêm ngặt OO đến nỗi nó sẽ gây ra lỗi khi nó nghĩ rằng bạn nên thừa kế mã từ một lớp khác. Tốt nhất họ cung cấp một môi trường thuận lợi để thực hiện nó.

Tôi nghĩ lợi ích lớn nhất của OOP là sự chấp nhận chung về cách tổ chức mã. Mọi thứ khác là nước thịt. Một nhóm lập trình viên có thể không hoàn toàn đồng ý về cách tất cả các lớp nên được cấu trúc, nhưng họ sẽ có thể tìm thấy mã.

Tôi đã thấy đủ mã thủ tục để biết nó có thể ở bất cứ đâu và đôi khi nó ở mọi nơi.


"Và không có ngôn ngữ nào nghiêm túc đến mức OO sẽ gây ra lỗi khi nó nghĩ rằng bạn nên thừa kế mã từ một lớp khác" - dù sao, dù sao đi nữa!
Steven A. Lowe

1

OOP cung cấp cho bạn nhiều cách hơn để sử dụng lại mã. Đó là tất cả.


OOP cũng thúc đẩy tái sử dụng giao diện và tái sử dụng thiết kế.
rwong

Nó cung cấp cho tôi ít cách viết mã chung, có thể tái sử dụng, trừu tượng cao hơn các mô hình khác, chẳng hạn như lập trình chức năng (currying, thư viện tổ hợp, v.v.) và siêu lập trình. Trên thực tế, OOP dường như có một mức độ trừu tượng, khi các lựa chọn thay thế hoàn toàn không bị giới hạn.
SK-logic

@ SK-logic: trực giao.
Steven A. Lowe

1

Tái sử dụng theo chiều ngang: các khía cạnh, đặc điểm, ghép

OO cổ điển đôi khi không được sử dụng lại mã, đặc biệt khi bạn phát điên vì thừa kế vì không có cách nào tốt hơn để chia sẻ chức năng thực tế giữa các lớp. Đối với vấn đề này, các cơ chế tái sử dụng ngang đã được tạo ra, chẳng hạn như AOP, các đặc điểm và ghép.

Lập trình định hướng theo khía cạnh

Tôi coi AOP là nửa cam còn thiếu của OOP. AOP không thực sự được biết đến, nhưng nó đã được đưa vào mã sản xuất.

Tôi sẽ thử giải thích bằng các thuật ngữ đơn giản: hãy tưởng tượng rằng bạn có thể tiêm và lọc chức năng với một cấu trúc đặc biệt gọi là một khía cạnh, các khía cạnh này có "phương thức" xác định những gì và sẽ bị ảnh hưởng như thế nào thông qua phản xạ , nhưng tại thời điểm biên dịch , quá trình này được gọi là dệt .

Một ví dụ sẽ là một khía cạnh cho biết "đối với tất cả các phương thức của một số lớp bắt đầu bằng get, chương trình của bạn sẽ ghi vào một tệp nhật ký dữ liệu đã nhận và thời gian nhận được".

Xem hai bài nói chuyện này nếu bạn muốn hiểu rõ hơn về AOP:

Đặc điểm & Ghép

Các đặc điểm là một cấu trúc khác để xác định mã có thể tái sử dụng bổ sung cho OOP, chúng tương tự như mixins , nhưng sạch hơn.

Thay vì giải thích chúng, có một RFC PHP tuyệt vời giải thích cả hai . Các đặc điểm đang đến với btw PHP, chúng đã được cam kết vào thân cây.

Tóm tắt

OOP là chìa khóa trong mô-đun, theo quan điểm của tôi và như chúng ta thường biết ngày nay OOP vẫn chưa hoàn thiện .


0

OOP Cung cấp một bộ các công cụ hữu ích cho phép bạn viết mã có thể được sử dụng ở nhiều nơi hơn bạn có thể có mà không cần các công cụ đó. Nếu bạn viết một PrintIthàm lấy bất kỳ đối tượng cũ nào và gọi .toString()nó, bạn sẽ sử dụng lại mã đó ngay khi bạn gọi nó với nhiều hơn một loại đối tượng. Với các công cụ này, mỗi dòng mã làm được nhiều hơn.

Lập trình chức năng là rất nóng ngay bây giờ trong số các hipster. Nó cung cấp cho bạn một bộ công cụ hoàn toàn riêng biệt để làm cho mỗi dòng mã làm được nhiều hơn. Nó có thể không tốt hơn hoặc hoạt động, nhưng cung cấp một công cụ khác trong hộp công cụ.

(Có một ý tưởng điên rồ cho toàn bộ mức độ sử dụng lại hướng đối tượng: Ý tưởng là chúng ta có thể định nghĩa một Customerlớp duy nhất và sử dụng nó trong mọi ứng dụng chúng ta đã viết. Sau đó, các ứng dụng sẽ chỉ là một chút keo ở đây và đó. không hoạt động. Nhưng điều đó không có nghĩa là OO thất bại, hoặc thậm chí việc sử dụng lại không thành công. Các loại mã cơ bản được sử dụng lại trong các ứng dụng giúp viết các ứng dụng đã làm được nhiều hơn và viết chúng nhanh hơn.)


0

Đọc các bài viết trên, một vài nhận xét:

  • Nhiều người nghĩ rằng tái sử dụng mã trong OOP ngụ ý sự kế thừa. Tôi không đồng ý. Các giao diện và hợp đồng là cốt lõi để tái sử dụng mã trong các hệ thống OOP. OOP là một nỗ lực hộp màu xám trong việc tạo ra một công nghệ thành phần.
  • Sự khác biệt giữa các "khung" cụ thể và tên miền chung như là chủ đề của việc sử dụng lại cho rằng tôi quá trừu tượng. Theo quan điểm của tôi về mọi thứ, một thành phần (một hợp đồng giao diện ngắn gọn, tối thiểu và có thể sử dụng lại và việc thực hiện phía sau) chỉ có thể được thực hiện, nếu vấn đề mà nó giải quyết được hiểu rõ. Một thành phần cụ thể của miền, cho phép các chuyên gia không thuộc miền thực hiện công việc của họ với ít kiến ​​thức về tên miền là một thành phần hữu ích (lại). Người dùng cần phải hiểu giao diện, vì vậy sự phức tạp của miền vấn đề.
  • Các mức độ sử dụng lại thường bị lãng quên: Tái sử dụng ý tưởng, tái sử dụng Đặc điểm kỹ thuật, Sử dụng lại Kiến trúc / Thiết kế, Tái sử dụng Giao diện, Sử dụng lại trường hợp thử nghiệm. Mã sử ​​dụng lại không phải lúc nào cũng thuận lợi. Nhưng đó là một tiết kiệm thời gian lớn thường bám vào một kiến ​​trúc cụ thể để giải quyết một sản phẩm mới, tương tự.
  • Các mẫu Thiết kế OOP (Gamma và cộng sự) trong mắt tôi đã xây dựng các kỹ thuật triển khai chiến thuật thay vì có ý nghĩa trong bối cảnh sử dụng lại mã ở quy mô lớn hơn. Chúng giúp viết một ứng dụng với các phần tử OOP, tuy nhiên tôi sẽ không xem chúng là một giải pháp cho câu hỏi "sử dụng lại mã" ngoài một ứng dụng.
  • Có thể nó không công bằng: 20 năm kinh nghiệm C / C ++ / C # và 6 tháng lập trình chức năng (F #). Một yếu tố chính của việc cho phép sử dụng lại là: Mọi người cần dễ dàng tìm thấy "giao diện", nghiên cứu nó, hiểu nó, sau đó sử dụng nó. Lập trình chức năng thuần túy không giúp tôi dễ dàng nhìn thấy cấu trúc, các ứng cử viên để sử dụng lại hoặc nơi tất cả bắt đầu và nơi tất cả kết thúc. "Đường cú pháp" được ca ngợi thường là muối trong mắt tôi, ngăn tôi dễ dàng nhìn thấy những gì xảy ra. Do đó, tôi ít có khả năng cố gắng sử dụng lại một chức năng (đó là gì - bó chức năng?), Có thể có tác dụng phụ ẩn mà tôi thậm chí không thể nhìn thấy (đánh giá lười biếng, đơn nguyên, ...). Đừng hiểu sai ý tôi, lập trình chức năng có những mặt rất hay, nhưng tất cả những điểm mạnh được tuyên bố tôi thấy với một biện pháp nghi ngờ tốt.
  • Đặc điểm kỹ thuật, thiết kế, triển khai được kết hợp, nhưng không dễ dàng vượt qua các quan điểm về "điều tương tự". Quan trọng hơn nhiều đối với tăng năng suất trong tương lai so với mô hình lập trình mới là, để thu hẹp khoảng cách, tăng (lý luận tự động, truy xuất nguồn gốc) các lợi ích chung giữa các quan điểm đó. Các ngôn ngữ đặc tả được chính thức hóa, các ký hiệu kiểm tra được tiêu chuẩn hóa (ví dụ: ttcn3) và các ngôn ngữ lập trình hỗ trợ xác minh các giao diện và hợp đồng đối với các thông số kỹ thuật mà không cần bình luận có thể là những gì chúng ta cần gấp nhất.

0

Vấn đề là imho tinh tế hơn:

  1. OOP là một phương pháp tuyệt vời để cấu trúc mã với trạng thái có thể thay đổi . Bằng cách đóng gói trạng thái vào các đối tượng, mã trạng thái bắt buộc trở nên dễ hiểu hơn bởi vì, ví dụ, nếu một phần trạng thái được biểu thị dưới dạng các trường riêng của một lớp, bạn biết rằng ít nhất đoạn trạng thái cụ thể này chỉ có thể được sửa đổi bằng các phương thức này lớp học. (Và bạn có thể dễ dàng phá vỡ lợi ích này bằng cách lạm dụng quyền thừa kế, btw.) Điều này bây giờ là đủ, nhưng waaay tốt hơn là không có ngay cả điều này.
  2. mã với trạng thái có thể thay đổi vốn đã khó sử dụng lại . Cách khó hơn mã sử dụng cấu trúc dữ liệu bất biến.

Vì vậy, bản thân OOP không tệ khi tạo ra mã có thể tái sử dụng , nhưng các loại mã được viết bằng OOP vốn đã khó sử dụng lại .

Ngoài ra, lập trình chức năng có thể dẫn đến mã tái sử dụng nhiều hơn . Nhưng có được sự trừu tượng ngay để viết mã chức năng lành mạnh trong khi đáp ứng thời hạn có thể không thực hiện được. Và trừu tượng "nửa phải" sẽ dễ dàng hơn để thể hiện phong cách OOP. Và nó sẽ không có xu hướng dẫn đến việc sử dụng lại mã dễ dàng hơn - mức độ trừu tượng cao hơn có nghĩa là việc hiểu mã sẽ đòi hỏi một khoản đầu tư trả trước cao hơn từ năng lực nhận thức hạn chế của lập trình viên.

Như một ví dụ thực tế: Mã trò chơi bao gồm rất nhiều trạng thái có thể thay đổi, bởi vì đây là cách tự nhiên để suy nghĩ về mã hóa trò chơi, trừ khi đó là một câu đố rất thuật toán / thuật toán, vì vậy rõ ràng cuối cùng nó được cấu trúc bằng OO. Và tất nhiên là khó sử dụng lại. Nhưng cùng một mã, chứa cùng một kiến ​​thức, sẽ khó sử dụng hơn nếu không có OOP . Và viết lại nó thành phong cách chức năng có thể cần thay đổi hoàn toàn cách bạn nghĩ về mã đó, kiến ​​thức đằng sau nó. Vâng, kiến thức thu được đằng sau mã sẽ rõ ràng hơn nhiều sau khi viết lại OO thành FP có thể ... nhưng chi phí có thể rất lớn và nó có thể làloại chi phí cũng sẽ phải trả cho những người muốn sử dụng lại mã cực kỳ thông minh và trừu tượng mà bạn kết thúc , thật nghịch lý, mọi người cuối cùng sẽ không sử dụng lại mã, ngay cả khi về mặt kỹ thuật nó có thể tái sử dụng nhiều hơn.

... dẫn đến sự tinh tế cuối cùng: tái sử dụng mã là về giao diện People | Code , không phải về mã. OOP thực hiện tốt công việc phục vụ giao diện này vì nó ánh xạ tốt với số lượng người nghĩ về nhiều loại mã được viết hiện nay. FP có thể tốt hơn cho việc tái sử dụng mã, nhưng imho không dễ dàng sử dụng lại loại mã mà mọi người thực sự cần phải viết ngày nay. Điều này sẽ thay đổi như loại mã mà chúng ta cần viết thay đổi.

PS Và nếu bất cứ ai muốn nói rằng "OO không phải là về trạng thái có thể thay đổi, bạn cũng có thể có OO với trạng thái bất biến" ... Tôi gọi đó là "FP sử dụng các lớp làm không gian tên". Thật tuyệt vời khi nó hoạt động cho bạn và nó tránh được một số thiếu sót của một số hệ thống mô-đun ngôn ngữ và có thể dẫn đến mã có thể tái sử dụng nhiều hơn. Nhưng đó không phải là OO;)

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.