Có nghĩa là gì bởi OOP ẩn giấu nhà nước? [đóng cửa]


11

Trong một trong nhiều lời tuyên bố chống OOP trên cat-v.org tôi đã tìm thấy một đoạn của Joe Armstrong đưa ra một số phản đối chống lại mô hình OOP, một trong số đó là:

Phản đối 4 - Đối tượng có trạng thái riêng tư

Nhà nước là gốc rễ của mọi tội lỗi. Trong các chức năng đặc biệt với tác dụng phụ nên tránh.

Trong khi trạng thái trong ngôn ngữ lập trình là không mong muốn, thì trong trạng thái thực tế có rất nhiều. Tôi rất quan tâm đến trạng thái tài khoản ngân hàng của mình và khi tôi gửi hoặc rút tiền từ ngân hàng của mình, tôi hy vọng trạng thái tài khoản ngân hàng của mình sẽ được cập nhật chính xác.

Cho rằng trạng thái tồn tại trong thế giới thực, ngôn ngữ lập trình nên cung cấp phương tiện gì để đối phó với trạng thái?

Các OOPL nói rằng, Che giấu trạng thái khỏi lập trình viên. Các trạng thái được ẩn và chỉ hiển thị thông qua các chức năng truy cập. Các ngôn ngữ lập trình thông thường (C, Pascal) nói rằng khả năng hiển thị của các biến trạng thái được kiểm soát bởi các quy tắc phạm vi của ngôn ngữ. Ngôn ngữ khai báo thuần túy nói rằng không có nhà nước. Trạng thái toàn cầu của hệ thống được đưa vào tất cả các chức năng và đi ra từ tất cả các chức năng. Các cơ chế như monad (cho FPL) và DCG (ngôn ngữ logic) được sử dụng để ẩn trạng thái khỏi lập trình viên để họ có thể lập trình, như thể trạng thái không quan trọng, nhưng điều này cần thiết để truy cập đầy đủ vào trạng thái của hệ thống.

Các ứng dụng ẩn giấu trạng thái khỏi tùy chọn lập trình viên do OOPLs chọn là lựa chọn tồi tệ nhất có thể. Thay vì tiết lộ trạng thái và cố gắng tìm cách giảm thiểu sự phiền toái của nhà nước, họ che giấu nó đi.

Chính xác thì điều này có nghĩa là gì? Tôi có rất ít kinh nghiệm về thủ tục hoặc cấp độ thấp, chủ yếu là OOP, vì vậy điều đó có thể giải thích tôi không quen thuộc với điều này. Và từ một quan điểm hiện đại hơn, bây giờ hầu hết sự cuồng loạn hướng đối tượng đã được thông qua (ít nhất là theo như tôi có thể nói), các bạn nghĩ chính xác / có liên quan như thế nào?

Cảm ơn bạn đã giúp đỡ.


3
đề nghị đọc: Thảo luận về $ {blog}
gnat

1
Nếu bạn hỏi tôi, bài viết bạn liên kết để đưa ra một vài lập luận khá kém (chưa kể đến chất lượng của bài viết). Tôi sẽ không đặt quá nhiều cổ phiếu vào những gì nó nói.
Benjamin Hodgson

1
Bah Càng ngày tôi càng nghĩ toàn bộ điều "bất di bất dịch" này là một ý tưởng hay bắt đầu bốc mùi của tôn giáo.
Rob

3
Joe Armstrong đã công khai thừa nhận rằng sự phản đối của ông đối với OO dựa trên những hiểu lầm nghiêm trọng về chính xác OO là gì. Bây giờ anh ấy đã nhận ra rằng Erlang thực sự là một ngôn ngữ hướng đối tượng sâu sắc (trên thực tế, nó có thể là ngôn ngữ hướng đối tượng nhất trong sử dụng chính thống).
Jörg W Mittag

9
Để mở rộng về điều đó: lần đầu tiên lưu trữ archive.org về cơn thịnh nộ của Joe Armstrong là từ tháng 4 năm 2001. Joe đã viết luận án vào năm 2003. Trong khi viết luận án, anh ta đã học được rất nhiều về OO, và anh ta nhận ra rằng mình đã trở thành con mồi của quan niệm sai lầm phổ biến rằng OO bằng cách nào đó có liên quan đến trạng thái đột biến (không phải, trạng thái đột biến là hoàn toàn trực giao). Kể từ đó, anh ta đã thừa nhận rằng những lời chỉ trích của mình về OO là sai và trớ trêu thay Erlang thực sự là một ngôn ngữ hướng đối tượng (nó có thông điệp, nó có các đối tượng mà nó gọi là các quá trình, nó được đóng gói).
Jörg W Mittag

