Czy kompilowanie kodu w trakcie pracy jest korzystne?

183

Niedawno odbyłem rozmowę o pracę, podczas której dali mi godzinę na napisanie prawdziwego kodu. To nie była wielka ilość, prawdopodobnie mniej niż 100 linii. Po około 45 minutach skompilowałem, uruchomiłem i uruchomiłem. Być może spędziłem 5-10 minut na opracowywaniu błędów kompilacji i kilku drobnych błędów, ale ogólnie było bardzo płynnie. (Nawiasem mówiąc, dostałem od nich ofertę.)

Zaskoczyło mnie jednak to, że po przekazaniu wypełnionego kodu ankieter powiedział mi, że jedyne, co zrobiłem źle, to „nie kompilacja podczas pracy”. Zapytałem go, na czym polega różnica, a on odpowiedział: „co byś zrobił, gdybyś ukończył kod, który nie skompilował się w czasie”.

W moim rozumieniu jest to niepoprawny argument, ponieważ „uzyskanie kodu do kompilacji” dla danej długości kodu zazwyczaj wymaga naprawy stałej liczby błędów kompilacji i zajmuje dość stałą ilość czasu, co powinno być takie samo, niezależnie od tego, czy zrobisz to po tobie zakończ pisanie kodu lub jeśli przeplatasz go czasem kodowania. Jeśli już, przeszkadzanie w kodowaniu w poszukiwaniu brakujących średników prawdopodobnie wpłynie negatywnie na wydajność. Z wyjątkiem ekstremalnych okoliczności, gdy eksperymentuję z niejasnościami na krawędziach takich rzeczy, jak funkcje wirtualne w klasach pochodnych itp., Rozsądne wydaje się oczekiwanie, że kod napisany przez doświadczonego programistę się skompiluje, pomijając od czasu do czasu błąd pisania, a nawet jeśli nie, to „

W innym podobnym incydencie otrzymałem niepełną bazę kodów w wywiadzie i poprosiłem o jej zakończenie i wprowadzenie niezbędnych modyfikacji, aby uruchomić. Zacząłem od przeczytania istniejącego kodu, a następnie po kilku minutach (nawet zanim skończyłem przeglądać kod), ankieter powiedział mi, że to wystarczy. Kiedy zapytałem go, co by zrobił (tj. „Co zrobiłem źle”), powiedział mi, że zacząłby od natychmiastowego skompilowania kodu.

Dlaczego to w ogóle ma znaczenie? Moim zdaniem i z mojego doświadczenia, to, czy kompilacja fragmentu kodu jest zasadniczo losowa, wiąże się z takimi rzeczami, jak to, czy brakuje średników, i ma niewiele wspólnego z poprawnością podstawowego programu. (Dla mnie skupianie się na kompilacji jest jak przeprowadzanie artykułu przez sprawdzanie pisowni bez korekty w celu sprawdzenia gramatyki.)

Jeśli podasz mi niekompletny kod, pierwszą rzeczą, którą zrobię, będzie jego przeczytanie. Nie będę nawet próbował go skompilować, dopóki nie będę wiedział, co robi kod i nie będę wiedział, że algorytm jest poprawny.

W każdym razie, to tylko kilka ostatnich incydentów, ale ogólnie słyszałem, że wielu programistów mówi o kompilowaniu swojego kodu w miarę ich rozwoju, a jednak nikt nie był w stanie powiedzieć mi o korzyściach płynących z tego. Rozumiem korzyści płynące z testowania kodu podczas pracy, ale po co kompilować?

Więc moje pytanie brzmi: czy coś mi umknęło? Czy kompilacja w trakcie pracy jest rzeczywiście korzystna? Czy jest to jakiś mit propagowany przez społeczność programistów, że należy często kompilować kod?

CaptainCodeman
źródło
54
Albo to, albo że moje nawyki nazywane są złymi nawykami przez ludzi o różnych nawykach.
CaptainCodeman
9
@DocBrown Porównanie jest ważne, jeśli celem końcowym jest posiadanie właściwego produktu. Program, który „uruchamia się”, nie jest lepszy od programu, który działa nieprawidłowo. Nie możesz oczekiwać, że kompilacja sprawdzi Twój kod za Ciebie bardziej niż możesz się spodziewać sprawdzania pisowni, aby naprawić błędy gramatyczne.
CaptainCodeman
7
To, czy kompilacja zakłóca przebieg pracy, jest bardzo subiektywne i zależy od języka, środowiska kompilacji, rozmiaru / złożoności projektu itp. IMO może stanowić problem w przypadku dużych projektów.
pjc50
64
W pełni zgadzam się z PO. Nie rozumiem, jak ktoś może oceniać nawyki pracy, np. Kiedy używa on / ona do uruchomienia kompilatora. Liczy się tylko wysiłek. Czy to jest poprawne? Czy można to utrzymać? Czy działa w oczekiwanym czasie? Ile czasu zajęło jego wdrożenie? To są interesujące pytania. Wszystko inne jest arbitralne BS. Jeśli rozmówca napisze 2-godzinny idealny kod, który kompiluje się przy pierwszej próbie, to gdzie jest problem? Tylko dlatego, że osoba przeprowadzająca wywiad robi to inaczej? Moja bogini.
JensG
9
Należy również wspomnieć, że w przypadku niektórych języków i IDE (Java / [Eclipse | NetBeans | etc], C # / Visual Studio, ...), IDE jest już kompilacji wszystko w tle w czasie rzeczywistym, podczas pisania, w efekt daje natychmiastową informację zwrotną, czy popełniłeś błąd. Można by mieć nadzieję, że programiści IDE przeprowadzili badania popierające to podejście kompilacji w miarę użytkowania.
Ogre Psalm33

Odpowiedzi:

223

Czy kompilacja w trakcie pracy jest rzeczywiście korzystna?

Jest. Zapewnia krótszą pętlę sprzężenia zwrotnego - co na ogół podczas projektowania (interfejs użytkownika, oprogramowanie do pisania, projektowanie wizualne itp.) Jest dobrą rzeczą.

Krótka pętla sprzężenia zwrotnego oznacza, że ​​możesz szybko naprawić błędy wcześniej, zanim staną się one droższe.

Aby pożyczyć swój przykład, powiedz, że kodujesz w języku podobnym do C i zapomniałeś }gdzieś w środku programu.

