1. SOLID 원칙

더보기

1. SOLID

 

OOP, 객체 지향 프로그래밍 설계의 기본 원칙

 

SOLID  Eng. Kor.
SRP Single Responsibility Principle 단일 책임 원칙
OCP Open-Closed Principle 개방-폐쇄 원칙 
LSP Liskov Substitution Principle 리스코프 치환 원칙 
ISP Interface Segregation Principle 인터페이스 분리 원칙
DIP Dependency Inversion Principle 의존성 역전 원칙

 

 

2. SOLID 학습 목적

 

DI, 의존성 주입을 정확하게 이해하고

MVVM 패턴을 효과적으로 구현하기 위해서는

객체 지향 프로그래밍 설계의 5대 원칙(SOILD)를 이해하고 적절히 적용해야 합니다.

 

 

3. WPF 학습방향

 

C# WPF XAML, CodeBehind 기반 프로젝트 구현

C# WPF XAML, CodeBehind + Thread, Network

DI 이해

SOLID 이해

MVVM 적용

 

 

4. 고려사항

 

모든 프로그래밍 기술들은 현장을 경험하지 못한 학습자 관점에서 이해하기 어렵습니다.

 

모든 프로그래밍 기술들은 학습자를 위한 것이 아니라, 현장의 개발 효율을 높이기 위해 발전한 기술이기  때문에, 여러명과 협업하고, 수많은 기술들을 포함시켜, 최소 몇개월 단위로 작업을 목적으로 하기에, 단편적인 예제들로 학습자들에게 필요성을 납득시키기가 쉽지 않습니다.

 

"굳이 적용해야 하는가?" 하는 의문이 들 수도 있지만,

지금 학습 할 것들은 현장에서 사용하는 살아있는 지식이며,

기본적인 이론입니다.

 

납득하기 어렵더라도, 우선 알고 계셔야합니다.

 

2. 단일 책임 원칙 (SRP, Single responsibility principle)

더보기

1. 개념
"There should never be more than one reason for a class to change."
클래스가 여러개의 책임(기능)을 갖게 되면, 각 책임에 맞춰 연결된 모든 구현부를 변경해야하는 문제가 발생한다.

 

 

2. SRP를 지키지 않은 예제

using System;

// 단일 책임 원칙을 위반한 클래스
class Work
{
    public void Execute()
    {
        string networkData = AccessToNetwork();
        string downloadedData = DownloadData(networkData);
        string decryptedData = DecryptData(downloadedData);
        SaveAsFile(decryptedData);
    }

    private string AccessToNetwork()
    {
        Console.WriteLine("네트워크에 접근 중...");
        return "네트워크에서 받은 암호화된 데이터";
    }

    private string DownloadData(string networkData)
    {
        Console.WriteLine("데이터 다운로드 중...");
        return networkData;
    }

    private string DecryptData(string encryptedData)
    {
        Console.WriteLine("데이터 복호화 중...");
        return "복호화된 데이터";
    }

    private void SaveAsFile(string data)
    {
        Console.WriteLine("파일로 데이터 저장 중...");
    }
}

class Program
{
    static void Main()
    {
        Work work = new Work();
        work.Execute();
    }
}

 

Work 클래스가

  • 네트워크 접근
  • 데이터 다운로드
  • 데이터 복호화
  • 파일 저장

여러 책임을 한 곳에서 수행하고 있어 단일 책임 원칙(SRP)을 위반하고 있습니다.

Work 클래스의 기능 중 하나만 수정하더라도, 연결된 모든 클래스가 그에 맞춰 수정되어야 합니다.

 

 

 


3. SRP 적용된 예제

using System;

// 네트워크 접근 책임 클래스
class NetworkAccessor
{
    public string AccessToNetwork()
    {
        Console.WriteLine("네트워크에 접근 중...");
        return "네트워크에서 받은 암호화된 데이터";
    }
}

// 데이터 다운로드 책임 클래스
class DataDownloader
{
    public string DownloadData(string networkData)
    {
        Console.WriteLine("데이터 다운로드 중...");
        return networkData;
    }
}

// 데이터 복호화 책임 클래스
class DataDecryptor
{
    public string DecryptData(string encryptedData)
    {
        Console.WriteLine("데이터 복호화 중...");
        return "복호화된 데이터";
    }
}

