단일 책임 원칙을 사용할 때 "책임"은 무엇입니까?


198

"단일 책임 원칙"이 "한 가지 일만"을 의미하는 것은 아님이 분명합니다. 그것이 방법에 대한 것입니다.

public Interface CustomerCRUD
{
    public void Create(Customer customer);
    public Customer Read(int CustomerID);
    public void Update(Customer customer);
    public void Delete(int CustomerID);
}

밥 마틴은 "수업은 변화해야 할 단 하나의 이유가 있어야한다"고 말했다. 그러나 SOLID를 처음 사용하는 프로그래머라면 마음을 감싸기가 어렵습니다.

나는 또 다른 질문에 대한 답변을 썼는데 , 여기서 책임은 직책과 같다고 제안했고 식당 요를 사용하여 내 요점을 설명함으로써 주제를 중심으로 춤을 추었습니다. 그러나 이것은 여전히 ​​누군가가 자신의 수업 책임을 정의하는 데 사용할 수있는 일련의 원칙을 분명히 보여주지는 않습니다.

어떻게합니까? 각 학급의 책임을 어떻게 결정하고 SRP와 관련하여 책임을 어떻게 정의합니까?


28
코드 검토에 게시 하고 찢어짐 :-D
Jörg W Mittag

8
@ JörgWMittag 안녕하세요, 사람들을 놀라게하지 마십시오 :)
Flambino

118
재향 군인들의 이러한 질문은 우리가 유지하려고하는 규칙과 원칙이 결코 간단 하거나 단순 하지 않다는 것을 보여줍니다 . 그것들은 좋은 규칙 들이 있어야하기 때문에 자기 모순적이고 신비적 이다. 그리고 저는 이와 같은 질문이 현명한 사람을 겸손하게하고 싶습니다. 고마워 Robert!
svidgen

41
이 질문이 멍청한 놈에 의해 게시 된 경우 즉시 + + 중복으로 표시되었는지 궁금합니다.)
Andrejs

9
@rmunn : 또는 다른 말로하면-큰 담당자는 더 많은 담당자를 유치합니다. 아무도 스택 교환에 대한 기본적인 인간의 편견을 취소하지 않았기 때문에
Andrejs

답변:


117

이 문제를 해결하는 한 가지 방법은 향후 프로젝트의 잠재적 요구 사항 변화를 상상하고이를 실현하기 위해 무엇을해야하는지 자문하는 것입니다.

예를 들면 다음과 같습니다.

새로운 사업 요건 : 캘리포니아에 위치한 사용자는 특별 할인을받습니다.

"좋은"변화의 예 : 할인을 계산하는 클래스에서 코드를 수정해야합니다.

잘못된 변경의 예 : User 클래스에서 코드를 수정해야하며 그 변경은 할인과 관련이없는 클래스 (예 : 등록, 열거 및 관리)를 포함하여 User 클래스를 사용하는 다른 클래스에 계단식으로 영향을 미칩니다.

또는:

새로운 비 기능적 요구 사항 : SQL Server 대신 Oracle을 사용하기 시작합니다

올바른 변경 예 : DTO에서 데이터를 유지하는 방법을 결정하는 데이터 액세스 계층에서 단일 클래스를 수정하기 만하면됩니다.

나쁜 변경 : 모든 비즈니스 계층 클래스에는 SQL Server 관련 논리가 포함되어 있으므로 모든 비즈니스 계층 클래스를 수정해야합니다.

아이디어는 향후 잠재적 변경의 풋 프린트를 최소화하여 코드 수정을 변경 영역 당 하나의 코드 영역으로 제한하는 것입니다.

최소한 수업에서 논리적 관심사와 물리적 관심사를 분리해야합니다. 예제의 큰 세트는에서 찾을 수 있습니다 System.IO네임 스페이스 : 거기에 우리가 물리적 스트림 (예를 들면의 각종 찾을 수 있습니다 FileStream, MemoryStream또는 NetworkStream) 여러 독자와 작가 ( BinaryWriter, TextWriter논리적 수준에서) 그 일을. 그들에게이 방법을 분리함으로써, 우리는 combinatoric 폭발을 방지 : 대신 필요한의 FileStreamTextWriter, FileStreamBinaryWriter, NetworkStreamTextWriter, NetworkStreamBinaryWriter, MemoryStreamTextWriter, 그리고 MemoryStreamBinaryWriter, 당신은 단지 작가와 스트림를 연결하고 당신이 원하는 것을 할 수 있습니다. 그런 다음 나중에 XmlWriter메모리, 파일 및 네트워크에 대해 별도로 다시 구현할 필요없이을 추가 할 수 있습니다 .


34
앞서 생각하는 것에 동의하지만, YAGNI와 같은 원칙과 TDD thar와 같은 방법론이 그 반대를 제안합니다.
Robert Harvey

87
야니는 오늘날 우리가 필요로하지 않는 물건을 만들지 말라고 말합니다. 확장 가능한 방식으로 물건을 만들지 말라고 지시하지 않습니다. "소프트웨어 엔터티 (클래스, 모듈, 함수 등)는 확장을 위해 열려야하지만 수정을 위해 닫혀 있어야합니다."라는 개방 / 폐쇄 원칙 도 참조하십시오 .
John Wu

18
@JohnW : YAGNI 의견만으로는 +1. 나는 야 그니가 변화에 반응 할 수없는 견고하고 융통성없는 시스템을 구축 할 변명 이 아니라는 것을 사람들에게 얼마나 많이 설명해야하는지 믿을 수 없다.
Greg Burghardt

36
@JohnWu : 동의하지 않습니다. YAGNI는 오늘날 우리가 필요로하지 않는 것을 제작하지 말라고 말합니다. 예를 들어, 가독성과 테스트는 프로그램이 항상 "오늘"필요로하는 것이므로 YAGNI는 구조와 주 입점을 추가하지 않을 이유가 결코 아닙니다. 그러나 "확장 성"이 이점이 "오늘"명백하지 않은 상당한 비용을 추가하자마자 YAGNI는 이러한 유형의 확장 성을 피해야합니다. 후자는 과도하게 엔지니어링되기 때문입니다.
Doc Brown

9
@JohnWu 우리는 SQL 2008에서 2012로 전환했습니다. 변경이 필요한 총 두 개의 쿼리가있었습니다. 그리고 SQL Auth에서 신뢰할 수있는 것으로? 왜 코드 변경일까요? 구성 파일에서 connectionString을 변경하는 것으로 충분합니다. 다시 YAGNI. YAGNI와 SRP는 때때로 경쟁 문제로, 어느 쪽이 비용 / 혜택이 더 좋은지 판단해야합니다.
Andy

