Na temat rozwijania głębokiej wiedzy z zakresu programowania

136

Czasami widzę pytania na temat przypadków skrajnych i innych dziwności w przepełnieniu stosu, na które z łatwością odpowiadają Jona Skeeta i Erica Lipperta, wykazując głęboką znajomość języka i jego wielu zawiłości, takich jak ten:

Możesz pomyśleć, że aby użyć foreachpętli, kolekcja, nad którą się iterujesz, musi zaimplementować IEnumerablelub IEnumerable<T>. Ale jak się okazuje, tak naprawdę nie jest to wymóg. Wymagane jest, aby typ kolekcji miał wywoływaną metodę publiczną GetEnumerator, i która musi zwracać jakiś typ, który ma wywoływany moduł pobierania właściwości publicznej Currenti metodę publiczną, MoveNextktóra zwraca a bool. Jeśli kompilator może stwierdzić, że wszystkie te wymagania są spełnione, generowany jest kod, aby użyć tych metod. Tylko jeśli te wymagania nie są spełnione, sprawdzamy, czy obiekt implementuje IEnumerablelub IEnumerable<T>.

To fajne rzeczy, które warto wiedzieć. Rozumiem, dlaczego Eric to wie; jest w zespole kompilatorów, więc musi wiedzieć. Ale co z tymi, którzy wykazują tak głęboką wiedzę, ale nie są poufnymi?

Jak zwykli śmiertelnicy (którzy nie należą do zespołu kompilatora C #) dowiadują się o takich rzeczach?

W szczególności, czy istnieją metody, których używają ci ludzie, aby systematycznie wykorzeniać taką wiedzę, eksplorować ją i internalizować (uczynić ją własną)?

Robert Harvey
źródło
10
Myślę, że jest to szczególnie tam, gdzie świeci oprogramowanie open source. Fajnie jest wejść do frameworka / systemu / bibliotek. Kiedyś pracowałem z Qt, miałem lepsze zrozumienie wewnętrznych elementów frameworka, niż kiedy pracowałem z WinForms.
Vitor Py
2
Kiedy chcesz poznać ten konkretny przykład, poza tym, że nie wyglądasz głupio przed specjalnym tłumem? Idiotowie to udowodnili. Poza tym seria Effective C #, Java, C ++ itp. Może zawierać fajne rzeczy. Blog Erica Lipperta jest również dobrym źródłem. Ogólnie rzecz biorąc, często nie wiemy, czego nie wiemy, tak jak mówią „żyj przez 100 lat, ucz się przez 100 lat i giń głupcem”.
Job
26
Czy warto? Jestem dwujęzyczny i staram się nauczyć kilku innych języków mówionych. Brałem udział w zajęciach z matematyki, ale nie było ich wystarczająco dużo. Chciałbym nauczyć się grać w tenisa pół przyzwoicie i nauczyć się pływać za pomocą motylkowego uderzenia. Chciałbym więcej podróżować. Chcę nauczyć się trochę Clojure. Nie chcę być ekspertem w jednym języku, mieć doktorat z matematyki, spędzać 30 godzin tygodniowo w basenie takim jak Michael Phelps itp. Wiedza Lipperta i Skeeta wynika z faktu, że włożyli wiele wysiłek związany z jedną (lub kilkoma) rzeczami, jednocześnie tracąc inne doświadczenia. Może zmienić pracę?
Job
10
„Rozumiem, dlaczego Eric to wie; jest członkiem zespołu kompilatorów, więc musi wiedzieć”. - są szanse, że on to wie, ponieważ wymyślił to w pierwszej kolejności . Wątpię, żeby musiał „dowiedzieć się”, że tak to działa :)
Alex ten Brink
10
@Alex: Właściwie pracowałem tylko nad C #, odkąd zaczęliśmy budować implementację C # 3. Specyfikacja „foreach” została napisana ponad sześć lat wcześniej. Nadal codziennie dowiaduję się szalonych historycznych rzeczy o języku. Na przykład dowiedziałem się dzisiaj, że dla delegatów ((A + B) + C) - (A + C) = A + B + C, ale ((A + B) + C) - (B + C) = A . Dziwne!
Eric Lippert,

Odpowiedzi:

167

Po pierwsze, dzięki za miłe słowa.

Jeśli chcesz uzyskać dogłębną znajomość C #, niewątpliwie zaletą jest posiadanie specyfikacji języka, dziesięciu lat notatek projektowych, kodu źródłowego, bazy danych błędów oraz Andersa, Madsa, Scotta i Petera. Z pewnością mam szczęście, nie ma co do tego wątpliwości.

