it-swarm-eu.dev

Vede použití výrazů LINQ a Lambda k méně čitelnému kódu?

Mám diskuzi se spolupracovníkem na Linq, zkopíruji sem:

Spolupracovník: Buďme upřímní zde. Linq syntax saje. Je to matoucí a neintuitivní.

Já: ach no tak, matoucí než T-SQL?

Spolupracovník: uh, ano.

Já: má stejné základní části, vyberte, kde a odkud

Spolupracovník: Linq je pro mě bastardizace relačních + OO. Spolupracovník: Nechápejte mě špatně - je to neuvěřitelně silné, ale znovu použili SQL, aby používali kolekce objektů.

Jsem toho názoru, že používání Linq + Lamda's je velmi silné (souhlasí), a také usnadňuje čtení kódu (v tomto bodě nesouhlasí):

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

nebo

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

nebo (kód VB zde)

   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

Pro mě je to čisté a snadné (alespoň jednodušší než alternativy) číst, jaké jsou vaše názory na to?

43
BlackICE

Už nemůžu najít ten pravý příspěvek, ale Eric Lippert (a možná i několik dalších softies) se při několika příležitostech opíral o to, jak je Linq deklarativní, což je pro několik tříd problémů mnohem intuitivnější než imperativní syntaxe.

Linq umožňuje psát kód, který vyjadřuje záměr , nikoli mechanismus .

Řekni mi, co je lépe čitelné. Tento:

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);
    }
}

Nebo toto?

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

Nebo dokonce tohle?

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

Prvním příkladem je jen svazek zbytečných kotlových desek, aby bylo dosaženo co nejjednodušších výsledků. Každý, kdo si myslí, že je více čitelnější než verze Linq, musí nechat vyšetřit hlavu. Nejen to, ale první ztrácí paměť. Nemůžete to ani napsat pomocí yield return kvůli třídění.

Váš spolupracovník může říct, co chce; Osobně si myslím, že Linq nezměřitelně zlepšil můj kód čitelnosti.

Ani o Linqovi není nic „relačního“. Může mít některé povrchové podobnosti s SQL, ale nepokouší se v jakémkoli tvaru nebo formě implementovat relační počet. Je to jen banda rozšíření, která usnadňují vyhledávání a projektování sekvencí. „Dotaz“ neznamená „relační“ a ve skutečnosti existuje několik nerelačních databází, které používají syntaxi podobnou SQL. Linq je čistě objektově orientovaný, prostě se stává, že pracuje s relačními databázemi prostřednictvím frameworků jako Linq do SQL kvůli nějakému výrazu voodoo stromů a chytrému designu od tým C #, čímž se anonymní funkce implicitně převádějí na stromy výrazů.

74
Aaronaught

Spolupracovník: Buďme upřímní zde. Linq syntax saje. Je to matoucí a neintuitivní.

S touto kritikou se nemůžete hádat. Pro vašeho spolupracovníka to naštve . Nepodařilo se nám navrhnout syntax, která byla pro ně jasná a intuitivní. To je naše chyba a můžete se omluvit svému spolupracovníkovi. Jsem rád, že mohu navrhnout, jak je zlepšit; co konkrétně považuje váš spolupracovník za matoucí nebo neintuitivní?

Nemůžete však potěšit každého. Můj osobní názor a názor většiny lidí, se kterými jsem na toto téma hovořil, je, že syntaxe porozumění dotazu je mnohem jasnější než ekvivalentní imperativní syntaxe. Očividně ne všichni souhlasí, ale naštěstí nevyžadujeme shodu všech milionů našich zákazníků, když děláme jazykový design.

Co se týče toho, co je „intuitivní“, připomněl jsem si příběh anglického lingvisty, který studoval mnoho různých jazyků, a nakonec jsem dospěl k závěru, že angličtina je nejlepší ze všech jazyků, protože v angličtině, slova přicházejí ve stejném pořadí, jak si je myslíte. Na rozdíl od francouzštiny, kde neustále říkají věci jako „pes bílý jí maso červené“. Jak těžké musí být pro Francouze přemýšlet slova v správných a poté je musíte říct v francouzském pořadí! Francouzština je tak neintuitivní! Je úžasné, že Francouzi to dokáží promluvit. A německy? kde si myslí, že „pes jí maso“, ale pak musí říci „pes maso jí“!?! Tak neintuitivní.