76

실제로, 책임은 변화 할 가능성이 있는 것들에 의해 좌우됩니다 . 따라서 불행히도 책임을 구성하는 요소에 도달하는 과학적 또는 공식적인 방법은 없습니다. 판결 요청입니다.

경험상 어떤 변화가 있을지에 관한 것 입니다.

우리는이 원칙의 언어를 쌍곡적이고 문자 적이며 열성적인 분노로 적용하는 경향이 있습니다. 우리는 클래스 변경되거나 단순히 문제를 해결하는 데 도움이되는 라인을 따라 나누는 경향 있습니다. (후자의 이유는 본질적으로 나쁘지 않습니다.) 그러나 SRP는 자체적으로 존재하지 않습니다. 유지 관리 가능한 소프트웨어 를 만드는 데 사용됩니다.

다시 말하지만, 부서가 변경 가능성 에 의해 주도 되지 않으면 YAGNI가 더 적용 가능하다면 실제로 SRP 1 에 서비스를 제공 하지 않습니다 . 둘 다 동일한 궁극적 목표를 제공합니다. 그리고 모두가 희망 - 판단의 문제이다 노련한 판단.

밥 아저씨가 이것에 대해 글을 쓸 때, 우리는 "변화를 요구하는 사람"이라는 관점에서 "책임"을 생각할 것을 제안합니다. 다시 말해서, 우리는 B 당이 변화를 요청했기 때문에 A 당이 일자리를 잃는 것을 원하지 않습니다.

소프트웨어 모듈을 작성할 때 변경이 요청 될 때 이러한 변경이 단일 개인 또는 좁은 정의 된 단일 비즈니스 기능을 나타내는 하나의 밀접하게 연결된 단일 사용자 그룹에서만 발생할 수 있는지 확인하려고합니다. 모듈을 조직 전체의 복잡성으로부터 분리하고 각 모듈이 하나의 비즈니스 기능의 요구에 책임을 지도록 시스템을 설계하려고합니다. ( 삼촌 삼촌-단일 책임 원칙 )

경험이 풍부하고 숙련 된 개발자라면 변경 될 가능성이 있습니다. 그리고 그 정신 목록은 산업과 조직에 따라 다소 다를 것입니다.

특정 응용 프로그램, 특정 조직의 책임은 궁극적으로 노련한 판단 의 문제입니다 . 변화 가능성에 관한 것입니다. 그리고 어떤 의미에서, 누가 모듈의 내부 로직 을 소유하고 있는지 에 관한 것 입니다 .


1. 분명히, 그것이 그들이 나쁜 분열 이라는 것을 의미하지는 않습니다 . 코드 가독성을 극적으로 향상시키는 훌륭한 부서 가 될 수 있습니다 . 그것은 단지 그들이 SRP에 의해 주도되지 않는다는 것을 의미합니다.


11
가장 좋은 대답은 실제로 삼촌 밥의 생각을 인용 한 것입니다. 변경 될 가능성에 관해서는, 모두가 "데이터베이스를 변경하면 어떻게 될까?" 또는 "XML에서 JSON으로 전환하면 어떻게됩니까?" 나는 이것이 일반적으로 잘못 인도 되었다고 생각합니다 . 실제 질문은 "이 정수를 부동 소수점으로 변경하고 필드를 추가하고이 문자열을 문자열 목록으로 변경해야한다면 어떻게해야할까요?"
user949300

2
이것은 부정 행위입니다. 단일 책임 자체는 제안 된 "변경 격리"방법 일뿐입니다. 책임을 "단일"로 유지하기 위해 변경 사항을 분리해야한다고 설명하는 것은이를 수행하는 방법을 제안하지 않으며 요구 사항의 출처 만 설명합니다.
Basilevs

6
@Basilevs 밥 삼촌의 대답은 말할 것도없고,이 대답에서 당신이보고있는 결핍에 대해 연마하려고 노력하고 있습니다! 그러나 SRP가 "변경"이 1 개의 클래스에만 영향을 미치도록 보장하는 것이 아니라는 것을 분명히해야 할 것입니다. 각 수업이 "한 번의 변경"에만 응답하도록하는 것입니다. ... 각 클래스에서 단일 소유자에게 화살표를 그리려고합니다. 각 소유자에서 단일 클래스로가 아닙니다.
svidgen

2
실용적으로 답변 해 주셔서 감사합니다! Bob 아저씨조차도 Agile Architecture의 SOLID 원칙에 대한 열의 준수에 대해 경고합니다 . 인용 부호는 없지만, 기본적으로 분할 책임은 본질적으로 코드의 추상화 수준을 높이고 모든 추상화는 비용이 발생하므로 SRP (또는 다른 원칙)를 따르는 이점비용을 능가 하는지 확인하십시오. 더 많은 추상화를 추가합니다. (다음 댓글에 계속)
Michael L.

4
그렇기 때문에 우리 제품을 고객에게 조기에 합리적으로 자주 배치해야하므로 디자인을 강제 로 변경하고 해당 제품에서 어떤 영역이 변경 수 있는지 확인할 수 있습니다 . 또한 그는 모든 종류의 변화 로부터 우리 자신을 보호 할 수 없다고 경고합니다 . 를 들어 어떤 응용 프로그램, 변화의 특정 종류 만들 어려울 것이다. 우리는 이것이 일어날 가능성이 가장 적은 변화인지 확인해야합니다.
Michael L.

29

"수업 변경해야 할 이유는 한 가지만 있어야합니다"를 따릅니다.

저에게 이것은 제품 소유자가 생각해 볼 수있는 무질서한 계획 ( "모바일을 지원해야합니다!", "우리는 클라우드로 가야합니다!", "중국어를 지원해야합니다!")을 의미합니다. 좋은 디자인은 이러한 계획의 영향을 더 작은 영역으로 제한하고 상대적으로 쉽게 달성 할 수 있습니다. 잘못된 디자인은 많은 코드를 작성하고 위험한 변경을 많이한다는 것을 의미합니다.

경험은 그 미친 계획의 가능성을 적절하게 평가할 수있는 유일한 방법입니다. 하나를 쉽게 만들면 다른 두 사람이 더 어려워 질 수 있고 디자인의 우수성을 평가할 수 있기 때문입니다. 숙련 된 프로그래머는 코드를 변경하기 위해 무엇을해야하는지, 엉덩이에 물릴 때 무엇을해야하는지, 어떤 트릭으로 인해 일이 쉬워 지는지 상상할 수 있습니다. 숙련 된 프로그래머는 제품 소유자가 미쳤던 물건을 요청할 때 자신이 얼마나 망가 졌는지에 대해 좋은 생각을 가지고 있습니다.

