Przejdź do głównej zawartości

Dlaczego nie lubię zintegrowanych środowisk programistycznych?


Czym jest zintegrowane środowisko programistyczne(IDE) nie trzeba tłumaczyć. Do najpopularniejszych należą Visual Studio, Eclipse, NetBeans, QTCreator, Borland Developer Studio, Xcode. Posiadają wiele przydatnych narzędzi do refaktoringu kodu, podpowiadają składnie, indeksują symbole w obrębie projektu, integrują się z systemem kontroli wersji i posiadają tysiące funkcji „ułatwiających” codzienną pracę.
Skoro są takie cudowne to czy można im coś zarzucić? Moja odpowiedź brzmi TAK. A jest to przede wszystkim konfiguracja projektu do pracy z zewnętrznymi niestandardowymi bibliotekami i sposób budowania. W większości wymienionych środowisk nie jest generowany automatycznie plik makefile, ustawienia sposobu budowy projektu i linkowania zaszyte są gdzieś po zakładkach, i opcjach konfiguracyjnych. Jestem jednocześnie świadom że każde z tych środowisk pozwala na wczytanie własnego makefila i na jego podstawie potrafi utworzyć, zindeksować projekt, tym nie mniej nie jest to opcja domyślna. Dodanie odpowiednich bibliotek (np. opencv/boost) do projektu VS to prawdziwa droga przez mękę, zresztą w Eclipsie nie jest wcale lepiej. A przecież można inaczej. Wystarczy utworzyć plik Makefile i w nim umieścić odpowiednie informację np.: nazwa i ścieżka do kompilatora, flagi kompilacji, opcje linkera. Wszystko to w jednym miejscu, jasno prosto i przejrzyście.
Czy rzeczywiście jest tak źle? Tak naprawdę wszystko to jest osiągalne z poziomu IDE. Konfiguracja zazwyczaj zebrana jest w jednym miejscu i nie jest aż tak uciążliwa, wykonuje się ją raz na początku projektu. Jaka jest zatem przewaga makefile nad systemem budowania dostarczanym przez IDE?
Dla małych projektów, niedużej ilości developerów bądź też pracy hobbistycznej sprawa nie jest oczywista. Problem zaczyna pojawiać się w momencie w którym chcemy budować nasz projekt na maszynie nie będącej stacją developerską. Na takiej maszynie należałoby zainstalować odpowiednie IDE, kompilator, biblioteki, i w jakiś sposób uruchomić build ze wszystkimi zależnościami, ścieżkami itp..
A co w przypadku gdy mamy do czynienia z makefilem? No cóż instalujemy kompilator i biblioteki zaciągami projekt i budujemy.
Sytuacja staje się znacznie bardziej złożona gdy mamy do czynienia z systemem ciągłej integracji (continus integration). Dla takich systemów rozpoczyna się poszukiwanie odpowiednich wtyczek, czytanie dokumentacji, wyciąganie konfiguracji z projektowych plików xml, pisanie skryptów. Innymi słowy horror jakich mało (na potwierdzenie swoich słów proponuje każdemu kto ma możliwość skonfigurować Jenkinsa z Xcodem oraz projektem na iOs'a). Makefile pozwoli nam na szybkie wykonanie builda. Dla klasycznego make budowa staje się prosta, wystarczy przecież wpisać make i wszystko zrobione. Zazwyczaj nie są nawet wymagane korekcje ścieżek. Co więcej jeżeli projekt korzysta ze standardowych bibliotek dostępnych na wielu systemach istnieje spora szansa że uda się go przenieść z jednego systemu operacyjnego na inny podmieniając jedynie nazwę kompilatora. Można sobie wyobrazić przeniesienie projektu napisanego na windowsie z wykorzystaniem bibliotek takich jak boost, opencv na linuxa. Każdy kto kiedyś próbował wie w czym problem. Innymi słowy jeżeli mam możliwość wyboru IDE, wybieram takie które pozwoli mi korzystać z zewnętrznego makefila. Daje mi to pełną kontrolę nad tym co się dzieje podczas procesu budowania i umożliwia szybkie modyfikowanie flag kompilacji. Ponadto sprawia że współpraca z systemem ciągłej integracji staje się zazwyczaj bajecznie prosta.

Komentarze

Popularne posty z tego bloga

Makra i preprocesor

Jako programista klasycznego C przyszło mi wielokrotnie ścierać się z makrami. Makro to zestaw instrukcji umieszczanych w kodzie są jednak interpretowane nie przez kompilator ale przez preprocesor. Preprocesor jest „pomocnikiem” kompilatora, zajmuje się on np. wstawianiem treści plików nagłówkowych do plików z kodem za pomocą instrukcji #include. Preprocesor należy rozumieć jako prymitywny edytor tekstu dokonujący „korekcji” plików z kodem źródłowym przed rozpoczęciem ich przetwarzania przez kompilator. Jakie są zalety wykorzystywania tych rozwiązań w kodzie? Tak naprawdę w języku C w czasach przed wprowadzeniem słowa kluczowego inline umożliwiały wstawianie kodu we wskazane miejsce. Należy bowiem pamiętać że każdorazowe wstawienie makroinstrukcji powoduje ingerencję w kod źródłowy (innymi słowy we wskazanym miejscu zostanie wstawiony stosowny fragment kodu). Łatwo obserwowalnym efektem częstego wykorzystywania makr w plikach z kodem jest rozrost pliku binarnego oraz jego szybsze d

C++11 Iterowanie

Zasadniczo iterowanie po elementach tablicy/vectora/listy itp. nie jest niczym nowym, interesującym ani pasjonującym, ot szara codzienność. Przyjrzyjmy się zatem jak robimy to najczęściej: class Image { public:   Image();   void rotate(float angle);   void display();   void* serialize(); }; class ShowImage { public:   void operator()(Image image)   {     image.display();   } }; //... std::vector<Image> imageCollection(10); for(int i=0; i<imageCollection.size(); ++i) {   imageCollection[i].display(); } for( std::vector<Image>::iterator                          currentImage = imageCollection.begin();                         currentImage < imageCollection.end();                         ++currentImage ) {   currentImage->display(); } std::for_each(imageCollection.begin(), imageCollection.end(),               ShowImage()); Dla naszych potrzeb stworzyliśmy sp

C++11 Variadic templates – szablony ze zmienną liczba parametrów

Witam w nowym roku. Dziś będzie o nowym elemencie szablonów czyli o szablonach ze zmienną liczbą parametrów. Ich implementacja i zachowanie różni się nieco od klasycznych szablonów. Nowa funkcjonalność pozwala na tworzenie bezpiecznych list typów. template<typename ...Ts> void variadic_template(){} Pierwszą nowością jest zastosowanie ...(wielokropka) przy określaniu typów szablonu. W ten sposób sygnalizujemy mnogość typów. Niestety nie mamy możliwości iterowania po kolejnych typach wewnątrz naszego szablonu. Ponadto taka definicja pozwala na stworzenie/wywołanie naszej szablonowej funkcji bez typów. variadic_template<>(); Aby tego uniknąć można uciec się do następującej sztuczki: template<typename T1, typename ...Ts> void variadic_template(T1 arg, Ts... args) W powyższym przykładzie jawnie wymuszamy podanie przynajmniej jednego typ dla naszej funkcji szablonowej. Jak już wspomniałem nie możemy jawnie iterować po typach przekazanych do