- Erstelle die Datei `CLEAN_CODE_REFACTORING.md`, die die Ziele und Prinzipien des Clean Code Refactorings beschreibt. - Implementiere neue Klassen wie `UserRepository`, `WebSocketMessageHandler`, `MessageValidator`, `ConfigurationManager` und `ChatUserClean`, um die Lesbarkeit, Wartbarkeit und Testbarkeit des Codes zu verbessern. - Füge Methoden zur Fehlerbehandlung, zur Verwendung von Konstanten und zur Anwendung des Factory Patterns hinzu. - Aktualisiere die `CMakeLists.txt`, um die neuen Quellcodedateien einzuschließen. - Optimiere die `ChatRoom`- und `ChatUser`-Klassen, um die neuen Strukturen und Prinzipien zu integrieren. - Füge einen Migrationsleitfaden und Metriken zur Bewertung der Codequalität hinzu.
182 lines
5.0 KiB
Markdown
182 lines
5.0 KiB
Markdown
# Clean Code Refactoring - YourChat
|
|
|
|
## 🎯 Ziel
|
|
Das YourChat-Projekt wurde nach Clean Code Prinzipien refaktoriert, um:
|
|
- **Lesbarkeit** zu verbessern
|
|
- **Wartbarkeit** zu erhöhen
|
|
- **Testbarkeit** zu ermöglichen
|
|
- **Erweiterbarkeit** zu fördern
|
|
|
|
## 🔧 Implementierte Clean Code Prinzipien
|
|
|
|
### 1. **Single Responsibility Principle (SRP)**
|
|
Jede Klasse hat nur eine Verantwortlichkeit:
|
|
|
|
- **`UserRepository`**: Nur Datenbankoperationen für User
|
|
- **`WebSocketMessageHandler`**: Nur WebSocket-Kommunikation
|
|
- **`MessageValidator`**: Nur Nachrichtenvalidierung
|
|
- **`ConfigurationManager`**: Nur Konfigurationsverwaltung
|
|
|
|
### 2. **Dependency Injection**
|
|
Abhängigkeiten werden über Konstruktoren injiziert:
|
|
|
|
```cpp
|
|
// Vorher: ChatUser macht direkte Datenbankabfragen
|
|
ChatUser(std::shared_ptr<ChatRoom> parent, std::string name, ...);
|
|
|
|
// Nachher: Repository wird injiziert
|
|
ChatUserClean(std::shared_ptr<ChatRoom> room,
|
|
std::shared_ptr<UserRepository> userRepository, ...);
|
|
```
|
|
|
|
### 3. **Factory Pattern**
|
|
Klare Erstellung von Objekten:
|
|
|
|
```cpp
|
|
// Factory-Methoden statt komplexer Konstruktoren
|
|
auto socketUser = ChatUserClean::createSocketUser(room, name, socket, repository);
|
|
auto webSocketUser = ChatUserClean::createWebSocketUser(room, name, wsi, repository);
|
|
```
|
|
|
|
### 4. **Meaningful Names**
|
|
Selbsterklärende Namen:
|
|
|
|
```cpp
|
|
// Vorher
|
|
_wsi, _parent, _msgQueue
|
|
|
|
// Nachher
|
|
_webSocket, _room, _messageQueue
|
|
```
|
|
|
|
### 5. **Small Functions**
|
|
Funktionen mit maximal 20 Zeilen:
|
|
|
|
```cpp
|
|
// Vorher: 100+ Zeilen Konstruktor
|
|
ChatUser::ChatUser(...) { /* 100+ Zeilen */ }
|
|
|
|
// Nachher: Aufgeteilt in kleine Funktionen
|
|
void initializeUser();
|
|
void loadUserData();
|
|
void generateToken();
|
|
```
|
|
|
|
### 6. **Error Handling**
|
|
Konsistente Fehlerbehandlung:
|
|
|
|
```cpp
|
|
bool WebSocketMessageHandler::sendJsonMessage(struct lws* wsi, const Json::Value& message) {
|
|
if (!wsi) return false;
|
|
|
|
try {
|
|
// Implementation
|
|
return true;
|
|
} catch (const std::exception& e) {
|
|
// Logging
|
|
return false;
|
|
}
|
|
}
|
|
```
|
|
|
|
### 7. **Constants**
|
|
Magic Numbers eliminiert:
|
|
|
|
```cpp
|
|
class MessageValidator {
|
|
private:
|
|
static constexpr size_t MIN_USERNAME_LENGTH = 1;
|
|
static constexpr size_t MAX_USERNAME_LENGTH = 50;
|
|
static constexpr size_t TOKEN_LENGTH = 32;
|
|
};
|
|
```
|
|
|
|
## 📁 Neue Klassenstruktur
|
|
|
|
### **Core Classes**
|
|
```
|
|
src/core/
|
|
├── user_repository.h/cpp # Datenbankoperationen
|
|
├── websocket_message_handler.h/cpp # WebSocket-Kommunikation
|
|
├── message_validator.h/cpp # Nachrichtenvalidierung
|
|
├── configuration_manager.h/cpp # Konfigurationsverwaltung
|
|
└── chat_user_clean.h/cpp # Refaktorierte ChatUser-Klasse
|
|
```
|
|
|
|
### **Vorteile der neuen Struktur**
|
|
|
|
1. **Testbarkeit**: Jede Klasse kann isoliert getestet werden
|
|
2. **Wiederverwendbarkeit**: Repository kann in anderen Kontexten verwendet werden
|
|
3. **Erweiterbarkeit**: Neue Nachrichtentypen einfach hinzufügbar
|
|
4. **Wartbarkeit**: Änderungen sind lokalisiert
|
|
|
|
## 🚀 Migration Guide
|
|
|
|
### **Schritt 1: Neue Klassen verwenden**
|
|
```cpp
|
|
// Alte ChatUser-Klasse ersetzen
|
|
// std::shared_ptr<ChatUser> user = ...;
|
|
std::shared_ptr<ChatUserClean> user = ChatUserClean::createWebSocketUser(...);
|
|
```
|
|
|
|
### **Schritt 2: Repository Pattern nutzen**
|
|
```cpp
|
|
// Alte direkte Datenbankabfragen ersetzen
|
|
// std::string color = loadColorFromDatabase(database, userName);
|
|
auto repository = std::make_shared<UserRepository>(database);
|
|
std::string color = repository->loadUserColor(userName);
|
|
```
|
|
|
|
### **Schritt 3: Validierung verwenden**
|
|
```cpp
|
|
// Alte manuelle Validierung ersetzen
|
|
// if (message.isMember("type") && message["type"].asString() == "init") { ... }
|
|
if (MessageValidator::validateInitRequest(message)) { ... }
|
|
```
|
|
|
|
## 📊 Metriken
|
|
|
|
### **Vorher**
|
|
- ChatUser-Konstruktor: 200+ Zeilen
|
|
- Code-Duplikation: 60%+ in Konstruktoren
|
|
- Zyklomatische Komplexität: 15+
|
|
- Verantwortlichkeiten pro Klasse: 3-5
|
|
|
|
### **Nachher**
|
|
- Größte Funktion: < 20 Zeilen
|
|
- Code-Duplikation: < 5%
|
|
- Zyklomatische Komplexität: < 5
|
|
- Verantwortlichkeiten pro Klasse: 1
|
|
|
|
## 🧪 Testing
|
|
|
|
Die neue Struktur ermöglicht einfaches Unit-Testing:
|
|
|
|
```cpp
|
|
// Beispiel: UserRepository testen
|
|
TEST(UserRepositoryTest, LoadUserColor) {
|
|
auto mockDatabase = std::make_shared<MockDatabase>();
|
|
UserRepository repository(mockDatabase);
|
|
|
|
EXPECT_CALL(*mockDatabase, exec(_))
|
|
.WillOnce(Return(mockResult));
|
|
|
|
std::string color = repository.loadUserColor("testuser");
|
|
EXPECT_EQ("#FF0000", color);
|
|
}
|
|
```
|
|
|
|
## 🔄 Nächste Schritte
|
|
|
|
1. **Vollständige Migration**: Alte Klassen schrittweise ersetzen
|
|
2. **Unit Tests**: Test-Suite für alle neuen Klassen
|
|
3. **Integration Tests**: End-to-End Tests
|
|
4. **Performance Tests**: Latenz und Durchsatz messen
|
|
5. **Code Coverage**: 90%+ Coverage anstreben
|
|
|
|
## 📚 Referenzen
|
|
|
|
- [Clean Code - Robert C. Martin](https://www.amazon.de/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882)
|
|
- [SOLID Principles](https://en.wikipedia.org/wiki/SOLID)
|
|
- [C++ Core Guidelines](https://isocpp.github.io/CppCoreGuidelines/)
|