Bagaimana pemisahan kode dan data menjadi praktik?

29

Silakan baca pertanyaan dengan seksama: pertanyaannya adalah bagaimana , bukan mengapa .

Saya baru-baru ini menemukan jawaban ini , yang menyarankan menggunakan database untuk menyimpan data abadi:

Kedengarannya seperti banyak angka ajaib yang Anda gambarkan - terutama jika mereka bagian yang bergantung - benar-benar data, bukan kode. [...] Ini bisa berarti database tipe SQL, atau itu bisa berarti file teks yang diformat.

Tampaknya bagi saya bahwa jika Anda memiliki data yang merupakan bagian dari apa yang program Anda lakukan, maka yang harus dilakukan adalah memasukkannya ke dalam program . Misalnya, jika fungsi program Anda adalah untuk menghitung vokal, apa yang salah dengan memilikinya vowels = "aeiou"? Bagaimanapun, sebagian besar bahasa memiliki struktur data yang dirancang untuk penggunaan ini secara tepat. Mengapa Anda repot-repot memisahkan data dengan meletakkannya di "file teks yang diformat", seperti yang disarankan di atas? Mengapa tidak membuat file teks yang diformat dalam bahasa pemrograman pilihan Anda? Sekarang apakah ini basis data? Atau kode?

Saya yakin beberapa orang akan berpikir ini adalah pertanyaan bodoh, tetapi saya menanyakannya dengan serius. Saya merasa seperti "kode dan data terpisah" muncul secara budaya sebagai semacam kebenaran yang terbukti dengan sendirinya, bersama dengan hal-hal lain yang jelas seperti "tidak memberikan variabel Anda nama yang menyesatkan" dan "jangan menghindari menggunakan spasi putih hanya karena bahasa Anda menganggap tidak signifikan ".

Ambil contoh, artikel ini: Masalah dengan Memisahkan Data dari Kode Boneka . Masalahnya ? Apa masalahnya? Jika Wayang adalah bahasa untuk menggambarkan infrastruktur saya, mengapa tidak bisa juga menjelaskan bahwa server nama adalah 8.8.8.8? Menurut saya masalahnya bukan pada kode dan data yang bercampur, 1 tetapi Wayang tidak memiliki struktur data yang cukup kaya dan cara untuk berinteraksi dengan hal-hal lain.

Saya menemukan pergeseran ini mengganggu. Pemrograman berorientasi objek mengatakan "kami ingin kaya struktur data yang sewenang-wenang", dan dengan demikian memberkahi struktur data dengan kekuatan kode. Anda mendapatkan enkapsulasi dan abstraksi sebagai hasilnya. Bahkan database SQL memiliki prosedur tersimpan. Ketika Anda mengolah data menjadi YAML atau file teks atau database bodoh seolah-olah Anda menghapus tumor dari kode, Anda kehilangan semua itu.

Adakah yang bisa menjelaskan bagaimana praktik memisahkan data dari kode ini terjadi, dan kemana arahnya? Adakah yang bisa mengutip publikasi oleh tokoh-tokoh, atau memberikan beberapa data yang relevan yang menunjukkan "kode terpisah dari data" sebagai perintah yang muncul, dan menggambarkan asalnya?

1: jika seseorang dapat membuat perbedaan seperti itu. Saya melihat Anda, programmer Lisp.

Phil Frost
sumber
5
Jangan ragu untuk mengubur semua html & css dalam bahasa pilihan Anda.
JeffO
3
Saya pikir apa yang dimaksud oleh penulis kutipan adalah bahwa angka ajaib tidak benar-benar berubah.
Pieter B
4
Tidak ada yang salah dengan mengkodekan vokal dengan susah payah. Jika aplikasi Anda hanya akan digunakan untuk menghitung vokal dalam bahasa Inggris.
Michael Paulukonis
3
Alasan teknis besar untuk memisahkan kode dan data adalah tidak harus mengkompilasi ulang kode ketika data berubah. Oleh karena itu, saya akan mempertanyakan apakah ini berlaku pada tingkat yang sama dengan bahasa scripting.
user16764
1
@MichaelPaulukonis: Dan memasukkannya ke dalam basis data adalah solusi palsu. Diperlukan perubahan untuk Belanda? Nol (bahkan bukan perubahan DB). Diperlukan perubahan untuk bahasa Prancis / Jerman? Setidaknya dukungan ISO-8859-1. (Lebih dari DB). Perubahan yang dibutuhkan untuk bahasa Yunani / Rusia? Dukungan Unicode (lebih dari DB). Sebenarnya, saya tidak bisa memikirkan bahasa apa pun di mana DB itu membantu.
MSalters

Jawaban:

22

Ada banyak alasan bagus untuk memisahkan data dari kode, dan beberapa alasan tidak. Berikut ini yang terlintas dalam pikiran.

