Style kodowania przy użyciu kilku różnych bibliotek

9

Pracuję nad jakimś kodem C ++, który wykorzystuje kilka bibliotek, w tym niektóre biblioteki C, które wszystkie mają różne style kodowania. Zostanie otwarty, gdy osiągnie etap użyteczności. Co spowodowałoby najmniej zamieszania u krótkoterminowego współpracownika, który sprawdza kod, aby naprawić jeden błąd lub dodać jedną funkcję?

  • Korzystaj z jednego spójnego stylu kodowania w całej aplikacji, nawet jeśli czasami nie pasuje on do typowego stylu kodowania używanych bibliotek.
  • Gdy biblioteka jest intensywnie używana w określonym module, należy zachować zgodność z typowym stylem kodowania tej biblioteki (tj. Stylem kodowania stosowanym we własnym kodzie i dokumentacji biblioteki) w tym module.

Sądzę, że ten ostatni ułatwi ekspertom z tej konkretnej biblioteki jednorazowy wkład i ułatwi dołączenie samouczka / przykładowego kodu podczas programowania. Jednak powoduje to, że styl kodowania jest niespójny w całej aplikacji. Jakie są zalety i wady każdego podejścia?

Karl Bielefeldt
źródło
4
Czy można by uniknąć tego problemu, pakując wszystkie biblioteki we własne niestandardowe abstrakcje? Twój własny kod i abstrakty mogłyby wtedy być zgodne z jednym stylem kodowania.
MetaFight,
Dużo tego, co robię, to abstrakcji tych bibliotek. Pytanie brzmi, jakiego stylu kodowania użyć w abstrakcji.
Karl Bielefeldt,
6
Ach Nie jestem tutaj ekspertem, ale wydaje się, że najlepiej byłoby skorzystać z konwencji samej biblioteki. Stosowanie niedopasowanej konwencji brzmi jak koszmar konserwacji. I tak długo, jak styl biblioteki jest zawarty w klasie / module, który ją streszcza, zakładam, że byłby OK. Ponownie, nie jestem tutaj profesjonalistą, ale wydaje się, że jest to równowaga, która zapewnia łatwiejsze utrzymanie abstrakcji, a także pozwala mieć własny styl w pozostałej części aplikacji.
MetaFight,
1
Czasami takie abstrakcje mogą być trochę brzydkie, postaraj się utrzymać je w czystości bez względu na stosowane konwencje, ale przede wszystkim upewnij się, że interfejs API prezentowany w abstrakcji ma wystarczającą jakość, że nie będziesz musiał wracać wplątanie się w abstrakcję, a konsumenci będą mogli z łatwością pracować z twoimi abstrakcjami, aby ich kod nie stał się bałaganem, jak w twoich abstrakcjach. Krótko mówiąc, nie ma dobrej odpowiedzi, ale dopóki twoje abstrakcje prezentują dobre interfejsy API, przynajmniej powstrzymujesz problem przed ich rozprzestrzenianiem się.
Jimmy Hoffa,
1
Co dokładnie rozumiesz przez „styl kodowania” - proste rzeczy, takie jak użycie_underscores / camelCase / PascalCase i lokalizacja nawiasów klamrowych, lub bardziej złożone rzeczy, takie jak układ klasy / metody / funkcji oraz styl imperatywny / funkcjonalny?
Izkata,

Odpowiedzi:

10

Myślę, że to zależy od tego, jak duży będzie projekt.

Z jednej strony załóżmy, że masz projekt o wartości 1 Mloc. W przypadku tak dużego projektu jest mało prawdopodobne, aby jedna osoba była „ekspertem” we wszystkich zaangażowanych obszarach. Tak więc w tym przypadku trzymałbym się istniejących stylów kodu dla każdego głównego komponentu. Nowi programiści wybiorą obszar, dowiedzą się o tym i jest mało prawdopodobne, że zobaczą wiele innych składników, które mogą mieć różne style kodu.

Jeśli projekt jest dużo mniejszy, jeżeli jest prawdopodobne, że ludzie rozumieją całą bazę kodu, a następnie wybrałbym dominujący styl kodu i trzymać się tego. W tym przypadku uważam, że spójność w całym projekcie ma większy sens, ponieważ nowi programiści będą prawdopodobnie pracować we wszystkich obszarach projektu.

