Наступна функція перевіряє, чи немає підозрілих осіб у списку осіб, імена яких були "захаркоджені":
void checkSecurity(String[] people) {
boolean found = false;
for (int i = 0; i < people.Length; i++) {
if (!found) {
if (people[i].Equals(“Don”)) {
sendAlert();
found = true;
}
if (people[i].Equals(“John”)) {
sendAlert();
found = true;
}
}
}
}
Помічені "запахи коду":
void checkSecurity(String[] people) {
boolean found = false; ///Забруднювач коду - "мертва" булева змінна, що виступає у ролі керуючого флагу
for (int i = 0; i < people.Length; i++) { ///Роздувач коду
if (!found) {
if (people[i].Equals(“Don”)) { ///Забруднювач коду - "дублювання коду"
sendAlert();
found = true;
}
if (people[i].Equals(“John”)) { ///Забруднювач коду - "дублювання коду"
sendAlert();
found = true;
}
}
}
}
Рефакторинг:
- Видалення керуючого флагу та заміна на return, оскільки при знаходженні хоча б однієї людини з іменем "Don" або "John", ми викликаємо метод sendAlert() та відразу завершуємо цикл, оскільки далі перевіряти вже немає сенсу;
- Покращення циклу шляхом використання для ітерації елементів масиву людей, тим самим спростити логіку циклу;
- Прибрати дублювання коду.
void checkSecurity(String[] people) {
for (String person : people) {
if (person.equals("Don") || person.equals("John")) {
sendAlert();
return;
}
}
}
enum TransportType {
eCar,
ePlane,
eSubmarine
};
class Transport {
public:
Transport(TransportType type) : m_type (type) {}
int GetSpeed(int distance, int time) {
if (time != 0) {
switch(m_type) {
case eCar:
return distance/time;
case ePlane:
return distance/(time - getTakeOffTime() - getLandingTime());
case eSubmarine:
return distance/(time - getDiveTime() - getAscentTime());
}
}
}
...
private:
int m_takeOffTime;
int m_landingTime;
int m_diveTime;
int m_ascentTime;
enum m_type;
};
Помічені "запахи коду":
enum TransportType { /// створити наслідування
eCar,
ePlane,
eSubmarine
};
class Transport {
public:
Transport(TransportType type) : m_type (type) {}
int GetSpeed(int distance, int time) {
if (time != 0) { /// заміна на if (time == 0){return 0;}
switch(m_type) { /// конструкція switch буде збільшуватись
case eCar:
return distance/time;
case ePlane:
return distance/(time - getTakeOffTime() - getLandingTime()); /// використання приватних полів всередині класу.
case eSubmarine:
return distance/(time - getDiveTime() - getAscentTime()); /// використання приватних полів всередині класу.
}
}
}
...
private:
int m_takeOffTime; /// відсутні методи доступу до приватних змінних
int m_landingTime;
int m_diveTime;
int m_ascentTime;
enum m_type;
};
Рефакторинг:
- Наслідування елементів enum TransportType від класу Transport;
- Зміна логіки публічного методу;
- Заміна конструкції switch;
- Заміна кодування типу класом;
- Написання гетерів для доступу до приватних полів;
class Transport {
public:
virtual ~Transport() = default;
virtual int GetSpeed(int distance, int time) const = 0;
};
class Car : public Transport {
public:
int GetSpeed(int distance, int time) const override {
if (time == 0) {
return 0;
}
return distance / time;
}
};
class Plane : public Transport {
public:
Plane(int takeOffTime, int landingTime)
: m_takeOffTime(takeOffTime), m_landingTime(landingTime) {}
int GetSpeed(int distance, int time) const override {
if (time == 0) {
return 0;
}
time -= GetTakeOffTime() + GetLandingTime();
return distance / time;
}
int GetTakeOffTime() const { return m_takeOffTime; }
int GetLandingTime() const { return m_landingTime; }
private:
int m_takeOffTime;
int m_landingTime;
};
class Submarine : public Transport {
public:
Submarine(int diveTime, int ascentTime)
: m_diveTime(diveTime), m_ascentTime(ascentTime) {}
int GetSpeed(int distance, int time) const override {
if (time == 0) {
return 0;
}
time -= GetDiveTime() + GetAscentTime();
return distance / time;
}
int GetDiveTime() const { return m_diveTime; }
int GetAscentTime() const { return m_ascentTime; }
private:
int m_diveTime;
int m_ascentTime;
};