실제로 단위 테스트가 도움이된다는 것을 알게되었습니다. 코드가 융통성이 없으면 테스트하기가 어렵습니다. 모형 또는 다른 테스트 데이터를 주입 할 수없는 경우 해당 SupportChinese코드 를 주입하지 못할 수 있습니다.

또 다른 기준은 엘리베이터 피치입니다. 전통적인 엘리베이터 피치는 "만약 당신이 투자자와 함께 엘리베이터에 있었다면, 아이디어로 팔 수 있습니까?" 스타트 업은 자신이 무엇을하고 있는지, 초점이 무엇인지에 대한 간단하고 간단한 설명이 필요합니다. 마찬가지로, 클래스 (및 기능)가 무엇인지 간단한 설명이 있어야 할을 . "이 클래스는 이러한 특정 시나리오에서 사용할 수 있도록 일부 fubar를 구현합니다". 다른 개발자에게 "이 클래스는 사용자를 만듭니다"라고 말할 수 있습니다. 다른 개발자와 의사 소통 할 수 없다면 버그 가 생길 것 입니다.


때로는 지저분한 변화라고 생각한 것을 구현하려고 할 때 간단하게 드러나거나 작은 리 팩터로 간단하게 만들고 유용한 기능을 동시에 추가합니다. 하지만 보통 문제가 발생하는 것을 볼 수 있습니다.

16
나는 "엘리베이터 피치"아이디어의 큰 지지자입니다. 한두 문장에서 수업이 무엇을하는지 설명하기 어려운 경우, 당신은 위험한 지역에 있습니다.
Ivan

1
중요한 요점은 다음과 같습니다. 미친 계획의 가능성은 프로젝트 소유자마다 크게 다릅니다. 일반적인 경험뿐만 아니라 프로젝트 소유자를 얼마나 잘 알고 있는지에 의존해야합니다. 나는 1 주일에 이르기까지 우리의 달리기를 절단하고 싶어하고, 사람들을 위해 일한 여전히 방향 중간 질주를 변경하는 것을 방지 할 수 없었다.
Kevin Krumwiede

1
명백한 이점 외에도 "엘리베이터 피치"를 사용하여 코드를 문서화하면 여러 책임을 밝히는 데 도움이되는 자연어를 사용하여 코드가 수행하는 작업을 생각할 수 있습니다.
Alexander

1
@KevinKrumwiede "머리를 자른 채로 돌아 다니는 닭"과 "와일드 거위 체이스"방법론에 대한 것입니다!

26

아무도 모른다. 또는 적어도 하나의 정의에 동의 할 수 없습니다. 이것이 SPR (및 기타 SOLID 원칙)을 논란의 여지가있는 이유입니다.

나는 책임이 무엇인지 아닌지를 알아낼 수 있다고 소프트웨어 개발자가 자신의 경력을 통해 배우는 기술 중 하나입니다. 더 많은 코드를 작성하고 검토할수록 무언가가 단일 책임인지 다중 책임인지 판단해야합니다. 또는 코드의 개별 부분에 단일 책임이 적용되는 경우.

나는 SRP의 주요 목적이 엄격한 규칙이 아니라고 주장한다. 코드에서 응집력을 염두에두고 항상 어떤 코드가 응집성인지 아닌지를 결정하기 위해 의식적인 노력을 기울여야한다는 점을 상기시켜야합니다.


20
새로운 프로그래머는 SOLID를 마치 법률 집합처럼 취급하지 않는 경향이 있습니다. 사람들이 수업 디자인을 향상시키는 데 도움이되는 좋은 아이디어 그룹 일뿐입니다. 아아, 사람들은이 원칙들을 너무 진지하게 받아들이는 경향이있다. 최근에 SOLID를 작업 요구 사항 중 하나로 언급 한 작업 게시를 보았습니다.
Robert Harvey

9
마지막 단락에 +42 @RobertHarvey가 말했듯이 SPR, SOLID 및 YAGNI와 같은 것은 " 절대 규칙 " 으로 간주하지 말고 "좋은 조언"의 일반적인 원칙으로 삼아야합니다 . 그들과 다른 사람들 사이에서 조언은 모순 될 수 있지만, (경쟁적인 규칙을 따르는 것과는 대조적으로) 그 조언의 균형을 맞추면 (경험이 커질수록 시간이 지남에 따라) 더 나은 소프트웨어를 생산하게됩니다. 소프트웨어 개발 에는 " 절대 규칙이 없습니다 "라는 단 하나의 "절대 규칙"이 있어야합니다 .
TripeHound

이것은 SRP의 한 측면에 대한 설명입니다. 그러나 SOLID 원칙이 어려운 규칙이 아니더라도, 아무도 자신이 의미하는 바를 이해하지 못하면 그다지 가치가 없습니다. ... 이해하기 어려운 것이 합리적입니다. 어떤 기술과 마찬가지로, 거기에 뭔가 로부터 좋은 구별 좋은! 그러나 ... "아무도 모르는"것은 더 번거로운 의식입니다. (그리고 이것이 SOLID의 의도라고 생각하지 않습니다!)
svidgen

3
"아무도 모른다"는 말로 @Euphoric 은 모든 유스 케이스에 맞는 정확한 정의 가 없음을 의미하기를 바랍니다 . 어느 정도의 판단이 필요한 것입니다. 책임이있는 위치를 결정하는 가장 좋은 방법 중 하나는 빠르게 반복하고 코드베이스가 알려주는 것 입니다. 코드를 쉽게 관리 할 수없는 "냄새"를 찾으십시오. 예를 들어, 단일 비즈니스 규칙에 대한 변경이 계단식으로 관련이없는 것처럼 보이는 클래스에 영향을 미치기 시작하면 SRP를 위반했을 수 있습니다.
Michael L.

1
@TripeHound와 다른 모든 "규칙"이 개발의 진정한 종교를 정의하는 데 존재하지 않지만 유지 관리 가능한 소프트웨어를 개발할 가능성을 높이기 위해 존재한다고 지적한 사람들은 진심으로 두 번째입니다. 유지 관리 가능한 소프트웨어를 홍보하고 품질을 향상 시키거나 개발 효율성을 높이는 방법을 설명 할 수없는 경우 "모범 사례"를 따르는 것에 매우주의하십시오.
Michael L.

5

"책임"이라는 용어는 소프트웨어를 사용하여 소프트웨어가 얼마나 잘 구성되어 있는지 조사 할 수 있기 때문에 은유로 유용하다고 생각합니다. 특히 두 가지 원칙에 중점을 두었습니다.

  • 책임은 권위와 비례합니다.
  • 두 개체가 같은 일을 책임지지 않아야합니다.