Câu trả lời:


32

Chính xác thì điều này có nghĩa là gì?

Trong ngữ cảnh này, điều đó có nghĩa là OOP che khuất trạng thái của một chương trình bằng cách ẩn nó khỏi chương trình nhưng vẫn làm cho nó hiển thị thông qua các phương thức truy cập (rò rỉ). Lập luận là bằng cách che khuất trạng thái, nó làm cho nó khó khăn hơn để làm việc và bởi phần mở rộng dẫn đến nhiều lỗi hơn.

Làm thế nào chính xác / có liên quan để các bạn nghĩ rằng đoạn văn là?

Tôi cảm thấy rằng nó có liên quan, nhưng bị đánh giá sai. Hoàn toàn có vấn đề nếu lớp của bạn rò rỉ khái niệm trạng thái của nó ra thế giới bên ngoài. Hoàn toàn có một vấn đề nếu lớp của bạn cố gắng che khuất trạng thái khi nó bị thế giới bên ngoài thao túng. Điều đó mặc dù không phải là một thất bại của OOP nói chung, nhưng với thiết kế riêng của lớp. Tôi sẽ không nói rằng chính trạng thái ẩn là một vấn đề - các đơn vị làm điều này trong lập trình chức năng mọi lúc.

Trong trường hợp tốt nhất, OOP hoạt động giống như sự pha trộn tốt nhất giữa lập trình chức năng và thủ tục - mọi người có thể sử dụng lớp "như thể trạng thái không quan trọng" vì trạng thái riêng được sử dụng để bảo vệ các bất biến của lớp bị ẩn, nhưng có quyền tự do để sử dụng một trạng thái công khai được xác định rõ của lớp mà trừu tượng hóa các chi tiết.

OOP có làm cho mọi người khó đạt được trường hợp tốt nhất này không? Có khả năng. "Các trường Java" và toàn bộ Hình dạng / Vòng tròn / Hình chữ nhật hoặc Xe hơi có trường dạy OO của Wheels có lẽ có nhiều điều đáng trách hơn chính cách tiếp cận. OOP hiện đại mất khá nhiều từ lập trình chức năng, khuyến khích các đối tượng bất biến và các hàm thuần túy trong khi không khuyến khích sự kế thừa để giúp dễ dàng thiết kế các lớp hoạt động tốt.


3
Đồng ý toàn bộ về toàn bộ "trường java", đừng như vậy chút nào. Cảm ơn bạn rất nhiều, tôi sẽ bỏ phiếu nếu tôi có thể.
Jake

2
Nói chính xác: các đơn nguyên nói chung không ẩn trạng thái, một số đơn vị thực hiện (ví dụ IO). Xem trong số những người khác stackoverflow.com/questions/2488646/
Mạnh

2
+1. Đây là một phân tích cân bằng và nhiều sắc thái hơn nhiều so với bài viết mà người hỏi đã liên kết
Benjamin Hodgson

2
Joe Armstrong đã công khai thừa nhận rằng sự phản đối của ông đối với OO dựa trên những hiểu lầm nghiêm trọng về chính xác OO là gì. Bây giờ anh ấy đã nhận ra rằng Erlang thực sự là một ngôn ngữ hướng đối tượng sâu sắc (trên thực tế, nó có thể là ngôn ngữ hướng đối tượng nhất trong sử dụng chính thống).
Jörg W Mittag

2
Jorg - bạn có thể gửi một liên kết đến theo dõi của Joe không? Tôi rất muốn đọc nó. Và @radarbob, ngay trên!
dùng949300

2

Lý do về một hệ thống sẽ khó khăn nếu có những phần trạng thái có thể thay đổi mà không có "chủ sở hữu" rõ ràng duy nhất. Điều đó không có nghĩa là các đối tượng không bao giờ có trạng thái có thể thay đổi, mà là các đối tượng có trạng thái có thể thay đổi không nên được sử dụng theo cách mà quyền sở hữu có thể không rõ ràng, và ngược lại, các đối tượng sẽ được tự do chuyển qua mà không cần theo dõi quyền sở hữu được bất biến.

