Haruskah setiap objek tahu bagaimana menampilkan / menggambar diri mereka sendiri?

8

David West dalam bukunya Object Thinking (bab 10, bagian 1, sub-bagian 2) mengusulkan bahwa dalam lingkungan OO yang ideal, setiap objek harus mampu menampilkan diri berdasarkan permintaan; baik itu untuk manusia (sebagai GUI), komponen non-asli (seperti JSON dan / atau XML), atau pihak lain yang berkepentingan:

Pemikiran objek mengatakan bahwa pandangan (kadang-kadang disebut antarmuka) —grafis atau sebaliknya — adalah sarana bagi suatu objek untuk berkomunikasi dengan objek lain dan tidak lebih. Kebutuhan akan tampilan muncul ketika suatu objek perlu menampilkan dirinya dalam bentuk "non-pribumi" ke beberapa objek lain (biasanya manusia) atau aplikasi (misalnya, tampilan XML untuk objek data yang dibagikan di seluruh platform).

Penemuan kebutuhan dan parameter yang harus dipenuhi oleh tampilan dimanifestasikan dalam skenario di mana objek berpartisipasi. Setiap kali suatu objek diminta untuk menampilkan dirinya, ia harus menggunakan tampilan — representasi — yang sesuai untuk pengirim pesan tampilan itu. Jika, misalnya, suatu objek mencoba untuk instantiate sendiri (mendapatkan nilai untuk dirinya sendiri), objek itu harus menyajikan pandangan itu sendiri sebagai permintaan implisit kepada manusia (atau objek penyedia layanan lainnya) untuk suatu nilai. Jika kami sedang membangun GUI yang akan berfungsi sebagai perantara antara objek perangkat lunak dan objek manusia, kami akan menggunakan mesin terbang untuk tujuan tampilan dan widget untuk tujuan interaksi.

Tapi mesin terbang dan widget mana yang perlu dimasukkan dalam GUI? Hanya yang diperlukan untuk menyelesaikan skenario atau skenario yang menarik segera saat aplikasi berjalan. Perspektif ini berlawanan dengan intuisi untuk sebagian besar pengembang karena menunjukkan bahwa GUI harus ditentukan dari aplikasi keluar.

Sebagai contoh, pertimbangkan tempat pembuatan bir. Di satu sisi ada tong-tong berisi bir. Di jalur produksi kompleks yang terdiri dari mesin cuci botol, stasiun pengisi, mesin penutup, dan perakit paket. Di atas itu semua adalah stasiun kontrol yang memantau tempat pembuatan bir dan memberitahu manajer manusia tentang status dan masalah. Pengembang tradisional cenderung memulai analisis dan desain "sistem manajemen tempat pembuatan bir" dari sudut pandang panel kontrol. Ini analog dengan mendesain dari antarmuka di.

Sebaliknya, berpikir objek menyarankan agar Anda mempertimbangkan objek mana yang merupakan pelanggan utama tempat pembuatan bir dan semua mesin yang banyak sekali. Atas nama siapa ada labirin peralatan yang rumit itu ada? Jawaban bisnis yang benar adalah, tentu saja, "Pelanggan." Tetapi jawaban yang lebih mencerminkan pemikiran objek adalah, "Bir." Semua skenario ditulis dari perspektif bir, mencoba masuk ke dalam botol, dengan topi, ditempatkan dalam paket, dan tinggal di truk. Panel kontrol adalah pengamat pasif 5 dari keadaan tempat pembuatan bir. Jika bir menemui masalah di beberapa titik, bir bertanggung jawab untuk meminta intervensi dari operator manusia dengan mengirimkan pesan ke panel kontrol (atau panel kontrol khusus mesin) yang meminta layanan intervensi.

Perspektif ini akan menyederhanakan desain GUI dan, yang lebih penting, menghilangkan host dari objek manajer dan pengontrol yang tampaknya tak terhindarkan muncul ketika merancang dari perspektif panel kontrol (GUI).

Berasal dari seorang pemula di dunia OO: haruskah ini benar-benar terjadi?

Memiliki objek yang tahu bagaimana merepresentasikan diri mereka tentu dapat mengurangi jumlah objek controller / manager yang berulang kali dikatakan Barat dalam bukunya, seorang Object Thinker seharusnya mencoba menghindari dengan cara apa pun. Tetapi tidakkah mematuhi "aturan" ini merusak SRP ?

Juga (jika ternyata memang demikian), mengingat implementasi yang khas di, katakanlah, aplikasi Android: Bagaimana seseorang dapat mencapai tujuan seperti ini? Haruskah setiap objek yang kita buat tahu bagaimana menampilkan dirinya sebagai View?