// 파일 저장 책임 클래스
class FileSaver
{
    public void SaveAsFile(string data)
    {
        Console.WriteLine("파일로 데이터 저장 중...");
    }
}

// Work 클래스는 각 책임을 가진 클래스를 조합하여 사용
class Work
{
    private readonly NetworkAccessor _networkAccessor = new NetworkAccessor();
    private readonly DataDownloader _dataDownloader = new DataDownloader();
    private readonly DataDecryptor _dataDecryptor = new DataDecryptor();
    private readonly FileSaver _fileSaver = new FileSaver();
    
    public void Execute()
    {
        string networkData = _networkAccessor.AccessToNetwork();
        string downloadedData = _dataDownloader.DownloadData(networkData);
        string decryptedData = _dataDecryptor.DecryptData(downloadedData);
        _fileSaver.SaveAsFile(decryptedData);
    }
}

class Program
{
    static void Main()
    {
        Work work = new Work();
        work.Execute();
    }
}

 

 

코드에서 단일 책임 원칙(SRP)을 적용하여 각 클래스가 하나의 역할만 수행하도록 설계했습니다.

  • NetworkAccessor → 네트워크 접근
  • DataDownloader → 데이터 다운로드
  • DataDecryptor → 데이터 복호화
  • FileSaver → 파일 저장
  • Work → 각 책임 클래스를 조합하여 실행

이렇게 하면 각 클래스가 독립적으로 변경될 수 있어 유지보수성이 향상됩니다.

 

3. 추가 예제

더보기

1. SRP를 지키지 않은 예제

using System;

// 사용자 정보 클래스
class User
{
    public string Name { get; set; }
    public string Email { get; set; }
}

// 사용자 관리 클래스 (SRP가 지켜지지 않은 상태)
class UserManager
{
    public void RegisterUser(string name, string email)
    {
        // 사용자 정보 저장
        Console.WriteLine($"사용자 {name}의 정보가 저장되었습니다.");

        // 사용자에게 이메일 발송
        Console.WriteLine($"{name}님에게 이메일({email})을 발송하였습니다.");
    }
}

// 프로그램 실행
class Program
{
    static void Main()
    {
        UserManager userManager = new UserManager();
        userManager.RegisterUser("홍길동", "hong@example.com");
    }
}

 

UserManager 클래스는 사용자 등록에 관련된 두 가지 책임을 동시에 처리하고 있습니다.

  • 사용자 데이터 저장: 사용자 정보를 저장하는 기능을 수행.
  • 이메일 발송: 사용자에게 이메일을 보내는 기능을 수행.

단일 책임 원칙(SRP)에 맞지 않으며, 나중에 UserManager 클래스가 복잡해질 경우 유지보수 및 확장이 어려워질 수 있습니다. 각 책임을 별도의 클래스로 분리하는 것이 좋은 설계입니다

 

 

 

 

2. SRP 적용된 예제

using System;

// 새로운 SRP 예제: 사용자 정보 처리
class User
{
    public string Name { get; set; }
    public string Email { get; set; }
}

// 사용자 데이터 저장 책임 클래스
class UserDataSaver
{
    public void SaveUser(User user)
    {
        Console.WriteLine($"사용자 {user.Name}의 정보가 저장되었습니다.");
    }
}

// 사용자 알림 책임 클래스
class UserNotifier
{
    public void SendNotification(User user)
    {
        Console.WriteLine($"{user.Name}님에게 이메일({user.Email})을 발송하였습니다.");
    }
}

// SRP를 준수하는 사용자 관리 클래스
class UserManager
{
    private readonly UserDataSaver _userDataSaver = new UserDataSaver();
    private readonly UserNotifier _userNotifier = new UserNotifier();

    public void RegisterUser(string name, string email)
    {
        User user = new User { Name = name, Email = email };
        _userDataSaver.SaveUser(user);
        _userNotifier.SendNotification(user);
    }
}

// 프로그램 실행
class Program
{
    static void Main()
    {

        UserManager userManager = new UserManager();
        userManager.RegisterUser("홍길동", "hong@example.com");
    }
}