====== Pisanie programów ====== Oto kilka rad i wskazówek dotyczących pisania i komentowania kodu: * [[#Komentowanie_kodu|Komentowanie kodu]] * [[#Obsluga_wyjatkow|Obsługa wyjątków]] ====== Komentowanie kodu ====== * Wszystkie **deklaracje** funckji, **deklaracje oraz definicje** klas, w przypadku wielomodułowych programów staramy się umieszczać **w pliku nagłówkowym**. Staramy się unikać używania dyrektywy **#include** w plikach nagłówkowych, chyba że jest to niezbędne lub zamierzone. * Pliki nagłówkowe powinny zawierać tylko niezbędne deklaracje oraz definicje. * Pliki nagłówkowe powinny być **zabezpieczone** przed wielokrotną kompilacją: #ifndef PLIKH #define PLIKH // treść pliku nagłówkowego #endif * Dyrektywą **#include** włączamy tylko pliki nagłówkowe. **Niewolno** włączać plików *.c, *.cpp. * Dla zwiększenia przejrzystości, szczególnie dużych plików (ponad 300 linii kodu) warto stosować dodatkowe separatory pomiędzy częściami kodu np. pomiędzy funkcjami: /// \brief opis funckji func1 /// /// \param __i - opis parametru __i /// \param __f - opis parametru __f /// \return funkcja zwraca: /// \li 0 - w przypadku gdy... /// \li 1 - w przypadku gdy... /// \li 2 - w przypadku gdy... int func1(int __i, float __f) { // Ciało funckji } // ---------------------------------------------------- /// \brief opis funckji func2 /// /// \return brak zwracanych wartosci void func2(void) { // Ciało funckji } // ---------------------------------------------------- /// \brief opis funckji func3 /// /// \param __f_ptr - opis parametru __f_ptr /// \return znak ktory reprezentuje char func3(char(* __f_ptr)(int, float*& __in_ptr_ref)) { // Ciało funckji } // ---------------------------------------------------- * Należy stosować **jak najwięcej** komentarzy. Krytyczne miejsca programu **muszą** być komentowane. * Dodatkowym atutem, wpływającym na jakość tworzonego kodu jest stosowanie komentarzy zgodnych ze specyfikacją wymaganą przez Doxygen. Oto przykład komentarzy dla pliku nagłówkowego: /** * \file nazwapliku.h * \author Imie i Nazwisko * \date 1.10.2008 * \version 1.0 * \brief Krótki opis co plik zawiera */ // ------------------------------------------------------------------------- #ifndef PLIKH #define PLIKH // ------------------------------------------------------------------------- /** * \class klasa * \author autor * \date 1.10.2008 * \brief Krótki opis klasy */ class klasa { private: int f1; ///< opis pola klasy int f2; ///< opis pola klasy float f1; ///< opis pola klasy public: /// \brief Konstruktor domyślny klasy klasa(void); /// \brief Konstruktor klasy /// /// \param f - opis parametru klasa(int f); /// \brief opis metody 1 /// /// \param _a - opis parametru /// \param *c - opis parametru /// \return opis zwracanej wartości int metoda1(int _a, double* c); }; // ------------------------------------------------------------------------- #endif Komentarze zgodne z Doxygen stosujemy tylko **raz** np. tylko w pliku nagłówkowym. Można a nawet trzeba sporządzać także komentarze "robocze", które nie będą uwzględniane przez narzędzie, szczególnie w najważniejszych miejscach programu. * Staramy się robić wcięcia, dla kolejnych poziomów zagnieżdżeń kodu. Standartowo 3-5 spacji. * **Nie używamy znaku tablulacji**: * ponieważ powoduje to problem w przejrzystości kodu otwartego w innych edytorach niż ten w którym był pisany; * z powyższego powodu konfigurujemy edytor tak aby zamieniał znak tabulacji na spacje; * jeżeli edytor nie posiada takiej opcji to najwyższy czas go zmienić; ====== Obsługa wyjątków ====== Podczas pisania programów w ramach zajęć należy stosować mechanizmy obsługi sytuacji wyjątkowych. Poniżej zaproponowany sposób pozwoli na stworzenie kodu który w tym kontekście będzie prawidłowo przechodził testy. * Ściągnij plik {{:pl:dydaktyka:jimp2:2016:part2:org:aghexception.tar.gz|}} który zawiera definicję klasy przeznaczonej do obsługi sytuacji wyjątkowych. * Klasa ma już gotowe metody które są gotowe do użycia. * Jeżeli chcesz możesz tworzyć swoje klasy do obsługi błędów jednak aby mogły one poprawnie przechodzić testy muszą one dziedziczyć podaną klasę **aghException** w sposób publiczny. * Niezastosowanie tej klasy do obsługi błędów będzie skutkowało możliwymi błędami podczas testów które w takim wypadku nie będą mogły zostać usprawiedliwione. ===== Jak używać ===== Poniżej prosty przykład użycia klasy. \\ Mamy prostą funkcję **getValue** która zwraca wartość znajdującą się w tablicy **_tab** na miejscu o indeksie przesłanym jako argument. Jeżeli wartość indeksu jest nieprawidłowa (tzn. poza zakresem tablicy) to w takim wypadku najlepszym rozwiązaniem jest wyrzucenie wyjątku (**throw**). int& aghVector::getValue(int _index) const { if((_index < 0) || (_index >= size())) throw aghException(0, "Index out of range", __FILE__, __LINE__); return _tab[_index]; } W powyższym przykładzie wykorzystana jest klasa **aghException**. Aby obsłużyć tak wyrzucony wyjątek np. w funkcji **main** robimy tak: try { v->getValue(-1) = 6; } catch(aghException& e) { cout << e << endl; } catch(...) { cout << "\nUnrecognized error\n"; } W tym przypadku obsługa wyjątku zostanie przekierowana do bloku: catch(aghException& e) i na ekranie pojawi się taki komunikat: Error in aghVector.h file at 69 line. Error code: 0 (Index out of range). Natomiast wszystkie pozostałe błędy które nie są obsługiwane przez podaną klasę będą obsługiwane w bloku: catch(...)