Trong thực tế, lập trình hiệu quả thường xuyên yêu cầu một số đối tượng có trạng thái đột biến; tuy nhiên, trạng thái như vậy nên được giới hạn trong các đối tượng công nhân không chia sẻ . Hãy xem xét các giao diện IEnumerable/ IEnumeratortrong .NET: nếu một bộ sưu tập thực hiện IEnumerable, nó sẽ cho phép các mục được đọc ra cùng một lúc. Quá trình thực sự đọc ra một bộ sưu tập thường sẽ yêu cầu theo dõi những mục nào đã được đọc (một phần của trạng thái có thể thay đổi), nhưng trạng thái đó không được bao gồm trong quá trình thực hiện IEnumerable. Thay vào đó, IEnumerablecung cấp một phương thức được gọi là GetEnumeratorsẽ trả về một đối tượng thực hiện IEnumeratorvà chứa đủ trạng thái để cho phép các mục được đọc ra khỏi bộ sưu tập. Tuy nhiên, thực tế là đối tượng chứa trạng thái như vậy sẽ không gây ra vấn đề gì, tuy nhiên,nếu đối tượng thực hiện IEnumeratorkhông được chia sẻ .

Mẫu tốt nhất trong hầu hết các trường hợp là sử dụng hỗn hợp các đối tượng được chia sẻ tự do nhưng sẽ không bao giờ được sửa đổi (ít nhất là sau khi chúng được chia sẻ) và các đối tượng có chủ sở hữu rõ ràng và có thể được chủ sở hữu đó sửa đổi tự do , nhưng không bao giờ được chia sẻ với bất cứ ai.


Sự phân biệt tuyệt vời giữa những gì nên bất biến và những gì có thể có trạng thái đột biến. Đọc điều này, tôi nhận ra rằng các biểu đồ đối tượng gần đây của tôi (không thay đổi so với trước đây) về cơ bản tuân theo hướng dẫn này mà không cần nêu rõ như bạn đã làm. Đây là một thuốc giải độc vừa phải tốt cho "trạng thái đột biến luôn luôn xấu xa" đôi khi bạn nghe thấy.
Mike hỗ trợ Monica

@Mike: Tôi nghĩ vấn đề thực sự là tất cả các tham chiếu đối tượng trong Java và .NET hoàn toàn bừa bãi; bất kỳ mã nào có được hoặc nhận được một tham chiếu đến một đối tượng đều có thể chia sẻ nó với bất kỳ mã nào khác mà không bị hạn chế. Không khung nào có bất kỳ khái niệm nào về trường tham chiếu không thể chia sẻ; cấu trúc và byrefs trong .NET rất gần, nhưng chúng khá hạn chế về những gì chúng có thể làm hoặc những gì chúng có thể ngăn chặn mã bên ngoài thực hiện. Trong mọi trường hợp, tôi sẽ đưa ra một câu nói cơ bản liên quan đến trạng thái có thể thay đổi: vào lúc 12 giờ sáng, một vật thể có thể đồng thời đại diện cho ...
supercat

... trạng thái hiện tại của một vật thể trong thế giới thực và trạng thái của vật thể đó vào lúc 12 giờ sáng. Nếu trạng thái trong thế giới thực của đối tượng thay đổi, nó sẽ không còn có thể cho một đối tượng đại diện cho cả hai. Đôi khi, cần phải có đối tượng tiếp tục đại diện cho trạng thái 12:57 sáng và đôi khi là trạng thái hiện tại. Tuy nhiên, mối quan hệ giữa trạng thái 12 giờ sáng và trạng thái hiện tại không thể duy trì nếu trạng thái hiện tại thay đổi.
supercat

0

Có nguy cơ vượt ra ngoài việc trả lời câu hỏi, thật dễ dàng nhận thấy những sai sót trong ý tưởng về OOP, nhưng tôi có xu hướng nghĩ rằng sức mạnh của một ý tưởng được phản ánh trong khả năng bị lạm dụng.

Rốt cuộc, mọi người đều có ngôn ngữ yêu thích của họ, mà họ mô tả bằng thuật ngữ như "rất rất mạnh mẽ" có nghĩa là họ thực sự thích nó . Nhưng điều kỳ diệu của tính phổ quát tính toán là cho dù ngôn ngữ có vẻ vang đến đâu, nếu nó thực sự mạnh mẽ, nó có thể mô phỏng ngôn ngữ lắp ráp. Và nếu nó có thể, ai đó sẽ thấy rằng nó làm. (Không có gì sai với ngôn ngữ lắp ráp.)

