Saat mentransfer objek melalui API, seperti dalam format JSON schemaless, apa cara ideal untuk mengembalikan properti string yang tidak ada? Saya tahu bahwa ada berbagai cara untuk melakukan ini seperti dalam contoh di tautan yang tercantum di bawah ini.
Saya yakin saya telah menggunakan null di masa lalu tetapi tidak memiliki alasan yang baik untuk melakukan itu. Tampaknya lurus ke depan untuk menggunakan null ketika berhadapan dengan database. Tetapi basis data tampak seperti detail implementasi yang tidak seharusnya menjadi perhatian pihak di sisi lain API. Misalnya mereka mungkin menggunakan datastore schemaless yang hanya menyimpan properti dengan nilai (non-null).
Dari sudut pandang kode, membatasi fungsi string hanya berfungsi dengan satu jenis, yaitu string
(bukan nol), membuatnya lebih mudah untuk dibuktikan; menghindari nol juga merupakan alasan untuk memiliki Option
objek. Jadi, jika kode yang menghasilkan permintaan / respons tidak menggunakan null, tebakan saya adalah kode di sisi lain API tidak akan dipaksa untuk menggunakan null juga.
Saya lebih suka ide menggunakan string kosong sebagai cara mudah untuk menghindari menggunakan null. Satu argumen yang saya dengar untuk menggunakan null dan terhadap string kosong adalah bahwa string kosong berarti properti itu ada. Meskipun saya memahami perbedaannya, saya juga bertanya-tanya apakah itu hanya detail implementasi dan apakah menggunakan string kosong atau kosong akan membuat perbedaan nyata. Saya juga bertanya-tanya apakah string kosong analog dengan array kosong.
Jadi, mana cara terbaik untuk melakukannya yang mengatasi masalah itu? Apakah itu tergantung pada format objek yang ditransfer (skema / skema)?
sumber
if( value === null) { use parent value; }
Namun, jika Anda menetapkan nilai anak, bahkan ke string kosong (mis. Menimpa nilai induk default dengan kosong), lalu bagaimana Anda "mewarisi kembali" nilainya? Bagi saya, menetapkannya sebagai null berarti "setel nilai ini sehingga kami tahu untuk menggunakan nilai induk."null
(memang benar yangnull
dihindari seperti itu), si penanya berarti "Kembalikan bukan-nol" [Objek] (yaitu: String kosong, Array kosong, dll.) Ketika mereka tulis "hindari".Jawaban:
TLDR; Hapus properti nol
Hal pertama yang perlu diingat adalah bahwa aplikasi di tepi mereka tidak berorientasi objek (atau fungsional jika pemrograman dalam paradigma itu). JSON yang Anda terima bukan objek dan tidak boleh diperlakukan seperti itu. Itu hanya data terstruktur yang dapat (atau mungkin tidak) dikonversi menjadi objek. Secara umum, JSON yang masuk tidak boleh dipercaya sebagai objek bisnis hingga validasi. Hanya fakta bahwa itu deserialized tidak membuatnya valid. Karena JSON juga memiliki primitif terbatas dibandingkan dengan bahasa back-end, sering layak untuk membuat DTO yang selaras JSON untuk data yang masuk. Kemudian gunakan DTO untuk membangun objek bisnis (atau kesalahan mencoba) untuk menjalankan operasi API.
Ketika Anda melihat JSON hanya sebagai format transmisi, lebih masuk akal untuk menghilangkan properti yang tidak disetel. Lebih sedikit mengirim melalui kawat. Jika bahasa back-end Anda tidak menggunakan nulls secara default, Anda mungkin dapat mengkonfigurasi deserializer Anda untuk memberikan kesalahan. Sebagai contoh, pengaturan umum saya untuk Newtonsoft.Json menerjemahkan properti null / missing hanya ke / dari
option
tipe F # dan jika tidak akan terjadi kesalahan. Ini memberikan representasi alami bidang mana yang opsional (yangoption
bertipe).Seperti biasa, generalisasi hanya membuat Anda sejauh ini. Mungkin ada kasus di mana properti default atau null lebih cocok. Tetapi kuncinya adalah tidak melihat struktur data di tepi sistem Anda sebagai objek bisnis. Objek bisnis harus membawa jaminan bisnis (mis. Nama setidaknya 3 karakter) ketika berhasil dibuat. Tetapi struktur data yang ditarik dari kawat tidak memiliki jaminan nyata.
sumber
Pembaruan: Saya telah mengedit jawabannya sedikit, karena mungkin menyebabkan kebingungan.
Pergi dengan string kosong adalah tidak pasti. String kosong masih merupakan nilai, itu hanya kosong. Tidak ada nilai yang harus ditunjukkan menggunakan konstruk yang tidak mewakili apa pun
null
,.Dari sudut pandang pengembang API, hanya ada dua jenis properti:
null
.Ini membuatnya cukup jelas bahwa ketika sebuah properti wajib, yaitu. diperlukan, tidak pernah bisa
null
.Di sisi lain, jika properti opsional dari suatu objek tidak disetel dan dibiarkan kosong, saya lebih suka menyimpannya dalam respon dengan
null
nilai. Dari pengalaman saya, ini memudahkan klien API untuk mengimplementasikan parsing, karena mereka tidak diharuskan memeriksa apakah suatu properti benar-benar ada atau tidak, karena selalu ada di sana, dan mereka dapat dengan mudah mengonversi respons ke DTO khusus mereka, memperlakukannull
nilai-nilai sebagai opsional.Termasuk / menghapus bidang secara dinamis dari kekuatan respons termasuk kondisi tambahan pada klien.
Apa pun caranya, apa pun yang Anda pilih, pastikan Anda tetap konsisten dan terdokumentasi dengan baik. Dengan begitu tidak masalah apa yang Anda gunakan untuk API Anda, selama perilakunya dapat diprediksi.
sumber
null
untuk referensi. Memadukan nilai dengan referensi adalah salah satu perhatian saya. Bagaimana Anda membedakan bidang opsional dengannull
bidang string non-opsional yang memilikinull
nilai? Sedang parsing, bukankah menguji keberadaan properti membuat parser lebih rapuh?null
untuk menunjukkan nilai opsional. Jadi, ketika Anda mendefinisikan objek yang memiliki properti string non-opsional, dan konsumen tidak memiliki properti ini, itu harus mengirim string kosong untuk properti itu. Apakah itu benar?null
Penggunaan tergantung pada Aplikasi / BahasaPada akhirnya pilihan untuk digunakan atau tidaknya
null
nilai aplikasi yang valid sebagian besar ditentukan oleh aplikasi Anda dan bahasa pemrograman / antarmuka / tepi.Pada level fundamental, saya sarankan mencoba menggunakan tipe yang berbeda jika ada kelas nilai yang berbeda.
null
mungkin menjadi opsi jika antarmuka Anda mengizinkannya dan hanya ada dua kelas properti yang Anda coba wakili. Menghilangkan properti mungkin menjadi opsi jika antarmuka atau format Anda memungkinkannya. Tipe agregat baru (kelas, objek, tipe pesan) dapat menjadi pilihan lain.Sebagai contoh string Anda, jika ini dalam bahasa pemrograman, saya akan bertanya pada diri sendiri beberapa pertanyaan.
Option
mungkin akan lebih baik untuk desain antarmuka Anda.Option
mungkin mengisi kasus ini dengan baik jika string Anda tidak dapat dibatalkan. Namun, Anda mungkin harus memeriksa input pengguna untuknull
nilai string, jadi saya mungkin akan menunda kembali ke pertanyaan pertama: berapa banyak tipe nilai yang ingin / ingin saya wakili.null
indikasi kesalahan programmer dalam bahasa pemrograman saya? Sayangnya,null
sering kali nilai default untuk petunjuk atau referensi yang tidak diinisialisasi (atau tidak diinisialisasi secara eksplisit) dalam beberapa bahasa. Apakahnull
sebagai nilai dapat diterima sebagai nilai default? Apakah aman sebagai nilai default? Kadangnull
- kadang merupakan indikasi nilai yang tidak dialokasikan. Haruskah saya memberi konsumen antarmuka saya indikasi tentang potensi manajemen memori ini atau masalah inisialisasi dalam program mereka? Apa modus kegagalan dari panggilan seperti itu dalam menghadapi masalah seperti itu? Apakah penelepon dalam proses yang sama atau utas dengan saya sehingga kesalahan seperti itu berisiko tinggi untuk aplikasi saya?Bergantung pada jawaban Anda atas pertanyaan-pertanyaan ini, Anda mungkin dapat mengasah apakah
null
antarmuka Anda cocok atau tidak .Contoh 1
null
kemungkinan nilai string dikembalikan setelah kegagalan mengalokasikan ruang untuk string.Jawab:
null
mungkin tidak tepatDasar Pemikiran:
null
dalam hal ini sebenarnya digunakan untuk menunjukkan dua jenis nilai yang berbeda. Yang pertama mungkin merupakan nilai default yang ingin ditetapkan pengguna antarmuka Anda. Sayangnya, nilai kedua adalah tanda untuk menunjukkan bahwa sistem Anda tidak berfungsi dengan benar. Dalam kasus seperti itu, Anda mungkin ingin gagal seaman mungkin (apa pun artinya bagi sistem Anda).Contoh 2
char *
anggota.NULL
char *
anggota untuk API Anda dapat ditunjukkan dengan nilai tunggalNULL
char *
anggota secara eksplisit .Jawab:
NULL
mungkin tepatDasar Pemikiran: Ada sedikit kemungkinan bahwa struct Anda melewati
NULL
pemeriksaan tetapi tidak diinisialisasi. Namun, API Anda mungkin tidak dapat menjelaskan hal ini kecuali Anda memiliki semacam checksum pada nilai struct dan / atau rentang memeriksa alamat struct. Linter MISRA-C dapat membantu pengguna API Anda dengan menandai penggunaan struct sebelum inisialisasi mereka. Namun, untukchar *
anggota, jika penunjuk ke struct menunjuk ke struct yang diinisialisasi,NULL
adalah nilai default dari anggota yang tidak ditentukan dalam penginisialisasi struct. Oleh karena itu,NULL
dapat berfungsi sebagai nilai default aman untukchar *
anggota struct di aplikasi Anda.Jika itu pada antarmuka serialisasi, saya akan bertanya pada diri sendiri pertanyaan berikut tentang apakah akan menggunakan null pada string.
null
indikasi potensi kesalahan sisi klien? Untuk JSON dalam JavaScript, ini mungkin tidak karenanull
tidak selalu digunakan sebagai indikasi kegagalan alokasi. Dalam JavaScript, ini digunakan sebagai indikasi eksplisit tentang tidak adanya objek dari referensi yang akan ditetapkan bermasalah. Namun, ada parser dan serialis non-javascript di luar sana yang memetakan JSONnull
kenull
tipe asli . Jika ini masalahnya, ini meminta diskusi tentang apakahnull
penggunaan asli atau tidak cocok untuk kombinasi bahasa, parser, dan serializer tertentu.null
sebenarnya menunjukkan bahwa Anda memiliki tipe pesan baru seluruhnya. Mungkin lebih bersih bagi konsumen Anda dari format serialisasi untuk hanya menentukan jenis pesan yang sama sekali berbeda. Ini memastikan bahwa validasi dan logika aplikasi mereka dapat memiliki pemisahan yang bersih antara dua perbedaan pesan yang disediakan antarmuka web Anda.Nasihat Umum
null
tidak dapat menjadi nilai di tepi atau antarmuka yang tidak mendukungnya. Jika Anda menggunakan sesuatu yang sifatnya sangat longgar pada pengetikan nilai properti (yaitu JSON), cobalah untuk mendorong beberapa bentuk skema atau validasi pada perangkat lunak edge konsumen (mis. Skema JSON ) jika Anda bisa. Jika itu adalah bahasa pemrograman API, validasikan input pengguna secara statis jika memungkinkan (melalui pengetikan) atau sekeras yang masuk akal dalam runtime (alias praktikkan pemrograman defensif pada antarmuka yang dihadapkan konsumen). Yang terpenting, dokumentasikan atau tentukan tepi sehingga tidak ada pertanyaan tentang:sumber
Berikut analisis pribadi saya terhadap pertanyaan-pertanyaan ini. Itu tidak didukung oleh buku, kertas, studi atau apa pun, hanya pengalaman pribadi saya.
String kosong sebagai
null
Ini adalah jalan keluar bagi saya. Jangan mencampur semantik string kosong dengan yang tidak didefinisikan. Dalam banyak kasus, mereka dapat dipertukarkan dengan sempurna, tetapi Anda dapat mengalami kasus-kasus di mana yang tidak didefinisikan dan didefinisikan tetapi kosong berarti sesuatu yang berbeda.
Semacam contoh bodoh: katakanlah ada atribut yang menyimpan kunci asing, dan atribut itu tidak didefinisikan atau sedang
null
, itu berarti bahwa tidak ada hubungan yang didefinisikan, sedangkan string kosong""
dapat dipahami sebagai hubungan yang didefinisikan dan ID rekaman asing adalah string kosong itu.Tidak didefinisikan vs
null
Ini bukan topik hitam atau putih. Ada pro dan kontra untuk kedua pendekatan tersebut.
Dalam mendukung
null
nilai-nilai yang mendefinisikan secara eksplisit , ada pro ini:Dalam mendukung asumsi kunci tidak ada sama dengan semantik
null
:Seandainya API entah bagaimana stabil, dan Anda mendokumentasikannya dengan seksama, saya pikir sangat baik untuk menyatakan bahwa kunci yang tidak ada sama dengan arti
null
. Tetapi jika lebih berantakan dan kacau (seperti yang sering terjadi), saya pikir Anda dapat menghindari sakit kepala jika Anda secara eksplisit mendefinisikan setiap nilai dalam setiap pesan. Yaitu jika ragu, saya cenderung mengikuti pendekatan verbose.Semua yang dikatakan, hal terpenting terpenting: nyatakan niat Anda dengan jelas dan konsisten. Jangan lakukan satu hal di sini dan yang lain di sana. Perangkat lunak yang dapat diprediksi adalah perangkat lunak yang lebih baik.
sumber
null
. Contoh lain: dalam permainan, ada objek karakter, dan memiliki atribut "mitra". Seorangnull
pasangan jelas berarti bahwa tidak ada pasangan sama sekali, tetapi""
dapat dipahami karena ada pasangan yang namanya""
.null
untuk string kosong. Mungkin membuatnya dalam bentuk, tetapi tidak pernah dalam model data.name
yang saya bicarakan, apakah Anda mengizinkan nama mitra menjadi nol?Saya akan memasok string kosong dalam situasi di mana string hadir, dan itu terjadi menjadi string kosong. Saya akan memberikan nol dalam situasi di mana saya ingin secara eksplisit mengatakan "tidak, data ini tidak ada". Dan hilangkan kunci untuk mengatakan "tidak ada data di sana, jangan repot-repot".
Anda menilai situasi mana yang bisa terjadi. Apakah masuk akal jika aplikasi Anda memiliki string kosong? Apakah Anda ingin membedakan antara mengatakan "tidak ada data" secara eksplisit dengan menggunakan nol dan secara implisit dengan tidak memiliki nilai? Anda seharusnya hanya memiliki kedua kemungkinan (null dan tidak ada kunci sekarang) jika keduanya perlu dibedakan oleh klien.
Sekarang perlu diingat bahwa ini semua tentang pengiriman data. Apa yang penerima lakukan dengan data adalah urusan mereka, dan mereka akan melakukan apa yang paling nyaman bagi mereka. Penerima harus dapat menangani apa pun yang Anda lemparkan padanya (mungkin dengan menolak data) tanpa menabrak.
Jika tidak ada pertimbangan lain, maka saya akan mengirimkan apa yang paling nyaman bagi pengirim, dan mendokumentasikannya . Saya lebih suka untuk tidak mengirim nilai yang tidak ada sama sekali karena ini cenderung meningkatkan kecepatan penyandian, transmisi dan penguraian JSON.
sumber
Meskipun saya tidak bisa mengatakan apa yang terbaik itu hampir pasti bukan detail implementasi yang sederhana , itu mengubah struktur bagaimana Anda dapat berinteraksi dengan variabel itu.
Jika sesuatu bisa menjadi nol Anda harus selalu memperlakukannya seolah-olah itu akan menjadi nol di beberapa titik , jadi Anda akan selalu memiliki dua alur kerja , satu untuk nol, satu untuk string yang valid. Split workflow tidak selalu merupakan hal yang buruk, karena ada sedikit penanganan kesalahan dan penggunaan case khusus yang dapat Anda manfaatkan, tetapi itu mengaburkan kode Anda.
Jika Anda selalu berinteraksi dengan string dengan cara yang sama , mungkin akan lebih mudah untuk fungsionalitas untuk tetap berada di kepala Anda .
Jadi seperti halnya dengan pertanyaan "apa yang terbaik", saya pergi dengan jawabannya: itu tergantung . Jika Anda ingin membagi alur kerja Anda dan menangkap secara lebih eksplisit ketika sesuatu tidak disetel, gunakan null. Jika Anda lebih suka program tetap seperti apa adanya, gunakan string kosong. Yang penting adalah Anda konsisten , pilih pengembalian bersama dan tetap dengan itu.
Mengingat Anda membuat API, saya akan merekomendasikan menempel pada string kosong karena ada lebih sedikit bagi pengguna untuk mengimbangi, karena sebagai pengguna API saya tidak akan tahu setiap alasan API Anda bisa memberi saya nilai nol kecuali jika Anda didokumentasikan dengan sangat baik, yang tidak akan dibaca oleh beberapa pengguna.
sumber
string
s, tidak pernah nol. Jika API menggunakan null, maka pada titik tertentu produsen perlu membuat ininull
agar sesuai dengan API. Maka konsumen perlu menanganinull
juga. Tapi saya pikir saya mengerti apa yang Anda katakan, hanya memutuskan dan mendefinisikan API dengan otoritas, bukan? Apakah itu berarti tidak ada yang salah dengan mereka?Dokumen!
TL; DR>
Lakukan sesuai keinginan Anda - terkadang konteks di mana ia digunakan penting. Contoh, Bind Variabel ke Oracle SQL: String Kosong ditafsirkan sebagai NULL.
Cukup saya katakan - Pastikan Anda mendokumentasikan setiap skenario yang disebutkan
Kode Anda mungkin bertindak dengan cara berbeda - mendokumentasikan bagaimana kode Anda bereaksi terhadapnya:
Kemudian selain itu - terserah pada Anda untuk berperilaku secara konsisten, dan mungkin mengadopsi beberapa praktik terbaik Anda sendiri. Dokumentasikan perilaku yang konsisten. Contoh:
sumber
tl; dr - jika Anda menggunakannya: konsisten dalam artinya.
Jika Anda termasuk
null
, apa artinya? Ada alam semesta hal-hal yang bisa berarti. Satu nilai sama sekali tidak cukup untuk mewakili nilai yang hilang atau tidak diketahui (dan ini hanya dua dari segudang kemungkinan: misalnya Hilang - itu sudah diukur, tetapi kami belum mengetahuinya. Tidak diketahui - kami tidak mencoba mengukur saya t.)Dalam contoh yang saya temui baru-baru ini, bidang dapat kosong karena tidak dilaporkan untuk melindungi privasi seseorang, tetapi bidang itu diketahui di sisi pengirim, tidak dikenal di sisi pengirim, tetapi diketahui oleh reporter asli atau tidak diketahui keduanya. Dan semua ini penting bagi penerima. Jadi biasanya satu nilai saja tidak cukup.
Dengan asumsi dunia terbuka (Anda benar-benar tidak tahu tentang hal-hal yang tidak disebutkan), Anda cukup meninggalkannya dan itu bisa apa saja. Dengan asumsi dunia tertutup (hal-hal yang tidak dinyatakan salah, misalnya dalam SQL) Anda sebaiknya memperjelas apa
null
artinya dan konsisten dengan definisi itu karena Anda dapat ...sumber