Ketepatan waktu. Kapan nilai data diketahui? Apakah pada saat kode ditulis, ketika dikompilasi, ditautkan, dilepaskan, dilisensikan, dikonfigurasikan, mulai dieksekusi atau saat berjalan. Misalnya, jumlah hari dalam seminggu (7) diketahui lebih awal, tetapi nilai tukar USD / AUD akan diketahui cukup terlambat.

Struktur. Apakah ini waktu data tunggal yang ditetapkan menurut pertimbangan tunggal, atau mungkinkah itu merupakan warisan atau bagian dari koleksi item yang lebih besar? Bahasa seperti YAML dan JSON memungkinkan penggabungan nilai dari berbagai sumber. Mungkin beberapa hal yang awalnya tampak tidak berubah lebih baik dibuat diakses sebagai properti di manajer konfigurasi.

Lokalitas. Jika semua item data disimpan di sejumlah tempat, jauh lebih mudah untuk mengelolanya, terutama jika beberapa mungkin perlu diubah menjadi nilai baru (tidak berubah). Mengedit kode sumber hanya untuk mengubah nilai data akan menimbulkan risiko perubahan dan bug yang tidak disengaja.

Pemisahan masalah. Agar algoritme berfungsi dengan benar sebaiknya dipisahkan dari pertimbangan nilai data apa yang digunakan. Data diperlukan untuk menguji algoritma, bukan untuk menjadi bagian dari mereka. Lihat juga http://c2.com/cgi/wiki?ZeroOneInfinityRule .

Untuk menjawab pertanyaan Anda, ini bukan hal baru. Prinsip-prinsip inti tidak berubah dalam lebih dari 30 tahun, dan telah ditulis berulang kali dalam kurun waktu tersebut. Saya tidak dapat mengingat publikasi besar tentang topik ini karena umumnya tidak dianggap kontroversial, hanya sesuatu untuk dijelaskan kepada pendatang baru. Ada sedikit lebih banyak di sini: http://c2.com/cgi/wiki?SeparationOfDataAndCode .

Pengalaman pribadi saya adalah bahwa pentingnya pemisahan ini dalam perangkat lunak tertentu menjadi lebih besar dari waktu ke waktu, tidak kurang. Nilai-nilai yang hard-coded dipindahkan ke file header, nilai-nilai yang dikompilasi dipindahkan ke file konfigurasi, nilai-nilai sederhana menjadi bagian dari struktur hierarkis dan dikelola.

Mengenai tren, saya belum melihat perubahan besar dalam sikap di antara programmer profesional (10+ tahun), tetapi industri ini semakin penuh dengan anak muda dan banyak hal yang saya pikir dikenal dan memutuskan terus ditantang dan diciptakan kembali, kadang-kadang keluar dari baru wawasan tetapi kadang-kadang karena ketidaktahuan.

david.pfx
sumber
2
Bisakah Anda memperluas sejarah dan tren praktik ini? Jika semua orang memberikan pertimbangan ini, saya tidak akan mengajukan pertanyaan. Premis dari pertanyaan adalah bahwa orang tidak hati-hati mempertimbangkan ke mana data mereka harus pergi (konstanta yang dikompilasi, database eksternal, YAML ...) tetapi mereka hanya berpikir "KODE DAN DATA CAMPURAN BURUK! HULK SMASH!" Mengapa atau kapan ini menjadi sesuatu?
Phil Frost
Itu bukan bagian dari pengalaman saya, jadi saya tidak bisa memberi tahu Anda. Saya telah menambahkan beberapa paras ke jawaban saya.
david.pfx
Saya pikir "masuknya anak muda" adalah penjelasan yang valid, tetapi saya menunda menerima karena saya ingin mendengar dari beberapa anak muda ini untuk melihat dari mana mereka mendapatkan ide. Jelas mereka mendapat bagian "kode dan data terpisah", tapi saya rasa mereka tidak mendapatkan sisanya. Apakah mereka membacanya di posting blog? Buku? Dimana dan kapan?
Phil Frost
Anda akan selalu mendapatkan "_____ BURUK! HULK SMASH!" - itu tidak berarti itu benar. Seringkali hal semacam ini (misalnya "GOTO 'BURUK! HULK SMASH!") Diajarkan kepada pemula, tanpa mengajari mereka mengapa, atau apa pengecualiannya.
AMADANON Inc.
Localityjuga bekerja secara terbalik: Kami berakhir dengan semacam-jenis sistem plugin karena persyaratan khusus untuk klien yang berbeda, dan melalui beberapa tahun percobaan dan kesalahan dipelajari untuk menjaga konstanta mereka (bahkan tabel, dengan cara daftar dikt) keluar dari database dan kode. Keduanya karena menggunakannya di mana saja selain "plugin" itu tidak benar, dan karena perubahan secara otomatis diversi ketika perubahan terjadi.
Izkata
8

Skala data jauh lebih baik, dan dapat ditanyakan dan dimodifikasi dengan lebih mudah, ketika dipisahkan dari kode. Bahkan jika data Anda bersifat kodish - misalnya, data Anda mewakili aturan atau perintah - jika Anda dapat menyimpan yang mewakili kode itu sebagai data terstruktur, Anda dapat menikmati manfaat menyimpannya secara terpisah:

