Saya baru-baru ini membaca posting blog Three Big Lies dan saya mengalami kesulitan membenarkan kebohongan kedua, yang dikutip di sini:
(KEBOHONGAN # 2) KODE HARUS DIRANCANG DI SELURUH MODEL DUNIA
Tidak ada nilai dalam kode menjadi semacam model atau peta dunia imajiner. Saya tidak tahu mengapa ini sangat menarik untuk beberapa programmer, tetapi ini sangat populer. Jika ada roket di dalam gim, yakinlah bahwa ada kelas "Rocket" (Asumsikan kodenya adalah C ++) yang berisi data untuk tepat satu roket dan melakukan hal-hal rockety. Tanpa memperhatikan sama sekali untuk apa tranformasi data yang benar-benar dilakukan, atau untuk tata letak data. Atau dalam hal ini, tanpa pemahaman dasar bahwa di mana ada satu hal, mungkin ada lebih dari satu.
Meskipun ada banyak hukuman performa untuk desain semacam ini, yang paling signifikan adalah bahwa ia tidak berskala. Sama sekali. Seratus roket berharga seratus kali lipat satu roket. Dan sangat mungkin harganya lebih dari itu! Bahkan untuk non-programmer, itu tidak masuk akal. Skala ekonomi. Jika Anda memiliki lebih banyak sesuatu, itu harus menjadi lebih murah, bukan lebih mahal. Dan cara untuk melakukannya adalah merancang data dengan benar dan mengelompokkan berbagai hal dengan transformasi serupa.
Inilah masalah saya dengan kebohongan ini secara khusus.
Ada nilai dalam kode menjadi model / peta dunia imajiner sebagai pemodelan dunia imajiner membantu (setidaknya saya, secara pribadi) memvisualisasikan dan mengatur kode.
Bagi saya, memiliki kelas "Rocket" adalah pilihan yang sangat valid untuk sebuah kelas. Mungkin "Roket" dapat dipecah menjadi jenis Roket seperti AGM-114 Hellfire, dll. Yang akan mengandung kekuatan payload, kecepatan maks, radius putar maks, tipe penargetan dan sebagainya, tetapi masih setiap roket yang ditembakkan harus memiliki posisi dan kecepatan.
Tentu saja memiliki 100 Rocket harganya lebih dari 1 Rocket. Jika ada 100 Rocket di layar, harus ada 100 perhitungan yang berbeda untuk memperbarui posisi mereka. Paragraf kedua kedengarannya seperti membuat klaim bahwa jika ada 100 Rocket, seharusnya biayanya kurang dari 100 perhitungan untuk memperbarui negara?
Masalah saya di sini adalah bahwa penulis menyajikan model pemrograman "cacat" tetapi tidak menyajikan cara untuk "memperbaiki" itu. Mungkin saya tersandung analogi kelas Rocket, tapi saya benar-benar ingin memahami alasan di balik kebohongan ini. Apa alternatifnya?
sumber
Jawaban:
Pertama, mari kita lihat beberapa konteks: ini adalah perancang permainan yang menulis di blog yang subjeknya mengalami penurunan kinerja terakhir dari CPU BE Cell. Dengan kata lain: ini tentang pemrograman game konsol, lebih khusus lagi, pemrograman game konsol untuk PlayStation 3.
Sekarang, programmer game adalah sekelompok orang yang penasaran, programmer game konsol lebih dari itu, dan Cell BE adalah CPU yang agak aneh. (Ada alasan Sony menggunakan desain yang lebih konvensional untuk PlayStation 4!)
Jadi, kita harus melihat pernyataan itu dalam konteks ini.
Ada juga beberapa penyederhanaan dalam posting blog itu. Secara khusus, kebohongan # 2 ini tidak disajikan dengan baik.
Saya berpendapat bahwa segala sesuatu yang abstrak dari dunia nyata adalah model dalam arti tertentu. Dan karena perangkat lunak tidak nyata, tetapi virtual, selalu merupakan abstraksi dan dengan demikian selalu menjadi model. Tapi! Seorang model tidak harus memiliki pemetaan 1: 1 yang bersih ke dunia nyata. Lagipula, itulah yang menjadikannya model.
Jadi, dalam beberapa hal, pengarangnya jelas salah: perangkat lunak adalah model. Periode. Dalam arti lain, ia benar: model itu sebenarnya tidak harus menyerupai dunia nyata sama sekali.
Saya akan memberikan contoh yang sudah saya berikan dalam beberapa jawaban lain selama bertahun-tahun, contoh Pengenalan Rekening Bank OO 101 yang terkenal. Inilah yang tampak seperti Rekening Bank di hampir setiap kelas OO:
Jadi:
balance
adalah data , dantransfer
merupakan operasi .Tapi! Inilah yang tampak seperti Rekening Bank di hampir setiap perangkat lunak perbankan:
Jadi, sekarang
transfer
adalah data danbalance
merupakan operasi (lipatan kiri atas log transaksi). (Anda juga akan melihat bahwaTransactionSlip
itu tidak berubah,balance
adalah fungsi murni, ituTransactionLog
bisa menjadi datastructure abadi "hampir" hanya menambahkan ... Saya yakin banyak dari Anda melihat bug konkuren mencolok dalam implementasi pertama, yang sekarang secara ajaib hilang .)Perhatikan bahwa keduanya adalah model. Keduanya sama-sama valid. Keduanya benar. Kedua model ini sama saja. Namun, keduanya persis dua sama lain: segala sesuatu yang merupakan data dalam satu model adalah operasi dalam model lainnya, dan segala sesuatu yang merupakan operasi dalam satu model adalah data dalam model lainnya.
Jadi, pertanyaannya bukan apakah Anda memodelkan "dunia nyata" dalam kode Anda, tetapi bagaimana Anda memodelkannya.
Ternyata, model kedua sebenarnya juga bagaimana perbankan bekerja di dunia nyata. Seperti yang saya sebutkan di atas, model kedua ini sebagian besar tidak berubah dan murni, dan kebal terhadap bug konkurensi, yang sebenarnya sangat penting jika Anda menganggap bahwa ada waktu yang tidak terlalu lama yang lalu, di mana
TransactionSlip
s sebenarnya slip kertas yang dikirim sekitar via kuda & kereta.Namun, fakta bahwa model kedua ini benar-benar cocok dengan cara kerja perbankan dunia nyata dan cara kerja perangkat lunak perbankan dunia nyata, tidak secara otomatis membuatnya menjadi lebih "benar". Karena, sebenarnya, model pertama ("salah") cukup mendekati perkiraan bagaimana pelanggan perbankan memandang bank mereka. Bagi mereka ,
transfer
adalah operasi (mereka harus mengisi formulir), danbalance
merupakan bagian dari data di bagian bawah pernyataan akun mereka.Jadi, mungkin benar bahwa dalam kode mesin game inti dari penembak PS3 berkinerja tinggi, tidak akan ada
Rocket
tipe, tapi tetap saja, akan ada beberapa pemodelan dunia yang terjadi, bahkan jika modelnya terlihat aneh untuk seseorang yang bukan ahli dalam domain pemrograman mesin fisika permainan konsol.sumber
balance
sebagai data dan transaksi sebagai lebih banyak data, dan transfer sebagai operasi, karena itulah yang dilihat pengguna, meskipun back-end dapat memperlakukannya secara berbeda.Saya tidak setuju dengan setiap "kebohongan" yang dia usulkan.
TL; DR Penulis artikel ini mencoba menjadi kontroversial untuk membuat artikel mereka lebih menarik, tetapi apa yang disebut "kebohongan" diterima oleh pengembang perangkat lunak untuk alasan yang baik.
Kebohongan 1 - Big O penting untuk tujuan penskalaan. Tidak ada yang peduli jika aplikasi kecil membutuhkan waktu lebih lama yang merupakan satu-satunya masalah konstanta waktu, mereka peduli bahwa ketika mereka menggandakan ukuran input, itu tidak menggandakan waktu eksekusi dengan faktor 10.
Kebohongan 2 - Program pemodelan setelah dunia nyata memungkinkan seorang programmer melihat kode Anda 3 tahun kemudian untuk dengan mudah memahami apa yang dilakukannya. Kode perlu dipertahankan atau Anda harus menghabiskan berjam-jam hanya mencoba memahami apa yang sedang dilakukan oleh program. Jawaban lain menyarankan agar Anda dapat memiliki lebih banyak kelas generik seperti
LaunchPad
danMassiveDeviceMover
. Ini belum tentu kelas buruk untuk dimiliki, tetapi Anda masih perluRocket
kelas. Bagaimana orang tahu apa yangMassiveDeviceMover
dilakukan atau apa yang bergerak? Apakah itu memindahkan gunung, pesawat ruang angkasa, atau planet? Ini pada dasarnya berarti bahwa menambahkan dalam kelas-kelas sepertiMassiveDeviceMover
membuat program Anda kurang efisien (tetapi mungkin jauh lebih mudah dibaca dan dimengerti).Selain itu Biaya waktu pengembang mulai melebihi biaya perangkat keras sejak lama. Ini adalah ide yang mengerikan untuk memulai mencoba mendesain dengan optimisasi di depan pikiran Anda. Anda memprogramnya dengan cara yang mudah dan dapat dimengerti dan kemudian mengubah program Anda setelah mengetahui bagian mana dari program Anda yang membutuhkan banyak waktu untuk dijalankan. Jangan lupa: 80% dari waktu pelaksanaan digunakan oleh 20% dari program.
Kebohongan 3 - Kode sangat penting. Kode yang ditulis dengan baik (dan modular) memungkinkan penggunaan kembali (menghemat banyak waktu kerja). Ini juga memungkinkan Anda untuk menyaring dan mengenali data yang buruk sehingga dapat ditangani. Data luar biasa, tetapi tanpa kode itu tidak mungkin untuk menganalisis dan mendapatkan informasi yang berguna darinya.
sumber
Dalam sistem e-commerce, Anda tidak berurusan dengan "roket" di tingkat kelas, Anda berurusan dengan "produk." Jadi itu tergantung pada apa yang Anda coba capai dan tingkat abstraksi yang Anda inginkan.
Dalam sebuah permainan, dapat dikatakan bahwa roket hanyalah salah satu dari banyak jenis "objek bergerak". Fisika yang sama berlaku untuk semua benda bergerak lainnya. Jadi paling tidak, "roket" akan mewarisi dari beberapa kelas dasar "objek bergerak" yang lebih umum.
Bagaimanapun, penulis bagian yang Anda kutip agaknya melebih-lebihkan kasusnya. Roket masih dapat memiliki karakteristik unik, seperti "jumlah bahan bakar yang tersisa" dan "dorong," dan Anda tidak perlu seratus kelas untuk mewakili ini untuk seratus roket, Anda hanya perlu satu. Pembuatan objek berbiaya sangat rendah di sebagian besar bahasa pemrograman yang layak, jadi jika Anda perlu melacak hal-hal seperti roket, gagasan bahwa Anda tidak boleh membuat objek Rocket karena mungkin terlalu mahal tidak masuk akal.
sumber
Masalah dengan dunia nyata adalah fisika yang terkutuk itu. Kami memisahkan benda-benda menjadi benda-benda fisik di dunia nyata karena mereka lebih mudah untuk bergerak daripada atom individu, atau terak cair raksasa dari sesuatu yang mungkin berpotensi menjadi roket.
Demikian juga, dunia nyata menyediakan sejumlah fitur berguna yang kita andalkan. Sangat mudah untuk membuat pengecualian Penguin - "semua burung terbang, kecuali ...". Dan sangat mudah untuk menyebut benda-benda sebagai roket, maksud saya jika saya menyebut penguin itu roket dan menyalakannya ... itu tidak berhasil.
Jadi bagaimana kita memisahkan hal-hal di dunia nyata secara konseptual bekerja di bawah kendala itu. Ketika kita melakukan hal-hal dalam kode, kita harus memisahkan hal-hal agar berfungsi dengan baik di bawah kendala - kendala itu, yang jelas berbeda.
Pikirkan tentang jaringan. Kami tidak memodelkan port dan kabel dan router dalam kode. Alih-alih, kami abstrak komunikasi jaringan menjadi koneksi dan protokol. Kami melakukan itu karena ini adalah abstraksi yang berguna terlepas dari penerapannya di dunia nyata. Dan itu menempatkan kendala berguna (misalnya: Anda tidak dapat berkomunikasi sampai koneksi dibuka) yang hanya penting dalam kode .
Jadi ya, kadang-kadang memodelkan kode setelah dunia nyata bekerja, tapi itu kebetulan . Ketika orang berbicara tentang OOP, benda itu bukan benda dunia nyata. Yang dikatakan sekolah dan tutorial adalah tragedi yang berlangsung beberapa dekade.
sumber
Rocket
tipe dalam kode orang ini, saya berani bertaruh bahwa masih ada beberapa model ...Alternatifnya adalah dengan memodelkan hal-hal yang program Anda pedulikan. Bahkan jika program Anda berurusan dengan roket, Anda mungkin tidak perlu memiliki entitas bernama a
Rocket
. Misalnya, Anda mungkin memilikiLaunchPad
entitas danLaunchSchedule
entitas danMassiveDeviceMover
entitas. Fakta bahwa semua ini membantu meluncurkan roket tidak berarti Anda menangani sendiri roket.sumber
Ini adalah masalah sebenarnya, tetapi saya akan memberikan Anda pendapat saya sebagai pengembang, mungkin itu akan membantu.
Pertama, saya tidak akan menyebutnya kebohongan, sebagai kesalahpahaman umum. Menyebutnya bohong hanyalah hype.
Satu Dia benar, dalam beberapa hal. Tidak akan menghabiskan banyak waktu untuk ini, karena itu bukan bagian dari pertanyaan. Tetapi pada dasarnya dia benar. Saya dapat menyatakan kembali ini sebagai "Apa yang berhasil di laboratorium mungkin tidak bekerja dalam kehidupan nyata". Terlalu banyak pengembang tetap dengan desain yang bekerja di "lab" tetapi gagal dalam aplikasi dunia nyata.
Tiga Kedengarannya agak sabun kotak bagi saya, tetapi pada dasarnya dia benar lagi. Tetapi ini dapat ditulis ulang untuk "menulis kode sesuai kebutuhan Anda, jangan mencoba menyesuaikan kebutuhan dengan kode Anda."
Dua Lagi, ini dia benar. Saya telah melihat pengembang menghabiskan waktu berminggu-minggu atau lebih lama mengembangkan kelas "roket" ketika kelas "kendaraan" sederhana akan bekerja, atau kelas "bergerak" yang lebih sederhana. Jika yang perlu dilakukan roket adalah bergerak dari sisi kiri layar ke kanan dan mengeluarkan suara, maka Anda dapat menggunakan kelas yang sama dengan yang Anda lakukan untuk mobil, kereta api, kapal, dan lalat. 100 harus biaya kurang dari 1 * 100 argumen tampaknya menghabiskan waktu dalam pengembangan, dan tidak terlalu banyak dalam biaya perhitungan. Meskipun berpegang pada kelas umum yang lebih sedikit yang dapat digunakan kembali adalah "lebih murah" maka banyak kelas khusus yang tidak dapat digunakan kembali. Ini mungkin dapat ditulis ulang sebagai "kelas umum lebih baik daripada kelas tertentu,
Intinya, seluruh artikel dapat ditulis ulang, dengan lebih sedikit kata kunci dan hanya akan menjadi paragraf yang paling panjang. Yang mengatakan, ini adalah posting blog yang berfokus pada area pemrograman yang sempit. Saya telah melakukan beberapa pemrograman tertanam, dan saya bisa setuju, dengan ide umum di balik pernyataan ini, meskipun ada sedikit "bulu" di sekitar mereka untuk membuatnya cocok untuk presentasi di GDC.
Satu catatan terakhir, artikel itu ditulis pada tahun 2008 (terbaik yang bisa saya katakan). Segalanya berubah dengan cepat. Pernyataan ini benar hari ini, tetapi sistem embedded jauh lebih umum hari ini kemudian saat itu, dan pola pengembangan berubah. Mungkin bahkan dalam menanggapi artikel / pembicaraan ini.
sumber
Saya merasa menarik bahwa ini terletak di sekitar masalah akademik: Platform, efisiensi penggunaan memori, dan data. Tapi itu benar-benar mengabaikan unsur manusia.
Perangkat lunak adalah tentang memenuhi kebutuhan orang. Biasanya ini dikuantifikasi dalam istilah bisnis - ada pelanggan yang menginginkan sesuatu dan pendukung yang bersedia membayar untuk mewujudkannya. Jika perangkat lunak ditulis dengan cara untuk memenuhi kebutuhan kedua sisi persamaan, maka itu adalah perangkat lunak yang baik, jika tidak, itu adalah perangkat lunak yang buruk.
Jika platform tidak penting bagi pelanggan, maka platform tidak penting. Jika efisiensi memori tidak penting bagi pelanggan, maka itu tidak penting. Jika data tidak penting bagi pelanggan, maka data tidak penting. Jika kode berfungsi, tetapi tidak dapat dibaca atau dipelihara, dan pelanggan menginginkan perubahan cepat dan dapat diandalkan dengan harga yang layak, maka kode yang ditulis dengan buruk adalah hal yang buruk. Jika kode tersebut berfungsi, tetapi tidak dapat dibaca atau dipelihara, dan pelanggan tidak peduli atau bersedia membayar untuk refactor mahal, maka kode yang ditulis dengan buruk adalah hal yang baik.
Kebohongan besarnya adalah bahwa apa pun kecuali unsur manusia itu penting. Mengapa data penting? Karena ada beberapa pelanggan atau pemangku kepentingan yang membutuhkannya. Itu adalah "kebenaran besar".
sumber
IMHO Jika kode "dirancang di sekitar model dunia" lebih mudah untuk dipahami, baik untuk desainer dan pengembang, dan untuk pengelola. Tapi saya pikir itu bukan hanya saya, dan bukan hanya perangkat lunak. Dari Wikipedia: Pemodelan ilmiah adalah kegiatan ilmiah, yang tujuannya adalah untuk membuat bagian atau fitur tertentu dari dunia lebih mudah untuk dipahami, didefinisikan, diukur, divisualisasikan, atau disimulasikan dengan merujuknya ke pengetahuan yang ada dan biasanya diterima secara umum.
sumber