Jeśli kompilujesz zaraz po zakończeniu pisania instrukcji, możesz być całkiem pewien, że właśnie wprowadziłeś błąd kompilacji i możesz go naprawić w ciągu kilku sekund.

Jeśli jednak tego nie zrobisz, będziesz musiał spędzić dużo czasu na czytaniu kodu, szukając dokładnej pozycji }i upewniając się, że po zlokalizowaniu błędu poprawka jest rzeczywiście zamierzona. Odbyłoby się to chwilę po tym, jak zostawiłeś ten fragment kodu. Nie będzie tak krystalicznie czysty, jak w momencie, gdy go napisałeś.


Tak, wynik końcowy jest taki sam, ale zmarnowałeś sporo czasu na kwestie składniowe, z którymi kompilator jest w stanie Ci pomóc - czas, który może być znacznie krótszy, jeśli skompilowałeś się podczas pracy.

Oded
źródło
72
Rzeczywiście, w przypadku takich błędów składniowych nowoczesne IDE zasadniczo kompilują i rekompilują cały czas, aby pętla zwrotna była tak krótka, jak to tylko możliwe, i jest nieuzasadniona pomocna w wykrywaniu drobnych błędów.
Phoshi
12
@CaptainCodeman - Powiedziałbym, że są pewne błędy kompilacji, które wymagałyby od ciebie przeszukania dość dużo kodu. Jest to bardziej prawdziwe w przypadku większych baz kodu i większych zestawów zmian.
Oded
29
Czasami kompilator podaje podpowiedź zamiast podpowiedzi, na przykład błędy szablonu gcc.
pjc50
14
@ pjc50: absolutnie (co jest łatwiejsze w obsłudze, nie zmieniając zbyt wielu rzeczy na raz przed następną kompilacją, więc wiesz dokładnie, co w końcu zmieniłeś).
Doc Brown
21
Pomysł nie polega wyłącznie na kompilacji losowej. Kompiluje się na każdym znaczącym etapie, kompiluje się, gdy oczekuje się, że nadal będzie działać poprawnie. Na przykład skompiluję, aby przetestować, aby upewnić się, że obiekty są poprawnie tworzone / usuwane, lub aby upewnić się, że zdarzenia są poprawnie uruchamiane do nowej klasy, którą utworzyłem. Jeśli utworzę klasę i w jakiś sposób podpiszę ją do swojego programu, chcę się upewnić, że zrobiłem to poprawnie, zanim zacznę podpinać więcej rzeczy do mojej aplikacji. Mniej ważne w przypadku małych aplikacji, niezbędne w przypadku dużych.
Thebluefish
108

Kompilacja jest formą testu, szczególnie w językach, w których szeroko stosuje się takie typy, jak Haskell lub ML . W innych językach jest to skanowanie składniowe, które niewiele mówi.

Powiedziawszy to, „kompiluj się, jak idziesz” wydaje mi się bardzo sytuacyjnym nawykiem. Równie dobrze możesz zostać uznany za „niespokojnego” za kompilowanie częściej niż osobiste uprzedzenia ankietera. To brzmi jak dręczenie; nikt nie lubi przyznawać się do tego, że osoba, która przeprowadziła wywiad, zdała test; przechyla skale negocjacji płacowych.

Nie wszystkie systemy kompilacji są szybkie. Pracowałem na (C ++) projektu gdzie Producent wydadzą 30 sekund tylko stat „ie wszystko, aby ustalić, czy jest potrzebne do budowy, czy nie, a większość plików zajmie kilka minut, aby zbudować, jeśli nie dokonano zmian. Niechętnie robiliśmy to częściej niż co 10-15 minut. Ktoś bez wątpienia dostarczy anegdotę dotyczącą kompilacji polegającej na zabraniu talii kart perforowanych i przeniesieniu ich do innego budynku ...

Skompiluj, gdy poczujesz, że masz w głowie kompletną jednostkę konceptualną i jesteś gotowy, aby ją zatwierdzić. Raz na minutę lub raz w tygodniu w zależności od przepływu pracy.

pjc50
źródło
25
kiedy zabierasz swoje karty dziurkowania do sysopsów, aby je załadować, upewnij się, że nigdy ich nie upuścisz, ponieważ umieszczenie ich z powrotem w odpowiedniej kolejności jest prawdziwym PitA! Ach, w czasach, gdy podstawowym narzędziem do debugowania była gumka.
gbjbaanb
3
Kiedy zaczynałem programować, mierzyłem swój postęp przez ilość kodu, który mógłbym napisać bez kompilacji - zasadniczo przez jakość mojego kompilatora mentalnego. Na początku było kilka znaków, a potem kilka wierszy. Teraz mnie to nie obchodzi. Dużo kompiluję dla drobnych zmian, których chcę tylko zobaczyć, kompiluję bardzo mało, robiąc układ strukturalny projektu.
Phil
Hmm Chcę tylko powiedzieć, że dobrze napisany plik C ++ nie powinien zająć więcej niż kilka sekund na kompilację. Jeśli jest dłuższy, jest to zapach złego kodu. A jeśli jest tak duży, że make ma problemy, argumentowałbym, że aplikacja jest zbyt monolityczna. „Mój” make nigdy nie miał problemów i nie ma problemu nawet przy kompilacji Linuksa.
fresnel
2
Kiedy wyszedłem, było 1,5 miliona LOC. Zauważ, że Linux nie jest C ++; szablony wydają się być wolne w gcc, a jeśli zrobiłeś coś sprytnego i przydatnego, co okazuje się powolne w kompilacji, nie ma łatwego sposobu profilowania kompilatora, aby ustalić, co to było.
pjc50
21
@gbjbaanb Myślę, że lepiej byłoby powiedzieć „dni, w których kontrola źródła była elastyczna”. ;)
JasonMArcher
35

Więc moje pytanie brzmi: czy coś mi umknęło?