izin

Jika data tersebut bersandi keras, Anda harus mengedit file sumber untuk mengedit data itu. Itu berarti bahwa:

  • Hanya pengembang yang dapat mengedit data. Ini buruk - entri data bukan sesuatu yang membutuhkan keterampilan dan pengetahuan pengembang.

  • Non-pengembang dapat mengedit file sumber. Ini buruk - mereka mungkin mengacaukan file sumber tanpa menyadarinya!

  • Data dikodekan ke dalam file sumber terpisah, dan non-pengembang hanya memiliki akses ke file-file itu. Tapi ini tidak terlalu diperhitungkan - sekarang data dipisahkan dari kode dan disimpan dalam file itu sendiri ...

pengeditan

Jadi, mengenai siapa yang dapat mengedit data, yang terbaik adalah menyimpannya secara terpisah. Bagaimana dengan bagaimana mereka akan mengedit data? Jika Anda memiliki banyak data, mengetiknya dengan tangan adalah hal yang membosankan dan tidak perlu kesalahan. Memiliki beberapa UI untuk ini jauh lebih baik! Bahkan jika Anda masih harus mengetik semuanya, Anda tidak perlu mengetikkan boiler-plate format, jadi ada sedikit kemungkinan Anda akan mengacaukan format dan mengacaukan seluruh file!

Jika data tersebut berkode keras, membuat UI itu berarti alat otomatis akan mengedit file sumber tulisan tangan Anda. Biarkan itu meresap - alat otomatis akan membuka file sumber Anda, berusaha menemukan di mana data seharusnya, dan memodifikasi kode itu. Brrr ... Microsoft memperkenalkan kelas parsial ke C # hanya untuk menghindari hal-hal itu ...

Jika data terpisah, alat otomatis Anda hanya perlu mengedit file data. Saya lebih suka percaya bahwa program komputer mengedit datafile tidak jarang saat ini ...

scaling

Skala kode dan data sangat berbeda. Ketika kode Anda tumbuh, Anda ingin memisahkannya ke dalam lebih banyak kelas dan metode (atau struktur dan fungsi data), tetapi data Anda - tidak peduli berapa banyak itu tumbuh - Anda ingin tetap di satu tempat. Bahkan jika Anda harus memisahkannya ke beberapa file, Anda ingin menggabungkan file-file itu bersama-sama entah bagaimana, sehingga akan lebih mudah untuk mengakses data dari kode.

Jadi, bayangkan Anda memiliki ribuan baris data di dalam file sumber. Compiler / interpreter harus melalui semua data itu setiap kali membaca file, dan menguraikannya dengan lexer & parser yang mahal - bahkan jika Anda tidak akan mengakses data itu dalam menjalankan program ini. Juga, ketika Anda mengedit kode aktual dalam file itu, Anda harus berkeliling data, yang merepotkan seluruh proses. Juga, file data dapat diindeks. Data berkode keras? Tidak terlalu ...

mencari

Anda memiliki banyak data - wajar saja jika Anda ingin mencarinya.

  • Jika Anda menyimpannya dalam database - Anda dapat menggunakan bahasa permintaan basis data.

  • Jika Anda menyimpannya dalam file XML - Anda dapat menggunakan XPath.

  • Jika Anda menyimpannya di JSON / YAML - Anda dapat memuatnya dalam REPL bahasa scripting favorit Anda dan mencarinya.

  • Bahkan jika Anda menyimpannya dalam file teks biasa, karena memiliki struktur yang dapat dikenali oleh program Anda, Anda dapat menggunakan grep / sed / awk untuk mencarinya.

Meskipun benar bahwa Anda juga dapat grep / sed / awk melalui data kode yang sulit dalam file sumber, itu tidak berfungsi juga, karena permintaan Anda dapat cocok dengan baris lain yang tidak terkait, atau kehilangan baris yang ditulis berbeda karena sintaks representasi data bahasa pemrograman memungkinkannya.

Ada alat untuk mencari melalui kode, tetapi mereka bagus untuk menemukan deklarasi, bukan data kode keras.

Yang telah dibilang...

Sangat penting untuk membedakan antara data dan kode. Hanya karena sesuatu ditulis sebagai kode, bukan berarti itu bukan data. Dan hanya karena sesuatu ditulis dengan representasi data tidak berarti itu bukan kode.

Saya memiliki kelas ketika kami memiliki aturan yang sangat ketat tentang "angka ajaib" - kami tidak dapat memiliki angka dalam kode kami. Itu berarti kami harus melakukan hal-hal seperti:

