Mọi đối tượng nên biết cách trình bày / vẽ chính mình?


8

David West trong cuốn sách Tư duy đối tượng (chương 10, phần 1, tiểu mục 2) đã đề xuất rằng trong một môi trường OO lý tưởng, mọi đối tượng nên có khả năng trình bày theo yêu cầu; có thể là con người (dưới dạng GUI), các thành phần không phải là nguồn gốc (như JSON và / hoặc XML) hoặc bất kỳ bên nào quan tâm khác:

Suy nghĩ đối tượng nói rằng một khung nhìn (đôi khi được gọi là một giao diện), hay còn gọi là cách khác là một phương tiện để một đối tượng giao tiếp với một đối tượng khác và không có gì khác. Nhu cầu về chế độ xem xuất hiện khi một đối tượng cần thể hiện chính nó dưới dạng một người không phải là người bản địa của một nhóm đối với một đối tượng khác (thường là con người) hoặc ứng dụng (ví dụ: chế độ xem XML cho các đối tượng dữ liệu được chia sẻ trên các nền tảng).

Khám phá về nhu cầu và các tham số phải được thỏa mãn bởi một khung nhìn được biểu hiện trong các tình huống mà đối tượng tham gia. Bất cứ khi nào một đối tượng được yêu cầu hiển thị chính nó, nó phải sử dụng chế độ xem một biểu tượng phù hợp cho người gửi tin nhắn hiển thị đó. Ví dụ, nếu một đối tượng đang cố gắng tự khởi tạo (lấy một giá trị cho chính nó), thì nó phải đưa ra một quan điểm về chính nó như một yêu cầu ngầm đối với một con người (hoặc đối tượng cung cấp dịch vụ khác) cho một giá trị. Nếu chúng ta đang xây dựng một GUI sẽ đóng vai trò trung gian giữa một đối tượng phần mềm và đối tượng người, chúng ta sẽ sử dụng glyphs cho mục đích hiển thị và các widget cho mục đích tương tác.

Nhưng glyphs và widget nào cần được đưa vào GUI? Chỉ những người cần thiết để hoàn thành kịch bản hoặc kịch bản 4 quan tâm ngay lập tức khi ứng dụng chạy. Viễn cảnh này là phản trực giác đối với hầu hết các nhà phát triển vì nó gợi ý rằng GUI được xác định từ ứng dụng.

Ví dụ, xem xét một nhà máy bia. Tắt sang một bên là những thùng đầy bia. Tại một dây chuyền sản xuất phức tạp bao gồm máy rửa chai, trạm nạp, máy đóng nắp và máy lắp ráp gói. Trên hết là một trạm điều khiển giám sát nhà máy bia và thông báo cho các nhà quản lý con người về tình trạng và vấn đề. Các nhà phát triển truyền thống có khả năng bắt đầu phân tích và thiết kế hệ thống quản lý nhà máy bia của họ theo quan điểm của bảng điều khiển. Điều này tương tự như thiết kế từ giao diện trong.

Thay vào đó, tư duy đối tượng sẽ đề xuất rằng bạn xem xét đối tượng nào là khách hàng chính của nhà máy bia và tất cả các máy móc của nó. Nhân danh thiết bị phức tạp tồn tại thay mặt cho ai? Tất nhiên, câu trả lời đúng cho doanh nghiệp là khách hàng. Nhưng một câu trả lời phản ánh rõ hơn về suy nghĩ của đối tượng là, Bia. Tất cả các kịch bản được viết từ quan điểm của bia, cố gắng tự chui vào một cái chai, có nắp, được đặt trong một gói, và cư trú trong một chiếc xe tải. Bảng điều khiển là một người quan sát thụ động 5 về tình trạng của nhà máy bia. Nếu bia gặp phải sự cố tại một số điểm, thì trách nhiệm của bia là yêu cầu sự can thiệp của người vận hành con người bằng cách gửi tin nhắn đến bảng điều khiển (hoặc bảng điều khiển dành riêng cho máy) yêu cầu dịch vụ can thiệp.