Tak: twój umysł nie jest kompilatorem. Chociaż kompilator może dokonywać n przełączeń kontekstu na sekundę, twój umysł nie może. Liczba zmian kontekstu, jakie może dokonać twój umysł w ciągu dnia, zależy od wielu czynników, takich jak doświadczenie / znajomość bazy kodu, stopień zanurzenia w kodzie, czystość kodu, stopień złożoności problemu, jak bardzo jesteś zmęczony, jeśli często przeszkadza ci w hałaśliwym otoczeniu i tak dalej.

Kompilacja bazy kodu (jednocześnie), po raz pierwszy (pomyśl „projekt z 20 plikami”) zmusi cię do zmiany kontekstu z tego, o czym myślisz (np. „Ta wartość jest tutaj ustawiona na 5, a następnie w pętla for blablabla, a złożony algorytm zwraca poprawną wartość po powrocie ") do problemu kompilacji, który jest całkowicie niezwiązany z tym, o czym myślisz (inny plik / moduł / funkcja / warunki wstępne / składnia / nazwy zmiennych, warunki wstępne itp. ).

Im więcej kodu skompilujesz naraz, tym więcej kontekstu musi zmienić Twój umysł. Nie stanowi to problemu dla małej bazy kodu, gdy cały napisany kod jest tym, co napisałeś w ciągu godziny. Jest to duży problem podczas pracy w istniejącej bazie kodu, z wieloma (i wielokrotnie nieudokumentowanymi) współzależnościami.

Czy kompilacja w trakcie pracy jest rzeczywiście korzystna?

Minimalizujesz zmiany kontekstu, jakie musi wprowadzić twój umysł, pozwalając ci bardziej skoncentrować się na wpływie i skutkach ubocznych wprowadzanych zmian. Sprawia również, że jesteś mniej zmęczony (i mniej podatny na błędy) i zwiększa jakość twoich wyników (tj. Możesz zagwarantować zminimalizowane skutki uboczne łatwiej, gdy zmieniasz i kompilujesz jeden plik na raz, niż kiedy kompilujesz i zmieniasz dziesięć).

Jeśli kompilujesz w bardzo krótkich iteracjach (przy założeniu, że proces kompilacji jest zoptymalizowany pod kątem krótkiego czasu), możliwe jest naprawienie błędów kompilacji bez wychodzenia z „strefy”.

Czy jest to jakiś mit propagowany przez społeczność programistów, że należy często kompilować kod?

Jest propagowany także przez społeczność programistyczną, ale ma ku temu dobre powody.

W moim rozumieniu jest to niepoprawny argument, ponieważ „uzyskanie kodu do kompilacji” dla danej długości kodu zazwyczaj wymaga naprawy stałej liczby błędów kompilacji i zajmuje dość stały czas

Wydaje mi się, że masz niewielkie (lub nie ma) doświadczenia w utrzymaniu średnich i dużych baz kodu (setki lub tysiące plików źródłowych). W tym miejscu najbardziej pomoże ta postawa (tj. „Kompiluj, jak idziesz”), i właśnie tam tworzysz taki nawyk.

Wyobrażam sobie, że ludzie, którzy cię przesłuchiwali, wyciągnęli podobny wniosek („nie masz dużego doświadczenia w dużych bazach kodu”).

utnapistim
źródło
1
„skompiluj i zmień dziesięć” - mnóstwo sytuacji, w których jest to najmniej znacząca jednostka do wypróbowania; takie jak dodanie nowego parametru do funkcji i wszystkich witryn wywołań.
pjc50
7
Przełączniki kontekstu. Żartujesz, prawda? Jeśli mówimy o automatycznej kompilacji w tle, aby wskazać błędy składniowe w kodzie podczas pracy, to w porządku. Jednak najszybszy przełącznik kontekstu nie będzie w stanie stwierdzić, czy logika algorytmu jest poprawnie zaimplementowana, czy algorytm w ogóle jest odpowiedni. Ale to odróżnia działające rozwiązanie od starannie zorganizowanej, bezbłędnej kompilacji i szybkiego, ale całkowicie błędnego kodu.
JensG
5
@JenS, nie, nie żartuję. Konieczność przeskoczenia całego kodu w celu naprawienia błędów kompilacji gwarantuje, że nie będziesz już myśleć o problemie, który obecnie rozwiązujesz (wydostanie się ze strefy). Jeśli zamiast tego możesz kompilować podczas pisania kodu, możesz nadal pracować nad sprawdzaniem algorytmu - a nie jego składni. Najszybszym sposobem obsługi przełączników kontekstu jest zapewnienie, że nie będziesz ich potrzebować). Mój post zakłada jednak idealny świat (z szybką kompilacją dużych baz kodu w C ++ i zminimalizowanymi wzajemnymi zależnościami).
utnapistim
1
@JensG, co wydaje się logicznym błędem: nie chodzi o wybór między skompilowanym kodem a gównianym kodem, ale o wszelkie możliwe korzyści z kompilacji więcej niż raz.
Jorg
1
Wątpię, aby twierdzenie, że kilkakrotne zerwanie koncentracji na krótki czas w celu naprawienia pojedynczych błędów składniowych jest szybsze niż zerwanie go raz i naprawienie kilkunastu błędów składniowych za jednym razem (po tym, jak martwisz się o swój algorytm). Z pewnością nie tak działają przełączniki kontekstu w komputerach (tutaj próbujemy zoptymalizować przepustowość). Pracowałem nad projektem z około 500 tys. LoC kodu C ++, który ewoluował przez ponad dekadę, więc mam nadzieję, że nie wyciągnęliśmy jeszcze karty braku doświadczenia?
Voo
26

Myślę, że jest tu coś więcej niż trochę profesjonalnego snobizmu. Sugeruje się, że „jeśli nigdy nie musiałeś regularnie kompilować, nigdy nie pracowałeś z niczym tak skomplikowanym - zdobądź więcej doświadczenia i wróć, gdy nauczysz się pracować dokładnie tak, jak my”.

