Các mô hình không OOP có hỗ trợ các khái niệm như đóng gói không?


12

Một trong những khái niệm quan trọng trong lập trình hướng đối tượng là Encapsulation. Tuy nhiên, gần đây thế giới phần mềm dường như đang nghiêng về các mô hình khác như lập trình chức năng.

Nó làm tôi suy nghĩ, còn về đóng gói và các nguyên lý OOP khác thì sao? Họ có sai không?

Có phải OOP được áp dụng sai? Chẳng hạn, Alan Kay được chú ý khi nói trong Bài phát biểu OOPSLA'97: "Tôi đã phát minh ra thuật ngữ hướng đối tượng và tôi có thể nói với bạn rằng tôi không có C ++ trong đầu."

Joe Armstrong - "Các đối tượng liên kết các chức năng và cấu trúc dữ liệu với nhau thành các đơn vị không thể chia tách. Tôi nghĩ đây là một lỗi cơ bản vì các chức năng và cấu trúc dữ liệu thuộc về các thế giới hoàn toàn khác nhau."




2
Tôi muốn nói rằng câu hỏi trước tiên cần làm rõ ý nghĩa của Encapsulation và ý nghĩa của ngôn ngữ để hỗ trợ nó.
Euphoric

14
Tôi đang gặp khó khăn để tìm ra những gì câu hỏi này đang hỏi. Có phải nó hỏi liệu đóng gói có thể tồn tại bên ngoài OO (dòng chủ đề) không? Có phải nó hỏi liệu đóng gói là sai (đoạn thứ hai)? Có phải nó hỏi liệu OO được áp dụng sai (đoạn thứ ba)? Và OP muốn nói gì với câu nói đó của Joe Armstrong? OP định nghĩa "đóng gói" như thế nào? OP định nghĩa "OO" như thế nào? Những "nguyên lý khác" là gì?
Jörg W Mittag

1
Robert Martin đã từng nói rằng OOP đã đóng gói đi và sau đó vá nó lại bằng những vụ hack khủng khiếp. "Chúng tôi đã đóng gói hoàn hảo trước oo". Tất nhiên anh ấy là người quá khích, nhưng bây giờ mỗi khi tôi thấy ai đó nói rằng OO là về đóng gói, tôi nhớ đến chú Bob.
GnP

Câu trả lời:


15

Tôi nghĩ cái bẫy bạn rơi vào đây đang nghĩ rằng có một định nghĩa cứng nhắc về bất kỳ mô hình lập trình nào (có cấu trúc, hướng đối tượng, chức năng, và các cộng sự).

Nếu bạn hỏi hai nhà phát triển khác nhau về ý nghĩa của OOP, bạn sẽ nhận được hai câu trả lời khác nhau. Vâng, như một nghề nghiệp, chúng tôi đồng ý rằng có một vài chủ đề phổ biến như đóng gói, ẩn dữ liệu, v.v. được bao phủ bởi bất kỳ lớp kỹ thuật phần mềm OOP nào ở trường đại học.

Tuy nhiên , trong thế giới thực, mọi thứ không hoàn toàn bị cắt và khô, đó là lý do tại sao hai nhà phát triển sẽ đưa ra hai câu trả lời khác nhau. Có lẽ họ là chuyên gia trong các ngôn ngữ khác nhau thể hiện các khái niệm OOP khác nhau. Mô hình ngôn ngữ có xu hướng chồng chéo. Cơn thịnh nộ mới nhất tính đến năm 2013 hoặc lâu hơn là kết hợp lập trình chức năng trong các ngôn ngữ hướng đối tượng thông qua việc đóng cửa hoặc lambdas. Java 8 hướng đối tượng hay chức năng? Tôi sẽ gọi nó là hướng đối tượng với một chút chức năng. Một số người khác có thể mô tả nó khác nhau.

Có phải OOP được áp dụng sai?