Jednak nawet bez tych zalet nadal można uzyskać głęboką wiedzę na ten temat.

Kiedy zaczynałem w firmie Microsoft, pracowałem nad interpretatorem JScript dostarczanym z programem Internet Explorer 3. Mój menedżer w tym czasie powiedział mi coś, co było jedną z najlepszych rad, jakie kiedykolwiek otrzymałem. Powiedział, że chce, abym został uznanym ekspertem w Microsoft w zakresie składni i semantyki języka JScript, i że powinienem zająć się tym, szukając pytań na temat tych aspektów JScript i odpowiadając na nie. W szczególności odpowiadanie na pytania, na które nie znałem odpowiedzi, ponieważ to są te, z których chciałbym się uczyć.

Oczywiście StackOverflow i inne publiczne fora pytań i odpowiedzi są jak picie z węża strażackiego dla tego rodzaju rzeczy. Wówczas czytałem religijnie comp.lang.javascript i nasze wewnętrzne fora Microsoft „JS User” i postępowałem zgodnie z radą mojego menedżera: kiedy zobaczyłem pytanie dotyczące semantyki języka, na które nie znałem odpowiedzi, zrobiłem to mój interes, aby się dowiedzieć.

Jeśli chcesz wykonać „głębokie nurkowanie”, musisz ostrożnie wybrać. Do dziś jestem niesamowicie nieświadomy działania modelu obiektowego przeglądarki. Ponieważ w ostatnich latach koncentrowałem się na zostaniu ekspertem w języku C #, jestem niesamowicie nieświadomy, jak działają różne klasy w bibliotekach klas podstawowych. Mam szczęście, że mam pracę, która nagradza konkretną głęboką wiedzę; jeśli twoja praca lub twoje talenty są bardziej zgodne z byciem generalistą, pójście głęboko może nie działać dla ciebie.

Bardzo pomocne jest również pisanie bloga; wymagając ode mnie wyjaśniania innym skomplikowanych tematów, jestem zmuszony przez cały czas stawić czoła własnemu niedostatecznemu zrozumieniu różnych tematów.

Eric Lippert
źródło
14
Nie chcę przeciągać tego tematu, ale po przeczytaniu tej odpowiedzi jestem ciekawy, dlaczego nie zadałeś żadnych pytań tutaj ani na temat przepełnienia stosu. Czy w tym momencie Twoi koledzy, blog itp. Są dla Ciebie wystarczające? Czy są lepsze zasoby niż SO, o których powinniśmy wiedzieć?
Matthew Przeczytał
6
Być może źle zrozumiałeś, co mówi. Wbrew intuicji, nie zadawał pytań, aby się czegoś nauczyć, odpowiadał na pytania.
jhocking
65

Będąc po stronie „guru” raz lub dwa, mogę ci powiedzieć, że często to, co postrzegasz jako „głęboką znajomość” języka lub systemu programowania, jest często wynikiem „guru”, który ostatnio walczył o miesiąc, aby rozwiązać dokładnie ten sam problem. Jest to szczególnie prawdziwe na forum, na którym ludzie mogą wybrać pytania, na które odpowiedzą. Nawet tacy jak Jon Skeet i Eric Lippert musieli w pewnym momencie nauczyć się cześć. Zdobywają wiedzę jedną koncepcję na raz, tak samo jak wszyscy inni.

Karl Bielefeldt
źródło
1
To bardzo dobra uwaga. Często podejmując długie okresy badań często znajduję pytania, na które mogę teraz odpowiedzieć z powodu rzeczy, których nauczyłem się wcześniej tego samego dnia.
Matthew Przeczytał
47

Parafrazując jogina bhadżana:

„Jeśli chcesz się czegoś nauczyć, przeczytaj o tym; jeśli chcesz coś zrozumieć, napisz o tym; jeśli chcesz coś opanować, zaprogramuj to”.

Programowanie jest jak największe wyzwanie dydaktyczne. Nauczenie komputera zrobienia czegoś wymaga, abyś naprawdę dobrze znał swoje umiejętności - lub nauczysz się je opanowywać.

Na przykład, jeśli chcesz nauczyć się fizyki, napisz silnik fizyki. Jeśli chcesz nauczyć się szachów, zaprogramuj grę w szachy. Jeśli chcesz nauczyć się głębokiej wiedzy w języku C #, napisz kompilator C # (lub inne narzędzie).

