Link do repozytorium: https://github.com/johnnyrock92/zjp
Kod do refaktoryzacji został napisany w języku Python na podstawie kodu z książki Refaktoryzacja. Ulepszanie struktury istniejącego kodu. Wydanie II Martina Fowlera (str. 18-19). Celem projektu jest refaktoryzacja kodu, czyli poprawienie jego struktury oraz zastosowanie konwencji przedstawionych w książce, które mają spowodować zwiększenie czytelności i jakości kodu.
Stworzony program jest używany przez firmę zatrudniającą aktorów teatralnych do grania w różnych przedstawieniach. Klienci zamawiają przedstawienia, a firma wystawia rachunki uzależnione od przedstawienia i liczebności publiki. Do wyboru są dwa rodzaje przedstawień: tragedie i komedie. Firma również przyznaje punkty promocyjne, które można wymieniać na rabaty za przyszłe przedstawienia.
Aktorzy zapisują dane przedstawień w pliku plays.json
, dane do rachunku są zapisane w pliku invoices.json
.
CC score | Rank | Risk |
---|---|---|
1 - 5 | A | low - simple block |
6 - 10 | B | low - well structured and stable block |
11 - 20 | C | moderate - slighltly complex block |
21 - 30 | D | more than moderate - more complex block |
31 - 40 | E | high - complex block, alarming |
41+ | F | very high - error-prone, unstable block |
MI score | Rank | Maintainability |
---|---|---|
100 - 20 | A | Very high |
19 - 10 | B | Medium |
9 - 0 | C | Extremely low |
Wskazuje błędy w składni kodu.
Narzędzia łączące cechy powyższych metryk i analizy składni pod kątem błędów.
- Average complexity (CC): B (7.0)
- Lines of Code (LOC): 42
- Maintainability Index (MI): 65.97
tests_v0.py . 1 passed Wynik pozytywny
- Powielony kod (Duplicated Code)
- Długa metoda (Long Method)
- Average complexity (CC): A (2.14)
- Lines of Code (LOC): 76
- Maintainability Index (MI): 72.16
Ekstrakcja metody (Extract Method)
- utworzenie funkcji openJsonFile()
- utworzenie funkcji amountFor()
- utworzenie funkcji playFor()
- utworzenie funkcji volumeCreditsFor()
- utworzenie funkcji totalVolumeCredits()
- utworzenie funkcji totalAmount()
Zmiana nazw zmiennych (Rename Variable)
- perf -> aPerformance
- użycie nazwy result w nowych funkcjach
Zmniejszenie liczby parametrów (Remove Parameter)
- usunięcie parametru play z funkcji amountFor()
Zastąpienie zmiennej tymczasowej zapytaniem (Replace Temp with Query)
- wchłonięcie zmiennej play i użycie w jej miejsce funkcji playFor()
- wchłonięcie zmiennej thisAmount i użycie w jej miejsce funkcji amountFor()
Podział pętli (Split Loop)
- totalVolumeCredits()
- totalAmount()
tests_v1.py ............ 12 passed Wynik pozytywny
- Skomplikowane instrukcje warunkowe (Switch Statements)
- Average complexity (CC): A (1.58)
- Lines of Code (LOC): 109
- Maintainability Index (MI): 61.93
- Ekstrakcja metody (Extract Method)
- utworzenie funkcji renderPlainText()
- utworzenie funkcji run()
- rozłożenie instrukcji warunkowych poprzez utworzenie zagnieżdżonych funkcji comedy() oraz tragedy() w funkcji amountFor()
- Włączenie funkcji do nowych klas (Combine Functions into Class)
- utworzenie klasy Statement
- utworzenie klasy ReadData
- Zmiana nazw funkcji (Rename Function)
- konwencja z użyciem znaku podkreślenia: nazwa_nazwa()
tests_v2.py ............. 13 passed Wynik pozytywny
- Nadmiar komentarzy (Comments)
- Pojemnik na dane (Data Class)
- Average complexity (CC): A (1.5)
- Lines of Code (LOC): 91
- Maintainability Index (MI): 60.68
- Ekstrakcja metody (Extract Method)
- przesunięcie nadmiernie skomentowanego fragmentu do funkcji switch()
- Przeniesienie metody (Move Method)
- przeniesienie metody wczytywania danych do klasy Statement() i usunięcie klasy ReadData()
tests_v3.py ............. 13 passed Wynik pozytywny
- Nadmiernie rozbudowana klasa (Large Class)
statement.py calculate.py render.py Średnio lub Suma Average complexity (CC) A (1.25) A (1.66) A (2.0) A (1.63) Lines of Code (LOC) 18 61 23 102 Maintainability Index (MI) 100 74 91.16 88.38
- Wydzielenie klasy (Extract Class)
- przeniesienie metod do nowych modułów z utworzonymi klasami Render oraz Calculate
tests.py ............. 13 passed Wynik pozytywny
V0 --> V1
Rozkład jednej dużej funkcji na kilka funkcji
V1 --> V2
Utworzenie klas i przeniesienie definicji funkcji do utworzonych metod w klasach
V2 --> V3
Usunięcie klasy odczytującej dane (przeniesienie jej funkcjonalności do klasy Statement)
V3 --> V Infinity
Utworzenie modułów wraz z nowymi klasami (przeniesienie metod z klasy Statement)