it-swarm.dev

LINQ ve Lambda İfadeleri kullanımı daha az okunabilir koda yol açar mı?

Linq'de bir iş arkadaşınızla bir tartışma yapıyorum, buraya kopyalayacağım:

İş arkadaşı: Burada dürüst olalım. Linq sözdizimi berbat. Kafa karıştırıcı ve sezgisel değil.

Ben: oh hadi, T-SQL'den daha kafa karıştırıcı mı?

İş arkadaşı: Ah, evet.

Ben: Aynı temel parçalara sahip, seç, nerede ve

İş arkadaşı: Linq, bana göre, ilişkisel + OO'nun piç haline getirilmesidir. İş arkadaşı: Beni yanlış anlamayın - inanılmaz derecede güçlü, ancak SQL'i nesne koleksiyonlarını kullanmak için yeniden tasarladılar.

Linq + Lamda'yı kullanmanın çok güçlü olduğu (hemfikir olduğu) ve aynı zamanda kodun okunmasını kolaylaştırdığı görüşündeyim (o noktada aynı fikirde değil):

pickFiles = from f in pickFolder.GetFiles("*.txt")
where ValidAuditFileName.IsMatch(f.Name)
select f;

veya

var existing = from s in ActiveRecordLinq.AsQueryable<ScannedEntity>()
where s.FileName == f.FullName && s.DocumentType != "Unknown"
select s;

veya (burada VB kodu)

   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

Bana göre bu okunması temiz ve kolaydır (en azından alternatiflerden daha kolay), hakkındaki görüşleriniz nelerdir?

43
BlackICE

Artık doğru gönderiyi bulamıyorum, ancak Eric Lippert (ve muhtemelen birkaç diğer sofya), Linq'in deklaratif olduğu çeşitli vesilelerle birkaç sezgisel olanı seçti. zorunl sözdiziminden.

Linq, mekanizmasını değil, niyeti ifade eden kod yazmanıza olanak tanır .

Bana hangisinin daha kolay okunacağını söylüyorsun. Bu:

IEnumerable<Customer> GetVipCustomers(IEnumerable<Customer> source)
{
    List<Customer> results = new List<Customer>();
    foreach (Customer c in source)
    {
        if (c.FirstName == "Aaron")
        {
            results.Add(c);
        }
    }
    results.Sort(new LastNameComparer());
    return results;
}

class LastNameComparer : IComparer<Customer>
{
    public int Compare(Customer a, Customer b)
    {
        return x.LastName.CompareTo(b.LastName);
    }
}

Veya bu?

IEnumerable<Customer> GetVipCustomers(IEnumerable<Customer> source)
{
    return from c in source
           where c.FirstName == "Aaron"
           orderby c.LastName
           select c;
}

Yoksa bu bile mi?

IEnumerable<Customer> GetVipCustomers(IEnumerable<Customer> source)
{
    return source.Where(c => c.FirstName == "Aaron").OrderBy(c => c.LastName);
}

İlk örnek, en basit sonuçları elde etmek için sadece bir grup anlamsız kazan plakasıdır. Linq versiyonlarından daha okunabilir olduğunu düşünen herkesin kafasının muayene edilmesi gerekir. Sadece bu değil, birincisi hafızayı boşa harcıyor. yield return sıralama nedeniyle.

İş arkadaşınız ne istediğini söyleyebilir; şahsen, Linq benim kod okunabilirliğini ölçülemez bir şekilde geliştirdiğini düşünüyorum.

Linq hakkında da “ilişkisel” bir şey yok. SQL ile bazı yüzeysel benzerlikleri olabilir, ancak ilişkisel hesabı uygulamak için herhangi bir şekil veya biçimde girişimde bulunmaz. Dizileri sorgulamayı ve yansıtmayı kolaylaştıran bir grup uzantı. "Sorgu", "ilişkisel" anlamına gelmez ve aslında SQL benzeri sözdizimini kullanan ilişkisel olmayan birkaç veritabanı vardır. Linq tamamen nesne yönelimlidir, sadece bazı ifade ağacı vudu ve akıllı tasarım nedeniyle Linq to SQL gibi çerçevelerle ilişkisel veritabanlarıyla çalışır. C # ekibi, anonim işlevleri ifade ağaçlarına dolaylı olarak dönüştürülebilir hale getirir.

74
Aaronaught

İş arkadaşı: Burada dürüst olalım. Linq sözdizimi berbat. Kafa karıştırıcı ve sezgisel değil.

Bu eleştiriyle tartışamazsınız. İş arkadaşınız için berbat. Onlar için açık ve sezgisel bir sözdizimi tasarlayamadık. Bu bizim başarısızlığımız ve özürlerimi iş arkadaşınıza aktarabilirsiniz. Bunu nasıl daha iyi hale getireceğime dair öneriler almaktan mutluluk duyuyorum; iş arkadaşınız özellikle hangi kafa karıştırıcı veya sezgisel bulmuyor?