Phối cảnh này sẽ đơn giản hóa thiết kế GUI và quan trọng hơn là loại bỏ máy chủ của các đối tượng trình quản lý và trình điều khiển dường như phát sinh chắc chắn khi thiết kế từ phối cảnh của bảng điều khiển (GUI).

Đến từ một người mới bắt đầu trong thế giới OO: điều này thực sự có nên xảy ra không?

Có những đối tượng biết cách tự đại diện chắc chắn có thể giảm số lượng đối tượng điều khiển / quản lý mà West liên tục nói trong cuốn sách của mình, một Nhà tư tưởng đối tượng được cho là nên cố gắng tránh bằng mọi giá. Nhưng sẽ không tuân thủ "quy tắc" này phá vỡ SRP ?

Ngoài ra (nếu nó trở thành trường hợp), được đưa ra một triển khai điển hình trong một ứng dụng Android: Làm thế nào một người có thể đạt được loại mục tiêu này? Có phải mọi đối tượng chúng ta tạo ra đều biết cách thể hiện bản thân như một View?


3
SRP không có nghĩa là những gì bạn nghĩ nó có nghĩa. SRP có nghĩa là đối tượng "xe hơi" của bạn không chẩn đoán các vấn đề về thú cưng. Điều đó không có nghĩa là một yếu tố UI trực quan không nên có khả năng hiển thị.
Robert Harvey

Tôi hiểu rồi. Tuy nhiên, bạn có đề cập đến yếu tố UI trực quan . Bây giờ, nếu chúng ta áp dụng quy tắc này trong thiết kế phần mềm của mình, liệu phần lớn các đối tượng chúng ta sẽ tạo ra là các yếu tố UI trực quan ? Bởi vì hầu hết trong số họ sẽ yêu cầu tương tác với người dùng sớm hay muộn, phải không?
MrHadiSatrio

1
@RobertHarvey Tôi không chắc cách trích dẫn đó có thể được xem là hỗ trợ một kiểu kiểu MVC. Nó đọc giống như nó nói rằng trách nhiệm của lớp là xác định giao diện / "khung nhìn" của nó để đáp ứng nhu cầu của nó, trong khi trong một mô hình MVC, mô hình sẽ không biết gì về chế độ xem hiển thị nó.
Ben Aaronson

1
@ridsatrio Vì bạn là người mới bắt đầu tự thừa nhận ... Tôi khuyên bạn nên cố gắng viết các giao diện tồn tại để nói với một đối tượng về một điều gì đó xảy ra ngoài tầm kiểm soát của nó hơn là các phương thức bảo các đối tượng làm việc. Vì vậy, các phương thức như "buttonWasClicky" hoặc "pageWillBeDisplayed" tốt hơn "changeState" hoặc "drawInCorner". "Nói đừng hỏi ..." nói với các đối tượng về những gì đang xảy ra thay vì yêu cầu họ làm việc.
Daniel T.

2
Tại một thời điểm, tác giả đã ngừng viết và nghĩ: "Tôi có thực sự muốn dạy mọi người về OOP bằng cách nói về bia muốn ở trong chai và nói với các nhà khai thác khi không thể?" Tôi không thấy làm thế nào điều này được cho là để chiếu sáng bất kỳ khái niệm hoặc ý tưởng nào cho bất cứ ai.
Sebastian Redl

Câu trả lời:


12

Tôi nghĩ rằng đây là một trong những điều khó hiểu nhất về thiết kế OO và thành thật mà nói, tôi nghĩ rằng rất nhiều tác giả đã sai về nó và / hoặc không giải thích nó rất tốt. Rất nhiều người mắc phải sai lầm này và không bao giờ thực sự hiểu được. Hãy lấy một ví dụ không dựa trên GUI nhưng gặp phải một cạm bẫy tương tự.