To, co je „intuitivní“, je často jen otázka důvěrnosti. Trvalo mi měsíce práce s LINQ, než jsem zastavil začátek dotazů s klauzulí „select“. Nyní je to druhá přirozenost a pořadí SQL se zdá být bizarní.

Což to je! Pravidla pro určování rozsahu jsou všechna zmatená v SQL. Možná byste chtěli upozornit svého spolupracovníka na to, že LINQ byl pečlivě navržen tak, aby (1) zavedení proměnných a rozsahů probíhalo zleva doprava (*) a (2) pořadí, ve kterém se dotaz objeví na stránce, je pořadí, ve kterém se provádí. To znamená, když říkáte

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

c se objeví v rozsahu vlevo a zůstává v rozsahu vpravo. A pořadí, ve kterém se věci dějí, jsou: první „zákazníci“ je vyhodnoceno. Poté se vyhodnotí „kde“ a filtruje se sekvence. Poté je filtrovaná sekvence promítnuta pomocí „select“.

SQL tuto vlastnost nemá. Pokud řeknete

SELECT Name FROM Customers WHERE City = 'London'

pak „Jméno“ je přivedeno do rozsahu něčím napravo, ne nalevo a dotaz je proveden v úplně zmateném pořadí; prostřední klauzule je vyhodnocena nejprve, potom poslední a poté první. To se mi teď zdá bláznivé a neintuitivní, protože jsem tak dlouho pracoval výhradně s LINQ.


(*) Pravidla pro určování rozsahu jsou v LINQ trochu podivná s klauzuly o spojení. Ale jiné než to, rozsahy pěkně hnízdí.

69
Eric Lippert

Stejně jako cokoli jiného v programovacím světě si musíte zvyknout na syntaxi a poté je (potenciálně) snadněji čitelný.

Stejně jako cokoli jiného v programovacím světě existuje potenciál pro špagetový kód nebo jiné zneužití.

Stejně jako cokoli jiného v programovacím světě, můžete to udělat tímto způsobem nebo jiným způsobem.

Stejně jako cokoli jiného v programovacím světě se může počet ujetých kilometrů lišit.

22
Wonko the Sane

Viděl jsem komentář/poznámku, kde uvedl něco - ve vztahu k LINQ/lambda - v řádcích: „Napište kód čitelný lidem, nikoli čitelný do vašeho počítače“.

Myslím si, že toto tvrzení má mnoho zásluh, ale zvažte vývojáře (jako jsem já), který prošel celou škálou vývojových jazyků od Shromáždění, přes procedurální, přes OO, přes řízené, využívající paralelní řešení s vysokou výkonností úlohy .

Sám jsem si oblíbil, aby byl můj kód co nejčitelnější a nejpoužívanější, a přijal mnoho zásad návrhu vzoru GOF, abych dodal systémy a služby kvality výroby v celé řadě různých obchodních odvětví.

Poprvé jsem se setkal s výrazem lambda, který jsem si pomyslel: „Co to k čertu je!?“ Okamžitě to bylo kontraintuitivní k mé známé (a tedy pohodlné) explicitní deklarativní syntaxi. Mladší <5yrs v práci kluci to však lapovali, jako by to byla manna z nebe!

Je to proto, že po celá léta se myšlení jako počítače (v syntaktickém smyslu) překládalo velmi snadno do přímé kódovací syntaxe (bez ohledu na jazyk). Když jste měli toto výpočetní myšlení po dobu asi 20 + let (v mém případě 30+), musíte ocenit, že počáteční syntaktický šok lambda výrazu lze snadno převést do strachu a nedůvěry.