Ale oczywiście ma to jeszcze inną stronę. Niektóre projekty wymagają kompilacji. Pracowałem z frameworkami, których skompilowanie zajmuje nawet 30 minut po nawet niewielkich zmianach. Niebo pomoże ci, jeśli kiedykolwiek będziesz musiał edytować plik nagłówka. Pełne rekompilacje są zwykle wykonywane z dnia na dzień, a jeśli polegasz na kompilatorze, aby złapać swoje błędy, nadal występują rzadkie błędy, które nie zostaną wykryte podczas częściowej kompilacji. W tych warunkach po prostu nie kompilujesz co 5 minut - chyba że czujesz się leniwy .

Kompilator nie może ci pomóc z błędami logicznymi lub semantycznymi, a błędy składniowe naprawdę nie są tak trudne, że warto poświęcić połowę dnia na kompilację. Oczywiście będziesz robił okazjonalne literówki, ale zakładam, że możesz zarówno pisać dotykiem, jak i czytać. Jeśli masz swobodę wyboru, użyj stylu kodowania, który dobrze wykorzystuje układ, aby wizualnie wyróżnić błędy i nigdy więcej nie upuścisz nawiasu klamrowego, nawiasu ani średnika. To wymaga trochę praktyki i nieco więcej dyscypliny niż większość ludzi jest przyzwyczajona, ale jest to możliwe. Mogę pisać kod przez kilka godzin na raz, w zwykłym edytorze tekstowym i kompilować go po raz pierwszy lepiej niż dziewięć razy na dziesięć. Jasne, że mogłem kompilować częściej, ale nie pamiętam, kiedy ostatni raz miałem błąd, który łatwiej byłoby poprawić.

Jeśli nie jesteś fanem ciągłej rekompilacji, masz dobre towarzystwo. Oto Donald Knuth:

Jeśli chodzi o twoje prawdziwe pytanie, pomysł natychmiastowej kompilacji i „testów jednostkowych” przemawia do mnie bardzo rzadko, gdy czuję się w zupełnie nieznanym środowisku i potrzebuję informacji zwrotnej na temat tego, co działa, a co nie. W przeciwnym razie marnuje się mnóstwo czasu na działania, których po prostu nigdy nie muszę wykonywać ani nawet o tym myśleć.


Biorąc to wszystko pod uwagę ... jeśli pracujesz w kontekście, w którym kompilacja jest darmową akcją, dlaczego nie miałbyś? W domu, przy projektach osobistych, wciskam ctrl-S mniej więcej raz na 30 sekund, a skrót „kompiluj” prawie tak często w środowisku IDE, które nieustannie przepuszcza kod przez interfejs użytkownika kompilatora, aby zapewnić wyróżnianie błędów w czasie rzeczywistym. Po co mijać bezpłatny lunch?

DeveloperInDevelopment
źródło
Nie zgadzam się, że kompilacja jest darmowa, rozproszenie uwagi jest kosztowne! Ale poza tym dobra odpowiedź, dzięki :)
CaptainCodeman
Może zamiast tego powinienem był odważnie napisać kursywą „jeśli” i „iff” ... Myślę, że w zależności od projektu, kompilatora i środowiska może to być dosłownie blisko darmowej akcji. Jeśli masz drugie okno lub ekran kompilatora, możesz kompilować prawie tak często, jak przestajesz oddychać. Gdybyś był naprawdę hardkorowy (nie jestem), nie musiałbyś nawet odwracać wzroku od swojego kodu - pod warunkiem, że kompilator wygenerował wystarczająco dużo błędów, aby zarejestrować się w twojej wizji peryferyjnej. Ponownie, jest to kompilacja iff jest dość szybka, w przeciwnym razie patrz wyżej.
DeveloperInDevelopment
2
I hit ctrl-S about once every 30 seconds. Prawdopodobnie oszczędzam dwa razy częściej lol. To naprawdę zły nawyk. Czasami zapisuję w środku wiersza kodu, a następnie zapisuję ponownie na końcu. Ilekroć przestaję myśleć przez chwilę i nie piszę, oszczędzam.
Cruncher
21

Kompilowanie na bieżąco ma wiele zalet. Ale bardzo się zgadzam, że pozostawanie przy zadaniu jest OK strategią kodowania.

Najbardziej znaczącą korzyścią z kompilacji przyrostowej jest mentalność wielu osób, które czekają na kompilację i przetestowanie końca : bardziej zależy nam na uruchomieniu kodu niż na czymkolwiek innym w tym momencie. Mówimy „Och, po prostu dodaj ten nawias, aby kompilator przestał narzekać” lub „och, po prostu użyj tego” bez zastanawiania się, czy istnieje ukryty błąd semantyczny, który ukrywa ten błąd składniowy. Naprawdę uważam, że błędy składniowe często zagnieżdżają się w błędach semantycznych (odwrotnie - nieprawda).

Jako przykład powiedzmy, że zmieniłem znaczenie zmiennej i w rezultacie zmieniłem jej nazwę. Zmiana nazwy generuje później błąd składniowy w kodzie, ale jeśli po prostu poprawię nazwę przez kompilatora, zignorowałem przyczynę tego błędu.

Lan
źródło
5
+1 za podkreślenie związku między błędami semantycznymi i sytaktycznymi
Doc Brown
15

Rozumiem korzyści płynące z testowania kodu podczas pracy, ale po co kompilować?

Ale w jaki sposób będziesz testować swój kod, gdy nie skompilujesz się odpowiednio?

Skrajnym przypadkiem jest rozwój testowy (TDD). Oczywiste jest, że TDD nie działa z twoją strategią, ponieważ TDD oznacza wyjątkowo krótkie cykle zapisu-testu, kompilacji (powinno się nie udać), zapisu kodu, kompilacji ponownie, uruchomienia testu, poprawiania błędów, kompilacji ponownie, refaktora, kompilacji - ponownie, uruchom test i tak dalej ...

Więc nie każdy robi TDD, przynajmniej nie zawsze (ja też, przyznaję). Przy obecnej strategii nigdy nie będziesz mieć szansy na wypróbowanie TDD. Ale nawet jeśli nie korzystasz z TDD, wyjątkowo pomocne jest regularne testowanie kodu - co nie jest możliwe, jeśli nie kompilujesz go regularnie. A gdy test się nie powiedzie, musisz go uruchomić w celu debugowania (co może pomóc ci zrozumieć, dlaczego dobrze wyglądający algorytm, który napisałeś kilka minut wcześniej, nie zachowuje się tak ładnie, jak ci się wydaje). Im więcej kodu piszesz bez kompilacji, tym więcej kodu piszesz bez testowania, więc tym bardziej prawdopodobne jest, że natrafisz na przypadek, w którym nie możesz przewidzieć, że czas na rozwiązanie problemu to „O (1)”, ponieważ napisałeś.

