Saya melihat komponen MvcContrib Grid dan saya terpesona, namun pada saat yang sama jijik, oleh trik sintaksis yang digunakan dalam sintaks Grid :
.Attributes(style => "width:100%")
Sintaks di atas menetapkan atribut gaya HTML yang dihasilkan width:100%
. Sekarang jika Anda memperhatikan, 'gaya' tidak ditentukan. Itu disimpulkan dari nama parameter dalam ekspresi! Saya harus menggali ini dan menemukan di mana 'keajaiban' terjadi:
Hash(params Func<object, TValue>[] hash)
{
foreach (var func in hash)
{
Add(func.Method.GetParameters()[0].Name, func(null));
}
}
Jadi memang, kode menggunakan formal, waktu kompilasi, nama parameter untuk membuat kamus pasangan nama-nilai atribut. Sintaks yang dihasilkan memang sangat ekspresif, tetapi pada saat yang sama sangat berbahaya.
Penggunaan umum ekspresi lambda memungkinkan penggantian nama yang digunakan tanpa efek samping. Saya melihat contoh di buku yang mengatakan collection.ForEach(book => Fire.Burn(book))
saya tahu saya bisa menulis dalam kode saya collection.ForEach(log => Fire.Burn(log))
dan itu artinya sama . Tetapi dengan sintaks MvcContrib Grid di sini tiba-tiba, saya menemukan kode yang secara aktif mencari dan membuat keputusan berdasarkan nama yang saya pilih untuk variabel saya!
Jadi apakah ini praktik umum dengan komunitas C # 3.5 / 4.0 dan pecinta ekspresi lambda? Atau maverick jahat yang tidak perlu saya khawatirkan?
sumber
Jawaban:
Ini memiliki interop yang buruk. Sebagai contoh, perhatikan contoh C # - F # ini
C #:
F #:
Hasil:
"arg" dicetak (bukan "yadda").
Akibatnya, perancang perpustakaan harus menghindari 'penyalahgunaan' semacam ini, atau setidaknya memberikan kelebihan 'standar' (misalnya yang menggunakan nama string sebagai parameter tambahan) jika mereka ingin memiliki interop yang bagus di seluruh bahasa .Net.
sumber
Saya menemukan bahwa aneh bukan karena namanya , tetapi karena lambda tidak perlu ; itu bisa menggunakan tipe anonim dan lebih fleksibel:
Ini adalah pola yang digunakan di sebagian besar ASP.NET MVC (misalnya), dan memiliki kegunaan lain ( peringatan , perhatikan juga pemikiran Ayende jika namanya adalah nilai ajaib daripada spesifik penelepon)
sumber
HtmlAttributes
kelas dengan atribut yang diharapkan (untuk intellisense), dan hanya mengabaikan mereka dengannull
nilai-nilai ...Hanya ingin memberikan pendapat saya (saya adalah penulis komponen grid MvcContrib).
Ini jelas merupakan penyalahgunaan bahasa - tidak diragukan lagi. Namun, saya tidak akan benar-benar menganggapnya kontra intuitif - ketika Anda melihat panggilan ke
Attributes(style => "width:100%", @class => "foo")
saya pikir itu cukup jelas apa yang terjadi (Ini tentu saja tidak lebih buruk daripada pendekatan tipe anonim). Dari perspektif intellisense, saya setuju itu cukup buram.
Bagi yang berminat, beberapa info latar belakang tentang penggunaannya di MvcContrib ...
Saya menambahkan ini ke grid sebagai preferensi pribadi - Saya tidak suka penggunaan tipe anonim sebagai kamus (memiliki parameter yang mengambil "objek" sama buramnya dengan yang mengambil params Func []) dan initializer koleksi Kamus adalah agak bertele-tele (saya juga bukan penggemar antarmuka verbose yang fasih, misalnya harus menyatukan beberapa panggilan ke suatu Atribut ("style", "display: none"). Attribute ("class", "foo") dll)
Jika C # memiliki sintaksis kurang verbose untuk kamus literal, maka saya tidak akan repot memasukkan sintaks ini dalam komponen grid :)
Saya juga ingin menunjukkan bahwa penggunaan ini di MvcContrib sepenuhnya opsional - ini adalah metode ekstensi yang membungkus kelebihan yang mengambil IDictionary sebagai gantinya. Saya pikir sangat penting bahwa jika Anda memberikan metode seperti ini, Anda juga harus mendukung pendekatan yang lebih 'normal', misalnya untuk interop dengan bahasa lain.
Juga, seseorang menyebutkan 'overhead refleksi' dan saya hanya ingin menunjukkan bahwa sebenarnya tidak ada banyak overhead dengan pendekatan ini - tidak ada refleksi runtime atau kompilasi ekspresi yang terlibat (lihat http://blog.bittercoder.com /PermaLink,guid,206e64d1-29ae-4362-874b-83f5b103727f.aspx ).
sumber
saya akan lebih memilih
Ini jauh lebih eksplisit dan standar dan tidak ada yang diperoleh dengan menggunakan lambdas.
sumber
html.Attributes.Add("style", "width:100%");
tidak membaca sebaikstyle = "width:100%"
(html aktual yang dihasilkan), sedangkanstyle => "width:100%"
sangat dekat dengan apa yang tampak seperti dalam HTML yang dihasilkan.Selamat Datang di Rails Land :)
Tidak ada yang salah dengan itu selama Anda tahu apa yang terjadi. (Justru ketika hal semacam ini tidak didokumentasikan dengan baik bahwa ada masalah).
Keseluruhan kerangka Rails dibangun di atas gagasan konvensi atas konfigurasi. Memberi penamaan dengan cara-cara tertentu membuat Anda tertarik pada konvensi yang mereka gunakan dan Anda mendapatkan banyak fungsi secara gratis. Mengikuti konvensi penamaan akan membuat Anda lebih cepat. Semuanya bekerja dengan baik.
Tempat lain di mana saya pernah melihat trik seperti ini adalah dalam pemanggilan metode panggilan dalam Moq. Anda lulus lambda, tetapi lambda tidak pernah dieksekusi. Mereka hanya menggunakan ekspresi untuk memastikan bahwa pemanggilan metode terjadi dan melemparkan pengecualian jika tidak.
sumber
Ini mengerikan pada lebih dari satu level. Dan tidak, ini tidak seperti Ruby. Ini penyalahgunaan C # dan .NET.
Ada banyak saran tentang bagaimana melakukan ini dengan cara yang lebih mudah: tuple, tipe anonim, antarmuka yang lancar dan sebagainya.
Apa yang membuatnya begitu buruk adalah bahwa itu hanya cara untuk menghargai demi kebaikannya sendiri:
Apa yang terjadi ketika Anda perlu memanggil ini dari Visual Basic?
.Attributes(Function(style) "width:100%")
Ini benar-benar berlawanan dengan intuisi, dan intellisense akan memberikan sedikit bantuan untuk mengetahui cara mengirimkan barang.
Itu tidak perlu tidak efisien.
Tidak ada yang akan tahu bagaimana cara mempertahankannya.
Apa jenis argumen yang masuk ke atribut? itu
Func<object,string>
? Bagaimana niat itu diungkapkan? Apa dokumentasi intellisense Anda akan berkata, "Harap abaikan semua nilai objek"?Saya pikir Anda sepenuhnya dibenarkan memiliki perasaan jijik.
sumber
Saya di kamp "sintaks kecemerlangan", jika mereka mendokumentasikannya dengan jelas, dan ini terlihat keren, hampir tidak ada masalah dengan imo!
sumber
Keduanya. Ini penyalahgunaan ekspresi lambda DAN kecemerlangan sintaksis.
sumber
Saya hampir tidak pernah menemukan penggunaan semacam ini. Saya pikir itu "tidak pantas" :)
Ini bukan cara penggunaan yang umum, ini tidak sesuai dengan konvensi umum. Sintaks semacam ini tentu saja memiliki pro dan kontra:
Cons
Pro
Intinya - dalam desain API publik saya akan memilih cara yang lebih eksplisit.
sumber
Tidak, itu tentu bukan praktik yang umum. Ini kontra-intuitif, tidak ada cara hanya melihat kode untuk mengetahui apa fungsinya. Anda harus tahu bagaimana itu digunakan untuk memahami bagaimana itu digunakan.
Alih-alih memasok atribut menggunakan array delegasi, metode chaining akan lebih jelas dan berkinerja lebih baik:
Meskipun ini sedikit lebih banyak untuk diketik, ini jelas dan intuitif.
sumber
.Attribute("style", "width:100%")
memberi sayastyle="width:100%"
, tetapi untuk semua yang saya tahu itu bisa memberi sayafoooooo
. Saya tidak melihat perbedaannya.Bisakah saya menggunakan ini untuk membuat frase?
magic lambda (n): fungsi lambda yang digunakan hanya untuk tujuan mengganti string sihir.
sumber
Apa yang salah dengan yang berikut ini:
sumber
Semua ini mengomel tentang "horridness" adalah sekelompok c # guys lama bereaksi berlebihan (dan saya seorang programmer C # lama dan masih penggemar bahasa). Tidak ada yang mengerikan tentang sintaks ini. Ini hanyalah upaya untuk membuat sintaksis terlihat lebih seperti apa yang Anda coba ekspresikan. Semakin sedikit "noise" yang ada dalam sintaks untuk sesuatu, semakin mudah programmer dapat memahaminya. Mengurangi kebisingan dalam satu baris kode hanya membantu sedikit, tetapi biarkan itu menumpuk di semakin banyak kode, dan ternyata menjadi manfaat besar.
Ini adalah upaya oleh penulis untuk mengupayakan manfaat yang sama dengan yang diberikan DSL kepada Anda - ketika kode hanya "terlihat seperti" apa yang Anda coba katakan, Anda telah mencapai tempat yang ajaib. Anda dapat memperdebatkan apakah ini baik untuk interop, atau apakah itu lebih baik daripada metode anonim untuk membenarkan beberapa biaya "kompleksitas". Cukup adil ... jadi dalam proyek Anda, Anda harus membuat pilihan yang tepat apakah akan menggunakan sintaksis semacam ini. Tapi tetap saja ... ini adalah upaya pintar oleh seorang programmer untuk melakukan apa, pada akhirnya, kita semua coba lakukan (apakah kita menyadarinya atau tidak). Dan apa yang kita semua coba lakukan, adalah ini: "Katakan pada komputer apa yang ingin kita lakukan dalam bahasa yang sedekat mungkin dengan cara kita berpikir tentang apa yang ingin dilakukan."
Semakin dekat dengan mengekspresikan instruksi kami ke komputer dengan cara yang sama yang kami pikir secara internal adalah kunci untuk membuat perangkat lunak lebih dapat dirawat dan lebih akurat.
EDIT: Saya telah mengatakan "kunci untuk membuat perangkat lunak lebih dapat dipelihara dan lebih akurat", yang merupakan sedikit unicorniness yang terlalu naif dan berlebihan. Saya mengubahnya menjadi "kunci."
sumber
Ini adalah salah satu manfaat dari pohon ekspresi - seseorang dapat memeriksa kode itu sendiri untuk informasi tambahan. Itu adalah bagaimana
.Where(e => e.Name == "Jamie")
dapat dikonversi ke dalam klausa SQL Where yang setara. Ini adalah penggunaan cerdas pohon ekspresi, meskipun saya berharap itu tidak lebih jauh dari ini. Apa pun yang lebih kompleks kemungkinan akan lebih sulit daripada kode yang diharapkan untuk diganti, jadi saya menduga itu akan membatasi diri.sumber
Ini merupakan pendekatan yang menarik. Jika Anda membatasi sisi kanan ekspresi menjadi konstanta hanya maka Anda bisa menerapkan menggunakan
Yang saya pikir adalah apa yang sebenarnya Anda inginkan daripada delegasi (Anda menggunakan lambda untuk mendapatkan nama kedua belah pihak) Lihat implementasi naif di bawah ini:
Ini bahkan mungkin membahas masalah interop lintas bahasa yang disebutkan sebelumnya di utas.
sumber
Kode ini sangat pintar, tetapi berpotensi menyebabkan lebih banyak masalah yang dipecahkan.
Seperti yang telah Anda tunjukkan, sekarang ada ketergantungan yang tidak jelas antara nama parameter (gaya) dan atribut HTML. Tidak ada pemeriksaan waktu kompilasi yang dilakukan. Jika nama parameter salah ketik, halaman mungkin tidak akan memiliki pesan kesalahan runtime, tetapi jauh lebih sulit untuk menemukan bug logika (tidak ada kesalahan, tetapi perilaku salah).
Solusi yang lebih baik adalah memiliki anggota data yang dapat diperiksa pada waktu kompilasi. Jadi alih-alih ini:
kode dengan properti Style dapat diperiksa oleh kompiler:
atau bahkan:
Itu lebih banyak bekerja untuk pembuat kode, tetapi pendekatan ini mengambil keuntungan dari kemampuan pengecekan tipe C yang kuat, yang membantu mencegah bug masuk ke kode sejak awal.
sumber
memang sepertinya Ruby =), setidaknya bagi saya penggunaan sumber daya statis untuk "pencarian" dinamis nanti tidak cocok untuk pertimbangan desain api, harap trik pintar ini opsional di api itu.
Kami dapat mewarisi dari IDictionary (atau tidak) dan menyediakan pengindeks yang berperilaku seperti array php ketika Anda tidak perlu menambahkan kunci untuk menetapkan nilai. Ini akan menjadi penggunaan semantik Net yang valid bukan hanya c #, dan masih membutuhkan dokumentasi.
semoga ini membantu
sumber
Menurut pendapat saya itu adalah penyalahgunaan lambda.
Untuk sintaks kecemerlangan saya menemukan hal yang
style=>"width:100%"
membingungkan. Terutama karena=>
bukan=
sumber
IMHO, ini adalah cara yang keren untuk melakukannya. Kita semua menyukai kenyataan bahwa penamaan Pengontrol kelas akan membuatnya menjadi pengontrol di MVC bukan? Jadi ada kasus di mana penamaan itu penting.
Niatnya juga sangat jelas di sini. Sangat mudah dipahami yang
.Attribute( book => "something")
akan menghasilkanbook="something"
dan.Attribute( log => "something")
akan menghasilkanlog="something"
Saya kira itu seharusnya tidak menjadi masalah jika Anda memperlakukannya seperti sebuah konvensi. Saya berpendapat bahwa apa pun yang membuat Anda menulis lebih sedikit kode dan membuat niat menjadi jelas adalah hal yang baik.
sumber
Jika nama metode (func) dipilih dengan baik, maka ini adalah cara yang brilian untuk menghindari sakit kepala pemeliharaan (yaitu: menambahkan fungsi baru, tetapi lupa menambahkannya ke daftar pemetaan fungsi-parameter). Tentu saja, Anda perlu mendokumentasikannya dengan berat dan sebaiknya Anda membuat dokumentasi untuk parameter dari dokumentasi untuk fungsi di kelas tersebut secara otomatis ...
sumber
Saya pikir ini tidak lebih baik daripada "string ajaib". Saya juga bukan penggemar jenis anonim untuk ini. Perlu pendekatan yang lebih baik & sangat diketik.
sumber