Ancak, herkesi memnun edemezsiniz. Benim kişisel görüşüm ve bu konuda konuştuğum insanların çoğunun görüşü, sorgu anlama sözdiziminin eşdeğer zorunlu sözdiziminden çok daha açık olmasıdır. Açıkçası herkes aynı fikirde değil, ama neyse ki dil tasarımı yaparken milyonlarca müşterimizin fikir birliğine ihtiyaç duymuyoruz.

"Sezgisel" ne olduğu konusunda, birçok farklı dili inceleyen ve sonunda İngilizce'nin tüm dillerin en iyisi olduğu sonucuna varılan İngilizce dilbilimcinin hikayesini hatırlattım çünkü İngilizce, kelimeler geliyor - düşündüğünüz sırayla. Fransızların aksine, sürekli "köpek beyazı eti kırmızı yer" gibi şeyler söylüyorlar. Fransızların düşün doğru düzenindeki kelimeler için ve sonra demek onları Fransızca sipariş! Fransızca çok sezgisel değil! Fransızların konuşmayı başarması şaşırtıcı. Ya Alman? "köpek eti yiyor" sanıyorlar ama sonra "et yiyor köpek" demek zorundalar!?! Çok sezgisel değil.

Genellikle "sezgisel" olan şey sadece bir aşinalık meselesidir. Sorgularıma "select" yan tümcesiyle başlamayı bırakmadan önce LINQ ile çalışmak beni ay aldı. Şimdi ikinci doğa ve SQL sırası tuhaf görünüyor.

Hangisi! Kapsam belirleme kurallarının tümü SQL'de karışıktır. İş arkadaşınıza işaret etmek isteyebileceğiniz bir şey, LINQ'nun (1) değişkenlerin ve kapsamların tanıtımı soldan sağa (*) ve (2) sorgunun sayfada göründüğü sırayla yürütme sırası. Yani, dediğin zaman

from c in customers where c.City == "London" select c.Name

c solda kapsamda görünür ve sağda kapsamda kalır. Ve işlerin gerçekleşme sırası: ilk "müşteriler" değerlendirilir. Daha sonra diziyi filtrelemek için "nerede" değerlendirilir. Ardından filtrelenen sekans "seç" ile yansıtılır.

SQL'de bu özellik yok. Eğer öyle diyorsan

SELECT Name FROM Customers WHERE City = 'London'

"Ad" sola değil sağına doğru bir şeyle kapsam içine alınır ve sorgu tamamen dağınık bir sırada yürütülür; önce orta fıkra, sonra son fıkra ve sonra ilk fıkra değerlendirilir. Bu uzun zamandır sadece LINQ ile çalışarak bana deli ve sezgisel gelmiyor.


(*) LINQ'da birleştirme cümleleri olan kapsam belirleme kuralları biraz garip. Ama bunun dışında, kapsamlar güzel yuvalar.

69
Eric Lippert

Programlama dünyasındaki her şey gibi, sözdizimine alışmanız gerekir ve sonra (potansiyel olarak) okunması daha kolaydır.

Programlama dünyasındaki herhangi bir şey gibi, spagetti kodu veya diğer kötüye kullanım potansiyeli vardır.

Programlama dünyasındaki herhangi bir şey gibi, bunu bu şekilde veya başka bir şekilde yapabilirsiniz.

Programlama dünyasındaki her şey gibi, kilometreniz de değişebilir.

22
Wonko the Sane

LINQ/lambda ile ilgili olarak, "Bilgisayarınıza okunabilir olmaktan ziyade insanlara okunabilir kod yaz" komutunu içeren bir açıklama/açıklama gördüm.

Bununla birlikte, bu ifadenin çok fazla değeri olduğunu düşünüyorum, ancak Meclis'ten, geliştirme prosedüründen OO'ya, yönetilenden, yüksek verimli iş paralel çözümlerinden yararlanarak, geliştirme dillerinin tüm gamını geçen geliştiriciyi (kendim gibi) düşünün .

Kodumu olabildiğince okunabilir ve tekrar kullanılabilir hale getirmekten ve çok sayıda farklı iş sektöründe üretim kalitesi sistemleri ve hizmetleri sunmak için GOF tasarım deseni ilkelerinin çoğunu benimsemekten gurur duydum.

Lambda ifadesiyle ilk karşılaştığımda şöyle düşündüm: "Bu da ne böyle!?!" Benim tanıdık (ve dolayısıyla rahat) açık beyan sözdizimine karşı hemen sezgiseldi. Genç <5 yıl işte adamlar, ancak gökten manna gibi onu alıştırdı!

Çünkü yıllardır bilgisayar gibi düşünmek (sözdizimsel anlamda) doğrudan kodlama sözdizimine (dilden bağımsız olarak) kolayca tercüme edilebilir. Yaklaşık 20 + yıl (benim durumumda 30+) için bu hesaplama zihniyetine sahip olduğunuzda, lambda ifadesinin ilk sözdizimsel şokunun kolayca korku ve güvensizliğe dönüşebilir.