Maglob
źródło
2
Programowanie jest także skromną próbą pisania (oczywiście do przeczytania przez ludzi) w najbardziej jednoznaczny sposób.
vpit3833,
4
Ten cytat zabrzmiał naprawdę głęboko, dopóki nie przeczytałem przykładu szachowego. Niestety zaprogramowanie szachowej sztucznej inteligencji nie uczyni cię lepszym szachistą (jest to po prostu wyszukiwanie w drzewie Min-Max). Nadal +1
bughi
1
@bughi Może uda Ci się opanować zasady: D
Julio Rodrigues
@bughi, „program it” to bardzo szeroki termin, nie zawsze związany z pisaniem kodu !! Pomyśl tylko trochę po wyjęciu z pudełka.
Nitesh Verma
25

O ile mi wiadomo, sposobami na nauczenie się tego są:

  • Przeczytaj o tym od kogoś takiego jak Eric Lippert
  • Doświadcz, a następnie rozwiąż problemy z pierwszej ręki.

Drugi sposób może potrwać znacznie dłużej, ale prawdopodobnie doprowadzi do głębszego zrozumienia (ale nie zawsze).

FrustratedWithFormsDesigner
źródło
17
Lub obydwa. [15 znaków]
Michael K
23

Powiedziałbym:

Po nauczeniu się stosunkowo przydatnego zestawu języków (tych, których potrzebujesz do prawdziwej pracy) na poziomie, na którym możesz wykonywać najczęstsze zadania, przestań uczyć się więcej języków, dopóki nie przestudiujesz przynajmniej jednego dogłębnie. Moim zdaniem część problemu w naszej branży polega na tym, że ludzie uczą się pierwszych 5-10% języka, zanim przejdą do innego języka. Gdy będziesz już w stanie wykonywać najczęstsze zadania w pracy, zacznij od głębszej analizy jednego. (Możesz wrócić do poszerzania się po osiągnięciu pewnej głębokości, a następnie poruszać się między nimi.)

Zgłaszaj się na bardziej złożone, trudniejsze zadania, które zmuszają cię do dokładnego rozwiązania problemów. Jeśli nie ma tam, gdzie pracujesz, poszukaj zadań do wykonania na licencji open source lub rozpocznij pracę nad osobistym projektem, który sprawi, że będziesz musiał przejść dogłębnie. Jeśli Twoja praca nie ma interesujących problemów, zastanów się, czy nie znaleźć bardziej wymagającej pracy.

Przeczytaj zaawansowane książki w jednym języku (na przykład w przypadku SQl Server, będzie to obejmowało czytanie o dostrajaniu wydajności i wewnętrznych elementach bazy danych) zamiast uczenia się X za 30 dni.

Przeczytaj interesujące pytania tutaj i inne miejsca, w których są zadawane, i spróbuj rozwiązać je samodzielnie. Jeśli chcesz się uczyć, spróbuj rozwiązać niektóre bez wcześniejszego przeczytania innych odpowiedzi. Nawet jeśli pytanie już zostało udzielone, dowiesz się więcej, jeśli sam znajdziesz odpowiedź. Możesz nawet znaleźć lepszą odpowiedź niż ta, na którą było pytanie.

Zadaj kilka trudniejszych pytań. Oceń odpowiedzi, które otrzymałeś, a nie tylko ich używaj. Upewnij się, że rozumiesz, dlaczego odpowiedź zadziała lub nie. Wykorzystaj te odpowiedzi jako miejsce rozpoczęcia badań.

Znajdź dobre blogi techniczne od znanych ekspertów w tej dziedzinie i przeczytaj je.

Przestańcie wyrzucać swoją wiedzę po jej zakończeniu. Naucz się zachować. Większość ekspertów nie musi szukać wspólnej składni. Nie muszą wymyślać koła za każdym razem, gdy napotykają problem, ponieważ pamiętają, jak wcześniej podeszli do podobnego problemu. Mogą połączyć kropki i zobaczyć, jak problem X, który zrobili dwa lata temu, jest podobny do problemu Y, który mają teraz (zadziwia mnie, jak niewiele osób wydaje się w stanie tworzyć takie połączenia). Dzięki temu mają więcej czasu na badania bardziej interesujących tematów.

HLGEM
źródło
Dobra odpowiedź. Ale zastanawiam się, jak mogę lepiej zachować wiedzę i połączyć kropki?
Radzę zanotować wszystko, czego się nauczysz. Zacząłem to robić w Evernote i przez kilka lat odkryłem, że mogę żyć z moich notatek. Powoli doszedłem do momentu, w którym moje notatki można przerobić na prezentacje, które jestem gotów przedstawić w mgnieniu oka.
Shivasubramanian A
9