Không, vấn đề là các ngôn ngữ khác nhau thể hiện các khái niệm lập trình khác nhau. Có lẽ một ngôn ngữ bỏ qua một khái niệm OOP và một ngôn ngữ khác bao gồm nó nhưng lại bỏ qua một khái niệm OOP khác. Các ngôn ngữ thường được thiết kế cho một mục đích: làm cho một loại nhiệm vụ nhất định trở nên dễ dàng, với chi phí làm cho các nhiệm vụ khác trở nên khó khăn hơn. Điều đó không đúng cũng không sai, nó chỉ đơn giản là một sự đánh đổi trong thế giới thực không thể tránh khỏi.

Thế giới thực không phải là lớp học. Chúng ta hoặc cần thảo luận về các mô hình lập trình khái niệm ở cấp độ trừu tượng, hoặc chúng ta cần thảo luận về các ngôn ngữ lập trình thực sự buộc phải thực hiện sự đánh đổi để có ích. Miễn là một ngôn ngữ lập trình hầu hết được định nghĩa bởi một định nghĩa trừu tượng về OOP, chúng ta có thể đưa nó vào nhóm đó.


10

Tuy nhiên, gần đây thế giới phần mềm dường như đang nghiêng về các mô hình khác như lập trình chức năng.

Đó là tranh cãi. Đầu tiên, tôi không thấy bất kỳ mô hình nào khác ngoài OOP và lập trình chức năng được thảo luận rộng rãi, vì vậy tôi đoán chúng ta có thể quên cụm từ "mô hình khác như" , chúng ta hãy nói về FP, không có gì khác.

Những lý do tại sao lập trình chức năng trở nên phổ biến trong những năm qua đã được thảo luận trong các câu hỏi khác ở đây, tôi sẽ không lặp lại điều này ( ví dụ ở đây hoặc ở đây ). Nhưng, theo tôi, đây không phải là vì "OOP là một sai lầm lớn" hay "Chức năng so với OOP là loại trừ lẫn nhau", nó giống như mọi người mở rộng hộp công cụ của họ và cố gắng tận dụng tốt nhất cả hai thế giới. Ok, chắc chắn có những chuyên gia là những người cứng rắn ủng hộ người này hơn người kia, nhưng bạn sẽ tìm thấy những kẻ đó ở cả hai phía.

Nó làm tôi suy nghĩ, còn về đóng gói và các nguyên lý OOP khác thì sao? Họ có sai không?

Đóng gói có nhiều hương vị khác nhau. Các ngôn ngữ lập trình chức năng và các cấu trúc ngôn ngữ cung cấp các hình thức đóng gói nhất định, các đối tượng khác hướng đối tượng. Nếu bạn đang tìm kiếm các ví dụ về đóng gói với các phương tiện chức năng, hãy bắt đầu với các bao đóng .

Liên quan đến "các nguyên lý khác": không, chúng không sai, nhưng đối với các kịch bản nhất định như song song hóa quy mô cao, các phương pháp tiếp cận chức năng có thể mở rộng tốt hơn. Đối với các kịch bản khác, như tạo các khung UI được thiết kế tốt, OOP tiếp cận tỷ lệ có thể tốt hơn (YMMV, tôi không có ví dụ tốt hơn trong tay). Hơn nữa, tôi chắc chắn đối với hầu hết các kịch bản trong thế giới thực, nó phụ thuộc vào kiến ​​thức và kinh nghiệm của nhóm với mô hình lập trình yêu thích của nó như thế nào một hệ thống nhất định sẽ mở rộng.

Có phải OOP được áp dụng sai? Chẳng hạn, Alan Kay được chú ý khi nói trong Bài phát biểu OOPSLA'97: "Tôi đã phát minh ra thuật ngữ hướng đối tượng và tôi có thể nói với bạn rằng tôi không có C ++ trong đầu."