이 두 가지 원칙은 우리가 서로 경쟁하기 때문에 의미있게 책임을지게합니다. 코드를 통해 무언가를 할 수있는 권한을 부여하는 경우 코드의 기능에 대한 책임이 있어야합니다. 이로 인해 클래스가 커져야 할 책임이 생겨서 "변화해야 할 한 가지 이유"가 더 넓고 넓은 범위로 확대되었습니다. 그러나 사물을 넓히면 자연스럽게 여러 엔터티가 같은 일을 담당하는 상황에 처하게됩니다. 이것은 실제 책임에 문제가 있기 때문에 코딩에도 문제가 있습니다. 결과적으로이 원칙은 책임을 복제되지 않은 소포로 세분 할 때 범위가 좁아지게합니다.

이 두 가지 외에도 세 번째 원칙은 합리적입니다.

  • 책임을 위임 할 수 있습니다

갓 짜여진 프로그램, 빈 슬레이트를 생각해보십시오. 처음에는 하나의 엔터티 만 있으며 이는 전체 프로그램입니다. 모든 책임은 ... 당연히 어느 시점에서 기능이나 수업에 책임을 위임하기 시작합니다. 이 시점에서 처음 두 규칙은 그 책임의 균형을 강요합니다. 최고 수준의 프로그램은 관리자가 팀의 생산성을 담당하는 것처럼 전체 결과에 대해 여전히 책임이 있지만 각 하위 조직은 책임을 위임 받았으며 해당 책임을 수행 할 권한이 있습니다.

또한 보너스로 인해 SOLID는 기업 소프트웨어 개발과 특히 호환 될 수 있습니다. 지구상의 모든 회사는 책임을 위임하는 방법에 대한 개념을 가지고 있으며 모두 동의하지는 않습니다. 회사 자체의 위임을 연상시키는 방식으로 소프트웨어 내에서 책임을 위임하면 미래의 개발자가이 회사에서 업무를 수행하는 방법을보다 쉽게 ​​익힐 수 있습니다.


이것이 100 % 확실하지 않다고 확신합니다. 그러나 "권한"과 관련하여 "책임"을 설명하는 것이 통찰력있는 방법이라고 생각합니다. (+1)
svidgen

Pirsig는 "기계에 문제를 일으키는 경향이 있습니다"라고 말했습니다.

@nocomprende 당신은 또한 기계에 당신의 강점을 구축하는 경향이 있습니다. 나는 당신의 강점과 약점이 동일 할 때, 그것이 흥미로워 질 때라고 주장합니다.
Cort Ammon

5

에서 이 회의 예일, 삼촌 밥 이주는 재미 예 :

여기에 이미지 설명을 입력하십시오

그는 Employee변경해야 할 세 가지 이유, 변경 요구 사항의 세 가지 소스가 있으며,이 유머러스하고 뺨을 내밀지 만 설명 은 한다고 설명합니다.

  • 는 IF CalcPay()방법에 오류가 및 US $의 회사 수백만 비용, CFO가 당신을 해고 할 것이다 .

  • 는 IF ReportHours()방법에 오류가 및 US $의 회사 수백만 비용, 운영 책임자 (COO) 당신을 해고 할 것이다 .

  • 는 IF WriteEmmployee() 방법은 많은 양의 데이터의 삭제가 발생하고 US $의 회사 수백만 비용에 오류가, CTO 인 당신을 해고 할 것이다 .

따라서 같은 클래스에서 비용이 많이 드는 오류로 인해 세 가지 C 레벨 exec가 발생할 수 있으므로 클래스에 너무 많은 책임이 있습니다.

그는 SRP 위반을 해결하는이 솔루션을 제공하지만 비디오에는 표시되지 않은 DIP 위반을 해결해야합니다.

여기에 이미지 설명을 입력하십시오


이 예제는 책임 이 잘못된 클래스처럼 보입니다 .
Robert Harvey

4
@RobertHarvey 클래스에 책임이 너무 많으면 추가 책임이 잘못된 책임 임을 의미합니다 .
Tulains Córdova

5
당신이하는 말을 듣지만 설득력이 없습니다. 책임이 너무 많은 수업과 비즈니스가 전혀없는 일을하는 수업에는 차이가 있습니다. 소리는 같지만 그렇지 않습니다. 땅콩을 세는 것은 호두를 부르는 것과 다릅니다. Bob 아저씨의 원리와 Bob 아저씨의 예입니다. 그러나 충분히 설명 적이라면이 질문이 전혀 필요하지 않습니다.
Robert Harvey

@RobertHarvey, 차이점은 무엇입니까? 그 상황은 나에게 동형 인 것 같습니다.
Paul Draper

3

"변경 사유"보다 사물을 세분화하는 더 좋은 방법은 두 가지 (또는 그 이상)의 행동을 수행해야하는 코드가 별도의 객체 참조를 보유해야하는지 여부를 고려하는 것에서 시작하는 것입니다. 각 작업에 대해, 그리고 하나의 작업 만 수행 할 수 있지만 다른 작업은 수행 할 수없는 공용 개체를 갖는 것이 유용한 지 여부

두 질문 모두에 대한 답이 예라면, 조치는 별도의 수업으로 수행되어야 함을 나타냅니다. 두 질문 모두에 대한 대답이 '아니오'라면, 공공 입장에서 볼 때 하나의 수업이 있어야 함을 시사합니다. 코드가 다루기 어려울 경우 내부적으로 개인 클래스로 세분 될 수 있습니다. 첫 번째 질문에 대한 답이 '아니오',하지만 두 번째 예라면, 각 작업에 대한 별도의 클래스가 있어야한다 플러스 다른 사람의 인스턴스에 대한 참조를 포함하는 복합 클래스입니다.

금전 등록기의 키패드, 신호음, 숫자 판독, 영수증 프린터 및 금전함에 대한 별도의 클래스가 있고 완전한 금전 등록기에 대한 복합 클래스가없는 경우 트랜잭션을 처리해야하는 코드가 실수로 호출 될 수 있습니다. 한 컴퓨터의 키패드에서 입력을 받고, 두 번째 컴퓨터의 신호음에서 소음을 발생시키고, 세 번째 컴퓨터의 디스플레이에 숫자를 표시하고, 네 번째 컴퓨터의 프린터에 영수증을 인쇄하며, 다섯 번째 컴퓨터의 금전 함을 띄웁니다. 각 하위 함수는 별도의 클래스에서 유용하게 처리 될 수 있지만 결합하는 복합 클래스도 있어야합니다. 복합 클래스는 가능한 많은 논리를 구성 클래스에 위임해야합니다.