Doktor Brown
źródło
1
Zgadzam się z tobą, ale myślę, że istnieje różnica między kompilacją programu, ponieważ chcesz go uruchomić, a kompilacją, gdy nie ma nic ważnego do przetestowania (lub do naprawy błędów kompilacji).
CaptainCodeman
@CaptainCodeman: Myślę, że pisząc 100 linii kodu, prawie zawsze powinno być mnóstwo małych części, które mogłyby być indywidualnie testowane. 100 linii kodu zwykle oznacza od 4 do 15 funkcji (lub> 20, jeśli kodujesz w stylu Boba Martina).
Doc Brown
5
@CaptainCodeman: W TDD nigdy nie ma „nic znaczącego” do przetestowania. Klasycznym przykładem jest to, że chcesz napisać nową klasę (nazwijmy ją Foo), a następnie pierwszą rzeczą, którą robisz, jest utworzenie testu jednostkowego i zapisu, new Foo();który oczywiście nie skompiluje się, ponieważ nie napisałeś definicji klasy. W TDD jest to prawidłowy powód do uruchomienia kompilatora - dowodzi, że test jednostkowy działa (przez niepowodzenie).
slebetman
@slebetman: dzięki za pomocny komentarz. Chciałbym dodać, że IMHO nie jest ograniczone do TDD. Pisząc 100 linii kodu, zawsze jest coś sensownego do przetestowania pomiędzy nimi, jeśli robisz TDD, czy nie.
Doc Brown
14

Zgadzam się z tobą, że błędy kompilatora nie powinny stanowić problemu dla doświadczonego programisty. Nie sądzę, aby koszt ich naprawy z czasem znacznie wzrósł, aby się martwić. Gdyby można było odłożyć naprawienie wszystkich błędów kompilatora na chwilę przed wypchnięciem, zrobiłbym to, ponieważ spowodowałoby to znacznie mniejsze i bardziej skonsolidowane przerwanie.

Niestety, znalezienie błędów kompilatora nie jest jedyną czynnością kompilatora. Ryzykując stwierdzenie oczywistości, kompilacja jest wymagana do uruchomienia programu, a uruchomienie programu jest wymagane, aby znaleźć wszystkie bardziej złożone, subtelne i interesujące błędy w czasie wykonywania, które tworzą nawet doświadczeni programiści. Błędy tego typu trudniejsze, a zatem droższe do naprawienia, im dłużej odkładasz ich debugowanie, ponieważ mogą się nawzajem budować lub maskować.

Jednak niekoniecznie oznaczałbym kogoś w wywiadzie za odłożenie kompilacji do samego końca. Wywiady są zwykle bardzo proste, a doświadczeni programiści zwykle znają swoje ograniczenia. Im bardziej jesteś pewien tego, co napisałeś, tym dłużej będziesz przechodził między kompilacjami. To tylko ludzka natura.

Jednak aby nie oznaczać cię za to, zaufanie musiałoby być uzasadnione. Jeśli spędziłeś 45 minut na pisaniu czegoś bez kompilacji, a następnie potrzebowałeś kolejnych 45 minut na debugowanie, to bym to ciężko ważył przeciwko tobie.

Karl Bielefeldt
źródło
8

Jedną ważną rzeczą przy kompilacji często, o ile nie widzę innych odpowiedzi, jest to: jeśli kompilujesz rzadko i otrzymujesz dużą liczbę błędów kompilatora, większość z nich jest bez znaczenia, ponieważ są one generowane przez pierwszy błąd. Może to być spowodowane błędnym typem, literówką lub zwykłym błędem składni, który powoduje, że niektóre deklaracje są nieprawidłowe.

Zawsze możesz po prostu naprawić pierwszy, ponownie skompilować, naprawić następny pozostały itd., Ale przy dużej podstawie kodu może to być powolne. Ale jeśli spróbujesz przejrzeć długą listę błędów kompilatora i wykryć błędy, które są niezależne, poświęcasz dużo czasu na czytanie nieistotnych komunikatów lub nawigację kodu z miejsca wtórnego błędu do rzeczywistej przyczyny.

Inną rzeczą dotyczącą regularnych kompilacji jest to, że nic nie stoi na przeszkodzie, aby rozpocząć kompilację, gdy tylko zostanie napisany kompletny blok kodu, który powinien zostać skompilowany. Możesz kontynuować pisanie więcej kodu podczas kompilacji, o ile nie zapiszesz nowych zmian, dopóki kompilacja się nie zakończy. Więc praktycznie nie tracisz czasu na czekanie na kompilację. Jeśli zaczekasz, aż napiszesz wszystko, co zamierzasz napisać w tym czasie, musisz poczekać na kompilację bez żadnego działania. Jest to w zasadzie ręczna wersja tego, co nowoczesne IDE mogą robić automatycznie w tle.

hyde
źródło
Co ciekawe, jest to dobry powód, aby regularnie kompilować, nawet jeśli kompilacja jest powolna . Słuszna uwaga.
sleske
3

Dla wystarczająco doświadczonego programisty kompilowanie kodu nigdy nie jest wąskim gardłem.

Kiedy znasz język wystarczająco dobrze (tj. Kiedy nie musisz już myśleć o składni, a zamiast tego po prostu kodować funkcjonalność), zwykle nie popełniasz prostych błędów składniowych. Te, które robisz, to zwykle literówki lub błędy kopiowania i wklejania, i można je usunąć w krótkim czasie za pomocą kilku przejść kompilacyjnych.

Regularnie piszę kod przez cały dzień bez kompilacji, a następnie kompiluję i naprawiam błędy składniowe i ostrzeżenia zgłaszane przez kompilator przed zatwierdzeniem mojego kodu (z dopiskiem „trzeba przetestować!” ). Nie mam problemu z czyszczeniem ponad 1000 linii kodu C lub C ++ w ciągu zaledwie kilku minut.