Prawdopodobnie najtrudniej jest podjąć średnie projekty. W takim przypadku musisz obliczyć koszty każdego podejścia i zdecydować się na takie, które Twoim zdaniem będzie najtańsze w perspektywie długoterminowej. Wyzwanie polega na tym, że średnie projekty zwykle rozwijały się na tyle, że refaktoryzacja kompletnego stylu wydaje się zbyt droga. Możesz rzucić okiem na strukturę drzewa kodu, aby sprawdzić, czy można zorganizować grupowanie określonych stylów kodu.

Tak czy inaczej, ostateczna decyzja powinna spoczywać na zespole, który tworzy ten pakiet.


Niektóre wartości odstające, które mogą zmienić moje rozumowanie z góry:

  • Jeśli jeden lub więcej modułów ma okropny styl, nie ma sensu go utrzymywać, nawet przy większym projekcie. Tak, styl jest subiektywny, ale jeśli ty i twoi koledzy z projektu naprawdę nie lubicie sposobu, w jaki przepływają poszczególne obszary, to przestańcie dawny styl i nadaj mu lepszy.

  • Jeśli wszystkie style są dość blisko siebie, równie dobrze może być zadeklarowanie „oto nowy sposób” i użycie go do całego nowego kodu i znacznych refaktoryzacji. Może to sprawić, że recenzje będą trochę uciążliwe, ale z mojego doświadczenia wynika, że ​​większość ludzi jest w stanie dostosować się do tego podejścia. Zapewnia także znak ostrzegawczy, w którym znajduje się stary kod.

  • Czasami styl jest zmieniany w zależności od nowej funkcjonalności dodanej do języka. C ++ na przestrzeni lat zyskał wiele funkcji. Sensowne może być przebudowanie w razie potrzeby starszego stylu na nowszy, który korzysta z tych funkcji.

  • Niektóre biblioteki mogą mieć szczególnie idiomatyczne podejście lub styl. Jeśli tak, trzymałbym się tego stylu dla tej biblioteki, nawet jeśli może to kolidować z resztą projektu. Chodzi tutaj o zwiększenie szans, że ktoś, kto pracuje frobnosticatorsnad innymi projektami, będzie również pracował nad twoim projektem.


W niektórych komentarzach jako uwagę wzięto pod uwagę style imperatywne i obiektowe.

Moduły, które są „ciężkie” w określonym stylu, prawdopodobnie powinny tak pozostać, jeśli moduł jest średniej wielkości lub większy. Pracowałem z trzema głównymi stylami (tryb rozkazujący, obiektywny i funkcjonalny) i przekształciłem ciężkie style rozkazujące w styl OO. Przy średniej lub większej ilości kodu refaktoryzacja może być (wyjątkowo) trudna. Moje doświadczenie było zakłopotane, ponieważ nie miałem żadnego wsparcia narzędziowego do pomocy w refaktoryzacji.

Wyobrażam sobie, że istnieje silna korelacja między modułami o silnie imperatywnej stylistyce a modułami idiomatycznymi dla poszczególnych nisz programistycznych, co sięga ostatniego punktu, który podniosłem z wartościami odstającymi. Tak więc każdy moduł, który znajdziesz dla tej funkcjonalności, będzie tak wyglądał i chcesz, aby eksperci z tej domeny mogli łatwo pracować również nad Twoim projektem. Ale jeśli istnieją opcje, a twojemu zespołowi nie podoba się styl tego modułu, zbadałbym te opcje.

Podobnie pracowałem z modułem w stylu OO, w którym zasady OO zostały posunięte za daleko i były niewłaściwie stosowane. Jako przykład zastosowano interfejsy jako substytut wielokrotnego dziedziczenia. I jak można się spodziewać, była to prymitywna implementacja. Byłem w stanie poczynić rozsądne postępy w refaktoryzacji tego modułu, ale ostatecznie zrezygnowałem z tego podejścia, ponieważ znalazłem lepsze pakiety do użycia.


źródło
To dobry sposób na wyrażenie tego. Podobne projekty to około 300 KLOC.
Karl Bielefeldt,
3

Wygląda na to, że należy wziąć pod uwagę wiele warstw, przynajmniej:

  1. Istniejące biblioteki i wszelkie ich modyfikacje.
  2. Nowy kod testu jednostkowego dla tych bibliotek.
  3. Warstwa abstrakcji.
  4. Interfejs API prezentowany przez warstwę abstrakcji.
  5. Przykład i kod testowy przy użyciu warstwy abstrakcji.

Zakładam, że nie ma sensu po prostu przestawiać całego kodu na wspólny styl z góry - gdyby tak było, nie zadałbyś tego pytania.

