Rozmawiam ze współpracownikiem na temat Linq, skopiuję tutaj:
Współpracownik: Bądźmy szczerzy tutaj. Składnia Linq jest do bani. Jest to mylące i nieintuicyjne.
Ja: och, daj spokój, bardziej zagmatwany niż T-SQL?
Współpracownik: tak.
Ja: ma te same podstawowe części, wybierz, gdzie i skąd
Współpracownik: Linq jest dla mnie draństwem relacji + OO. Współpracownik: Nie zrozum mnie źle - jest niewiarygodnie potężny, ale zmienili przeznaczenie SQL na wykorzystanie kolekcji obiektów.
Uważam, że używanie Linq + Lamdy jest bardzo wydajne (zgadza się), a także ułatwia czytanie kodu (nie zgadza się w tej kwestii):
pickFiles = from f in pickFolder.GetFiles("*.txt")
where ValidAuditFileName.IsMatch(f.Name)
select f;
lub
var existing = from s in ActiveRecordLinq.AsQueryable<ScannedEntity>()
where s.FileName == f.FullName && s.DocumentType != "Unknown"
select s;
lub (tutaj kod VB)
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
Dla mnie jest to czyste i łatwe (przynajmniej łatwiejsze niż alternatywy) do przeczytania, jakie są twoje opinie na ten temat?
źródło
Odpowiedzi:
Nie mogę już znaleźć właściwego postu, ale Eric Lippert (i być może kilka innych dodatków) kilkakrotnie wypowiadał się na temat deklaratywności Linq , co w przypadku kilku klas problemów jest znacznie bardziej intuicyjne niż składnia imperatywna .
Linq umożliwia pisanie kodu, który wyraża zamiar , a nie mechanizm .
Powiedz mi, co jest łatwiejsze do odczytania. To:
Albo to?
A może nawet to?
Pierwszy przykład to po prostu garść bezsensownych bojlerów, aby uzyskać najprostsze wyniki. Każdy, kto uważa, że jest bardziej czytelny niż wersje Linq, musi zbadać jego głowę. Nie tylko to, ale pierwsze marnuje pamięć. Nie możesz nawet napisać tego używając
yield return
sortowania.Twój współpracownik może powiedzieć, co chce; osobiście uważam, że Linq niezmiernie poprawił moją czytelność kodu.
W Linq też nie ma nic „relacyjnego”. Może mieć pewne powierzchowne podobieństwa do SQL, ale nie próbuje w żadnym kształcie ani formie zaimplementować rachunku relacyjnego. To tylko kilka rozszerzeń, które ułatwiają wyszukiwanie i wyświetlanie sekwencji. „Zapytanie” nie oznacza „relacyjnego”, a w rzeczywistości istnieje kilka nierelacyjnych baz danych, które wykorzystują składnię podobną do SQL. Linq jest zorientowany czysto obiektowo, po prostu zdarza się, że współpracuje z relacyjnymi bazami danych poprzez frameworki, takie jak Linq do SQL, z powodu niektórych drzewek wyrażeń voodoo i sprytnego projektu zespołu C #, dzięki czemu anonimowe funkcje można w sposób niejawny przekształcać w drzewa wyrażeń.
źródło
Linq is purely object-oriented
+1 za to. Z tego powodu nasz przewodnik po stylu zespołu wymusza stosowanie płynnej składni zamiast składni zapytania. Uważam, że sprawia to, że charakter linku OO jest bardziej oczywisty dla kogoś, kto sprzeciwia się notacji w językach podobnych do C.GetVipCustomers()
, co, jak sama nazwa wskazuje, zwraca kolekcję klientów VIP, w dowolnej kolejności. W rzadkich przypadkach, w których ważna jest kolejność, takich jak wyświetlanie na ekranie, niech dzwoniący posortuje kolekcję.Z tą krytyką nie można się kłócić. Dla twojego współpracownika jest do bani . Nie udało się zaprojektować składni, która byłaby dla nich jasna i intuicyjna. To nasza wina i możesz przekazać moje przeprosiny swojemu współpracownikowi. Cieszę się, że mogę zasugerować, jak to zrobić lepiej; co konkretnie twój współpracownik uważa za mylące lub nieintuicyjne?
Jednak nie możesz zadowolić wszystkich. Moja osobista opinia oraz opinia większości osób, z którymi rozmawiałem na ten temat, jest taka, że składnia rozumienia zapytania jest znacznie bardziej przejrzysta niż równoważna składnia imperatywna. Oczywiście nie wszyscy się z tym zgadzają, ale na szczęście nie wymagamy konsensusu od wszystkich milionów naszych klientów, gdy projektujemy język.
Na temat tego, co jest „intuicyjne”, przypomina mi się historia angielskiego lingwisty, który studiował wiele różnych języków i ostatecznie stwierdził, że angielski jest najlepszy ze wszystkich języków, ponieważ w języku angielskim słowa są w tej samej kolejności, w jakiej pomyśl im . W przeciwieństwie do francuskiego, gdzie ciągle mówią takie rzeczy, jak: „biały pies zjada mięso czerwone”. Jak trudno musi Francuzom myśleć słowa we właściwej kolejności, a następnie wymawiać je w kolejności francuskiej ! Francuski jest taki nieintuicyjny! To niesamowite, że Francuzom się to mówi. A niemiecki? gdzie myślą, że „pies je mięso”, a potem muszą powiedzieć „pies je mięso”!?!
Często to, co jest „intuicyjne”, jest jedynie kwestią znajomości. Zajęło mi miesiące pracy z LINQ, zanim przestałem zaczynać zapytania z klauzulą „select”. Teraz jest to druga natura, a kolejność SQL wydaje się dziwna.
Który to jest! Reguły określania zakresu są pomieszane w SQL. Warto zwrócić uwagę współpracownikowi na to, że LINQ został starannie zaprojektowany, aby (1) wprowadzenie zmiennych i zakresów odbywało się od lewej do prawej (*), oraz (2) kolejność, w jakiej zapytanie pojawia się na stronie: kolejność, w jakiej jest wykonywana. To znaczy, kiedy mówisz
c pojawia się w zakresie po lewej stronie i pozostaje w zakresie przez prawo. Kolejność, w jakiej się to dzieje, jest następująca: najpierw oceniani są „klienci”. Następnie oceniane jest „gdzie” w celu przefiltrowania sekwencji. Następnie filtrowana sekwencja jest rzutowana przez „select”.
SQL nie ma tej właściwości. Jeśli powiesz
następnie „Nazwa” jest wprowadzana w zakres przez coś po prawej, a nie po lewej, a zapytanie jest wykonywane w całkowicie pomieszanej kolejności; środkowa klauzula jest oceniana jako pierwsza, potem ostatnia, a następnie pierwsza. To wydaje mi się teraz szalone i nieintuicyjne, ponieważ tak długo pracowałem wyłącznie z LINQ.
(*) Reguły określania zakresu są trochę dziwne w LINQ z klauzulami łączenia. Ale poza tym lunety ładnie się zagnieżdżają.
źródło
c.
wpisania IDE zna już typc
i może dać ci IntelliSense. W LINQ mówisz „od c u klientów, gdzie c.” i bum, IntelliSense pomaga ci, wymieniając członkówCustomer
. W SQL, gdy wpiszesz „WYBIERZ nazwę od klientów”, nie możesz uzyskać żadnej pomocy IDE, aby powiedzieć, że „nazwa” jest dobrym wyborem, ponieważ pisałeśname
wcześniejcustomers
.Jak wszystko inne w świecie programowania, musisz przyzwyczaić się do składni, a wtedy jest (potencjalnie) łatwiejszy do odczytania.
Jak wszystko inne w świecie programowania, istnieje możliwość wystąpienia kodu spaghetti lub innych nadużyć.
Jak wszystko inne w świecie programowania, możesz to zrobić w ten lub inny sposób.
Jak wszystko inne w świecie programowania, przebieg może się różnić.
źródło
Widziałem komentarz / uwagę, w której coś mówiło - w odniesieniu do LINQ / lambda - w następujący sposób: „Napisz kod czytelny dla ludzi, a nie dla twojego komputera”.
Myślę, że to stwierdzenie ma wiele zalet, jednak weź pod uwagę programistę (takiego jak ja), który przeszedł całą gamę języków programowania od montażu, poprzez procedury, przez OO, poprzez zarządzanie, poprzez wykorzystanie rozwiązań o wysokiej przepustowości równoległych zadań .
Szczyciłem się tym, że mój kod jest tak czytelny i jak to możliwe, że można go ponownie wykorzystać, i że zastosowałem wiele zasad wzornictwa projektowego GOF w celu dostarczenia systemów i usług jakości produkcji w wielu różnych sektorach biznesowych.
Gdy pierwszy raz spotkałem wyrażenie lambda, pomyślałem: „Co to do diabła jest!?!” Było to natychmiast sprzeczne z intuicją w stosunku do mojej znanej (i dlatego wygodnej) wyraźnej składni deklaratywnej. Młodsi w wieku <5 lat w pracy chłopaki jednak to zrobili, jakby to była manna z nieba!
Dzieje się tak dlatego, że przez lata myślenie jak komputer (w sensie syntaktycznym) bardzo łatwo przekładało się na składnię kodowania bezpośredniego (niezależnie od języka). Kiedy masz już obliczeniowy sposób myślenia przez około 20 lat (w moim przypadku 30+), musisz docenić, że początkowy szok syntaktyczny wyrażenia lambda może łatwo przełożyć się na strach i nieufność.
Może współpracownik w PO pochodził z podobnego środowiska jak ja (tj. Był kilka razy w okolicy) i było to dla nich sprzeczne z intuicją? Moje pytanie brzmi: co zrobiłeś z tym? Czy próbowałeś ponownie wyedukować rówieśnika, aby rozumiał korzyści płynące ze składni wbudowanej, czy też pręgowałeś go / krytykowaliście za to, że „nie byli w programie”? Ten pierwszy prawdopodobnie widziałby, jak twój współpracownik podszedł do twojego sposobu myślenia, ten drugi prawdopodobnie spowodowałby, że jeszcze bardziej nie ufają składni LINQ / lambda, a tym samym pogarszają negatywną opinię.
Dla siebie musiałem ponownie wyedukować swój sposób myślenia (jak mówi Eric powyżej, nie jest to nieznaczna zmiana umysłu i musiałem programować w Mirandzie w latach 80., więc miałem swój udział w funkcjonalnym programowaniu) ale kiedy już przeszedłem przez ten ból, korzyści były oczywiste, ale - co ważniejsze - tam, gdzie jego użycie zostało nadmiernie wykorzystane (tj. użyte w celu użycia go), ponad złożone i powtarzalne (biorąc pod uwagę zasadę DRY w tym przypadku).
Ponieważ ktoś, kto nie tylko nadal pisze dużo kodu, ale również musi dokonać przeglądu technicznego dużo kodu, konieczne było zrozumienie tych zasad, aby móc bezstronnie przeglądać elementy, doradzając, gdzie użycie wyrażenia lambda może być bardziej wydajne / czytelny, a także zachęcić programistów do rozważenia czytelności bardzo złożonych wbudowanych wyrażeń lambda (w których wywołanie metody - w takich przypadkach - uczyniłoby kod bardziej czytelnym, łatwym do utrzymania i rozszerzalnym).
Więc kiedy ktoś mówi, że „nie dostaje lambda?” lub składnia LINQ, zamiast nazywać je luddysem, próbując pomóc im zrozumieć podstawowe zasady. Mogą przecież mieć „oldskulowe” pochodzenie, takie jak ja.
źródło
Wyrażenia lambda prowadzą do mniej czytelnego kodu, jeśli zapytania są zbyt długie. Jest to jednak znacznie lepsze niż zbyt wiele zagnieżdżonych pętli .
Lepiej jest z mieszanką tych dwóch .
Napisz w Lambda, jeśli jest szybszy (potrzebujesz, żeby był szybki) lub łatwiejszy do odczytania.
źródło
Myślę, że w większości przypadków (z wyjątkiem robienia czegoś bardzo dziwnego) zależy od tego, czy masz na myśli „czytelny” jako ktoś, kto ma pojęcie o tym, co się dzieje, czy też może z łatwością znaleźć wszystkie małe drobne szczegóły.
Myślę, że link pomaga w tym pierwszym, ale często (szczególnie podczas debugowania) boli ten drugi.
IMHO, kiedy patrzę na kod, nie jestem zaznajomiony z tym pierwszym, jest znacznie ważniejszy niż drugi, więc uważam, że jest on znacznie bardziej czytelny.
źródło
where e.FirstName == "John"
i tłumaczy je na zapytanie SQL! Robi to, patrząc na nieskompilowane (ale parsowane) wyrażenie, widząc, że jest to porównanie właściwości wywoływanejFirstName
przez utrwalony byt, i to w porównaniu do łańcucha itp. Wiele się dzieje.Uważam, że składnia LINQ jest intuicyjna i łatwa do odczytania, zwłaszcza, że umieszczają FROM na początku tam, gdzie należy zamiast na środku, jak w SQL. Ale lambda IMO są mylące i utrudniają odczytanie kodu.
źródło
\x -> x * x
) czy F # (fun x -> x * x
)?Zgadzam się z Tobą, że składnia Linq nie różni się znacząco od T-SQL. Myślę, że twój współpracownik może naprawdę sprzeciwić się mieszaniu relacji, w których jego ładny i błyszczący kod OO. Z drugiej strony programowanie funkcjonalne wymaga trochę przyzwyczajenia się i chęci przyzwyczajenia się do niego.
źródło
To zależy. Oczywiście T-SQL w unikalny sposób zapewnia rozwiązania oparte na DB. Oczywiście LINQ wyjątkowo oferuje niektóre rozwiązania OO.
Jednak; „bardziej mylące niż T-SQL?” - jest omawiany / zadawany w pytaniu wstępnym. Wyraźnie implikuje to pewne funkcje, których żadna z istniejących odpowiedzi nie rozwiązuje, zamiast tego oskarża (oczywiście znającego SQL) krytyka, że utknął w przeszłości.
Chociaż doceniam LINQ za pewne cechy i nie bardzo nie zgadzam się z istniejącymi tutaj odpowiedziami, czuję, że kontrapunkt zasługuje na reprezentację:
Wiele lat po zapoznaniu się z LINQ, wykonywanie pewnych rodzajów operacji grupowych, sprzężeń zewnętrznych i innych niż equijoins, praca z kluczami kompozytowymi i inne operacje w LINQ wciąż powodują, że mam zawroty głowy. (Zwłaszcza, gdy celem jest relacyjny back-end z pytaniami wrażliwymi na wydajność).
Jeśli uważasz, że to intuicyjne, masz więcej mocy. ;)
źródło
Prawdopodobnie jest powód, dla którego Linq jest do bani, po prostu spróbuj tworzyć przykłady z prawdziwego świata, zamiast tych przykładów z podręcznika.
spróbuj pokazać tę funkcję w linqlamdathings, a zobaczysz, że całe piękno zniknęło, a klasyczny sposób pozostaje czytelny. Nie wspominając o odroczonych problemach z wykonaniem i ustawianiu punktów przerwania.
Prawda jest taka, że LinqLambdaThings są bardzo przydatne w kilku przypadkach i nie uważa się, że zastępują one wszystkie zręczne obiekty, których nigdy nie rozumieliście
źródło
source.Where(c => c.IsVip && c.FirstName == "Aaron" || c.SecondName == "Aaron").Take(maxCount).OrderBy(d => d.LastName);
trudno jest je odczytać, więc mogłem się pomylić;)