Z drugiej strony debugowanie i testowanie zajmuje trochę czasu. Błędy logiczne pojawiają się z wielu powodów i jeszcze nie spotkałem się z kompilatorem, który powie mi o podprogramie, o którym całkowicie zapomniałem napisać, lub zauważy, że moje drzewo binarne nie działa, ponieważ wkleiłem, node->leftkiedy powinno być node->right.

Chociaż myślę, że generalnie nierozsądnie jest walczyć z ankieterem, powiedziałbym, że jeśli uważasz, że twój styl jest wart obrony, powinieneś zwrócić uwagę, że masz dość czasu na debugowanie napisanego kodu. Tego nigdy nie zaniedbuje żaden dobry programista.

ps - Gdybym widział, jak przeglądasz kod, czytając go, zatrudniłbym cię na miejscu. Tak robi profesjonalista za każdym razem.

par
źródło
4
„Nie spotkałem się jeszcze z kompilatorem, który powie mi o podprogramie, o którym całkowicie zapomniałem napisać”. Całkowicie polegam na kompilatorze, który informuje mnie, gdy nie dokonałem daleko idących zmian. Czasami nawet zmieniam nazwę zmiennej, aby uniemożliwić pomyślną kompilację, dopóki nie sprawdzę każdego wystąpienia jej użycia i nie nadałem im nowej nazwy. Nie rozumiem, jak możesz powiedzieć, że nie spotkałeś kompilatora, który nie ostrzega cię, jeśli czegoś brakuje. Chyba, że ​​piszesz puste procedury zastępcze, a następnie zapominasz o nich, w takim przypadku niebo ci pomoże.
Ian Goldby
@par Dziękuję za odpowiedź; Dobrze wiedzieć, że nie tylko ja tak koduję!
CaptainCodeman
3
@CaptainCodeman Wiem, że błędy logiczne są bardziej podstępne niż błędy kompilatora. Ale to jego twierdzenie, że kompilator nie jest w stanie powiedzieć ci o brakującym kodzie, który chciałem zakwestionować. Chyba że celowo piszesz niewłaściwy (lub niekompletny) kod, który się kompiluje…, ale to raczej pokonuje argument, że błędy, których kompilator nie może złapać, są prawdziwym problemem IMO. Cholera, nawet używam kompilatora, aby przenieść kursor do linii, w której następnie muszę napisać kod. Ale może jestem bardzo leniwy.
Ian Goldby
1
@IanGoldby: Całkowicie przegapiłeś ten punkt, a nawet posunąłem się tak daleko, że powiedziałem, że wybrałeś przekręcenie moich słów. Kompilator nie może ostrzec Cię o brakującym kodzie w ten sam sposób, w jaki nie mogę powiedzieć Ci, co zjesz jutro na śniadanie. Celowe wprowadzanie błędów składniowych, aby kompilator przypomniał o czymś, co jest techniką programowania; nie kwalifikuje się jako błąd ani nie daje psychicznym mocarstwom kompilatora.
parametr
1
@par Przepraszam za przestępstwo, które oczywiście spowodowałem moim komentarzem - nie było zamierzone i na pewno nie zamierzałem wprowadzać w błąd co do tego, co powiedziałeś. Widzę teraz, że kiedy piszesz niekompletny kod, który mimo wszystko się kompiluje, czynisz praktykę, aby upewnić się, że nie można go zapomnieć, dodając #warning lub TODO. To legalna technika. Ważną rzeczą, na którą oboje się zgadzamy, jest to, że kod, który się kompiluje, ale nie działa, jest znacznie bardziej niebezpieczny niż kod, który się nie kompiluje.
Ian Goldby
3

Nie, wstrzymywanie kompilacji nie jest nierozsądne, dopóki nie wykonasz wystarczającej ilości kodu (a „wystarczająca ilość” zależy od kodera i napisanego kodu).

Na przykład, jeśli jesteś niesamowitym programistą, który nie spieszy się z jego poprawnym działaniem i nie piszesz dużych ilości ani skomplikowanego kodu, to regularne kompilowanie jest marnotrawstwem i prawdopodobnie również rozprasza. Jeśli nie, to skompilowanie każdej funkcji może być dobrą rzeczą. To zależy od osoby.

Dla przykładu wyobraź sobie, że piszesz kod JavaScript - nie ma kompilatora. Zamiast tego (biorąc pod uwagę charakter większości kodu JavaScript) uruchomiłbyś program (lub odświeżyłeś stronę), aby zobaczyć wyniki swojego kodowania. Teraz nie możesz tego zrobić, dopóki nie napiszesz wystarczającej ilości kodu, aby mieć sens. W rezultacie programiści JavaScript mają tendencję do „kompilowania” tak często, jak to możliwe, co niekoniecznie bardzo często.

Krótko mówiąc, nie ma tutaj poprawnej odpowiedzi - osoba przeprowadzająca wywiad nie jest w błędzie, ale ty też. Rób to, co czyni cię produktywnym, i zapomnij, co ktoś mówi ci, co masz robić. Jest o wiele ważniejsze czynniki w kodowaniu niż twoja tendencja do F7regularnego uderzania (lub nie) nie ma absolutnie żadnego znaczenia.

gbjbaanb
źródło
Twój drugi akapit jest niejasny; możesz go edytować, aby wyjaśnić, czy „niesamowity programista” powinien się regularnie kompilować, czy nie. (Czy dodałeś „t” i zmieniłeś „nie” na „nie”?)
DougM
@DougM - ta dużo.
gbjbaanb
Dość często kod skryptowy jest opracowywany „na żywo”, to znaczy jest wykonywany w środowisku REPL. Tak więc „kompilacja” rzeczywiście dzieje się cały czas, większość kodu zapisanego w pliku źródłowym została również wykonana raz. Nie wszyscy piszą w ten sposób kod skryptu, ale powiedziałbym, że każdy, kto lubił względne „bezpieczeństwo” języków o typie statycznym i błędy kompilatora podane przez zły kod, powinien w ten sposób działać w językach skryptowych.
hyde
2