Trong Java, mọi đối tượng đều có phương thức bằng. Sau đó, bạn có các loại bộ sưu tập như tập hợp và bản đồ phụ thuộc vào phương thức này để xác định khi nào các đối tượng sẽ được thêm vào bộ sưu tập hoặc khi chúng trùng lặp. Điều này có vẻ như OO tốt cho rất nhiều người. Vấn đề là những gì bạn kết thúc là một đối tượng (bộ sưu tập) có hành vi không được xác định bởi nó mà bởi các đối tượng mà nó chứa. Điều này hơi giống với việc đưa hành khách đi xe buýt trực tiếp đến nơi cần đến. Nếu họ không đồng ý thì sao? Đây không phải là một vấn đề lý thuyết, nó thực sự là một vấn đề nhức nhối khi bạn về cơ bản phải phá vỡ sự kế thừa để ngăn chặn các lỗi trong chương trình của bạn. Lấy một hình dạng và một màu sắc. Là một hình vuông 2x2 bằng với một hình vuông màu xanh 2x2? Shape nói 'có' và ColoringShape nói 'không'. WHO' phải không Câu trả lời phụ thuộc vào những gì bạn muốn xảy ra trong bộ sưu tập của bạn. Nó có thể không phụ thuộc vào những gì bạn đang cố gắng làm.

Bạn sẽ thấy điều này xuất hiện như một vấn đề hết lần này đến lần khác. Điều buồn cười là có một giải pháp và nó ở ngay bên cạnh tại So sánh. Các đối tượng triển khai so sánh có cùng câu hỏi hóc búa này nhưng bây giờ chúng không chỉ xác định xem chúng có bằng nhau không mà còn lớn hơn đối tượng khác hay không. Nó thực sự khó hiểu bên ngoài phạm vi sử dụng rất hẹp. Vì vậy, chúng ta có một thứ khác gọi là So sánh. Công việc của chúng ta là nhìn vào hai vật thể và cho biết bộ sưu tập cái nào lớn hơn. Tất cả các vấn đề mà bạn đã cố gắng thực hiện trong đối tượng So sánh sẽ biến mất.

Tôi không biết cuốn sách này và tôi không biết tác giả nhưng ví dụ với bia có vẻ không hữu ích chút nào. Làm thế nào để bia biết liệu nó nên được trong một chai hoặc trong một thùng và tại sao nó sẽ được đưa ra quyết định? Công việc là thưởng thức hương vị và đưa rượu vào máu của người dùng. Chúng ta có thực sự nghĩ rằng nhà máy bia làm việc theo cách này? "OK bia, bạn nên ở trong một chai hoặc trong một thùng và nếu đó là một chai, nó nên là một chai 25 ounce hoặc một chai 12 ounce?" Bia gì trong trường hợp này (không có ý định chơi chữ) nào? Có phải là một giọt bia? Có thể điều này nằm ngoài ngữ cảnh nhưng tôi nghĩ điều này đã sai hoặc ít nhất là nó không thêm bất kỳ sự chiếu sáng nào vào khái niệm này.

Như đã nói, có một cách tiếp cận để xây dựng các giao diện mà tôi đã sử dụng có thể đơn giản hóa mọi thứ và làm cho nó trở nên OO hơn. Về cơ bản, bạn tạo một giao diện xác định các hành động trừu tượng mà bạn có thể thực hiện để hiển thị đối tượng. Bạn có thể có một giao diện được gọi là Displaycác phương thức như setTitlehoặc setDescriptionnếu bạn đang sử dụng mẫu đặt tên Java tiêu chuẩn. Sau đó, đối tượng của bạn sẽ có một phương thứcdisplay(Display display)(bởi vì ba lần là sự quyến rũ!) Trong cách tiếp cận này, đối tượng không cần hiểu giao diện là gì, nó có thể là văn bản, nhị phân, svg, bitmap, bất cứ điều gì và giao diện không cần biết về đối tượng . Theo cách này, một đối tượng có thể "hiển thị chính nó" mà không cần biết về cách hoạt động của màn hình. Cách tiếp cận này có thể làm giảm đáng kể số lượng các lớp bao bọc cần thiết nhưng nó có thể cồng kềnh nếu bạn có các yêu cầu hiển thị phức tạp khác nhau tùy theo đối tượng. Bạn có thể kết hợp nó với các cách tiếp cận kiểu MVC tiêu chuẩn để có hiệu quả tốt.


2
Câu trả lời hay, và tôi nghĩ nó chạm đến tất cả các vấn đề liên quan.
Robert Harvey

