1. 개요
이 사용방법(예제)에서는 개체 지향 프로그래밍의 SOLID 원칙 중 하나인 단일 책임 원칙에 대해 설명합니다 .
전반적으로 이 원칙이 무엇인지, 소프트웨어를 설계할 때 이를 구현하는 방법에 대해 자세히 살펴보겠습니다. 또한 이 원칙이 오해의 소지가 있는 경우에 대해 설명합니다.
*SRP = 단일 책임 원칙
2. 단일 책임 원칙
이름에서 알 수 있듯이 이 원칙은 각 클래스가 하나의 책임, 하나의 목적을 가져야 한다고 명시합니다 . 이는 클래스가 하나의 작업만 수행한다는 의미이므로 변경해야 하는 이유는 하나뿐 이어야 한다는 결론을 내리게 됩니다 .
우리는 너무 많이 알고 관련 없는 행동을 하는 객체를 원하지 않습니다. 이러한 클래스는 유지하기가 더 어렵습니다. 예를 들어 여러 가지 이유로 많이 변경하는 클래스가 있는 경우 이 클래스를 더 많은 클래스로 나누어 각각 단일 관심사를 처리해야 합니다. 확실히 오류가 발생하면 찾기가 더 쉬울 것입니다.
어떤 식으로든 텍스트를 변경하는 코드가 포함된 클래스를 생각해 봅시다. 이 클래스의 유일한 작업은 텍스트를 조작하는 것입니다 .
public class TextManipulator {
private String text;
public TextManipulator(String text) {
this.text = text;
}
public String getText() {
return text;
}
public void appendText(String newText) {
text = text.concat(newText);
}
public String findWordAndReplace(String word, String replacementWord) {
if (text.contains(word)) {
text = text.replace(word, replacementWord);
}
return text;
}
public String findWordAndDelete(String word) {
if (text.contains(word)) {
text = text.replace(word, "");
}
return text;
}
public void printText() {
System.out.println(textManipulator.getText());
}
}
괜찮아 보일지 모르지만 SRP의 좋은 예는 아닙니다. 여기에서 우리는 두 가지 책임이 있습니다 : 텍스트를 조작하고 인쇄하는 것입니다 .
이 클래스에서 텍스트를 출력하는 메서드를 갖는 것은 단일 책임 원칙을 위반합니다. 이를 위해 텍스트 인쇄만 처리하는 다른 클래스를 만들어야 합니다.
public class TextPrinter {
TextManipulator textManipulator;
public TextPrinter(TextManipulator textManipulator) {
this.textManipulator = textManipulator;
}
public void printText() {
System.out.println(textManipulator.getText());
}
public void printOutEachWordOfText() {
System.out.println(Arrays.toString(textManipulator.getText().split(" ")));
}
public void printRangeOfCharacters(int startingIndex, int endIndex) {
System.out.println(textManipulator.getText().substring(startingIndex, endIndex));
}
}
이제 이 클래스에서 우리는 우리가 원하는 만큼 다양한 인쇄 텍스트에 대한 메서드를 만들 수 있습니다.
3. 이 원칙은 어떻게 오해의 소지가 있습니까?
소프트웨어에서 SRP를 구현하는 요령은 각 클래스의 책임을 아는 것입니다.
그러나 모든 개발자는 클래스 목적에 대한 비전을 가지고 있어 작업을 까다롭게 만듭니다. 이 원칙을 구현하는 방법에 대한 엄격한 지침이 없기 때문에 책임이 무엇인지에 대한 해석이 남아 있습니다.
이것이 의미하는 바는 애플리케이션의 디자이너인 우리만이 어떤 것이 클래스 범위에 있는지 여부를 결정할 수 있다는 것입니다.
SRP 원칙에 따라 클래스를 작성할 때 문제 도메인, 비즈니스 요구 사항 및 애플리케이션 아키텍처에 대해 생각해야 합니다. 매우 주관적이어서 이 원칙을 구현하는 것이 생각보다 어렵습니다. 이 사용방법(예제)에 있는 예제만큼 간단하지는 않습니다.
이것은 우리를 다음 요점으로 인도합니다.
4. 응집력
SRP 원칙에 따라 우리 수업은 하나의 기능을 고수합니다. 그들의 방법과 데이터는 하나의 명확한 목적과 관련될 것입니다. 이것은 높은 응집력 과 견고함을 의미하며 함께 오류를 줄입니다 .
SRP 원칙을 기반으로 소프트웨어를 설계할 때 응집력은 클래스에 대한 단일 책임을 찾는 데 도움이 되므로 필수적입니다. 이 개념은 또한 하나 이상의 책임이 있는 클래스를 찾는 데 도움이 됩니다.
TextManipulator 클래스 메서드 로 돌아가 보겠습니다 .
...
public void appendText(String newText) {
text = text.concat(newText);
}
public String findWordAndReplace(String word, String replacementWord) {
if (text.contains(word)) {
text = text.replace(word, replacementWord);
}
return text;
}
public String findWordAndDelete(String word) {
if (text.contains(word)) {
text = text.replace(word, "");
}
return text;
}
...
여기에 이 클래스가 수행하는 작업이 명확하게 표시되어 있습니다. 텍스트 조작.
그러나 응집력에 대해 생각하지 않고 이 클래스의 책임이 무엇인지에 대한 명확한 정의가 없다면 텍스트 작성 및 업데이트는 서로 다른 별개의 작업이라고 말할 수 있습니다. 이러한 생각에 따라 WriteText 및 UpdateText 라는 두 개의 개별 클래스여야 한다는 결론을 내릴 수 있습니다 .
실제로 우리는 거의 항상 함께 사용해야 하는 밀접하게 결합되고 느슨하게 결합된 두 클래스를 얻게 됩니다. 이 세 가지 방법은 서로 다른 작업을 수행할 수 있지만 기본적으로 텍스트 조작이라는 단일 목적을 수행합니다 . 핵심은 지나치게 생각하지 않는 것입니다.
분석법에서 높은 응집력을 달성하는 데 도움이 되는 도구 중 하나는 LCOM입니다. 기본적으로 LCOM은 클래스 구성 요소 간의 연결과 서로 간의 관계를 측정합니다.
Martin Hitz와 Behzad Montazeri는 Sonarqube 가 한동안 측정했지만 그 이후로 더 이상 사용되지 않는 LCOM4를 도입했습니다.
5. 결론
원칙의 이름은 자명하지만 잘못 구현하기가 얼마나 쉬운지 알 수 있습니다. 프로젝트를 개발할 때 모든 클래스의 책임을 구분하고 응집력에 각별한 주의를 기울이십시오.
항상 그렇듯이 코드는 GitHub에서 사용할 수 있습니다.