#define THE_NUMBER_ZERO 0
//....
for(int i=THE_NUMBER_ZERO;i<cout;++i){
//....

yang benar-benar konyol! Ya, 0secara teknis "data", tetapi itu hanya sebagai bagian dari kode seperti sisa forloop! Jadi, meskipun kita dapat menyatakannya sebagai data dan memisahkannya dari kode, itu tidak berarti kita harus melakukannya . Bukan karena kami ingin meninggalkan data di dalam kode, tetapi karena sebenarnya bukan data - tidak lebih dari sisa kode, yang juga dikompilasi menjadi satu dan nol ...

Idan Arye
sumber
7

Saya pikir ada beberapa kebingungan yang terjadi. Anda menggabungkan dua hal bersama-sama: "Memisahkan kode dan data" dan "mengekspresikan perilaku program sebagai data".

Dalam kasus Anda, Anda sebenarnya khawatir tentang yang kedua dan mencampur yang pertama ke dalamnya. Saat Anda mengekspresikan perilaku program sebagai data, membuatnya lebih mudah diperluas. Dalam contoh Anda dengan vowels = "aeiou", lalu menambahkan vokal baru semudah menambahkan karakter. Jika Anda memiliki data ini secara eksternal, Anda dapat mengubah perilaku ini tanpa harus mengkompilasi ulang program.

Dan ketika Anda memikirkannya, OOP adalah perpanjangan dari pemikiran ini. Mengikat data dan perilaku bersama-sama akan memungkinkan Anda untuk mengubah perilaku program berdasarkan data program.

Euforia
sumber
2
Karena secara alami, daftar vokal akan berubah.
cHao
13
@ cHao Begitu saya masuk, ya .
Pasang kembali Monica
2
i18n dapat mematahkan kepala Anda - lihat beberapa contoh buruk di Jawa di javaspecialists.eu/archive/Issue209.html
Rory Hunter
2
@ Angew: Segera setelah saya masuk, Anda sudah gagal . Anda memerlukan kode untuk ini; solusi naif tidak mampu menangani setiap kasus bahkan dalam bahasa Inggris. (Lupakan ïsebentar; mari kita bicarakan ydan w!) Memindahkan daftar ke database tidak akan memperbaikinya, dan sebenarnya berbahaya - kerumitannya tidak ada artinya jika dilakukan salah, tetapi Anda tidak akan bahkan tahu apa yang "salah" adalah kecuali Anda sedang merancang untuk i18n dari bawah ke atas. Pada titik mana Anda sudah menyadari bahwa daftar vokal tidak akan memotongnya.
cHao
1
@ BenLee: Sebenarnya saya tidak akan sedikit terkejut. Saat ini saya sedang berusaha mengubah beberapa kode seperti itu saat kita bicara. Tetapi outsourcing semua ke database adalah meramal dari segala macam lainnya. Jika Anda belum tahu apakah sesuatu perlu diubah - dan yang lebih penting, jika Anda belum tahu bagaimana itu perlu dimodifikasi - maka IMO lebih baik menunggu sampai Anda memerlukan fleksibilitas sebelum menambahkannya .
cHao
5

Misalnya, jika fungsi program Anda adalah untuk menghitung vokal, apa yang salah dengan memiliki vokal = "aeiou" di dalamnya?

Menyimpan konfigurasi secara eksternal memungkinkan Anda memiliki satu versi kode yang diharapkan dapat berfungsi dengan banyak konfigurasi, alternatifnya adalah mempertahankan banyak versi perangkat lunak yang hanya berbeda oleh konfigurasi.

Anda menyebutkan vokal = "aeiou", bagaimana jika saya kadang ingin "y", haruskah saya membangun kembali seluruh program? Bisakah saya memutakhirkan versi dengan mudah sekarang setelah saya memodifikasi kodenya? Jika ada kesalahan, apakah saya yang menyebabkannya, atau apakah programnya rusak?

Jika ini ada di dalam program Anda, itu menyiratkan bahwa program Anda tidak mengharapkan pengguna untuk mengubah definisi vokal tanpa memindai kode untuk melihat kemungkinan efek samping. Jika definisi disimpan secara eksternal, itu berarti bahwa program tidak boleh rusak untuk nilai wajar yang ditetapkan dalam konfigurasi.

Ketika Anda mengolah data menjadi YAML atau file teks atau database bodoh seolah-olah Anda menghapus tumor dari kode

Beberapa melihatnya sebagai kebalikan, yaitu, Anda menghapus tumor kode dari data berharga Anda, lihat: kutipan Torvalds tentang programmer yang baik

FMJaguar
sumber
4
Kutipan Torvalds mengacu pada struktur data, bukan data.
user949300
OP menyatakan: "Pemrograman berorientasi objek mengatakan" kami ingin struktur data kaya secara sewenang-wenang ", dan dengan demikian memberkahi struktur data dengan kekuatan kode."
FMJaguar
1
Jika Anda membuat perubahan mendasar pada definisi apa vokal itu, Anda harus mengulangi semua tes otomatis. Sistem jarang jika pernah memiliki kemampuan untuk menjalankan kembali pengujian ketika file konfigurasi berubah pada sistem yang digunakan. Jadi definisi seperti itu perlu dibangun ke dalam sistem; mungkin sebagai dua set kode keras dengan opsi konfigurasi untuk memilih di antara mereka.
soru
+1 untuk kutipan Torvalds. Saya setuju dengan sentimen ini: dalam contoh wayang, saya pikir masalahnya adalah wayang tidak memiliki struktur data yang baik untuk mewakili informasi yang orang ingin masukkan ke dalamnya. Daripada memperbaiki struktur data, pengembang boneka menegaskan bahwa "data dalam kode" adalah masalahnya (mengapa? Itulah pertanyaannya!) Dan mengembangkan hiera , yang saya lihat lebih dari memindahkan masalah di tempat lain, dan juga membuatnya tidak mungkin. untuk mengaitkan perilaku dengan data.
Phil Frost
2

Saya berada di satu proyek di mana pemimpin bersikeras untuk menempatkan data referensi ke dalam tabel kecil, dan saya pikir itu konyol. Tetapi karena kami sudah memiliki infrastruktur kegigihan kami dan konektivitas, itu akhirnya menjadi biaya yang cukup rendah di atas operasi kegigihan lainnya yang kami lakukan.

Sekarang, saya masih berpikir itu adalah keputusan yang konyol, dan jika kita tidak memiliki infrastruktur, saya tidak akan melakukannya.

Tetapi beberapa argumen yang mendukung yang saya lihat adalah:

  • Jika Anda memiliki pola pikir basis data, maka memasukkan data referensi ke dalam basis data SQL memungkinkan Anda bergabung di dalamnya untuk pelaporan.
  • Jika Anda memiliki utilitas admin, atau akses ke database, maka Anda dapat mengubah nilai saat runtime. (Meskipun itu bisa bermain dengan api.)

Juga, terkadang kebijakan menghalangi praktik pengkodean. Sebagai contoh, saya telah bekerja di beberapa toko di mana mendorong file .xml adalah A-OK, sementara menyentuh garis dalam kode memerlukan siklus regresi penuh, dan mungkin tes beban. Jadi ada satu tim di mana file .xml saya untuk proyek sangat kaya (dan mungkin -heh- mungkin berisi beberapa kode).

Saya selalu bertanya pada diri sendiri apakah saya akan menikmati manfaat dari mendorong data keluar dari kode ke dalam penyimpanan data eksternal, bahkan jika itu hanya file teks, tetapi saya telah bekerja dengan orang-orang yang melihatnya dengan cara itu sebagai yang pertama. impuls.

rampok
sumber
3
Komentar bagus tentang prosedur toko, di mana pengeditan XML "ok" tapi mengedit hal yang sama dalam kode adalah masalah besar.
user949300
bekerja di satu toko di mana semuanya berada dalam database yang bisa, hingga ke layar teks. Terlepas dari kode antarmuka pengguna, satu-satunya hal yang tidak ada dalam database adalah lokasi basis data dan kredensial ...
jwenting
3
itu selalu terdengar konyol sampai, suatu hari, seseorang bertanya "bisakah kita mengkonfigurasi ulang ini untuk pengguna X yang menuntutnya", dan setelah itu tampaknya tidak begitu konyol. Pelanggan sial :)
gbjbaanb
2
... dan jika hari itu "tidak pernah", maka itu waktu yang lama terasa konyol
Rob
2