Đây thực sự là một câu trả lời rất hay. Hãy suy nghĩ về nó, có lẽ cách bạn cho phép các đối tượng tự vẽ thông qua một giao diện được xác định là cách tiếp cận tốt nhất cho vấn đề này. Theo cách này, các đối tượng vẫn có quyền kiểm soát cách chúng muốn được hiển thị (không phải bởi bộ điều khiển bên ngoài) nhưng không cần chúng tìm hiểu cách thức Displayhoạt động trong triển khai cụ thể của nó ( JFrameví dụ như chúng phải được cung cấp đơn giản ). Cảm ơn.
MrHadiSatrio 30/03/2016

1
Câu trả lời này thật tuyệt vời và tôi đã phản ánh rất nhiều về OOP nói chung. Tôi đã tìm thấy một ECS dễ dàng hơn nhiều để duy trì việc phân tách dữ liệu và chức năng, và một phần vì nó không chịu sự tương tự của những gì bạn mô tả khi sử dụng các đối tượng cố gắng xác định bên trong hành vi chính xác để so sánh với chính họ là gì thứ gì khác.

8

Nguyên tắc trách nhiệm duy nhất không có nghĩa là một lớp chỉ làm một việc. Nó có nghĩa là một lớp có một lý do duy nhất để thay đổi.

Có lẽ bạn đang nghĩ về một phương pháp , mà thực sự chỉ làm một việc.

Theo kết luận hợp lý, phiên bản SRP của bạn có nghĩa là bạn sẽ không bao giờ có thể đăng nhập bất cứ điều gì, vì đăng nhập là một trách nhiệm riêng biệt.

Tốt hơn nên nghĩ về một lớp học như là một chủ đề duy nhất, được xác định rõ . Bạn có thể có một số phương pháp hỗ trợ chủ đề đó và tất cả chúng có thể làm những việc khác nhau.

Phương thức "hiển thị tôi" cơ bản nhất là ToString, luôn luôn là một phương thức trên đối tượng.


Tất cả những gì đã nói, khi chúng tôi tạo UI, chúng tôi thường khuyến khích Tách mối quan tâm bằng cách cung cấp các đối tượng có mục đích duy nhất là hiển thị dữ liệu từ các đối tượng khác (ví dụ: Lượt xem).

Có lẽ một ví dụ là theo thứ tự. Hãy xem xét một trang web PHP, sử dụng View. Một cái nhìn đơn giản có thể trông như thế này:

<?php
class View
{
    private $model;
    private $controller;

    public function __construct($controller,$model) {
        $this->controller = $controller;
        $this->model = $model;
    }

    public function output(){
        return "<p>" . $this->model->string . "</p>";
    }
}

Trong PHP, View luôn chứa một output()hàm. Để có được đại diện trực quan của chế độ xem, tất cả những gì bạn phải làm là gọi output()và bạn sẽ nhận được một chuỗi phù hợp để hiển thị trong bất kỳ trình duyệt hiện đại nào.

Nếu bạn sẽ chú ý, View sẽ tham chiếu một đối tượng được gọi model. Đây là đối tượng chứa dữ liệu thực tế. Khung nhìn và Mô hình nằm trong các đối tượng riêng biệt; đây là những gì thiết lập sự tách biệt mối quan tâm.

Tách các mối quan tâm là rất quan trọng đối với các trang web, bởi vì đó là những gì cho phép một nhà thiết kế làm việc trên một thiết kế trang web ngoài các lập trình viên.

Đọc thêm
Mô hình MVC và PHP


Ổn thỏa. Nhưng một khi chúng ta đã tách chế độ xem khỏi mô hình, thì đó vẫn là công việc của mô hình để cung cấp chế độ xem? Bởi vì đó là những gì tôi nhận được từ trích dẫn ở trên: đối tượng (hoặc mô hình trong vốn từ vựng của bạn) nên biết cách hiển thị chính nó, phải không? Theo một nghĩa nào đó, giả sử bạn có một Receiptđối tượng trong một phần mềm POS thông thường, bạn vẫn sẽ gọi Receipt.draw(Canvas)và không ReceiptView.draw(Receipt).
MrHadiSatrio

