Saya telah mempelajari buku "C ++ Demystified" . Sekarang saya sudah mulai membaca "Pemrograman Berorientasi Objek dalam Turbo C ++ edisi pertama (edisi 1)" oleh Robert Lafore. Saya tidak memiliki pengetahuan pemrograman yang melampaui buku-buku ini. Buku ini mungkin sudah usang karena sudah berusia 20 tahun. Saya memiliki edisi terbaru, saya menggunakan yang lama karena saya menyukainya, terutama saya hanya mempelajari konsep dasar OOP yang digunakan dalam C ++ melalui edisi pertama buku Lafore.
Buku Lafore menekankan bahwa "OOP" hanya berguna untuk program yang lebih besar dan kompleks . Dikatakan dalam setiap buku OOP (juga dalam buku Lafore) bahwa paradigma prosedural rentan terhadap kesalahan misalnya data global yang mudah rentan oleh fungsi. Dikatakan bahwa programmer dapat membuat kesalahan jujur dalam bahasa prosedural misalnya dengan membuat fungsi yang secara tidak sengaja merusak data.
Jujur berbicara, saya memposting pertanyaan saya karena saya tidak memahami penjelasan yang diberikan dalam buku ini: Pemrograman Berorientasi Objek dalam C ++ (Edisi ke-4) Saya tidak memahami pernyataan ini yang ditulis dalam buku Lafore:
Pemrograman berorientasi objek dikembangkan karena keterbatasan ditemukan dalam pendekatan sebelumnya untuk pemrograman .... Ketika program tumbuh semakin besar dan kompleks, bahkan pendekatan pemrograman terstruktur mulai menunjukkan tanda-tanda ketegangan ... .... Menganalisis alasan untuk kegagalan-kegagalan ini mengungkapkan bahwa ada kelemahan dalam paradigma prosedural itu sendiri. Tidak peduli seberapa baik pendekatan pemrograman terstruktur diimplementasikan, program besar menjadi sangat kompleks .... ... Ada dua masalah terkait. Pertama, fungsi memiliki akses tidak terbatas ke data global. Kedua, fungsi dan data yang tidak terkait, dasar dari paradigma prosedural, memberikan model yang buruk dari dunia nyata ...
Saya telah mempelajari buku "Dismystified C ++" oleh Jeff Kent, saya sangat menyukai buku ini, dalam buku ini sebagian besar pemrograman prosedural dijelaskan. Saya tidak mengerti mengapa pemrograman prosedural (terstruktur) lemah!
Buku Lafore menjelaskan konsep dengan sangat baik dengan beberapa contoh yang baik. Juga saya telah memahami intuisi dengan membaca buku Lafore bahwa OOP lebih baik daripada pemrograman prosedural tetapi saya ingin tahu bagaimana tepatnya dalam pemrograman pemrograman prosedural lebih lemah daripada OOP.
Saya ingin melihat sendiri apa masalah praktis yang akan dihadapi seseorang dalam pemrograman prosedural, bagaimana OOP akan membuat pemrograman lebih mudah. Saya pikir saya akan mendapatkan jawaban saya hanya dengan membaca buku Lafore secara kontemplatif tetapi saya ingin melihat dengan mata kepala saya sendiri masalah dalam kode prosedural, saya ingin melihat bagaimana kode gaya OOP dari sebuah program menghilangkan kesalahan-kesalahan sebelumnya yang akan terjadi jika program yang sama harus ditulis menggunakan paradigma prosedural.
Ada banyak fitur OOP dan saya mengerti tidak mungkin bagi seseorang untuk menjelaskan kepada saya bagaimana semua fitur ini menghilangkan kesalahan sebelumnya yang akan menghasilkan dengan menulis kode dengan gaya prosedural.
Jadi, inilah pertanyaan saya:
Keterbatasan pemrograman prosedural mana yang ditangani OOP dan bagaimana cara efektif menghapus batasan ini dalam praktik?
Secara khusus, apakah ada contoh untuk program yang sulit dirancang dengan menggunakan paradigma prosedural tetapi mudah dirancang menggunakan OOP?
PS: Cross diposting dari: /programming//q/22510004/3429430
sumber
Jawaban:
Dalam bahasa prosedural, Anda tidak dapat selalu menyatakan batasan yang diperlukan untuk membuktikan bahwa penelepon menggunakan modul dengan cara yang didukung. Dengan tidak adanya batasan kompilator yang dapat diperiksa, Anda harus menulis dokumentasi dan berharap hal itu diikuti, dan menggunakan unit test untuk menunjukkan penggunaan yang dimaksudkan.
Deklarasi Jenis adalah pembatasan deklaratif yang paling jelas (yaitu: "membuktikan bahwa x adalah pelampung"). Memaksa mutasi data melewati fungsi yang diketahui dirancang untuk data itu adalah hal lain. Penegakan protokol (metode memanggil pemesanan) adalah pembatasan lain yang didukung sebagian yaitu: "constructor -> othermethods * -> destructor".
Ada juga manfaat nyata (dan beberapa kelemahan) ketika kompiler tahu tentang polanya. Mengetik statis dengan tipe polimorfik sedikit masalah ketika Anda meniru enkapsulasi data dari bahasa prosedural. Sebagai contoh:
tipe x1 adalah subtipe dari x, t1 adalah subtipe dari t
Ini adalah salah satu cara untuk merangkum data dalam bahasa prosedural untuk memiliki tipe t dengan metode f dan g, dan subkelas t1 yang melakukan hal yang sama:
t_f (t, x, y, z, ...), t_g (t, x, y, ...) t1_f (t1, x, y, z, ...)
Untuk menggunakan kode ini apa adanya, Anda harus melakukan pemeriksaan jenis dan mengaktifkan jenis t sebelum memutuskan jenis f yang akan Anda panggil. Anda bisa mengatasinya seperti ini:
ketik t {d: data f: function g: function}
Sehingga Anda memanggil tf (x, y, z) sebagai gantinya, di mana pemeriksaan ketik dan beralih untuk menemukan metode sekarang diganti dengan hanya memiliki setiap instance menyimpan metode penunjuk metode secara eksplisit. Sekarang jika Anda memiliki sejumlah besar fungsi per jenis, ini adalah representasi yang boros. Anda kemudian dapat menggunakan strategi lain seperti memiliki t tunjuk ke variabel m yang berisi semua fungsi anggota. Jika fitur ini adalah bagian dari bahasa, maka Anda dapat membiarkan kompiler mengetahui bagaimana cara menangani representasi pola ini secara efisien.
Tetapi enkapsulasi data adalah pengakuan bahwa keadaan yang dapat berubah buruk. Solusi berorientasi objek adalah menyembunyikannya di balik metode. Idealnya, semua metode dalam objek akan memiliki urutan panggilan yang terdefinisi dengan baik (yaitu: constructor -> open -> [read | write] -> close -> destruct); yang kadang-kadang disebut 'protokol' (penelitian: "Microsoft Singularity"). Tetapi di luar konstruksi dan kerusakan, persyaratan ini umumnya bukan bagian dari sistem tipe - atau didokumentasikan dengan baik. Dalam pengertian ini, objek adalah instance bersamaan dari mesin negara yang ditransisikan dengan pemanggilan metode; sedemikian rupa sehingga Anda mungkin memiliki beberapa instance dan menggunakannya dengan cara yang disisipkan secara sewenang-wenang.
Tetapi dalam mengakui bahwa keadaan bersama yang bisa berubah itu buruk, dapat dicatat bahwa orientasi objek dapat membuat masalah konkurensi karena struktur data objek adalah keadaan yang bisa berubah yang banyak objek rujukan. Sebagian besar bahasa berorientasi objek dieksekusi pada utas penelepon, yang berarti bahwa ada kondisi lomba dalam pemanggilan metode; apalagi dalam urutan fungsi panggilan non-atom. Sebagai alternatif, setiap objek bisa mendapatkan pesan async dalam antrian dan melayani mereka semua di utas objek (dengan metode pribadi), dan menanggapi pemanggil dengan mengirimkannya pesan.
Bandingkan panggilan metode Java dalam konteks multi-utas dengan Erlang memproses pengiriman pesan (yang hanya merujuk nilai yang tidak dapat diubah) satu sama lain.
Orientasi Objek Tidak Terbatas dalam kombinasi dengan paralelisme adalah masalah karena penguncian. Ada teknik mulai dari Software Transactional Memory (yaitu: transaksi ACID di dalam objek memori mirip dengan basis data) hingga menggunakan "berbagi memori dengan berkomunikasi (data abadi)" (fungsional pemrograman hybrid) pendekatan.
Menurut pendapat saya, literatur Object Orientation memfokuskan JAUH terlalu banyak pada pewarisan dan tidak cukup pada protokol (metode pemeriksaan pemesanan doa, prakondisi, postkondisi, dll.). Input yang dikonsumsi suatu objek biasanya harus memiliki tata bahasa yang jelas, dapat diekspresikan sebagai tipe.
sumber
Pemrograman prosedural / fungsional sama sekali tidak lebih lemah dari OOP , bahkan tanpa masuk ke argumen Turing (bahasa saya memiliki kekuatan Turing dan dapat melakukan apa pun yang dilakukan orang lain), yang tidak berarti banyak. Sebenarnya, teknik berorientasi objek pertama kali bereksperimen dalam bahasa yang tidak memilikinya. Dalam hal ini pemrograman OO hanya gaya pemrograman prosedural tertentu . Tapi itu membantu menegakkan disiplin ilmu tertentu, seperti modularitas, abstraksi dan penyembunyian informasi yang penting untuk pemahaman dan pemeliharaan program.
Beberapa paradigma pemrograman berevolusi dari visi teoritis komputasi. Bahasa seperti Lisp berevolusi dari lambda-calculus dan gagasan meta-sirkularitas bahasa (mirip dengan refleksivitas dalam bahasa alami). Klausa klakson yang menjadi ayah dari Prolog dan pemrograman kendala. Keluarga Algol juga berutang pada lambda-calculus, tetapi tanpa refleksivitas bawaan.
Lisp adalah contoh yang menarik, karena telah menjadi ujian bagi banyak inovasi bahasa pemrograman, yang dapat dilacak pada warisan genetik ganda.
Namun bahasa kemudian berkembang, seringkali dengan nama baru. Faktor utama evolusi adalah praktik pemrograman. Pengguna mengidentifikasi praktik pemrograman yang meningkatkan properti program seperti keterbacaan, pemeliharaan, kemampuan kebenaran. Kemudian mereka mencoba untuk menambah fitur atau kendala bahasa yang akan mendukung dan kadang-kadang menegakkan praktik-praktik ini untuk meningkatkan kualitas program.
Artinya , praktik-praktik ini sudah dimungkinkan dalam bahasa pemrograman yang lebih lama, tetapi perlu pemahaman dan disiplin untuk menggunakannya. Memasukkannya ke dalam bahasa baru sebagai konsep utama dengan sintaksis khusus membuat praktik ini lebih mudah digunakan dan mudah dipahami, terutama untuk pengguna yang kurang canggih (yaitu, sebagian besar). Ini juga membuat hidup sedikit lebih mudah bagi pengguna yang canggih.
Dalam beberapa hal, untuk mendesain bahasa apa subprogram / fungsi / prosedur untuk sebuah program. Setelah konsep yang berguna diidentifikasi, diberikan nama (mungkin) dan sintaks, sehingga dapat dengan mudah digunakan dalam semua program yang dikembangkan dengan bahasa itu. Dan ketika berhasil, itu akan dimasukkan dalam bahasa masa depan juga.
Contoh: menciptakan kembali orientasi objek
Saya sekarang mencoba mengilustrasikannya pada sebuah contoh (yang tentunya dapat dipoles lebih lanjut, diberi waktu). Tujuan dari contoh ini bukan untuk menunjukkan bahwa program berorientasi objek dapat ditulis dalam gaya pemrograman prosedural, mungkin dengan mengorbankan kelayakan dan pemeliharaan. Saya lebih suka mencoba untuk menunjukkan bahwa beberapa bahasa tanpa fasilitas OO benar-benar dapat menggunakan fungsi tingkat tinggi dan struktur data untuk benar-benar menciptakan cara untuk meniru secara efektif Orientasi Obyek , untuk mendapatkan manfaat dari kualitasnya mengenai organisasi program, termasuk modularitas, abstraksi dan penyembunyian informasi .
Seperti yang saya katakan, Lisp adalah testbed banyak evolusi bahasa, termasuk paradigma OO (meskipun apa yang bisa dianggap bahasa OO pertama adalah Simula 67, dalam keluarga Algol). Lisp sangat sederhana, dan kode untuk juru bahasa dasarnya kurang dari satu halaman. Tetapi Anda dapat melakukan pemrograman OO di Lisp. Yang Anda butuhkan adalah fungsi urutan yang lebih tinggi.
Saya tidak akan menggunakan sintaks Lisp esoterik, melainkan kode semu, untuk menyederhanakan presentasi. Dan saya akan mempertimbangkan masalah esensial sederhana: menyembunyikan informasi dan modularitas . Mendefinisikan kelas objek sekaligus mencegah pengguna mengakses (sebagian besar) implementasi.
Misalkan saya ingin membuat kelas yang disebut vektor, mewakili vektor 2 dimensi, dengan metode termasuk: penambahan vektor, ukuran vektor, dan paralelisme.
Kemudian saya dapat menetapkan vektor yang dibuat ke nama fungsi aktual yang akan digunakan.
[vektor, xcoord, ycoord, vplus, vsize, vparallel] = vectorclass ()
Mengapa begitu rumit? Karena saya dapat mendefinisikan dalam fungsi perantara konstruksi vektor yang saya tidak ingin terlihat oleh seluruh program, sehingga dapat mempertahankan modularitas.
Kita dapat membuat koleksi lain dalam koordinat kutub
Tapi saya mungkin ingin menggunakan kedua implementasi secara acuh tak acuh. Salah satu cara untuk melakukannya adalah dengan menambahkan komponen tipe ke semua nilai dan mendefinisikan semua fungsi di atas dalam lingkungan yang sama: Kemudian saya dapat mendefinisikan masing-masing fungsi yang dikembalikan sehingga pertama-tama akan menguji jenis koordinat, kemudian menerapkan fungsi spesifik untuk itu.
Apa yang telah saya peroleh: fungsi spesifik tetap tidak terlihat (karena pelingkupan pengidentifikasi lokal), dan sisanya dari program hanya dapat menggunakan yang paling abstrak yang dikembalikan oleh panggilan ke vectorclass.
Satu keberatan adalah bahwa saya dapat langsung mendefinisikan masing-masing fungsi abstrak dalam program, dan meninggalkan definisi fungsi-fungsi dependen tipe-koordinat. Maka akan disembunyikan juga. Itu benar, tetapi kemudian kode untuk setiap tipe koordinat akan dipotong kecil-kecil tersebar di program, yang kurang dapat diperbaiki dan dipelihara.
Sebenarnya, saya bahkan tidak perlu memberi mereka nama, dan saya hanya bisa menyimpan nilai fungsional sebagai anonim dalam struktur data yang diindeks oleh tipe dan string yang mewakili nama fungsi. Struktur ini menjadi lokal ke vektor fungsi tidak akan terlihat dari sisa program.
Untuk menyederhanakan penggunaan, alih-alih mengembalikan daftar fungsi, saya dapat mengembalikan fungsi tunggal yang disebut apply taking sebagai argumen yang secara eksplisit mengetikkan nilai dan string, dan menerapkan fungsi dengan tipe dan nama yang tepat. Ini sangat mirip dengan memanggil metode untuk kelas OO.
Saya akan berhenti di sini, dalam rekonstruksi fasilitas berorientasi objek ini.
Apa yang saya coba lakukan adalah untuk menunjukkan bahwa tidak terlalu sulit untuk membangun orientasi objek yang dapat digunakan dalam bahasa yang cukup kuat, termasuk warisan dan fitur-fitur lainnya. Metacircularity dari interpreter dapat membantu, tetapi sebagian besar pada tingkat sintaksis, yang masih jauh dari dapat diabaikan.
Pengguna orientasi objek pertama melakukan percobaan konsep seperti itu. Dan itu umumnya benar dari banyak perbaikan pada bahasa pemrograman. Tentu saja, analisis teoretis juga memiliki peran dan membantu memahami atau memperbaiki konsep-konsep ini.
Tetapi gagasan bahwa bahasa yang tidak memiliki fitur OO ditakdirkan untuk gagal di beberapa proyek sama sekali tidak beralasan. Jika perlu, mereka dapat meniru implementasi fitur-fitur ini dengan cukup efektif. Banyak bahasa memiliki kekuatan sintaksis dan semantik untuk melakukan orientasi objek dengan cukup efektif, bahkan ketika itu tidak built-in. Dan itu lebih dari sekadar argumen Turing.
OOP tidak membahas keterbatasan bahasa lain, tetapi mendukung atau menegakkan metodologi pemrograman yang membantu menulis program yang lebih baik, sehingga membantu pengguna yang kurang berpengalaman untuk mengikuti praktik baik yang telah digunakan dan dikembangkan oleh programmer yang lebih maju dan berkembang tanpa dukungan itu.
Saya percaya buku yang bagus untuk memahami semua ini mungkin Abelson & Sussman: struktur dan interpretasi program komputer .
sumber
Sedikit sejarah dalam urutan, saya pikir.
Era dari pertengahan 1960-an hingga pertengahan 1970-an sekarang dikenal sebagai "krisis perangkat lunak". Saya tidak bisa mengatakannya lebih baik daripada Dijkstra dalam kuliah penghargaan Turing dari tahun 1972:
Ini adalah waktu komputer 32-bit pertama, multiprosesor sejati pertama dan komputer tertanam pertama, dan jelas bagi para peneliti bahwa ini akan menjadi penting untuk pemrograman di masa depan. Itu adalah waktu dalam sejarah ketika permintaan pelanggan melampaui kemampuan programmer untuk pertama kalinya.
Tidak mengherankan, itu adalah waktu yang sangat subur dalam penelitian pemrograman. Sebelum pertengahan 1960-an, kami memang memiliki LISP dan AP / L, tetapi bahasa "utama" pada dasarnya prosedural: FORTRAN, ALGOL, COBOL, PL / I dan sebagainya. Dari pertengahan 1960-an hingga pertengahan 1970-an, kami mendapat Logo, Pascal, C, Forth, Smalltalk, Prolog, ML, dan Modula, dan itu tidak termasuk DSL seperti SQL dan pendahulunya.
Itu juga merupakan waktu dalam sejarah ketika banyak teknik kunci untuk mengimplementasikan bahasa pemrograman sedang dikembangkan. Pada periode ini kami mendapatkan penguraian LR, analisis aliran data, eliminasi subekspresi umum, dan pengakuan pertama bahwa masalah penyusun tertentu (mis. Alokasi register) adalah NP-hard, dan mencoba mengatasinya.
Ini adalah konteks di mana OOP muncul. Jadi jawaban awal tahun 1970-an untuk pertanyaan Anda tentang masalah apa yang dipecahkan OOP dalam praktiknya, jawaban pertama adalah bahwa hal itu tampaknya memecahkan banyak masalah (baik yang kontemporer maupun yang diantisipasi) yang dihadapi para programmer pada periode sejarah tersebut. Namun, ini bukan saatnya OO menjadi mainstream. Kami akan segera melakukannya.
Ketika Alan Kay menciptakan istilah "berorientasi objek", gambaran yang ada dalam benaknya adalah bahwa sistem perangkat lunak akan terstruktur seperti sistem biologis. Anda akan memiliki sesuatu seperti sel individu ("objek") yang berinteraksi satu sama lain dengan mengirimkan sesuatu yang analog dengan sinyal kimia ("pesan"). Anda tidak bisa (atau, setidaknya, tidak mau) mengintip ke dalam sel; Anda hanya akan berinteraksi dengannya melalui jalur pensinyalan. Selain itu, Anda dapat memiliki lebih dari satu dari setiap jenis sel jika perlu.
Anda dapat melihat bahwa ada beberapa tema penting di sini: konsep protokol pensinyalan yang didefinisikan dengan baik (dalam terminologi modern, antarmuka), konsep implementasi tersembunyi dari luar (dalam terminologi modern, privasi), dan konsep memiliki beberapa "benda" dengan tipe yang sama yang berkeliaran pada waktu yang sama (dalam terminologi modern, Instansiasi).
Satu hal yang mungkin Anda perhatikan adalah hilang, dan itu warisan, dan ada alasan untuk ini.
Pemrograman berorientasi objek adalah gagasan abstrak, dan gagasan abstrak dapat diimplementasikan dengan cara yang berbeda dalam bahasa pemrograman yang berbeda. Konsep abstrak dari "metode", misalnya, dapat diimplementasikan dalam C menggunakan pointer fungsi, dan di C ++ menggunakan fungsi anggota, dan dalam Smalltalk menggunakan metode (yang seharusnya tidak mengejutkan, karena Smalltalk mengimplementasikan konsep abstrak cukup langsung). Inilah yang dimaksud orang ketika mereka menunjukkan (dengan benar) bahwa Anda dapat "melakukan" OOP dalam (hampir) bahasa apa pun.
Warisan, di sisi lain, adalah fitur bahasa pemrograman yang konkret. Warisan dapat bermanfaat untuk menerapkan sistem OOP. Atau setidaknya, inilah yang terjadi sampai awal 1990-an.
Waktu dari pertengahan 1980-an hingga pertengahan 1990-an juga merupakan waktu dalam sejarah ketika segalanya berubah. Selama waktu ini, kami memiliki komputer 32-bit yang murah dan ada di mana-mana, sehingga bisnis dan banyak rumah mampu memasang komputer yang hampir sekuat mainframe terendah saat itu di setiap meja. Itu juga masa kejayaan Ini juga era kebangkitan GUI modern, dan sistem operasi jaringan.
Dalam konteks inilah Analisis dan Desain Berorientasi Objek muncul.
Pengaruh OOAD, karya "tiga Amigos" (Booch, Rumbar dan Jacobson) dan lainnya (misalnya metode Shlaer-Mellor, desain yang digerakkan oleh tanggung jawab, dll), tidak dapat dikecilkan. Ini adalah alasan mengapa sebagian besar bahasa baru yang telah dikembangkan sejak awal 1990-an (setidaknya, sebagian besar yang pernah Anda dengar) memiliki objek bergaya Simula.
Jadi jawaban tahun 1990-an untuk pertanyaan Anda adalah bahwa ia mendukung solusi (pada saat itu) terbaik untuk analisis dan metodologi desain berorientasi domain.
Sejak itu, karena kami memiliki palu, kami menerapkan OOP pada hampir semua masalah yang muncul sejak itu. OOAD dan model objek yang digunakannya mendorong dan memungkinkan pengembangan tangkas dan uji-didorong, cluster dan sistem terdistribusi lainnya, dan sebagainya.
GUI modern dan sistem operasi apa pun yang dirancang dalam 20 tahun terakhir cenderung memberikan layanannya sebagai objek, sehingga setiap bahasa pemrograman praktis baru membutuhkan, paling tidak, cara untuk mengikat sistem yang kita gunakan saat ini.
Jadi jawaban modern adalah: Ini memecahkan masalah interfacing ke dunia modern. Dunia modern dibangun di atas OOP untuk alasan yang sama bahwa dunia 1880 dibangun di atas uap: kita memahaminya, kita dapat mengendalikannya, dan ia melakukan pekerjaan dengan cukup baik.
Itu bukan untuk mengatakan bahwa penelitian berhenti di sini, tentu saja, tetapi itu sangat menunjukkan bahwa setiap teknologi baru akan membutuhkan OO sebagai kasus pembatas. Anda tidak harus menjadi OO, tetapi Anda tidak bisa secara fundamental tidak kompatibel dengannya.
sumber
Tidak ada, sungguh. OOP tidak benar-benar menyelesaikan masalah, sebenarnya; tidak ada yang dapat Anda lakukan dengan sistem berorientasi objek yang tidak dapat Anda lakukan dengan sistem berorientasi objek-memang, tidak ada yang dapat Anda lakukan dengan baik yang tidak dapat dilakukan dengan mesin Turing. Semuanya berubah menjadi kode mesin pada akhirnya, dan ASM tentu saja tidak berorientasi objek.
Apa yang dilakukan paradigma OOP untuk Anda adalah membuatnya lebih mudah untuk mengatur variabel dan fungsi, dan memungkinkan Anda untuk memindahkannya bersama-sama dengan lebih mudah.
Katakanlah saya ingin menulis permainan kartu dengan Python. Bagaimana saya mewakili kartu?
Jika saya tidak tahu tentang OOP, saya mungkin melakukannya dengan cara ini:
Saya mungkin akan menulis beberapa kode untuk menghasilkan kartu-kartu itu alih-alih hanya menuliskannya dengan tangan, tetapi Anda mengerti maksudnya. "1S" mewakili 1 Spades, "JD" mewakili Jack of Diamonds, dan sebagainya. Saya juga membutuhkan kode untuk Joker, tetapi kami hanya akan berpura-pura tidak ada Joker untuk saat ini.
Sekarang ketika saya ingin mengocok dek, saya hanya perlu "mengocok" daftarnya. Kemudian, untuk mengambil kartu dari atas geladak, saya mengeluarkan entri atas dari daftar, memberi saya string. Sederhana.
Sekarang jika saya ingin mencari tahu kartu yang saya gunakan untuk keperluan menampilkannya kepada pemain, saya memerlukan fungsi seperti ini:
Agak besar, panjang, dan tidak efisien, tetapi bekerja (dan sangat unpythonic, tapi itu intinya di sini).
Sekarang bagaimana jika saya ingin kartu dapat bergerak di sekitar layar? Saya harus menyimpan posisi mereka entah bagaimana. Saya bisa menambahkannya di akhir kode kartu mereka, tapi itu mungkin agak sulit. Sebagai gantinya, mari kita buat daftar lain di mana setiap kartu berada:
Lalu saya menulis kode saya sehingga indeks posisi masing-masing kartu dalam daftar adalah sama dengan indeks kartu itu sendiri di geladak.
Atau setidaknya itu seharusnya. Kecuali saya melakukan kesalahan. Yang saya mungkin sangat baik, karena kode saya harus agak rumit untuk menangani pengaturan ini. Ketika saya ingin mengocok kartu, saya harus mengocok posisi dalam urutan yang sama. Apa yang terjadi jika saya mengambil kartu sepenuhnya dari geladak? Saya harus mengambil posisinya juga, dan meletakkannya di tempat lain.
Dan bagaimana jika saya ingin menyimpan lebih banyak informasi tentang kartu? Bagaimana jika saya ingin menyimpan apakah setiap kartu dibalik? Bagaimana jika saya menginginkan semacam mesin fisika, dan perlu mengetahui kecepatan kartu juga? Saya akan membutuhkan daftar lain sepenuhnya untuk menyimpan grafik untuk setiap kartu! Dan untuk semua poin data ini, saya akan memerlukan kode terpisah untuk menjaga semuanya terorganisir dengan baik sehingga setiap kartu memetakan semua datanya!
Sekarang mari kita coba cara OOP ini.
Alih-alih daftar kode, mari kita mendefinisikan kelas Kartu dan membangun daftar objek Kartu dari itu.
Sekarang, tiba-tiba, semuanya jauh lebih sederhana. Jika saya ingin memindahkan kartu, saya tidak perlu mencari tahu di mana kartu itu berada di geladak, lalu menggunakannya untuk mengeluarkan posisinya dari susunan posisi. Saya hanya harus mengatakannya
thecard.pos=newpos
. Ketika saya mengeluarkan kartu dari daftar deck utama, saya tidak perlu membuat daftar baru untuk menyimpan semua data lainnya; ketika objek kartu bergerak, semua propertinya bergerak bersamanya. Dan jika saya ingin kartu yang berperilaku berbeda ketika dibalik, saya tidak perlu memodifikasi fungsi membalik dalam kode utama saya sehingga mendeteksi kartu ini dan melakukan perilaku yang berbeda; Saya hanya perlu subclass Card dan memodifikasi fungsi flip () pada subclass.Tapi tidak ada yang saya lakukan di sana tidak dapat dilakukan tanpa OO. Hanya saja, dengan bahasa berorientasi objek, bahasa tersebut melakukan banyak pekerjaan untuk menjaga hal-hal bersama untuk Anda, yang berarti Anda memiliki lebih sedikit kesempatan untuk membuat kesalahan, dan kode Anda lebih pendek dan lebih mudah untuk dibaca dan ditulis.
Atau, untuk meringkas lebih banyak lagi, OO memungkinkan Anda untuk menulis program yang tampak lebih sederhana yang melakukan pekerjaan yang sama dengan program yang lebih kompleks dengan menyembunyikan banyak kerumitan umum penanganan data di balik tabir abstraksi.
sumber
Setelah menulis embedded C selama beberapa tahun mengelola hal-hal seperti perangkat, port serial, dan paket komunikasi antara port serial, port jaringan, dan server; Saya menemukan diri saya, seorang insinyur listrik terlatih dengan pengalaman pemrograman prosedural yang terbatas, meramu abstraksi saya sendiri dari perangkat keras yang akhirnya bermanifestasi dalam apa yang kemudian saya sadari adalah apa yang oleh orang normal disebut 'Pemrograman Berorientasi Objek'.
Ketika saya pindah ke sisi server saya terkena sebuah pabrik yang mengatur representasi objek dari masing-masing perangkat dalam memori di instantiation. Saya tidak mengerti kata-kata atau apa yang terjadi pada awalnya - saya hanya tahu saya pergi ke file bernama demikian dan itu dan menulis kode. Kemudian, saya menemukan diri saya, lagi-lagi, akhirnya mengenali nilai OOP.
Saya, secara pribadi, berpikir ini adalah satu-satunya cara untuk mengajarkan orientasi objek. Saya memiliki kelas Pengantar OOP (Jawa) tahun pertama saya dan benar-benar di atas kepala saya. Deskripsi OOP dibangun di atas mengklasifikasikan kucing-> kucing-> mamalia-> benda- atau daun-> cabang-> pohon-> taman, menurut pendapat saya, metodologi yang benar-benar konyol karena tidak ada yang akan mencoba untuk menyelesaikannya masalah, jika Anda bahkan bisa menyebutnya masalah ...
Saya pikir lebih mudah untuk menjawab pertanyaan Anda jika Anda melihatnya dalam istilah yang kurang absolut - bukan 'apa yang dipecahkannya', tetapi lebih dari perspektif 'di sini ada masalah, dan inilah cara membuatnya lebih mudah'. Dalam kasus port serial khusus saya, kami memiliki sekelompok waktu kompilasi #ifdefs yang menambahkan dan menghapus kode yang secara statis membuka dan menutup port serial. Fungsi port terbuka dipanggil di semua tempat, dan dapat ditemukan di mana saja di 100k baris kode OS yang kami miliki, dan IDE tidak menghilangkan apa yang tidak didefinisikan - Anda harus melacaknya secara manual, dan membawanya di kepala Anda. Tidak dapat dihindari Anda dapat memiliki beberapa tugas mencoba membuka port serial yang diberikan mengharapkan perangkat mereka di ujung yang lain, dan kemudian tidak ada kode yang baru saja Anda tulis berfungsi, dan Anda tidak tahu mengapa.
Abstraksi itu, meskipun masih dalam C, 'port' port serial (well, hanya tipe data struktur) yang kami punya array - satu untuk setiap port serial - dan alih-alih memiliki [DMA yang setara dalam port serial] "OpenSerialPortA" "SetBaudRate" dll. Fungsi dipanggil langsung pada perangkat keras dari tugas, kami memanggil fungsi pembantu yang Anda lewati semua parameter komunikasi (baud, parity, dll.), Yang pertama kali memeriksa susunan struktur untuk melihat apakah itu port sudah dibuka - jika demikian, dengan tugas apa, yang akan memberitahu Anda sebagai printf debug, sehingga Anda dapat langsung melompat ke bagian kode yang Anda butuhkan untuk menonaktifkan - dan jika tidak, maka ia melanjutkan untuk mengatur semua parameter melalui fungsi perakitan HAL mereka, dan akhirnya membuka port.
Tentu saja, ada bahaya untuk OOP juga. Ketika saya akhirnya membersihkan basis kode itu dan membuat semuanya rapi dan bersih - menulis driver baru untuk lini produk itu akhirnya menjadi ilmu yang dapat dihitung dan dapat diprediksi, manajer saya MENGELOLA produk secara spesifik karena itu adalah proyek yang kurang ia perlukan untuk mengelola, dan dia adalah manajemen menengah batas dilepas. Yang mengambil banyak dari saya / saya merasa sangat mengecewakan sehingga saya berhenti dari pekerjaan saya. LOL.
sumber
ada banyak klaim dan niat tentang apa / di mana pemrograman OOP memiliki keunggulan dibandingkan pemrograman prosedural termasuk oleh para penemu dan penggunanya. tetapi semata-mata karena suatu teknologi dirancang untuk tujuan tertentu oleh perancangnya tidak menjamin bahwa itu akan berhasil dalam tujuan itu. ini adalah pemahaman kunci dalam bidang rekayasa perangkat lunak yang berasal dari esai terkenal Brooks "No silver bullet" yang masih relevan meskipun ada revolusi pengkodean OOP. (lihat juga Gartner Hype Cycle untuk teknologi baru.)
banyak yang telah menggunakan keduanya juga memiliki pendapat dari pengalaman anekdotal, dan ini memiliki beberapa nilai, tetapi diketahui dalam banyak penelitian ilmiah bahwa analisis yang dilaporkan sendiri dapat tidak akurat. tampaknya memang ada sedikit analisis kuantitatif dari perbedaan-perbedaan ini atau jika ada, itu tidak banyak dikutip. sungguh menakjubkan betapa banyak ilmuwan komputer berbicara secara otoritatif tentang topik-topik tertentu yang menjadi pusat bidang mereka, tetapi tidak benar-benar mengutip penelitian ilmiah untuk mendukung pandangan mereka dan tidak menyadari bahwa mereka sebenarnya menyampaikan kebijaksanaan konvensional di bidang mereka (walaupun tersebar luas ).
karena ini adalah situs / forum sains , berikut adalah upaya singkat untuk menempatkan banyak pendapat tentang pijakan yang lebih kuat dan menghitung perbedaan yang sebenarnya. mungkin ada studi lain & berharap orang lain mungkin menunjukkannya jika mereka mendengar. (pertanyaan zen: jika memang ada perbedaan besar, dan begitu banyak upaya besar-besaran di bidang rekayasa perangkat lunak komersial dan di tempat lain telah diterapkan / diinvestasikan untuk menyadarinya, mengapa bukti ilmiah mengenai hal ini begitu sulit didapat? Bukankah seharusnya ada beberapa referensi klasik yang sangat dikutip di bidang yang secara kuantitatif menghitung perbedaannya?)
makalah ini menggunakan analisis eksperimental / kuantitatif / ilmiah & secara khusus mendukung pemahaman oleh programmer pemula ditingkatkan dengan metode pengkodean OOP dalam beberapa kasus tetapi tidak meyakinkan dalam kasus lain (relatif terhadap ukuran program). perhatikan ini hanya satu dari banyak / klaim utama tentang keunggulan OOP yang diajukan dalam jawaban lain & oleh pendukung OOP. studi ini mungkin mengukur elemen psikologis yang dikenal sebagai "muatan kognitif / overhead" pemahaman pengkodean .
Perbandingan pemahaman program berorientasi objek dan prosedural oleh programmer pemula Berinteraksi dengan Komputer. Susan Wiedenbeck, Vennila Ramalingam, Suseela Sarasamma, Cynthia L Corritore (1999)
Lihat juga:
Apa manfaat pemrograman berorientasi objek daripada pemrograman prosedural?programmer.se
Apakah pemrograman prosedural memiliki kelebihan dibandingkan OOP? stackoverflow
sumber
Hati-hati. Baca klasik oleh R. King "My Cat is Object-Oriented" dalam "Konsep, Database, dan Aplikasi berorientasi objek" (Kim dan Lochovsky, eds) (ACM, 1989). "Berorientasi objek" telah menjadi kata yang lebih menarik daripada konsep tebang habis.
Selain itu, ada banyak variasi pada tema, dengan sedikit kesamaan. Ada bahasa berbasis prototipe (warisan adalah dari objek, tidak ada kelas seperti itu) dan bahasa berbasis kelas. Ada bahasa yang memungkinkan pewarisan berganda, yang lain tidak. Beberapa bahasa memiliki gagasan seperti antarmuka Java (dapat diambil sebagai bentuk pewarisan berganda yang dipermudah). Ada ide tentang mixin. Warisan dapat menjadi sangat ketat (seperti dalam C ++, tidak dapat benar-benar mengubah apa yang Anda dapatkan dalam subkelas), atau ditangani dengan sangat bebas (dalam Perl, subkelas dapat mendefinisikan ulang hampir semua hal). Beberapa bahasa memiliki root tunggal untuk warisan (biasanya disebut Object, dengan perilaku default), yang lain memungkinkan pemrogram untuk membuat banyak pohon. Beberapa bahasa bersikeras bahwa "semuanya adalah objek", yang lain menangani objek dan non-objek, beberapa (seperti Java) memiliki "sebagian besar objek, tetapi beberapa jenis di sini tidak". Beberapa bahasa bersikeras pada enkapsulasi ketat negara dalam objek, yang lain menjadikannya opsional (C ++ 'pribadi, dilindungi, publik), yang lain tidak memiliki enkapsulasi sama sekali. Jika Anda menyipitkan mata pada bahasa seperti Skema dari sudut kanan, Anda melihat OOP bawaan tanpa upaya khusus (dapat mendefinisikan fungsi yang mengembalikan fungsi yang merangkum beberapa kondisi lokal).
sumber
Agar Pemrograman Berorientasi Objek ringkas membahas masalah keamanan data yang ada dalam pemrograman prosedural. Ini dilakukan dengan menggunakan konsep enkapsulasi data, hanya memungkinkan kelas yang sah untuk mewarisi data. Pengubah akses memudahkan pencapaian tujuan ini. Semoga itu bisa membantu. :)
sumber