Ini akan menjadi pertanyaan yang sangat non-teknis, lunak dan saya tidak yakin apakah ini platform yang tepat. Tapi saya seorang siswa CS pemula jadi saya harap kalian menoleransi itu.
Pada semester pertama kami diperkenalkan dengan konsep OOP seperti enkapsulasi, penyembunyian data, modularitas, pewarisan dan sebagainya melalui Java dan UML. (Java adalah bahasa pemrograman pertama saya)
Cara saya memahaminya, OOP adalah cara mengelola kompleksitas perangkat lunak. Tetapi prinsip-prinsipnya tidak baru atau unik, mereka dalam arti universal untuk semua bidang teknik.
Misalnya mobil adalah struktur yang sangat kompleks yang kerumitannya dikelola oleh hierarki komponen modular dan dikemas dengan perilaku dan antarmuka yang terdefinisi dengan baik.
Tapi saya tidak mengerti alasan di balik memperkenalkan paradigma pemrograman baru. Saya pikir semua prinsip yang digunakan untuk mengelola kompleksitas dapat diwujudkan dengan bahasa pemrograman prosedural. Sebagai contoh, untuk modularitas kita hanya dapat membagi program menjadi banyak program kecil yang melakukan tugas-tugas yang didefinisikan dengan baik yang kodenya terkandung dalam file terpisah. Program-program ini akan berinteraksi satu sama lain melalui input dan output yang terdefinisi dengan baik. File-file tersebut mungkin dilindungi (terenkripsi?) Untuk mencapai enkapsulasi. Untuk penggunaan ulang kode, kita dapat memanggil file-file itu kapan saja mereka dibutuhkan dalam program baru. Tidakkah ini menangkap semua OOP atau apakah saya kehilangan sesuatu yang sangat jelas?
Saya tidak meminta bukti bahwa OOP mengelola kompleksitas. Menurut pendapat saya itu memang benar. Tetapi saya pikir semua prinsip yang digunakan untuk mengelola kompleksitas seperti modularitas, enkapsulasi, penyembunyian data, dan sebagainya dapat dengan mudah diimplementasikan oleh bahasa prosedural. Jadi mengapa benar-benar OOP jika kita dapat mengelola kompleksitas tanpa itu?
sumber
Jawaban:
Biarkan saya coba dengan jawaban teori yang sangat rendah :)
Apa yang sebenarnya Anda tanyakan adalah: Mengapa menyertakan dukungan untuk Object Orientation (OO) langsung dalam bahasa ketika bahasa prosedural dapat digunakan untuk merancang dan menulis kode OO?
Dan jawabannya adalah: Untuk memiliki standar bagaimana OO diekspresikan dalam kode sumber sehingga Anda tidak berakhir dengan 22 implementasi yang berbeda untuk abstraksi yang sama.
Sebagai contoh, katakanlah saya membuat
MagicButton
danMagicSlider
yang dapat digunakan dalam sistem antarmuka pengguna. Saya perlu cara untuk mengelompokkan metode yang dapat digunakan dengan MagicButton, metode yang hanya dapat digunakan dengan MagicSlider, dan metode yang dapat digunakan oleh keduanya. Objek-objek ini berbagi beberapa metode karena keduanya adalah objek Magic gui.Saya dapat melakukan pengelompokan dengan memberi nama fungsi dengan cara khusus
MagicSlider_DoSomething ...
, dengan memasukkan metode dalam file tertentu yang dinamai dengan cara khususMagicSliderMethods.XXX
, atau saya dapat menemukan beberapa cara khusus lain untuk melakukan hal yang sama. Jika tidak ada cara standar dalam bahasa untuk melakukannya, saya akan melakukannya berbeda dari Anda, dan berbeda dari orang lain. Ini membuat kode berbagi jauh lebih sulit.Ya, keterlambatan pengiriman - metode virtual dalam bahasa OO - dapat diimplementasikan dalam bahasa prosedural, tetapi ada banyak cara berbeda untuk mengimplementasikannya. Bergantung pada siapa yang menulis kode Anda akan berakhir dengan implementasi OO yang berbeda di dalam program yang sama.
Pikirkan tentang pengembang pemeliharaan yang buruk. Orang ini harus mengelola abstraksi objek yang berbeda dan cara yang berbeda untuk memanggil metode virtual tergantung pada siapa yang menulis kode asli.
Juga: Memiliki abstraksi dalam bahasa memungkinkan editor kode tingkat lanjut seperti Eclipse untuk melakukan banyak analisis statis pada kode. Misalnya Eclipse dapat menawarkan daftar semua metode yang dapat digunakan pada objek, serta implementasi otomatis dari "metode TODO" kosong. Eclispe tahu persis metode mana yang harus diterapkan oleh kelas Anda berdasarkan kelas mana yang Anda perluas dan antarmuka mana yang Anda terapkan. Ini hampir mustahil jika tidak ada standar bahasa untuk melakukan OO.
sumber
Tidak satu pun dari mereka adalah konsep OOP. Mereka semua ada di luar OO, independen dari OO dan bahkan banyak ditemukan sebelum OO.
Jadi, jika Anda berpikir bahwa itulah yang dimaksud dengan OO, maka kesimpulan Anda benar: Anda dapat melakukan semua itu dalam bahasa prosedural, karena tidak ada hubungannya dengan OO .
Sebagai contoh, salah satu makalah mani tentang Modularitas adalah Pada Kriteria Untuk Digunakan dalam Sistem Penguraian menjadi Modul . Tidak disebutkan OO di sana. (Itu ditulis pada tahun 1972, saat itu OO masih merupakan ceruk yang tidak jelas, meskipun sudah berusia lebih dari satu dekade.)
Sementara Abstraksi Data penting dalam OO, itu lebih merupakan konsekuensi dari fitur utama OO (Messaging) daripada itu adalah fitur yang menentukan. Juga, sangat penting untuk diingat bahwa ada berbagai jenis abstraksi data. Dua jenis abstraksi data yang paling umum digunakan saat ini (jika kita mengabaikan "tidak abstraksi apa pun", yang mungkin masih digunakan lebih dari dua gabungan lainnya), adalah Abstrak Jenis dan Objek Data . Jadi, hanya dengan mengatakan "Menyembunyikan Informasi", "Enkapsulasi", dan "Abstraksi Data", Anda tidak mengatakan apa pun tentang OO, karena OO hanyalah satu bentuk Abstraksi Data, dan keduanya pada dasarnya berbeda secara mendasar:
Omong-omong, ini artinya di Java, kelas tidak berorientasi objek. Dua contoh dari kelas yang sama dapat mengakses representasi masing-masing dan implementasi pribadi. Oleh karena itu, instance dari kelas bukanlah objek, mereka sebenarnya adalah instance ADT. Java
interface
, bagaimanapun, jangan memberikan berorientasi objek abstraksi data. Jadi, dengan kata lain: hanya instance dari interface yang objek di Java, instance dari class tidak.Pada dasarnya, untuk tipe, Anda hanya dapat menggunakan antarmuka. Ini berarti jenis parameter metode dan konstruktor, jenis kembali metode, jenis bidang contoh, bidang statis, dan bidang lokal, argumen ke
instanceof
operator atau operator gips, dan argumen jenis untuk konstruktor tipe generik harus selalu berupa antarmuka. Kelas dapat digunakan hanya secara langsung setelahnew
operator, di tempat lain.Apa yang Anda gambarkan adalah OO.
Itu memang cara yang baik untuk berpikir tentang OO. Faktanya, itulah yang ada di pikiran para penemu OO. (Alan Kay melangkah lebih jauh: dia membayangkan banyak komputer kecil mengirim pesan satu sama lain melalui jaringan.) Apa yang Anda sebut "program" biasanya disebut "objek" dan alih-alih "panggilan", kita biasanya mengatakan "mengirim pesan" ".
Orientasi Objek adalah semua tentang Pesan (alias pengiriman dinamis ). Istilah "Object Oriented" diciptakan oleh Dr. Alan Kay, desainer utama Smalltalk, dan ia mendefinisikannya seperti ini :
Mari kita jabarkan:
Dari segi implementasi, olahpesan adalah panggilan prosedur yang terikat akhir, dan jika panggilan prosedur terlambat, maka Anda tidak dapat mengetahui pada waktu desain apa yang akan Anda panggil, sehingga Anda tidak dapat membuat asumsi tentang representasi konkret negara. Jadi, sebenarnya ini tentang pesan, keterlambatan mengikat adalah implementasi dari pesan dan enkapsulasi adalah konsekuensi dari itu.
Dia kemudian mengklarifikasi bahwa " Gagasan besar adalah 'pesan' ", dan menyesal telah menyebutnya "berorientasi objek" daripada "berorientasi pesan", karena istilah "berorientasi objek" menempatkan fokus pada hal yang tidak penting (objek ) dan mengalihkan perhatian dari apa yang benar-benar penting (olahpesan):
(Tentu saja, hari ini, kebanyakan orang bahkan tidak fokus pada objek tetapi pada kelas, yang bahkan lebih salah.)
Pesan adalah hal mendasar bagi OO, baik sebagai metafora maupun sebagai mekanisme.
Jika Anda mengirim pesan kepada seseorang, Anda tidak tahu apa yang mereka lakukan dengannya. Satu- satunya hal yang dapat Anda amati, adalah respons mereka. Anda tidak tahu apakah mereka memproses pesan itu sendiri (yaitu jika objek memiliki metode), jika mereka meneruskan pesan tersebut ke orang lain (delegasi / proxy), jika mereka memahaminya. Itulah enkapsulasi tentang semua, itulah tujuan dari OO. Anda bahkan tidak dapat membedakan proksi dari yang asli, asalkan merespons bagaimana Anda mengharapkannya.
Istilah yang lebih "modern" untuk "pengiriman pesan" adalah "metode pengiriman dinamis" atau "panggilan metode virtual", tetapi itu kehilangan metafora dan berfokus pada mekanisme.
Jadi, ada dua cara untuk melihat definisi Alan Kay: jika Anda melihatnya berdiri sendiri, Anda mungkin mengamati bahwa pesan pada dasarnya adalah panggilan prosedur yang terikat akhir dan ikatan yang mengikat menyiratkan enkapsulasi, sehingga kita dapat menyimpulkan bahwa # 1 dan # 2 sebenarnya redundan, dan OO adalah tentang pengikatan akhir.
Namun, ia kemudian mengklarifikasi bahwa hal yang penting adalah olahpesan, sehingga kita dapat melihatnya dari sudut yang berbeda: olahpesan terlambat. Sekarang, jika olahpesan adalah satu - satunya hal yang mungkin, maka # 3 akan sepele benar: jika hanya ada satu hal, dan hal itu adalah keterlambatan, maka semua hal terikat terlambat. Dan sekali lagi, enkapsulasi mengikuti dari olahpesan.
Poin-poin serupa juga dibuat dalam On Understanding Data Abstraction, Revisited oleh William R. Cook dan juga Proposalnya untuk Definisi Modern tentang "Objek" dan "Berorientasi Objek" :
Di Smalltalk-72, bahkan tidak ada benda! Ada hanya aliran pesan yang mendapat diurai, ditulis ulang dan dialihkan. Pertama datang metode (cara standar untuk mengurai dan mengubah rute aliran pesan), kemudian datang objek (pengelompokan metode yang berbagi beberapa keadaan pribadi). Warisan datang jauh kemudian, dan kelas hanya diperkenalkan sebagai cara untuk mendukung warisan. Andaikata kelompok riset Kay sudah tahu tentang prototipe, mereka mungkin tidak akan pernah memperkenalkan kelas sejak awal.
Benjamin Pierce dalam Jenis dan Bahasa Pemrograman berargumen bahwa fitur penentu Orientasi Objek adalah Open Recursion .
Jadi: menurut Alan Kay, OO adalah tentang pesan. Menurut William Cook, OO adalah tentang pengiriman metode dinamis (yang benar-benar hal yang sama). Menurut Benjamin Pierce, OO adalah tentang Open Recursion, yang pada dasarnya berarti bahwa referensi-diri diselesaikan secara dinamis (atau setidaknya itu cara untuk memikirkannya), atau, dengan kata lain, pengiriman pesan.
Seperti yang Anda lihat, orang yang menciptakan istilah "OO" memiliki pandangan yang agak metafisik pada objek, Cook memiliki pandangan yang agak pragmatis, dan Pierce memiliki pandangan matematika yang sangat ketat. Tetapi yang penting adalah: filsuf, pragmatis, dan ahli teori semuanya setuju! Pesan adalah satu pilar OO. Titik.
Perhatikan bahwa tidak disebutkan pewarisan di sini! Warisan tidak penting untuk OO. Secara umum, sebagian besar bahasa OO memiliki beberapa cara implementasi digunakan kembali tetapi itu tidak harus menjadi warisan. Bisa juga berupa beberapa bentuk delegasi, misalnya. Bahkan, The Treaty of Orlando membahas delegasi sebagai alternatif pewarisan dan bagaimana berbagai bentuk pendelegasian dan pewarisan mengarah pada titik desain yang berbeda dalam ruang desain bahasa yang berorientasi objek. (Perhatikan bahwa sebenarnya bahkan dalam bahasa yang mendukung warisan, seperti Java, orang sebenarnya diajarkan untuk menghindarinya, sekali lagi menunjukkan bahwa itu tidak perlu untuk OO.)
sumber
Ketika Anda mengatakan, "sangat mudah" Anda membuat pernyataan yang sangat berani. Cara saya membacanya adalah: "Saya tidak melihat kesulitannya, jadi pasti tidak terlalu besar." Ketika diutarakan seperti itu, menjadi jelas bahwa Anda tidak bertanya "mengapa kita membutuhkan OO", Anda bertanya "mengapa bukan kesulitan yang ditemui paradigma pemrograman lain yang mengarah pada penemuan OO yang segera terlihat oleh saya? "
Jawaban untuk pertanyaan itu adalah bahwa banyak dari kesulitan ini tidak ada dalam jenis program yang sedang Anda kerjakan. Anda tidak diminta untuk memperbarui kode spageti berusia 40 tahun. Anda tidak berusaha menulis pengelola tampilan baru untuk sistem operasi. Anda tidak men-debug aplikasi multithreaded terdistribusi.
Untuk banyak jenis program mainan yang kami para siswa CS ditugaskan untuk menulis, kami dapat juga menulisnya dalam BASIC atau perakitan sebagai Java atau Python. Itu karena kompleksitas tugas yang melekat sangat rendah, hanya ada satu pengembang, tidak ada masalah interoperabilitas warisan, kinerja tidak masalah, dan kode kemungkinan hanya akan pernah berjalan beberapa kali pada satu mesin.
Bayangkan mengambil sopir siswa dan meminta mereka untuk bergabung ke jalan yang sibuk di jam sibuk, pada transmisi manual tanpa sinkronisasi, menuju ke atas bukit yang curam. Bencana. Mengapa? Mereka tidak dapat mengelola tingkat kerumitan yang diperlukan untuk secara bersamaan mengikuti semua aturan yang diperlukan oleh tugas tersebut.
Sekarang bayangkan siswa yang sama, kendaraan yang sama, mengemudi dengan kecepatan berjalan di tempat parkir kosong. Mereka baik-baik saja, karena tingkat keterampilan mereka memadai untuk tugas itu. Tidak ada tekanan, risiko kecil, dan mereka dapat mengambil masing-masing tugas mulai, mencengkeram, menggeser, mempercepat, menyetir satu per satu.
Siswa itu mungkin bertanya mengapa kita memiliki transmisi otomatis, jika seorang pengemudi yang terampil dapat melakukan semua hal ini secara bersamaan? Jawabannya adalah bahwa pengemudi yang cukup terampil tidak, dalam kondisi optimal, perlu otomatis. Tapi kami tidak semua pengemudi profesional dalam kondisi puncak, dan kami biasanya menginginkan kenyamanan memiliki desainer mobil yang mengurus semua kerumitan itu bagi kami.
Pemrogram yang terampil dan cukup disiplin memang dapat membuat sistem kompleksitas-tinggi yang berfungsi dalam C, atau assembly. Tapi kita tidak semua Linus Torvalds. Kita juga tidak harus menciptakan perangkat lunak yang bermanfaat.
Saya pribadi tidak tertarik harus menemukan kembali semua fitur bahasa modern sebelum saya bahkan dapat mengatasi masalah yang ada. Jika saya dapat memanfaatkan bahasa yang menyertakan solusi untuk masalah yang sudah diselesaikan, mengapa saya tidak?
Jadi saya akan membalikkan pertanyaan Anda, dan bertanya kepada Anda, jika bahasa menyediakan fitur nyaman seperti enkapsulasi, dan polimorfisme, mengapa kita tidak menggunakannya?
sumber
Apa yang Anda gambarkan bukan OOP, itu abstraksi. Abstraksi hadir dalam semua model desain modern, bahkan yang bukan OOP. Dan OOP adalah jenis abstraksi yang sangat spesifik.
Pertama, perlu dicatat bahwa tidak ada definisi tunggal OOP, jadi mungkin ada orang yang tidak setuju dengan apa yang saya karakterisasikan sebagai OOP.
Kedua, penting untuk diingat bahwa OOP terinspirasi oleh model desain tradisional, sehingga kesamaan dengan desain mobil bukan kebetulan.
Namun, inilah beberapa cara OOP lebih bernuansa daripada apa yang Anda katakan:
Enkapsulasi: ini bukan hanya tentang memiliki set antarmuka untuk modul (yaitu abstraksi), ini tentang melarang akses di luar antarmuka ini. Di Jawa, mengakses variabel pribadi adalah kesalahan kompilasi, sedangkan dalam desain mobil Anda, Anda dapat (dalam beberapa kasus) menggunakan hal-hal dengan cara yang berbeda dari antarmuka yang diinginkan.
Warisan: Ini benar-benar hal yang membuat OOP unik. Setelah Anda mendefinisikan antarmuka, Anda dapat membuat banyak hal untuk mengimplementasikan antarmuka itu, dan Anda dapat melakukan ini dengan cara heirarkis, mengubah bagian spesifik dari implementasinya, sambil mewarisi semua bagian sebelumnya, secara besar-besaran mengurangi duplikasi kode.
Jika Anda berpikir dalam hal komponen mobil yang dienkapsulasi, sebenarnya tidak ada yang setara dengan ini. Tidak ada cara bagi saya untuk membuat roda gigi dengan mengambil roda gigi yang berbeda dan mengubah bagian tertentu dari implementasinya. (Setidaknya saya tidak berpikir begitu, saya tidak tahu banyak tentang mobil).
Polimorfisme : Setelah Anda mendefinisikan antarmuka, apa pun yang menggunakan antarmuka itu tidak dapat dibedakan, dari sudut pandang operasi apa yang tersedia, dan Anda tidak perlu tahu implementasi apa yang digunakan untuk menggunakan antarmuka. Di sinilah subtyping dan Prinsip Pergantian Liskov menjadi penting.
Penggandengan : Aspek utama dari OOP adalah bahwa kami erat menghubungkan hal-hal dengan operasi yang sama, dan menyebarkan berbagai bentuk yang mereka dapat miliki. Data digabungkan dengan operasi pada data itu. Ini berarti sangat mudah untuk menambahkan bentuk data baru (implementasi baru), tetapi sangat sulit untuk menambahkan operasi baru ke antarmuka (karena Anda harus memperbarui setiap kelas yang mengimplementasikan antarmuka). Ini berbeda dengan Tipe Data Aljabar dalam bahasa fungsional, di mana sangat mudah untuk menambahkan operasi baru (Anda hanya menulis fungsi yang berhubungan dengan semua kasus), tetapi sulit untuk menambahkan varian baru (karena Anda perlu menambahkan yang baru huruf ke semua fungsi Anda).
sumber
Ini tergantung pada arti kata, "kebutuhan."
Jika "kebutuhan" berarti membutuhkan, tidak, kami tidak memerlukannya.
Jika "kebutuhan" berarti "memberikan manfaat yang kuat", maka saya akan berkata, "Ya," kami menginginkannya.
Gambar besar
Bahasa OO mengikat fungsionalitas ke data.
Anda dapat menghindari fungsi pengikatan dan penulisan ini yang menyampaikan nilai data.
Tapi kemudian Anda mungkin akan berakhir dengan rasi bintang data yang berjalan bersama, dan Anda akan mulai membagikan tupel, catatan, atau kamus data.
Dan sungguh, itu semua pemanggilan metode adalah: fungsi parsial pada set data terikat.
Fitur demi fitur
Fitur OOP:
Namun, tidak satu pun dari hal-hal itu terjadi begitu mudah seperti dengan bahasa berorientasi objek dengan dukungan kelas satu dari fitur-fitur itu.
Referensi
Ada banyak kritik terhadap OOP .
Namun, penelitian tampaknya mengindikasikan bahwa kami mendapatkan produktivitas programmer yang lebih besar dari penggunaan kembali kode melalui OOP. Ini adalah temuan yang kontroversial, dan beberapa peneliti mengatakan mereka tidak dapat mereproduksi kenaikan produktivitas ini, mengingat kendala tertentu. (sumber)
Kesimpulan
Kami tidak "membutuhkan" OOP. Tetapi dalam beberapa kasus, pengguna menginginkan OOP.
Pemahaman saya adalah bahwa programmer dewasa bisa sangat produktif dalam gaya berorientasi objek. Dan ketika paket memiliki objek inti dengan antarmuka sederhana yang mudah dipahami, bahkan programmer baru bisa menjadi sangat produktif dengan cepat.
sumber
Saya akan mencoba untuk singkat.
Prinsip inti OO adalah kombinasi data dan perilaku dalam satu unit organisasi (objek).
Inilah yang memungkinkan kami untuk mengontrol kompleksitas dan itu adalah konsep yang cukup inovatif ketika muncul. Bandingkan dengan file di satu sisi (data murni), program yang membaca dan memproses file di sisi lain (logika murni) dan output (data murni lagi).
Hanya sekali Anda memiliki paket data dan logika bersama, memodelkan entitas dunia nyata, Anda dapat mulai bertukar pesan, membuat kelas anak, memisahkan pribadi dari data dan perilaku publik, menerapkan perilaku polimorfik, melakukan semua keajaiban khusus-OO ini.
Jadi, ya, OO adalah masalah besar. Dan tidak, itu bukan hanya sekelompok barang lama dengan nama mewah.
Membongkar semuanya, melihat elemen-elemennya dan kemudian berkata "oh, well, tidak ada apa pun di sini yang belum pernah saya lihat sebelumnya" tidak mengenali majelis yang memegang inovasi. Hasilnya lebih dari jumlah bagian-bagiannya.
sumber
Tidak ada definisi "resmi" dari pemrograman berorientasi objek, dan orang-orang yang masuk akal tidak setuju pada apa yang sebenarnya mendefinisikan kualitas OO. Ada yang bilang pesan, ada yang bilang subtyping, ada yang bilang warisan, ada yang bilang bundling data dan perilaku. Itu tidak berarti istilah itu tidak ada artinya, hanya saja Anda tidak boleh terlalu terjebak dalam pertengkaran tentang apa sebenarnya OO itu.
Enkapsulasi dan modularitas adalah prinsip desain yang lebih mendasar, dan harus diterapkan dalam semua paradigma pemrograman. Para pendukung OO tidak mengklaim bahwa sifat-sifat ini hanya dapat dicapai dengan OO - hanya bahwa OO sangat cocok untuk mencapai ini. Tentu saja para pendukung paradigma lain seperti mengatakan pemrograman fungsional mengklaim hal yang sama untuk paradigma mereka. Dalam prakteknya banyak bahasa yang sukses adalah multi-paradigma dan OO, fungsional dll harus dilihat sebagai alat daripada "satu cara yang benar".
Benar, karena pada akhirnya Anda dapat melakukan apa saja dalam bahasa pemrograman apa pun. Mungkin lebih mudah di beberapa bahasa daripada di yang lain, karena semua bahasa memiliki kekuatan dan kelemahan yang berbeda.
sumber
Sesuatu yang belum dijawab oleh jawaban lain: nyatakan.
Anda berbicara tentang OO sebagai alat untuk mengelola kompleksitas . Apa kompleksitasnya? Itu istilah yang kabur. Kita semua memiliki perasaan gestalt tentang apa artinya, tetapi lebih sulit untuk menjabarkannya. Kita dapat mengukur kompleksitas siklomatik, yaitu jumlah jalur run-time melalui kode, tetapi saya tidak tahu itu yang sedang kita bicarakan ketika kita menggunakan OO untuk mengelola kompleksitas.
Apa yang saya pikir kita bicarakan adalah kompleksitas yang terkait dengan negara.
Ada dua ide utama di balik enkapsulasi . Salah satunya, menyembunyikan detail implementasi , cukup tertutup dalam jawaban lainnya. Tapi yang lain menyembunyikan kondisi run-time-nya . Kami tidak main-main dengan data internal objek; kami mengirim pesan (atau memanggil metode jika Anda lebih suka detail implementasi daripada konsep seperti yang ditunjukkan Jörg Mittag). Mengapa?
Orang-orang telah menyebutkan itu karena Anda tidak dapat mengubah struktur internal data Anda tanpa mengubah kode yang mengaksesnya, dan Anda ingin melakukannya di satu tempat (metode accessor) alih-alih 300 tempat.
Tapi itu juga karena membuat kode sulit untuk dipikirkan : kode prosedural (apakah dalam bahasa yang sifatnya prosedural atau hanya ditulis dengan gaya itu) menawarkan sedikit bantuan untuk memaksakan pembatasan pada mutasi negara. Apa pun bisa berubah kapan saja dari mana saja. Fungsi / metode panggilan mungkin memiliki aksi seram di kejauhan. Pengujian otomatis lebih sulit, karena keberhasilan tes ditentukan oleh nilai variabel non-lokal yang banyak diakses / diakses.
Dua paradigma pemrograman besar lainnya (OO dan fungsional) menawarkan solusi yang menarik, namun hampir sama sekali bertentangan dengan masalah kompleksitas terkait kondisi. Dalam pemrograman fungsional seseorang mencoba menghindarinya sepenuhnya: fungsi umumnya murni, operasi pada struktur data mengembalikan salinan daripada memperbarui yang asli di tempat, dll.
OO di sisi lain menawarkan alat untuk berurusan dengan mengelola negara (bukan alat untuk menghindarinya). Selain alat tingkat bahasa seperti pengubah akses (dilindungi / publik / pribadi), getter dan setter, dll. Ada juga sejumlah konvensi terkait seperti Hukum Demeter yang menyarankan agar tidak menjangkau objek melalui untuk mendapatkan data objek lainnya. .
Perhatikan bahwa Anda tidak perlu objek untuk benar-benar melakukan semua ini: Anda bisa memiliki penutupan yang memiliki data yang tidak dapat diakses dan mengembalikan struktur fungsi data untuk memanipulasinya. Tapi bukankah itu sebuah objek? Bukankah itu sesuai dengan konsepsi kita tentang apa objek itu, secara intuitif? Dan jika kita memiliki konsep ini, bukankah lebih baik mengulanginya dalam bahasa daripada (seperti jawaban lain katakan) mengandalkan ledakan kombinasi dari implementasi ad-hoc yang bersaing?
sumber
Tidak. Tetapi mereka dapat membantu dalam banyak situasi.
Saya telah menggunakan terutama satu bahasa OO selama beberapa dekade, tetapi sebagian besar kode saya sebenarnya benar-benar gaya prosedural pra-OO. Namun, untuk apa pun yang melibatkan GUI, saya menggunakan pustaka OO yang luas dari bahasa untuk metode dan objek bawaan, karena sangat menyederhanakan kode saya.
Misalnya, aplikasi Windows yang menggunakan API Windows tingkat rendah asli untuk menampilkan formulir, tombol, dan bidang edit memerlukan banyak kode, sedangkan sebaliknya menggunakan perpustakaan objek yang datang dengan Visual Basic atau C # atau Delphi membuat hal yang sama Program kecil dan sepele. Jadi, kode OO saya biasanya relatif kecil dan untuk GUI, sedangkan kode saya yang dipanggil objek-objek itu biasanya jauh lebih besar dan biasanya tidak peduli dengan menjadi OO (meskipun dapat bervariasi tergantung pada masalah yang saya coba selesaikan).
Saya telah melihat program OO yang terlalu rumit, bergantung pada aturan esoterik yang rumit tentang bagaimana objek diimplementasikan, dan bisa lebih sederhana jika ditulis tanpa konsep OO. Saya juga melihat yang sebaliknya: sistem kompleks yang menangis untuk diimplementasikan kembali dan disederhanakan dengan menggunakan objek.
Ketika Anda mendapatkan pengalaman, Anda akan menemukan situasi yang berbeda membutuhkan alat dan solusi yang berbeda, dan satu ukuran tidak cocok untuk semua.
sumber
Sebagai seseorang yang terlibat dalam proyek yang sangat besar seluruhnya ditulis dalam C, saya pasti dapat mengatakan bahwa jawabannya adalah "tidak" yang jelas.
Modularitas itu penting. Tapi modularitas dapat diimplementasikan dalam bahasa yang praktis. Sebagai contoh, C mendukung kompilasi modular, file header dan tipe struktur. Ini cukup untuk 99% kasus. Tentukan modul untuk setiap tipe data abstrak baru yang Anda butuhkan, dan tentukan fungsi untuk beroperasi pada tipe data. Terkadang, Anda menginginkan kinerja dan fungsi-fungsi itu ada di file header sebagai fungsi inline, di lain waktu Anda akan menggunakan fungsi standar. Itu semua tidak terlihat oleh pengguna cara mana yang dipilih.
Komposisi penopang struktur. Misalnya, Anda bisa memiliki tabel hash terkunci yang terdiri dari kunci mutex dan tabel hash biasa. Ini bukan pemrograman berorientasi objek; tidak ada subclass yang dilakukan. Komposisi adalah alat yang jauh lebih tua dari gagasan pemrograman berorientasi objek.
Untuk 1% kasus di mana kompilasi modularitas tidak cukup, dan Anda memerlukan modularitas runtime, ada hal yang disebut pointer fungsi. Mereka memungkinkan memiliki implementasi individual dari antarmuka yang terdefinisi dengan baik. Perhatikan bahwa ini bukan pemrograman berorientasi objek dalam bahasa yang tidak berorientasi objek. Ini mendefinisikan antarmuka dan kemudian mengimplementasikannya. Misalnya, subklas tidak digunakan di sini.
Pertimbangkan mungkin proyek open source paling kompleks yang ada. Yakni, kernel Linux. Itu sepenuhnya ditulis dalam bahasa C. Hal ini dilakukan terutama dengan menggunakan alat modularitas tingkat kompilasi standar termasuk komposisi, dan kemudian kadang-kadang setiap kali dibutuhkan modularitas runtime, fungsi pointer digunakan untuk mendefinisikan dan mengimplementasikan antarmuka.
Jika Anda mencoba menemukan contoh pemrograman berorientasi objek di kernel Linux, saya yakin menemukan contoh seperti itu sangat sulit, kecuali jika Anda memperluas pemrograman berorientasi objek untuk memasukkan tugas-tugas standar seperti "mendefinisikan antarmuka dan kemudian mengimplementasikannya".
Perhatikan bahwa bahkan bahasa pemrograman C mendukung pemrograman berorientasi objek jika Anda benar-benar membutuhkannya. Sebagai contoh, pertimbangkan toolkit antarmuka pengguna grafis GTK. Ini sebenarnya berorientasi objek, meskipun ditulis dalam bahasa yang tidak berorientasi objek. Jadi, ini menunjukkan bahwa gagasan bahwa Anda memerlukan "bahasa berorientasi objek" sangat cacat. Tidak ada yang bisa dilakukan oleh bahasa berorientasi objek yang tidak bisa dilakukan oleh jenis bahasa lain. Selain itu, jika Anda seorang programmer ahli, Anda tahu cara menulis kode berorientasi objek dalam bahasa apa pun dengan sangat mudah. Ini bukan beban untuk menggunakan C, misalnya.
Jadi, kesimpulannya adalah bahwa bahasa berorientasi objek mungkin hanya berguna untuk programmer pemula yang gagal memahami bagaimana konsep itu sebenarnya diimplementasikan. Namun, saya tidak ingin berada di dekat proyek di mana programmer adalah programmer pemula.
sumber
Alasan untuk memperkenalkan paradigma pemrograman, termasuk metode berorientasi objek, adalah untuk membuatnya lebih mudah untuk membuat program yang lebih canggih dan kuat. Dalam edisi Agustus 1981 dari Majalah Byte, Daniel Ingalls , salah satu pencipta kunci Smalltalk, mendefinisikan "berorientasi objek" sebagai melibatkan kemampuan berikut:
Ini adalah prinsip yang diidentifikasi Ingalls sebagai pertimbangan desain mengemudi untuk SmallTalk-80 yang dikembangkan oleh Xerox Parc Research. Dalam artikel majalah yang disebutkan di atas, Anda dapat membaca deskripsi terperinci dari masing-masing prinsip ini dan bagaimana mereka berkontribusi pada paradigma berorientasi objek menurut Ingalls.
Semua prinsip ini dapat diterapkan dengan menggunakan bahasa lengkap Turing, apakah itu prosedural, bahasa rakitan atau apa pun. Ini adalah prinsip desain, bukan spesifikasi bahasa. Bahasa berorientasi objek dimaksudkan untuk membuatnya lebih mudah untuk menggunakan prinsip-prinsip ini saat membuat perangkat lunak.
Misalnya, untuk mengambil prinsip pertama Ingall (manajemen penyimpanan otomatis), siapa pun dapat menulis sistem manajemen penyimpanan otomatis mereka sendiri dalam bahasa prosedural, tetapi akan banyak pekerjaan yang harus dilakukan. Saat menggunakan bahasa seperti SmallTalk atau Java yang memiliki manajemen penyimpanan otomatis bawaan, programmer tidak harus melakukan banyak hal seperti mengelola memori. Pengorbanannya adalah bahwa programmer kurang mendapat kendali atas cara memori digunakan. Jadi, ada manfaat dan kelemahannya. Gagasan paradigma desain seperti pemrograman berorientasi objek adalah bahwa manfaat dari paradigma akan lebih besar daripada kerugian untuk setidaknya beberapa programmer.
sumber
Salah satu cara mengelola kompleksitas perangkat lunak adalah dengan memisahkan kerangka kerja dari tindakan yang diinginkan sepenuhnya menggunakan Bahasa Spesifik Domain . Ini berarti bahwa level kode pemrograman berbeda dari level di mana hasil yang diinginkan dikonfigurasi - bahasa atau sistem yang sama sekali berbeda. Ketika ini dilakukan dengan benar, kode konvensional pada dasarnya menjadi perpustakaan, dan pengguna atau orang lain yang menciptakan hasil yang diinginkan menyambungkan hal-hal bersama-sama dengan bahasa scripting atau alat desain visual, seperti pembuat laporan.
Untuk bisa bekerja, ini membutuhkan gambar batas ketat di sekitar operasi apa yang mungkin dilakukan dan bagaimana mereka terhubung (bahasa skrip atau desain visual, seperti alat konstruksi formulir). Metadata adalah cara penting untuk mengabstraksi konfigurasi run-time dari detail pengkodean, sehingga memungkinkan suatu sistem untuk mendukung berbagai hasil yang diinginkan. Jika batas-batasnya ditetapkan dan dipegang (tidak menerima setiap permintaan untuk perpanjangan yang datang), Anda dapat memiliki sistem yang tahan lama dan kuat yang bekerja untuk orang-orang, tanpa mereka perlu menjadi programmer untuk mencapai apa yang mereka inginkan.
Martin Fowler telah menulis buku tentang ini, dan tekniknya hampir sama tuanya dengan pemrograman itu sendiri. Anda hampir bisa mengatakan bahwa semua bahasa pemrograman adalah Bahasa Khusus Domain, dan idenya endemik, diabaikan karena sangat jelas. Tetapi Anda masih bisa membuat skrip atau alat desain visual Anda sendiri untuk membuat hidup Anda lebih mudah. Terkadang generalisasi masalah membuatnya lebih mudah untuk dipecahkan!
sumber
Ini adalah pertanyaan yang sangat bagus dan saya merasa jawaban yang diberikan di sini belum melakukan keadilan, jadi saya akan melanjutkan dan menambahkan pemikiran saya.
Tujuannya adalah - Mengelola Kompleksitas Perangkat Lunak . Tujuannya bukan "menggunakan bahasa OO".
Tidak ada 'alasan' di balik memperkenalkan paradigma baru. Ini adalah sesuatu yang terjadi secara alami ketika pengkodean menjadi lebih matang. Lebih masuk akal untuk menulis kode di mana kita menambahkan pelatih di akhir kereta (kereta dimodelkan menggunakan daftar tertaut) daripada menambahkan simpul baru ke akhir daftar tertaut.
Coding dalam hal entitas dunia nyata adalah cara-cara yang jelas dan benar untuk kode ketika kita sedang coding tentang entitas dunia nyata.
Sebuah komputer dapat bekerja dengan menambahkan sebuah simpul ke akhir daftar yang terhubung semudah itu dapat bekerja dengan menambahkan pelatih tambahan di ujung kereta. Tetapi bagi manusia itu lebih mudah untuk bekerja dengan kereta dan pelatih daripada dengan daftar dan simpul yang terhubung meskipun ketika kita naik ke level yang lebih dalam, kita menemukan kereta dimodelkan melalui daftar yang terhubung.
Melindungi atau mengenkripsi file tidak dapat mencapai enkapsulasi. Kebalikan dari enkripsi adalah dekripsi. Kebalikan dari enkapsulasi adalah Dekapsulasi yang berarti Dekomposisi struktur dan kelas dalam bahasa pemrograman untuk mencapai kinerja yang lebih baik. Kinerja diperoleh dari mengurangi lalu lintas memori dan menghindari pemeriksaan aturan OOP.
Karenanya Anda dapat menulis kode yang terenkripsi dan juga dienkapsulasi dengan baik karena keduanya adalah konsep yang berbeda.
Enkapsulasi membantu dalam mengelola kompleksitas karena itu dekat dengan kenyataan.
Oleh karena itu, program dalam objek karena, lebih mudah bagi Anda untuk kode dan lebih cepat bagi Anda dan orang lain untuk mengerti.
sumber
Satu hal yang perlu diingat adalah ini:
OOP bukan tentang fitur bahasa; ini tentang cara Anda menyusun kode Anda .
OOP adalah cara berpikir, dan merancang arsitektur kode Anda, dan dapat dilakukan dalam hampir semua bahasa. Ini terutama termasuk bahasa-bahasa tingkat rendah, non-OO, yang disebut assembler dan C. Anda dapat melakukan pemrograman berorientasi objek dengan sempurna di assembler, dan kernel Linux, yang ditulis dalam C, cukup berorientasi objek dalam banyak aspek .
Yang mengatakan, fitur OO dalam bahasa sangat mengurangi jumlah kode boilerplate yang perlu Anda tulis untuk mencapai hasil yang diinginkan . Di mana Anda perlu secara eksplisit mendefinisikan tabel fungsi virtual dan mengisinya dengan pointer fungsi yang sesuai di C, Anda tidak melakukan apa pun di Java, dan Anda selesai. Bahasa OO hanya menghapus semua yang memungkinkan cruft dari kode sumber, menyembunyikannya di belakang abstraksi tingkat bahasa yang bagus (seperti kelas, metode, anggota, kelas dasar, panggilan konstruktor / destruktor implisit, dll.).
Jadi, tidak, kita tidak perlu bahasa OO untuk melakukan OOP. Hanya saja, OOP jauh lebih mudah dilakukan dengan bahasa OO yang layak.
sumber
Pemrograman berorientasi objek lebih dari sekedar modul + enkapsulasi. Seperti yang Anda katakan, dimungkinkan untuk menggunakan enkapsulasi modul + dalam bahasa (prosedural) yang tidak berorientasi objek. OOP melibatkan lebih dari itu: melibatkan objek dan metode. Jadi, tidak, itu tidak menangkap OOP. Lihat, misalnya, https://en.wikipedia.org/wiki/Object-oriented_programming atau pengantar buku teks yang bagus untuk OOP.
sumber
Alasan terbesarnya adalah, ketika sebuah program menjadi lebih kompleks, Anda perlu membuat beberapa bagiannya tidak terlihat dari bagian lain, atau kompleksitas aplikasi dan jumlah fungsi akan membuat otak Anda menggiring bola keluar dari telinga Anda.
Mari kita bayangkan sistem 100 kelas, masing-masing dengan sekitar 20 operasi yang dapat dilakukan pada mereka; itu 2.000 fungsi. Namun, dari jumlah tersebut, mungkin hanya 500 yang merupakan operasi lengkap seperti 'Simpan' dan 'Hapus', sedangkan 1500 adalah fungsi internal yang melakukan sedikit pemeliharaan, atau memiliki peran utilitas. Mempertimbangkan;
Begitu
SetName
juga fungsi yang harus dilakukan orang terhadap seseorang, tetapiSplitPersonName
merupakan fungsi utilitas yang digunakan oleh orang tersebut.Pemrograman prosedural yang lurus tidak membuat perbedaan antara kedua operasi ini. Itu berarti 2.000 fungsional Anda semua bersaing untuk perhatian Anda. Namun, jika kita dapat menandai fungsi-fungsi ini sebagai 'tersedia untuk semua orang yang memiliki catatan orang' dan 'hanya digunakan sebagai fungsi utilitas di dalam catatan orang' maka perhatian kita sekarang adalah 500 'tersedia untuk fungsi semua orang', dan 15 'utilitas' fungsi untuk kelas yang sedang Anda edit.
Itu apa
public
danprivate
lakukan;sumber