Izinkan saya mengajukan pertanyaan tandingan yang sangat serius: Apa, menurut Anda, perbedaan antara "data" dan "kode"?

Ketika saya mendengar kata "data", saya pikir "keadaan". Data, menurut definisi, adalah hal yang dirancang untuk dikelola oleh aplikasi itu sendiri, dan oleh karena itu, hal yang tidak pernah diketahui aplikasi pada saat kompilasi. Data hard-code tidak mungkin , karena segera setelah Anda membuat-kode data, itu menjadi perilaku - bukan data.

Jenis data bervariasi berdasarkan aplikasi; sistem faktur komersial dapat menyimpan pelanggan dan memesan informasi dalam database SQL, dan program vektor-grafik mungkin menyimpan data geometri dan metadata dalam file biner. Dalam kedua kasus ini dan semua yang ada di antaranya, ada pemisahan yang jelas dan tidak dapat dipecahkan antara kode dan data. Data itu milik pengguna , bukan programmer, jadi tidak akan pernah bisa dikodekan dengan keras.

Apa yang Anda bicarakan adalah, untuk menggunakan deskripsi yang paling akurat secara teknis tersedia untuk kosa kata saya saat ini: informasi yang mengatur perilaku program yang tidak ditulis dalam bahasa pemrograman utama yang digunakan untuk mengembangkan sebagian besar aplikasi.

Bahkan definisi ini, yang jauh lebih sedikit ambigu daripada hanya kata "data", memiliki beberapa masalah. Misalnya, bagaimana jika sebagian besar program masing-masing ditulis dalam bahasa yang berbeda? Saya secara pribadi telah mengerjakan beberapa proyek yaitu sekitar 50% C # dan 50% JavaScript. Apakah kode JavaScript "data"? Kebanyakan orang akan mengatakan tidak. Bagaimana dengan HTML, apakah itu "data"? Kebanyakan orang masih mengatakan tidak.