MrHadiSatrio
sumber
3
SRP tidak berarti apa yang Anda pikirkan artinya. SRP berarti bahwa objek "mobil" Anda tidak mendiagnosis masalah hewan peliharaan. Itu tidak berarti bahwa elemen UI visual seharusnya tidak mampu menampilkan dirinya sendiri.
Robert Harvey
Saya melihat. Namun Anda menyebutkan elemen UI visual . Sekarang, jika kita menerapkan aturan ini dalam mendesain perangkat lunak kita, bukankah sebagian besar objek yang pada akhirnya akan kita buat adalah elemen UI visual ? Karena kebanyakan dari mereka akan menuntut interaksi dengan pengguna cepat atau lambat, kan?
MrHadiSatrio
1
@ RobertTarvey Saya tidak yakin bagaimana kutipan itu dapat dilihat mendukung pola tipe MVC. Bunyinya seperti mengatakan itu tanggung jawab kelas untuk mendefinisikan antarmuka / "tampilan" untuk memenuhi kebutuhannya, sedangkan dalam pola MVC, model akan mengabaikan tampilan yang menampilkannya.
Ben Aaronson
1
@ridsatrio Karena Anda adalah pemula yang mengaku sendiri ... Saya sarankan Anda berusaha untuk menulis antarmuka yang ada untuk memberi tahu objek tentang sesuatu yang terjadi di luar kendali daripada metode yang memberitahu objek untuk melakukan sesuatu. Jadi metode seperti "buttonWasClicked" atau "pageWillBeDisplayed" lebih baik daripada "changeState" atau "drawInCorner". "Katakan jangan tanya ..." ceritakan objek tentang apa yang terjadi daripada meminta mereka melakukan sesuatu.
Daniel T.
2
Penulis pada satu titik harus berhenti menulis dan berpikir, "Apakah saya benar-benar ingin mengajar orang tentang OOP dengan berbicara tentang bir yang ingin dimasukkan ke dalam botol dan memberi tahu operator ketika tidak bisa?" Saya tidak melihat bagaimana ini seharusnya menerangi konsep atau ide apa pun kepada siapa pun.
Sebastian Redl

Jawaban:

12

Saya pikir ini adalah salah satu hal yang paling sulit untuk dipahami tentang desain OO dan jujur, saya pikir banyak penulis yang salah tentang hal itu dan / atau tidak menjelaskannya dengan baik. Banyak orang melakukan kesalahan ini dan tidak pernah benar-benar memahaminya. Mari kita ambil contoh yang tidak berbasis GUI tetapi berjalan ke perangkap yang sama.

Di Jawa, setiap objek memiliki metode sama dengan. Anda kemudian memiliki tipe koleksi seperti set dan peta yang bergantung pada metode ini untuk menentukan kapan objek harus ditambahkan ke koleksi atau ketika mereka duplikat. Sepertinya ini adalah OO yang baik bagi banyak orang. Masalahnya adalah apa yang Anda akhirnya dapatkan adalah sebuah objek (koleksi) yang perilakunya tidak ditentukan olehnya tetapi oleh objek-objek yang dikandungnya. Ini agak seperti memiliki penumpang di bus langsung ke mana harus pergi. Bagaimana jika mereka tidak setuju? Ini bukan masalah teoretis, ini masalah yang sangat pelik di mana Anda pada dasarnya harus memutuskan warisan untuk mencegah bug di program Anda. Ambil Bentuk dan Bentuk Berwarna. Apakah kotak 2x2 sama dengan kotak biru 2x2? Shape mengatakan 'ya' dan ColoredShape mengatakan 'tidak'. WHO' benar? Jawabannya tergantung pada apa yang Anda inginkan terjadi dalam koleksi Anda. Mungkin tidak tergantung pada apa yang Anda coba lakukan.

Anda akan melihat ini muncul sebagai masalah berulang kali. Yang lucu adalah bahwa ada solusi dan tepat di sebelah Sebanding. Objek yang mengimplementasikan Comparable memiliki teka-teki yang sama tetapi sekarang mereka tidak hanya harus menentukan apakah mereka setara tetapi apakah mereka lebih besar dari objek lain. Ini benar-benar keras di luar ruang lingkup penggunaan yang sangat sempit. Jadi kita memiliki hal lain yang disebut Pembanding. Tugasnya adalah melihat dua benda dan memberi tahu koleksi mana yang lebih besar. Semua masalah yang Anda coba lakukan di objek Sebanding ini menghilang.

