Dlaczego C ++ jest nadal „hybrydowy”

16

W pokrewnym pytaniu wyjaśniono, dlaczego C ++ nie jest kompatybilny z C w wielu aspektach. Jednak C ++ jest nadal językiem „hybrydowym” *. I niestety wielu programistów nadal uważa C ++ za „C ze strumieniami i wbudowanymi łańcuchami”. Powoduje to naprawdę źle napisany kod, który nie jest ani C ++ ani C. IMHO, byłoby lepiej, gdyby język / kompilator zmusił do pewnego stopnia programistów do napisania bardziej eleganckiego kodu. Czy istnieje więc uzasadnienie dla zachowania nowoczesnej hybrydyzacji C ++ (na przykład C ++ 0x i przyszłych wersji)?

* Przez hybrydę mam na myśli, że to programista decyduje, czy będzie używał: standardowych ciągów i strumieni, klas, przestrzeni nazw innych niż domyślne itp.

sakisk
źródło
Czy istnieją jakieś ustawienia kompilatora / IDE, które mogłyby to wymusić?
FrustratedWithFormsDesigner
@FrustratedWithFormsDesigner Nie znam żadnych narzędzi, które to robią. Jednak bardziej sensowne byłoby napisanie takiego narzędzia (kompilatora, IDE itp.), Gdyby te funkcje były częścią standardowego C ++.
sakisk
2
Raison d'etre C ++ to kompatybilność wsteczna i możliwość użycia wszystkich brudnych sztuczek, które były możliwe w C. Zabierz to, a to tylko kolejny klon C #, D lub Java. Jeśli tego chciałeś, dlaczego nie użyć C #, D lub Java?
nikie
5
@nikie: Hahahaha. Ponieważ szablony, typy wartości, silne odwołania, deterministyczne zniszczenie, wielokrotne dziedziczenie, szybkość wykonania, niskie zużycie pamięci, te rzeczy w ogóle nie istnieją.
DeadMG,
2
@nikie: Z wyjątkiem D ma też obrzydliwości, takie jak wartości Objectbinarne i wartości kopiowania oraz tablice asocjacyjne określane przez język (dlaczego ...), a także inne podejrzane decyzje projektowe. Ponadto skutecznie ma ten sam paradygmat GC, co inne, więc wątpiłbym w to, że ma mało pamięci.
DeadMG,

Odpowiedzi:

26

Tak, istnieje silne uzasadnienie: kod C ++ prawie zawsze musi wywoływać istniejący kod C. Najlepsze, co możemy zrobić, to ułatwić pisanie dobrego kodu. Projektant języka nie może nic zrobić, aby uniemożliwić pisanie złego kodu.

Kevin Cline
źródło
1
Jasne, ale skoro jest to tylko w przypadku starszego kodu, dlaczego nowsze wersje C ++ muszą pozostać kompatybilne? Stary kod nadal może używać starszej wersji C ++.
sakisk
15
@faif, w mojej pracy cały czas piszę nowy kod C ++, który potrzebuje interfejsu z nowym kodem C. To nie tylko problem ze starszymi wersjami.
Karl Bielefeldt,
5
@faif: nowsze wersje C ++ muszą być kompatybilne wstecz - nie tylko w celu obsługi starszego kodu C, ale także kilkuset milionów wierszy istniejącego kodu C ++. Jeśli chcesz czegoś, co nie jest kompatybilne z poprzednimi wersjami, ale jest lepiej zaprojektowane, możesz przejść na język taki jak D. Nawiasem mówiąc, tutaj jest naprawdę dobry artykuł o potrzebie kompatybilności wstecznej Joela Spolsky'ego
Doc Brown
4
The best we can do is make it easy to write good code.- Czy mówimy o tym samym C ++?
BlueRaja - Danny Pflughoeft
4
@ BlueRaja-DannyPflughoeft: O wiele łatwiej jest pisać dobry kod w C ++ niż w Javie lub C #. Dzięki C ++ mogę czytać klasę i jeśli wszystkie pozostałe zachowują się, wiem, że pamięć i zasoby nie zostaną przeciekły. Z Javą i C # nie mogę tego zrobić; Muszę sprawdzić inne klasy, aby sprawdzić, czy któraś z nich wymaga sfinalizowania. Szablony C ++ pozwalają mi również na OSUSZANIE kodu, który należy powtórzyć w Javie.
Kevin Cline,
20