Možná spolupracovník v OP přišel z podobného pozadí jako já (tj. Několikrát jsem byl kolem bloku) a bylo to v té době pro ně kontraintuitivní? Moje otázka zní: co jsi s tím udělal? Pokusili jste se přeškolit svého vrstevníka, aby pochopil výhody vložené syntaxe, nebo jste je pranýřovali/vystrašovali, že jste nebyli s programem? První z nich by pravděpodobně viděl, jak se váš spolupracovník přiblíží k vaší linii myšlení, druhý z nich by pravděpodobně donutil ještě více nedůvěřovat syntaxi LINQ/lambda a tak zhoršovat negativní názor.

Pro sebe jsem musel přeškolit svůj vlastní způsob myšlení (jak Eric klade výše, není to bezvýznamný posun mysli a já jsem musel programovat v Mirandě v 80. letech, takže jsem měl svůj podíl na funkčním programování) ale jakmile jsem prošel tou bolestí, výhody byly zřejmé, ale - a co je důležitější -, kde bylo její použití nad použité (tj. použito pro jeho použití) ), příliš složité a opakující se (s ohledem na princip DRY)).

Jako někdo, kdo nejen stále píše hodně kódu, ale také musí technicky hodně zkontrolovat mnoho kódu, bylo nezbytné, abych porozuměl těmto principům, abych mohl věci kontrolovat nestranně, radit, kde může být použití výrazu lambda efektivnější/čitelné, a také přimět vývojáře, aby zvážili čitelnost vysoce komplexních inline lambda výrazů (kde by volání metody - v těchto případech - učinilo kód lépe čitelným, udržovatelným a rozšiřitelným).

Takže když někdo říká, že „Nechápejte lambdu?“ nebo LINQ syntaxe, spíše než je označit jako luditele pokusit se jim pomoci pochopit základní principy. Koneckonců mohou mít „starou školu“ jako já.

6
CWC

Lambda Expressions vede k méně čitelnému kódu, pokud jsou dotazy příliš dlouhé. Je však mnohem lepší než příliš mnoho vnořené smyčky.

Je lepší s směs dvo.

Napište to do Lambdy, pokud je to rychlejší (potřebujete, aby bylo rychlé) nebo snáze čitelné.

4
Amir Rezaei

Myslím, že to ve většině případů (s výjimkou případů, kdy děláte něco velmi bizarního), záleží na tom, zda máte na mysli „čitelné“, protože někdo získává představu o tom, co se děje, nebo zda dokáže snadno najít všechny drobné detaily.

Myslím, že spojení pomáhá s první, ale často (zejména při ladění) bolí druhé.

IMHO, když se dívám na kód, jsem obeznámen s prvním, který je nesmírně důležitější než ten druhý, takže mi připadá mnohem čitelnější.

1
Bill

Syntaxe LINQ považuji za intuitivní a snadno čitelná, zejména proto, že na začátku vložili FROM, kde patří namísto uprostřed, jako v SQL. Ale IMO lambdy jsou matoucí a ztěžují čtení kódu.

1
Mason Wheeler

Souhlasím s vámi, že syntaxe Linq se významně neliší od T-SQL. Myslím, že váš spolupracovník by mohl mít námitky proti tomu, aby se relační věci smísily, v nichž jeho pěkný a lesklý kód OO). Na druhé straně funkční programování vyžaduje trochu zvyknutí a ochotu zvyknout si na to.

1
Larry Coleman

Záleží. T-SQL jednoznačně poskytuje některá relační řešení DB. LINQ jednoznačně poskytuje některá řešení OO).

Nicméně; "více matoucí než T-SQL?" - je diskutováno/položeno v počáteční otázce. To jasně znamená některé rysy, na které se žádná ze stávajících odpovědí nezabývá, namísto toho obviňuje (zjevně SQL známého) kritika, že v minulosti uvízl.

Takže ačkoliv LINQ oceňuji za určité vlastnosti a moc nesouhlasím s existujícími odpověďmi, cítím, že kontrapunkt si zaslouží reprezentaci:

Po letech, kdy jsem se seznámil s LINQ, stále provádím určité typy skupinových operací, vnější spojení a nerovnosti, práci s kompozitními klíči a další operace v LINQ. (Zejména při cílení na relační back-end s otázkami citlivými na výkon.)

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

Pokud si myslíte, že je to intuitivní, více síly pro vás. ;)

0
shannon