Jakiś czas temu zadałem pytanie na temat SO napisane w C ++, ale zamiast uzyskać odpowiedź na dany problem, komentarze oszalały na temat mojego stylu kodowania, nawet gdy wskazałem, że jest to fragment kodu WIP i że zamierzałem to wyczyścić później, kiedy miałem uruchomioną skrzynkę podstawową. (Otrzymałem tyle głosów, że zdecydowałem się wyciągnąć pytanie, ponieważ mój przedstawiciel na SO jest już prawie bez szans)
Zastanawiałem się, dlaczego ludzie przyjmują tak twardą postawę: „jesteś noobem, idź się pieprzyć”. Zostałem oskarżony o pisanie w C ++ tak, jakby to była Java. Coś, czego nie rozumiem, a to wciąż mnie zaskakuje.
Od wielu lat programuję w kilku językach OOP, aczkolwiek w przerwach. Wybieram język, który ma być używany, pod względem dostępnych bibliotek i optymalnych środowisk wykonywania dla danego zadania. Przyjmuję wzorce projektowe w kodzie OOP i jestem całkiem pewny, że moje użycie wzorców jest prawidłowe i że OO jest mądre, mogę trzymać własne. Rozumiem zestaw narzędzi OOP, ale wybieram korzystanie z tych narzędzi tylko wtedy, gdy uważam, że jest to naprawdę wymagane, a nie tylko po to, aby użyć mojej sztuczki, aby pokazać moje umiejętności programistyczne. (Wiem, że nie są na najwyższym poziomie, ale myślę, że nie są też na poziomie n00b).
Projektuję kod przed napisaniem pojedynczego wiersza. Aby zdefiniować testy, wymieniam cele określonej klasy i kryteria, które musi spełnić. Ponieważ łatwiej jest mi tworzyć diagramy sekwencji, a następnie pisać kod, postanowiłem napisać moje testy po tym, jak interfejs stanie się oczywisty.
Muszę przyznać, że w kodzie, który zamieściłem w pytaniu, nadal używałem wskaźników, zamiast inteligentnych wskaźników. Używam RAII, kiedy tylko mogę. Wiem, że właściwe RAII oznacza ochronę przed punktami zerowymi, ale działam stopniowo. To była praca w toku i zamierzałem ją później wyczyścić. Ten sposób pracy został zdecydowanie potępiony.
Moim zdaniem najpierw powinienem mieć działający przykład, aby sprawdzić, czy przypadek podstawowy jest realnym sposobem myślenia. Zdarza mi się również myśleć, że wyczyszczenie kodu jest czymś, co jest typowe dla fazy refaktoryzacji zwinnej, po udowodnieniu podstawowego przypadku. Muszę przyznać, że chociaż powoli otrzymuję standard Cxx, wolę używać tego, co rozumiem, zamiast ryzykować używanie koncepcji, których jeszcze nie opanowałem w kodzie produkcyjnym. Od czasu do czasu próbuję nowych rzeczy, ale zwykle w projektach, które mam na boku, tylko w tym celu.
[edytuj] Chciałbym wyjaśnić, że sugestia komara [1] nie pojawiła się w wyszukiwaniu, które zrobiłem, zanim zacząłem zadawać moje pytanie. Jednak chociaż jego sugestia obejmuje jeden aspekt pytania, pytanie, do którego się odnosił, nie odpowiada na sedno mojego pytania, a jedynie na jego część. Moje pytanie dotyczy bardziej odpowiedzi na mój styl kodowania oraz profesjonalnych aspektów obsługi różnych stylów kodowania i (pozornych) poziomów umiejętności. Z moim poprzednim pytaniem w sprawie SO i jego odpowiedzią jest przypadek. [/edytować]
Pytanie brzmi: dlaczego szydzić z kogoś, kto nie używa twojego stylu kodowania?
Sprawy / podziały dla mnie są następujące:
- Dlaczego niewłaściwą praktyką programistyczną byłoby używanie kodu podatnego na błędy w sytuacjach prototypowych, jeśli refaktoryzacja czyni go później bardziej niezawodnym?
- W jaki sposób program napisany w C ++ mógłby wyglądać tak, jak napisano w Javie? Co sprawia, że jest to zły program (biorąc pod uwagę, że wskazałem zamiar obecnego stylu i planowane prace nad ulepszeniem?)
- Jak miałbym być kiepskim profesjonalistą, jeśli wybiorę konstrukcję używaną w pewnym paradygmacie programowania (np. OOP / DP)?
źródło
int
zmiennymi do śledzenia rzeczywistej długości.Odpowiedzi:
Nie widząc kodu, o którym mowa, istnieje kilka sposobów pisania kodu Java w C ++, niektóre gorsze niż inne.
Z wyjątkiem nr 1, żaden z nich nie czyni programu C ++ złym programem, ale nie jest to również rodzaj kodu, nad którym wolę pracować jako programista C ++. (Nie podobałoby mi się też praca z Perlem nie idiomatycznym lub w stylu C, Python nie idiomatyczny itp.) Język ma własne narzędzia, idiomy i filozofię, a dobry kod używa tych narzędzi i idiomów zamiast próbować używać najniższy wspólny mianownik lub próba odtworzenia podejścia innego języka. Pisanie nieidiomatycznego kodu w określonym języku / domenie problemowej / czymkolwiek nie czyni kogoś złym programistą, oznacza to po prostu, że muszą dowiedzieć się więcej o tym języku / domenie problemowej / czymkolwiek. I nie ma w tym nic złego; jest bardzo długa lista rzeczy, o których muszę się więcej dowiedzieć, a w szczególności C ++ ma absolutną masę rzeczy do nauczenia się.
Jeśli chodzi o szczególne pytanie dotyczące pisania podatnego na błędy kodu z zamiarem jego późniejszego wyczyszczenia, nie jest on czarno-biały:
Aby użyć na przykład wskaźników surowych w porównaniu ze wskaźnikami inteligentnymi, jeśli zamierzasz pracować w C ++, użycie RAII i inteligentnych wskaźników jest na tyle podstawowe, że pisanie kodu w ten sposób powinno być szybsze niż powrót i wyczyszczenie go później. Ponownie, niezastosowanie się do tego nie oznacza, że ktoś jest złym programistą, nieprofesjonalnym itp., Ale oznacza, że jest więcej do nauczenia się.
źródło
new
są uważane za narzędzia powertools. Automatyczne przechowywanie jest narzędziem ręcznym.Każdy język programowania ma zestaw idiomów i najlepszych praktyk, które zwykle prowadzą do eleganckiego, poprawnego i wydajnego kodu. Oto kilka najgorszych praktyk, które doskonale działają w innym języku:
for ($i = 0; $i < 42; $i++) { … }
w Perlu, ale nie w PHP(w Perlu, zmienne powinny być deklarowane, a takie pętle powinny iterować w zakresie)
new Foo()
w C ++ bez uzasadnionego powodu, ale nie w Javie(C ++ nie ma funkcji wyrzucania elementów bezużytecznych, więc należy użyć RAII. W przeciwnym razie Noobs wycieknie pamięć)
(Python jest językiem opartym na wielu paradygmatach, zamiast tego wymusza „OOP” i obsługuje funkcje na najwyższym poziomie)
return null
w Scali, ale nie w jakimkolwiek języku podobnym do C(ponieważ Scala ma
Option
typ)(ponieważ stos Java przepełnia się szybko, podczas gdy OCaml ma optymalizację wywołania ogona)
Łatwo jest używać nowego języka, tak jakby to było coś, co wiesz, a przy odrobinie szczęścia to nawet zadziała. „Możesz pisać Fortran w dowolnym języku”. Ale tak naprawdę nie chcesz ignorować określonych funkcji języka X, ponieważ są duże szanse, że X oferuje przewagę nad U.
„ Wybieram język, który ma być używany pod względem dostępnych bibliotek i optymalnych środowisk wykonywania dla danego zadania ” - ale to, czy ten język X jest rzeczywiście lepszy niż język U dla danego zadania, zależy również od jego znajomości tego języka, lub ile czasu zajmie zapoznanie się z nim w wystarczającym stopniu, aby dobrze go używać. Nie dałbyś ciężkiej piły łańcuchowej tylko dlatego, że tnie ona drewno najszybciej, gdy naprawdę chcesz swój stary nóż do pióra, ponieważ idealnie pasuje do dłoni. Chyba że naprawdę chcesz powalić drzewo.
Ale twoje pytanie dotyczy bardziej kwestii kulturowej : nauka wszystkich najlepszych praktyk zajmuje dużo czasu, a nowicjusze zadają najwięcej pytań, podczas gdy guru odpowiadają na nie. Ale to, co jest oczywiste dla guru, nie jest oczywiste dla początkującego, a guru czasami o tym zapominają. Jako nowicjusz rozwiązaniem jest nie przestać zadawać pytań. Można jednak wykazać się otwartością na naukę i stosowanie najlepszych praktyk, np. Próbując maksymalnie wyczyścić kod, zanim pokażemy go innym. Większość języków ma kilka podstawowych najlepszych praktyk, które są łatwe do nauczenia się, nawet jeśli cała krzywa uczenia się jest naprawdę bardzo długa.
Częstym problemem jest to, że ludzie początkujący w programowaniu ignorują wcięcia lub inne formatowanie, a następnie są zdezorientowani, ponieważ ich program nie działa. Byłbym również zdezorientowany, a pierwszym krokiem do zrozumienia programu jest upewnienie się, że jest on idealnie ułożony. Wtedy proste błędy, takie jak zapomniany cytat zamykający lub brakujący przecinek, nagle stają się oczywiste. Ufam, że już ćwiczysz dobre formatowanie, a oto metafora innych najlepszych praktyk: najlepsze praktyki zapobiegają błędom, najlepsze praktyki ułatwiają znajdowanie błędów, stosowanie najlepszych praktyk pojawia się przed znalezieniem problemu .
Mówienie „Naprawię to później” jest zbyt tanie, gdy naprawienie go teraz rozwiązałoby problem (ta legalna „faza oczyszczania” może nigdy nie nadejść, więc jedyną odpowiedzialną opcją jest zrobienie tego dobrze pierwszy raz). Przynajmniej próba uczynienia twojego kodu tak dobrym, jak to możliwe, zanim poprosisz innych o pomoc, ułatwia im rozumowanie twojego kodu, więc jest to grzeczna rzecz.
źródło
optional<T>
iNullable<T>
odpowiednio. Ponadto praktycznie wszyscy przeciekają pamięć w C ++ bez RAII, noob lub nie.Nie jestem hardcorowym programistą C ++, ale ...
Należy pamiętać, że błąd w C ++ zwykle oznacza „niezdefiniowane zachowanie”. W bezpiecznym języku najgorszym, co może się zdarzyć, jest wyjątek natychmiast kończący program. W C ++ masz szczęście, jeśli dostaniesz segfault. Jest całkowicie możliwe, że Twój program robi coś subtelnie złego. Może również zachowywać się poprawnie przez pewien czas i ujawniać błędy znacznie później, lub może zachowywać się poprawnie cały czas, ale ostatecznie pochłonie całą twoją pamięć.
W każdym razie wystarczy tylko jeden błąd, aby całkowicie usunąć program z szyn i przejść na nieznane terytorium. Jest prawdopodobne, że dla etatowego programisty C ++ „przypadek podstawowy” oznacza „brak możliwości nieokreślonego zachowania lub wycieków pamięci”.
Nie wydaje mi się, aby istniała odpowiedź na to pytanie, która nie będzie w dużej mierze spekulacyjna i opiniowana. Jeśli jednak chcesz, żebym się tym zajął, Java ma kilka powiązanych ze sobą antypatternów, takich jak fakt, że wszystko musi być przedmiotem. Gdzie w innych językach chcesz przekazać wskaźnik, funktor, lub funkcji, w Javie zwykle znaleźć mnóstwo bezsensowne i wąsko-użyteczne
ThingDoers
,FooFactories
iIFrobnicators
które są tylko funkcje w przebraniu.Podobnie, w przypadku gdy w innych językach możesz przekazać prostą krotkę lub bezimienną strukturę, w Javie spakowanie nawet zaledwie 2 obiektów do prostego kontenera danych wymaga uprzedniego zdefiniowania ponad 30-liniowej klasy NamedThing z setterami, getterami i Javadocsem. Względny brak funkcji Javy zmusza programistów do wykonywania obiektowych podwójnych backflipów, aby czasem załatwić sprawę. Wynikowy kod rzadko jest idiomatyczny poza Javą.
Jest też fakt, że w C ++ potrzebujesz bardzo uproszczonego wykresu obiektowego do ręcznego zarządzania pamięcią; zwykle obiekt jest własnością dokładnie jednego innego obiektu. W Javie nie musisz stosować się do tak ścisłych ograniczeń, ponieważ śmieciarz zapewnia, że rzeczy zostaną wyczyszczone, gdy nie będzie już żadnych odniesień do nich. Zdecydowanie istnieje ryzyko nieprawidłowego zarządzania pamięcią, jeśli po prostu transliterujesz kod z Java na C ++.
Wreszcie może to być po prostu elitaryzm. Nie będę udawał, że stanowią większość, ale zdecydowanie widziałem sentyment „Nie potrzebuję języka, który trzymałby mnie za rękę i powstrzymywał mnie od robienia głupich rzeczy” wśród niektórych programistów C ++. Ich zdaniem C ++ jest „prawdziwym” językiem, a jeśli nie możesz poradzić sobie z jego osobliwościami, nie jesteś „prawdziwym programistą”.
źródło
Nieco odpowiedź na temat ...
Nie martw się - jest to powszechne „zachowanie” w każdej społeczności ekspertów. I bądź szczery, jeśli jesteś dobry w jakimkolwiek języku i napotkasz kod, który jest „dziwny”, prawdopodobnie również go skrytykujesz. (ponieważ chcę TEACH).
Jestem w perlowym świecie - kiedy zobaczę coś takiego:
zamiast:
napewno to skomentuje - (czytaj: naucz autora) o
join
funkcji.W każdym razie zbyt duża krytyka przynosi efekt przeciwny do zamierzonego, a jednym z najlepszych przykładów jest następny: (wzięty z: http://perl-begin.org/humour/#How_can_I_switch_off_the_T.V..3F )
(Ten fragment został wysłany anonimowo do pastebota w dniu 23 marca 2011 r. Został umieszczony tutaj dla potomności po pewnej edycji.) - nieco zmodyfikowany
źródło
Pisząc szybko i brudnie z myślą o późniejszym naprawianiu, istnieje niebezpieczeństwo zapomnienia czegoś, co musisz naprawić.
W java nie musisz myśleć o tym, kto jest właścicielem określonego obiektu, po prostu przekazujesz referencję i zapominasz o tym, jakby to było nic. Jednak w C ++ musi istnieć jasna definicja tego, kto jest właścicielem obiektu i kto jest odpowiedzialny za jego wyczyszczenie.
Nie zrobiłbyś; C ++ jest językiem opartym na wielu paradygmatach, zdarza się, że dość dobrze obsługuje OOP, ale potrafi też robić wiele innych rzeczy. Jednak większość z nich sprowadza się do użycia odpowiedniego narzędzia do pracy zamiast wyciągania młotka za każdym razem, gdy trzeba wbić spiczasty kolec w jakieś drewno.
Powodem, dla którego otrzymałeś złą odpowiedź, jest to, że większość osób na SO ocenia umiejętności na podstawie tego, jak idiomatycznie możesz pisać w języku, o który pytasz. Ludzie znający C ++ mają tendencję do szarpania, gdy widzą zły kod, który wygląda jak coś, co gryzie ich w przeszłości.
źródło