본문 바로가기
개발/Architecture & Design Pattern

C++ - 단일 책임 원칙 (SRP, Single Responsibility Principle)

by 피로물든딸기 2024. 2. 12.
반응형

C, C++ 전체 링크

Architecture & Design Pattern 전체 링크

 

단일 책임 원칙 (SRP, Single Responsibility Principle)

- 소프트웨어의 모듈 또는 클래스는 단 하나의 책임만 가져야 한다.

- 클래스를 바꾸는 이유는 한 가지뿐이어야 한다.

- 유지 보수, 재사용성, 테스트 용이성에 이점이 있다.


먼저 단일 책임 원칙 위반 사례를 보자.

 

아래의 예시는 fstreamofstreamifstream을 이용하여 파일을 쓰고 읽을 수 있는 FileManager 클래스다.

class FileManager 
{
public:
	void writeFile(const string& filename, const string& content) 
	{
		ofstream file(filename);
		...
	}

	string readFile(const string& filename) 
	{
		string content;
		ifstream file(filename);
		...

		return content;
	}
};

 

FileManager는 다음과 같이 사용할 수 있는데, 이 클래스는 현재 두 가지 일을 하고 있다. (읽기, 쓰기)

단일 책임만 가지기 위해서는 쓰기와 읽기 기능을 서로 다른 책임으로 분리해야 한다.

int main() 
{
	FileManager* fileManager = new FileManager();

	string content = "Hello, World!";
	fileManager->writeFile("example.txt", content);

	string readContent = fileManager->readFile("example.txt");
	cout << "File content: " << readContent << endl;

	return 0;
}

 

예시 코드는 다음과 같다.

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

class FileManager 
{
public:
	void writeFile(const string& filename, const string& content) 
	{
		ofstream file(filename);
		if (file.is_open()) 
		{
			file << content;
			file.close();
		}
		else 
		{
			cerr << "Unable to open file: " << filename << endl;
		}
	}

	string readFile(const string& filename) 
	{
		string content;
		ifstream file(filename);
		if (file.is_open()) 
		{
			string line;
			while (getline(file, line)) content += line + "\n";

			file.close();
		}
		else 
		{
			cerr << "Unable to open file: " << filename << endl;
		}

		return content;
	}
};

int main() 
{
	FileManager* fileManager = new FileManager();

	string content = "Hello, World!";
	fileManager->writeFile("example.txt", content);

	string readContent = fileManager->readFile("example.txt");
	cout << "File content: " << readContent << endl;

	return 0;
}


단일 책임 원칙 적용

 

FileManagerwrite/read 메서드를 해당 기능에 맞게 클래스로 구분하면 된다.

FileMangerFileWriterFileReader로 나누면 클라이언트 코드는 다음과 같이 변경된다.

int main() 
{
	FileWriter* fileWriter = new FileWriter();
	FileReader* fileReader = new FileReader();

	string content = "Hello, World!";
	fileWriter->writeFile("example.txt", content);

	string readContent = fileReader->readFile("example.txt");
	cout << "File content: " << readContent << endl;

	return 0;
}

 

전체 코드는 다음과 같다.

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

class FileWriter 
{
public:
	void writeFile(const string& filename, const string& content) 
	{
		ofstream file(filename);
		if (file.is_open()) 
		{
			file << content;
			file.close();
		}
		else 
		{
			cerr << "Unable to open file: " << filename << endl;
		}
	}
};

class FileReader
{
public:
	string readFile(const string& filename) 
	{
		string content;
		ifstream file(filename);
		if (file.is_open())
		{
			string line;
			while (getline(file, line)) content += line + "\n";

			file.close();
		}
		else 
		{
			cerr << "Unable to open file: " << filename << endl;
		}

		return content;
	}
};

int main() 
{
	FileWriter* fileWriter = new FileWriter();
	FileReader* fileReader = new FileReader();

	string content = "Hello, World!";
	fileWriter->writeFile("example.txt", content);

	string readContent = fileReader->readFile("example.txt");
	cout << "File content: " << readContent << endl;

	return 0;
}

 

 

 

반응형

댓글