각 클래스의 "책임"은 실제 논리를 통합하거나 그렇게하는 다른 여러 클래스에 공통된 연결 지점을 제공하는 것이라고 말할 수 있지만, 가장 중요한 것은 클라이언트 코드가 클래스를 보는 방법에 가장 중점을 두는 것입니다. 클라이언트 코드가 무언가를 단일 객체로 보는 것이 합리적이라면 클라이언트 코드는이를 단일 객체로 간주해야합니다.


이것은 건전한 조언입니다. SRP보다 더 많은 기준에 따라 책임을 나누는 것이 좋습니다.
Jørgen Fogh

1
자동차 유추 : 나는 다른 사람의 탱크에 얼마나 많은 가스가 있는지 알 필요가 없으며 다른 사람의 와이퍼를 켜고 싶어합니다. (그러나 그것은 인터넷의 정의입니다) (Shh! 당신은 이야기를 망칠 것입니다)

1
@nocomprende- "다른 사람의 탱크에 얼마나 많은 가스가 있는지 알 필요가 없습니다."– 다음 여행을 위해 "차용"할 가족 용 차량을 결정하려는 십대가 아니라면 ...;)
alephzero

3

SRP는 제대로 이해하기 어렵습니다. 코드에 '작업'을 할당하고 각 부분에 명확한 책임이 있는지 확인해야합니다. 실제 생활에서와 같이 어떤 경우에는 사람들 사이에서 일을 나누는 것이 매우 자연 스러울 수 있지만, 다른 경우에는 특히 자신이 알지 못하는 경우 (또는 그 일) 정말 까다로울 수 있습니다.

항상 먼저 작동하는 간단한 코드를 작성한 다음 약간 리팩터링하는 것이 좋습니다 . 잠시 후 코드가 자연스럽게 클러스터링되는 방식을 보는 경향이 있습니다. 코드 (또는 사람)와 수행 할 작업을 알기 전에 책임을지는 것은 실수라고 생각합니다.

모듈이 너무 많은 작업을 시작하여 디버그 / 유지하기 어려운 경우가 있습니다. 이것이 리팩토링의 순간입니다. 핵심 작업은 무엇이며 다른 모듈에 어떤 작업을 제공 할 수 있습니까? 예를 들어 보안 검사 및 기타 작업을 처리해야합니까, 아니면 먼저 다른 곳에서 보안 검사를 수행해야합니까, 아니면 코드가 더 복잡해 집니까?

너무 많은 간접 지시를 사용하면 다시 엉망이됩니다 ... 다른 원칙과 마찬가지로이 원칙은 KISS, YAGNI 등과 같은 다른 원칙과 충돌 할 것입니다. 모든 것이 균형의 문제입니다.


SRP는 콘스탄틴의 응집력이 크지 않습니까?
Nick Keighley

충분히 긴 코드를 작성하면 자연스럽게 이러한 패턴을 찾을 수 있지만 이름을 지정하여 학습 속도를 높일 수 있으며 커뮤니케이션에 도움이됩니다.
Christophe Roussy

@ NickKeighley 나는 그것이 응집력이라고 생각합니다. 그렇게 큰 글씨는 아니지만 다른 관점에서 보았습니다.
sdenham

3

"단일 책임 원칙"은 혼란스러운 이름 일 것입니다. "변경해야하는 한 가지 이유"만이 원칙을 더 잘 설명하지만 여전히 이해하기 쉽습니다. 우리는 런타임에 객체가 상태를 변경시키는 원인에 대해 이야기하지 않습니다. 앞으로 개발자가 코드를 변경해야하는 원인에 대해 논의하고 있습니다.

버그를 수정하지 않는 한 변경 사항은 새로운 비즈니스 요구 사항 또는 변경된 비즈니스 요구 사항으로 인한 것입니다. 코드 외부에서 생각해야하고 외부 요인으로 인해 요구 사항이 독립적 으로 변경되는 원인을 상상해야 합니다. 말하다:

  • 정치적 결정으로 인해 세율이 변경됩니다.
  • 마케팅은 모든 제품의 이름을 변경하기로 결정
  • UI를 액세스 할 수 있도록 다시 디자인해야합니다
  • 데이터베이스가 혼잡하므로 최적화를 수행해야합니다.
  • 모바일 앱을 수용해야합니다
  • 등등...

이상적으로는 독립적 인 요소가 다른 클래스에 영향을 미치기를 원합니다. 예를 들어 세금은 제품 이름과 관계없이 변경되므로 동일한 클래스에 영향을 미치지 않아야합니다. 그렇지 않으면 세금 변경으로 인해 제품 이름 지정 오류가 발생할 수 있습니다. 이는 모듈 식 시스템으로 피하고 싶은 타이트한 커플 링입니다.

그러니 그냥 변경할 수 있는지의 초점하지 않습니다 - 아무것도 생각할 향후 변경 될 수 있습니다. 독립적으로 변할 수있는 것에 집중 하십시오. 변경 사항은 다른 행위자에 의해 발생하는 경우 일반적으로 독립적입니다.

직책을 가진 당신의 예는 올바른 길을 가고 있지만, 당신은 더 문자 그대로 받아 들여야합니다! 마케팅이 코드를 변경하고 재무가 다른 변경을 야기 할 수있는 경우, 이러한 변경은 문자 그대로 다른 직책이므로 변경이 독립적으로 발생하기 때문에 동일한 코드에 영향을 미치지 않아야합니다.

이 용어를 발명 한 Bob 아저씨를 인용 하면 :

소프트웨어 모듈을 작성할 때 변경이 요청 될 때 이러한 변경이 단일 개인 또는 좁은 정의 된 단일 비즈니스 기능을 나타내는 하나의 밀접하게 연결된 단일 사용자 그룹에서만 발생할 수 있는지 확인하려고합니다. 모듈을 조직 전체의 복잡성으로부터 분리하고 각 모듈이 하나의 비즈니스 기능의 요구에 책임을 지도록 시스템을 설계하려고합니다.

요약하자면 : "책임"은 단일 비즈니스 기능을 제공합니다. 두 명 이상의 배우가 수업을 변경해야 할 경우 수업에서이 원칙을 어기 게됩니다.


그의 저서 인 "Clean Architecture"에 따르면 이것은 정확히 맞습니다. 비즈니스 규칙은 하나의 소스에서, 한 번은 소스에서만 가져와야합니다. 이는 HR, 운영 및 IT 모두 "단일 책임"에서 공식화 요건을 협력해야한다는 것을 의미합니다. 이것이 원칙입니다. +1
베니 스코그 버그

2

SOLID 프로그래밍 원칙을 설명하고이 원칙을 따르거나 따르지 않는 코드 예제를 제공하는 좋은 기사는 https://scotch.io/bar-talk/solid-the-first-five-principles-of-object-oriented- 디자인 .

