A modular, scalable refactoring of a legacy messaging application. This project demonstrates the transformation of a monolithic "C with Classes" script into a robust, layered architecture adhering to SOLID principles and Modern C++ (C++17/20) standards.
The objective was to take a fragile, tightly coupled codebase and architect a solution that allows for:
- Scalability: Efficient data handling for large user bases.
- Extensibility: Easy addition of new user interfaces (GUI, Voice, VR) without touching business logic.
- Testability: Decoupled components that allow for unit testing via mocking.
The project uses a Layered Architecture with strict Separation of Concerns:
IMessageService(Interface): Defines the contract for messaging operations. This abstraction allows the backend to be swapped (e.g., from In-Memory to SQL) without breaking the app.InMemoryMessageService(Implementation): A concrete implementation using optimized data structures.- Data Structures: Replaced
std::vector(O(n)) withstd::unordered_mapandstd::unordered_set(O(1)) for instant user lookups and inbox retrieval. - Memory Management: Full RAII compliance. Zero manual
new/delete. usedstd::unique_ptrand value semantics to prevent leaks.
- Data Structures: Replaced
- Dependency Injection: The UI accepts an
IMessageService&in its constructor, decoupling it from the specific backend implementation. - Dispatch Table: Uses
std::unordered_map<std::string, std::function<void()>>to map user inputs to actions, replacing fragileif/elsechains and adhering to the Open/Closed Principle.
- Modern C++ Idioms:
- Structured Binding: For clean return values (e.g.,
auto [iter, success] = ...). - Move Semantics: Messages are
std::move'd rather than copied, ensuring high performance even with large payloads. - Smart Pointers & Containers: Safe memory handling using standard library containers.
- Structured Binding: For clean return values (e.g.,
- Safety:
[[nodiscard]]attributes to enforce error checking.enum classfor type-safe return states.- Const Correctness applied rigorously to read-only methods.
βββ Core/
β βββ IMessageService.h # Abstract Interface
β βββ MessageService.h # Concrete Header
β βββ MessageService.cpp # Business Logic Implementation
βββ UI/
β βββ CommandLineUI.h # CLI Header
β βββ CommandLineUI.cpp # CLI Implementation (Input/Output)
βββ main.cpp # Composition Root
- A C++ Compiler supporting C++17 or higher (MSVC, GCC, Clang).
- Visual Studio (recommended) or CMake.
- Open the solution file (
.sln). - Ensure the project properties include
$(ProjectDir)in Additional Include Directories to support modular includes. - Build and Run.
Because of the interface-based design, adding a new UI (e.g., for a Game Engine) is trivial:
// You don't need to change the Service code at all!
class GameHUD : public IGameUI {
Core::IMessageService& service;
public:
void OnSendButtonClicked(string msg) {
service.sendMessage("Player1", "Player2", msg);
}
};