Java czy C++? Wady i zalety obu języków programowania
To jedne z najpopularniejszych języków, przynajmniej jeśli chodzi o aplikacje desktopowe. Każdy z nich ma swoje wady i zalety, nie można więc powiedzieć, że jeden może w pełni zastąpić drugi. Dlatego postanowiłem postawić inne pytanie i znaleźć na nie odpowiedź: Który język wybrać do realizacji konkretnego zadania?
Andrzej Kidaj. Grafik, poligraf, skończony DTPowiec, fotograf, webdeveloper, bloger (kidaj.ad3.eu)i freelancer. Człowiek-orkiestra, najlepiej gra na nerwach. Od 20 lat w branży graficzno-programistycznej. Niektórzy wyzywają go nawet od artystów czy innych ekspertów, ale się tym nie przejmuje, bo zna prawdę.
Spis treści
Nie jestem zawodowym programistą
Nie jestem wymiataczem w żadnym z wymienionych języków. Znam je na tyle dobrze, żeby popełnić w każdym z nich jakąś aplikację (trochę zresztą ich popełniłem), ale daleko mi do ninja kodersów znających najdrobniejsze niuanse programowania. Zaczynałem od C/C++ (jeszcze na studiach), co pozwoliło mi poznać składnię, zakochać się w niej i bez większego problemu zrobić coś w innych językach opartych o te same zasady. Obecnie siedzę w PHP i JavaScript.
Dostałem kiedyś propozycję napisania aplikacji desktopowej z założeniem, że musi być przenośna na różne systemy. Sugerowano mi Pythona, ale z miejsca odrzuciła mnie jego składnia, której musiałbym się uczyć od zera. Poza tym słyszałem, że programiści miewają problem podczas takiego „żonglowania” różnymi językami. Skoro na co dzień używam PHP, wolałem nie kombinować z zupełnie nowym językiem. Java narzucała się sama.
Pokuszę się więc o porównanie Javy i C++ jako najpopularniejszych (moim zdaniem) języków do tworzenia aplikacji desktopowych. Oto wynik moich rozważań.
Wydajność
Nie ma wątpliwości, że język kompilowany pod konkretny procesor czy system operacyjny (mowa o C++) zawsze będzie szybszy od interpretowanego. Co prawda Java jest kompilowana, ale tylko do tzw. byte-code’u, który wykonywany jest na maszynie wirtualnej. Są różne głosy, że w niektórych sytuacjach Java jest wydajniejsza, ale tak naprawdę wszystko zależy od jakości napisanego kodu. Jeden napisze niewydajną aplikację w assemblerze, inny bardzo wydajną w Pascalu. Ale gdy do programowania weźmie się zawodowiec, to dam sobie głowę uciąć, że zawsze wybierze C++, a nie Javę. W dodatku w C++ można robić wstawki assemblerowe, w Javie, ze względu na przenośność kodu, już nie bardzo.
Przenośność
Założeniem Javy była stu procentowa przenośność na róże platformy. Program napisany raz powinien dać się uruchomić na każdym systemie. Teoretycznie da się to zrobić, w praktyce różnie z tym bywa. W przypadku prostych aplikacji nie ma problemu, bardziej skomplikowane nie tylko wyglądają inaczej, ale mogą też stwarzać nieprzewidziane problemy. Mój program do faktur na Maku gubi niektóre elementy, przyciski nie mieszczą się w okienkach, niektóre komponenty wyglądają inaczej. Chociaż uczciwie muszę przyznać, że to i tak lepiej niż w przypadku programów napisanych w C++. Te ruszą tylko na konkretnym OS, pod który zostały skompilowane.
Nie wszystko się da
Nigdy nie widziałem napisanego w Javie programu rezydentnego czy w ogóle takiego, który wykorzystywałby właściwości danego systemu operacyjnego np. obsługę rejestru, właśnie ze względu na tą przenośność. Nie wyobrażam sobie też hackera kodującego w Javie. Wirusów chyba też nie ma, ale tu akurat nie ma co płakać.
Klasy, biblioteki, obiekty, tablice i dużo więcej…
Klasy bez dwóch zdań to wspaniały wynalazek. Ale Java wymusza używania klas do wszystkiego. Przy dużych projektach jest to zaleta, bo kod jest czytelniejszy, ale przy prostych aplikacjach to przerost formy nad treścią. Są też funkcje, dla których nie ma wręcz sensu tworzyć klasy. A jednak trzeba. Przy małych programach trzeba więc napisać nieporównywalnie więcej kodu. Gdzie więc ta oszczędność czasu podczas programowania, o której tyle się mówi?
Twórcy języka C/C++ zakładali, że programista wie co robi i dali wolną rękę niemal we wszystkim. W dodatku głównym założeniem było „jak najmniej naciśnięć klawiszy”. Z jednej strony zwiększa to ryzyko popełnienia błędu niewychwytywalnego przez kompilator, ale za to jest o wiele mnie klepania kodu. Wiele danych można przekazywać po prostu jako wskaźnik (na tablicę, funkcję, obiekt), nawet bez konieczności rzutowania. W Javie to nie przejdzie. Tutaj z założenia niemal wszystko jest przekazywane jako wskaźnik, ale konieczne jest rzutowanie. Czasami wychodzą z tego karkołomne i zaciemnione operacje. I znowu więcej pisania niż to ma sens. Swoją drogą ciekawi mnie, jak to się ma do wydajności. Czy rzutowanie jest realizowane podczas kompilowania do byte-code czy podczas wykonywania programu?
Każdy obiekt obsługiwany jest nieco inaczej, aż prosi się o ujednolicenie wszystkiego. Domyślam się, że wynika to z samej ewolucji i rozwoju języka, ale z punktu widzenia programisty jest to bardzo uciążliwe. W dodatku klasa String zupełnie niepodobna do niczego. Niby działa jak prosta tablica, ale jest obiektem.
Dla przykładu w SetSize można niezależnie przekazać szerokość i wysokość albo jako obiekt zawierający te wartości. Ale już SetMinSize przyjmuje tylko obiekt. W ogóle bez sensu jest konieczność tworzenia i przekazywania obiektów, w przypadkach gdy można przekazać same parametry (mniej pisania) np. SetBackground(new Color(R,G,B)). Często mam wrażenie, że wiele metod było pisanych przez różnych programistów, którzy w ogóle nie mieli ze sobą kontaktu.
Java ma dużo gotowych obiektów do tablicowania danych. Każdy działa nieco inaczej i problemem może tu być wybór najefektywniejszego do danego typu danych i operacji na nich wykonywanych. Za to dużym plusem jest garbage collector, który odciąża mnie od konieczności zajmowania się obsługą pamięci, co jest jednym z największych problemów podczas programowania w C/C++. Z tego powodu bardzo lubię PHP, który też sam się tym zajmuje.
Tworzenie interfejsu użytkownika
Java udostępnia różne biblioteki do rysowania interfejsu użytkownika, ale Swing jest (podobno) najbardziej uniwersalny i responsywny. Wszytko pozycjonuje się zależnie od innych elementów (kontrolek). Z jednej strony to przydatna funkcja, bo nie trzeba się martwić dostępnym obszarem (wszystko się ładnie dopasuje), z drugiej strony trzeba się mocno nakombinować w przypadku okienek, gdzie elementy muszą być zawsze w konkretnym miejscu.
Mimo wszystko łatwość tworzenia interfejsu to bardzo duży plus, bo można od razu zająć się konkretnym zadaniem programu i nie martwić rysowaniem elementów, kontrolek itp. Dzięki temu program do faktur pisałem w miesiąc zamiast w rok. Nie są to może wyżyny programowana, ale program lat działa i pomaga mi w pracy.
Co prawda do C/C++ też są odpowiednie biblioteki, a nawet wizualne IDE, ale jakoś nie mam do nich przekonania. Między innymi dlatego polubiłem PHP, w którym bardzo łatwo generuję kod HTML do wyświetlenia w przeglądarce.
Kompilator
Java zawsze jest taka sama (jeden kompilator), kod wynikowy również, do C/C++ jest wiele kompilatorów do każdego systemu i tworzą różny kod wynikowy. Środowiska wizualne tworzą masę ciężkiego kodu, GCC bardzo mały i kompaktowy. C/C++ dla każdego procesora i systemu też trochę się różni, nie wystarczy więc przenieść i skomplikować pliki źródłowe. Często trzeba spędzić sporo czasu, żeby je odpowiednio przygotować. Czyli pojawia się problem przenośności programu. Skompilowany program w Javie można uruchamiać na każdym komputerze pod warunkiem zainstalowania maszyny wirtualnej. Ja swój program do faktur napisany pod Windowsem, bez większego problemu odpalam na MacBooku.
Środowisko programistyczne
Wybrałem środowisko Eclipse (napisane w Javie zresztą), jako najbardziej dla mnie przyjazne. Wszystko piszę z palca, ale za to mam całkiem sporą kontrolę nad całością kodu źródłowego. Jako że nie jestem jeszcze zbyt biegły w tym języku, mam włączone podpowiedzi. I tu się pojawia problem, bo czasami lista metod danej klasy wczytuje się kilkanaście sekund (mam bardzo szybki komputer, na wolniejszym trwało to czasami kilkadziesiąt sekund). Pół biedy gdyby można to było jakoś przerwać, ale się nie da. A przynajmniej nie znam sposobu. W ogóle często widać przycinanie się edytora, co mnie irytuje, bo komfort i płynność pracy stawiam na pierwszym miejscu.
Do C/C++ używałem Dev Cpp i Code Blocks, które zawsze śmigały jak na dopalaczach.
Podsumowanie
Nie można jednoznacznie powiedzieć, że jeden język jest lepszy od drugiego (bez wnikania, który to). Wynik moich rozważań jest jednak prosty: do aplikacji, które więcej pokazują niż przetwarzają, wybiorę Javę, bo nie muszę martwić się rysowaniem interfejsu. Do aplikacji wymagających dużej mocy obliczeniowej tylko i wyłącznie C/C++ i ewentualnie wspomogę się assemblerem. A Ty? Który język preferujesz i dlaczego?
Artykuł został pierwotnie opublikowany na łamach kidaj.ad3.eu.