SRP와 관련된 예제에서 그는 몇 가지 모양 클래스 (원과 사각형)와 여러 모양의 총 면적을 계산하도록 설계된 클래스의 예를 제공합니다.

첫 번째 예에서 그는 면적 계산 클래스를 작성하고 출력을 HTML로 리턴합니다. 나중에 그는 대신 JSON으로 표시하고 영역 계산 클래스를 변경해야한다고 결정합니다.

이 예제의 문제점은 영역 계산 클래스가 모양 영역을 계산하고 해당 영역을 표시하는 것입니다. 그런 다음 영역을 표시하기 위해 특별히 설계된 다른 클래스를 사용하여이 작업을 수행하는 더 좋은 방법을 사용합니다.

이것은 간단한 예제이며 코드 스 니펫이있는 기사를보다 쉽게 ​​이해할 수 있지만 SRP의 핵심 아이디어를 보여줍니다.


0

우선, 당신이 가지고있는 것은 실제로 두 가지 별도의 문제입니다 : 클래스에 넣을 메소드의 문제와 인터페이스 팽창의 문제입니다.

인터페이스

이 인터페이스가 있습니다 :

public Interface CustomerCRUD
{
  public void Create(Customer customer);
  public Customer Read(int CustomerID);
  public void Update(Customer customer);
  public void Delete(int CustomerID);
}

아마도 CustomerCRUD인터페이스에 맞는 여러 클래스 (인터페이스가 필요하지 않음)와 do_crud(customer: CustomerCRUD)적합한 객체를 취하는 일부 함수가 있다고 가정합니다. 그러나 당신은 이미 SRP를 깨뜨 렸습니다. 당신은이 네 가지 별개의 작업들을 하나로 묶었습니다.

나중에 데이터베이스 뷰에서 작업한다고 가정 해 봅시다. 데이터베이스보기가 단지Read 에 대해 사용 가능한 방법을. 그러나 do_query_stuff(customer: ???)완전한 테이블이나 뷰에서 연산자를 투명하게 작성하는 함수를 작성하려고합니다 . 결국이 Read방법 만 사용합니다 .

인터페이스를 만드십시오

공용 인터페이스 CustomerReader {공용 고객 읽기 (customerID : int)}

CustomerCrud인터페이스를 다음 과 같이 고려하십시오 .

public interface CustomerCRUD extends CustomerReader
{
  public void Create(Customer customer);
  public void Update(Customer customer);
  public void Delete(int CustomerID);
}

그러나 끝이 없습니다. 만들 수는 있지만 업데이트 할 수없는 개체가있을 수 있습니다.이 토끼 구멍은 너무 깊습니다. 단일 책임 원칙을 준수하는 유일한 방법은 모든 인터페이스에 정확히 하나의 메소드를 포함시키는 것 입니다. Go는 실제로 내가 본 것에서이 방법론을 따릅니다. 대부분의 인터페이스에는 단일 함수가 포함되어 있습니다. 두 함수를 포함하는 인터페이스를 지정하려면 두 가지 기능을 결합한 새 인터페이스를 어색하게 만들어야합니다. 곧 인터페이스의 폭발적인 폭발이 일어납니다.

이 혼란을 피하는 방법은 인터페이스 (공칭 서브 타이핑의 형태) 대신 구조적 서브 타이핑 (예 : OCaml에서 구현)을 사용하는 것입니다. 우리는 인터페이스를 정의하지 않습니다. 대신 간단히 함수를 작성할 수 있습니다

let do_customer_stuff customer = customer.read ... customer.update ...

우리가 좋아하는 방법을 호출합니다. OCaml은 형식 유추를 사용하여 이러한 메서드를 구현하는 모든 개체를 전달할 수 있는지 확인합니다. 이 예에서는 customer유형 이 결정 <read: int -> unit, update: int -> unit, ...>됩니다.

클래스

인터페이스 혼란을 해결합니다 . 그러나 여전히 여러 메소드를 포함하는 클래스를 구현해야합니다. 예를 들어, 우리는 두 개의 서로 다른 클래스를 생성해야 CustomerReader하고 CustomerWriter? 테이블을 읽는 방법을 변경하려면 (예 : 데이터를 가져 오기 전에 응답을 redis로 캐시하지만) 이제는 어떻게 작성됩니까? 당신이 따르는 경우 논리적 결론을 추론의 사슬을, 당신은 함수형 프로그래밍에 불가분 리드입니다 :)


4
"무의미"는 약간 강하다. 나는 "신비한"또는 "젠"뒤에 숨을 수있었습니다. 그러나 무의미
svidgen

왜 구조적 서브 타이핑이 솔루션인지 조금 더 설명해 주시겠습니까?
Robert Harvey

@RobertHarvey 내 답변을 크게 재구성했습니다
gardenhead

4
단일 클래스 만 구현하는 경우에도 인터페이스를 사용합니다. 왜? 단위 테스트에서 조롱.
Eternal21

0

내 마음에 오는 SRP에 가장 가까운 것은 사용 흐름입니다. 특정 클래스에 대한 명확한 사용 흐름이 없으면 클래스에 디자인 냄새가있을 수 있습니다.

사용 흐름은 주어진 메소드 호출 승계로 예상되는 (따라서 테스트 할 수있는) 결과를 제공합니다. 기본적으로 IMHO를 사용하는 유스 케이스로 클래스를 정의하므로 모든 프로그램 방법론이 구현보다 인터페이스에 중점을 둡니다.


0

여러 요구 사항을 변경하고 구성 요소를 변경할 필요가 없습니다 .

그러나 SOLID에 대해 처음들을 때 언뜻 이해한다는 점을 잘 알고 있습니다.


SRPYAGNI 가 서로 모순 될 수 있다는 많은 의견이 있지만 TDD (GOOS, London School) 에서 시행하는 YAGN I 는 고객의 관점에서 내 구성 요소를 생각하고 디자인하도록 가르쳐주었습니다. 나는 클라이언트가 원하는 것을 최소한으로하는 것, 즉 얼마나 적은 것을해야하는지에 따라 인터페이스를 디자인하기 시작 했다 . 그리고 그 운동은 TDD에 대한 지식 없이도 수행 될 수 있습니다.

나는 밥 아저씨가 묘사 한 기술을 좋아합니다 (슬프게도 기억할 수는 없습니다).

이 수업은 무엇을합니까?

귀하의 답변에 And 또는 Or 중 하나가 포함되어 있습니까?

그렇다면 답변의 해당 부분을 추출하십시오.