Saya tidak tahu buku ini dan saya tidak tahu penulisnya, tetapi contoh dengan bir sepertinya tidak membantu sama sekali. Bagaimana bir itu tahu apakah itu harus dalam botol atau dalam tong dan mengapa harus membuat keputusan itu? Tugasnya adalah mencicipi enak dan mengantarkan alkohol ke aliran darah pengguna. Apakah kita benar-benar berpikir tempat pembuatan bir bekerja dengan cara ini? "OK bir, haruskah kamu dalam botol atau dalam tong dan jika itu botol, haruskah itu botol 25 ons atau botol 12 ons?" Apa bir dalam kasus ini (tidak ada permainan kata-kata yang dimaksudkan)? Apakah ini setetes bir? Mungkin ini di luar konteks tapi saya pikir ini salah atau paling tidak tidak menambah iluminasi pada konsep ini.

Setelah mengatakan semua itu, ada pendekatan untuk membangun antarmuka yang saya gunakan yang dapat menyederhanakan banyak hal dan membuatnya lebih OO. Pada dasarnya, Anda membuat antarmuka yang mendefinisikan tindakan abstrak yang dapat Anda ambil untuk menampilkan objek. Anda mungkin memiliki antarmuka yang disebut Displaymetode seperti setTitleatau setDescriptionjika Anda menggunakan pola penamaan Java standar. Maka objek Anda akan memiliki metodedisplay(Display display)(karena tiga kali pesona!) Dalam pendekatan ini, objek tidak perlu memahami apa antarmuka, itu bisa berupa teks, biner, svg, bitmap, apa pun dan antarmuka tidak perlu tahu tentang objek . Dengan cara ini suatu objek dapat "menampilkan dirinya" tanpa perlu tahu tentang cara kerja display. Pendekatan ini dapat sangat mengurangi jumlah kelas pembungkus yang dibutuhkan tetapi dapat merepotkan jika Anda memiliki persyaratan tampilan kompleks yang bervariasi berdasarkan objek. Anda dapat mencampurnya dengan pendekatan tipe MVC standar untuk efek yang baik.

JimmyJames
sumber
2
Jawaban yang bagus, dan saya pikir itu menyentuh semua masalah yang relevan.
Robert Harvey
Ini memang jawaban yang sangat bagus. Kalau dipikir-pikir, mungkin cara Anda mengaktifkan objek untuk menggambar sendiri melalui antarmuka yang ditentukan adalah pendekatan terbaik untuk masalah ini. Dengan cara ini, objek masih memegang hak mereka untuk mengontrol bagaimana mereka ingin ditampilkan (bukan oleh pengontrol eksternal) tetapi tanpa perlu mereka untuk belajar bagaimana suatu Displayakan bekerja dalam implementasi konkretnya (sebagaimana seharusnya, mereka diberi dataran JFrame, misalnya ). Terima kasih.
MrHadiSatrio
1
Jawaban ini luar biasa dan membuat saya banyak berpikir tentang OOP secara umum. Saya telah menemukan ECS menjadi jauh lebih mudah untuk dipelihara yang memisahkan data dan fungsionalitas, dan sebagian karena tidak menderita analogi dari apa yang Anda gambarkan menggunakan objek yang mencoba menentukan secara internal apa perilaku yang benar untuk membandingkan diri mereka dengan sesuatu yang lain.
8

Prinsip Tanggung Jawab Tunggal tidak berarti bahwa kelas hanya melakukan satu hal. Ini berarti bahwa kelas memiliki satu alasan untuk berubah.

Anda mungkin sedang memikirkan suatu metode , yang sebenarnya hanya melakukan satu hal.

Diambil pada kesimpulan logisnya, versi SRP Anda akan berarti bahwa Anda tidak akan pernah bisa mencatat apa pun, karena penebangan adalah tanggung jawab terpisah.

Lebih baik menganggap kelas sebagai subjek tunggal yang didefinisikan dengan baik . Anda dapat memiliki beberapa metode yang mendukung subjek itu, dan mereka semua bisa melakukan hal yang berbeda.

Metode "tampilkan saya" yang paling mendasar adalah ToString, yang selalu merupakan metode pada objek.


Semua yang dikatakan, ketika kita membuat UI, kami biasanya mendorong Pemisahan Kekhawatiran dengan menyediakan objek yang tujuannya hanya menampilkan data dari objek lain (yaitu Views).

Mungkin contohnya ada dalam urutan. Pertimbangkan situs web PHP, menggunakan Tampilan. Tampilan sederhana mungkin terlihat seperti ini:

<?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>";
    }
}

Dalam PHP, View selalu berisi output()fungsi. Untuk mendapatkan representasi visual dari tampilan, yang harus Anda lakukan adalah menelepon output(), dan Anda akan mendapatkan string yang cocok untuk ditampilkan di browser modern apa pun.