2
Trong MVC, trách nhiệm của Bộ điều khiển là chọn chế độ xem nào sẽ sử dụng.
Robert Harvey

Nhưng đối tượng điều khiển là những gì chính xác được đặt ra như những điều cần tránh trong nhận thức của phương Tây trong Tư duy đối tượng (và do đó trong trích dẫn đó). Trích dẫn nêu rõ rằng toàn bộ ý tưởng đằng sau "các đối tượng biết cách tự hiển thị" là để tránh "các đối tượng quản lý và điều khiển".
MrHadiSatrio

Điều đó tốt, nhưng tôi nghĩ bạn sẽ phải giới hạn suy nghĩ đó cho các đối tượng có mục đích duy nhất là hiển thị trực quan. Quan điểm, nói cách khác. Bộ điều khiển không quan tâm cách View hiển thị chính nó; nó chỉ quan tâm đến việc sử dụng xem. Ngoài ra, MVC không phải là mô hình hiển thị duy nhất có thể và các mô hình khác (đặc biệt là MVVM) hoạt động hơi khác. Nhưng nguyên tắc cơ bản của Tách biệt mối quan tâm vẫn còn.
Robert Harvey

Lưu ý rằng các cuốn sách mà bạn đang đọckhá cũ cho một cuốn sách phần mềm (2004). MVC và MVVM chưa được sử dụng phổ biến.
Robert Harvey

1

Đánh giá từ các trích dẫn bạn đã dán, bạn đang hiểu sai văn bản.

Tác giả không nói rằng mọi đối tượng sẽ có thể tự trình bày trong một giao diện người dùng. Điều này là không thể, vì một đối tượng không thể biết nó sẽ được hiển thị trong giao diện người dùng nào (trong ứng dụng WinForms, ứng dụng linux sử dụng XServer, dưới dạng chuỗi JSON, dưới dạng XML, dưới dạng hình ảnh PNG, v.v.).

Vấn đề được đưa ra là bạn nên viết các khung nhìn chuyên biệt với trách nhiệm duy nhất là hiển thị một thực thể nhất định. Ví dụ, bạn có thể viết một khung nhìn hiển thị một đối tượng dưới dạng HTML (như được thực hiện bởi các khung nhìn trong các ứng dụng MVC). Bạn có thể tạo một bộ tuần tự hóa JSON có thể biến một đối tượng thành một chuỗi JSON. Bạn có thể tạo một đối tượng biến các loại đối tượng khác thành báo cáo PDF. Tất cả phụ thuộc vào.

Vấn đề là, tách thực thể kinh doanh khỏi đại diện trực quan (hoặc nối tiếp). Chúng là những thứ khác nhau và thay đổi vì những lý do khác nhau.


Tôi đã chỉnh sửa câu hỏi của tôi để giải thích về trích dẫn.
MrHadiSatrio

1
Mặc dù tôi thừa nhận câu trả lời của mình không còn phù hợp nữa, tôi không thấy câu hỏi của bạn có liên quan gì đến trích dẫn. Đoạn trích dường như được nói nhiều hơn về các API và giao diện, thay vì hiển thị trực quan. Những phần nào của một đối tượng nên có thể truy cập được và những thông điệp nào nó có thể gửi để nó hoàn thành công việc trong lĩnh vực kinh doanh?
sara

"Nếu chúng tôi đang xây dựng một GUI sẽ đóng vai trò trung gian giữa một đối tượng phần mềm và đối tượng người, chúng tôi sẽ sử dụng glyphs cho mục đích hiển thị và các widget cho mục đích tương tác." Đánh giá theo câu đó, tôi khá chắc chắn rằng trích dẫn cũng bao hàm mục đích kết xuất trực quan.
MrHadiSatrio

Không có gì ở đó nói rằng "đối tượng trong câu hỏi nên chọn glyphs và widget nào đại diện tốt nhất cho bất kỳ bối cảnh cụ thể nào, và cũng phải chịu trách nhiệm hiển thị glyphs và widget nói trên." Đối tượng và vật hiển thị nó không nhất thiết (không nên) giống nhau.
sara
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.