Chắc chắn OOP thường được áp dụng sai bởi nhiều người, nhưng tôi chắc chắn điều tương tự cũng đúng với FP. Và tôi sẽ ngạc nhiên nếu John Mc Carthy (nhà thiết kế của Lisp) có một cái gì đó giống như Javascript khi anh ấy nghĩ về lập trình chức năng (thương xót tôi, đừng châm chọc tôi quá nhiều cho sự so sánh đó ;-)

Joe Armstrong - "Các đối tượng liên kết các chức năng và cấu trúc dữ liệu với nhau thành các đơn vị không thể chia tách. Tôi nghĩ đây là một lỗi cơ bản vì các chức năng và cấu trúc dữ liệu thuộc về các thế giới hoàn toàn khác nhau."

Tôi đoán nhà phát minh của Erlang có một số lập luận tốt, nhưng anh ta cũng có quan điểm rất riêng của mình, vì vậy hãy để anh ta có ý kiến ​​và xây dựng ý kiến ​​của riêng bạn. Có rất nhiều chuyên gia khác có ý tưởng khác về việc này.


1
Tôi không chắc chắn OO là chi tiết tốt hơn cho GUI, hơn nữa OO và GUI xuất hiện cùng một lúc. +1 cho McCarthy / javascript mặc dù;)
jk.

1
Để công bằng, một số người cho rằng các phương pháp hiện có là thiếu sót và có thể được thay thế bằng một cái gì đó khác . Tôi không biết liệu tôi sẽ gọi đó là "mở rộng" hay đúng hơn là "cải thiện" hộp công cụ :)
Andres F.

1
@AresresF. Đó là một bài đọc tuyệt vời. Tôi dự định đi qua bài báo đó một cách chi tiết khi tôi có thời gian.
Robert Harvey

4

Tất nhiên:

struct Foo
{
    string bar;
    int bux;
}

Tôi biết những gì bạn sẽ nói: "Nhưng điều đó cũng không gói gọn hành vi!" Chà, tôi với Joe Armstrong về điều này: bạn có thể viết toàn bộ chương trình hoặc hệ điều hành mà không bao giờ yêu cầu các đối tượng hạng nhất. Linux chứng minh điều đó.

Các lập trình viên Javascript thường đóng gói trạng thái và hành vi trong các hàm và các bao đóng, không phải các lớp.


3
Bạn cũng có thể xúc đồi đất với chỉ một muỗng cà phê. Nhưng bất cứ ai tuyên bố đó là cách tối ưu để làm điều đó nên được xem với sự nghi ngờ.
Euphoric

6
Tôi chưa bao giờ nói nó là tối ưu, và đó không phải là những gì OP yêu cầu. Trong một tin tức khác, tôi thấy thật thú vị khi Linux đủ điều kiện là xúc đất bằng một muỗng cà phê.
Robert Harvey

2
@jk. Tất nhiên. C cũng vậy.
Robert Harvey

1
thực sự nó là loại
jk.

4
Tôi sẽ không gọi cấu trúc C là 'đóng gói'. Họ không bảo vệ dữ liệu cũng không nhất thiết phải cung cấp bất kỳ phương pháp tiêu chuẩn nào để truy cập nó. Họ chỉ cứu bạn khỏi làm số học con trỏ thủ công. Ví dụ, khá phổ biến để tìm mã mạng chuyển các gói được tuần tự hóa thành các cấu trúc và ngược lại. Nhận thứ tự byte mạng sai và vui vẻ xảy ra.
david25272

2

Vấn đề chính ở đây là Encapsulation không phải là khái niệm được định nghĩa cứng nhắc và tại sao nó lại hữu ích. Thực hiện một số nghiên cứu cho thấy cách mọi người nhìn thấy sự đóng gói được đánh giá cao và rất nhiều người nhầm lẫn nó với Trừu tượng.

Định nghĩa đầu tiên bạn sẽ tìm

Encapsulation là một khái niệm liên kết dữ liệu và các chức năng thao túng dữ liệu ...