Biorąc kolejno:

  1. W przypadku istniejącej bazy kodu prawdopodobnie będziesz chciał trzymać się tego stylu.
  2. Nowy kod testu jednostkowego dla istniejącego kodu stoi w szarym obszarze, szczególnie w zależności od tego, jak bardzo jest zintegrowany ze starszym kodem. Ale najprawdopodobniej postaram się zrobić to w „preferowanym stylu”.
  3. Nowy kod w warstwie abstrakcji. Zapewniając, że jest to naprawdę oddzielna warstwa kodu, nie powinno być trudności z używaniem preferowanego stylu, nawet jeśli kod robi wiele interakcji ze starszym stylem lub stylami. Większość kodu musi łączyć się z innymi stylami i nigdy nie znalazłem tego problemu.
  4. Oczywiście sam interfejs API wymaga najbardziej przemyślanych i spełniających maksymalne wymagania w zakresie użyteczności.
  5. Każdy przykład lub kod testowy powinien również być napisany w preferowanym stylu. W zależności od kompletności abstrakcji (tj. Czy całkowicie ukrywa dolne warstwy), może to być łatwe lub trudne. Oczywiście upewnienie się, że kod przyszłego klienta będzie czytelny, będzie jednym z twoich kluczowych celów.

Niektóre rzeczy, które znalazłem osobiście, to duża baza kodu starszego typu:

  • Ustawienie preferowanego stylu i wymuszenie zmian w kodzie nie powoduje magicznej migracji całego starego kodu do nowego stylu.

  • Większość inżynierów lubi kodować (mniej więcej) istniejący styl w danej bibliotece. Wymaganie w inny sposób powoduje dużo egzekwowania.

  • Wymaganie preferowanego stylu w bibliotece starszej wersji powoduje zwykle dużą niespójność stylu w tej bibliotece. Dlatego w przypadku standardów, które dotyczą wyłącznie prezentacji, w przeciwieństwie do odporności kodu, trudno jest dostrzec wiele korzyści w ich wymaganiu.

W ostatecznym wydaniu (nieco nie na temat, ale myślę, że jest to istotne), prawda jest taka, że ​​niektórzy inżynierowie mają trudności z trzymaniem się innego standardu stylu niż ten, który znają najlepiej. Zdecydowanie polecam angażowanie zespołu w podejmowanie decyzji dotyczących stylu i upewnianie się, że jest dostępny. Po wykonaniu tej czynności masz znacznie lepszą pozycję do zastosowania standardu w kodzie mieszanym.

Keith
źródło
0

Zgodzę się z @MetaFight tutaj na wypadek, gdybyś rozwijał duży projekt z wieloma modułami stron trzecich.

Zmapujmy twój problem za pomocą prawdziwego problemu słownego: „ Załóżmy, że masz cichy styl życia w swoim domu. Podoba ci się miejsce, w którym możesz być cicho, nigdy nie mówisz głośniej i nigdy nie lubisz, gdy robi to jakikolwiek członek rodziny. różnych ludzi spoza codziennego życia, aby przynieść coś do domu. Niekoniecznie będą też mówić niższym głosem, w takim przypadku odpowiednio kształtujesz się w kontaktach z takimi ludźmi. W ten sposób interfejs lub opakowanie dla tych osób jest bardzo elastyczne ze względu na twoja praca do wykonania. "Głupi przykład ... lol

Ale moim celem jest stworzenie opakowania dla takich bibliotek zgodnie z ich standardem kodowania w taki sposób, aby używać tych bibliotek przez te opakowania, zachowując oryginalny styl kodowania wewnątrz.

+1 dla MetaFight.

theinsaneone
źródło
Dokładnie właściwe rozwiązanie imo. Używam wrapperów do wiązania kodu, który inni ludzie piszą również dla moich projektów. Zdefiniuj interfejs z góry, a następnie, kiedy go zaimplementujesz, możesz go owinąć i przetestować w czarnej skrzynce.
Kieveli
1
Dlaczego jest to przegłosowane? Myślę, że to najlepsze rozwiązanie :)
MetaFight,
0

Wyraźnie spowodowałoby to najmniej zamieszania przy użyciu jednego stylu kodowania w całym projekcie. Istotą zastosowania stylu kodowania jest przede wszystkim ułatwienie odczytu i modyfikacji kodu.

Jeśli chodzi o styl kodu używany wewnętrznie w bibliotece, nie sądzę, aby był on istotny. Jeśli biblioteka jest zbyt niezbędna, napisanie opakowania OO jest w porządku, ale nie wymaga to użycia tego samego stylu kodu, co w przykładach lub elementach wewnętrznych biblioteki.

Gustav Bertram
źródło