IMCAT.DEV
로그인 가입
C++ 고급 디자인패턴

C++ C++의 디자인 원칙 (SOLID 등)

C++ C++의 디자인 원칙 (SOLID 등) — 고급

C++의 디자인 원칙 (SOLID 등)

1. 도입 (왜 배워야 하는가)

프로그래밍에서 코드의 품질과 유지보수성은 매우 중요합니다. 특히 팀 프로젝트나 대규모 시스템을 개발할 때, 디자인 원칙을 따르는 것은 코드의 가독성을 높이고, 버그를 줄이며, 새로운 기능을 추가할 때 발생하는 문제를 최소화하는 데 도움이 됩니다. 이를 통해 개발자는 더 나은 소프트웨어를 만들 수 있으며, 고객의 요구를 빠르게 충족할 수 있습니다.

디자인 원칙을 모른다면, 코드가 복잡해지고 가독성이 떨어지며, 수정이 어려워질 수 있습니다. 이는 결국 개발 시간의 증가와 비용의 상승으로 이어질 수 있습니다. 따라서 SOLID 원칙은 C++ 프로그래머에게 필수적으로 배워야 할 중요한 개념입니다.

2. 핵심 개념 설명

SOLID는 객체지향 프로그래밍의 다섯 가지 설계 원칙을 나타내며, 각 원칙은 다음과 같은 의미를 가집니다:

원칙설명
S - 단일 책임 원칙 (Single Responsibility Principle)클래스는 하나의 책임만 가져야 한다.
O - 개방-폐쇄 원칙 (Open/Closed Principle)클래스는 확장에 열려 있어야 하고, 수정에는 닫혀 있어야 한다.
L - 리스코프 치환 원칙 (Liskov Substitution Principle)자식 클래스는 부모 클래스의 자리를 대체할 수 있어야 한다.
I - 인터페이스 분리 원칙 (Interface Segregation Principle)클라이언트는 사용하지 않는 인터페이스에 의존하지 않아야 한다.
D - 의존관계 역전 원칙 (Dependency Inversion Principle)고수준 모듈은 저수준 모듈에 의존하면 안 된다.

이러한 원칙들은 마치 레고 블록처럼, 각기 다른 조각들이 함께 모여 강력한 구조물을 형성하는 것과 같습니다. 각 원칙이 지켜질 때, 코드는 더욱 튼튼하고 유연하게 변할 수 있습니다.

3. 기본 코드 예제

단일 책임 원칙 (SRP) 코드 예제

#include <iostream>
#include <string>

class Report {
public:
    void generateReport(const std::string& data) {
        std::cout << "Report generated with data: " << data << std::endl;
    }
};

class ReportPrinter {
public:
    void printReport(const Report& report) {
        std::cout << "Printing report..." << std::endl;
    }
};

int main() {
    Report report;
    report.generateReport("Sales Data");

    ReportPrinter printer;
    printer.printReport(report);

    return 0;
}

실행 결과:

Report generated with data: Sales Data
Printing report...
  • Report 클래스는 보고서를 생성하는 책임을 가진다.
  • ReportPrinter 클래스는 보고서를 출력하는 책임을 가진다.
  • 이처럼 각 클래스가 하나의 책임만 가지므로, 유지보수가 용이하다.
  • 4. 실전 활용 예제

    예제 1: 쇼핑몰에서 장바구니 구현

    #include <iostream>
    #include <vector>
    #include <string>
    
    class Item {
    public:
        std::string name;
        double price;
        
        Item(std::string n, double p) : name(n), price(p) {}
    };
    
    class Cart {
    private:
        std::vector<Item> items;
    
    public:
        void addItem(const Item& item) {
            items.push_back(item);
        }
    
        void displayItems() {
            std::cout << "Items in Cart:" << std::endl;
            for (const auto& item : items) {
                std::cout << item.name << ": $" << item.price << std::endl;
            }
        }
    };
    
    int main() {
        Cart cart;
        cart.addItem(Item("Shirt", 19.99));
        cart.addItem(Item("Pants", 39.99));
        
        cart.displayItems();
    
        return 0;
    }

    실행 결과:

    Items in Cart:
    Shirt: $19.99
    Pants: $39.99
  • Item 클래스는 상품의 이름과 가격을 가진다.
  • Cart 클래스는 장바구니의 아이템을 관리하고, 출력하는 책임을 가진다.
  • 이 구조는 SOLID 원칙을 따르며, 장바구니에 새로운 기능을 쉽게 추가할 수 있다.
  • 5. 흔한 실수와 주의사항

    실수 1: 단일 책임 원칙 위반

    class Report {
    public:
        void generateReport(const std::string& data) {
            // Generate report
        }
        
        void printReport() {
            // Print report
        }
    };
    // 위 코드는 Report 클래스가 두 가지 책임을 가짐
  • 올바른 코드: Report 클래스와 ReportPrinter 클래스를 분리하여 각 클래스에 하나의 책임을 부여해야 한다.
  • 실수 2: 의존관계 역전 원칙 위반

    class Database {
    public:
        void saveData() {
            // Save data to the database
        }
    };
    
    class User {
    private:
        Database db; // 의존성 주입이 없음
    
    public:
        void saveUser() {
            db.saveData();
        }
    };
    // 위 코드는 User 클래스가 Database에 강하게 결합되어 있음
  • 올바른 코드: 인터페이스를 통해 의존성을 주입하여 유연성을 높여야 한다.
  • 6. 정리

  • SOLID 원칙은 객체지향 프로그래밍에서 코드의 품질을 높이는 데 도움을 준다.
  • 각 원칙은 클래스의 책임을 명확히 하고, 코드를 확장 가능하게 만든다.
  • 디자인 원칙을 적용하면 유지보수와 팀 작업이 용이해진다.
  • 다음에 학습하면 좋은 주제

  • 디자인 패턴 (예: 전략 패턴, 옵저버 패턴)
  • 객체지향 설계 원칙 (GRASP)
  • C++의 메모리 관리 및 스마트 포인터 사용법