Cảm nhận cá nhân của tôi về bandwagon OOP là nó đại diện cho sự giáo dục của mọi người về công nghệ phần mềm / khoa học máy tính. Họ bị cản trở ở một mức độ mà họ nghĩ rằng đó là tất cả về cấu trúc dữ liệu. Các lớp, kế thừa, các thùng chứa, các trình lặp, các bản đồ băm, các thuộc tính, ẩn trạng thái , v.v. - tất cả về cấu trúc dữ liệu - càng nhiều càng tốt.

Cá nhân tôi muốn thấy một cấp độ tiếp theo nơi mọi người sẽ học cách giải quyết vấn đề bằng cách nhìn vào ngôn ngữ. Nơi họ sẽ hiểu khái niệm về ngôn ngữ dành riêng cho miền, làm thế nào để dễ dàng tạo ra chúng và để cho sự sáng tạo của họ là một phần không thể thiếu trong việc giải quyết vấn đề. Không sai khi nói rằng cấu trúc dữ liệu ngôn ngữ. Mọi người nên có kỹ năng thiết kế ngôn ngữ đó, vì vậy họ không chỉ loay hoay với nó.

Sau đó, ở cấp độ tiếp theo, tôi muốn thấy trí tuệ nhân tạo được hồi sinh. Tôi muốn thấy các lập trình viên vượt ra ngoài byte và luồng và các bảng chức năng ảo và CUDA và chuyển sang cách làm cho máy móc lý luận, tìm hiểu và tạo. Tôi biết điều này đã tiến rất xa trong các góc nhỏ của lĩnh vực, nhưng không nơi nào đủ rộng.


1
"Nếu nó thực sự mạnh mẽ, nó có thể mô phỏng ngôn ngữ lắp ráp" - bạn trao đổi định nghĩa về powerfulquyền đó. Khi những người khác nói powerful, họ nói về việc nó cho phép các lập trình viên trừu tượng đến mức nào , đó là một câu chuyện khác với sức mạnh tính toán .
Phil

@Phil: trừu tượng là một trong những từ đó :)
Mike Dunlavey

Không Bạn đang nói về lời nói. Tôi đã nói về ý tưởng. Việc sử dụng từ thứ 2 và thứ 3 của bạn powercó nghĩa là những thứ khác nhau. Xin đừng đánh lạc hướng.
Phil

Btw, nếu bạn quan tâm, hãy xem Vợt , hơi gần với cách tiếp cận mà bạn đang nói trong đoạn 4 của bạn (cho phép các lập trình viên đưa ngôn ngữ đến mức độ của vấn đề thay vì làm cho họ giải quyết vấn đề của họ bộ cấu trúc cố định của ngôn ngữ). Nó vượt xa Lisp / Scheme cổ điển, chỉ trong trường hợp bất kỳ ai cũng có ấn tượng đó khi lần đầu tiên nhìn vào nó.
Phil

0

Khả năng truy cập không phải là một tính năng của OOP, nó dành riêng cho việc triển khai như Java và Microsoft dotNET. Tính năng chính xác định OOP là đa hình.

Dù sao, bằng cách ẩn trạng thái đối tượng, không có cách nào để tạo API có ý nghĩa. Trình bày là một thành phần quan trọng của OOP trong thế giới thực. Những người không đồng ý có thể có sự thù địch phi lý đối với ngành công nghiệp phần mềm, điều này khiến cho ý kiến ​​của họ không liên quan theo quan điểm của tôi.

Các trang web như trang bạn liên kết nổi tiếng với những suy nghĩ và chỉ trích cực kỳ cứng nhắc về công nghệ mới. Một số người không nhận được nó.


Một đối tượng nên tồn tại để bảo vệ sự bất biến của khái niệm mà nó mô hình. Trình bày là một mối quan tâm hoàn toàn riêng biệt và không thể được xử lý một cách hiệu quả và duy trì bởi cùng một đối tượng, bởi vì một đối tượng không thể hiểu tất cả các cách khác nhau mà nó có thể được trình bày theo thời gian và không gian. Bài thuyết trình phải được xử lý thông qua một số cơ chế khác như truyền phát sự kiện và các khung nhìn cụ thể hóa nếu mục tiêu của bạn là các đối tượng linh hoạt, có thể duy trì. Lần duy nhất một đối tượng nên thay đổi là nếu khái niệm của nó được sửa đổi hoặc bất biến của nó thay đổi.
Andrew Larsson
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.