이 기술은 절대적이며 @svidgen이 말했듯이 SRP 는 판단 요청이지만 새로운 것을 배우면 절대적인 것이 가장 좋으며 항상 무언가 를하는 것이 더 쉽습니다 . 분리하지 않는 이유를 확인하십시오. 교양 추정은하고 있지 어떻게가 모르기 때문에. 이것은 예술이며 경험이 필요합니다.


SRP 에 대해 이야기 할 때 많은 답변이 디커플링에 대한 논쟁을하는 것처럼 보입니다 .

SRP는 것입니다 하지 변화가 종속성 그래프를 전파하지 않도록 할 수 있습니다.

이론적으로 SRP 가 없으면 의존성이 없습니다 ...

한 번의 변경으로 인해 응용 프로그램에서 많은 부분이 변경되지 않아야하지만 그에 대한 다른 원칙이 있습니다. 그러나 SRP공개 폐쇄 원칙을 개선합니다 . 이 원리는 추상화에 관한 것이지만, 작은 추상화는 재 구현하기가 더 쉽다 .

따라서 SOLID 전체를 교육 할 때 요구 사항이 변경 될 때 SRP를 사용하면 코드를 적게 변경할 수 있으며 실제로는 코드를 적게 작성할 수 있습니다 .


3
When learning something new, absolutes are the best, it is easier to just always do something.-내 경험상, 새로운 프로그래머는 너무 독단적입니다. 절대주의는 생각하지 않는 개발자와화물 컬트 프로그래밍으로 이어집니다. "다만 이렇게"말하는 그래서 당신이 당신이 말하는 사람이 나중에해야 할 것 이해, 괜찮 잊다 당신이 그들을 가르친 것.
Robert Harvey

@RobertHarvey은 완전히 사실 그것은 독단적 인 행동을 만들고, 당신은해야 재 학습 / 잊다 당신이 경험을 얻을 수있다. 이것은 내 요점입니다. 새로운 프로그래머가 자신의 결정을 추론 할 방법없이 판단 요청을하려고 시도하면 그것이 왜 효과가 있었는지, 언제 일했는지 알지 못하기 때문에 경계선이 쓸모없는 것처럼 보입니다. 사람들이 그것을 과도 하게 함으로써 , 자격이없는 추측 대신 예외를 찾도록 가르칩니다. 당신이 말한 모든 것은 절대주의에 관한 것이기 때문에 그것이 시작점이되어야합니다.
Chris Wohlert 2016 년

@RobertHarvey, 빠른 실생활 사례 : 자녀에게 항상 정직 하도록 가르치는 경우가 많지만 나이가 들어감에 따라 사람들이 가장 정직한 생각을 듣고 싶지 않은 몇 가지 예외가있을 수 있습니다. 5 살짜리 아이가 정직하다는 것에 대한 올바른 판단을 요구하는 것은 기껏해야 낙관적입니다. :)
Chris Wohlert 2016 년

0

그것에 대한 명확한 대답은 없습니다. 질문은 좁지 만 설명은 아닙니다.

제게는 원한다면 Occam 's Razor와 같은 것입니다. 현재 코드를 측정하려고 할 때 이상적입니다. 단순하고 간단한 단어로 정리하기는 어렵습니다. 또 다른 은유는»하나의 주제«는 추상적이며, 즉 이해하기 어려운»단일 책임«입니다. 세 번째 설명은 한 단계의 추상화를 다루는 것이다.

그것은 실제로 무엇을 의미합니까?

최근에는 주로 두 단계로 구성된 코딩 스타일을 사용합니다.

1 단계는 창조적 혼돈으로 가장 잘 묘사됩니다. 이 단계에서는 생각이 흐를 때 코드를 작성합니다.

2 단계는 완전히 반대입니다. 허리케인 후 청소하는 것과 같습니다. 가장 많은 노력과 훈련이 필요합니다. 그런 다음 디자이너의 관점에서 코드를 봅니다.

나는 주로 파이썬에서 일하고 있는데 나중에 객체와 클래스를 생각할 수 있습니다. 첫 번째 단계 I- 함수 만 작성하고 다른 모듈에서 거의 무작위로 전파합니다. 에서 단계 II 내가가는 일이있어 후에, 나는 어떤 모듈을 거래하는 솔루션의 부분에 대해 자세히 살펴 있습니다. 그리고 모듈을 살펴보면서 주제가 나에게 등장합니다. 일부 기능은 주제별로 관련되어 있습니다. 이것은 수업에 좋은 후보입니다 . 그리고 함수를 클래스로 바꾼 후-거의 들여 쓰기 self로 파이썬에서 매개 변수 목록에 추가 합니다.)-나는 SRPOccam의 면도기와 같은 기능을 사용하여 다른 모듈과 클래스에 기능을 제거합니다.

현재 예는 다른 날에 작은 내보내기 기능을 작성하는 것일 수 있습니다 .

지퍼 에 csv , excel 및 결합 된 excel 시트 가 필요했습니다.

일반 기능은 각각 세 가지 보기 (= 기능)로 수행되었습니다 . 각 함수는 필터를 결정하는 일반적인 방법과 데이터를 검색하는 두 번째 방법을 사용했습니다. 그런 다음 각 기능에서 내보내기 준비가 수행되어 서버에서 응답으로 전달되었습니다.

너무 많은 추상화 레벨이 혼합되었습니다.

I) 수신 / 발신 요청 / 응답 처리

II) 필터 결정

III) 데이터 검색

IV) 데이터 변환

쉬운 단계는 exporter첫 번째 단계에서 레이어 II-IV를 처리 하기 위해 하나의 추상화 ( ) 를 사용하는 것 입니다.

요청 / 응답을 다루는 주제 만 남았습니다 . 동일한 추상화 수준에서 요청 매개 변수추출 하는 것이 좋습니다. 그래서 저는이 관점에서 "책임"을 가지고있었습니다 .

둘째, 수출 업체를 분리해야하는데, 우리가 보았 듯이 적어도 3 개의 다른 추상화 계층으로 구성되었습니다.

결정 필터 기준 및 실제 retrival는 거의 동일한 추상화 레벨 (필터는 데이터의 적절한 서브 세트를 얻기 위하여 필요하다)에있다. 이러한 수준은 데이터 액세스 계층 과 같은 것으로 설정되었습니다 .

다음 단계에서는 실제 내보내기 메커니즘을 따로 분리했습니다. 임시 파일에 쓰기가 필요한 경우 디스크에 데이터를 실제로 쓰기위한 것과 실제 형식을 처리하는 다른 두 가지 "책임"으로 나누었습니다.

클래스와 모듈의 형성과 함께, 상황이 더 명확 해졌고, 무엇이 어디에 속해 있는지가 명확 해졌습니다. 그리고 수업 이 너무 많은지 여부는 항상 잠재 질문 입니다.

