Wybacz za zwłokę, ale trochę mi się weekendowe plany pozmieniały. Ad rem:
odnośnie setterów/getterów: liczy się kontekst. Niemniej u Ciebie to są "przelotki" do pól klasy, nic więcej. Interfejs:
class Network
{
public:
void setIp(const QString& addr) {
m_addr = addr;
}
QString addr() const {
returm m_addr;
}
private:
QString m_addr;
};
możesz z powodzeniem zamienić na:
class Network
{
public:
QString m_addr;
};
albo nawet pójść po całości:
struct Network
{
QString m_addr;
};
W QT settery mają jakiś tam sens z uwagi na ew. możliwość emitowania sygnałów, kiedy coś się zmieni, ale nie korzystasz z tego.
Ktoś może powiedzieć "ale walidacja". Tu jej nie robisz, ale weźmy przykład
class ProgressBar {
public:
void setPercentage(uint8_t percents) {
if (percents > 100) throw out_of_range("Progress's percentage cannot exceed 100");
m_percentage = percents;
}
void redraw();
private:
uint8_t m_percentage;
};
Tak naprawdę walidację/nasycanie można przerzucić na samą klasę przechowującą dane i będzie to miało sens o tyle większy, że od razu widzisz jakiego typu wartości są
//poniższą klasę może być warto "stemplatkować", zarówno z uwagi na typ, jak i wartości...
struct U8ProgressPercentage {
explicit U8ProgressPercentage (uint8_t number)
: m_number(number)
{
if (number > 100) throw out_of_range("Progress's percentage cannot exceed 100");
}
operator uint8_t() const {return m_number;}
//ciach, dalej resztę interfejsu sobie dośpiewaj....
};
class ProgressBar {
public:
U8ProgressPercentage m_percentage;
void redraw();
};
@Azarien jeżeli nie piszesz w gołym Vimie albo Emacsie, to typ argumentu albo i całą sygnaturę funkcji podpowie Ci edytor, także Dog
może tego Ball
a fetch
, pickUp
, albo carry
i będzie to OK, w zależności od tego co ten pies ma konkretnie reprezentować. Także argument, że nie widać co się dzieje jest imho słaby. Jak psu potrzebujesz ustawiać piłkę, to raczej abstrakcja kuleje. Ale dla jasności: nie widzę problemu żeby np. moduł klimatyzatora miał setTemperature
. Oczywiście, to są wszystko zalecenia i dobre praktyki a życie sobie...
Odn. setWeight
: jeżeli ten pies reprezentuje NPCa w grze, jego waga może być zmieniana powiedzmy czarami i ma to wpływ na zachowanie z punktu widzenia fizyki (nie wiem, pęd przy uderzeniu w ziemię podczas upadku przelicza się na obrażenia... przykład z kapelusza) to ten setter może mieć sens, można także pomyśleć o upublicznieniu pola i może styknie. Ale z drugiej strony, jak ten pies ma być lekkim obiektem z weterynaryjnej bazy danych, to nie widzę sensu tego settera, można po prostu stary obiekt podmienić na nowy, interfejs będzie czystszy imho (albo i będzie to niemożliwe, bo np. framework wymaga że setter ma być i wtedy koniec).
Ale znowu: kontekst, kontekst, kontekst.
Imho usprawiedliwionym jest istnienie settera (ale nie będę się przy tym upierał, no i pytanie czy to nadal jest typowy setter) jeśli ma jeszcze wywołać skutki uboczne np. emitować sygnał albo przerysować obiekt po zmianie wartości, vide (ale zobacz jak ta funkcja się nazywa):
class ProgressBar {
public:
void setValueAndRedraw(uint8_t value) {
m_percentage = U8ProgressPercentage(value);
redraw();
}
void redraw();
private:
U8ProgressPercentage m_percentage;
};
Tyle ogólników.
Co do Twojego kodu:
Settery i gettery są głupimi przelotkami. Ja bym je wyrzucił. Opcja druga: wszystkie pola zrobić prywatne, dać tylko gettery jeśli to potrzebne a ustawiać je na etapie konstrukcji.
Ładujesz wszystko przez wartość, np. QString. To niekoniecznie błąd, ale imho dobrą praktyką jest używanie albo const referencji, albo odpowiednie używanie move semantics (std::move) jeśli jednak lecisz po wartościach.
Metody niemodyfikujące obiektu powinny być const
, tego nie ma.
Nazewnictwo tragedia. Coś się na ten connect
tak uparł? No i decyduj się czy metody od małych czy dużych liter. bo tu zero konsekwencji.
Te wszystkie for od begin
do end
to chyba dałoby się for_each
/ranged for
zastąpić?
BTW, zamiast
JasiuIKasia::iterator i;
for (i = kasiazjasiem.begin(); //ciach....
możesz zrobić
for (auto i {kasiazjasiem.begin()}; //ciach
Na koniec: metoda ReadSettings
sprawia wrażenie prób chodzenia po drzewie. Jak wiesz jaki tam masz format konfiga, będzie on dobry i taki jak zakładasz, to do diabła z tym, ale koncepcyjnie to imho możnaby też poprawić.