Pisanie programów
Oto kilka rad i wskazówek dotyczących pisania i komentowania kodu:
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
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(...)