Załóżmy, że jestem ograniczony do używania C ++ przez środowisko w projekcie. Czy dobrze jest zapobiegać korzystaniu z niektórych funkcji językowych, które ma C ++, ale Java nie ma (np .: wielokrotne dziedziczenie, przeciążenie operatora)?
Myślę, że powodem są:
- Ponieważ Java jest nowsza niż C ++, jeśli Java nie udostępnia funkcji, którą posiada C ++, oznacza to, że ta funkcja nie jest dobra, dlatego powinniśmy jej unikać.
- Kod C ++ z funkcjami specyficznymi dla C ++ (np. Funkcje znajomych, wielokrotne dziedziczenie) może być utrzymywany lub sprawdzany tylko przez programistów C ++, ale jeśli po prostu piszemy C ++ jak Java (bez funkcji specyficznej dla języka C ++), kod może być utrzymywany lub sprawdzany przez oba Programiści C ++ i Java.
- Możesz zostać poproszony o konwersję kodu na Javę
- Kod bez funkcji specyficznych dla C ++ jest zwykle łatwiejszy w utrzymaniu
- Każda funkcja specyficzna dla języka C ++ (np. Wielokrotne dziedziczenie) powinna mieć alternatywy do zaimplementowania w Javie. Jeśli nie, oznacza to, że wzór lub architektura kodu jest problematyczna.
Czy to prawda?
java
c++
code-quality
grgrr
źródło
źródło
volatile
, dostępu członków klasy prywatnej pakietu, refleksji / introspekcji, wreszcie bloków, sprawdzonych wyjątków i tak dalej? Całe to pytanie nie ma większego sensu ... C ++ i Java są powierzchownie podobne, ale ostatecznie bardzo różne języki.SomeObject a = previousObject;
robi bardzo różne rzeczy w Javie i C ++. W Javie kopiuje odwołanie, podczas gdy w C ++ kopiuje obiekt. W Javie modyfikacjea
wpłynęłyby również na poprzedni obiekt. W C ++ masz dwa oddzielne obiekty.Odpowiedzi:
Nie. Jest to żałośnie i strasznie wprowadzane w błąd.
źródło
operator<<( ostream &, T const & )
jest zazwyczaj realizowane za pośrednictwemfriend
. Taki jest problem z ogólnymi stwierdzeniami o tym, co jest dobrym językiem, a co złym: są dobrą radą, z wyjątkiem sytuacji, gdy nie są ...To, że na pierwszy rzut oka wydaje się podobna składnia, nie oznacza, że oba języki są kompatybilne.
1, 4 i 5 to tak naprawdę to samo pytanie:
Teraz nie jestem fanem C ++, ale powiedzenie „Kod bez specyficznych funkcji C ++ jest zwykle łatwiejszy w utrzymaniu” jest po prostu śmieszne - czy naprawdę wierzysz, że Java ma wszystko dobrze i wziął wszystkie dobre cechy, ignorując wszystkie złe? Czy naprawdę wierzysz, że istnieje coś, co jest uniwersalną cechą „złą” lub „dobrą”? Jeśli tak, to dlaczego nie mamy jednego języka, który jest czysto dobry? I nie, Java z pewnością nie jest tym językiem. Czy to oznacza, że Java i C ++ są bezużyteczne? Oczywiście nie.
Co się stanie, jeśli Twoi liderzy zdecydują się na przeniesienie do C #, a nie Java? C # nie tylko obsługuje nadpisywanie operatorów, ale jest także domyślny - jeśli chcesz, aby ludzie używali np.
obj.Equals(obj2)
Zamiastobj == obj2
, ludzie będą popełniać błędy przez cały czas. Nawet jeśli trzymasz się tylko wspólnych cech tych dwóch języków, są inne oczekiwania , inna kultura. Jeśli zrobisz cośif (myField == null)
w C ++, ludzie zobaczą, że jesteś nowicjuszem. Jeśli używaszif (null == myField)
w C #, ludzie zobaczą, że tak naprawdę nie jesteś jeszcze natywny w C # - powody, dla których programiści C nauczyli się korzystać z wariantu „odwróconego”, nie istnieją już w C #.Korzystając z Twojej logiki, powinniśmy utknąć w kodzie maszynowym lub asemblerze, lub w języku COBOL, ponieważ dlaczego kiedykolwiek miałbyś zmienić się na coś takiego jak Pascal, gdy tylko dodaje on nowe funkcje, których Twoi programiści będą musieli się nauczyć? Dlaczego mielibyśmy używać czegoś takiego jak SQL, skoro nie ma nawet pętli ? Dlaczego mielibyśmy używać czegoś innego niż SQL, skoro SQL nie ma pętli, a X ma?
Kod C ++ z pewnością nie może być utrzymywany przez programistów Java. Nie rozumiem, skąd wziął się ten pomysł - co dokładnie pozostaje, gdy ograniczysz C ++ do funkcji, które działają dokładnie tak samo jak w Javie? Nie dostaniesz nawet wywołań metod - nawet wywołań funkcji . Ponownie, tylko dlatego, że obie języki używają nawiasów klamrowych, nie oznacza, że języki są w żaden sposób zamienne.
Konwersja kodu C ++ podobnego do języka Java będzie bardzo podatna na błędy bez względu na to, co robisz. Jest po prostu zbyt wiele różnic. Jeśli zależy ci na przepisaniu aplikacji w innym języku, pomyśl o rozsądnych sposobach modularyzacji wszystkiego, abyś mógł wymienić części bez zepsucia całości. Ale w końcu YAGNI - bez względu na to, co robisz, przygotowanie kodu do konwersji na Javę będzie wiązało się ze znacznymi kosztami. To czas, który najprawdopodobniej lepiej spędzić na dodawaniu lub ulepszaniu swoich funkcji.
Używamy różnych języków, ponieważ dają nam inny zestaw narzędzi do rozwiązywania problemów. Jeśli potrzebujesz plików wykonywalnych, które działają „wszędzie”, skorzystaj z Java. Jeśli potrzebujesz kodu, który kompiluje się „wszędzie”, C ++ działa dobrze. Jeśli chcesz kodu łatwego do zrozumienia i przeanalizowania, skorzystaj z LISP lub cokolwiek innego. Ale mogę ci powiedzieć jedno - pisanie kodu w jednym języku tak, jakbyś pisał go w innym, jest zawsze błędem i będziesz cierpieć. Nie wspominając już o tym, że kiedy faktycznie zatrudnisz faceta w C ++, on uruchomi sekundę, kiedy zobaczy kod „kompatybilny z Javą”. I ... facet z Javy zrobi to samo. Wiesz, nawet „znając” zarówno C ++, jak i Javę, bym działał jak diabli :)
Właściwie musiałem pracować nad (zwykłym) kodem C napisanym przez programistę Pascal, który wydawał się myśleć tak jak ty. Użył
#define
s, aby przedefiniować C, aby wyglądać bardziej jak Pascal, wraz z takimi rzeczami, jak „POCZĄTEK przekłada się na {”. Rezultat był raczej przewidywalny - kod, którego ani C, ani programiści Pascal nie mogą zrozumieć, i pełen błędów, które były wynikiem przeciekającej „abstrakcji” Pascala nad C. A Pascal i C są prawie identyczne z dzisiejszego punktu widzenia. Nawet przejście na C <-> C ++ jest znacznie bardziej zróżnicowane, a to wciąż orzeszki dla czegoś takiego jak C ++ <-> Java.źródło
myFunc()
porównaniu(myFunc)
), i to ma bardzo dobry powód. Języki oparte na LISP są nadal bardzo popularne, szczególnie wśród ludzi matematyki / fizyki. Najważniejsze jest to, że języki LISPy są bardzo nieznane współczesnym programistom w stylu C - ale to nie jest powód, aby je ignorować. Schemat, Clojure oraz w pewnym stopniu języki oparte na ML (OCaml, F # ...) są naprawdę bardzo LISPy.if (myField == null)
jakoif (myField = null)
, który skompiluje dobrze C / C ++, ale prawdopodobnie nie zrobi tego, co zamierzałeś. Z drugiej stronyif (null = myField)
wyrzuci błąd, ponieważ nie można przypisać stałej.Odpowiem na twoje pytania po kolei.
Tak, każda funkcja nieobecna w Javie jest przekleństwem na dysku twardym. Musi zostać wypalony z bazy kodu. Ci, którzy nie będą posłuszni, będą prześladowani, a ich dusze będą wykorzystywane do uspokajania bogów RAID.
W razie wątpliwości napisz kod dla najmniej kompetentnego członka zespołu. Kod jest odczytywany znacznie częściej niż jest napisany, a kod, który jest tak sprytny, jak potrafisz pisać, jest zbyt sprytny, aby go czytać. Recenzje kodu, których nie rozumieją pracownicy recepcji, należy odrzucić. Aby pomóc, naucz ich programowania w języku Visual Basic 2.0 przez weekend, a następnie naśladuj styl kodowania w dowolnym języku, którego używasz.
Prawdziwe! Ale po co zatrzymywać się na Javie? Możesz zostać poproszony o konwersję kodu na podstawowy, asembler i / lub perl jeden dzień. Ponieważ istnieją interpretery Perla w każdym języku, po prostu napisz swój program jako długi ciąg perla i wgraj w niego argumenty w wybranym języku.
Teraz, gdy musisz zmienić język, po prostu przepisz kod zawijający łańcuch perla.
Prawdą jest, że kod, który wykorzystuje mniej funkcji, jest łatwiejszy w utrzymaniu. A ponieważ wszystkie języki są równoważne Maszynie Turinga, a Maszyna Turinga ma najmniej funkcji w jakimkolwiek języku programowania, powyższy interpreter perla faktycznie uruchamia Maszynę Turinga (taśma i wszystkie), która rozwiązuje twój problem.
Funkcje specyficzne dla języka C ++ mają cenne zastosowanie. Ponieważ nie są Javą, są przekleństwem, a ci, którzy z niej korzystają, mogą być markowymi heretykami. Gdyby C ++ nie miał tych funkcji językowych, nie byłbyś w stanie znaleźć tych, które musisz poświęcić. Funkcje języka C ++ rozwiązują problemy!
Look, C ++ i Java mają inny zestaw możliwości. Programowanie na przecięciu C ++ i Java skutkuje kodem, który odrzucił większość zalet obu języków.
Java została opracowana częściowo w reakcji na pewne nadużycie funkcji C ++. Nie oznacza to, że reakcja była uzasadniona, zwłaszcza lata później, kiedy cechy już dojrzały.
Możesz robić okropne rzeczy z przeciążeniem operatora; ale żaden język nie może zapobiec napisaniu okropnego kodu w tym języku, chyba że powstrzyma to napisanie całego kodu w tym języku.
Możesz także robić bardzo eleganckie rzeczy z przeciążeniem operatora. Proste rzeczy, takie jak liczba zespolona lub klasa macierzy, która działa jak liczba zespolona lub macierz.
Należy zachować ostrożność przy korzystaniu z funkcji C ++ niedostępnych w Javie. To, że obecny zestaw programistów na ich obecnym poziomie umiejętności nie rozumie funkcji, nie oznacza, że nigdy nie należy jej używać; jednocześnie, tylko dlatego, że możesz użyć funkcji, nie oznacza, że powinieneś. Jednak w sklepie z dużą ilością Java szanse na opór będą silniejsze niż powinny w stosunku do funkcji innych niż Java.
Konwersja kodu między językami najlepiej jest przerobić, bez względu na to, jak strukturalnie są one podobne. Każda próba zrobienia tego bez takiego przepisywania zakończy się niepowodzeniem.
Wiele funkcji specyficznych dla C ++ to cuda w utrzymaniu. Usuwanie typu (jak
std::function
) pozwala rozdzielić hierarchie, co zmniejsza zależności. Inteligentne wskaźniki i deterministyczne czasy życia oraz RAII zmniejszają niespodzianki w czasie wykonywania i usuwają podstawową zasób zasobów. Ciężkie, statyczne kontrole typu oznaczają, że kod nie kompiluje się, a nie działa. Wtyczki zmniejszają powielanie kodu. ADL pozwala na niezależne ad-hoc rozszerzanie interfejsów między hierarchiami typów. Lambda pozwala pisać kod obok miejsca, w którym jest używany. Przekazywanie i przenoszenie zmniejsza liczbę kopii i sprawia, że programowanie w stylu funkcjonalnym (bez efektów ubocznych) jest wydajne. Przeciążenie operatora zmniejsza szum linii i sprawia, że kod wygląda bardziej jak matematyka, którą modeluje.Uważaj na dół Turinga Tar. Możesz zaimplementować wszystko w dowolnym języku (w tym surową maszynę Turinga z taśmą), ale to nie znaczy, że powinieneś . Emulowanie funkcji C ++ przy użyciu konstrukcji języka Java w C ++ jest okropnym pomysłem; spowoduje to niemożliwy do utrzymania kod, którego nikt nie będzie w stanie odczytać ani zrozumieć.
Możesz czerpać inspirację z projektów Java i przenieść je do C ++. Jestem wielkim fanem przyjmowania funkcji języka Python i implementowania ich w C ++, ponieważ podoba mi się składnia. Ale to nie znaczy, że piszę metody klas jako metody statyczne, biorąc jawne „ja”, a następnie piszę opakowanie, które przekazuje do niego wywołanie metody niestatycznej.
Nowoczesne C ++ nie jest tak bardzo podobne do języka emulowanego i odrzucanego przez Javę. Nie daj się zablokować funkcjom jednego języka; nie ma „jednego prawdziwego języka”. Dowiedz się o nowych językach i ich funkcjach oraz chłonąć ich odrębność.
źródło
Odpowiem tylko na twoje powody:
źródło
delete
.delete
. Z tego co pamiętam, w co najmniej jednym z tych przypadków dynamiczna alokacja (new
) również nie była potrzebna.make_shared
.Java ma funkcje, których C ++ nie ma, takie jak wbudowany, szybki i niezawodny moduł wyrzucania elementów bezużytecznych, hierarchia obiektów z jednym katalogiem głównym i potężna introspekcja.
Inne funkcje Javy są zaprojektowane tak, aby współpracowały z funkcjami wyłącznymi dla Javy, a wiele pominiętych przez Javy funkcji C ++ jest możliwych, ponieważ nowe funkcje nadrabiają brak. Na przykład Java nie ma obiektów alokowanych na stosie z deterministycznymi destrukatorami, ale w końcu ma bloki (i try-with-resources od Java 7) oraz moduł wyrzucający elementy bezużyteczne.
C ++ nie ma w końcu bloków ani wyrzucania elementów bezużytecznych. Jeśli nie używasz destruktorów, ponieważ nie istnieją one w Javie (nie liczę finalizatorów), jesteś na poziomie zarządzania zasobami C (tj. Wszystkie ręcznie), z tym wyjątkiem, że nie możesz nawet pogrupować swojego czyszczenia do bloku czyszczenia, do którego musisz przejść, ponieważ Java też go nie ma. Czy naprawdę uważasz, że poprawia to łatwość konserwacji?
Java ma nadrzędną hierarchię obiektów, w której każda klasa ostatecznie wywodzi się z Object, a kilka prymitywnych typów można również automatycznie umieszczać w takich klasach. Umożliwia to jednokrotne pisanie pojemników z obiektami w celu przechowywania wskaźników do obiektu. Java 5 wprowadziła generyczne, które pozbywają się rzutów, których wymagają takie kontenery, ale nadal kompilują się do prawie tego samego kodu.
C ++ nie ma takiej hierarchii. Aby ułatwić pisanie kontenerów, które działają dla wielu typów, korzystasz z szablonów, które są schematami tworzonymi przez kompilator w razie potrzeby dla różnych typów. Czy zabronisz używania szablonów (i makr) i pójdziesz drogą C, pisząc ciągle ten sam kod kontenera dla różnych typów, lub używając pustych wskaźników? (Czekaj, Java nie ma pustych wskaźników!) Czy jesteś pewien, że zwiększy to łatwość konserwacji?
Przyzwoity język ma wiele funkcji zaprojektowanych do współpracy. Zabraniając funkcji z języka A, ponieważ język B ich nie ma, kalekujesz język A, ponieważ nie dodajesz jednocześnie funkcji z B, które sprawiają, że B jest spójną całością.
Nie oznacza to, że nie wolno ograniczać dozwolonych funkcji C ++. C ++ jest dużym, historycznie rozwijanym językiem, który kładzie nacisk na umożliwienie programiście robienia tego, co chce, nad bezpieczeństwem i łatwością użycia, i nie wszystkie jego funkcje w całej ich elastyczności są niezbędne do tworzenia dobrych programów. Istnieje wiele standardów kodowania, które ograniczają korzystanie z niektórych funkcji; na przykład wytyczne Google w większości zabraniają wielokrotnego dziedziczenia, złożonych szablonów i wyjątków (choć ten ostatni jest z przyczyn historycznych). Ale żadna funkcja nie jest zabroniona „ponieważ Java jej nie ma”; funkcje są rozważane w ramach samego C ++.
źródło
Object
jest prawievoid*
do większości zastosowań - wciąż, fuj.finally
nie zastępuje ich. Te dwa języki są zasadniczo różne.Zastanawiałem się, czy nie zawracać sobie głowy publikowaniem kolejnej odpowiedzi, gdy już masz numer, który wydaje się całkowicie rozsądnymi wnioskami: że twój pomysł jest w zasadzie katastrofą, która czeka na nadejście. Myślę jednak, że nie podali oni bardzo istotnych powodów takiego wniosku.
Różnice między Javą a C ++ sięgają znacznie głębiej niż szczegóły, na których wydajesz się skupiać.
Na przykład mówisz o zakazie wielokrotnego dziedziczenia w C ++. Po pierwsze, zwrócę uwagę, że po prostu tego nie rozumiem. Java definiuje „interfejsy” jako oddzielne rzeczy od „klas”. Jedna klasa dziedziczy po tylko jednej innej klasie, ale może implementować dowolną liczbę interfejsów.
C ++ nie rozdziela w ten sposób dwóch pojęć. Najbliższy analogowe C ++ zapewnia interfejs do wdrożenia w Javie jest dziedziczenie z innej klasy. W związku z tym, aby utrzymać dwa wyrównane w miarę dobrze, prawdopodobnie musisz użyć wielokrotnego dziedziczenia w C ++, ale chcesz ograniczyć niektóre z tych klas podstawowych w mniej więcej taki sam sposób, w jaki Java ogranicza interfejs w porównaniu do klasy (tj. Zasadniczo że określa podpisy funkcji, ale przynajmniej nie implementacje).
To jednak ledwo zarysowuje rzeczywiste różnice między nimi. W rzeczywistości, gdzie kod Java prawdopodobnie definiuje interfejsy i klasy, które implementują te interfejsy, kod C ++ jest znacznie bardziej prawdopodobne, aby zdefiniować niektóre szablony, które będą działać z dowolną klasą, która spełnia jej wymagania (nie tylko te zdefiniowane specjalnie do implementacji interfejsu (s) określa).
Jeśli naprawdę chcesz kodu, który jest w zasadzie „Javą używającą składni C ++”, prawie na pewno będziesz musiał zabronić czegokolwiek i wszystkiego podobnego do tego ostatniego. Musisz ograniczyć korzystanie z szablonów do z grubsza poziomu „kontenera T”, który obsługuje generyczne Java. Niestety, zrobienie tego spowoduje kod C ++, który jest takim bałaganem, że nikt nie jest w stanie utrzymać go tak, jak jest teraz, nie wspominając o długoterminowej możliwości przetłumaczenia go na inny język programowania.
Jeśli naprawdę chcesz kodu, który można w przyszłości przekonwertować na inny język, postaraj się, aby był on jak najbardziej czysty i czytelny. Idealne jest, aby napisać pseudo-kod i nadal go uruchamiać. Dobrze napisane nowoczesne podejście do C ++ idealnie pasuje do tego znacznie bliżej niż sugerowany przez ciebie podzbiór. Bez względu na to, jak go napiszesz, jeśli kiedykolwiek tłumaczysz na Javę, będziesz musiał faktycznie przetłumaczyć kod, a nie tylko składnię poszczególnych instrukcji.
źródło
Jeśli masz zamiar napisać kod w języku X, poświęć czas na odpowiednią naukę języka i skorzystaj ze wszystkich oferowanych przez niego funkcji, aby pomóc Ci rozwiązać problem. Złe rzeczy dzieją się, gdy próbujesz wykonać tłumaczenie „słowo w słowo” z jednego języka na inny, czy to z japońskiego na angielski, czy z Java na C ++. O wiele lepiej jest zacząć od dobrego zrozumienia problemu i wyrazić rozwiązanie w sposób najbardziej naturalny dla używanego języka.
Wiele lat temu widziałem program w języku C, który nie miał wcięcia, a każda instrukcja zaczynała się w kolumnie 7, ponieważ autorem kodu był programista z Fortranu, który akurat używał C. Inni programiści z Fortranu martwili się tymi nowymi modami zwanymi wskaźnikami. Nie miałem serca wspominać wskaźników do wskaźników, myślę, że zemdlałyby na miejscu.
Wyobraź sobie, że zatrudnisz kogoś, kto utrzyma ten kod w przyszłości. Jeśli jest to dobry kod C ++, będziesz mógł zatrudnić kompetentnego programistę C ++ i powinien on być w stanie znaleźć drogę. Jeśli jest to „Java w C ++”, to ani programiści C ++, ani Java nie będą mieli łatwego zrozumienia kodu.
źródło
Wszystkie twoje powody mogą zostać obalone:
Nie oznacza to, że funkcja nie jest dobra (żadna funkcja nie może być z natury zła). Oznacza to tylko, że funkcja była często niewłaściwie używana (lub niemożliwa do wdrożenia z powodu podstawowych pojęć, takich jak bezpośrednie wskaźniki vs. wyrzucanie elementów bezużytecznych). Java z definicji ma być łatwiejsza i bardziej przyjazna dla programistów, stąd usunięcie funkcji, które okazały się łatwe do nadużyć.
Och, może być? Zobaczmy najprostszy kod C ++:
Ups, nie używa się funkcji „specyficznych dla języka”, ale jest to już niemożliwe do utrzymania przez programistów Java! Ponieważ w Javie dereferencje dotyczą „.” podczas gdy tutaj jest to „->.
Lub C #. Lub Haskell. Lub Python. Lub Ruby. Lub COBOL (tak, możesz!). Jak możesz powiedzieć o przyszłości?
Dokładnie odwrotnie. Każda funkcja została wprowadzona w celu ułatwienia programowania, a tym samym łatwiejszej konserwacji. Np .: weź program działający na liczbach zmiennoprzecinkowych. Teraz zaktualizuj go, aby obsługiwał liczby zespolone. Przeciążenie operatora na ratunek!
Ale Java DOES ma wiele dziedziczeń! Nazywa się to „interfejsem”. Implementacja Java jest problematycznym obejściem, aby uniknąć przerażającego diamentu spowodowanego tym, że wszystko pochodzi
Object
. Odbywa się to poprzez wprowadzenie,interface
którego jedynym celem jest bycie czymś, co nie pochodziObject
. C ++ nigdy nie miał tego problemu - nie ma obowiązkowej wspólnej podstawy, więc każda klasa może funkcjonować jako interfejs bez przerażającego diamentu.Uwaga dodatkowa: Java niedawno wprowadziła ... konkretne metody w interfejsach. Dodano funkcję C ++ zawsze musiał rozwiązać problem, którego nigdy nie było.
Wspomniałeś też tylko o kilku „rzeczach, które ma C ++, ale Java nie”. Jedną z największych różnic między C ++ a Javą jest kontrola nad układem pamięci. Możesz utworzyć tablicę wskaźników do obiektów (tak jak w Javie) LUB możesz stworzyć ciągły blok pamięci. Teraz, gdybym się martwił o funkcję C ++, która może wprowadzać w błąd programistów Java, coś tak ukrytego i subtelnego, jak ten, znalazłby się na mojej liście znacznie wyżej niż oczywiste i rozpoznawalne na pierwszy rzut oka rzeczy takie jak wielokrotne dziedziczenie lub przeciążone operatory.
Konkluzja: Czysty kod to czysty kod. Java lub C ++ - ta sama różnica. Po prostu to proste. Niepotrzebne komplikacje są główną przyczyną złego kodu.
źródło
Nie, ogólnie nie powinieneś pisać w C ++ tak jak w Javie i zdecydowanie nie powinieneś pomijać funkcji języka C ++, które nie są obecne w Javie.
Po pierwsze, Java jest śmieciami i dlatego nie ma odpowiednika słowa kluczowego „delete” w C ++. W porządku, więc wdrażasz program bez usuwania, ponieważ zgodnie z twoimi regułami jest to niedozwolone.
Gratulacje, masz teraz wyciek pamięci;). To też nie jest teoria - widziałem, że dokładnie taka sytuacja ma miejsce w grze typu open source.
Podobnie Java nie ma żadnych wskaźników podobnych do C ++, co wyklucza wiele typowych konwencji wywołań funkcji.
Istnieją funkcje C ++, których powinieneś unikać (patrz poniżej), ale „nie bycie w Javie” nie jest dobrym testem lakmusowym.
Lepsze wytyczne byłyby następujące:
Pozycja (3) oznacza, że nie powinieneś mieć kodu dla programistów Java w C ++ bez przeszkolenia ich w C ++. Istnieją pewne subtelne, ale bardzo ważne różnice, których mogą się nie nauczyć, jeśli próbują potraktować to jak dziwny dialekt języka Java.
Pozycja (2) oznacza, że jeśli twój zespół jest niewygodny w przypadku wielokrotnego dziedziczenia (na przykład) i jeśli istnieje odpowiednie rozwiązanie, które go nie używa, może być wskazane użycie tego alternatywnego rozwiązania. Zależy to jednak konkretnie od twojego zespołu. Z drugiej strony, jeśli twój zespół jest bardziej niewygodny z tym alternatywnym rozwiązaniem niż z wielokrotnym dziedziczeniem, użyj wielokrotnego dziedziczenia!
Wreszcie istnieją C ++ cechy językowe C ++, których prawdopodobnie należy unikać. Jeśli chcesz wiedzieć, co to jest, zapytaj programistów C ++ , a nie programistów innego języka. Niektóre przykłady na początek to arytmetyka wskaźników (brak uniwersalnego konsensusu) i goto.
źródło
W innych odpowiedziach jest już kilka dobrych punktów, ale chciałbym udzielić bardziej kompletnej odpowiedzi, odpowiadając indywidualnie na pytania i wypowiedzi.
Odpowiedzi na to dość dobrze: Java nie jest „dobrą częścią” C ++, ani nie ma powodu, aby tak sądzić.
W szczególności, chociaż zalety każdej indywidualnej funkcji C ++ są dyskusyjne, wiele funkcji C ++ 11 / C ++ 14, które nie są częścią Javy, niekoniecznie jest wykluczonych, ponieważ projektanci Javy uznali, że to zły pomysł. Przykładowo, do wersji 8 Java nie miała lambd, ale zostały wprowadzone do C ++ w standardzie C ++ 11. Przed wersją Java 8 twoje założenie, że brakuje funkcji C ++ w Javie z założenia, ponieważ „nie są one dobre”, sugerowałoby, że lambdy jako funkcje językowe są „nie dobre” (ku przerażeniu LISPerów na całym świecie, chociaż są prawdopodobnie wystarczająco przerażony, by usłyszeć, że podobno naprawdę lubisz Javę). Ale teraz projektanci Java umieścili swój znaczek zatwierdzenia (TM) na lambdas, więc teraz są dobrą rzeczą.
Aby zagłębić się nieco głębiej, nawet w Javie 8, lambdas-as-closures nie są tak elastyczne jak lambd C ++ 14, ale może to wynikać raczej z ograniczeń architektury JVM niż świadomej decyzji, że bardziej elastyczne podejście jest złe perspektywa projektowania języka.
To jest główna rzecz, na którą chciałem odpowiedzieć.
Ogólnie rzecz biorąc, uzyskiwanie recenzji kodu od programistów, którzy nie są w pełni zaznajomieni z używanym językiem, może mieć pewną wartość. Mogą udzielać cennych informacji zwrotnych na temat przejrzystości nazw i komentarzy funkcji / metod oraz (jak prawidłowo sugeruje twoje pytanie), jeśli język jest podobny do jednego lub więcej języków, które już znają, mogą być w stanie śledzić podstawowy przebieg programu i potencjalnie wyłapać błędy logiczne.
Jednak to nie przypadek, że tego rodzaju przeglądu nigdy nie będzie „tak dobre jak” lub „równoważne” test z programistów, którzy rzeczywiście znają język, którego używasz. Zasadniczo dzieje się tak dlatego, że sprawienie, by jeden język wyglądał jak inny, zwykle ukrywa subtelne różnice, podczas gdy sprawienie, aby jeden język zachowywał się tak, jak inny (szczególnie w przypadku C ++ i Java), może być nie-idiomatyczny dla języka i / lub może być zbyt mylący dla recenzentów.
Najpierw zastanówmy się, co to znaczy, że C ++ „wygląda jak” Java. W prostym przypadku możesz użyć
new
do tworzenia instancji obiektów, tak jak w Javie:Ale obiekty instancja ten sposób wykorzystania
->
zamiast.
do wywołania metody, więc jeśli chcesz metoda nazywa się wyglądać jak Java, należy zamiast pisać:Ale to nie jest idiomatyczne; w szczególności pamięć musi zostać później wyczyszczona za pomocą
delete &foo
, czego niektórzy doświadczeni deweloperzy C ++ mogą nawet nie zdawać sobie sprawy, że jest to legalny kod . Tak czy inaczej, są śmieszne symbole non-Java-jak posypane przez cały czas, więc nie możemy dość uczynić język „wyglądać” Java. (Możesz wyeliminować,*new
używając#define New *new
, lub, co gorsza,#define new *new
ale wtedy prosisz innych programistów, żeby cię nienawidzili.) I, jak wspomniano powyżej,delete
nie istnieje w Javie, więc w każdym razie (jak wspomniano w innej odpowiedzi ), tak naprawdę nigdy nie można sprawić, aby użycie obiektu „wyglądało” tak jak w Javie bez wycieków pamięci.Ale współczesne C ++ zawiera inteligentne wskaźniki wspólne, które zachowują się podobnie do zarządzanych pamięci Java zmiennych. Wszędzie w Javie, gdzie można pisać
Foo foo = new Foo();
, można zamiast tego napisać:Teraz używasz funkcji językowej, która w rzeczywistości przypomina Java pod maską. Ale nagle masz wiele do wyjaśnienia recenzentom spoza C ++: co to jest
shared_ptr
? Jakie są subtelne, skomplikowane „gotchas”make_shared
? (Wykorzystuje doskonałe przekazywanie, które ma pewne przypadki awarii i może prowadzić do wywołania „niewłaściwego” konstruktora.) Dlaczego metody muszą być wywoływane za pomocą->
, ale.
kompilator zezwala na używanie z niektórymi metodami? (shared_ptr
ma swoje własne metody.) Jeśli metodaFoo::reset(void)
istnieje, nieostrożny programista może spróbować ją wywołaćfoo.reset()
, co (jeśli istnieje tylko jeden wspólny wskaźnik wskazujący na to wystąpienieFoo
momentu wywołania) spowoduje usunięcie pamięci podstawowej i unieważnieniefoo
, oraz Deweloperzy Java raczej nie złapią tego problemu.Ponadto, C ++ ma wiele z pułapek , które są specyficzne dla języka. Jak mogę najlepiej powiedzieć, większość programistów C ++ uczy się radzić sobie z tymi pułapkami, stopniowo rozwijając swój własny idiom dotyczący „bezpiecznych” praktyk C ++, co często jest w pewnym stopniu unikalne dla nich lub dla ich zespołu programistów (patrz na przykład istniejąca odpowiedź, która wspomina Praktyki kodowania Google i komentarz na ten temat, że „doświadczeni weterani C ++ zwykle odrzucają wytyczne Google dotyczące kodowania”). Wszystkie twierdzenia, że język może być zbyt skomplikowany, jak się wydaje (przynajmniej z mojego doświadczenia), zazwyczaj spotykają się z pewną odmianą „no cóż, przestań go źle używać”. Zdaję sobie sprawę, że jest to bardzo negatywny pogląd na społeczność C ++, a na pewno są doświadczeni programiści chętniej pomagający uczącym się języków, ale tak jest wydają się być pewną obroną przed np. niezdefiniowanym zachowaniem (patrz na przykład większość dyskusji w moim linku „pułapki” powyżej).
Programiści Java po prostu nie będą pomocni w znajdowaniu i korygowaniu tych pułapek poprzez przegląd kodu.
Jest to całkowicie poprawne - godne pochwały, nawet - próba uwzględnienia tego, co może się stać z twoim kodem w przyszłości, gdy będziesz w fazie projektowania.
Ale po pierwsze, ta szczególna uwaga wydaje się być zdalną możliwością: kod jest zwykle albo ponownie używany, jak jest (na przykład możesz podłączyć część lub całość działającego kodu C ++ do jakiegoś przyszłego oprogramowania Java za pomocą interfejsu JNI) lub przepisać całkowicie niż bezpośrednio „transkrybowane”.
Po drugie, później powiesz:
To zasadniczo anuluje punkt „konwersji na Javę”. Jeśli oprogramowanie jest napisane w idiomatic C ++, a następnie przekonwertowane na idiomatic Java, nie ma powodu oczekiwać, że ta konwersja zostanie (lub mogłaby!) Zostać wykonana poprzez zastosowanie dokładnego odwzorowania funkcji C ++ w stosunku do funkcji Java.
Nie jest jasne, co masz na myśli, ale w pewnym stopniu zgadzam się z częścią tego: chyba że jesteś bardzo ostrożny, a nawet jeśli jesteś ostrożny, funkcje C ++ mogą prowadzić do problemów z utrzymaniem. C ++ FQA Lite (strona krytycznie o języku i jego zwolenników od kogoś, kto przynajmniej wydaje się właściwie zrozumieć to dość dobrze) stwierdza, że
UWAGA: Jeśli jesteś fanem C ++ i przejdziesz do tego punktu w mojej odpowiedzi i masz ochotę zeskoczyć do komentarzy, aby argumentować, że autor FQA tak naprawdę nie rozumie C ++ lub jest nieuczciwy w większości swoich argumentów , zauważ, że (1) dokładnie dwa zdania po zacytowaniu go potwierdzam, że FQA jest bardzo stronniczym źródłem i (2) tak naprawdę nie ma znaczenia, co próbuję powiedzieć, czy autor FQA rozumie C ++ , i nie próbuję obalić C ++, i powinieneś przeczytać resztę postu, nie zakładając, że jestem anty-C ++ tylko dlatego, że zacytowałem FQA. Koniec noty.
Podobnie, Linus Torvalds nienawidzi C ++ zasadniczo z tego powodu (ostrzeżenie: link zawiera wiele przekleństw, w prawdziwie niesławnym stylu Linusa).
Oczywiście są to bardzo stronnicze podejście do tej kwestii, ale nawet zwolennicy C ++ często twierdzą, że nie powinieneś używać całego zestawu funkcji językowych (ponownie, przeczytaj wytyczne Google dotyczące kodowania; także Bjarne Stroustrup, twórca C ++ , publicznie stwierdził: „W C ++ istnieje dużo mniejszy i bardziej przejrzysty język, który próbuje się wydostać”).
Sądzę więc, że istnieje pewna zaleta, że funkcje C ++ mogą być zbyt łatwe do niewłaściwego użycia, szczególnie jeśli pochodzisz z języka Java. Ponadto warto zaspokoić te problemy, ograniczając się do niektórych podzbiorów języka.
Jednak decydowanie o tym, który podzbiór ma być użyty w oparciu o inny język, nie wydaje się właściwym podejściem, chyba że „innym językiem” jest C, ponieważ tak naprawdę istnieje podzbiór C języka podobnego do C. (Linus odnosi się do tego w powyższym rantzie, a Scott Meyers nawet odnosi się do tego podzbioru jako „podjęzyka”). Paradygmat czasu wykonywania Javy (odśmiecanie, uruchamianie na maszynie wirtualnej) jest tak zasadniczo odmienny od C ++, że jest to nie jest jasne, że istnieją użyteczne lekcje na temat korzystania z C ++, a jak wspomniano powyżej, próba wyciągnięcia lekcji na temat C ++ bezpośrednio z Javy może prowadzić do bardzo nieidiomatycznego kodu.
Zamiast tego spróbuj zdefiniować „akceptowalny podzbiór” języka, rozumiejąc, jak można go używać idiomatycznie. Jeśli chcesz dość restrykcyjnego podzbioru, który nadal korzysta z wielu funkcji C ++ wykraczających poza to, co oferuje C, wspomniane wyżej wytyczne Google Coding mogą być dobrym miejscem na rozpoczęcie. Jasne, dostaniesz programistów, którzy twierdzą, że nie ma „żadnego racjonalnego argumentu” dla niektórych ograniczeń Google , ale jeśli nie chcesz zatrudnić Alexandrescu z dala od jego pracy nad językiem D (który sam powinien ci coś powiedzieć), to jest to prawdopodobnie dobrze. Jest to z pewnością lepsze niż próba przekształcenia C ++ w Javę.
Innym dobrym punktem wyjścia dla zestawu wytycznych dla kodu są nowe Wytyczne dla C ++ , będące w trakcie opracowywania przez Bjarne Stroustrup i Herb Sutter.
Jedynym innym sposobem radzenia sobie z niedociągnięciami C ++ jest wybór innego języka. Wygląda na to, że lubisz Javę i uważasz, że istnieje szansa, że ten projekt zostanie ostatecznie przekształcony w Javę. Jak zauważono w innej odpowiedzi, możesz po prostu ... zacząć od Javy.
Są dwa powody, dla których naprawdę możesz potrzebować czegoś innego niż Java:
Już trochę to rozwiązałem, ale celowo pominąłem twoje drugie zdanie.
Nie jestem przekonany, że coś takiego
constexpr
, co nie miałoby sensu w języku częściowo JIT, takim jak Java, wskazuje na nieprawidłową architekturę. Jestem bardziej otwarty na pomysł, że nadmierne korzystanie z meta-programowania szablonów może być większym problemem niż jest to warte, szczególnie teraz, gdyconstexpr
istnieje do przeprowadzania oceny funkcji czasu kompilacji, ale wynika z tego,constexpr
że nie ma wady projektowej, jeśli używam go: po prostu upewniasz się, że niektóre obliczenia występują nawet przed uruchomieniem kodu, co jest niesamowitym wzrostem wydajności (zobacz na przykład ten wpis dotyczący problemu n-body w grze Benchmark Game , który przewyższa każdy inny wpis z wyjątkiem innego napisany w C ++,źródło
import SomeVeryBasicPackage
i po prostu to zrobiłeś ?” Zadaj pytanie zaawansowany i pierwsza odpowiedź jest niemal nieuchronnie wzdłuż linii „Dlaczego nieimport SomeMagicalPackage
i po prostu zrobić to ?”Nie.
Jeśli „w środowisku projektu” jesteś ograniczony do posługiwania się C ++, to nie ma sensu nawet myśleć o jakiejkolwiek innej technologii, bez względu na to, jak bardzo osobiście wolisz / mam nadzieję, że będziesz go używał / ewangelizował.
To, czy „Technologia X” czy „Y” obsługuje jakąkolwiek daną funkcję, nie powinno mieć żadnego wpływu na sposób, w jaki budujesz aplikację C ++.
Jest to aplikacja C ++, prawdopodobnie z jakiegoś „dobrego powodu” (teraz lub w przeszłości), więc powinieneś napisać ją jako aplikację C ++, używając tego, co zapewnia ten „zestaw narzędzi”.
Jeśli i kiedy istnieje potrzeba przeniesienia aplikacji na inną technologię, wtedy (i tylko wtedy) możesz rozważyć funkcje na innych platformach. Nie ma sensu „obcięcie nosa do przekór twarzy” na znikoma szansa, że coś może się wydarzyć. Pamiętaj jednak, że hurtowe przepisywanie jest kosztowną, ryzykowną operacją, której kierownictwo raczej nie podejmie bez uzasadnionego powodu.
Podobna debata („używać lub nie używać”) była kilka lat temu w świecie Visual Basic [.Net], gdzie ktoś miał świetny pomysł, aby pisać aplikacje Visual Basic bez używania żadnego z [podstawowych języków] funkcjonalność zapewniana przez przestrzeń nazw Microsoft.VisualBasic. To byłoby jak próba napisania aplikacji w C ++ bez przestrzeni std :: names; OK, jest to możliwe, ale dlaczego, u licha, ktoś przy zdrowych zmysłach miałby to robić?
źródło
Microsoft.VisualBasic
nazw jest trochę rozciągnięta. Minęło wiele lat, odkąd go ostatnio używałem, ale przynajmniej na początku było to głównie ukierunkowane na wsteczną kompatybilność z VB6 (i / lub aby programiści VB6 czuli się jak w domu); w większości zapewniał funkcjonalność, która była już dostępna w pozostałej części frameworka w bardziej nowoczesnej (i lepiej zintegrowanej) formie, więc w nowych projektach rzadko ma sens używanie go. Przeciwnie, wstd::
przestrzeni nazw znajduje się cała standardowa biblioteka - unikanie jej byłoby jak unikanie całej BCL w .NET.Wszystkie obecne odpowiedzi mówią, że jest to zła rzecz, ponieważ powinieneś skorzystać z używanego języka, a także wyjaśnić, dlaczego funkcja C ++ nie jest „zła” tylko dlatego, że nie jest w jave. Odpowiem na to z innej strony.
Jedną rzeczą jest unikanie złożonej funkcji C ++, takiej jak wielokrotne dziedziczenie, przeciążanie operatora i definiowanie własnego szablonu.
Ale każdy problem, który wykonuje coś więcej niż najprostsze zadanie:
Nie ma wspólnego podzbioru Java i C ++, który pozwala na powyższe, dlatego nie można zrobić tego, o co pytasz. (Gdybyś pytał o Javę i C #, miałbyś dużo większą szansę, ponieważ obaj używają śmieciarek.)
Jednak może być wymagane napisanie kodu, aby programista Java mógł zrozumieć, co robi (ale nie szczegółowe „jak”), co byłoby rozsądne.
Możesz także zaprojektować własny język, który zaimplementowałeś zarówno w C ++, jak i JAVA .....
źródło
Nikt nie powinien pisać kodu, którego inni koderzy nie rozumieją. Jeśli uważasz, że blokada języka stanowi problem, poczekaj, aż pojawi się blokada programisty. Jedno jest bardziej prawdopodobne, że zatrzyma cię jako zakładnika niż drugie.
Naprawdę nie ma technicznych powodów. Stworzyłeś scenariusz, w którym język był używany z jakiegokolwiek powodu, ale wielu obecnych i prawdopodobnie przyszłych programistów tak naprawdę go nie rozumie.
Domyślam się, że programiści Java mogą pisać C ++ w taki sposób, w jaki piszą w Javie, więc po co ustawiać to jako regułę. Możesz odkryć niektóre funkcje specyficzne dla C ++, które są łatwiejsze do wdrożenia i utrzymania dzięki małej instrukcji / dokumentacji C ++ dla programistów Java niż wielka kula bałaganu Java, z którym w przeciwnym razie utknęliby.
Jest to argument o problemach programistów BASIC przechodzących na języki obiektowe. Nie chodzi o to, że wdrażają praktyki OOP ze szkodą dla nowych deweloperów, którzy ich nie rozumieją, ale że w ogóle tego nie wdrażają. Jeśli tak, zwykle źle to rozumieją. Jeśli coś zrobiono źle, należy je usunąć bez względu na przyczynę.
Poza kimś po prostu ślepo kopiującym i wklejającym kod, zrobią to w wielu obszarach, których i tak nie rozumieją.
źródło