Można zacząć od głęboko przestudiowaniu specyfikacji językowych tych, które starają się być ekspertem off. Na przykład:

Marcelo
źródło
3
Dobra odpowiedź - na przykład sekcja 15.8.4 powiązanej specyfikacji C # obejmuje implementację foreachzachowania opisanego w cytowanym poście na blogu autorstwa Erica Lipperta. Jeśli ktoś kiedykolwiek znajdzie się myśli coś w stylu „Zastanawiam się, jak foreach naprawdę działa ..” to byłoby dobrym miejscem do rozpoczęcia poszukiwań.
Carson63000,
6

Zdobądź Reflector lub inny dekompilator (ponieważ teraz płaci) i zacznij otwierać niektóre z najczęściej używanych bibliotek .NET, aby dowiedzieć się, jak działają elementy wewnętrzne. W połączeniu z książką taką jak CLR przez C # dostaniesz się dość głęboko (głębiej niż większość z nas pójdzie do swojej zwykłej pracy).

Bart
źródło
5
Zrobiłem to z BitConverterklasami i odkryłem IsLittleEndianflagę specyficzną dla systemu.
Robert Harvey
LOL. +1 dla isLittleEndian
Rudy
4

Tę wiedzę rozwinąłem w C ++, spędzając comp.lang.c++.moderatedtam kilka lat, chociaż tak naprawdę nie pracowałem tak ciężko, aby w niej napisać kod. Nie jestem jednak pewien, jak guru mogę powiedzieć, że jestem.

Myślę, że istnieją dwa rodzaje wiedzy na temat języka programowania:

  1. Znajomość ciekawostek dotyczących języka i umiejętność unikania pułapek.
  2. Umiejętność skutecznego rozwiązywania problemów.

Numer 2 można osiągnąć tylko przez programowanie w języku i przyglądanie się kodowi innych osób, ale numer 1 można osiągnąć, poświęcając dużo czasu na czytanie o języku na forach dyskusyjnych, sprawdzając, jakie pytania zadają ludzie i jakie odpowiedzi są. StackOverflow to również dobre miejsce do tego.

Ken Bloom
źródło
4

Głęboka wiedza i wiedza programistyczna oznaczają wygodę na wszystkich poziomach abstrakcji. To znaczy

  • biblioteki i interfejsy API
  • semantyka języka
  • optymalizacje kompilatora
  • elementy wewnętrzne kompilatora i generowanie kodu
  • zachowanie środowiska wykonawczego i modułu wyrzucania elementów bezużytecznych
  • problemy związane z architekturą i zestawem instrukcji

Wszystko, co widziałem w ciągu ostatnich 15 lat, pokazało, że tylko jeśli naprawdę możesz dostać się do kompilatora i środowiska uruchomieniowego, masz szansę na głęboką biegłość. Być może będziesz musiał zmusić się do zrobienia kroku i rozpoczęcia rozumowania (i budowania) oprogramowania na kolejnym poziomie abstrakcji niżej na stosie , ale jest to jedyny sposób na ekspertyzę.

Wszystko, co mamy, to język abstrakcji. Musisz zrozumieć, w jaki sposób języki programowania są projektowane i budowane, aby naprawdę wiedzieć, co robi maszyna.

Don Stewart
źródło
3

Przeczytaj dokładny podręcznik Nie jest to szczególnie głęboka wiedza. Jest opublikowany w sekcji 8.6.4 specyfikacji języka C # . Powinieneś mieć zwyczaj przynajmniej przeszukiwania specyfikacji dla używanych języków, a także przeszukiwania dokumentacji dla wszystkich wbudowanych bibliotek.

W każdym razie, to nie jest mój pomysł na głęboką wiedzę; to tylko nieciekawy szczegół implementacyjny. Może być bardziej interesujące, jeśli projektant wyjaśni, dlaczego zostało to zrobione w bardziej dynamiczny sposób, zamiast po prostu sprawdzić, czy obiekt implementuje Iterable.

Kevin Cline
źródło
1
Nie sądzę, że istnieje coś takiego jak „przeglądanie” specyfikacji języka C #.
Robert Harvey
@RobertHarvey: możesz przejrzeć większość formalnego języka obejmującego rzeczy, które już znasz, takie jak pierwszeństwo operatora i składnia deklaracji, i skupić się na nieoczekiwanych, ale użytecznych szczegółach, takich jak dokładne zachowanie konstruktorów C # foreach lub Java enum.
kevin cline
Możesz kupić wersję standardu z adnotacjami. To jest trochę przestarzałe, ale komentarze są nadal bardzo interesujące dla części języka, które są objęte.
Jørgen Fogh