각 학급의 책임을 어떻게 결정하고 SRP와 관련하여 책임을 어떻게 정의합니까?

따라야 할 레시피를 제공하기는 어렵습니다. 물론, 나는 한 단계의 추상화 추상화를 반복 할 수있다.

대부분 나를 위해 그것은 현재 디자인으로 이어지는 일종의 "예술적 직관"입니다. 아티스트가 점토를 조각하거나 그림을 그리는 것처럼 코드를 모델링합니다.

내가 코딩 밥 로스 라고 상상해보십시오 .)


0

SRP를 따르는 코드를 작성하려고 시도하는 것 :

  • 해결해야 할 특정 문제를 선택하십시오.
  • 이를 해결하는 코드를 작성하고 한 가지 방법으로 모든 것을 작성하십시오 (예 : main);
  • 코드를 신중하게 분석하고 비즈니스를 기반으로 수행중인 모든 작업에서 볼 수있는 책임을 정의하십시오 (이는 비즈니스 / 프로젝트 / 고객에 따라 결정되는 주관적인 부분입니다).
  • 모든 기능은 이미 구현되어 있습니다. 다음은 코드 구성 일뿐입니다 (이 방법에서는 추가 기능이나 메커니즘이 구현되지 않습니다).
  • 이전 단계에서 정의한 책임 (비즈니스 및 "변경해야하는 한 가지 이유"아이디어를 기반으로 정의 된 책임)에 따라 각각에 대해 별도의 클래스 또는 메소드를 추출하십시오.
  • 이 방법은 SPR에만 관심이 있습니다. 이상적으로는 다른 원칙도 준수하기위한 추가 단계가 있어야합니다.

예:

문제 : 사용자로부터 두 개의 숫자를 가져 와서 합계를 계산하고 결과를 사용자에게 출력하십시오.

//first step: solve the problem right away
static void Main(string[] args)
{
    Console.WriteLine("Number 1: ");
    int firstNumber = Convert.ToInt32(Console.ReadLine());

    Console.WriteLine("Number 2: ");
    int secondNumber = Convert.ToInt32(Console.ReadLine());

    int result = firstNumber + secondNumber;

    Console.WriteLine("Hi there! The result is: {0}", result);

    Console.ReadLine();
}

다음으로 수행해야 할 작업을 기반으로 책임을 정의하십시오. 이것에서 적절한 클래스를 추출하십시오.

//Responsible for getting two integers from the user
class Input {
    public int FirstNumber { get; set; }
    public int SecondNumber { get; set; }
    public void Read() {
        Console.WriteLine("Number 1: ");
        FirstNumber = Convert.ToInt32(Console.ReadLine());

        Console.WriteLine("Number 2: ");
        SecondNumber = Convert.ToInt32(Console.ReadLine());
    }
}

//Responsible for calculating the sum of two integers
class SumOperation {
    public int Result { get; set; }
    public void Calculate(int a, int b) {
        Result = a + b;
    }
}

//Responsible for the output of some value to the user
class Output {
    public void Write(int result) {
        Console.WriteLine("Hello! The result is: {0}", result);
    }
}

리팩토링 된 프로그램은 다음과 같습니다.

//Program: responsible for main execution.
//Gets two numbers from user and output their sum.
static void Main(string[] args)
{
    var input = new Input();
    input.Read();

    var operation = new SumOperation();
    operation.Calculate(input.FirstNumber, input.SecondNumber);

    var output = new Output();
    output.Write(operation.Result);

    Console.ReadLine();
}

참고 : 이 매우 간단한 예는 SRP 원칙 만 고려합니다. 다른 원칙 (예 : "L"-코드는 생성이 아닌 추상화에 의존해야 함)을 사용하면 코드에 더 많은 이점을 제공하고 비즈니스 변경에 대한 유지 관리가 더 쉬워집니다.


1
귀하의 예는 SRP를 적절히 설명하기에는 너무 단순합니다. 아무도 실제 생활에서 이것을하지 않을 것입니다.
Robert Harvey

예, 실제 프로젝트에서는 예제와 같이 정확한 코드를 작성하는 대신 의사 코드를 작성합니다. 의사 코드 후에 예제에서와 마찬가지로 책임을 분할하려고합니다. 어쨌든, 그것은 내가하는 방법입니다.
Emerson Cardoso

0

Robert C. Martins 는 2017 년 9 월 10 일에 출판 된 Clean Architecture : A Craftsman 's Guide to Software Structure and Design ( 2017 년 9 월 10 일 발행)에서 62 페이지에 다음과 같이 썼습니다.

역사적으로 SRP는 다음과 같이 설명되었습니다.

모듈에는 변경해야 할 단 하나의 이유가 있어야합니다

사용자와 이해 관계자를 만족시키기 위해 소프트웨어 시스템이 변경되었습니다. 이러한 사용자와 이해 관계자 "변경 이유"입니다. 그 원칙이 말하는 것입니다. 실제로, 우리는 다음과 같이 원칙을 바꾸어 쓸 수 있습니다 :

모듈은 한 명의 사용자 또는 이해 관계자에게만 책임을 져야합니다

불행히도, "사용자"와 "이해 관계자"라는 단어는 실제로 여기서 사용하기에 올바른 단어가 아닙니다. 제정신 방식으로 시스템을 변경하기를 원하는 둘 이상의 사용자 또는 이해 관계자가있을 수 있습니다. 대신 우리는 그룹을 언급하고 있습니다. 한 명 이상의 사람들이 그러한 변화를 필요로합니다. 우리는 그 그룹을 배우 로 지칭 할 것입니다 .

따라서 SRP의 최종 버전은 다음과 같습니다.

모듈은 오직 한 명의 액터 만 담당합니다.

따라서 이것은 코드에 관한 것이 아닙니다. SRP는 요구 사항 및 비즈니스 요구의 흐름을 제어하는 ​​것입니다.


왜 "코드에 관한 것이 아닙니다"라는 구별을하고 있는지 잘 모르겠습니다. 물론 코드에 관한 것입니다. 이것은 소프트웨어 개발입니다.
Robert Harvey

@RobertHarvey 내 요점은 요구 사항의 흐름이 하나의 소스 인 행위자로부터 온다는 것이다. 사용자와 이해 관계자는 코드가 아니며 비즈니스 규칙에 따라 요구 사항으로 제공됩니다. 따라서 SRP는 이러한 요구 사항을 제어하는 ​​프로세스이며 코드는 아닙니다. 소프트웨어 개발 (!)이지만 코드는 아닙니다.
베니 스코그 버그
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.