Belki OP'deki meslektaş kendimle benzer bir geçmişten gelmişti (yani birkaç blok ötede) ve o zaman onlara karşı sezgiseldi? Sorum şu: bu konuda ne yaptınız? Akranınızı satır içi sözdiziminin faydalarını anlamak için yeniden eğitmeye mi çalıştınız, yoksa “programla birlikte olmadıkları” için onları boyunduruk altına aldınız mı? Birincisi muhtemelen iş arkadaşınızın düşünme çizginize geldiğini görürdü, ikincisi muhtemelen LINQ/lambda sözdizimine daha fazla güvensizlik yapar ve böylece olumsuz düşünceyi daha da kötüleştirirdi.

Kendim için kendi düşünme biçimimi yeniden eğitmek zorunda kaldım (Eric yukarıda bahsettiği gibi, bu önemsiz bir zihin kayması değil ve Miranda'da 80'lerde programlamak zorunda kaldım, bu yüzden fonksiyonel programlama deneyiminden payımı aldım) ama bir kez o acıdan geçtikten sonra faydalar belliydi ama - daha da önemlisi - kullanımının kullanıldığı (yani onu kullanmak için kullanıldığı) ), karmaşık ve tekrarlayıcı olarak (DRY prensibi dikkate alınarak).

Sadece çok fazla kod yazmayan, aynı zamanda teknik olarak çok fazla kod incelemesi gereken biri olarak, bu ilkeleri anlamam gerekiyor, böylece öğeleri tarafsız bir şekilde inceleyebilmem, lambda ifadesinin kullanımının daha verimli olabileceği/ve geliştiricilerin son derece karmaşık satır içi lambda ifadelerinin okunabilirliğini dikkate almasını sağlamak için (bir yöntem çağrısı - bu durumlarda kodu daha okunabilir, bakımı ve genişletilebilir hale getirir).

Birisi "Lambda almadın mı?" veya LINQ sözdizimi yerine, onları markalamak yerine luddite temel prensipleri anlamalarına yardımcı olmaya çalışın. Sonuçta benim gibi "eski okul" geçmişine sahip olabilirler.

6
CWC

Sorgular çok uzunsa Lambda İfadeleri daha az okunabilir koda yol açar. Ancak çok fazla iç içe döngüler çok daha iyidir.

Bir ikisinin karışımı ile daha iyidir.

Daha hızlı (hızlı olmanız gerekir) veya okunması daha kolaysa Lambda'ya yazın.

4
Amir Rezaei

Ben çoğu durumda (çok tuhaf bir şey yaparken hariç) biri neler olup bittiğini fikrini almak ya da tüm küçük küçük ayrıntıları kolayca bulabilirsiniz eğer "okunabilir" demek istiyorsanız bağlıdır.

Bağlantının ilkine yardımcı olduğunu düşünüyorum, ancak sıklıkla (özellikle hata ayıklama sırasında) ikincisine zarar veriyor.

Ben kod bakarken IMHO Ben eski bilmiyorum ikincisinden çok daha önemlidir, bu yüzden çok daha okunabilir buluyorum.

1
Bill

LINQ sözdizimini sezgisel ve okunması kolay buluyorum, özellikle FROM'u SQL'de olduğu gibi ortada ait olduğu başlangıçta koydukları için. Ancak IMO lambdas kafa karıştırıcıdır ve kodun okunmasını zorlaştırır.

1
Mason Wheeler

Linq söz diziminin T-SQL'den önemli ölçüde farklı olmadığını kabul ediyorum. Ben iş arkadaşınız gerçekten onun ilişkisel şeyler karıştırmak için itiraz olabilir ki onun Nice ve parlak OO kodu. Öte yandan, fonksiyonel programlama biraz alışmak ve biraz istekli alışmak.

1
Larry Coleman

Değişir. Açıkçası, T-SQL bazı DB-ilişkisel çözümler sağlar. Açıkçası LINQ benzersiz bazı OO çözümler sağlar.

Ancak; "T-SQL'den daha mı kafa karıştırıcı?" - ilk soruda tartışılır/sorulur. Bu, mevcut cevapların hiçbirinin ele almadığı bazı özellikleri, geçmişte takılı kalmakla (açıkça SQL tanıştı) eleştirmeni suçlamakla açıkça ilgilidir.

Bu nedenle, bazı özellikler için LINQ'yu takdir etsem ve buradaki mevcut cevaplara çok fazla katılmıyorum, kontrpuanın temsili hak ettiğini hissediyorum:

LINQ'ye aşina olduktan yıllar sonra, belirli grup işlemleri, dış birleşimler ve equijoins olmayan birleşimler yapmak, bileşik anahtarlarla çalışmak ve LINQ'daki diğer işlemler hala beni rahatsız ediyor. (Özellikle performansa duyarlı sorularla ilişkisel bir arka uç hedeflerken.)

from c in categories
join p in products on c equals p.Category into ps
from p in ps.DefaultIfEmpty()

Bunun sezgisel olduğunu düşünüyorsanız, size daha fazla güç. ;)

0
shannon