Nếu đây là định nghĩa của bạn, thì phần lớn các ngôn ngữ có cách để nhóm dữ liệu và các chức năng hoạt động trên dữ liệu đó thành các lớp, mô-đun, thư viện, không gian tên, v.v.

Nhưng tôi sẽ lập luận rằng đó không phải là mục đích chính của đóng gói, vì định nghĩa đó vẫn tiếp tục:

..., và điều đó giữ cho cả hai an toàn khỏi sự can thiệp và sử dụng sai bên ngoài.

Wikipedia cũng đồng ý về điều đó:

Một cơ chế ngôn ngữ để hạn chế truy cập trực tiếp vào một số thành phần của đối tượng.

Nhưng bây giờ, chúng ta cần hỏi "nhiễu và lạm dụng" nghĩa là gì và tại sao nên hạn chế truy cập trực tiếp vào dữ liệu. Tôi tin rằng có hai lý do.

Đầu tiên là phạm vi giới hạn trong đó dữ liệu có thể bị đột biến là lợi ích tốt nhất của nhà phát triển. Cách quá thường xuyên cần phải có logic trước / sau khi giá trị được đặt. Và chỉ có số lượng hạn chế những nơi có thể đặt giá trị là vô cùng quý giá. Trong các ngôn ngữ OOP, điều này có thể được thực hiện bằng cách sử dụng các lớp. Trong các ngôn ngữ chức năng "có thể thay đổi" đóng cùng mục đích. Và bởi vì chúng ta biết các lớp = bao đóng , thậm chí còn có thể tranh cãi hơn các ngôn ngữ chức năng có thể thay đổi là "mô hình" khác với OOP.

Nhưng những gì về ngôn ngữ bất biến? Nó không có vấn đề về các biến đột biến. Đây là vấn đề thứ hai xuất hiện: các chức năng và dữ liệu ràng buộc cho phép giữ dữ liệu đó ở trạng thái hợp lệ. Hãy tưởng tượng bạn có cấu trúc bất biến cho Email. Cấu trúc này có stringtrường duy nhất . Chúng tôi có các yêu cầu là nếu bạn có giá trị của loại Emailthì trường đó chứa địa chỉ hợp lệ. Trong đóng gói của OOP, điều này được thực hiện dễ dàng bằng cách khai báo trường đó private, chỉ cung cấp Getphương thức và cóconstructor methodchỉ thành công nếu được truyền trong chuỗi là địa chỉ hợp lệ. Điều tương tự với đóng cửa. Bây giờ, đối với ngôn ngữ bất biến, cần có cách nói rằng cấu trúc chỉ có thể được khởi tạo thông qua chức năng cụ thể và chức năng đó có thể thất bại. Và tôi không biết bất kỳ ngôn ngữ nào phù hợp với tiêu chí đó (có lẽ ai đó trong các nhận xét có thể khai sáng cho tôi).

Vấn đề cuối cùng là đóng gói ngôn ngữ "hỗ trợ" nghĩa là gì. Một mặt có các ngôn ngữ cho phép thực thi đóng gói, do đó mã sẽ không được biên dịch nếu đóng gói bị hỏng. Mặt khác, ngôn ngữ có thể cung cấp cách thực hiện đóng gói, nhưng nó không thực thi nó, khiến nhà phát triển phải tự thực thi nó. Đối với trường hợp thứ hai, bất kỳ ngôn ngữ nào có cấu trúc và chức năng đều có thể hoạt động. Ngôn ngữ động và Haskell đến với tâm trí. Và tôi sẽ nói rằng không có nhiều ngôn ngữ nằm ở phía bên kia của quang phổ. Ngay cả C #, thực sự tốt trong việc thực thi đóng gói cho các đối tượng của nó cũng có thể được bỏ qua bằng cách sử dụng sự phản chiếu. Nhưng thấy rằng trong C # sẽ được coi là mùi mã lớn và không có nhà phát triển C # lành mạnh nào sẵn sàng làm điều đó.

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.