Jika Anda akan melihat, Lihat referensi objek yang disebut model. Ini adalah objek yang berisi data aktual. View dan Model berada di objek yang terpisah; inilah yang membentuk Pemisahan Kekhawatiran.

Pemisahan Kekhawatiran penting untuk situs web, karena itulah yang memungkinkan seorang desainer untuk bekerja pada desain halaman web terpisah dari programmer.

Bacaan Lebih Lanjut
Pola MVC dan PHP

Robert Harvey
sumber
Baik. Tapi begitu kita telah memisahkan pandangan dari model, apakah masih tugas model untuk memberikan pandangan? Karena itulah yang saya dapatkan dari kutipan di atas: objek (atau model dalam kosa kata Anda) harus tahu cara menampilkannya sendiri, bukan? Dalam arti, katakanlah Anda mendapat Receiptobjek dalam perangkat lunak POS yang khas, Anda masih akan menelepon Receipt.draw(Canvas)dan tidak ReceiptView.draw(Receipt).
MrHadiSatrio
2
Dalam MVC, adalah tanggung jawab Pengendali untuk memilih tampilan mana yang akan digunakan.
Robert Harvey
Tetapi objek pengontrol adalah apa yang secara tepat diajukan sebagai hal yang harus dihindari dalam persepsi Barat dalam Pemikiran Objek (dan dengan demikian dalam kutipan itu). Kutipan secara eksplisit menyatakan bahwa seluruh ide di balik "objek yang tahu cara menampilkan diri" adalah untuk menghindari "objek manajer dan pengontrol".
MrHadiSatrio
Tidak apa-apa, tapi saya pikir Anda harus membatasi pemikiran itu pada objek yang tujuan utamanya adalah tampilan visual. Tampilan, dengan kata lain. Pengontrol tidak peduli bagaimana tampilan itu sendiri; hanya peduli tentang tampilan mana yang akan digunakan. Selain itu, MVC bukan satu-satunya paradigma tampilan yang mungkin, dan lainnya (terutama MVVM) bekerja agak berbeda. Tetapi prinsip dasar Pemisahan Kekhawatiran tetap ada.
Robert Harvey
Perhatikan bahwa buku yang Anda baca sudah cukup tua untuk buku perangkat lunak (2004). MVC dan MVVM belum umum digunakan.
Robert Harvey
1

Menilai dari kutipan yang Anda tempel, Anda salah menafsirkan teks.

Penulis tidak mengatakan bahwa setiap objek harus dapat menampilkan dirinya dalam UI. Ini tidak mungkin, karena suatu objek tidak dapat mengetahui apa UI itu akan ditampilkan di (dalam aplikasi WinForms, aplikasi linux menggunakan XServer, sebagai string JSON, sebagai XML, sebagai gambar PNG dll).

Maksudnya adalah bahwa Anda harus menulis pandangan khusus yang satu-satunya tanggung jawab adalah menampilkan entitas tertentu. Misalnya Anda dapat menulis tampilan yang menjadikan objek sebagai HTML (seperti yang dilakukan oleh tampilan dalam aplikasi MVC). Anda bisa membuat serializer JSON yang bisa mengubah objek menjadi string JSON. Anda bisa membuat objek yang mengubah objek jenis lain menjadi laporan PDF. Semuanya tergantung.

Intinya adalah, pisahkan entitas bisnis dari representasi visual (atau serial). Mereka adalah hal yang berbeda dan berubah karena alasan yang berbeda.

sara
sumber
Saya telah mengedit pertanyaan saya untuk menguraikan kutipan.
MrHadiSatrio
1
Meskipun saya akui jawaban saya tidak lagi relevan, saya tidak mengerti apa pertanyaan Anda dengan kutipan itu. Kutipan tampaknya lebih berbicara dalam hal API dan antarmuka, daripada rendering visual. Bagian mana dari suatu objek yang harus dapat diakses dan pesan apa yang dapat dikirim agar dapat menyelesaikan pekerjaannya di domain bisnis?
sara
"Jika kami sedang membangun GUI yang akan berfungsi sebagai perantara antara objek perangkat lunak dan objek manusia, kami akan menggunakan mesin terbang untuk tujuan tampilan dan widget untuk tujuan interaksi." Menilai dengan kalimat itu, saya cukup yakin kutipan itu juga menyiratkan tujuan rendering visual.
MrHadiSatrio
Tidak ada yang menyatakan bahwa "objek tersebut harus memilih mesin terbang dan widget apa yang paling mewakili untuk setiap konteks tertentu, dan juga harus bertanggung jawab untuk membuat mesin terbang dan widget tersebut." Objek dan benda yang menampilkannya tidak harus (tidak boleh) merupakan hal yang sama.
sara