Przy dobrym środowisku programistycznym nie widzę powodu, by kompilować, chyba że planujesz przetestować kod. Narzędzia do sprawdzania składni w tle wychwytują większość wszystkiego, o czym mówi ankieter, chociaż przyznam, że wciąż istnieje kilka przypadków (obejmujących zmiany, które rozprzestrzeniają się między plikami), które nie zawsze są w pełni zidentyfikowane.

To powiedziawszy, postaram się skompilować i uruchomić prawie najmniejszą jednostkę kodu, która może faktycznie dać wynik. Pół godziny temu tworzyłem sposób drukowania niektórych wyników wyszukiwania i wykonałem pół tuzina wydruków testowych (do .pdf, a nie papierowych), wprowadzając zmiany do wyniku, aby wyglądał lepiej - wskaźnik około 1 kompilacji na 10 linie.

Loren Pechtel
źródło
1

Moim zdaniem i z mojego doświadczenia, to, czy kompilacja fragmentu kodu jest zasadniczo losowa, wiąże się z takimi rzeczami, jak to, czy brakuje średników, i ma niewiele wspólnego z poprawnością podstawowego programu. (Dla mnie skupianie się na kompilacji jest jak przeprowadzanie artykułu przez sprawdzanie pisowni bez korekty w celu sprawdzenia gramatyki.)

Moje doświadczenie jest bardzo różne: mniej niż 5% błędów kompilacji, które otrzymuję, dotyczy składni . Znam dobrze język, kiedy dostaję błędy, najczęściej są to błędy literowe, co mówi mi, że semantyka jest nieprawidłowa.

Dlatego cieszę się, że mogę jak najszybciej skorzystać z opinii mojego kompilatora. Czy kiedykolwiek doświadczyłeś używania IDE, które podkreśla błędy kompilacji w czasie rzeczywistym? Krótsza pętla sprzężenia zwrotnego może być bardzo cenna.

Jeśli podasz mi niekompletny kod, pierwszą rzeczą, którą zrobię, będzie jego przeczytanie. Nie będę nawet próbował go skompilować, dopóki nie będę wiedział, co robi kod i nie będę wiedział, że algorytm jest poprawny.

Jeśli masz pracować nad kodem napisanym przez kogoś innego, nie zawsze masz czas na przeczytanie wszystkiego. Dobra wiadomość jest taka: dobrze napisany kod ma niskie sprzężenie i powinien umożliwiać niezależne rozumowanie tylko tej części kodu, której potrzebujesz.

W takich przypadkach musisz założyć, że kod, którego jeszcze nie przeczytałeś, jest poprawny i leniwie sprawdzać, kiedy występuje problem.

„uzyskanie kodu do kompilacji” dla danej długości kodu zazwyczaj wiąże się z ustaleniem stałej liczby błędów kompilacji i zajmuje dość stałą ilość czasu, co powinno być takie samo bez względu na to, czy zrobisz to po zakończeniu pisania kodu, czy też przeplatasz z czasem kodowania.

Przełączanie kontekstu jest kosztowne dla twojego mózgu, dlatego naprawianie małych błędów natychmiast po ich napisaniu może być bardziej wydajne.

EDYCJA: Mogę również dokonać analogii z kontrolą źródła, gdy cały zespół pracuje na tych samych źródłach. Kompilowanie w trakcie pracy jest jak częste zatwierdzanie, pomaga uniknąć dużego bólu na końcu, gdy trzeba scalić i uporządkować wszystko.

Mówisz, że pod tekstem wyłączasz np. Czerwone linie. Czy robisz to również podczas pisania e-maila lub pisania dokumentu technicznego? Następnie musisz ponownie sprawdzić wszystkie strony zamiast naprawiać błędy podczas pracy.

Kolejną zaletą jest to, że podczas pracy nad kodem, jeśli cały czas kompilujesz go lub prawie kompilujesz, możesz korzystać z wielu funkcji IDE opartych na semantyce (bezpieczna zmiana nazwy, refaktoryzacja, znajdowanie zastosowań symbolu ...) .

Jeśli chcesz lepiej zrozumieć, w jaki sposób te funkcje pomagają, możesz spróbować włączyć je i ćwiczyć, aby przekonać się o ich zaletach. Można też spróbować zrobić kilka par programowanie z kimś, który jest używany do nich i zobaczyć, jak oni korzystać z nich.

Eldritch Conundrum
źródło
1
Zwykle wyłączam irytujące „funkcje” kompilatora, takie jak automatyczne formatowanie, rysowanie czerwonych linii pod tekstem itp., Ponieważ uważam, że jestem bardziej produktywny bez tych stępionych funkcji.
CaptainCodeman
1

Myślałem o tym trochę dłużej, ponieważ czułem, że coś jest bardzo, bardzo nie tak z ankieterem i nie mogłem dokładnie wskazać, co to jest. Oto problem: w przypadku każdego kodu, który napisałem w ciągu ostatnich dwudziestu lat, czas potrzebny do przekształcenia wykonalnego algorytmu w kod, który kompiluje, był minimalny. Jakikolwiek wzrost wydajności w tym obszarze ma tak niewielki wpływ na całkowity czas rozwoju, że jest całkowicie nieistotny, a ankieter, który odrzuca kandydata z powodu zauważalnej nieefektywności w tym obszarze, nie ma pojęcia, co czyni go dobrym deweloperem.

Najwięcej czasu należy poświęcić na zebranie informacji o tym, co powinien zrobić kod, zebranie informacji i specyfikacji dotyczących usług zewnętrznych, z których należy skorzystać, stworzenie globalnego projektu, który doprowadzi do poprawnego i łatwego do utrzymania kodu zamiast hakowania kodu razem i znalezienia algorytmów doprowadzi to do działania kodu zamiast kodu, który jest łączony razem, dopóki nie zdarzy się działać (kod, który oczywiście nie zawiera błędów w porównaniu do kodu, który nie ma oczywistych błędów).

Potem przychodzi trochę czasu na pisanie kodu, który się kompiluje.