Bagaimana dengan CSS? Apakah itu data atau kode? Jika kita menganggap kode sebagai sesuatu yang mengontrol perilaku program, maka CSS tidak benar-benar kode, karena hanya (well, sebagian besar) yang mempengaruhi penampilan, bukan perilaku. Tapi itu juga bukan data; pengguna tidak memilikinya, aplikasi bahkan tidak benar-benar memilikinya. Ini setara dengan kode untuk perancang UI. Ini seperti kode , tetapi tidak cukup kode.

Saya mungkin menyebut CSS semacam konfigurasi, tetapi definisi yang lebih praktis adalah bahwa itu hanya kode dalam bahasa domain-spesifik . Itulah yang sering diwakili oleh XML, YAML, dan "file berformat" lainnya. Dan alasan kami menggunakan bahasa khusus-domain adalah bahwa, secara umum, secara bersamaan lebih ringkas dan lebih ekspresif dalam domain khusus daripada mengkodekan informasi yang sama dalam bahasa pemrograman tujuan umum seperti C atau C # atau Java.

Apakah Anda mengenali format berikut?

{
    name: 'Jane Doe',
    age: 27,
    interests: ['cats', 'shoes']
}

Saya yakin kebanyakan orang melakukannya; itu JSON . Dan inilah hal yang menarik tentang JSON: Dalam JavaScript, ini jelas kode, dan dalam setiap bahasa lainnya, itu jelas diformat data. Hampir setiap bahasa pemrograman utama tunggal memiliki setidaknya satu perpustakaan untuk "parsing" JSON.

Jika kita menggunakan sintaks yang sama persis di dalam suatu fungsi dalam file JavaScript, itu tidak mungkin berupa apa pun selain kode. Namun, jika kita mengambil JSON itu, mendorongnya dalam .jsonfile, dan menguraikannya dalam aplikasi Java, tiba-tiba itu "data". Apakah itu masuk akal?

Saya berpendapat bahwa "data-ness" atau "konfigurasi-ness" atau "kode-ness" melekat pada apa yang sedang dijelaskan, bukan bagaimana itu dijelaskan.

Jika program Anda memerlukan kamus 1 juta kata untuk, katakanlah, menghasilkan frasa sandi acak, Anda ingin kode seperti ini:

var words = new List<string>();
words.Add("aa");
words.Add("aah");
words.Add("ahhed");
// snip 172836 more lines
words.Add("zyzzyva");
words.Add("zyzzyvas");

Atau apakah Anda hanya mendorong semua kata itu ke dalam file teks yang dibatasi baris dan memberi tahu program Anda untuk membacanya? Tidak masalah jika daftar kata tidak pernah berubah, ini bukan pertanyaan apakah Anda pengodean keras atau pengodean lunak (yang banyak dianggap sebagai anti-pola ketika diterapkan secara tidak tepat), itu hanya pertanyaan tentang format apa yang paling efisien dan membuatnya paling mudah untuk menggambarkan "barang", apa pun "barang" itu. Cukup tidak relevan apakah Anda menyebutnya kode atau data; ini adalah informasi yang diperlukan oleh program Anda untuk dapat dijalankan, dan format file-datar adalah cara yang paling nyaman untuk mengelola dan memeliharanya.

Dengan asumsi Anda mengikuti praktik yang benar, semua hal ini akan menjadi kontrol sumber, jadi Anda bisa menyebutnya kode, kode saja dalam format yang berbeda dan mungkin sangat minimalis. Atau Anda dapat menyebutnya konfigurasi, tetapi satu-satunya hal yang benar-benar membedakan kode dari konfigurasi adalah apakah Anda mendokumentasikannya dan memberi tahu pengguna akhir cara mengubahnya. Anda mungkin dapat menciptakan beberapa argumen palsu tentang konfigurasi yang ditafsirkan pada waktu startup atau runtime dan bukan pada waktu kompilasi, tetapi kemudian Anda akan mulai menggambarkan beberapa bahasa yang diketik secara dinamis dan hampir pasti apa saja dengan mesin skrip yang tertanam di dalamnya (misalnya kebanyakan game). Kode dan konfigurasi adalah apa pun yang Anda putuskan untuk diberi label, tidak lebih, tidak kurang.

Sekarang, ada adalah bahaya bagi eksternalisasi informasi yang tidak benar-benar aman untuk memodifikasi (lihat "coding lunak" link di atas). Jika Anda mengeksternalkan array vokal Anda dalam file konfigurasi, dan mendokumentasikannya sebagai file konfigurasi untuk pengguna akhir Anda, Anda memberi mereka cara yang hampir sangat mudah untuk langsung menghancurkan aplikasi Anda, misalnya dengan meletakkan "q" sebagai vokal. Tapi itu bukan masalah mendasar dengan "pemisahan kode dan data", itu hanya pengertian desain yang buruk.

