Saya sedang berdiskusi dengan rekan kerja di Linq, saya akan salin di sini:
Rekan kerja: Mari jujur di sini. Sintaks Linq menyebalkan. Ini membingungkan dan tidak intuitif.
Saya: oh ayolah, lebih membingungkan daripada T-SQL?
Rekan kerja: eh, ya.
Saya: ini memiliki bagian dasar yang sama, pilih, di mana, dan dari
Co-Worker: Linq, bagi saya, adalah bastardisasi relasional + OO. Rekan kerja: Jangan salah paham - ini sangat kuat, tetapi mereka menggunakan kembali SQL untuk menggunakan koleksi objek yang berlawanan.
Saya berpendapat bahwa menggunakan Linq + Lamda sangat kuat (dia setuju), dan juga membuat kode lebih mudah dibaca (dia tidak setuju tentang hal itu):
pickFiles = from f in pickFolder.GetFiles("*.txt")
where ValidAuditFileName.IsMatch(f.Name)
select f;
atau
var existing = from s in ActiveRecordLinq.AsQueryable<ScannedEntity>()
where s.FileName == f.FullName && s.DocumentType != "Unknown"
select s;
atau (kode VB di sini)
Dim notVerified = From image In images.AsParallel
Group Join verifyFile In verifyFolder.GetFiles("*.vfy").AsParallel.Where(
Function(v) v.Length > 0
).AsParallel
On image.Name.Replace(image.Extension, ".vfy") Equals verifyFile.Name
Into verifyList = Group
From verify In verifyList.DefaultIfEmpty
Where verify Is Nothing
Select verify
Bagi saya ini bersih dan mudah (setidaknya lebih mudah daripada alternatif) untuk membaca, apa pendapat Anda tentang itu?
sumber
Jawaban:
Saya tidak dapat menemukan pos yang tepat lagi, tetapi Eric Lippert (dan mungkin beberapa softies lainnya) telah beberapa kali berpendapat tentang bagaimana Linq deklaratif , yang, untuk beberapa kelas masalah, jauh lebih intuitif daripada sintaksis imperatif .
Linq memungkinkan Anda untuk menulis kode yang mengekspresikan maksud , bukan mekanismenya .
Anda memberi tahu saya mana yang lebih mudah dibaca. Ini:
Atau ini?
Atau bahkan ini?
Contoh pertama hanyalah sekelompok boilerplate sia-sia untuk mendapatkan hasil yang paling sederhana. Siapa pun yang berpikir bahwa itu lebih mudah dibaca daripada versi Linq perlu diperiksa kepalanya. Bukan hanya itu, tetapi yang pertama membuang-buang memori. Anda bahkan tidak dapat menulis menggunakan
yield return
karena penyortiran.Rekan kerja Anda dapat mengatakan apa yang diinginkannya; secara pribadi, saya pikir Linq telah meningkatkan keterbacaan kode saya tak terkira.
Tidak ada yang "relasional" tentang Linq juga. Ini mungkin memiliki beberapa kesamaan dangkal dengan SQL tetapi tidak mencoba dalam bentuk apa pun untuk menerapkan kalkulus relasional. Hanya sekelompok ekstensi yang membuatnya lebih mudah untuk melakukan kueri dan memproyeksikan urutan. "Query" tidak berarti "relational", dan sebenarnya ada beberapa database non-relasional yang menggunakan sintaks seperti SQL. Linq adalah murni berorientasi objek, itu hanya terjadi untuk bekerja dengan database relasional melalui kerangka kerja seperti Linq ke SQL karena beberapa voodoo pohon ekspresi dan desain pintar dari tim C #, membuat fungsi anonim secara implisit dikonversi menjadi pohon ekspresi.
sumber
Linq is purely object-oriented
+1 untuk ini. Ini juga mengapa panduan gaya tim kami memberlakukan penggunaan sintaks yang lancar di atas sintaks kueri. Saya menemukan bahwa membuat sifat tautan OO lebih jelas bagi seseorang yang terbiasa dengan notasi objek dalam bahasa C-like.GetVipCustomers()
, yang, seperti namanya, hanya akan mengembalikan koleksi pelanggan VIP, dalam urutan sewenang-wenang. Untuk kasus yang jarang terjadi di mana urutan penting, seperti output ke layar, biarkan pemanggil mengurutkan koleksi.Anda tidak bisa berdebat dengan kritik itu. Untuk rekan kerja Anda, itu menyebalkan . Kami gagal merancang sintaksis yang, bagi mereka, jelas dan intuitif. Itu gagal kami, dan Anda bisa menyampaikan permintaan maaf saya kepada rekan kerja Anda. Saya senang menerima saran tentang cara menjadikannya lebih baik; apa yang menurut rekan kerja Anda membingungkan atau tidak intuitif?
Namun, Anda tidak bisa menyenangkan semua orang. Pendapat pribadi saya, dan pendapat sebagian besar orang yang saya ajak bicara tentang masalah ini, adalah bahwa sintaks pemahaman kueri jauh lebih jelas daripada sintaksis imperatif yang setara. Jelas tidak semua orang setuju, tetapi untungnya kami tidak memerlukan konsensus dari semua jutaan pelanggan kami ketika kami melakukan desain bahasa.
Mengenai masalah apa yang "intuitif", saya diingatkan tentang kisah ahli bahasa Inggris yang mempelajari banyak bahasa berbeda dan akhirnya menyimpulkan bahwa bahasa Inggris adalah yang terbaik dari semua bahasa karena dalam bahasa Inggris, kata-katanya datang dalam urutan yang sama seperti yang Anda pikirkan mereka . Tidak seperti bahasa Prancis, di mana mereka terus-menerus mengatakan hal-hal seperti "anjing putih memakan daging merah". Betapa sulit bagi orang Prancis untuk memikirkan kata-kata dalam urutan yang benar dan kemudian harus mengucapkannya dalam urutan Prancis ! Bahasa Prancis sangat tidak intuitif! Sungguh menakjubkan bahwa Prancis berhasil berbicara itu. Dan Jerman? di mana mereka berpikir "anjing makan daging" tetapi kemudian harus mengatakan "anjing makan daging"!?!
Seringkali apa yang "intuitif" hanyalah masalah keakraban. Butuh berbulan - bulan saya bekerja dengan LINQ sebelum saya berhenti memulai pertanyaan saya dengan klausa "pilih". Sekarang sudah sifat kedua, dan urutan SQL tampaknya aneh.
Yang mana itu! Aturan pelingkupan semua kacau dalam SQL. Sesuatu yang Anda mungkin ingin tunjukkan kepada rekan kerja Anda adalah bahwa LINQ dirancang dengan hati-hati sehingga (1) pengenalan variabel dan cakupan terjadi dari kiri ke kanan (*), dan (2) urutan kueri muncul pada halaman tersebut. urutan pelaksanaannya. Itulah saat Anda mengatakannya
c muncul di lingkup di sebelah kiri, dan tetap di lingkup di sebelah kanan. Dan urutan terjadinya adalah: "pelanggan" pertama dievaluasi. Kemudian "di mana" dievaluasi untuk menyaring urutan. Kemudian urutan yang difilter diproyeksikan oleh "pilih".
SQL tidak memiliki properti ini. Jika Anda mengatakan
kemudian "Nama" dibawa ke ruang lingkup oleh sesuatu di kanannya, bukan ke kiri, dan kueri dieksekusi dalam urutan yang benar-benar kacau; klausa tengah dievaluasi pertama, kemudian klausa terakhir, dan kemudian klausa pertama. Itu sekarang tampak gila dan tidak intuitif bagi saya, telah bekerja hanya dengan LINQ begitu lama sekarang.
(*) Aturan pelingkupan agak aneh di LINQ dengan klausa gabungan. Tapi selain itu, cakupan sarangnya bagus.
sumber
c.
IDE sudah tahu jenisnyac
dan dapat memberi Anda IntelliSense. Di LINQ Anda mengatakan "dari c di pelanggan di mana c." dan boom, Anda mendapatkan IntelliSense membantu Anda dengan mendaftar anggotaCustomer
. Dalam SQL ketika Anda mengetik "SELECT name FROM customers", Anda tidak bisa mendapatkan bantuan IDE untuk memberi tahu Anda bahwa "nama" adalah pilihan yang baik karena Anda mengetikname
sebelumnyacustomers
.Seperti hal lain di dunia pemrograman, Anda harus terbiasa dengan sintaks, dan kemudian (berpotensi) lebih mudah dibaca.
Seperti hal lain di dunia pemrograman, ada potensi kode spageti atau pelanggaran lainnya.
Seperti hal lain di dunia pemrograman, Anda bisa melakukannya dengan cara ini atau cara lain.
Seperti hal lain di dunia pemrograman, jarak tempuh Anda mungkin beragam.
sumber
Saya melihat komentar / komentar di mana ia menyatakan sesuatu - dalam kaitannya dengan LINQ / lambda - di sepanjang baris: "Tulis kode yang dapat dibaca oleh manusia, daripada dibaca oleh komputer Anda".
Saya pikir pernyataan ini memiliki banyak manfaat, namun, pertimbangkan pengembang (seperti saya) yang telah melalui keseluruhan penuh bahasa pengembangan dari Majelis, melalui prosedural, melalui OO, melalui dikelola, dengan memanfaatkan solusi paralel tugas throughput tinggi .
Saya bangga membuat kode saya dapat dibaca dan dapat digunakan kembali sebanyak mungkin dan mengadopsi banyak prinsip pola desain GOF untuk memberikan sistem dan layanan kualitas produksi di berbagai sektor bisnis yang berbeda.
Pertama kali saya menemukan ekspresi lambda, saya berpikir: "Apa-apaan itu!?!" Itu langsung kontra-intuitif untuk sintaks deklaratif eksplisit akrab saya (dan karena itu nyaman). Yang lebih muda <5 thn di pekerjaan guys namun menjilatnya seperti manna dari surga!
Itu karena selama bertahun-tahun berpikir seperti komputer (dalam arti sintaksis) diterjemahkan dengan sangat mudah ke dalam sintaks pengkodean langsung (terlepas dari bahasa). Ketika Anda memiliki pola pikir komputasi selama sekitar 20+ tahun (30+ dalam kasus saya), Anda harus menghargai bahwa guncangan sintaksis awal dari ekspresi lambda dapat dengan mudah diterjemahkan menjadi ketakutan dan ketidakpercayaan.
Mungkin rekan kerja di OP berasal dari latar belakang yang sama dengan saya (yaitu beberapa kali berada di sekitar blok) dan itu kontra-intuitif bagi mereka pada waktu itu? Pertanyaan saya adalah: apa yang Anda lakukan? Apakah Anda mencoba mendidik ulang teman Anda untuk memahami manfaat sintaks sebaris, atau apakah Anda menjiplak / mengucilkan mereka karena tidak "mengikuti program"? Yang pertama mungkin akan melihat rekan kerja Anda mendekati garis pemikiran Anda, yang terakhir mungkin akan membuat mereka lebih tidak mempercayai sintaksis LINQ / lambda bahkan dan dengan demikian memperburuk opini negatif.
Bagi saya sendiri, saya harus mendidik kembali cara berpikir saya sendiri (seperti yang Eric katakan di atas, itu bukan perubahan pikiran yang tidak penting, dan saya harus memprogram di Miranda di tahun 80-an sehingga saya memiliki pengalaman pemrograman fungsional yang sama) tetapi begitu saya telah melalui rasa sakit itu manfaatnya jelas tetapi - yang lebih penting - di mana penggunaannya lebih digunakan (yaitu digunakan untuk menggunakannya), lebih kompleks dan berulang (mengingat prinsip KERING dalam contoh itu).
Sebagai seseorang yang tidak hanya masih menulis banyak kode tetapi juga harus secara teknis meninjau banyak kode, saya harus memahami prinsip-prinsip ini sehingga saya dapat meninjau item secara tidak memihak, memberi saran di mana penggunaan ekspresi lambda mungkin lebih efisien / dapat dibaca, dan juga untuk membuat pengembang mempertimbangkan keterbacaan ekspresi lambda inline yang sangat kompleks (di mana pemanggilan metode akan - dalam kasus tersebut - membuat kode lebih mudah dibaca, dipelihara, dan diperluas).
Jadi ketika seseorang mengatakan bahwa mereka "Jangan mendapatkan lambda?" atau sintaks LINQ, alih-alih mencap mereka sebagai luddite, cobalah untuk membantu mereka memahami prinsip-prinsip yang mendasarinya. Mereka mungkin memiliki latar belakang "sekolah tua" seperti saya.
sumber
Ekspresi Lambda mengarah ke kode yang kurang dapat dibaca jika kueri terlalu panjang. Namun itu jauh lebih baik daripada terlalu banyak loop bersarang .
Lebih baik dengan campuran keduanya .
Tulis di Lambda jika lebih cepat (Anda harus cepat) atau lebih mudah dibaca.
sumber
Saya pikir itu tergantung pada kebanyakan kasus (kecuali ketika melakukan sesuatu yang sangat aneh) pada jika Anda berarti "dapat dibaca" sebagai seseorang mendapatkan ide tentang apa yang sedang terjadi atau jika mereka dapat dengan mudah menemukan semua detail kecil kecil.
Saya pikir tautan membantu dengan yang pertama, tetapi sering (terutama ketika debugging) menyakiti yang terakhir.
IMHO ketika saya melihat kode saya tidak terbiasa dengan yang pertama jauh lebih penting daripada yang terakhir, jadi saya merasa jauh lebih mudah dibaca.
sumber
where e.FirstName == "John"
dan menerjemahkannya ke dalam query SQL! Itu melakukannya dengan melihat ekspresi yang tidak dikompilasi (tetapi diurai), melihat itu adalah perbandingan properti yang disebutFirstName
entitas yang bertahan, dan itu dibandingkan dengan string, dll. Ada banyak hal yang terjadi.Saya menemukan sintaksis LINQ intuitif dan mudah dibaca, terutama karena mereka meletakkan FROM di awal di mana ia berada, bukan di tengah seperti di SQL. Tapi lambda IMO membingungkan dan membuat kode lebih sulit dibaca.
sumber
\x -> x * x
) atau F # (fun x -> x * x
)?Saya setuju dengan Anda bahwa sintaks Linq tidak jauh berbeda dari T-SQL. Saya pikir rekan kerja Anda mungkin benar-benar keberatan dengan hal-hal relasional yang dicampur di mana kode OO-nya bagus dan mengkilap. Di sisi lain, pemrograman fungsional membutuhkan sedikit waktu untuk membiasakan diri, dan kemauan untuk terbiasa dengannya.
sumber
Tergantung. Jelas, T-SQL secara unik menyediakan beberapa solusi DB-relasional. Jelas LINQ secara unik menyediakan beberapa solusi OO.
Namun; "lebih membingungkan daripada T-SQL?" - dibahas / ditanyakan dalam pertanyaan awal. Ini jelas menyiratkan beberapa fitur yang tidak satupun dari alamat jawaban yang ada, alih-alih menuduh kritikus (yang jelas berkenalan dengan SQL) terjebak di masa lalu.
Jadi, meskipun saya menghargai LINQ untuk kualitas tertentu, dan tidak sangat tidak setuju dengan jawaban yang ada di sini, saya merasa tandingannya layak diwakili:
Bertahun-tahun setelah menjadi akrab dengan LINQ, melakukan beberapa jenis operasi grup, sambungan luar dan non-equijoins, bekerja dengan kunci komposit, dan operasi lain di LINQ masih membuat saya merasa ngeri. (Terutama ketika menargetkan back-end relasional dengan pertanyaan yang sensitif terhadap kinerja.)
Jika Anda berpikir itu intuitif, lebih banyak kekuatan untuk Anda. ;)
sumber
Mungkin ada alasan mengapa Linq menyebalkan, coba saja membuat contoh dunia nyata, daripada contoh buku teks ini.
cobalah untuk menunjukkan fungsi ini dalam linqlamdathings dan Anda akan melihat, bahwa semua keindahan hilang, sementara cara klasik tetap dapat dibaca. Belum lagi masalah eksekusi yang ditangguhkan dan pengaturan breakpoints.
Yang benar adalah LinqLambdaThings sangat berguna dalam beberapa kasus dan mereka tidak berpikir untuk mengganti semua orientasi objek bagus yang kalian tidak pernah mengerti
sumber
source.Where(c => c.IsVip && c.FirstName == "Aaron" || c.SecondName == "Aaron").Take(maxCount).OrderBy(d => d.LastName);
tetapi sulit untuk membaca milikmu jadi aku mungkin telah membuat kesalahan;)