Potem przychodzi więcej czasu, aby upewnić się, że kod działa, i upewnić się, że wiemy, że kod działa i pozostanie. Odbywa się to poprzez pisanie testów jednostkowych, przechodzenie przez kod i, w dużej mierze, przez dobrze zaprojektowany kod.

Ten ankieter skoncentrował się na czymś, co ujęte jest w dziesięciu słowach w mojej odpowiedzi. Co stanowi 10 procent lub mniej rzeczywistego czasu pracy. I ma prawie zerowy wpływ na zdolność tego programisty do tworzenia niezawodnego i działającego kodu.

gnasher729
źródło
To ma sens. Moim zdaniem dobry programista powinien być w stanie pisać kod na papierze przez cały dzień, a następnie pod koniec dnia pisać.
CaptainCodeman
1

Zaletą „kompilacji podczas pracy” jest ciągłe uzyskiwanie informacji zwrotnych i nie będziesz miał szansy pójść źle, zanim zostaniesz popchnięty we właściwym kierunku. Dla kompetentnego programisty, takiego jak ty, nie jest to wielka uwaga, ale dla wielu innych tak. Innymi słowy, „kompilacja w miarę postępów” jest sposobem na „zminimalizowanie maksymalnej straty”, nawet jeśli w twoim przypadku istnieją pewne potencjalne straty wydajności.

Obecnie firmy nie są zainteresowane tylko gotowym produktem. Chcą wiedzieć, że cały czas było „pod kontrolą”. Dla nich „dotarcie tam to połowa zabawy”.

Tom Au
źródło
wydaje się, że nie oferuje to nic istotnego w porównaniu z tym, co zostało opublikowane w poprzednich 16 odpowiedziach
gnat
2
Dzięki, ale o jakiej stracie mówimy? Z pewnością, chyba że zrobiłeś coś drastycznego, jak przypadkowe napisanie w niewłaściwym języku, nigdy nie musiałbyś przepisywać żadnego kodu tylko z powodu błędów kompilacji.
CaptainCodeman
@CaptainCodeman: Sprawia, że ​​firmy czują się lepiej, i jest formą „ubezpieczenia”. Jest to coś, co kosztuje, ale sprawia, że ​​większość ludzi (w tym menedżerowie) „lepiej spać w nocy”.
Tom Au
@gnat: Chciałem podkreślić, że większość korzyści to korzyści na poziomie „korporacyjnym”, a programista powinien to zrobić, ponieważ szef kazał mu to zrobić, a nie dlatego, że programista uważa, że ​​jest to dobre lub złe.
Tom Au
zostały już przedstawione punkty za „krótszą pętlą sprzężenia zwrotnego” i dobrze wyjaśnione w pierwszej odpowiedzi tutaj; Szczerze mówiąc, nie rozumiem, w jaki sposób upychanie się na temat „firm w dzisiejszych czasach” dodaje coś godnego w stosunku do tego, co zostało już powiedziane
zgryź
1

Inne odpowiedzi tutaj stanowią dobrą obronę za częste kompilowanie w pracy , ale ponieważ twoje pytanie koncentruje się na wywiadach , chciałbym zająć się tym zagadnieniem.

W moich wywiadach postępuję dokładnie odwrotnie: kandydaci nie mogą korzystać z kompilatora. Piszą krótkie programy na białej tablicy, a następnie omawiamy je. Przekonałem się, że zbyt wielu programistów używa kompilatora (lub interpretera) jako narzędzia, co jest znacznie większą stratą czasu niż zbyt rzadkie kompilowanie. Jeśli oferuję ci dużo pieniędzy i nie możesz nawet poprawnie napisać FizzBuzz bez kompilatora, to nigdy nie będziesz go ciąć długoterminowo, pracując nad problemami, które są 100 razy trudniejsze niż ćwiczenia z zabawkami w wywiadzie. A jednak te proste ćwiczenia wyeliminowały więcej kandydatów niż jakakolwiek inna część wywiadu.

Celem rozmowy jest ocena wzajemnego dopasowania kandydata i firmy. Dobre pytanie podczas rozmowy kwalifikacyjnej powinno określać cele pytania oraz sposób, w jaki rozmówca zostanie oceniony. Zadanie podstępnego pytania ankieterowi, a następnie ukaranie go za to, że nie zna ukrytej odpowiedzi, nie pomaga ankieterowi lub ankieterowi. Niestety, większość programistów - nawet starsi - nie są przeszkoleni do przeprowadzania wywiadów z innymi programistami, więc polegają wyłącznie na stereotypach i zadają te same pytania, które zadawali podczas rozmowy kwalifikacyjnej, nie zastanawiając się jednak, czy są to skuteczne techniki oceny kandydatów albo nie.

Nie twierdzę, że moje podejście jest „jedyną prawdziwą drogą”, ale bardzo mi pomogło. Podobnie jak wiele metodologii oprogramowania, które zaczynają się od dużej litery, istnieje tyle samo „mandatów” na rozmowę kwalifikacyjną. Wszystkie są piętrowe. Musisz zrobić to, co działa dla Ciebie i Twojej firmy.

Mark E. Haase
źródło
0

W większych projektach, z kilkoma podprogramami, chcesz przetestować te części przed użyciem ich w większym schemacie, ponieważ łatwiej jest debugować, jeśli wiesz, że niektóre części już działają.

Aby przetestować te mniejsze elementy, musisz skompilować.

Możliwe, że osoba przeprowadzająca wywiad myli tę sytuację z małym programem, który nie został zaprojektowany w ten sposób.

Per Alexandersson
źródło
0

Jeśli chodzi o drugi wywiad, zaletą kompilacji jest to, że w ciągu kilku sekund można zaobserwować, co programy robią (lub czego nie robią). Stamtąd łatwiej jest odczytać kod i skoncentrować swoje wysiłki na odpowiednich częściach. Być może tego oczekiwał ankieter.

Czytanie takiej nieznanej bazy kodu od początku do końca może być dość nieproduktywne (nie jesteś kompilatorem), podczas gdy kompilacja / uruchomienie aplikacji szybko da ci większy obraz.

Laurent
źródło
wydaje się, że nie oferuje to nic istotnego w porównaniu z tym, co zostało opublikowane w poprzednich 15 odpowiedziach
gnat