Apa yang saya katakan kepada para junior devs adalah bahwa mereka harus selalu mengeksternalisasi pengaturan yang mereka harapkan berubah per lingkungan. Itu termasuk hal-hal seperti string koneksi, nama pengguna, kunci API, jalur direktori, dan sebagainya. Mereka mungkin sama di kotak dev Anda dan dalam produksi, tetapi mungkin tidak, dan sysadmin akan memutuskan bagaimana mereka ingin terlihat dalam produksi, bukan devs. Jadi Anda memerlukan cara agar satu kelompok pengaturan diterapkan pada beberapa mesin, dan pengaturan lain diterapkan pada mesin lain - ergo, file konfigurasi eksternal (atau pengaturan dalam database, dll.)

Tetapi saya menekankan bahwa hanya dengan meletakkan beberapa "data" ke dalam "file" tidak sama dengan mengeksternalkannya sebagai konfigurasi. Menempatkan kamus kata ke dalam file teks tidak berarti Anda ingin pengguna (atau TI) mengubahnya, itu hanya cara untuk memudahkan pengembang untuk memahami apa yang sedang terjadi dan, jika perlu, membuat perubahan sesekali. Demikian juga, memasukkan informasi yang sama dalam tabel database tidak selalu dianggap sebagai eksternalisasi perilaku, jika tabel tersebut hanya baca dan / atau DBA diperintahkan untuk tidak mengacaukannya. Konfigurasi menyiratkan bahwa data dapat berubah, tetapi pada kenyataannya yang ditentukan oleh proses dan tanggung jawab daripada pilihan format.

Jadi, untuk meringkas:

  • "Kode" bukan istilah yang didefinisikan secara kaku. Jika Anda memperluas definisi untuk memasukkan bahasa khusus domain dan hal lain yang memengaruhi perilaku, banyak gesekan nyata ini akan hilang begitu saja dan semuanya masuk akal. Anda dapat memiliki "kode" DSL yang tidak dikompilasi dalam file datar.

  • "Data" menyiratkan informasi yang dimiliki oleh pengguna atau setidaknya seseorang selain pengembang, dan umumnya tidak tersedia pada waktu desain. Itu tidak dapat dikodekan dengan keras bahkan jika Anda ingin melakukannya. Dengan kemungkinan pengecualian dari kode modifikasi diri , pemisahan antara kode dan data adalah masalah definisi, bukan preferensi pribadi.

  • "Soft-coding" bisa menjadi praktik yang mengerikan ketika diterapkan berlebihan, tetapi tidak setiap instance eksternalisasi harus merupakan soft-coding, dan banyak contoh menyimpan informasi dalam "flat file" tidak selalu merupakan upaya yang bonafid untuk eksternalisasi.

  • Konfigurasi adalah tipe khusus dari soft-coding yang adalah diperlukan karena pengetahuan bahwa aplikasi mungkin perlu untuk menjalankan dalam lingkungan yang berbeda. Menyebarkan file konfigurasi terpisah bersama dengan aplikasi jauh lebih sedikit bekerja (dan jauh lebih berbahaya) daripada menggunakan versi kode yang berbeda untuk setiap lingkungan. Jadi beberapa jenis soft-coding sebenarnya bermanfaat.

Aaronaught
sumber
1

Saya sarankan membaca artikel klasik ini oleh Oren Eini (alias Ayende Rahien)

http://ayende.com/blog/3545/enabling-change-by-hard-coding-everything-the-smart-way

Hal yang dapat saya ambil darinya adalah fokus pada kesederhanaan dan keterbacaan. Ini dapat berarti bahwa hal-hal yang tidak mungkin dikonfigurasi ulang sebaiknya dibiarkan dengan kode keras (mudah dibaca). Ini memungkinkan Anda untuk menggunakan sintaks penuh bahasa pemrograman untuk mengekspresikan parameter, serta mendapatkan efek samping yang bermanfaat seperti penyelesaian kode dan kesalahan kompiler pada penyalahgunaan.

Dengan cara ini Anda berpotensi menghindari kompleksitas parsing / interpreting ("tetapi orang lain mem-parsing YAML / JSON saya" - memetakan teks yang diurai ke panggilan API tertentu dapat menjadi bentuk interpretasi), dan menghindari kompleksitas langkah lain antara data " "dan penggunaannya.

Beberapa kasus memang cenderung diekspresikan dalam data bahkan dalam skenario seperti ini: misalnya, menentukan ribuan titik dalam ruang 3D mungkin lebih cocok untuk file teks daripada kode, meskipun dalam beberapa bahasa, termasuk C menggunakan inisialisasi struct, kode dapat sesuai bahkan untuk itu.

orip
sumber
1

