To jest debata, w której biorę udział. Chciałbym uzyskać więcej opinii i punktów widzenia.
Mamy kilka klas, które są generowane w czasie kompilacji do obsługi operacji DB (w tym konkretnym przypadku z SubSonic, ale nie sądzę, że jest to bardzo ważne dla pytania). Generowanie jest ustawiane jako krok przed kompilacją w programie Visual Studio. Dlatego za każdym razem, gdy programista (lub oficjalny proces kompilacji) uruchamia kompilację, te klasy są generowane, a następnie kompilowane do projektu.
Teraz niektórzy twierdzą, że zapisanie tych klas w kontroli źródła może spowodować zamieszanie, na wypadek gdyby otrzymany kod nie pasował do tego, co zostałoby wygenerowane w twoim własnym środowisku.
Chciałbym mieć sposób na prześledzenie historii kodu, nawet jeśli jest on zwykle traktowany jako czarna skrzynka.
Jakieś argumenty lub kontrargumenty?
UPDATE: Zadałem to pytanie, ponieważ naprawdę wierzyłem, że jest jedna ostateczna odpowiedź. Patrząc na wszystkie odpowiedzi, mógłbym z dużą dozą pewności stwierdzić, że nie ma takiej odpowiedzi. Decyzja powinna być podjęta na podstawie więcej niż jednego parametru. Przeczytanie poniższych odpowiedzi może dostarczyć bardzo dobrych wskazówek dotyczących rodzajów pytań, które należy sobie zadać, podejmując decyzję w tej sprawie.
W tym momencie nie wybiorę zaakceptowanej odpowiedzi z powodów wymienionych powyżej.
źródło
Odpowiedzi:
Zapisanie go w kontroli źródła jest większym kłopotem niż jest warte.
Musisz zatwierdzać za każdym razem, gdy tworzysz kompilację, aby miała jakąkolwiek wartość.
Generalnie zostawiamy wygenerowany kod (idl, rzeczy jaxb itp.) Poza kontrolą źródła, gdzie pracuję i nigdy nie było to problemem
źródło
Umieść to w kontroli kodu źródłowego. Zaleta posiadania historii wszystkiego, co piszesz, dostępnej dla przyszłych programistów, przeważa nad niewielkim bólem wynikającym z okazjonalnego odtwarzania po synchronizacji.
źródło
Za każdym razem, gdy chcę pokazać zmiany w drzewie źródłowym w moim osobistym repozytorium, wszystkie „wygenerowane pliki” będą widoczne jako zmienione i wymagają zatwierdzenia.
Wolałbym mieć bardziej przejrzystą listę modyfikacji, która obejmuje tylko rzeczywiste aktualizacje, które zostały wykonane, a nie zmiany generowane automatycznie.
Zostaw je, a po kompilacji dodaj „ignoruj” do każdego z wygenerowanych plików.
źródło
Spójrz na to w ten sposób: czy sprawdzasz pliki obiektów w kontroli źródła? Wygenerowane pliki źródłowe są artefaktami kompilacji, podobnie jak pliki obiektów, biblioteki i pliki wykonywalne. Powinny być traktowane tak samo. Większość twierdzi, że nie należy sprawdzać wygenerowanych plików obiektów i plików wykonywalnych w kontroli źródła. Te same argumenty dotyczą wygenerowanego źródła.
Jeśli potrzebujesz spojrzeć na historyczną wersję wygenerowanego pliku, możesz zsynchronizować z historyczną wersją jego źródeł i odbudować.
Wpisywanie dowolnego rodzaju wygenerowanych plików do kontroli źródła jest analogiczne do denormalizacji bazy danych. Czasami istnieją powody, aby to zrobić (zazwyczaj ze względu na wydajność), ale należy to robić z wielką ostrożnością, ponieważ utrzymanie poprawności i spójności staje się znacznie trudniejsze po zdenormalizowaniu danych.
źródło
Powiedziałbym, że należy unikać dodawania wygenerowanego kodu (lub innych artefaktów) do kontroli źródła. Jeśli wygenerowany kod jest taki sam dla danych wejściowych, możesz po prostu sprawdzić wersje, które chcesz porównać i wygenerować kod do porównania.
źródło
Nazywam zasadę DRY. Jeśli masz już w repozytorium „pliki źródłowe”, które są używane do generowania tych plików kodu w czasie kompilacji, nie ma potrzeby „dwukrotnego” zatwierdzania tego samego kodu.
W ten sposób możesz również uniknąć niektórych problemów, jeśli na przykład generowanie kodu pewnego dnia się zepsuje.
źródło
Nie, z trzech powodów.
Kod źródłowy jest wszystkim, co jest konieczne i wystarczające, aby odtworzyć migawkę aplikacji z jakiegoś obecnego lub poprzedniego punktu w czasie - nic więcej i nic mniej. Po części oznacza to, że ktoś jest odpowiedzialny za wszystko, co zostało wpisane. Generalnie jestem szczęśliwy, że jestem odpowiedzialny za kod, który piszę, ale nie za kod, który jest generowany w konsekwencji tego, co piszę.
Nie chcę, aby ktoś ulegał pokusie, aby spróbować skrócić kompilację ze źródeł podstawowych za pomocą kodu pośredniego, który może być aktualny lub nie (a co ważniejsze, za który nie chcę brać odpowiedzialności). kusi niektórych ludzi, aby dali się wciągnąć w bezsensowny proces dotyczący debugowania konfliktów w kodzie pośrednim opartym na częściowych kompilacjach.
Gdy przejdzie do kontroli źródła, przyjmuję odpowiedzialność za plik. to jest tam, b. jest aktualny i c. jest niezawodnie integrowalny ze wszystkim innym. Obejmuje to usunięcie go, gdy już go nie używam. Im mniej tej odpowiedzialności, tym lepiej.
źródło
Naprawdę uważam, że nie powinieneś ich sprawdzać.
Z pewnością każda zmiana w wygenerowanym kodzie będzie albo szumem - zmianami między środowiskami lub zmianami w wyniku czegoś innego - np. Zmiany w twojej bazie danych. Jeśli skrypty tworzenia bazy danych (lub jakiekolwiek inne zależności) znajdują się w kontroli źródła, to dlaczego potrzebujesz również wygenerowanych skryptów?
źródło
Ogólna zasada brzmi nie , ale jeśli wygenerowanie kodu zajmuje trochę czasu (z powodu dostępu do bazy danych, usług internetowych itp.), Możesz chcieć zapisać wersję z pamięci podręcznej w kontroli źródła i oszczędzić wszystkim bólu.
Twoje narzędzia również muszą być tego świadome i obsługiwać wyewidencjonowywanie z kontroli źródła w razie potrzeby, zbyt wiele narzędzi decyduje się na wyewidencjonowanie z kontroli źródła bez żadnego powodu.
Dobre narzędzie będzie używać wersji z pamięci podręcznej bez jej dotykania (ani modyfikowania przedziałów czasowych w pliku).
Trzeba też umieścić duże ostrzeżenie w generowanym kodzie, aby ludzie nie modyfikowali pliku, ostrzeżenie na górze nie wystarczy, trzeba je powtarzać co kilkanaście wierszy.
źródło
Nie przechowujemy również wygenerowanego kodu DB: ponieważ jest on generowany, możesz go pobrać dowolnie w dowolnej wersji z plików źródłowych. Przechowywanie go byłoby jak przechowywanie kodu bajtowego lub podobnego.
Teraz musisz upewnić się, że generator kodu używany w danej wersji jest dostępny! Nowsze wersje mogą generować inny kod ...
źródło
Zostaw to.
Jeśli wpisujesz wygenerowane pliki, robisz coś nie tak. Co złego może się różnić, to może być to, że proces kompilacji jest nieefektywne, albo coś innego, ale nie widzę go zawsze jest dobrym pomysłem. Historia powinna być powiązana z plikami źródłowymi, a nie wygenerowanymi.
Powoduje to po prostu ból głowy dla osób, które następnie próbują rozwiązać różnice, znaleźć pliki, które nie są już generowane przez kompilację, a następnie je usunąć itp.
Świat bólu czeka na tych, którzy zarejestrują wygenerowane pliki!
źródło
Istnieje specjalny przypadek, w którym chcesz zaewidencjonować wygenerowane pliki: kiedy może zajść potrzeba kompilacji w systemach, w których narzędzia używane do generowania innych plików nie są dostępne. Klasycznym przykładem tego, z którym pracuję, jest kod Lex i Yacc. Ponieważ tworzymy system wykonawczy, który musi budować i działać na ogromnej różnorodności platform i architektur, możemy polegać tylko na systemach docelowych, aby mieć kompilatory C i C ++, a nie na narzędziach niezbędnych do wygenerowania kodu leksykalnego / parsującego dla naszej definicji interfejsu tłumacz. Tak więc, kiedy zmieniamy naszą gramatykę, sprawdzamy wygenerowany kod, aby go przeanalizować.
źródło
przyjeżdża trochę późno ... w każdym razie ...
Czy umieściłbyś plik pośredni kompilatora w kontroli wersji źródła? W przypadku generowania kodu, z definicji kod źródłowy jest wejściem generatora, podczas gdy wygenerowany kod można traktować jako pliki pośrednie między "rzeczywistym" źródłem a zbudowaną aplikacją.
Więc powiedziałbym: nie poddawaj wygenerowanego kodu pod kontrolę wersji, ale generator i jego wejście.
Konkretnie pracuję z generatorem kodu, który napisałem: nigdy nie musiałem utrzymywać wygenerowanego kodu źródłowego pod kontrolą wersji. Powiedziałbym nawet, że odkąd generator osiągnął pewien poziom dojrzałości, nie musiałem obserwować zawartości generowanego kodu, chociaż dane wejściowe (np. Opis modelu) uległy zmianie.
źródło
W niektórych projektach dodaję wygenerowany kod do kontroli źródła, ale to naprawdę zależy. Moja podstawowa wskazówka jest taka, że jeśli wygenerowany kod jest nieodłączną częścią kompilatora, nie będę go dodawać. Jeśli wygenerowany kod pochodzi z zewnętrznego narzędzia, takiego jak w tym przypadku SubSonic, to dodałbym if do kontroli źródła. Jeśli okresowo aktualizujesz komponent, chcę poznać zmiany w wygenerowanym źródle w przypadku pojawienia się błędów lub problemów.
Jeśli chodzi o wygenerowany kod, który musi zostać zarejestrowany, najgorszym scenariuszem jest ręczne różnicowanie plików i ich przywracanie, jeśli to konieczne. Jeśli używasz svn, możesz dodać hak przed zatwierdzeniem w svn, aby odmówić zatwierdzenia, jeśli plik tak naprawdę się nie zmienił.
źródło
Zadaniem zarządzania konfiguracją (którego kontrola wersji jest tylko jedną częścią) jest umożliwienie wykonania następujących czynności:
Pierwsza z nich zapewnia, że kiedy powiesz klientowi lub użytkownikowi końcowemu „błąd zgłoszony w zeszłym tygodniu został naprawiony i dodano nową funkcję”, nie wróci on dwie godziny później i powie „nie, nie ma”. Zapewnia również, że nie powiedzą „Dlaczego to robi X? Nigdy nie prosiliśmy o X”.
Drugi oznacza, że kiedy klient lub użytkownik końcowy zgłosi błąd w jakiejś wersji, którą wydałeś rok temu, możesz wrócić do tej wersji, odtworzyć błąd, naprawić go i udowodnić, że to twoja poprawka wyeliminowała błąd, a nie pewne zakłócenia kompilatora i inne poprawki.
Oznacza to, że Twój kompilator, biblioteki itp. Również muszą być częścią CM.
A teraz odpowiedz na twoje pytanie: jeśli potrafisz wykonać wszystkie powyższe czynności, nie musisz rejestrować żadnych reprezentacji pośrednich, ponieważ i tak masz gwarancję uzyskania tej samej odpowiedzi. Jeśli nie możesz zrobić wszystkiego powyżej, wszystkie zakłady są wyłączone, ponieważ nigdy nie możesz zagwarantować, że zrobisz to samo dwa razy i uzyskasz taką samą odpowiedź. Więc równie dobrze możesz umieścić wszystkie swoje pliki .o pod kontrolą wersji.
źródło
To naprawdę zależy. Ostatecznie celem jest odtworzenie tego, co miałeś, jeśli zajdzie taka potrzeba. Jeśli jesteś w stanie dokładnie zregenerować pliki binarne, nie ma potrzeby ich przechowywania. ale musisz pamiętać, że aby odtworzyć swoje rzeczy, prawdopodobnie będziesz potrzebować dokładnej konfiguracji, z którą to zrobiłeś w pierwszej kolejności, a to oznacza nie tylko kod źródłowy, ale także środowisko kompilacji, IDE, a może nawet inne biblioteki , generatory lub inne rzeczy, w dokładnej konfiguracji (wersjach), której użyłeś.
Miałem kłopoty w projektach, w których zaktualizowaliśmy nasze środowisko kompilacji do nowszych wersji lub nawet do innych dostawców, gdzie nie mogliśmy odtworzyć dokładnie tych plików binarnych, które mieliśmy wcześniej. Jest to prawdziwy ból, gdy pliki binarne, które mają być głęboko, zależą od pewnego rodzaju hasha, szczególnie w zabezpieczonym środowisku, a odtworzone pliki w jakiś sposób różnią się z powodu aktualizacji kompilatora lub czegokolwiek innego.
Czy mógłbyś więc przechowywać wygenerowany kod: powiedziałbym, że nie. Wydane pliki binarne lub produkty dostarczane, w tym narzędzia, z których je odtworzyłeś, będę przechowywać. A potem nie ma potrzeby przechowywania ich w kontroli źródła, po prostu zrób dobrą kopię zapasową tych plików.
źródło
Prawidłowa odpowiedź to „To zależy”. To zależy od potrzeb klienta. Jeśli możesz przywrócić kod do konkretnej wersji i bez niego stawić czoła audytowi zewnętrznemu, nadal nie jesteś na twardym gruncie. Jako deweloperzy musimy wziąć pod uwagę nie tylko „hałas”, ból i miejsce na dysku, ale również fakt, że mamy za zadanie odgrywać rolę generowania własności intelektualnej i mogą to mieć konsekwencje prawne. Czy byłbyś w stanie udowodnić sędziemu, że jesteś w stanie odtworzyć witrynę internetową dokładnie tak, jak widział ją klient dwa lata temu?
Nie sugeruję, abyś zapisywał lub nie zapisywał plików gen'd, niezależnie od tego, w jaki sposób zdecydujesz, jeśli nie angażujesz Ekspertów Przedmiotowych do decyzji, którą prawdopodobnie nie masz.
Moje dwa centy.
źródło
Przedstawiono tu dobre argumenty za i przeciw. Dla przypomnienia, system generacji T4 buduję w Visual Studio i nasza domyślna opcja out-of-the-box powoduje, że wygenerowany kod jest sprawdzany. Musisz trochę ciężej popracować, jeśli wolisz nie rejestrować.
Dla mnie kluczową kwestią jest różnicowanie generowanych danych wyjściowych, gdy aktualizowane jest wejście lub sam generator.
Jeśli nie masz wpisanych danych wyjściowych, musisz wykonać kopię całego wygenerowanego kodu przed aktualizacją generatora lub modyfikacją danych wejściowych, aby móc porównać to z danymi wyjściowymi z nowej wersji. Myślę, że jest to dość żmudny proces, ale po sprawdzeniu danych wyjściowych wystarczy porównać nowe dane wyjściowe z repozytorium.
W tym miejscu rozsądnie jest zapytać „Dlaczego przejmujesz się zmianami w generowanym kodzie?” (Szczególnie w porównaniu z kodem obiektowym). Uważam, że jest kilka kluczowych powodów, które wynikają raczej z obecnego stanu wiedzy, a nie z jakiegoś nieodłącznego problemu.
Tworzysz odręczny kod, który ściśle zazębia się z wygenerowanym kodem. W dzisiejszych czasach tak nie jest w przypadku plików obj. Kiedy generowany kod się zmienia, niestety dość często zdarza się, że jakiś odręczny kod musi się zmienić, aby pasował. Ludzie często nie obserwują wysokiego stopnia zgodności wstecznej z punktami rozszerzalności w wygenerowanym kodzie.
Wygenerowany kod po prostu zmienia swoje zachowanie. Nie tolerowałbyś tego ze strony kompilatora, ale uczciwie mówiąc, generator kodu na poziomie aplikacji jest ukierunkowany na inny obszar problemu z szerszym zakresem akceptowalnych rozwiązań. Ważne jest, aby sprawdzić, czy przyjęte przez Ciebie założenia dotyczące poprzedniego zachowania są teraz zepsute.
Po prostu nie ufasz w 100% wynikom generatora od wydania do wydania. Narzędzia generatora mają dużą wartość, nawet jeśli nie są one budowane i utrzymywane z rygorem dostawcy kompilatora. Wersja 1.0 mogła być całkowicie stabilna dla twojej aplikacji, ale być może 1.1 ma teraz kilka błędów dla twojego przypadku użycia. Alternatywnie zmieniasz wartości wejściowe i stwierdzasz, że ćwiczysz nowy element generatora, którego wcześniej nie używałeś - potencjalnie możesz zostać zaskoczony wynikami.
Zasadniczo wszystkie te rzeczy sprowadzają się do dojrzałości narzędzi - większość generatorów kodu aplikacji biznesowych nie jest tak bliska, jak kompilatory, a nawet narzędzia na poziomie lex / yacc od lat.
źródło
Obie strony mają słuszne i rozsądne argumenty i trudno jest zgodzić się na coś powszechnego. Systemy kontroli wersji (VCS) śledzą pliki, które programiści w nim umieszczają, i zakładają, że pliki w VCS są ręcznie tworzone przez programistów, a programiści są zainteresowani historią i zmianami między dowolnymi wersjami plików. To założenie wyrównuje dwie koncepcje: „Chcę pobrać ten plik, kiedy będę pobierać”. i „Interesuje mnie zmiana tego pliku”.
Teraz argumenty obu stron można przeformułować w ten sposób:
Na szczęście wydaje się, że te dwa wymagania nie są ze sobą zasadniczo sprzeczne. Przy pewnym rozszerzeniu obecnych VCS powinno być możliwe posiadanie obu. Innymi słowy, to fałszywy dylemat. Jeśli się chwilę zastanowić, nietrudno zdać sobie sprawę, że problem wynika z założenia, jakie trzymają VCS. Systemy VCS powinny odróżniać pliki, które są ręcznie tworzone przez programistów, od plików, które nie są ręcznie tworzone przez programistów, ale po prostu znajdują się w tym VCS. W przypadku pierwszej kategorii plików, którą zwykle nazywamy plikami źródłowymi (kodem), systemy VCS wykonały teraz świetną robotę. W przypadku tej drugiej kategorii VCS nie miały jeszcze takiej koncepcji, o ile wiem.
Podsumowanie
Weźmy git jako jeden przykład, aby zilustrować, co mam na myśli.
git status
nie powinien domyślnie wyświetlać wygenerowanych plików.git commit
powinien zawierać wygenerowane pliki jako migawkę.git diff
nie powinien domyślnie wyświetlać wygenerowanych plików.PS
Jako obejście można zastosować haki Git, ale byłoby wspaniale, gdyby git obsługiwał je natywnie.
gitignore
nie spełnia naszych wymagań, ponieważ zignorowane pliki nie trafią do VCS.enter code here
źródło
Argumentowałbym za. Jeśli korzystasz z procesu ciągłej integracji, który sprawdza kod, modyfikuje numer kompilacji, tworzy oprogramowanie, a następnie je testuje, to prostsze i łatwiejsze jest posiadanie tego kodu jako części repozytorium.
Ponadto jest to nieodłączna część każdej „migawki”, którą wykonujesz z repozytorium oprogramowania. Jeśli jest częścią oprogramowania, powinien być częścią repozytorium.
źródło
Powiedziałbym, że tak, chcesz go poddać kontroli źródła. Z punktu widzenia zarządzania konfiguracją WSZYSTKO, co jest używane do tworzenia kompilacji oprogramowania, musi być kontrolowane, aby można było je odtworzyć. Rozumiem, że wygenerowany kod można łatwo odtworzyć, ale można argumentować, że nie jest to to samo, ponieważ data / znaczniki czasu będą różne w obu kompilacjach. W niektórych obszarach, takich jak rząd, często tak się dzieje.
źródło
Generalnie wygenerowany kod nie musi być przechowywany w kontroli źródła, ponieważ historię wersji tego kodu można prześledzić na podstawie historii wersji kodu, który go wygenerował!
Jednak wygląda na to, że OP używa wygenerowanego kodu jako warstwy dostępu do danych aplikacji, zamiast ręcznie ją pisać. W takim przypadku zmieniłbym proces budowania i przekazałbym kod do kontroli źródła, ponieważ jest to krytyczny składnik kodu wykonawczego. Eliminuje to również zależność od narzędzia do generowania kodu z procesu kompilacji na wypadek, gdyby programiści musieli użyć innej wersji narzędzia dla różnych gałęzi.
Wygląda na to, że kod wystarczy wygenerować tylko raz, a nie przy każdej kompilacji. Gdy programista musi dodać / usunąć / zmienić sposób, w jaki obiekt uzyskuje dostęp do bazy danych, kod powinien zostać wygenerowany ponownie, tak jak przy ręcznych modyfikacjach. Przyspiesza to proces budowania, pozwala na ręczne optymalizacje warstwy dostępu do danych, a historia warstwy dostępu do danych jest zachowywana w prosty sposób.
źródło
Kończy mi się (niestety) poddanie wielu źródeł pochodnych kontroli źródła, ponieważ pracuję zdalnie z ludźmi, którym nie przeszkadza skonfigurowanie odpowiedniego środowiska kompilacji lub które nie mają umiejętności źródła pochodne są zbudowane dokładnie poprawnie. (A jeśli chodzi o narzędzia automatyczne Gnu, sam jestem jedną z tych osób! Nie mogę pracować z trzema różnymi systemami, z których każdy działa z inną wersją narzędzi automatycznych - i tylko z tą wersją).
Ten rodzaj trudności prawdopodobnie dotyczy raczej projektów typu open source w niepełnym wymiarze godzin, wolontariuszy niż płatnych projektów, w których osoba opłacająca rachunki może nalegać na jednolite środowisko kompilacji.
Robiąc to, w zasadzie zobowiązujesz się do tworzenia plików pochodnych tylko w jednej witrynie lub tylko w odpowiednio skonfigurowanych witrynach. Twoje pliki Makefile (lub cokolwiek innego) powinny być skonfigurowane tak, aby zauważały, gdzie są uruchomione i powinny odmawiać ponownego pobierania źródeł, chyba że wiedzą, że działają w bezpiecznym miejscu kompilacji.
źródło
Jeśli jest częścią kodu źródłowego, powinien zostać poddany kontroli źródła niezależnie od tego, kto lub co go generuje. Chcesz, aby kontrola źródła odzwierciedlała bieżący stan systemu bez konieczności jego ponownego generowania.
źródło
Absolutnie miej wygenerowany kod w kontroli źródła z wielu powodów. Powtarzam to, co wiele osób już powiedziało, ale są pewne powody, dla których bym to zrobił
źródło
CodeCompileUnit
do porządku kanonicznego.Pozostawiłbym wygenerowane pliki poza drzewem źródłowym, ale umieściłbym je w osobnym drzewie kompilacji.
np. przepływ pracy
Prawdopodobnie w Subversion / Mercurial / Git / etc są dobre sposoby na powiązanie historii prawdziwych plików źródłowych w obu miejscach.
źródło
Wygląda na to, że po obu stronach są bardzo mocne i przekonujące opinie. Zalecałbym przeczytanie wszystkich najczęściej głosowanych odpowiedzi, a następnie podjęcie decyzji, jakie argumenty mają zastosowanie w Twoim konkretnym przypadku.
UPDATE: Zadałem to pytanie, ponieważ naprawdę wierzyłem, że jest jedna ostateczna odpowiedź. Patrząc na wszystkie odpowiedzi, mógłbym z dużą dozą pewności stwierdzić, że nie ma takiej odpowiedzi. Decyzja powinna być podjęta na podstawie więcej niż jednego parametru. Przeczytanie innych odpowiedzi może dostarczyć bardzo dobrych wskazówek co do rodzajów pytań, które należy sobie zadać, podejmując decyzję w tej kwestii.
źródło