IMHO, byłoby lepiej, gdyby język / kompilator zmusił do pewnego stopnia programistów do napisania bardziej eleganckiego kodu.

Nie zrobiłby tego. W ogóle. Jako trywialną demonstrację dlaczego, zdefiniuj elegancki, a potem założę się, że dziesięć osób przyjdzie się z tobą nie zgodzić.

Wymuszone przez język style kodowania są naprawdę bardzo złe. Nie wspominając już o całym starszym kodzie, który zostanie złamany.

Warto zauważyć, że standardowe ciągi i klasy strumienia faktycznie są do bani . std::stringnie ma obsługi Unicode i najgorszego interfejsu, jaki można sobie wyobrazić. Strumienie mają straszne koszty ogólne i kiepski wygląd, a nawet uciekają się do wirtualnego dziedziczenia, wskaźników funkcji const char*i podobnych brzydek. Nie ukarałbym nikogo za całkowite zastąpienie obu tych klas / grup klas niestandardowymi.

Nieużywanie klas i przestrzeni nazw jest w porządku dla kodu w stylu tablicy, a istnieje wiele bibliotek udostępniających funkcje spoza klasy. Klasa wymuszona to naprawdę zły pomysł.

DeadMG
źródło
+1 za nieco bardziej realistyczne podejście (kiedy „elegancki kod” przestanie mówić: /
Rook
2
„Wymuszone przez język style kodowania są naprawdę bardzo złe”. Czy możesz podać jakieś przykłady? Myślę, że nawet proste rzeczy, takie jak wymuszone wcięcie kodu w Pythonie, poprawia czytelność kodu.
sakisk,
3
Nie jestem pewien, czy się z tym zgadzam. Głównym powodem używania CoffeeScript zamiast JavaScript jest to, że CoffeeScript został zaprojektowany w celu wymuszenia pisania bardziej eleganckiego kodu.
user16764,
3
Nie mogę się z tym zgodzić. Niektóre projekty językowe mają na celu zachęcanie do dobrych praktyk, a rozległy, nieokreślony charakter większości C ++ zasadniczo temu wyklucza. W rzeczywistości wyrzucenie języka, zachowanie dobrych części i poprawienie pozostałych jest główną motywacją istnienia C ++ 11 .
Robert Harvey
1
@Pubby: „Pisanie brzydkiego programu, który działa, jest lepsze niż pisanie pięknego programu, który nic nie robi”. Jasne, mogę się z tym zgodzić. Ale ten artykuł wykracza poza to i wydaje się argumentować, że brzydota jest w rzeczywistości cnotą. I to jest po prostu śmieszne.
Mason Wheeler,
8

C ++ jest hybrydą nie dlatego, że pozwala pisać kod w stylu C, ale dlatego, że obsługuje kilka paradygmatów programowania, takich jak proceduralne, obiektowe i ogólne. C ++ nie zmusza cię do jednego sposobu robienia rzeczy, i to jest jego siła, ponieważ różne problemy można łatwiej rozwiązać za pomocą różnych paradygmatów.

IMHO, byłoby lepiej, gdyby język / kompilator zmusił do pewnego stopnia programistów do napisania bardziej eleganckiego kodu.

Następnie musisz zdefiniować, co oznacza elegancki . Następnie musisz sprawdzić, czy twoja definicja elegancji jest odpowiednia dla wszystkich problematycznych domen i platform, dla których używany jest C ++. Styl kodowania, który jest elegancki do pisania edytora tekstu dla systemu Windows, może całkowicie nie nadawać się do pisania systemu osadzonego.

Rozważ napisanie kodu C ++ do działania na procesorze DSP. Po pierwsze, kompilator C ++ dla tego DSP może po prostu nie obsługiwać niektórych funkcji C ++, takich jak strumienie. Po drugie, jesteś poważnie ograniczony przez szybkość procesora i być może pamięć, więc niektóre funkcje C ++ mogą po prostu zabić twoją wydajność. Na przykład może być konieczne unikanie funkcji wirtualnych ze względu na szybkość. Takie rozważania radykalnie zmieniłyby twój styl programowania w porównaniu do tego, czego używałbyś na PC, a C ++ pozwala na to.

Podsumowując, C ++ to ogromny i skomplikowany język z wieloma funkcjami. Istnieje wiele powodów, dla których jakikolwiek podzbiór tych funkcji może nie mieć zastosowania do konkretnego projektu: szybkość, przenośność, obsługa kompilatora, a nawet doświadczenie i znajomość programisty. Z tego powodu wymuszanie przez programistę korzystania z niektórych funkcji w przeciwieństwie do innych do dowolnego zadania jest złym pomysłem. Pomyśl o Javie, gdzie język nakazuje, że każda funkcja musi być metodą klasy. Jest tak wiele przypadków, w których tworzenie klasy tylko do zawijania metody jest niewygodne i niepotrzebne, a jednak musisz to zrobić, ponieważ zmusza cię do tego język.

Dima
źródło
1
Nie można zgodzić się więcej. Pomyślałbym, że gdy ktoś powie „C ++ jest elastyczny”, tak mi się wydaje, ponieważ obsługuje o wiele więcej paradygmatów niż C.
prelic
5

IMHO, byłoby lepiej, gdyby język / kompilator zmusił do pewnego stopnia programistów do napisania bardziej eleganckiego kodu.

Nikt nie zmusza nikogo do używania C ++. Jeśli język Ci nie odpowiada, użyj innego - istnieje wiele języków, które są rozliczane jako „C ++ bez C”.

Filozofia projektowania C ++ polega na podejmowaniu decyzji przez programistę. Jeśli chcą strzelić sobie w stopę, pozwól im. Pozwala to zrobić wiele złych rzeczy, ale także zapewnia dużą elastyczność. Na przykład jest mało prawdopodobne, aby Boost mógł zostać napisany w języku takim jak Java, ponieważ korzysta on z funkcji językowych i praktyk powszechnie odrzucanych. Jest również mało prawdopodobne, aby C ++ urósł tak duży jak obecnie - dostęp do ogromnej biblioteki C jest ogromnym plusem, weź ją lub zostaw.

Kompatybilność C ++ z C jest zdecydowanie jednym z jego najsłabszych punktów, ale należy również pamiętać, że jest to jedna z jego największych zalet.


Dodam wspaniały cytat Jona Purdy'ego, który moim zdaniem jest niezwykle istotny:

Wszystko sprowadza się do pragmatyzmu kontra elegancji, a dla mnie, pomimo mojej obsesji na punkcie precyzyjnego, pięknego kodu, pisanie brzydkiego programu, który działa, jest lepsze niż pisanie pięknego programu, który nic nie robi.

Usunięcie hybrydy może poprawić elegancję, ale utrudnia jej zdolność.

Pubby
źródło
Czy wierzysz, że pragmatyzm i elegancja są ze sobą sprzeczne? Myślę, że Python, Ruby i Scala to dobre przykłady języków, które są zarówno pragmatyczne, jak i eleganckie.
sakisk
1
@faif: Nie, ale kompatybilność wsteczna i elegancja są sprzeczne. Dotyczy to również Pythona (2.x vs. 3.x).
dan04
4

Gdyby komitet próbował zmusić ludzi do używania (czyjegoś pojęcia) bardziej eleganckiego języka, prawdopodobnie zostałby zignorowany. Ludzie będą nadal robić, co chcą, a dostawcy kompilatorów będą podążać za rynkiem (ale dostawcy kompilatorów mają wystarczającą reprezentację w komitecie, aby temu zapobiec).

Wiele z tego, co popierasz, jest tak naprawdę kwestią osądu, w każdym razie opartą na problematycznej dziedzinie. Istnieje wiele małych programów, które po prostu nie potrzebują (na przykład) przestrzeni nazw. Próba zmuszenia mnie do korzystania z przestrzeni nazw podczas pisania 30-liniowego filtru tekstowego byłaby głupia i arogancka. Nawet jeśli zdecydujesz, że będzie to miało zastosowanie tylko wtedy, gdy więcej niż X wierszy kodu, funkcji Y lub cokolwiek by to dotyczyło, nadal generalnie przyniesie efekt przeciwny do zamierzonego. Przestrzenie nazw zostały zaprojektowane z konkretnego powodu, aby zapobiegać określonym problemom / leczyć je. Próba narzucenia ich użycia przy braku tych problemów nie przyniesie nikomu niczego pożytecznego.

Jednocześnie uważam, że warto zauważyć, że sporo osób naprawdę spędza dużo czasu i wysiłku, próbując nie tylko włączyć elegancję w C ++, ale także uczyć i zachęcać ludzi do korzystania z tych możliwości do pisania lepszego kodu (np. wielu współpracowników Boost). W związku z tym ludzie, którzy nadal nalegają na napisanie swojego kodu jako „C z klasami”, w zasadzie ignorują to, co się tam dzieje. Sądzę, że równie dobrze mogliby ignorować nowe kompilatory, jak ignorują wszystko, czego nauczyliśmy się korzystać z C ++ w ciągu ostatniej dekady lub więcej (np. Modern C ++ Design został opublikowany 11 lat temu - ale większość ludzi mówisz, że najwyraźniej jeszcze o nim nie słyszałeś, a tym bardziej nie czytałem ani nie rozumiałem nawet jego najprostszych części).

Jerry Coffin
źródło
2

Twój pomysł stanowi znaczną część uzasadnienia projektowego stojącego za Javą. Java zmusza cię do korzystania z klas, organizowania hierarchii plików zgodnie z hierarchią pakietów, wychwytywania wyjątków itp. Ludzie nadal potrafią pisać w nim kod podobny do C.

Jako programiści czasami zapominamy, że najlepsze rozwiązanie może nie być techniczne. Recenzje wzajemne są najbardziej znanym rozwiązaniem w tym przypadku.

Karl Bielefeldt
źródło
0

C ++ nie ma „jednej prawdziwej drogi”; każde podejście ma swoje mocne i słabe strony. Rozwiązanie można zapisać na sto różnych sposobów.

Jako programista musisz zdecydować, które podejście jest najlepsze dla danego zadania.

Koder
źródło
0

Myślę, że fakt, że wszystkie te rzeczy, które wymieniasz, są opcjonalne, stwarza potencjał dla większej elegancji, a nie mniej. Funkcja używana niepotrzebnie jest nieelegancka w moich oczach.

Problemy, które musimy rozwiązać za pomocą programowania, są bardzo odmienne.
Niektóre są dobrze rozwiązywane przy użyciu zasad OO (np. GUI), niektóre lepiej nadają się do czysto funkcjonalnego leczenia (np. Liczby), a niektóre najlepiej wyrażać niskopoziomowym językiem „blisko krzemu”.

Mnóstwo oprogramowania musi rozwiązać podproblemy, które najlepiej rozwiązać na jeden z tych sposobów. Zmuszenie rozwiązania do określonej formy doprowadzi tylko do tego, że kod będzie mniej dostosowany do jego celu (możesz nawet powiedzieć „mniej elegancki”).

Właśnie dlatego hybrydowość C ++ jest dobra - pozwala nam rozwiązać szeroki wachlarz problemów w sposób, który pasuje do problemu , a nie do obecnego dogmatu.
Oczywiście można go nadużywać - gdy masz coś elastycznego, istnieje ryzyko, że zginiesz go w zły sposób - ale elegancja wynika z dokładnego przemyślenia i doświadczenia, a nie z przestrzegania tego, co jest modne.

molbdnilo
źródło