Ok, anggap Anda ingin menulis semacam program c ++ untuk waktu luang Anda. Anda tahu persis apa yang harus dilakukan dan apa yang tidak perlu dilakukan. Sekarang ambil buku apa pun tentang "desain perangkat lunak modern". Inilah aturan mainnya: Untuk setiap kelas dalam proyek Anda dan setiap kasus kecil yang harus Anda laksanakan masing-masing dan setiap pola mewah yang Anda temukan dijelaskan dalam buku itu untuk membuat kode Anda "desain bersih". Yah, "injeksi ketergantungan" akan cukup untuk banyak ppl, saya kira. (Ini c ++, bukan java!) Pemrograman diajarkan dari sudut pandang yang semakin teoritis. Itu tidak cukup Anda menyelesaikan pekerjaan, Anda harus menulis kode yang dapat dikelola, bodoh membuktikan ... baik-baik saja dan benar. Masalahnya dimulai ketika hal. berhenti memikirkan alasan sebenarnya, pola desain diciptakan dan menjadi dogmatis.

Biarkan saya menghentikan Anda menulis alat penghitung surat Anda dengan (lebih) menggunakan prinsip desain tunggal sederhana: Ketika Anda menulis kode yang melakukan pekerjaan tertentu pada input data dari jenis tertentu, pastikan itu mampu melakukan tugas itu untuk setiap input yang diberikan data jenis itu. - Ketika Anda ingin menulis alat penghitung huruf, jelas masuk akal untuk menulisnya dengan cara sehingga tidak hanya dapat menghitung vokal, tetapi "huruf apa saja". - Karena Anda mungkin tidak tahu apa sebenarnya korpus yang Anda parsing, Anda juga dapat memilih pengkodean yang sangat umum (UTF-16) dan mencakup sebagian besar (semua?) Bahasa tertulis dan simbol-simbolnya.

Hingga saat itu, kami memiliki fungsi dengan dua argumen (corpus dan huruf yang akan dihitung). Kami hanya khawatir untuk menemukan "tipe" atau "kelas" yang cukup umum milik surat-surat itu juga: kami tentu dapat melakukan lebih baik daripada simbol ASCII!

Masukkan setan menggunakan "generalisasi dan usabilitas ulang" -dogma: - Mengapa tidak menghitung simbol apa pun dari kelas mana pun dalam aliran input dari kelas itu? (abstrak dari huruf ke bit urutan yang sewenang-wenang tetapi terbatas karena itu adalah yang paling umum yang bisa Anda dapatkan dengan komputer ...) - Tunggu, bahkan saat itu kami masih menghitung dalam bilangan alami. Namun menghitung dapat digeneralisasikan sebagai pemetaan dari set yang dapat dihitung untuk dirinya sendiri memenuhi aksioma ... [Anda mendapatkan ide]

Sekarang contoh itu mungkin konyol, tetapi jika Anda mempertimbangkan tugas-tugas desain yang lebih kompleks daripada alat hitung, Anda mungkin akan menemukan semua kesempatan untuk memperkenalkan abstraksi tambahan yang diperlukan sesuai dengan semacam pola desain yang Anda temukan di buku Anda.

Pemisahan "data" dan "kode" mungkin akan bersifat sepele (argumen fungsi) atau Anda akan menemukan diri Anda memperlakukan invarian sebagai variabel ("data").

Jika ada kebingungan, kemungkinan tentang "antarmuka" dan "layanan" dan semua kelas spesifik (misalnya tipe) tiba-tiba "data", yaitu dependensi yang akan disuntikkan dari luar. Saya merasa bahwa kursus informatika yang diajarkan di universitas telah menjadi seperti kuliah filsafat dan ada sedikit waktu untuk proyek nyata sehingga siswa dapat memperoleh pengalaman bagaimana membuat perangkat lunak yang berfungsi. Jika Anda pernah bertanya-tanya mengapa Anda diharuskan untuk menggunakan pola yang sangat rumit alih-alih solusi yang jelas, pengembangan ini (kemungkinan) bagaimana persyaratan itu "dibuat" ...

Untuk masalah spesifik Anda: Jika Anda dapat 1.) menulis sebuah program dengan maksimum hard-coding untuk kasus spesifik Anda dan kemudian 2.) menggeneralisasi dari kode itu dengan cara yang lurus ke depan dengan eg memperkenalkan lebih banyak argumen fungsi dan menggunakan "pola sepele" lainnya Anda dapat yakin Anda memisahkan kode dan data, cara yang jelas, seperti yang telah dilakukan sejak pemrograman fungsional telah ditemukan. (Ofc Anda lewati 1. dan lakukan 2. langsung ...)

Apa pun yang tidak jelas di sini kemungkinan adalah "kebuntuan teori": Seperti menulis antarmuka yang merujuk ke antarmuka dan antarmuka lain ... dan pada akhirnya Anda memiliki file xml kecil yang rapi untuk mengkonfigurasi semua antarmuka ini dan dependensi yang akan disuntikkan ke dalam kekacauan-antarmuka kelas Anda

Mari kita berharap saja, parser xml yang Anda perlukan tidak memerlukan xml-config untuk dapat berfungsi ...

bhak
sumber